Bladeren bron

LibWeb: Resolve text shadows in `LayoutState::commit()`

Rather than resolving the text-shadow each time painting commands are
recorded, we can resolve it once during the layout commit and save the
resolved values in paintable fragments. This is also step towards
getting rid of layout node pointer in paintable fragment.
Aliaksandr Kalenik 1 jaar geleden
bovenliggende
commit
ee5d66c5d5

+ 24 - 0
Userland/Libraries/LibWeb/Layout/LayoutState.cpp

@@ -357,6 +357,29 @@ void LayoutState::resolve_box_shadow_data()
     }
     }
 }
 }
 
 
+void LayoutState::resolve_text_shadows(Vector<Painting::PaintableWithLines&> const& paintables_with_lines)
+{
+    for (auto const& paintable_with_lines : paintables_with_lines) {
+        for (auto const& fragment : paintable_with_lines.fragments()) {
+            auto const& text_shadow = fragment.m_layout_node->computed_values().text_shadow();
+            if (!text_shadow.is_empty()) {
+                Vector<Painting::ShadowData> resolved_shadow_data;
+                resolved_shadow_data.ensure_capacity(text_shadow.size());
+                for (auto const& layer : text_shadow) {
+                    resolved_shadow_data.empend(
+                        layer.color,
+                        layer.offset_x.to_px(paintable_with_lines.layout_node()),
+                        layer.offset_y.to_px(paintable_with_lines.layout_node()),
+                        layer.blur_radius.to_px(paintable_with_lines.layout_node()),
+                        layer.spread_distance.to_px(paintable_with_lines.layout_node()),
+                        Painting::ShadowPlacement::Outer);
+                }
+                const_cast<Painting::PaintableFragment&>(fragment).set_shadows(move(resolved_shadow_data));
+            }
+        }
+    }
+}
+
 void LayoutState::commit(Box& root)
 void LayoutState::commit(Box& root)
 {
 {
     // Only the top-level LayoutState should ever be committed.
     // Only the top-level LayoutState should ever be committed.
@@ -452,6 +475,7 @@ void LayoutState::commit(Box& root)
 
 
     resolve_border_radii();
     resolve_border_radii();
     resolve_box_shadow_data();
     resolve_box_shadow_data();
+    resolve_text_shadows(paintables_with_lines);
 
 
     for (auto& it : used_values_per_layout_node) {
     for (auto& it : used_values_per_layout_node) {
         auto& used_values = *it.value;
         auto& used_values = *it.value;

+ 1 - 0
Userland/Libraries/LibWeb/Layout/LayoutState.h

@@ -188,6 +188,7 @@ private:
     void resolve_relative_positions(Vector<Painting::PaintableWithLines&> const&);
     void resolve_relative_positions(Vector<Painting::PaintableWithLines&> const&);
     void resolve_border_radii();
     void resolve_border_radii();
     void resolve_box_shadow_data();
     void resolve_box_shadow_data();
+    void resolve_text_shadows(Vector<Painting::PaintableWithLines&> const& paintables_with_lines);
 };
 };
 
 
 }
 }

+ 1 - 18
Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

@@ -662,24 +662,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
         for (auto& fragment : fragments()) {
         for (auto& fragment : fragments()) {
             if (fragment.contained_by_inline_node())
             if (fragment.contained_by_inline_node())
                 continue;
                 continue;
-            if (is<Layout::TextNode>(fragment.layout_node())) {
-                auto& text_shadow = fragment.layout_node().computed_values().text_shadow();
-                if (!text_shadow.is_empty()) {
-                    Vector<ShadowData> resolved_shadow_data;
-                    resolved_shadow_data.ensure_capacity(text_shadow.size());
-                    for (auto const& layer : text_shadow) {
-                        resolved_shadow_data.empend(
-                            layer.color,
-                            layer.offset_x.to_px(layout_box()),
-                            layer.offset_y.to_px(layout_box()),
-                            layer.blur_radius.to_px(layout_box()),
-                            layer.spread_distance.to_px(layout_box()),
-                            ShadowPlacement::Outer);
-                    }
-                    context.recording_painter().set_font(fragment.layout_node().first_available_font());
-                    paint_text_shadow(context, fragment, resolved_shadow_data);
-                }
-            }
+            paint_text_shadow(context, fragment, fragment.shadows());
         }
         }
     }
     }
 
 

+ 6 - 0
Userland/Libraries/LibWeb/Painting/PaintableFragment.h

@@ -14,6 +14,8 @@
 namespace Web::Painting {
 namespace Web::Painting {
 
 
 class PaintableFragment {
 class PaintableFragment {
+    friend struct Layout::LayoutState;
+
 public:
 public:
     explicit PaintableFragment(Layout::LineBoxFragment const&);
     explicit PaintableFragment(Layout::LineBoxFragment const&);
 
 
@@ -30,6 +32,9 @@ public:
     BorderRadiiData const& border_radii_data() const { return m_border_radii_data; }
     BorderRadiiData const& border_radii_data() const { return m_border_radii_data; }
     void set_border_radii_data(BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; }
     void set_border_radii_data(BorderRadiiData const& border_radii_data) { m_border_radii_data = border_radii_data; }
 
 
+    Vector<ShadowData> const& shadows() const { return m_shadows; }
+    void set_shadows(Vector<ShadowData>&& shadows) { m_shadows = shadows; }
+
     CSSPixelRect const absolute_rect() const;
     CSSPixelRect const absolute_rect() const;
 
 
     Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run() const { return m_glyph_run; }
     Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run() const { return m_glyph_run; }
@@ -53,6 +58,7 @@ private:
     int m_length;
     int m_length;
     Painting::BorderRadiiData m_border_radii_data;
     Painting::BorderRadiiData m_border_radii_data;
     Vector<Gfx::DrawGlyphOrEmoji> m_glyph_run;
     Vector<Gfx::DrawGlyphOrEmoji> m_glyph_run;
+    Vector<ShadowData> m_shadows;
     bool m_contained_by_inline_node { false };
     bool m_contained_by_inline_node { false };
 };
 };