Skip to content

Commit

Permalink
Add kerning to bitmap fonts created from BMFont files (#3035)
Browse files Browse the repository at this point in the history
* add kerning to BMFont

* fix unit test
  • Loading branch information
Geokureli authored Apr 15, 2024
1 parent 540cf28 commit 41a51c3
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 188 deletions.
62 changes: 22 additions & 40 deletions flixel/graphics/frames/FlxBitmapFont.hx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class FlxBitmapFont extends FlxFramesCollection
* Helper map where character's xAdvance are stored by char codes.
*/
var charAdvance:Map<Int, Int>;

var kerning:Map<Int, Map<Int, Int>>;

/**
* Atlas frame from which this font has been parsed.
Expand All @@ -88,6 +90,7 @@ class FlxBitmapFont extends FlxFramesCollection
parent.destroyOnNoUse = false;
charMap = new Map<Int, FlxFrame>();
charAdvance = new Map<Int, Int>();
kerning = new Map<Int, Map<Int, Int>>();
}

override public function destroy():Void
Expand Down Expand Up @@ -173,50 +176,13 @@ class FlxBitmapFont extends FlxFramesCollection
frame = graphic.imageFrame.frame;
}

var font:FlxBitmapFont = FlxBitmapFont.findFont(frame);
final font:FlxBitmapFont = FlxBitmapFont.findFont(frame);
if (font != null)
return font;

font = new FlxBitmapFont(frame);

final font = new FlxBitmapFont(frame);
final fontInfo = data.parse();

// how much to move the cursor when going to the next line.
font.lineHeight = fontInfo.common.lineHeight;
font.size = fontInfo.info.size;
font.fontName = fontInfo.info.face;
font.bold = fontInfo.info.bold;
font.italic = fontInfo.info.italic;

for (char in fontInfo.chars)
{
final frame = FlxRect.get();
frame.x = char.x; // X position within the bitmap image file.
frame.y = char.y; // Y position within the bitmap image file.
frame.width = char.width; // Width of the character in the image file.
frame.height = char.height; // Height of the character in the image file.

font.minOffsetX = (font.minOffsetX < -char.xoffset) ? -char.xoffset : font.minOffsetX;

if (char.id == -1)
{
throw 'Invalid font data!';
}

font.addCharFrame(char.id, frame, FlxPoint.weak(char.xoffset, char.yoffset), char.xadvance);

if (char.id == SPACE_CODE)
{
font.spaceWidth = char.xadvance;
}
else
{
font.lineHeight = (font.lineHeight > char.height + char.yoffset) ? font.lineHeight : char.height + char.yoffset;
}
}

font.updateSourceHeight();
return font;
return fontInfo.initBitmapFont(font);
}

/**
Expand Down Expand Up @@ -530,6 +496,22 @@ class FlxBitmapFont extends FlxFramesCollection
{
return charAdvance.exists(charCode) ? charAdvance.get(charCode) : 0;
}

public function getKerning(prevCode:Int, nextCode:Int):Int
{
if (kerning.exists(prevCode) && kerning[prevCode].exists(nextCode))
return kerning[prevCode][nextCode];
else
return 0;
}

public function addKerningPair(prevCode:Int, nextCode:Int, amount:Int)
{
if (!kerning.exists(prevCode))
kerning.set(prevCode, new Map<Int, Int>());

kerning[prevCode][nextCode] = amount;
}

public inline function getCharWidth(charCode:Int):Float
{
Expand Down
61 changes: 55 additions & 6 deletions flixel/graphics/frames/bmfont/BMFont.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package flixel.graphics.frames.bmfont;

import flixel.math.FlxRect;
import flixel.math.FlxPoint;
import flixel.system.FlxAssets;
import haxe.io.Bytes;
import haxe.io.BytesInput;
Expand All @@ -20,15 +22,15 @@ class BMFont
public var common:BMFontCommon;
public var pages:Array<BMFontPage>;
public var chars:Array<BMFontChar>;
public var kerning:Null<Array<BMFontKerning>> = null;
public var kernings:Null<Array<BMFontKerning>> = null;

function new(?info, ?common, ?pages, ?chars, ?kerning)
function new(?info, ?common, ?pages, ?chars, ?kernings)
{
this.info = info;
this.common = common;
this.pages = pages;
this.chars = chars;
this.kerning = kerning;
this.kernings = kernings;
}

public static function fromXml(xml:Xml)
Expand All @@ -38,14 +40,14 @@ class BMFont
final common = BMFontCommon.fromXml(main.node.get("common"));
final pages = BMFontPage.listFromXml(main.node.get("pages"));
final chars = BMFontChar.listFromXml(main.node.get("chars"));
var kerning:Array<BMFontKerning> = null;
var kernings:Array<BMFontKerning> = null;

if (main.hasNode("kernings"))
{
kerning = BMFontKerning.listFromXml(main.node.get("kernings"));
kernings = BMFontKerning.listFromXml(main.node.get("kernings"));
}

return new BMFont(info, common, pages, chars, kerning);
return new BMFont(info, common, pages, chars, kernings);
}

public static function fromText(text:String)
Expand Down Expand Up @@ -120,6 +122,53 @@ class BMFont
return new BMFont(info, common, pages, chars, kerning);
}

@:access(flixel.graphics.frames.FlxBitmapFont)
public function initBitmapFont(font:FlxBitmapFont):FlxBitmapFont
{
// how much to move the cursor when going to the next line.
font.lineHeight = common.lineHeight;
font.size = info.size;
font.fontName = info.face;
font.bold = info.bold;
font.italic = info.italic;

for (char in chars)
{
final frame = FlxRect.get();
frame.x = char.x; // X position within the bitmap image file.
frame.y = char.y; // Y position within the bitmap image file.
frame.width = char.width; // Width of the character in the image file.
frame.height = char.height; // Height of the character in the image file.

font.minOffsetX = (font.minOffsetX < -char.xoffset) ? -char.xoffset : font.minOffsetX;

if (char.id == -1)
{
throw 'Invalid font data!';
}

font.addCharFrame(char.id, frame, FlxPoint.get(char.xoffset, char.yoffset), char.xadvance);

if (char.id == FlxBitmapFont.SPACE_CODE)
{
font.spaceWidth = char.xadvance;
}
else
{
font.lineHeight = (font.lineHeight > char.height + char.yoffset) ? font.lineHeight : char.height + char.yoffset;
}
}

if (kernings != null)
{
for (kerning in kernings)
font.addKerningPair(kerning.first, kerning.second, kerning.amount);
}

font.updateSourceHeight();
return font;
}

public static function parse(data:FlxAngelCodeAsset):BMFont
{
return switch guessType(data)
Expand Down
Loading

0 comments on commit 41a51c3

Please sign in to comment.