use of com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics in project libgdx by libgdx.
the class FreeTypeFontGenerator method scaleForPixelWidth.
/** Uses max advance, ascender and descender of font to calculate real height that makes any n glyphs to fit in given pixel
* width.
* @param width the max width to fit (in pixels)
* @param numChars max number of characters that to fill width */
public int scaleForPixelWidth(int width, int numChars) {
SizeMetrics fontMetrics = face.getSize().getMetrics();
int advance = FreeType.toInt(fontMetrics.getMaxAdvance());
int ascent = FreeType.toInt(fontMetrics.getAscender());
int descent = FreeType.toInt(fontMetrics.getDescender());
int unscaledHeight = ascent - descent;
int height = unscaledHeight * width / (advance * numChars);
setPixelSizes(0, height);
return height;
}
use of com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics in project libgdx by libgdx.
the class FreeTypeFontGenerator method generateData.
/** Generates a new {@link BitmapFontData} instance, expert usage only. Throws a GdxRuntimeException if something went wrong.
* @param parameter configures how the font is generated */
public FreeTypeBitmapFontData generateData(FreeTypeFontParameter parameter, FreeTypeBitmapFontData data) {
parameter = parameter == null ? new FreeTypeFontParameter() : parameter;
char[] characters = parameter.characters.toCharArray();
int charactersLength = characters.length;
boolean incremental = parameter.incremental;
int flags = getLoadingFlags(parameter);
setPixelSizes(0, parameter.size);
// set general font data
SizeMetrics fontMetrics = face.getSize().getMetrics();
data.flipped = parameter.flip;
data.ascent = FreeType.toInt(fontMetrics.getAscender());
data.descent = FreeType.toInt(fontMetrics.getDescender());
data.lineHeight = FreeType.toInt(fontMetrics.getHeight());
float baseLine = data.ascent;
// if bitmapped
if (bitmapped && (data.lineHeight == 0)) {
for (int c = 32; c < (32 + face.getNumGlyphs()); c++) {
if (loadChar(c, flags)) {
int lh = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
data.lineHeight = (lh > data.lineHeight) ? lh : data.lineHeight;
}
}
}
data.lineHeight += parameter.spaceY;
// determine space width
if (loadChar(' ', flags) || loadChar('l', flags)) {
data.spaceWidth = FreeType.toInt(face.getGlyph().getMetrics().getHoriAdvance());
} else {
// Possibly very wrong.
data.spaceWidth = face.getMaxAdvanceWidth();
}
// determine x-height
for (char xChar : data.xChars) {
if (!loadChar(xChar, flags))
continue;
data.xHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}
if (data.xHeight == 0)
throw new GdxRuntimeException("No x-height character found in font");
// determine cap height
for (char capChar : data.capChars) {
if (!loadChar(capChar, flags))
continue;
data.capHeight = FreeType.toInt(face.getGlyph().getMetrics().getHeight());
break;
}
if (!bitmapped && data.capHeight == 1)
throw new GdxRuntimeException("No cap character found in font");
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) {
// Create a packer.
int size;
PackStrategy packStrategy;
if (incremental) {
size = maxTextureSize;
packStrategy = new GuillotineStrategy();
} else {
int maxGlyphHeight = (int) Math.ceil(data.lineHeight);
size = MathUtils.nextPowerOfTwo((int) Math.sqrt(maxGlyphHeight * maxGlyphHeight * charactersLength));
if (maxTextureSize > 0)
size = Math.min(size, maxTextureSize);
packStrategy = new SkylineStrategy();
}
ownsAtlas = true;
packer = new PixmapPacker(size, size, Format.RGBA8888, 1, false, packStrategy);
packer.setTransparentColor(parameter.color);
packer.getTransparentColor().a = 0;
if (parameter.borderWidth > 0) {
packer.setTransparentColor(parameter.borderColor);
packer.getTransparentColor().a = 0;
}
}
if (incremental)
data.glyphs = new Array(charactersLength + 32);
Stroker stroker = null;
if (parameter.borderWidth > 0) {
stroker = library.createStroker();
stroker.set((int) (parameter.borderWidth * 64f), parameter.borderStraight ? FreeType.FT_STROKER_LINECAP_BUTT : FreeType.FT_STROKER_LINECAP_ROUND, parameter.borderStraight ? FreeType.FT_STROKER_LINEJOIN_MITER_FIXED : FreeType.FT_STROKER_LINEJOIN_ROUND, 0);
}
Glyph missingGlyph = createGlyph('\0', data, parameter, stroker, baseLine, packer);
if (missingGlyph != null && missingGlyph.width != 0 && missingGlyph.height != 0) {
data.setGlyph('\0', missingGlyph);
if (incremental)
data.glyphs.add(missingGlyph);
}
// Create glyphs largest height first for best packing.
int[] heights = new int[charactersLength];
for (int i = 0, n = charactersLength; i < n; i++) {
int height = loadChar(characters[i], flags) ? FreeType.toInt(face.getGlyph().getMetrics().getHeight()) : 0;
heights[i] = height;
}
int heightsCount = heights.length;
while (heightsCount > 0) {
int best = 0, maxHeight = heights[0];
for (int i = 1; i < heightsCount; i++) {
int height = heights[i];
if (height > maxHeight) {
maxHeight = height;
best = i;
}
}
char c = characters[best];
Glyph glyph = createGlyph(c, data, parameter, stroker, baseLine, packer);
if (glyph != null) {
data.setGlyph(c, glyph);
if (incremental)
data.glyphs.add(glyph);
}
heightsCount--;
heights[best] = heights[heightsCount];
char tmpChar = characters[best];
characters[best] = characters[heightsCount];
characters[heightsCount] = tmpChar;
}
if (stroker != null && !incremental)
stroker.dispose();
if (incremental) {
data.generator = this;
data.parameter = parameter;
data.stroker = stroker;
data.packer = packer;
}
// Generate kerning.
parameter.kerning &= face.hasKerning();
if (parameter.kerning) {
for (int i = 0; i < charactersLength; i++) {
char firstChar = characters[i];
Glyph first = data.getGlyph(firstChar);
if (first == null)
continue;
int firstIndex = face.getCharIndex(firstChar);
for (int ii = i; ii < charactersLength; ii++) {
char secondChar = characters[ii];
Glyph second = data.getGlyph(secondChar);
if (second == null)
continue;
int secondIndex = face.getCharIndex(secondChar);
int kerning = face.getKerning(firstIndex, secondIndex, 0);
if (kerning != 0)
first.setKerning(secondChar, FreeType.toInt(kerning));
kerning = face.getKerning(secondIndex, firstIndex, 0);
if (kerning != 0)
second.setKerning(firstChar, FreeType.toInt(kerning));
}
}
}
// Generate texture regions.
if (ownsAtlas) {
data.regions = new Array();
packer.updateTextureRegions(data.regions, parameter.minFilter, parameter.magFilter, parameter.genMipMaps);
}
// Set space glyph.
Glyph spaceGlyph = data.getGlyph(' ');
if (spaceGlyph == null) {
spaceGlyph = new Glyph();
spaceGlyph.xadvance = (int) data.spaceWidth + parameter.spaceX;
spaceGlyph.id = (int) ' ';
data.setGlyph(' ', spaceGlyph);
}
if (spaceGlyph.width == 0)
spaceGlyph.width = (int) (spaceGlyph.xadvance + data.padRight);
return data;
}
use of com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics in project libgdx by libgdx.
the class FreeTypeFontGenerator method generateGlyphAndBitmap.
/** Returns null if glyph was not found. If there is nothing to render, for example with various space characters, then bitmap
* is null. */
public GlyphAndBitmap generateGlyphAndBitmap(int c, int size, boolean flip) {
setPixelSizes(0, size);
SizeMetrics fontMetrics = face.getSize().getMetrics();
int baseline = FreeType.toInt(fontMetrics.getAscender());
// 0 means 'undefined character code'
if (face.getCharIndex(c) == 0) {
return null;
}
// Try to load character
if (!loadChar(c)) {
throw new GdxRuntimeException("Unable to load character!");
}
GlyphSlot slot = face.getGlyph();
// Try to render to bitmap
Bitmap bitmap;
if (bitmapped) {
bitmap = slot.getBitmap();
} else if (!slot.renderGlyph(FreeType.FT_RENDER_MODE_NORMAL)) {
bitmap = null;
} else {
bitmap = slot.getBitmap();
}
GlyphMetrics metrics = slot.getMetrics();
Glyph glyph = new Glyph();
if (bitmap != null) {
glyph.width = bitmap.getWidth();
glyph.height = bitmap.getRows();
} else {
glyph.width = 0;
glyph.height = 0;
}
glyph.xoffset = slot.getBitmapLeft();
glyph.yoffset = flip ? -slot.getBitmapTop() + baseline : -(glyph.height - slot.getBitmapTop()) - baseline;
glyph.xadvance = FreeType.toInt(metrics.getHoriAdvance());
glyph.srcX = 0;
glyph.srcY = 0;
glyph.id = c;
GlyphAndBitmap result = new GlyphAndBitmap();
result.glyph = glyph;
result.bitmap = bitmap;
return result;
}
use of com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics in project libgdx by libgdx.
the class FreeTypeFontGenerator method scaleForPixelHeight.
/** Uses ascender and descender of font to calculate real height that makes all glyphs to fit in given pixel size. Source:
* http://nothings.org/stb/stb_truetype.h / stbtt_ScaleForPixelHeight */
public int scaleForPixelHeight(int height) {
setPixelSizes(0, height);
SizeMetrics fontMetrics = face.getSize().getMetrics();
int ascent = FreeType.toInt(fontMetrics.getAscender());
int descent = FreeType.toInt(fontMetrics.getDescender());
return height * height / (ascent - descent);
}
Aggregations