Revert: "Change: Support side-by-side fallback FontCaches instead of hierarchical. (#13303)"

This reverts commit 1829f7926d.
This commit is contained in:
Peter Nelson
2025-12-13 00:29:06 +00:00
committed by dP
parent 766ab3804d
commit 2c528229cb
32 changed files with 480 additions and 783 deletions

View File

@@ -11,9 +11,6 @@
#include "gfx_layout_icu.h"
#include "debug.h"
#include "gfx_func.h"
#include "gfx_layout_fallback.h"
#include "string_func.h"
#include "strings_func.h"
#include "language.h"
#include "table/control_codes.h"
@@ -43,7 +40,7 @@ public:
int length; ///< Length of the run in the buffer.
UBiDiLevel level; ///< Embedding level of the run.
UScriptCode script; ///< Script of the run.
Font font; ///< Font of the run.
Font *font; ///< Font of the run.
std::vector<GlyphID> glyphs; ///< The glyphs of the run. Valid after Shape() is called.
std::vector<int> advance; ///< The advance (width) of the glyphs. Valid after Shape() is called.
@@ -51,10 +48,9 @@ public:
std::vector<ParagraphLayouter::Position> positions; ///< The positions of the glyphs. Valid after Shape() is called.
int total_advance = 0; ///< The total advance of the run. Valid after Shape() is called.
ICURun(int start, int length, UBiDiLevel level, UScriptCode script, const Font &font) : start(start), length(length), level(level), script(script), font(font) {}
ICURun(int start, int length, UBiDiLevel level, UScriptCode script = USCRIPT_UNKNOWN, Font *font = nullptr) : start(start), length(length), level(level), script(script), font(font) {}
void Shape(UChar *buff, size_t length);
void FallbackShape(UChar *buff);
};
/**
@@ -70,7 +66,7 @@ public:
std::vector<int> glyph_to_char;
int total_advance;
Font font;
const Font *font;
public:
ICUVisualRun(const ICURun &run, int x);
@@ -79,8 +75,8 @@ public:
std::span<const Position> GetPositions() const override { return this->positions; }
std::span<const int> GetGlyphToCharMap() const override { return this->glyph_to_char; }
const Font &GetFont() const override { return this->font; }
int GetLeading() const override { return GetCharacterHeight(this->font.GetFontCache().GetSize()); }
const Font *GetFont() const override { return this->font; }
int GetLeading() const override { return this->font->fc->GetHeight(); }
int GetGlyphCount() const override { return this->glyphs.size(); }
int GetAdvance() const { return this->total_advance; }
};
@@ -145,46 +141,6 @@ ICUParagraphLayout::ICUVisualRun::ICUVisualRun(const ICURun &run, int x) :
}
}
/**
* Manually shape a run for built-in non-truetype fonts.
* Similar to but not quite the same as \a UniscribeRun::FallbackShape.
* @param buff The complete buffer of the run.
*/
void ICURun::FallbackShape(UChar *buff)
{
FontCache &fc = this->font.GetFontCache();
this->glyphs.reserve(this->length);
this->glyph_to_char.reserve(this->length);
/* Read each UTF-16 character, mapping to an appropriate glyph. */
for (int i = this->start; i < this->start + this->length; i += Utf16IsLeadSurrogate(buff[i]) ? 2 : 1) {
char32_t c = Utf16DecodeChar(reinterpret_cast<uint16_t *>(buff + i));
if (this->level & 1) c = SwapRtlPairedCharacters(c);
this->glyphs.emplace_back(fc.MapCharToGlyph(c));
this->glyph_to_char.push_back(i);
}
/* Reverse the sequence if this run is RTL. */
if (this->level & 1) {
std::reverse(std::begin(this->glyphs), std::end(this->glyphs));
std::reverse(std::begin(this->glyph_to_char), std::end(this->glyph_to_char));
}
this->positions.reserve(this->glyphs.size());
/* Set positions of each glyph. */
int y_offset = fc.GetGlyphYOffset();
int advance = 0;
for (const GlyphID glyph : this->glyphs) {
int x_advance = fc.GetGlyphWidth(glyph);
this->positions.emplace_back(advance, advance + x_advance - 1, y_offset);
this->advance.push_back(x_advance);
advance += x_advance;
}
this->total_advance = advance;
}
/**
* Shape a single run.
*
@@ -193,20 +149,7 @@ void ICURun::FallbackShape(UChar *buff)
*/
void ICURun::Shape(UChar *buff, size_t buff_length)
{
FontCache &fc = this->font.GetFontCache();
/* Make sure any former run is lost. */
this->glyphs.clear();
this->glyph_to_char.clear();
this->positions.clear();
this->advance.clear();
if (fc.IsBuiltInFont()) {
this->FallbackShape(buff);
return;
}
auto hbfont = hb_ft_font_create_referenced(*(static_cast<const FT_Face *>(fc.GetOSHandle())));
auto hbfont = hb_ft_font_create_referenced(*(static_cast<const FT_Face *>(font->fc->GetOSHandle())));
/* Match the flags with how we render the glyphs. */
hb_ft_font_set_load_flags(hbfont, GetFontAAState() ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO);
@@ -227,6 +170,12 @@ void ICURun::Shape(UChar *buff, size_t buff_length)
auto glyph_info = hb_buffer_get_glyph_infos(hbbuf, &glyph_count);
auto glyph_pos = hb_buffer_get_glyph_positions(hbbuf, &glyph_count);
/* Make sure any former run is lost. */
this->glyphs.clear();
this->glyph_to_char.clear();
this->positions.clear();
this->advance.clear();
/* Reserve space, as we already know the size. */
this->glyphs.reserve(glyph_count);
this->glyph_to_char.reserve(glyph_count);
@@ -234,12 +183,20 @@ void ICURun::Shape(UChar *buff, size_t buff_length)
this->advance.reserve(glyph_count);
/* Prepare the glyphs/position. ICUVisualRun will give the position an offset if needed. */
int y_offset = fc.GetGlyphYOffset();
hb_position_t advance = 0;
for (unsigned int i = 0; i < glyph_count; i++) {
int x_advance = glyph_pos[i].x_advance / FONT_SCALE;
this->glyphs.push_back(glyph_info[i].codepoint);
this->positions.emplace_back(glyph_pos[i].x_offset / FONT_SCALE + advance, glyph_pos[i].x_offset / FONT_SCALE + advance + x_advance - 1, glyph_pos[i].y_offset / FONT_SCALE + y_offset);
int x_advance;
if (buff[glyph_info[i].cluster] >= SCC_SPRITE_START && buff[glyph_info[i].cluster] <= SCC_SPRITE_END && glyph_info[i].codepoint == 0) {
auto glyph = this->font->fc->MapCharToGlyph(buff[glyph_info[i].cluster]);
x_advance = this->font->fc->GetGlyphWidth(glyph);
this->glyphs.push_back(glyph);
this->positions.emplace_back(advance, advance + x_advance - 1, (this->font->fc->GetHeight() - ScaleSpriteTrad(FontCache::GetDefaultFontHeight(this->font->fc->GetSize()))) / 2); // Align sprite font to centre
} else {
x_advance = glyph_pos[i].x_advance / FONT_SCALE;
this->glyphs.push_back(glyph_info[i].codepoint);
this->positions.emplace_back(glyph_pos[i].x_offset / FONT_SCALE + advance, glyph_pos[i].x_offset / FONT_SCALE + advance + x_advance - 1, glyph_pos[i].y_offset / FONT_SCALE);
}
this->glyph_to_char.push_back(glyph_info[i].cluster);
this->advance.push_back(x_advance);
@@ -323,7 +280,7 @@ std::vector<ICURun> ItemizeBidi(UChar *buff, size_t length)
UBiDiLevel level;
ubidi_getLogicalRun(ubidi, start_pos, &logical_pos, &level);
runs.emplace_back(start_pos, logical_pos - start_pos, level, USCRIPT_UNKNOWN, Font{});
runs.emplace_back(start_pos, logical_pos - start_pos, level);
}
assert(static_cast<size_t>(count) == runs.size());
@@ -354,7 +311,7 @@ std::vector<ICURun> ItemizeScript(UChar *buff, size_t length, std::vector<ICURun
int stop_pos = std::min(script_itemizer.getScriptEnd(), cur_run->start + cur_run->length);
assert(stop_pos - cur_pos > 0);
runs.emplace_back(cur_pos, stop_pos - cur_pos, cur_run->level, script_itemizer.getScriptCode(), Font{});
runs.emplace_back(cur_pos, stop_pos - cur_pos, cur_run->level, script_itemizer.getScriptCode());
if (stop_pos == cur_run->start + cur_run->length) cur_run++;
cur_pos = stop_pos;
@@ -402,6 +359,11 @@ std::vector<ICURun> ItemizeStyle(std::vector<ICURun> &runs_current, FontMap &fon
/* Can't layout an empty string. */
if (length == 0) return nullptr;
/* Can't layout our in-built sprite fonts. */
for (auto const &[position, font] : font_mapping) {
if (font->fc->IsBuiltInFont()) return nullptr;
}
auto runs = ItemizeBidi(buff, length);
runs = ItemizeScript(buff, length, runs);
runs = ItemizeStyle(runs, font_mapping);