static void MakeSpriteFont(FontDescription options, Stream stream) { float lineSpacing; Glyph[] glyphs = ImportFont(options, out lineSpacing); // Optimize. foreach (Glyph glyph in glyphs) { // Output cleartype texture if (options.AntiAlias != FontAntiAliasMode.ClearType) { BitmapUtils.ConvertGreyToAlpha(glyph.Bitmap); } GlyphCropper.Crop(glyph); } Bitmap bitmap = GlyphPacker.ArrangeGlyphs(glyphs); // Adjust line and character spacing. lineSpacing += options.LineSpacing; foreach (Glyph glyph in glyphs) { glyph.XAdvance += options.Spacing; } // Automatically detect whether this is a monochromatic or color font? if (options.Format == FontTextureFormat.Auto) { bool isMono = BitmapUtils.IsRgbEntirely(Color.White, bitmap); options.Format = isMono ? FontTextureFormat.CompressedMono : FontTextureFormat.Rgba32; } // Convert to premultiplied alpha format. if (!options.NoPremultiply) { if (options.AntiAlias == FontAntiAliasMode.ClearType) { BitmapUtils.PremultiplyAlphaClearType(bitmap); } else { BitmapUtils.PremultiplyAlpha(bitmap); } } SpriteFontWriter.WriteSpriteFont(options, stream, glyphs, lineSpacing, bitmap); }
public void Import(FontDescription options) { // Load the source bitmap. Bitmap bitmap; try { bitmap = new Bitmap(options.FontName); } catch { throw new FontException(string.Format("Unable to load '{0}'.", options.FontName)); } // Convert to our desired pixel format. bitmap = BitmapUtils.ChangePixelFormat(bitmap, PixelFormat.Format32bppArgb); // What characters are included in this font? var characters = Utilities.ToArray(CharacterRegion.Flatten(options.CharacterRegions)); int characterIndex = 0; char currentCharacter = '\0'; // Split the source image into a list of individual glyphs. var glyphList = new List <Glyph>(); Glyphs = glyphList; LineSpacing = 0; foreach (Rectangle rectangle in FindGlyphs(bitmap)) { if (characterIndex < characters.Length) { currentCharacter = characters[characterIndex++]; } else { currentCharacter++; } glyphList.Add(new Glyph(currentCharacter, bitmap, rectangle)); LineSpacing = Math.Max(LineSpacing, rectangle.Height); } // If the bitmap doesn't already have an alpha channel, create one now. if (BitmapUtils.IsAlphaEntirely(255, bitmap)) { BitmapUtils.ConvertGreyToAlpha(bitmap); } }
// Rasterizes a single character glyph. static Glyph ImportGlyph(char character, Font font, Brush brush, StringFormat stringFormat, Bitmap bitmap, System.Drawing.Graphics graphics) { string characterString = character.ToString(); // Measure the size of this character. SizeF size = graphics.MeasureString(characterString, font, Point.Empty, stringFormat); int characterWidth = (int)Math.Ceiling(size.Width); int characterHeight = (int)Math.Ceiling(size.Height); // Pad to make sure we capture any overhangs (negative ABC spacing, etc.) int padWidth = characterWidth; int padHeight = characterHeight / 2; int bitmapWidth = characterWidth + padWidth * 2; int bitmapHeight = characterHeight + padHeight * 2; if (bitmapWidth > MaxGlyphSize || bitmapHeight > MaxGlyphSize) { throw new Exception("Excessively large glyph won't fit in my lazily implemented fixed size temp surface."); } // Render the character. graphics.Clear(Color.Black); graphics.DrawString(characterString, font, brush, padWidth, padHeight, stringFormat); graphics.Flush(); // Clone the newly rendered image. Bitmap glyphBitmap = bitmap.Clone(new Rectangle(0, 0, bitmapWidth, bitmapHeight), PixelFormat.Format32bppArgb); BitmapUtils.ConvertGreyToAlpha(glyphBitmap); // Query its ABC spacing. float?abc = GetCharacterWidth(character, font, graphics); // Construct the output Glyph object. return(new Glyph(character, glyphBitmap) { XOffset = -padWidth, XAdvance = abc.HasValue ? padWidth - bitmapWidth + abc.Value : -padWidth, YOffset = -padHeight, }); }