public FreeTypeBitmapFontData generateData (FreeTypeFontParameter parameter, FreeTypeBitmapFontData data) {
        data.name = name + "-" + parameter.size;
        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.spaceXadvance = FreeType.toInt(face.getGlyph().getMetrics().getHoriAdvance());
        } else {
            data.spaceXadvance = face.getMaxAdvanceWidth(); // Possibly very wrong.
        }
        
        // 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()) + Math.abs(parameter.shadowOffsetY);
            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);
        }
        
        // Create glyphs largest height first for best packing.
        int[] heights = new int[charactersLength];
        for (int i = 0; i < charactersLength; i++) {
            char c = characters[i];
            
            int height = loadChar(c, flags) ? FreeType.toInt(face.getGlyph().getMetrics().getHeight()) : 0;
            heights[i] = height;
            
            if (c == '\0') {
                Glyph missingGlyph = createGlyph('\0', data, parameter, stroker, baseLine, packer);
                if (missingGlyph != null && missingGlyph.width != 0 && missingGlyph.height != 0) {
                    data.setGlyph('\0', missingGlyph);
                    data.missingGlyph = missingGlyph;
                    if (incremental) data.glyphs.add(missingGlyph);
                }
            }
        }
        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];
            if (data.getGlyph(c) == null) {
                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); // FT_KERNING_DEFAULT (scaled then rounded).
                    if (kerning != 0) first.setKerning(secondChar, FreeType.toInt(kerning));
                    
                    kerning = face.getKerning(secondIndex, firstIndex, 0); // FT_KERNING_DEFAULT (scaled then rounded).
                    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.spaceXadvance + parameter.spaceX;
            spaceGlyph.id = (int)' ';
            data.setGlyph(' ', spaceGlyph);
        }
        if (spaceGlyph.width == 0) spaceGlyph.width = (int)(spaceGlyph.xadvance + data.padRight);
        
        return data;
    }
Generates a new {@link BitmapFontData} instance, expert usage only. Throws a GdxRuntimeException if something went wrong.
@param parameter configures how the font is generated
core/src/com/badlogic/gdx/graphics/g2d/freetype/FreeTypeFontGenerator.java