mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Added basic kerning support for TrueType and BMFont fonts (resolves issue #1055.)
This commit is contained in:
@@ -59,7 +59,7 @@ public:
|
||||
private:
|
||||
|
||||
std::string tag;
|
||||
std::map<std::string, std::string> attributes;
|
||||
std::unordered_map<std::string, std::string> attributes;
|
||||
|
||||
};
|
||||
|
||||
@@ -226,7 +226,12 @@ void BMFontRasterizer::parseConfig(const std::string &configtext)
|
||||
}
|
||||
else if (tag == "kerning")
|
||||
{
|
||||
// TODO
|
||||
uint32 firstid = (uint32) cline.getAttributeInt("first");
|
||||
uint32 secondid = (uint32) cline.getAttributeInt("second");
|
||||
|
||||
uint64 packedids = ((uint64) firstid << 32) | (uint64) secondid;
|
||||
|
||||
kerning[packedids] = cline.getAttributeInt("amount");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +314,17 @@ bool BMFontRasterizer::hasGlyph(uint32 glyph) const
|
||||
return characters.find(glyph) != characters.end();
|
||||
}
|
||||
|
||||
float BMFontRasterizer::getKerning(uint32 leftglyph, uint32 rightglyph) const
|
||||
{
|
||||
uint64 packedglyphs = ((uint64) leftglyph << 32) | (uint64) rightglyph;
|
||||
|
||||
auto it = kerning.find(packedglyphs);
|
||||
if (it != kerning.end())
|
||||
return it->second;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool BMFontRasterizer::accepts(love::filesystem::FileData *fontdef)
|
||||
{
|
||||
const char *data = (const char *) fontdef->getData();
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "image/ImageData.h"
|
||||
|
||||
// C++
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace love
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
GlyphData *getGlyphData(uint32 glyph) const override;
|
||||
int getGlyphCount() const override;
|
||||
bool hasGlyph(uint32 glyph) const override;
|
||||
float getKerning(uint32 leftglyph, uint32 rightglyph) const;
|
||||
|
||||
static bool accepts(love::filesystem::FileData *fontdef);
|
||||
|
||||
@@ -68,10 +69,13 @@ private:
|
||||
std::string fontFolder;
|
||||
|
||||
// Image pages, indexed by their page id.
|
||||
std::map<int, StrongRef<image::ImageData>> images;
|
||||
std::unordered_map<int, StrongRef<image::ImageData>> images;
|
||||
|
||||
// Glyph characters, indexed by their glyph id.
|
||||
std::map<uint32, BMFontCharacter> characters;
|
||||
std::unordered_map<uint32, BMFontCharacter> characters;
|
||||
|
||||
// Kerning information, indexed by two (packed) characters.
|
||||
std::unordered_map<uint64, int> kerning;
|
||||
|
||||
int fontSize;
|
||||
bool unicode;
|
||||
|
||||
@@ -95,5 +95,10 @@ bool Rasterizer::hasGlyphs(const std::string &text) const
|
||||
return true;
|
||||
}
|
||||
|
||||
float Rasterizer::getKerning(uint32 /*leftglyph*/, uint32 /*rightglyph*/) const
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
} // font
|
||||
} // love
|
||||
|
||||
@@ -105,6 +105,11 @@ public:
|
||||
**/
|
||||
virtual bool hasGlyphs(const std::string &text) const;
|
||||
|
||||
/**
|
||||
* Gets the amount of horizontal kerning between two glyphs.
|
||||
**/
|
||||
virtual float getKerning(uint32 leftglyph, uint32 rightglyph) const;
|
||||
|
||||
protected:
|
||||
|
||||
FontMetrics metrics;
|
||||
|
||||
@@ -165,6 +165,13 @@ bool TrueTypeRasterizer::hasGlyph(uint32 glyph) const
|
||||
return FT_Get_Char_Index(face, glyph) != 0;
|
||||
}
|
||||
|
||||
float TrueTypeRasterizer::getKerning(uint32 leftglyph, uint32 rightglyph) const
|
||||
{
|
||||
FT_Vector kerning = {};
|
||||
FT_Get_Kerning(face, leftglyph, rightglyph, FT_KERNING_DEFAULT, &kerning);
|
||||
return float(kerning.x >> 6);
|
||||
}
|
||||
|
||||
bool TrueTypeRasterizer::accepts(FT_Library library, love::Data *data)
|
||||
{
|
||||
const FT_Byte *fbase = (const FT_Byte *) data->getData();
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
virtual GlyphData *getGlyphData(uint32 glyph) const;
|
||||
virtual int getGlyphCount() const;
|
||||
virtual bool hasGlyph(uint32 glyph) const;
|
||||
virtual float getKerning(uint32 leftglyph, uint32 rightglyph) const;
|
||||
|
||||
static bool accepts(FT_Library library, love::Data *data);
|
||||
|
||||
|
||||
@@ -316,6 +316,29 @@ const Font::Glyph &Font::findGlyph(uint32 glyph)
|
||||
return addGlyph(glyph);
|
||||
}
|
||||
|
||||
float Font::getKerning(uint32 leftglyph, uint32 rightglyph)
|
||||
{
|
||||
uint64 packedglyphs = ((uint64) leftglyph << 32) | (uint64) rightglyph;
|
||||
|
||||
const auto it = kerning.find(packedglyphs);
|
||||
if (it != kerning.end())
|
||||
return it->second;
|
||||
|
||||
float k = rasterizers[0]->getKerning(leftglyph, rightglyph);
|
||||
|
||||
for (const auto &r : rasterizers)
|
||||
{
|
||||
if (r->hasGlyph(leftglyph) && r->hasGlyph(rightglyph))
|
||||
{
|
||||
k = r->getKerning(leftglyph, rightglyph);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kerning[packedglyphs] = k;
|
||||
return k;
|
||||
}
|
||||
|
||||
float Font::getHeight() const
|
||||
{
|
||||
return (float) height;
|
||||
@@ -337,6 +360,8 @@ std::vector<Font::DrawCommand> Font::generateVertices(const std::string &text, s
|
||||
size_t vertstartsize = vertices.size();
|
||||
vertices.reserve(vertstartsize + text.length() * 4);
|
||||
|
||||
uint32 prevglyph = 0;
|
||||
|
||||
try
|
||||
{
|
||||
utf8::iterator<std::string::const_iterator> i(text.begin(), text.begin(), text.end());
|
||||
@@ -370,17 +395,21 @@ std::vector<Font::DrawCommand> Font::generateVertices(const std::string &text, s
|
||||
dy = offset.y;
|
||||
drawcommands.clear();
|
||||
vertices.resize(vertstartsize);
|
||||
prevglyph = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add kerning to the current horizontal offset.
|
||||
dx += getKerning(prevglyph, g);
|
||||
|
||||
if (glyph.texture != 0)
|
||||
{
|
||||
// Copy the vertices and set their proper relative positions.
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
vertices.push_back(glyph.vertices[j]);
|
||||
vertices.back().x += dx;
|
||||
vertices.back().y += dy + lineheight;
|
||||
vertices.back().x += dx /*+ kerning*/;
|
||||
vertices.back().y += dy /*+ kerning.y*/ + lineheight;
|
||||
}
|
||||
|
||||
// Check if glyph texture has changed since the last iteration.
|
||||
@@ -403,6 +432,8 @@ std::vector<Font::DrawCommand> Font::generateVertices(const std::string &text, s
|
||||
// Account for extra spacing given to space characters.
|
||||
if (g == ' ' && extra_spacing != 0.0f)
|
||||
dx = floorf(dx + extra_spacing);
|
||||
|
||||
prevglyph = g;
|
||||
}
|
||||
}
|
||||
catch (utf8::exception &e)
|
||||
|
||||
@@ -211,6 +211,7 @@ private:
|
||||
love::font::GlyphData *getRasterizerGlyphData(uint32 glyph);
|
||||
const Glyph &addGlyph(uint32 glyph);
|
||||
const Glyph &findGlyph(uint32 glyph);
|
||||
float getKerning(uint32 leftglyph, uint32 rightglyph);
|
||||
void printv(const Matrix4 &t, const std::vector<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices);
|
||||
|
||||
std::vector<StrongRef<love::font::Rasterizer>> rasterizers;
|
||||
@@ -227,6 +228,9 @@ private:
|
||||
// maps glyphs to glyph texture information
|
||||
std::unordered_map<uint32, Glyph> glyphs;
|
||||
|
||||
// map of left/right glyph pairs to horizontal kerning.
|
||||
std::unordered_map<uint64, float> kerning;
|
||||
|
||||
FontType type;
|
||||
Texture::Filter filter;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user