소스 검색

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.
Aliaksandr Kalenik 1 년 전
부모
커밋
df57d7ca68

BIN
Tests/LibWeb/Ref/assets/HashSans.woff


+ 23 - 0
Tests/LibWeb/Ref/reference/unicode-range-ref.html

@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        @font-face {
+            font-family: 'HashFont';
+            src: url('../assets/HashSans.woff');
+        }
+
+        .hash-font {
+          font-family: 'HashFont';
+        }
+
+        .text {
+          font-size: 100px;
+          font-family: "SerenitySans";
+        }
+    </style>
+</head>
+<body>
+    <div class="text"><span class="hash-font">A</span>B</div>
+</body>
+</html>

+ 21 - 0
Tests/LibWeb/Ref/unicode-range.html

@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <link rel="match" href="reference/unicode-range-ref.html" />
+    <style>
+        @font-face {
+            font-family: 'HashFont';
+            src: url('assets/HashSans.woff');
+            unicode-range: U+0041; /* Only letter 'A' */
+        }
+
+        .text {
+            font-family: 'HashFont', 'SerenitySans';
+            font-size: 100px;
+        }
+    </style>
+</head>
+<body>
+    <div class="text">AB</div>
+</body>
+</html>

+ 3 - 1
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<DrawGlyph>()) {
             auto& glyph = glyph_or_emoji.get<DrawGlyph>();
             draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);

+ 3 - 1
Userland/Libraries/LibGfx/Path.cpp

@@ -170,8 +170,10 @@ void Path::text(Utf8View text, Font const& font)
     }
 
     auto& scaled_font = static_cast<ScaledFont const&>(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<DrawGlyph>()) {
                 auto& glyph = glyph_or_emoji.get<DrawGlyph>();
                 move_to(glyph.position);

+ 13 - 11
Userland/Libraries/LibGfx/TextLayout.h

@@ -14,6 +14,7 @@
 #include <AK/Utf8View.h>
 #include <AK/Vector.h>
 #include <LibGfx/Font/Font.h>
+#include <LibGfx/FontCascadeList.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Rect.h>
 #include <LibGfx/TextElision.h>
@@ -92,34 +93,35 @@ using DrawGlyphOrEmoji = Variant<DrawGlyph, DrawEmoji>;
 Variant<DrawGlyph, DrawEmoji> prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font);
 
 template<typename Callback>
-void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, Font const& font, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional<float&> width = {})
+void for_each_glyph_position(FloatPoint baseline_start, Utf8View string, FontCascadeList const& font_list, Callback callback, IncludeLeftBearing include_left_bearing = IncludeLeftBearing::No, Optional<float&> 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<Gfx::Font const> 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<DrawGlyph>())
-                glyph_or_emoji.get<DrawGlyph>().position += FloatPoint(font.glyph_left_bearing(code_point), 0);
+                glyph_or_emoji.get<DrawGlyph>().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();
 }
 
 }

+ 1 - 1
Userland/Libraries/LibWeb/Layout/InlineLevelIterator.cpp

@@ -190,7 +190,7 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
         Vector<Gfx::DrawGlyphOrEmoji> 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;
             },

+ 2 - 2
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<Gfx::DrawGlyphOrEmoji> 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));