Search in sources :

Example 1 with SizeMetrics

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;
}
Also used : SizeMetrics(com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics)

Example 2 with SizeMetrics

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;
}
Also used : SizeMetrics(com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics) Stroker(com.badlogic.gdx.graphics.g2d.freetype.FreeType.Stroker) GdxRuntimeException(com.badlogic.gdx.utils.GdxRuntimeException) Array(com.badlogic.gdx.utils.Array) GuillotineStrategy(com.badlogic.gdx.graphics.g2d.PixmapPacker.GuillotineStrategy) SkylineStrategy(com.badlogic.gdx.graphics.g2d.PixmapPacker.SkylineStrategy) PixmapPacker(com.badlogic.gdx.graphics.g2d.PixmapPacker) Glyph(com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph) PackStrategy(com.badlogic.gdx.graphics.g2d.PixmapPacker.PackStrategy)

Example 3 with SizeMetrics

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;
}
Also used : GdxRuntimeException(com.badlogic.gdx.utils.GdxRuntimeException) GlyphSlot(com.badlogic.gdx.graphics.g2d.freetype.FreeType.GlyphSlot) Bitmap(com.badlogic.gdx.graphics.g2d.freetype.FreeType.Bitmap) GlyphMetrics(com.badlogic.gdx.graphics.g2d.freetype.FreeType.GlyphMetrics) Glyph(com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph) SizeMetrics(com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics)

Example 4 with SizeMetrics

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);
}
Also used : SizeMetrics(com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics)

Aggregations

SizeMetrics (com.badlogic.gdx.graphics.g2d.freetype.FreeType.SizeMetrics)4 Glyph (com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph)2 GdxRuntimeException (com.badlogic.gdx.utils.GdxRuntimeException)2 PixmapPacker (com.badlogic.gdx.graphics.g2d.PixmapPacker)1 GuillotineStrategy (com.badlogic.gdx.graphics.g2d.PixmapPacker.GuillotineStrategy)1 PackStrategy (com.badlogic.gdx.graphics.g2d.PixmapPacker.PackStrategy)1 SkylineStrategy (com.badlogic.gdx.graphics.g2d.PixmapPacker.SkylineStrategy)1 Bitmap (com.badlogic.gdx.graphics.g2d.freetype.FreeType.Bitmap)1 GlyphMetrics (com.badlogic.gdx.graphics.g2d.freetype.FreeType.GlyphMetrics)1 GlyphSlot (com.badlogic.gdx.graphics.g2d.freetype.FreeType.GlyphSlot)1 Stroker (com.badlogic.gdx.graphics.g2d.freetype.FreeType.Stroker)1 Array (com.badlogic.gdx.utils.Array)1