From df57d7ca6862d37ba3a6d79f5bf390d50df3f0aa Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 9 Dec 2023 23:45:57 +0100 Subject: [PATCH] LibGfx+LibWeb: Update for_each_glyph_position to use font cascade list This change updates function that builds list of glyphs to use font cascade list to find font for each code point. --- Tests/LibWeb/Ref/assets/HashSans.woff | Bin 0 -> 3388 bytes .../Ref/reference/unicode-range-ref.html | 23 +++++++++++++++++ Tests/LibWeb/Ref/unicode-range.html | 21 +++++++++++++++ Userland/Libraries/LibGfx/Painter.cpp | 4 ++- Userland/Libraries/LibGfx/Path.cpp | 4 ++- Userland/Libraries/LibGfx/TextLayout.h | 24 ++++++++++-------- .../LibWeb/Layout/InlineLevelIterator.cpp | 2 +- .../LibWeb/Painting/PaintableBox.cpp | 4 +-- 8 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 Tests/LibWeb/Ref/assets/HashSans.woff create mode 100644 Tests/LibWeb/Ref/reference/unicode-range-ref.html create mode 100644 Tests/LibWeb/Ref/unicode-range.html diff --git a/Tests/LibWeb/Ref/assets/HashSans.woff b/Tests/LibWeb/Ref/assets/HashSans.woff new file mode 100644 index 0000000000000000000000000000000000000000..fef3d53b001215c989489f3f4303d68781058a60 GIT binary patch literal 3388 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 + + + + + +
AB
+ + diff --git a/Tests/LibWeb/Ref/unicode-range.html b/Tests/LibWeb/Ref/unicode-range.html new file mode 100644 index 0000000000..c17d00a309 --- /dev/null +++ b/Tests/LibWeb/Ref/unicode-range.html @@ -0,0 +1,21 @@ + + + + + + + +
AB
+ + diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index fde4c74f39..df84adee8e 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -2439,7 +2439,9 @@ void Painter::draw_text_run(IntPoint baseline_start, Utf8View const& string, Fon void Painter::draw_text_run(FloatPoint baseline_start, Utf8View const& string, Font const& font, Color color) { - for_each_glyph_position(baseline_start, string, font, [&](DrawGlyphOrEmoji glyph_or_emoji) { + auto font_list = Gfx::FontCascadeList::create(); + font_list->add(font); + for_each_glyph_position(baseline_start, string, font_list, [&](DrawGlyphOrEmoji glyph_or_emoji) { if (glyph_or_emoji.has()) { auto& glyph = glyph_or_emoji.get(); draw_glyph(glyph.position, glyph.code_point, *glyph.font, color); diff --git a/Userland/Libraries/LibGfx/Path.cpp b/Userland/Libraries/LibGfx/Path.cpp index ed5a19dcf6..2700dae042 100644 --- a/Userland/Libraries/LibGfx/Path.cpp +++ b/Userland/Libraries/LibGfx/Path.cpp @@ -170,8 +170,10 @@ void Path::text(Utf8View text, Font const& font) } auto& scaled_font = static_cast(font); + auto font_list = Gfx::FontCascadeList::create(); + font_list->add(scaled_font); for_each_glyph_position( - last_point(), text, font, [&](DrawGlyphOrEmoji glyph_or_emoji) { + last_point(), text, font_list, [&](DrawGlyphOrEmoji glyph_or_emoji) { if (glyph_or_emoji.has()) { auto& glyph = glyph_or_emoji.get(); move_to(glyph.position); diff --git a/Userland/Libraries/LibGfx/TextLayout.h b/Userland/Libraries/LibGfx/TextLayout.h index 0d7ecf83c8..c627cf01f2 100644 --- a/Userland/Libraries/LibGfx/TextLayout.h +++ b/Userland/Libraries/LibGfx/TextLayout.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -92,34 +93,35 @@ using DrawGlyphOrEmoji = Variant; Variant prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font); template -void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, Font const& font, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional width = {}) +void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, FontCascadeList const& font_list, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional width = {}) { - float space_width = font.glyph_width(' ') + font.glyph_spacing(); + float space_width = font_list.first().glyph_width(' ') + font_list.first().glyph_spacing(); u32 last_code_point = 0; auto point = baseline_start; - point.translate_by(0, -font.pixel_metrics().ascent); - for (auto code_point_iterator = string.begin(); code_point_iterator != string.end(); ++code_point_iterator) { + auto it = code_point_iterator; // The callback function will advance the iterator, so create a copy for this lookup. auto code_point = *code_point_iterator; + RefPtr font = font_list.font_for_code_point(code_point); + + point.set_y(baseline_start.y() - font->pixel_metrics().ascent); + if (should_paint_as_space(code_point)) { point.translate_by(space_width, 0); last_code_point = code_point; continue; } - auto kerning = font.glyphs_horizontal_kerning(last_code_point, code_point); + auto kerning = font->glyphs_horizontal_kerning(last_code_point, code_point); if (kerning != 0.0f) point.translate_by(kerning, 0); - auto it = code_point_iterator; // The callback function will advance the iterator, so create a copy for this lookup. - auto glyph_width = font.glyph_or_emoji_width(it) + font.glyph_spacing(); - - auto glyph_or_emoji = prepare_draw_glyph_or_emoji(point, code_point_iterator, font); + auto glyph_width = font->glyph_or_emoji_width(it) + font->glyph_spacing(); + auto glyph_or_emoji = prepare_draw_glyph_or_emoji(point, code_point_iterator, *font); if (include_left_bearing == IncludeLeftBearing::Yes) { if (glyph_or_emoji.has()) - glyph_or_emoji.get().position += FloatPoint(font.glyph_left_bearing(code_point), 0); + glyph_or_emoji.get().position += FloatPoint(font->glyph_left_bearing(code_point), 0); } callback(glyph_or_emoji); @@ -129,7 +131,7 @@ void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, Font co } if (width.has_value()) - *width = point.x() - font.glyph_spacing(); + *width = point.x() - font_list.first().glyph_spacing(); } } diff --git a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp index 05f2485949..131f5ea9a0 100644 --- a/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp +++ b/Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp @@ -190,7 +190,7 @@ Optional InlineLevelIterator::next_without_lookahead( Vector glyph_run; float glyph_run_width = 0; Gfx::for_each_glyph_position( - { 0, 0 }, chunk.view, text_node.first_available_font(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) { + { 0, 0 }, chunk.view, text_node.font_list(), [&](Gfx::DrawGlyphOrEmoji const& glyph_or_emoji) { glyph_run.append(glyph_or_emoji); return IterationDecision::Continue; }, diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index cc69edb9f5..cc9c06ab0f 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -638,12 +638,12 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t auto text = text_node.text_for_rendering(); DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) }; - auto const& scaled_font = fragment.layout_node().scaled_font(context); Vector scaled_glyph_run; scaled_glyph_run.ensure_capacity(fragment.glyph_run().size()); + auto& font_cache = text_node.document().style_computer().font_cache(); for (auto glyph : fragment.glyph_run()) { glyph.visit([&](auto& glyph) { - glyph.font = scaled_font; + glyph.font = font_cache.scaled_font(*glyph.font, context.device_pixels_per_css_pixel()); glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel()); }); scaled_glyph_run.append(move(glyph));