ladybird/Libraries/LibWeb/CSS/StyleValues/ConicGradientStyleValue.h
Sam Atkins 6a4a60cbd5 LibWeb/CSS: Invalidate color-stop caches when source data changes
We previously only invalidated the cached color-stop data when the
painted area's size changed. However, multiple elements can use the
same gradient and be the same size, but have different parameters that
affect the gradient stop positions, for example if a stop has an em
position. This can also change for the same element over time.

The new cache instead uses these parameters as the cache key. So we
recompute the cache if lengths would resolve differently, or the area's
size is different.

The included test fails without this change.
2025-02-28 13:50:13 +01:00

77 lines
2.8 KiB
C++

/*
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/Angle.h>
#include <LibWeb/CSS/StyleValues/AbstractImageStyleValue.h>
#include <LibWeb/Painting/GradientPainting.h>
namespace Web::CSS {
class ConicGradientStyleValue final : public AbstractImageStyleValue {
public:
static ValueComparingNonnullRefPtr<ConicGradientStyleValue> create(Angle from_angle, ValueComparingNonnullRefPtr<PositionStyleValue> position, Vector<AngularColorStopListElement> color_stop_list, GradientRepeating repeating)
{
VERIFY(!color_stop_list.is_empty());
return adopt_ref(*new (nothrow) ConicGradientStyleValue(from_angle, move(position), move(color_stop_list), repeating));
}
virtual String to_string(SerializationMode) const override;
void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
virtual bool equals(CSSStyleValue const& other) const override;
Vector<AngularColorStopListElement> const& color_stop_list() const
{
return m_properties.color_stop_list;
}
float angle_degrees() const;
bool is_paintable() const override { return true; }
void resolve_for_size(Layout::NodeWithStyleAndBoxModelMetrics const&, CSSPixelSize) const override;
virtual ~ConicGradientStyleValue() override = default;
bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; }
private:
ConicGradientStyleValue(Angle from_angle, ValueComparingNonnullRefPtr<PositionStyleValue> position, Vector<AngularColorStopListElement> color_stop_list, GradientRepeating repeating)
: AbstractImageStyleValue(Type::ConicGradient)
, m_properties { .from_angle = from_angle, .position = move(position), .color_stop_list = move(color_stop_list), .repeating = repeating }
{
}
struct Properties {
// FIXME: Support <color-interpolation-method>
Angle from_angle;
ValueComparingNonnullRefPtr<PositionStyleValue> position;
Vector<AngularColorStopListElement> color_stop_list;
GradientRepeating repeating;
bool operator==(Properties const&) const = default;
} m_properties;
struct ResolvedDataCacheKey {
Length::ResolutionContext length_resolution_context;
CSSPixelSize size;
bool operator==(ResolvedDataCacheKey const&) const = default;
};
mutable Optional<ResolvedDataCacheKey> m_resolved_data_cache_key;
struct ResolvedData {
Painting::ConicGradientData data;
CSSPixelPoint position;
};
mutable Optional<ResolvedData> m_resolved;
};
}