79 using System.Collections.Generic;
81 using System.Drawing.Imaging;
83 namespace SiliconStudio.
Paradox.Assets.SpriteFont.Compiler
86 internal static class GlyphPacker
88 public static Bitmap ArrangeGlyphs(Glyph[] sourceGlyphs)
91 List<ArrangedGlyph> glyphs =
new List<ArrangedGlyph>();
93 for (
int i = 0; i < sourceGlyphs.Length; i++)
95 ArrangedGlyph glyph =
new ArrangedGlyph();
97 glyph.Source = sourceGlyphs[i];
100 glyph.Width = sourceGlyphs[i].Subrect.Width + 2;
101 glyph.Height = sourceGlyphs[i].Subrect.Height + 2;
107 glyphs.Sort(CompareGlyphSizes);
110 int outputWidth = GuessOutputWidth(sourceGlyphs);
111 int outputHeight = 0;
114 for (
int i = 0; i < glyphs.Count; i++)
116 PositionGlyph(glyphs, i, outputWidth);
118 outputHeight = Math.Max(outputHeight, glyphs[i].Y + glyphs[i].Height);
122 outputHeight = MakeValidTextureSize(outputHeight,
false);
124 return CopyGlyphsToOutput(glyphs, outputWidth, outputHeight);
129 static Bitmap CopyGlyphsToOutput(List<ArrangedGlyph> glyphs,
int width,
int height)
131 Bitmap output =
new Bitmap(width, height,
PixelFormat.Format32bppArgb);
133 foreach (ArrangedGlyph glyph
in glyphs)
135 Glyph sourceGlyph = glyph.Source;
136 Rectangle sourceRegion = sourceGlyph.Subrect;
137 Rectangle destinationRegion =
new Rectangle(glyph.X + 1, glyph.Y + 1, sourceRegion.Width, sourceRegion.Height);
139 BitmapUtils.CopyRect(sourceGlyph.Bitmap, sourceRegion, output, destinationRegion);
141 BitmapUtils.PadBorderPixels(output, destinationRegion);
143 sourceGlyph.Bitmap = output;
144 sourceGlyph.Subrect = destinationRegion;
165 static void PositionGlyph(List<ArrangedGlyph> glyphs,
int index,
int outputWidth)
173 int intersects = FindIntersectingGlyph(glyphs, index, x, y);
184 x = glyphs[intersects].X + glyphs[intersects].Width;
187 if (x + glyphs[index].Width > outputWidth)
197 static int FindIntersectingGlyph(List<ArrangedGlyph> glyphs,
int index,
int x,
int y)
199 int w = glyphs[index].Width;
200 int h = glyphs[index].Height;
202 for (
int i = 0; i < index; i++)
204 if (glyphs[i].X >= x + w)
207 if (glyphs[i].X + glyphs[i].Width <= x)
210 if (glyphs[i].Y >= y + h)
213 if (glyphs[i].Y + glyphs[i].Height <= y)
224 static int CompareGlyphSizes(ArrangedGlyph
a, ArrangedGlyph
b)
226 const int heightWeight = 1024;
228 int aSize = a.Height * heightWeight + a.Width;
229 int bSize = b.Height * heightWeight + b.Width;
232 return bSize.CompareTo(aSize);
234 return a.Source.Character.CompareTo(b.Source.Character);
239 static int GuessOutputWidth(Glyph[] sourceGlyphs)
244 foreach (Glyph glyph
in sourceGlyphs)
246 maxWidth = Math.Max(maxWidth, glyph.Subrect.Width);
247 totalSize += glyph.Subrect.Width * glyph.Subrect.Height;
250 int width = Math.Max((int)Math.Sqrt(totalSize), maxWidth);
252 return MakeValidTextureSize(width,
true);
257 static int MakeValidTextureSize(
int value,
bool requirePowerOfTwo)
260 const int blockSize = 4;
262 if (requirePowerOfTwo)
265 int powerOfTwo = blockSize;
267 while (powerOfTwo < value)
275 return (value + blockSize - 1) & ~(blockSize - 1);
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ float size_t y
System.Windows.Shapes.Rectangle Rectangle
PixelFormat
Defines various types of pixel formats.