private void LoadOrCreatePixelData(int cols, int rows, TextRenderingHint textRenderingHint)
{
Pixmap.Layer pixelLayer = new Pixmap.Layer(MathF.RoundToInt(cols*this.internalFont.Size*1.2f), MathF.RoundToInt(rows*this.internalFont.Height*1.2f));
Pixmap.Layer glyphTemp;
Pixmap.Layer glyphTempTypo;
Bitmap bm;
Bitmap measureBm = new Bitmap(1, 1);
Rect[] atlas = new Rect[SupportedChars.Length];
using (Graphics measureGraphics = Graphics.FromImage(measureBm))
{
Brush fntBrush = new SolidBrush(Color.Black);
StringFormat formatDef = StringFormat.GenericDefault;
formatDef.LineAlignment = StringAlignment.Near;
formatDef.FormatFlags = 0;
StringFormat formatTypo = StringFormat.GenericTypographic;
formatTypo.LineAlignment = StringAlignment.Near;
int x = 1;
int y = 1;
for (int i = 0; i < SupportedChars.Length; ++i)
{
string str = SupportedChars[i].ToString(CultureInfo.InvariantCulture);
bool isSpace = str == " ";
SizeF charSize = measureGraphics.MeasureString(str, this.internalFont, pixelLayer.Width, formatDef);
// Rasterize a single glyph for rendering
bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
using (Graphics glyphGraphics = Graphics.FromImage(bm))
{
glyphGraphics.Clear(Color.Transparent);
glyphGraphics.TextRenderingHint = textRenderingHint;
glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef);
}
glyphTemp = new Pixmap.Layer(bm);
// Rasterize a single glyph in typographic mode for metric analysis
if (!isSpace)
{
Rectangle glyphTempBounds = glyphTemp.OpaqueBounds();
glyphTemp.SubImage(glyphTempBounds.X, 0, glyphTempBounds.Width, glyphTemp.Height);
if (BodyAscentRef.Contains(SupportedChars[i]))
this.bodyAscent += glyphTempBounds.Height;
bm = new Bitmap((int) Math.Ceiling(Math.Max(1, charSize.Width)), this.internalFont.Height + 1);
using (Graphics glyphGraphics = Graphics.FromImage(bm))
{
glyphGraphics.Clear(Color.Transparent);
glyphGraphics.TextRenderingHint = textRenderingHint;
glyphGraphics.DrawString(str, this.internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo);
}
glyphTempTypo = new Pixmap.Layer(bm);
glyphTempTypo.Crop(true, false);
}
else
{
glyphTempTypo = glyphTemp;
}
// Update xy values if it doesn't fit anymore
if (x + glyphTemp.Width + 2 > pixelLayer.Width)
{
x = 1;
y += this.internalFont.Height + MathF.Clamp((int) MathF.Ceiling(this.internalFont.Height*0.1875f), 3, 10);
}
// Memorize atlas coordinates & glyph data
this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, glyphTemp.Width);
this.glyphs[i].width = glyphTemp.Width;
this.glyphs[i].height = glyphTemp.Height;
this.glyphs[i].offsetX = glyphTemp.Width - glyphTempTypo.Width;
if (isSpace)
{
this.glyphs[i].width /= 2;
this.glyphs[i].offsetX /= 2;
}
atlas[i].X = x;
atlas[i].Y = y;
atlas[i].W = glyphTemp.Width;
atlas[i].H = (this.internalFont.Height + 1);
// Draw it onto the font surface
glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y);
x += glyphTemp.Width + MathF.Clamp((int) MathF.Ceiling(this.internalFont.Height*0.125f), 2, 10);
if(glyphTempTypo != glyphTemp)
glyphTempTypo.Dispose();
glyphTemp.Dispose();
}
}
// White out texture except alpha channel.
for (int i = 0; i < pixelLayer.Data.Length; i++)
{
pixelLayer.Data[i].R = 255;
pixelLayer.Data[i].G = 255;
pixelLayer.Data[i].B = 255;
}
this.pixelData = new Pixmap(pixelLayer) {Atlas = new List<Rect>(atlas)};
}