diff --git a/Tests/LibWeb/Ref/assets/HashSans.woff b/Tests/LibWeb/Ref/assets/HashSans.woff new file mode 100644 index 00000000000..fef3d53b001 Binary files /dev/null and b/Tests/LibWeb/Ref/assets/HashSans.woff differ 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 00000000000..8ed0415f0d3 --- /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 00000000000..c17d00a3094 --- /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 fde4c74f39a..df84adee8e5 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 ed5a19dcf61..2700dae0423 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 0d7ecf83c8f..c627cf01f26 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 05f2485949b..131f5ea9a0c 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 cc69edb9f52..cc9c06ab0fa 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));