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));