Merge branch 'frankfontaine' into 'master'

Properly implement bitmap font kerning (#8378)

See merge request OpenMW/openmw!4565
This commit is contained in:
psi29a 2025-03-05 21:16:19 +00:00
commit 8bbb46b52c

View file

@ -363,8 +363,8 @@ namespace Gui
Point bottom_right; Point bottom_right;
float width; float width;
float height; float height;
float u2; // appears unused, always 0 float kerningLeft;
float kerning; float kerningRight;
float ascent; float ascent;
} GlyphInfo; } GlyphInfo;
@ -570,6 +570,12 @@ namespace Gui
additional.emplace(69, 0x0401); // Ё (Cyrillic Capital Letter Io) => E (latin capital E) additional.emplace(69, 0x0401); // Ё (Cyrillic Capital Letter Io) => E (latin capital E)
additional.emplace(137, 0x0451); // ё (Cyrillic Small Letter Io) => ë (latin small E-diaeresis) additional.emplace(137, 0x0451); // ё (Cyrillic Small Letter Io) => ë (latin small E-diaeresis)
// ASCII vertical bar, use this as text input cursor
additional.emplace(124, MyGUI::FontCodeType::Cursor);
// Underscore, use for NotDefined marker (used for glyphs not existing in the font)
additional.emplace(95, MyGUI::FontCodeType::NotDefined);
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
{ {
float x1 = data[i].top_left.x * width; float x1 = data[i].top_left.x * width;
@ -579,64 +585,31 @@ namespace Gui
ToUTF8::Utf8Encoder encoder(mEncoding); ToUTF8::Utf8Encoder encoder(mEncoding);
unsigned long unicodeVal = getUnicode(i, encoder, mEncoding); unsigned long unicodeVal = getUnicode(i, encoder, mEncoding);
const std::string coord = MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " " + MyGUI::utility::toString(h);
float advance = data[i].width + data[i].kerningRight;
// Yes MyGUI, we really do want an advance of 0 sometimes, thank you.
if (advance == 0.f && data[i].width != 0.f)
advance = std::numeric_limits<float>::min();
const std::string bearing = MyGUI::utility::toString(data[i].kerningLeft) + ' '
+ MyGUI::utility::toString((fontSize - data[i].ascent));
const MyGUI::IntSize size(static_cast<int>(data[i].width), static_cast<int>(data[i].height));
MyGUI::xml::ElementPtr code = codes->createChild("Code"); MyGUI::xml::ElementPtr code = codes->createChild("Code");
code->addAttribute("index", unicodeVal); code->addAttribute("index", unicodeVal);
code->addAttribute("coord", code->addAttribute("coord", coord);
MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " " + MyGUI::utility::toString(w) code->addAttribute("advance", advance);
+ " " + MyGUI::utility::toString(h)); code->addAttribute("bearing", bearing);
code->addAttribute("advance", data[i].width); code->addAttribute("size", size);
code->addAttribute("bearing",
MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize - data[i].ascent)));
code->addAttribute(
"size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
for (auto [it, end] = additional.equal_range(i); it != end; ++it) for (auto [it, end] = additional.equal_range(i); it != end; ++it)
{ {
code = codes->createChild("Code"); code = codes->createChild("Code");
code->addAttribute("index", it->second); code->addAttribute("index", it->second);
code->addAttribute("coord", code->addAttribute("coord", coord);
MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " " code->addAttribute("advance", advance);
+ MyGUI::utility::toString(w) + " " + MyGUI::utility::toString(h)); code->addAttribute("bearing", bearing);
code->addAttribute("advance", data[i].width); code->addAttribute("size", size);
code->addAttribute("bearing",
MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize - data[i].ascent)));
code->addAttribute(
"size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
}
// ASCII vertical bar, use this as text input cursor
if (i == 124)
{
MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code");
cursorCode->addAttribute("index", MyGUI::FontCodeType::Cursor);
cursorCode->addAttribute("coord",
MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " " + MyGUI::utility::toString(h));
cursorCode->addAttribute("advance", data[i].width);
cursorCode->addAttribute("bearing",
MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize - data[i].ascent)));
cursorCode->addAttribute(
"size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
}
// Underscore, use for NotDefined marker (used for glyphs not existing in the font)
if (i == 95)
{
MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code");
cursorCode->addAttribute("index", MyGUI::FontCodeType::NotDefined);
cursorCode->addAttribute("coord",
MyGUI::utility::toString(x1) + " " + MyGUI::utility::toString(y1) + " "
+ MyGUI::utility::toString(w) + " " + MyGUI::utility::toString(h));
cursorCode->addAttribute("advance", data[i].width);
cursorCode->addAttribute("bearing",
MyGUI::utility::toString(data[i].kerning) + " "
+ MyGUI::utility::toString((fontSize - data[i].ascent)));
cursorCode->addAttribute(
"size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
} }
} }
@ -645,12 +618,12 @@ namespace Gui
omitted.push_back(MyGUI::FontCodeType::SelectedBack); omitted.push_back(MyGUI::FontCodeType::SelectedBack);
for (const UnicodeIndex index : omitted) for (const UnicodeIndex index : omitted)
{ {
MyGUI::xml::ElementPtr cursorCode = codes->createChild("Code"); MyGUI::xml::ElementPtr code = codes->createChild("Code");
cursorCode->addAttribute("index", index); code->addAttribute("index", index);
cursorCode->addAttribute("coord", "0 0 0 0"); code->addAttribute("coord", "0 0 0 0");
cursorCode->addAttribute("advance", "0"); code->addAttribute("advance", "0");
cursorCode->addAttribute("bearing", "0 0"); code->addAttribute("bearing", "0 0");
cursorCode->addAttribute("size", "0 0"); code->addAttribute("size", "0 0");
} }
// Register the font with MyGUI // Register the font with MyGUI