1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:07:35 +00:00

LibWeb: Implement SVG opacity properties

This implements the stop-opacity, fill-opacity, and stroke-opacity
properties (in CSS). This replaces the existing more ad-hoc
fill-opacity attribute handling.
This commit is contained in:
MacDue 2023-05-19 20:35:39 +01:00 committed by Andreas Kling
parent 120e5b6b6f
commit 00cda96e2d
13 changed files with 141 additions and 29 deletions

View file

@ -62,6 +62,9 @@ public:
static float flex_shrink() { return 1.0f; }
static int order() { return 0; }
static float opacity() { return 1.0f; }
static float fill_opacity() { return 1.0f; }
static float stroke_opacity() { return 1.0f; }
static float stop_opacity() { return 1.0f; }
static CSS::Length border_radius() { return Length::make_px(0); }
static Variant<CSS::VerticalAlign, CSS::LengthPercentage> vertical_align() { return CSS::VerticalAlign::Baseline; }
static CSS::LengthBox inset() { return { CSS::Length::make_auto(), CSS::Length::make_auto(), CSS::Length::make_auto(), CSS::Length::make_auto() }; }
@ -284,8 +287,11 @@ public:
Optional<SVGPaint> const& fill() const { return m_inherited.fill; }
Optional<SVGPaint> const& stroke() const { return m_inherited.stroke; }
float fill_opacity() const { return m_inherited.fill_opacity; }
float stroke_opacity() const { return m_inherited.stroke_opacity; }
Optional<LengthPercentage> const& stroke_width() const { return m_inherited.stroke_width; }
Color stop_color() const { return m_noninherited.stop_color; }
float stop_opacity() const { return m_noninherited.stop_opacity; }
Vector<CSS::Transformation> const& transformations() const { return m_noninherited.transformations; }
CSS::TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; }
@ -321,6 +327,8 @@ protected:
Optional<SVGPaint> fill;
Optional<SVGPaint> stroke;
float fill_opacity { InitialValues::fill_opacity() };
float stroke_opacity { InitialValues::stroke_opacity() };
Optional<LengthPercentage> stroke_width;
} m_inherited;
@ -388,6 +396,7 @@ protected:
CSS::BorderCollapse border_collapse { InitialValues::border_collapse() };
Vector<Vector<String>> grid_template_areas { InitialValues::grid_template_areas() };
Gfx::Color stop_color { InitialValues::stop_color() };
float stop_opacity { InitialValues::stop_opacity() };
} m_noninherited;
};
@ -475,8 +484,11 @@ public:
void set_fill(SVGPaint value) { m_inherited.fill = value; }
void set_stroke(SVGPaint value) { m_inherited.stroke = value; }
void set_fill_opacity(float value) { m_inherited.fill_opacity = value; }
void set_stroke_opacity(float value) { m_inherited.stroke_opacity = value; }
void set_stroke_width(LengthPercentage value) { m_inherited.stroke_width = value; }
void set_stop_color(Color value) { m_noninherited.stop_color = value; }
void set_stop_opacity(float value) { m_noninherited.stop_opacity = value; }
};
}

View file

@ -629,6 +629,15 @@
"none"
]
},
"fill-opacity": {
"affects-layout": false,
"inherited": true,
"initial": "1",
"valid-types": [
"number",
"percentage"
]
},
"flex": {
"inherited": false,
"initial": "0 1 auto",
@ -1406,6 +1415,15 @@
"none"
]
},
"stroke-opacity": {
"affects-layout": false,
"inherited": true,
"initial": "1",
"valid-types": [
"number",
"percentage"
]
},
"stop-color": {
"affects-layout": false,
"inherited": false,
@ -1414,6 +1432,15 @@
"color"
]
},
"stop-opacity": {
"affects-layout": false,
"inherited": false,
"initial": "1",
"valid-types": [
"number",
"percentage"
]
},
"stroke-width": {
"affects-layout": false,
"inherited": true,

View file

@ -236,36 +236,58 @@ Optional<int> StyleProperties::z_index() const
return {};
}
float StyleProperties::opacity() const
static float resolve_opacity_value(CSS::StyleValue const& value)
{
auto value = property(CSS::PropertyID::Opacity);
float unclamped_opacity = 1.0f;
if (value->has_number()) {
unclamped_opacity = value->to_number();
} else if (value->is_calculated()) {
auto& calculated = value->as_calculated();
if (value.has_number()) {
unclamped_opacity = value.to_number();
} else if (value.is_calculated()) {
auto& calculated = value.as_calculated();
if (calculated.resolved_type() == CalculatedStyleValue::ResolvedType::Percentage) {
auto maybe_percentage = value->as_calculated().resolve_percentage();
auto maybe_percentage = value.as_calculated().resolve_percentage();
if (maybe_percentage.has_value())
unclamped_opacity = maybe_percentage->as_fraction();
else
dbgln("Unable to resolve calc() as opacity (percentage): {}", value->to_string());
dbgln("Unable to resolve calc() as opacity (percentage): {}", value.to_string());
} else {
auto maybe_number = const_cast<CalculatedStyleValue&>(value->as_calculated()).resolve_number();
auto maybe_number = const_cast<CalculatedStyleValue&>(value.as_calculated()).resolve_number();
if (maybe_number.has_value())
unclamped_opacity = maybe_number.value();
else
dbgln("Unable to resolve calc() as opacity (number): {}", value->to_string());
dbgln("Unable to resolve calc() as opacity (number): {}", value.to_string());
}
} else if (value->is_percentage()) {
unclamped_opacity = value->as_percentage().percentage().as_fraction();
} else if (value.is_percentage()) {
unclamped_opacity = value.as_percentage().percentage().as_fraction();
}
return clamp(unclamped_opacity, 0.0f, 1.0f);
}
float StyleProperties::opacity() const
{
auto value = property(CSS::PropertyID::Opacity);
return resolve_opacity_value(*value);
}
float StyleProperties::fill_opacity() const
{
auto value = property(CSS::PropertyID::FillOpacity);
return resolve_opacity_value(*value);
}
float StyleProperties::stroke_opacity() const
{
auto value = property(CSS::PropertyID::StrokeOpacity);
return resolve_opacity_value(*value);
}
float StyleProperties::stop_opacity() const
{
auto value = property(CSS::PropertyID::StopOpacity);
return resolve_opacity_value(*value);
}
Optional<CSS::FlexDirection> StyleProperties::flex_direction() const
{
auto value = property(CSS::PropertyID::FlexDirection);

View file

@ -99,6 +99,9 @@ public:
CSS::TransformOrigin transform_origin() const;
Color stop_color() const;
float stop_opacity() const;
float fill_opacity() const;
float stroke_opacity() const;
Gfx::Font const& computed_font() const
{