浏览代码

LibWeb: Incorporate spread-distance into box-shadow rendering

We also pass whether the shadow goes inside or outside the element. Only
outer shadows are rendered currently, and inner ones may want to be
handled separately from them, as they will never interfere with each
other.
Sam Atkins 3 年之前
父节点
当前提交
103613a3a9

+ 3 - 1
Userland/Libraries/LibWeb/CSS/ComputedValues.h

@@ -76,10 +76,12 @@ struct FlexBasisData {
 };
 };
 
 
 struct BoxShadowData {
 struct BoxShadowData {
+    Color color {};
     CSS::Length offset_x {};
     CSS::Length offset_x {};
     CSS::Length offset_y {};
     CSS::Length offset_y {};
     CSS::Length blur_radius {};
     CSS::Length blur_radius {};
-    Color color {};
+    CSS::Length spread_distance {};
+    CSS::BoxShadowPlacement placement { CSS::BoxShadowPlacement::Outer };
 };
 };
 
 
 class ComputedValues {
 class ComputedValues {

+ 1 - 2
Userland/Libraries/LibWeb/CSS/ResolvedCSSStyleDeclaration.cpp

@@ -523,8 +523,7 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
             return {};
             return {};
 
 
         auto make_box_shadow_style_value = [](BoxShadowData const& data) {
         auto make_box_shadow_style_value = [](BoxShadowData const& data) {
-            // FIXME: Add extra properties to BoxShadowData so we can include them here!
-            return BoxShadowStyleValue::create(data.color, data.offset_x, data.offset_y, data.blur_radius, Length::make_px(0), BoxShadowPlacement::Outer);
+            return BoxShadowStyleValue::create(data.color, data.offset_x, data.offset_y, data.blur_radius, data.spread_distance, data.placement);
         };
         };
 
 
         if (box_shadow_layers.size() == 1)
         if (box_shadow_layers.size() == 1)

+ 1 - 1
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -778,7 +778,7 @@ Vector<BoxShadowData> StyleProperties::box_shadow() const
     auto value = value_or_error.value();
     auto value = value_or_error.value();
 
 
     auto make_box_shadow_data = [](BoxShadowStyleValue const& box) {
     auto make_box_shadow_data = [](BoxShadowStyleValue const& box) {
-        return BoxShadowData { box.offset_x(), box.offset_y(), box.blur_radius(), box.color() };
+        return BoxShadowData { box.color(), box.offset_x(), box.offset_y(), box.blur_radius(), box.spread_distance(), box.placement() };
     };
     };
 
 
     if (value->is_value_list()) {
     if (value->is_value_list()) {

+ 3 - 1
Userland/Libraries/LibWeb/Layout/Box.cpp

@@ -106,10 +106,12 @@ void Box::paint_box_shadow(PaintContext& context)
     resolved_box_shadow_data.ensure_capacity(box_shadow_data.size());
     resolved_box_shadow_data.ensure_capacity(box_shadow_data.size());
     for (auto const& layer : box_shadow_data) {
     for (auto const& layer : box_shadow_data) {
         resolved_box_shadow_data.empend(
         resolved_box_shadow_data.empend(
+            layer.color,
             static_cast<int>(layer.offset_x.resolved_or_zero(*this).to_px(*this)),
             static_cast<int>(layer.offset_x.resolved_or_zero(*this).to_px(*this)),
             static_cast<int>(layer.offset_y.resolved_or_zero(*this).to_px(*this)),
             static_cast<int>(layer.offset_y.resolved_or_zero(*this).to_px(*this)),
             static_cast<int>(layer.blur_radius.resolved_or_zero(*this).to_px(*this)),
             static_cast<int>(layer.blur_radius.resolved_or_zero(*this).to_px(*this)),
-            layer.color);
+            static_cast<int>(layer.spread_distance.resolved_or_zero(*this).to_px(*this)),
+            layer.placement == CSS::BoxShadowPlacement::Outer ? Painting::BoxShadowPlacement::Outer : Painting::BoxShadowPlacement::Inner);
     }
     }
     Painting::paint_box_shadow(context, enclosing_int_rect(bordered_rect()), resolved_box_shadow_data);
     Painting::paint_box_shadow(context, enclosing_int_rect(bordered_rect()), resolved_box_shadow_data);
 }
 }

+ 3 - 1
Userland/Libraries/LibWeb/Layout/InlineNode.cpp

@@ -48,10 +48,12 @@ void InlineNode::paint(PaintContext& context, PaintPhase phase)
                 resolved_box_shadow_data.ensure_capacity(computed_box_shadow.size());
                 resolved_box_shadow_data.ensure_capacity(computed_box_shadow.size());
                 for (auto const& layer : computed_box_shadow) {
                 for (auto const& layer : computed_box_shadow) {
                     resolved_box_shadow_data.empend(
                     resolved_box_shadow_data.empend(
+                        layer.color,
                         static_cast<int>(layer.offset_x.resolved_or_zero(*this).to_px(*this)),
                         static_cast<int>(layer.offset_x.resolved_or_zero(*this).to_px(*this)),
                         static_cast<int>(layer.offset_y.resolved_or_zero(*this).to_px(*this)),
                         static_cast<int>(layer.offset_y.resolved_or_zero(*this).to_px(*this)),
                         static_cast<int>(layer.blur_radius.resolved_or_zero(*this).to_px(*this)),
                         static_cast<int>(layer.blur_radius.resolved_or_zero(*this).to_px(*this)),
-                        layer.color);
+                        static_cast<int>(layer.spread_distance.resolved_or_zero(*this).to_px(*this)),
+                        layer.placement == CSS::BoxShadowPlacement::Outer ? Painting::BoxShadowPlacement::Outer : Painting::BoxShadowPlacement::Inner);
                 }
                 }
                 Painting::paint_box_shadow(context, enclosing_int_rect(absolute_fragment_rect), resolved_box_shadow_data);
                 Painting::paint_box_shadow(context, enclosing_int_rect(absolute_fragment_rect), resolved_box_shadow_data);
             }
             }

+ 8 - 5
Userland/Libraries/LibWeb/Painting/ShadowPainting.cpp

@@ -21,17 +21,20 @@ void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, V
     // Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
     // Note: Box-shadow layers are ordered front-to-back, so we paint them in reverse
     for (int layer_index = box_shadow_layers.size() - 1; layer_index >= 0; layer_index--) {
     for (int layer_index = box_shadow_layers.size() - 1; layer_index >= 0; layer_index--) {
         auto& box_shadow_data = box_shadow_layers[layer_index];
         auto& box_shadow_data = box_shadow_layers[layer_index];
+        // FIXME: Paint inset shadows.
+        if (box_shadow_data.placement != BoxShadowPlacement::Outer)
+            continue;
 
 
         Gfx::IntRect bitmap_rect = {
         Gfx::IntRect bitmap_rect = {
             0,
             0,
             0,
             0,
-            content_rect.width() + 4 * box_shadow_data.blur_radius,
-            content_rect.height() + 4 * box_shadow_data.blur_radius
+            content_rect.width() + (2 * box_shadow_data.spread_distance) + (4 * box_shadow_data.blur_radius),
+            content_rect.height() + (2 * box_shadow_data.spread_distance) + (4 * box_shadow_data.blur_radius)
         };
         };
 
 
         Gfx::IntPoint blur_rect_position = {
         Gfx::IntPoint blur_rect_position = {
-            content_rect.x() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_x,
-            content_rect.y() - 2 * box_shadow_data.blur_radius + box_shadow_data.offset_y
+            content_rect.x() - box_shadow_data.spread_distance - (2 * box_shadow_data.blur_radius) + box_shadow_data.offset_x,
+            content_rect.y() - box_shadow_data.spread_distance - (2 * box_shadow_data.blur_radius) + box_shadow_data.offset_y
         };
         };
 
 
         if (bitmap_rect.is_empty())
         if (bitmap_rect.is_empty())
@@ -45,7 +48,7 @@ void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, V
         auto new_bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
         auto new_bitmap = bitmap_or_error.release_value_but_fixme_should_propagate_errors();
 
 
         Gfx::Painter painter(*new_bitmap);
         Gfx::Painter painter(*new_bitmap);
-        painter.fill_rect({ { 2 * box_shadow_data.blur_radius, 2 * box_shadow_data.blur_radius }, content_rect.size() }, box_shadow_data.color);
+        painter.fill_rect({ { 2 * box_shadow_data.blur_radius, 2 * box_shadow_data.blur_radius }, { content_rect.width() + (2 * box_shadow_data.spread_distance), content_rect.height() + (2 * box_shadow_data.spread_distance) } }, box_shadow_data.color);
 
 
         Gfx::FastBoxBlurFilter filter(*new_bitmap);
         Gfx::FastBoxBlurFilter filter(*new_bitmap);
         filter.apply_three_passes(box_shadow_data.blur_radius);
         filter.apply_three_passes(box_shadow_data.blur_radius);

+ 8 - 1
Userland/Libraries/LibWeb/Painting/ShadowPainting.h

@@ -11,11 +11,18 @@
 
 
 namespace Web::Painting {
 namespace Web::Painting {
 
 
+enum class BoxShadowPlacement {
+    Outer,
+    Inner,
+};
+
 struct BoxShadowData {
 struct BoxShadowData {
+    Gfx::Color color;
     int offset_x;
     int offset_x;
     int offset_y;
     int offset_y;
     int blur_radius;
     int blur_radius;
-    Gfx::Color color;
+    int spread_distance;
+    BoxShadowPlacement placement;
 };
 };
 
 
 void paint_box_shadow(PaintContext&, Gfx::IntRect const&, Vector<BoxShadowData> const&);
 void paint_box_shadow(PaintContext&, Gfx::IntRect const&, Vector<BoxShadowData> const&);