// Crops unused space from around the edge of a glyph bitmap. public static void Crop(Glyph glyph) { if (glyph == null) { throw new NullReferenceException("The given glyph may not be equal to null."); } // Crop the top. while ((glyph.Region.Height > 1) && BitmapUtils.MatchesAlpha(0, glyph.Bitmap, new Rectangle(glyph.Region.X, glyph.Region.Y, glyph.Region.Width, 1))) { ++glyph.Region.Y; --glyph.Region.Height; ++glyph.OffsetY; } // Crop the bottom. while ((glyph.Region.Height > 1) && BitmapUtils.MatchesAlpha(0, glyph.Bitmap, new Rectangle(glyph.Region.X, glyph.Region.Bottom - 1, glyph.Region.Width, 1))) { --glyph.Region.Height; } // Crop the left. while ((glyph.Region.Width > 1) && BitmapUtils.MatchesAlpha(0, glyph.Bitmap, new Rectangle(glyph.Region.X, glyph.Region.Y, 1, glyph.Region.Height))) { ++glyph.Region.X; --glyph.Region.Width; ++glyph.OffsetX; } // Crop the right. while ((glyph.Region.Width > 1) && BitmapUtils.MatchesAlpha(0, glyph.Bitmap, new Rectangle(glyph.Region.Right - 1, glyph.Region.Y, 1, glyph.Region.Height))) { --glyph.Region.Width; ++glyph.AdvanceX; } }
static void MakeSpriteFont(CommandLineOptions options) { // Import. Console.WriteLine("Importing {0}", options.SourceFont); float lineSpacing; Glyph[] glyphs = ImportFont(options, out lineSpacing); Console.WriteLine("Captured {0} glyphs", glyphs.Length); // Optimize. Console.WriteLine("Cropping glyph borders"); foreach (Glyph glyph in glyphs) { GlyphCropper.Crop(glyph); } Console.WriteLine("Packing glyphs into sprite sheet"); Bitmap bitmap; if (options.FastPack) { bitmap = GlyphPacker.ArrangeGlyphsFast(glyphs); } else { bitmap = GlyphPacker.ArrangeGlyphs(glyphs); } // Emit texture size warning based on known Feature Level limits. if (bitmap.Width > 16384 || bitmap.Height > 16384) { Console.WriteLine("WARNING: Resulting texture is too large for all known Feature Levels (9.1 - 12.1)"); } else if (bitmap.Width > 8192 || bitmap.Height > 8192) { if (options.FeatureLevel < FeatureLevel.FL11_0) { Console.WriteLine("WARNING: Resulting texture requires a Feature Level 11.0 or later device."); } } else if (bitmap.Width > 4096 || bitmap.Height > 4096) { if (options.FeatureLevel < FeatureLevel.FL10_0) { Console.WriteLine("WARNING: Resulting texture requires a Feature Level 10.0 or later device."); } } else if (bitmap.Width > 2048 || bitmap.Height > 2048) { if (options.FeatureLevel < FeatureLevel.FL9_3) { Console.WriteLine("WARNING: Resulting texture requires a Feature Level 9.3 or later device."); } } // Adjust line and character spacing. lineSpacing += options.LineSpacing; foreach (Glyph glyph in glyphs) { glyph.AdvanceX += options.CharacterSpacing; } // Automatically detect whether this is a monochromatic or color font? if (options.TextureFormat == TextureFormat.Auto) { bool isMono = BitmapUtils.MatchesRGB(Color.White, bitmap); options.TextureFormat = isMono ? TextureFormat.CompressedMono : TextureFormat.Rgba32; } // Convert to premultiplied alpha format. if (!options.NoPremultiply) { Console.WriteLine("Premultiplying alpha"); BitmapUtils.ConvertToPremultipliedAlpha(bitmap); } // Save output files. if (!string.IsNullOrEmpty(options.DebugOutputSpriteSheet)) { Console.WriteLine("Saving debug output spritesheet {0}", options.DebugOutputSpriteSheet); bitmap.Save(options.DebugOutputSpriteSheet); } Console.WriteLine("Writing {0} ({1} format)", options.OutputFile, options.TextureFormat); SpriteFontWriter.WriteSpriteFont(options, glyphs, lineSpacing, bitmap); }