Show More
Commit Description:
Update dialog.json
Commit Description:
Update dialog.json
File last commit:
Show/Diff file:
Action:
SpriteFontPlus/src/TtfFontBaker.cs
123 lines | 3.1 KiB | text/x-csharp | CSharpLexer
using SpriteFontPlus.Utility;
using StbTrueTypeSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace SpriteFontPlus
{
public static class TtfFontBaker
{
public static TtfFontBakerResult Bake(Stream ttfStream, float fontPixelHeight,
int bitmapWidth, int bitmapHeight,
IEnumerable<CharacterRange> characterRanges)
{
return Bake(ttfStream.ToByteArray(), fontPixelHeight, bitmapWidth, bitmapHeight, characterRanges);
}
public unsafe static TtfFontBakerResult Bake(byte[] ttf, float fontPixelHeight,
int bitmapWidth, int bitmapHeight,
IEnumerable<CharacterRange> characterRanges)
{
if (ttf == null || ttf.Length == 0)
{
throw new ArgumentNullException(nameof(ttf));
}
if (fontPixelHeight <= 0)
{
throw new ArgumentOutOfRangeException(nameof(fontPixelHeight));
}
if (bitmapWidth <= 0)
{
throw new ArgumentOutOfRangeException(nameof(bitmapWidth));
}
if (bitmapHeight <= 0)
{
throw new ArgumentOutOfRangeException(nameof(bitmapHeight));
}
if (characterRanges == null)
{
throw new ArgumentNullException(nameof(characterRanges));
}
if (!characterRanges.Any())
{
throw new ArgumentException("characterRanges must have a least one value.");
}
byte[] pixels;
var glyphs = new Dictionary<int, GlyphInfo>();
StbTrueType.stbtt_fontinfo fontInfo = new StbTrueType.stbtt_fontinfo();
fixed (byte* ttfPtr = ttf)
{
if (StbTrueType.stbtt_InitFont(fontInfo, ttfPtr, 0) == 0)
{
throw new Exception("Failed to init font.");
}
}
float scaleFactor = StbTrueType.stbtt_ScaleForPixelHeight(fontInfo, fontPixelHeight);
int ascent, descent, lineGap;
StbTrueType.stbtt_GetFontVMetrics(fontInfo, &ascent, &descent, &lineGap);
pixels = new byte[bitmapWidth * bitmapHeight];
StbTrueType.stbtt_pack_context pc = new StbTrueType.stbtt_pack_context();
fixed (byte* ttfPtr = ttf)
fixed (byte* pixelsPtr = pixels)
{
StbTrueType.stbtt_PackBegin(pc, pixelsPtr, bitmapWidth,
bitmapHeight, bitmapWidth, 1, null);
foreach (var range in characterRanges)
{
if (range.Start > range.End)
{
continue;
}
var cd = new StbTrueType.stbtt_packedchar[range.End - range.Start + 1];
for (var i = 0; i < cd.Length; ++i)
{
cd[i] = new StbTrueType.stbtt_packedchar();
}
fixed (StbTrueType.stbtt_packedchar* cdPtr = cd)
{
StbTrueType.stbtt_PackFontRange(pc, ttfPtr, 0, fontPixelHeight,
range.Start,
range.End - range.Start + 1,
cdPtr);
}
for (var i = 0; i < cd.Length; ++i)
{
var yOff = cd[i].yoff;
yOff += ascent * scaleFactor;
var glyphInfo = new GlyphInfo
{
X = cd[i].x0,
Y = cd[i].y0,
Width = cd[i].x1 - cd[i].x0,
Height = cd[i].y1 - cd[i].y0,
XOffset = (int)cd[i].xoff,
YOffset = (int)Math.Round(yOff),
XAdvance = (int)Math.Round(cd[i].xadvance)
};
glyphs[(char)(i + range.Start)] = glyphInfo;
}
}
}
return new TtfFontBakerResult(glyphs, fontPixelHeight, pixels, bitmapWidth, bitmapHeight);
}
}
}