1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-22 19:45:08 +00:00

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.
This commit is contained in:
Sam Atkins 2022-02-08 15:33:27 +00:00 committed by Andreas Kling
parent 10c6c77b5c
commit 103613a3a9
7 changed files with 27 additions and 12 deletions

View file

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

View file

@ -523,8 +523,7 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
return {};
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)

View file

@ -778,7 +778,7 @@ Vector<BoxShadowData> StyleProperties::box_shadow() const
auto value = value_or_error.value();
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()) {

View file

@ -106,10 +106,12 @@ void Box::paint_box_shadow(PaintContext& context)
resolved_box_shadow_data.ensure_capacity(box_shadow_data.size());
for (auto const& layer : box_shadow_data) {
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_y.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);
}

View file

@ -48,10 +48,12 @@ void InlineNode::paint(PaintContext& context, PaintPhase phase)
resolved_box_shadow_data.ensure_capacity(computed_box_shadow.size());
for (auto const& layer : computed_box_shadow) {
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_y.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);
}

View file

@ -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
for (int layer_index = box_shadow_layers.size() - 1; layer_index >= 0; 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 = {
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 = {
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())
@ -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();
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);
filter.apply_three_passes(box_shadow_data.blur_radius);

View file

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