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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 literal 0 HcmV?d00001 diff --git a/Tests/LibWeb/Ref/reference/unicode-range-ref.html b/Tests/LibWeb/Ref/reference/unicode-range-ref.html new file mode 100644 index 0000000000..8ed0415f0d --- /dev/null +++ b/Tests/LibWeb/Ref/reference/unicode-range-ref.html @@ -0,0 +1,23 @@ + + + + + + +
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));