Browse Source

LibWeb: Save unscaled glyph run in PaintTextShadow command

Implements the same optimization we already have for DrawGlyphRun by
saving unscaled glyph run and scale factor in a painting command, which
allows to avoid copying of glyphs vector to apply scaling during
recording.
Aliaksandr Kalenik 1 year ago
parent
commit
ebc282207b

+ 2 - 1
Userland/Libraries/LibWeb/Painting/Command.h

@@ -142,7 +142,8 @@ struct PaintTextShadow {
     int blur_radius;
     Gfx::IntRect shadow_bounding_rect;
     Gfx::IntRect text_rect;
-    Vector<Gfx::DrawGlyphOrEmoji> glyph_run;
+    NonnullRefPtr<Gfx::GlyphRun> glyph_run;
+    double glyph_run_scale { 1 };
     Color color;
     int fragment_baseline;
     Gfx::IntPoint draw_location;

+ 9 - 3
Userland/Libraries/LibWeb/Painting/DisplayListPlayerCPU.cpp

@@ -272,12 +272,18 @@ CommandResult DisplayListPlayerCPU::paint_text_shadow(PaintTextShadow const& com
     // FIXME: "Spread" the shadow somehow.
     Gfx::IntPoint const baseline_start(command.text_rect.x(), command.text_rect.y() + command.fragment_baseline);
     shadow_painter.translate(baseline_start);
-    for (auto const& glyph_or_emoji : command.glyph_run) {
+    auto const& glyphs = command.glyph_run->glyphs();
+    for (auto const& glyph_or_emoji : glyphs) {
+        auto transformed_glyph = glyph_or_emoji;
+        transformed_glyph.visit([&](auto& glyph) {
+            glyph.position = glyph.position.scaled(command.glyph_run_scale);
+            glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(command.glyph_run_scale));
+        });
         if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
-            auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
+            auto& glyph = transformed_glyph.get<Gfx::DrawGlyph>();
             shadow_painter.draw_glyph(glyph.position, glyph.code_point, *glyph.font, command.color);
         } else {
-            auto const& emoji = glyph_or_emoji.get<Gfx::DrawEmoji>();
+            auto& emoji = transformed_glyph.get<Gfx::DrawEmoji>();
             shadow_painter.draw_emoji(emoji.position.to_type<int>(), *emoji.emoji, *emoji.font);
         }
     }

+ 1 - 1
Userland/Libraries/LibWeb/Painting/DisplayListPlayerGPU.cpp

@@ -192,7 +192,7 @@ CommandResult DisplayListPlayerGPU::paint_text_shadow(PaintTextShadow const& com
     Gfx::FloatRect const shadow_location { command.draw_location, command.shadow_bounding_rect.size() };
     Gfx::IntPoint const baseline_start(command.text_rect.x(), command.text_rect.y() + command.fragment_baseline);
     text_shadow_painter->translate(baseline_start.to_type<float>());
-    text_shadow_painter->draw_glyph_run(command.glyph_run, command.color);
+    text_shadow_painter->draw_glyph_run(command.glyph_run->glyphs(), command.color);
     if (command.blur_radius == 0) {
         painter().blit_canvas(shadow_location, *text_shadow_canvas);
         return CommandResult::Continue;

+ 3 - 2
Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp

@@ -344,13 +344,14 @@ void DisplayListRecorder::paint_inner_box_shadow_params(PaintBoxShadowParams par
     append(PaintInnerBoxShadow { .box_shadow_params = params });
 }
 
-void DisplayListRecorder::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, int fragment_baseline, Gfx::IntPoint draw_location)
+void DisplayListRecorder::paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Gfx::GlyphRun const& glyph_run, double glyph_run_scale, Color color, int fragment_baseline, Gfx::IntPoint draw_location)
 {
     append(PaintTextShadow {
         .blur_radius = blur_radius,
         .shadow_bounding_rect = bounding_rect,
         .text_rect = text_rect,
-        .glyph_run = Vector<Gfx::DrawGlyphOrEmoji> { glyph_run },
+        .glyph_run = glyph_run,
+        .glyph_run_scale = glyph_run_scale,
         .color = color,
         .fragment_baseline = fragment_baseline,
         .draw_location = state().translation.map(draw_location) });

+ 1 - 1
Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h

@@ -127,7 +127,7 @@ public:
 
     void paint_outer_box_shadow_params(PaintBoxShadowParams params);
     void paint_inner_box_shadow_params(PaintBoxShadowParams params);
-    void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color color, int fragment_baseline, Gfx::IntPoint draw_location);
+    void paint_text_shadow(int blur_radius, Gfx::IntRect bounding_rect, Gfx::IntRect text_rect, Gfx::GlyphRun const&, double glyph_run_scale, Color color, int fragment_baseline, Gfx::IntPoint draw_location);
 
     void fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color color, Gfx::AntiAliasingPainter::CornerRadius top_left_radius, Gfx::AntiAliasingPainter::CornerRadius top_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_right_radius, Gfx::AntiAliasingPainter::CornerRadius bottom_left_radius, Vector<Gfx::Path> const& clip_paths = {});
     void fill_rect_with_rounded_corners(Gfx::IntRect const& a_rect, Color color, int radius, Vector<Gfx::Path> const& clip_paths = {});

+ 1 - 11
Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp

@@ -587,16 +587,6 @@ void paint_text_shadow(PaintContext& context, PaintableFragment const& fragment,
     auto draw_rect = context.enclosing_device_rect(fragment.absolute_rect()).to_type<int>();
     auto fragment_baseline = context.rounded_device_pixels(fragment.baseline()).value();
 
-    Vector<Gfx::DrawGlyphOrEmoji> scaled_glyph_run;
-    scaled_glyph_run.ensure_capacity(fragment.glyph_run().glyphs().size());
-    for (auto glyph : fragment.glyph_run().glyphs()) {
-        glyph.visit([&](auto& glyph) {
-            glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
-            glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
-        });
-        scaled_glyph_run.append(move(glyph));
-    }
-
     // Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
     for (auto& layer : shadow_layers.in_reverse()) {
         int offset_x = context.rounded_device_pixels(layer.offset_x).value();
@@ -620,7 +610,7 @@ void paint_text_shadow(PaintContext& context, PaintableFragment const& fragment,
             draw_rect.y() + offset_y - margin
         };
 
-        context.display_list_recorder().paint_text_shadow(blur_radius, bounding_rect, text_rect, scaled_glyph_run, layer.color, fragment_baseline, draw_location);
+        context.display_list_recorder().paint_text_shadow(blur_radius, bounding_rect, text_rect, fragment.glyph_run(), context.device_pixels_per_css_pixel(), layer.color, fragment_baseline, draw_location);
     }
 }