LibWeb/CSS: Use CSS::URL for <url> and <paint> types

This commit is contained in:
Sam Atkins 2025-04-29 15:32:46 +01:00
commit 326933cd93
Notes: github-actions[bot] 2025-04-30 16:39:41 +00:00
7 changed files with 40 additions and 26 deletions

View file

@ -32,6 +32,7 @@
#include <LibWeb/CSS/StyleValues/CursorStyleValue.h> #include <LibWeb/CSS/StyleValues/CursorStyleValue.h>
#include <LibWeb/CSS/StyleValues/ShadowStyleValue.h> #include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
#include <LibWeb/CSS/Transformation.h> #include <LibWeb/CSS/Transformation.h>
#include <LibWeb/CSS/URL.h>
namespace Web::CSS { namespace Web::CSS {
@ -225,40 +226,40 @@ public:
: m_value(color) : m_value(color)
{ {
} }
SVGPaint(::URL::URL const& url) SVGPaint(URL const& url)
: m_value(url) : m_value(url)
{ {
} }
bool is_color() const { return m_value.has<Color>(); } bool is_color() const { return m_value.has<Color>(); }
bool is_url() const { return m_value.has<::URL::URL>(); } bool is_url() const { return m_value.has<URL>(); }
Color as_color() const { return m_value.get<Color>(); } Color as_color() const { return m_value.get<Color>(); }
::URL::URL const& as_url() const { return m_value.get<::URL::URL>(); } URL const& as_url() const { return m_value.get<URL>(); }
private: private:
Variant<::URL::URL, Color> m_value; Variant<URL, Color> m_value;
}; };
// https://drafts.fxtf.org/css-masking-1/#typedef-mask-reference // https://drafts.fxtf.org/css-masking-1/#typedef-mask-reference
class MaskReference { class MaskReference {
public: public:
// TODO: Support other mask types. // TODO: Support other mask types.
MaskReference(::URL::URL const& url) MaskReference(URL const& url)
: m_url(url) : m_url(url)
{ {
} }
::URL::URL const& url() const { return m_url; } URL const& url() const { return m_url; }
private: private:
::URL::URL m_url; URL m_url;
}; };
// https://drafts.fxtf.org/css-masking/#the-clip-path // https://drafts.fxtf.org/css-masking/#the-clip-path
// TODO: Support clip sources. // TODO: Support clip sources.
class ClipPathReference { class ClipPathReference {
public: public:
ClipPathReference(::URL::URL const& url) ClipPathReference(URL const& url)
: m_clip_source(url) : m_clip_source(url)
{ {
} }
@ -270,16 +271,16 @@ public:
bool is_basic_shape() const { return m_clip_source.has<BasicShape>(); } bool is_basic_shape() const { return m_clip_source.has<BasicShape>(); }
bool is_url() const { return m_clip_source.has<::URL::URL>(); } bool is_url() const { return m_clip_source.has<URL>(); }
::URL::URL const& url() const { return m_clip_source.get<::URL::URL>(); } URL const& url() const { return m_clip_source.get<URL>(); }
BasicShapeStyleValue const& basic_shape() const { return *m_clip_source.get<BasicShape>(); } BasicShapeStyleValue const& basic_shape() const { return *m_clip_source.get<BasicShape>(); }
private: private:
using BasicShape = NonnullRefPtr<BasicShapeStyleValue const>; using BasicShape = NonnullRefPtr<BasicShapeStyleValue const>;
Variant<::URL::URL, BasicShape> m_clip_source; Variant<URL, BasicShape> m_clip_source;
}; };
struct BackgroundLayerData { struct BackgroundLayerData {

View file

@ -282,7 +282,7 @@ private:
Optional<ExplicitGridTrack> parse_track_sizing_function(ComponentValue const&); Optional<ExplicitGridTrack> parse_track_sizing_function(ComponentValue const&);
Optional<URL> parse_url_function(TokenStream<ComponentValue>&); Optional<URL> parse_url_function(TokenStream<ComponentValue>&);
RefPtr<CSSStyleValue const> parse_url_value(TokenStream<ComponentValue>&); RefPtr<URLStyleValue const> parse_url_value(TokenStream<ComponentValue>&);
Optional<ShapeRadius> parse_shape_radius(TokenStream<ComponentValue>&); Optional<ShapeRadius> parse_shape_radius(TokenStream<ComponentValue>&);
RefPtr<CSSStyleValue const> parse_basic_shape_value(TokenStream<ComponentValue>&); RefPtr<CSSStyleValue const> parse_basic_shape_value(TokenStream<ComponentValue>&);

View file

@ -55,6 +55,7 @@
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h> #include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h> #include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
#include <LibWeb/CSS/StyleValues/TransitionStyleValue.h> #include <LibWeb/CSS/StyleValues/TransitionStyleValue.h>
#include <LibWeb/CSS/StyleValues/URLStyleValue.h>
#include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h> #include <LibWeb/CSS/StyleValues/UnresolvedStyleValue.h>
#include <LibWeb/Dump.h> #include <LibWeb/Dump.h>
#include <LibWeb/Infra/Strings.h> #include <LibWeb/Infra/Strings.h>

View file

@ -2725,16 +2725,12 @@ Optional<URL> Parser::parse_url_function(TokenStream<ComponentValue>& tokens)
return {}; return {};
} }
RefPtr<CSSStyleValue const> Parser::parse_url_value(TokenStream<ComponentValue>& tokens) RefPtr<URLStyleValue const> Parser::parse_url_value(TokenStream<ComponentValue>& tokens)
{ {
auto url = parse_url_function(tokens); auto url = parse_url_function(tokens);
if (!url.has_value()) if (!url.has_value())
return nullptr; return nullptr;
// FIXME: Stop completing the URL here return URLStyleValue::create(url.release_value());
auto completed_url = complete_url(url->url());
if (!completed_url.has_value())
return nullptr;
return URLStyleValue::create(completed_url.release_value());
} }
// https://www.w3.org/TR/css-shapes-1/#typedef-shape-radius // https://www.w3.org/TR/css-shapes-1/#typedef-shape-radius

View file

@ -1,43 +1,43 @@
/* /*
* Copyright (c) 2023, MacDue <macdue@dueutil.tech> * Copyright (c) 2023, MacDue <macdue@dueutil.tech>
* Copyright (c) 2025, Sam Atkins <sam@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#pragma once #pragma once
#include <LibURL/URL.h>
#include <LibWeb/CSS/CSSStyleValue.h> #include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/Serialize.h> #include <LibWeb/CSS/URL.h>
namespace Web::CSS { namespace Web::CSS {
class URLStyleValue final : public StyleValueWithDefaultOperators<URLStyleValue> { class URLStyleValue final : public StyleValueWithDefaultOperators<URLStyleValue> {
public: public:
static ValueComparingNonnullRefPtr<URLStyleValue const> create(::URL::URL const& url) static ValueComparingNonnullRefPtr<URLStyleValue const> create(URL const& url)
{ {
return adopt_ref(*new (nothrow) URLStyleValue(url)); return adopt_ref(*new (nothrow) URLStyleValue(url));
} }
virtual ~URLStyleValue() override = default; virtual ~URLStyleValue() override = default;
::URL::URL const& url() const { return m_url; } URL const& url() const { return m_url; }
bool properties_equal(URLStyleValue const& other) const { return m_url == other.m_url; } bool properties_equal(URLStyleValue const& other) const { return m_url == other.m_url; }
virtual String to_string(SerializationMode) const override virtual String to_string(SerializationMode) const override
{ {
return serialize_a_url(m_url.to_string()); return m_url.to_string();
} }
private: private:
URLStyleValue(::URL::URL const& url) URLStyleValue(URL const& url)
: StyleValueWithDefaultOperators(Type::URL) : StyleValueWithDefaultOperators(Type::URL)
, m_url(url) , m_url(url)
{ {
} }
::URL::URL m_url; URL m_url;
}; };
} }

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org> * Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org> * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org> * Copyright (c) 2025, Jelle Raaijmakers <jelle@ladybird.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause

View file

@ -8,6 +8,7 @@
#pragma once #pragma once
#include <LibGfx/PaintStyle.h> #include <LibGfx/PaintStyle.h>
#include <LibWeb/CSS/URL.h>
#include <LibWeb/DOM/Node.h> #include <LibWeb/DOM/Node.h>
#include <LibWeb/SVG/AttributeParser.h> #include <LibWeb/SVG/AttributeParser.h>
#include <LibWeb/SVG/SVGAnimatedTransformList.h> #include <LibWeb/SVG/SVGAnimatedTransformList.h>
@ -91,6 +92,21 @@ protected:
return {}; return {};
} }
template<typename T>
GC::Ptr<T> try_resolve_url_to(CSS::URL const& url) const
{
// FIXME: Complete and use the entire URL, not just the fragment.
Optional<FlyString> fragment;
if (auto fragment_offset = url.url().find_byte_offset('#'); fragment_offset.has_value()) {
fragment = MUST(url.url().substring_from_byte_offset_with_shared_superstring(fragment_offset.value() + 1));
}
if (!fragment.has_value())
return {};
if (auto node = document().get_element_by_id(*fragment); node && is<T>(*node))
return static_cast<T&>(*node);
return {};
}
private: private:
virtual bool is_svg_graphics_element() const final { return true; } virtual bool is_svg_graphics_element() const final { return true; }
float resolve_relative_to_viewport_size(CSS::LengthPercentage const& length_percentage) const; float resolve_relative_to_viewport_size(CSS::LengthPercentage const& length_percentage) const;