if (FreeType.loadChar(face, ' ', FreeType.FT_LOAD_DEFAULT)) {
data.spaceWidth = FreeType.toInt(face.getGlyph().getMetrics().getHoriAdvance());
} else {
data.spaceWidth = face.getMaxAdvanceWidth(); // FIXME possibly very wrong :)
}
Glyph spaceGlyph = new Glyph();
spaceGlyph.xadvance = (int)data.spaceWidth;
spaceGlyph.id = (int)' ';
data.setGlyph(' ', spaceGlyph);
// determine x-height
for (char xChar : BitmapFont.xChars) {
if (!FreeType.loadChar(face, xChar, FreeType.FT_LOAD_DEFAULT)) continue;
data.xHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}
if (data.xHeight == 0) throw new GdxRuntimeException("No x-height character found in font");
for (char capChar : BitmapFont.capChars) {
if (!FreeType.loadChar(face, capChar, FreeType.FT_LOAD_DEFAULT)) continue;
data.capHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}
// determine cap height
if (!bitmapped && data.capHeight == 1) throw new GdxRuntimeException("No cap character found in font");
data.ascent = data.ascent - data.capHeight;
data.down = -data.lineHeight;
if (parameter.flip) {
data.ascent = -data.ascent;
data.down = -data.down;
}
boolean ownsAtlas = false;
PixmapPacker packer = parameter.packer;
if (packer == null) {
// generate the glyphs
int maxGlyphHeight = (int)Math.ceil(data.lineHeight);
int pageWidth = MathUtils
.nextPowerOfTwo((int)Math.sqrt(maxGlyphHeight * maxGlyphHeight * parameter.characters.length()));
if (maxTextureSize > 0) pageWidth = Math.min(pageWidth, maxTextureSize);
ownsAtlas = true;
packer = new PixmapPacker(pageWidth, pageWidth, Format.RGBA8888, 2, false);
}
// to minimize collisions we'll use this format : pathWithoutExtension_size[_flip]_glyph
String packPrefix = ownsAtlas ? "" : (filePath + '_' + parameter.size + (parameter.flip ? "_flip_" : '_'));
for (int i = 0; i < parameter.characters.length(); i++) {
char c = parameter.characters.charAt(i);
if (!FreeType.loadChar(face, c, FreeType.FT_LOAD_DEFAULT)) {
Gdx.app.log("FreeTypeFontGenerator", "Couldn't load char '" + c + "'");
continue;
}
if (!FreeType.renderGlyph(face.getGlyph(), FreeType.FT_RENDER_MODE_NORMAL)) {
Gdx.app.log("FreeTypeFontGenerator", "Couldn't render char '" + c + "'");
continue;
}
GlyphSlot slot = face.getGlyph();
GlyphMetrics metrics = slot.getMetrics();
Bitmap bitmap = slot.getBitmap();
Pixmap pixmap = bitmap.getPixmap(Format.RGBA8888);
Glyph glyph = new Glyph();
glyph.id = (int)c;
glyph.width = pixmap.getWidth();
glyph.height = pixmap.getHeight();
glyph.xoffset = slot.getBitmapLeft();
glyph.yoffset = parameter.flip ? -slot.getBitmapTop() + (int)baseLine : -(glyph.height - slot.getBitmapTop())
- (int)baseLine;
glyph.xadvance = FreeType.toInt(metrics.getHoriAdvance());
if (bitmapped) {
pixmap.setColor(Color.CLEAR);
pixmap.fill();
ByteBuffer buf = bitmap.getBuffer();
for (int h = 0; h < glyph.height; h++) {
int idx = h * bitmap.getPitch();
for (int w = 0; w < (glyph.width + glyph.xoffset); w++) {
int bit = (buf.get(idx + (w / 8)) >>> (7 - (w % 8))) & 1;
pixmap.drawPixel(w, h, ((bit == 1) ? Color.WHITE.toIntBits() : Color.CLEAR.toIntBits()));
}
}
}
String name = packPrefix + c;
Rectangle rect = packer.pack(name, pixmap);
// determine which page it was packed into
int pIndex = packer.getPageIndex(name);
if (pIndex == -1) // we should not get here
throw new IllegalStateException("packer was not able to insert '" + name + "' into a page");
glyph.page = pIndex;
glyph.srcX = (int)rect.x;
glyph.srcY = (int)rect.y;
data.setGlyph(c, glyph);
pixmap.dispose();
}
// generate kerning
for (int i = 0; i < parameter.characters.length(); i++) {
for (int j = 0; j < parameter.characters.length(); j++) {
char firstChar = parameter.characters.charAt(i);
Glyph first = data.getGlyph(firstChar);
if (first == null) continue;
char secondChar = parameter.characters.charAt(j);
Glyph second = data.getGlyph(secondChar);
if (second == null) continue;
int kerning = FreeType.getKerning(face, FreeType.getCharIndex(face, firstChar),
FreeType.getCharIndex(face, secondChar), 0);
if (kerning == 0) continue;
first.setKerning(secondChar, FreeType.toInt(kerning));