/// <summary> /// Function to read the chunk containing the font information. /// </summary> /// <param name="fontFile">The chunk file reader containing the font data.</param> /// <param name="name">Used defined name for the font.</param> /// <returns>A new <seealso cref="IGorgonFontInfo"/> containing information about the font.</returns> private static GorgonFontInfo GetFontInfo(GorgonChunkFileReader fontFile, string name) { GorgonBinaryReader reader = fontFile.OpenChunk(FontInfoChunk); var info = new GorgonFontInfo(reader.ReadString(), reader.ReadSingle(), reader.ReadValue <FontHeightMode>(), name) { FontStyle = reader.ReadValue <FontStyle>(), DefaultCharacter = reader.ReadChar(), Characters = reader.ReadString(), AntiAliasingMode = reader.ReadValue <FontAntiAliasMode>(), OutlineColor1 = new GorgonColor(reader.ReadInt32()), OutlineColor2 = new GorgonColor(reader.ReadInt32()), OutlineSize = reader.ReadInt32(), PackingSpacing = reader.ReadInt32(), TextureWidth = reader.ReadInt32(), TextureHeight = reader.ReadInt32(), UsePremultipliedTextures = reader.ReadValue <bool>(), UseKerningPairs = reader.ReadBoolean() }; fontFile.CloseChunk(); return(info); }
/// <summary> /// Function to generate the Gorgon bitmap fonts. /// </summary> /// <param name="fontFamilies">The list of TrueType font families to use.</param> /// <param name="window">The window that contains the loading message.</param> private static void GenerateGorgonFonts(IReadOnlyList <Drawing.FontFamily> fontFamilies, FormMain window) { // Pick a font to use with outlines. int fontWithOutlineIndex = GorgonRandom.RandomInt32(1, 5); _glowIndex = GorgonRandom.RandomInt32(fontWithOutlineIndex + 1, fontWithOutlineIndex + 5); int fontWithGradient = GorgonRandom.RandomInt32(_glowIndex + 1, _glowIndex + 5); int fontWithTexture = GorgonRandom.RandomInt32(fontWithGradient + 1, fontWithGradient + 5).Min(_fontFamilies.Count - 1); var pngCodec = new GorgonCodecPng(); using (IGorgonImage texture = pngCodec.LoadFromFile(Path.Combine(GorgonExample.GetResourcePath(@"Textures\Fonts\").FullName, "Gradient.png"))) { for (int i = 0; i < _fontFamilies.Count; ++i) { string fontFamily = _fontFamilies[i]; // Use this to determine if the font is avaiable. if (fontFamilies.All(item => !string.Equals(item.Name, fontFamily, StringComparison.InvariantCultureIgnoreCase))) { // Can't locate this one, move on... continue; } bool isExternal = Drawing.FontFamily.Families.All(item => !string.Equals(item.Name, fontFamily, StringComparison.InvariantCultureIgnoreCase)); string fontName; int outlineSize = 0; GorgonColor outlineColor1 = GorgonColor.BlackTransparent; GorgonColor outlineColor2 = GorgonColor.BlackTransparent; GorgonGlyphBrush brush = null; if (i == fontWithOutlineIndex) { fontName = $"{fontFamily} 32px Outlined{(isExternal ? " External TTF" : string.Empty)}"; outlineColor1 = GorgonColor.Black; outlineColor2 = GorgonColor.Black; outlineSize = 3; } else if (i == _glowIndex) { fontName = $"{fontFamily} 32px Outline as Glow{(isExternal ? " External TTF" : string.Empty)}"; outlineColor1 = new GorgonColor(GorgonColor.YellowPure, 1.0f); outlineColor2 = new GorgonColor(GorgonColor.DarkRed, 0.0f); outlineSize = 16; } else if (i == fontWithGradient) { fontName = $"{fontFamily} 32px Gradient{(isExternal ? " External TTF" : string.Empty)}"; brush = new GorgonGlyphLinearGradientBrush { StartColor = GorgonColor.White, EndColor = GorgonColor.Black, Angle = 45.0f }; } else if (i == fontWithTexture) { fontName = $"{fontFamily} 32px Textured{(isExternal ? " External TTF" : string.Empty)}"; brush = new GorgonGlyphTextureBrush(texture); } else { fontName = $"{fontFamily} 32px{(isExternal ? " External TTF" : string.Empty)}"; } window.UpdateStatus($"Generating Font: {fontFamily}".Ellipses(50)); var fontInfo = new GorgonFontInfo(fontFamily, 30.25f, name: fontName) { AntiAliasingMode = FontAntiAliasMode.AntiAlias, OutlineSize = outlineSize, OutlineColor1 = outlineColor1, OutlineColor2 = outlineColor2, UsePremultipliedTextures = false, Brush = brush }; _font.Add(_fontFactory.GetFont(fontInfo)); // Texture brushes have to be disposed when we're done with them. var disposableBrush = brush as IDisposable; disposableBrush?.Dispose(); } } }
/// <summary> /// Function to load the font data, with the specified size, from a stream. /// </summary> /// <param name="name">The name to assign to the font.</param> /// <param name="stream">The stream containing the font data.</param> /// <returns>A new <seealso cref="GorgonFont"/>, or, an existing font from the <seealso cref="GorgonFontFactory"/> cache.</returns> protected override GorgonFont OnLoadFromStream(string name, Stream stream) { var fontFile = new GorgonChunkFileReader(stream, new[] { FileHeader.ChunkID() }); GorgonFontInfo fontInfo = null; try { fontFile.Open(); fontInfo = GetFontInfo(fontFile, name); // If the font is already loaded, then just reuse it. if (Factory.HasFont(fontInfo)) { return(Factory.GetFont(fontInfo)); } GorgonBinaryReader reader = fontFile.OpenChunk(FontHeightChunk); // Read in information about the font height. float fontHeight = reader.ReadSingle(); float lineHeight = reader.ReadSingle(); float ascent = reader.ReadSingle(); float descent = reader.ReadSingle(); fontFile.CloseChunk(); if (fontFile.Chunks.Contains(BrushChunk)) { reader = fontFile.OpenChunk(BrushChunk); var brushType = (GlyphBrushType)reader.ReadInt32(); switch (brushType) { case GlyphBrushType.Hatched: fontInfo.Brush = new GorgonGlyphHatchBrush(); break; case GlyphBrushType.LinearGradient: fontInfo.Brush = new GorgonGlyphLinearGradientBrush(); break; case GlyphBrushType.PathGradient: fontInfo.Brush = new GorgonGlyphPathGradientBrush(); break; case GlyphBrushType.Texture: fontInfo.Brush = new GorgonGlyphTextureBrush(); break; default: fontInfo.Brush = new GorgonGlyphSolidBrush(); break; } fontInfo.Brush.ReadBrushData(reader); fontFile.CloseChunk(); } else { fontInfo.Brush = new GorgonGlyphSolidBrush(); } // If this font has kerning data, then load that in. IReadOnlyDictionary <GorgonKerningPair, int> kerningPairs = null; if (fontFile.Chunks.Contains(KernDataChunk)) { kerningPairs = ReadKernPairs(fontFile); } return(Factory.GetFont(fontInfo)); } finally { var brush = fontInfo?.Brush as IDisposable; brush?.Dispose(); fontFile.Close(); } }