mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 22:17:42 +00:00
LibWeb: Render multiple box-shadows
Because why not? :^)
This commit is contained in:
parent
b51f428165
commit
10c6c77b5c
8 changed files with 107 additions and 65 deletions
|
@ -104,7 +104,7 @@ public:
|
|||
CSS::AlignItems align_items() const { return m_noninherited.align_items; }
|
||||
float opacity() const { return m_noninherited.opacity; }
|
||||
CSS::JustifyContent justify_content() const { return m_noninherited.justify_content; }
|
||||
Optional<BoxShadowData> const& box_shadow() const { return m_noninherited.box_shadow; }
|
||||
Vector<BoxShadowData> const& box_shadow() const { return m_noninherited.box_shadow; }
|
||||
CSS::BoxSizing box_sizing() const { return m_noninherited.box_sizing; }
|
||||
CSS::LengthPercentage const& width() const { return m_noninherited.width; }
|
||||
CSS::LengthPercentage const& min_width() const { return m_noninherited.min_width; }
|
||||
|
@ -201,7 +201,7 @@ protected:
|
|||
CSS::Overflow overflow_x { InitialValues::overflow() };
|
||||
CSS::Overflow overflow_y { InitialValues::overflow() };
|
||||
float opacity { InitialValues::opacity() };
|
||||
Optional<BoxShadowData> box_shadow {};
|
||||
Vector<BoxShadowData> box_shadow {};
|
||||
Vector<CSS::Transformation> transformations {};
|
||||
CSS::BoxSizing box_sizing { InitialValues::box_sizing() };
|
||||
} m_noninherited;
|
||||
|
@ -255,7 +255,7 @@ public:
|
|||
void set_align_items(CSS::AlignItems value) { m_noninherited.align_items = value; }
|
||||
void set_opacity(float value) { m_noninherited.opacity = value; }
|
||||
void set_justify_content(CSS::JustifyContent value) { m_noninherited.justify_content = value; }
|
||||
void set_box_shadow(Optional<BoxShadowData> value) { m_noninherited.box_shadow = move(value); }
|
||||
void set_box_shadow(Vector<BoxShadowData>&& value) { m_noninherited.box_shadow = move(value); }
|
||||
void set_transformations(Vector<CSS::Transformation> value) { m_noninherited.transformations = move(value); }
|
||||
void set_box_sizing(CSS::BoxSizing value) { m_noninherited.box_sizing = value; }
|
||||
|
||||
|
|
|
@ -518,12 +518,23 @@ RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout:
|
|||
case CSS::PropertyID::JustifyContent:
|
||||
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().justify_content()));
|
||||
case CSS::PropertyID::BoxShadow: {
|
||||
auto maybe_box_shadow = layout_node.computed_values().box_shadow();
|
||||
if (!maybe_box_shadow.has_value())
|
||||
auto box_shadow_layers = layout_node.computed_values().box_shadow();
|
||||
if (box_shadow_layers.is_empty())
|
||||
return {};
|
||||
auto box_shadow_data = maybe_box_shadow.release_value();
|
||||
|
||||
auto make_box_shadow_style_value = [](BoxShadowData const& data) {
|
||||
// FIXME: Add extra properties to BoxShadowData so we can include them here!
|
||||
return BoxShadowStyleValue::create(box_shadow_data.color, box_shadow_data.offset_x, box_shadow_data.offset_y, box_shadow_data.blur_radius, Length::make_px(0), BoxShadowPlacement::Outer);
|
||||
return BoxShadowStyleValue::create(data.color, data.offset_x, data.offset_y, data.blur_radius, Length::make_px(0), BoxShadowPlacement::Outer);
|
||||
};
|
||||
|
||||
if (box_shadow_layers.size() == 1)
|
||||
return make_box_shadow_style_value(box_shadow_layers.first());
|
||||
|
||||
NonnullRefPtrVector<StyleValue> box_shadow;
|
||||
box_shadow.ensure_capacity(box_shadow_layers.size());
|
||||
for (auto const& layer : box_shadow_layers)
|
||||
box_shadow.append(make_box_shadow_style_value(layer));
|
||||
return StyleValueList::create(move(box_shadow), StyleValueList::Separator::Comma);
|
||||
}
|
||||
case CSS::PropertyID::Width:
|
||||
return style_value_for_length_percentage(layout_node.computed_values().width());
|
||||
|
|
|
@ -769,18 +769,35 @@ Optional<CSS::Overflow> StyleProperties::overflow(CSS::PropertyID property_id) c
|
|||
}
|
||||
}
|
||||
|
||||
Optional<CSS::BoxShadowData> StyleProperties::box_shadow() const
|
||||
Vector<BoxShadowData> StyleProperties::box_shadow() const
|
||||
{
|
||||
auto value_or_error = property(CSS::PropertyID::BoxShadow);
|
||||
auto value_or_error = property(PropertyID::BoxShadow);
|
||||
if (!value_or_error.has_value())
|
||||
return {};
|
||||
|
||||
auto value = value_or_error.value();
|
||||
if (!value->is_box_shadow())
|
||||
return {};
|
||||
|
||||
auto make_box_shadow_data = [](BoxShadowStyleValue const& box) {
|
||||
return BoxShadowData { box.offset_x(), box.offset_y(), box.blur_radius(), box.color() };
|
||||
};
|
||||
|
||||
if (value->is_value_list()) {
|
||||
auto& value_list = value->as_value_list();
|
||||
|
||||
Vector<BoxShadowData> box_shadow_data;
|
||||
box_shadow_data.ensure_capacity(value_list.size());
|
||||
for (auto const& layer_value : value_list.values())
|
||||
box_shadow_data.append(make_box_shadow_data(layer_value.as_box_shadow()));
|
||||
|
||||
return box_shadow_data;
|
||||
}
|
||||
|
||||
if (value->is_box_shadow()) {
|
||||
auto& box = value->as_box_shadow();
|
||||
return { { box.offset_x(), box.offset_y(), box.blur_radius(), box.color() } };
|
||||
return { make_box_shadow_data(box) };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
CSS::BoxSizing StyleProperties::box_sizing() const
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
Optional<CSS::JustifyContent> justify_content() const;
|
||||
Optional<CSS::Overflow> overflow_x() const;
|
||||
Optional<CSS::Overflow> overflow_y() const;
|
||||
Optional<CSS::BoxShadowData> box_shadow() const;
|
||||
Vector<CSS::BoxShadowData> box_shadow() const;
|
||||
CSS::BoxSizing box_sizing() const;
|
||||
Optional<CSS::PointerEvents> pointer_events() const;
|
||||
|
||||
|
|
|
@ -99,15 +99,18 @@ void Box::paint_background(PaintContext& context)
|
|||
void Box::paint_box_shadow(PaintContext& context)
|
||||
{
|
||||
auto box_shadow_data = computed_values().box_shadow();
|
||||
if (!box_shadow_data.has_value())
|
||||
if (box_shadow_data.is_empty())
|
||||
return;
|
||||
|
||||
auto resolved_box_shadow_data = Painting::BoxShadowData {
|
||||
.offset_x = (int)box_shadow_data->offset_x.resolved_or_zero(*this).to_px(*this),
|
||||
.offset_y = (int)box_shadow_data->offset_y.resolved_or_zero(*this).to_px(*this),
|
||||
.blur_radius = (int)box_shadow_data->blur_radius.resolved_or_zero(*this).to_px(*this),
|
||||
.color = box_shadow_data->color
|
||||
};
|
||||
Vector<Painting::BoxShadowData> resolved_box_shadow_data;
|
||||
resolved_box_shadow_data.ensure_capacity(box_shadow_data.size());
|
||||
for (auto const& layer : box_shadow_data) {
|
||||
resolved_box_shadow_data.empend(
|
||||
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);
|
||||
}
|
||||
Painting::paint_box_shadow(context, enclosing_int_rect(bordered_rect()), resolved_box_shadow_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,14 +43,17 @@ void InlineNode::paint(PaintContext& context, PaintPhase phase)
|
|||
auto border_radius_data = Painting::normalized_border_radius_data(*this, absolute_fragment_rect, top_left_border_radius, top_right_border_radius, bottom_right_border_radius, bottom_left_border_radius);
|
||||
Painting::paint_background(context, *this, enclosing_int_rect(absolute_fragment_rect), computed_values().background_color(), &computed_values().background_layers(), border_radius_data);
|
||||
|
||||
if (auto computed_box_shadow = computed_values().box_shadow(); computed_box_shadow.has_value()) {
|
||||
auto box_shadow_data = Painting::BoxShadowData {
|
||||
.offset_x = (int)computed_box_shadow->offset_x.resolved_or_zero(*this).to_px(*this),
|
||||
.offset_y = (int)computed_box_shadow->offset_y.resolved_or_zero(*this).to_px(*this),
|
||||
.blur_radius = (int)computed_box_shadow->blur_radius.resolved_or_zero(*this).to_px(*this),
|
||||
.color = computed_box_shadow->color
|
||||
};
|
||||
Painting::paint_box_shadow(context, enclosing_int_rect(absolute_fragment_rect), box_shadow_data);
|
||||
if (auto computed_box_shadow = computed_values().box_shadow(); !computed_box_shadow.is_empty()) {
|
||||
Vector<Painting::BoxShadowData> resolved_box_shadow_data;
|
||||
resolved_box_shadow_data.ensure_capacity(computed_box_shadow.size());
|
||||
for (auto const& layer : computed_box_shadow) {
|
||||
resolved_box_shadow_data.empend(
|
||||
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);
|
||||
}
|
||||
Painting::paint_box_shadow(context, enclosing_int_rect(absolute_fragment_rect), resolved_box_shadow_data);
|
||||
}
|
||||
|
||||
return IterationDecision::Continue;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -13,8 +13,15 @@
|
|||
|
||||
namespace Web::Painting {
|
||||
|
||||
void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, BoxShadowData const& box_shadow_data)
|
||||
void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, Vector<BoxShadowData> const& box_shadow_layers)
|
||||
{
|
||||
if (box_shadow_layers.is_empty())
|
||||
return;
|
||||
|
||||
// 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];
|
||||
|
||||
Gfx::IntRect bitmap_rect = {
|
||||
0,
|
||||
0,
|
||||
|
@ -50,5 +57,6 @@ void paint_box_shadow(PaintContext& context, Gfx::IntRect const& content_rect, B
|
|||
for (auto& rect : shattered.rects())
|
||||
context.painter().blit(rect.location() + blur_rect_position, *new_bitmap, rect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -18,6 +18,6 @@ struct BoxShadowData {
|
|||
Gfx::Color color;
|
||||
};
|
||||
|
||||
void paint_box_shadow(PaintContext&, Gfx::IntRect const&, BoxShadowData const&);
|
||||
void paint_box_shadow(PaintContext&, Gfx::IntRect const&, Vector<BoxShadowData> const&);
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue