From 9ab7c5d08de91954f9d93be223079d7ba006d881 Mon Sep 17 00:00:00 2001 From: Callum Law Date: Sun, 29 Jun 2025 17:18:05 +1200 Subject: [PATCH] LibWeb: Support relative lengths in `calc` color values Gains us ~40 WPT tests. --- Libraries/LibWeb/CSS/ComputedProperties.cpp | 17 ++++---- Libraries/LibWeb/CSS/Interpolation.cpp | 17 ++++++-- .../LibWeb/CSS/Parser/PropertyParsing.cpp | 1 + Libraries/LibWeb/DOM/Document.cpp | 7 ++- .../LibWeb/Editing/Internal/Algorithms.cpp | 3 +- .../HTML/Canvas/CanvasFillStrokeStyles.h | 34 ++++++++++++++- .../LibWeb/HTML/CanvasRenderingContext2D.cpp | 11 ++++- Libraries/LibWeb/Layout/Node.cpp | 15 ++++--- Libraries/LibWeb/Painting/BorderPainting.cpp | 1 + .../LibWeb/Painting/GradientPainting.cpp | 2 +- .../animations/box-shadow-interpolation.txt | 20 ++++----- .../css-color/parsing/color-computed-hsl.txt | 28 ++++++------ .../css-color/parsing/color-computed-hwb.txt | 10 ++--- .../css-color/parsing/color-computed-rgb.txt | 40 +++++++++--------- ...2d.fillStyle.parse.current.notrendered.txt | 6 +++ ...d.fillStyle.parse.current.notrendered.html | 31 ++++++++++++++ .../input/wpt-import/images/green-100x50.png | Bin 0 -> 205 bytes 17 files changed, 169 insertions(+), 74 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/images/green-100x50.png diff --git a/Libraries/LibWeb/CSS/ComputedProperties.cpp b/Libraries/LibWeb/CSS/ComputedProperties.cpp index cd0710c4835..35975404fb6 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.cpp +++ b/Libraries/LibWeb/CSS/ComputedProperties.cpp @@ -226,7 +226,7 @@ Color ComputedProperties::color_or_fallback(PropertyID id, Layout::NodeWithStyle auto const& value = property(id); if (!value.has_color()) return fallback; - return value.to_color(node, {}); + return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) }); } // https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme @@ -670,7 +670,7 @@ Optional ComputedProperties::accent_color(Layout::NodeWithStyle const& no { auto const& value = property(PropertyID::AccentColor); if (value.has_color()) - return value.to_color(node, {}); + return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) }); return {}; } @@ -924,7 +924,7 @@ Color ComputedProperties::caret_color(Layout::NodeWithStyle const& node) const return node.computed_values().color(); if (value.has_color()) - return value.to_color(node, {}); + return value.to_color(node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(node) }); return InitialValues::caret_color(); } @@ -1187,7 +1187,7 @@ Vector ComputedProperties::shadow(PropertyID property_id, Layout::No maybe_offset_y.release_value(), maybe_blur_radius.release_value(), maybe_spread_distance.release_value(), - value.color()->to_color(as(layout_node), {}), + value.color()->to_color(as(layout_node), { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }), value.placement() }; }; @@ -1807,8 +1807,9 @@ Color ComputedProperties::stop_color() const value = property(PropertyID::Color); } if (value->has_color()) { - // FIXME: This is used by the SVGStopElement, which does not participate in layout, - // so can't pass a layout node (so can't resolve some colors, e.g. palette ones) + // FIXME: This is used by the SVGStopElement, which does not participate in layout, so we can't pass a layout + // node or CalculationResolutionContext. This means we don't support all valid colors (e.g. palette + // colors, calculated values which depend on length resolution, etc) return value->to_color({}, {}); } return Color::Black; @@ -1893,8 +1894,8 @@ ScrollbarColorData ComputedProperties::scrollbar_color(Layout::NodeWithStyle con if (value.is_scrollbar_color()) { auto& scrollbar_color_value = value.as_scrollbar_color(); - auto thumb_color = scrollbar_color_value.thumb_color()->to_color(layout_node, {}); - auto track_color = scrollbar_color_value.track_color()->to_color(layout_node, {}); + auto thumb_color = scrollbar_color_value.thumb_color()->to_color(layout_node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }); + auto track_color = scrollbar_color_value.track_color()->to_color(layout_node, { .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }); return { thumb_color, track_color }; } diff --git a/Libraries/LibWeb/CSS/Interpolation.cpp b/Libraries/LibWeb/CSS/Interpolation.cpp index 8c9894a1e19..c1d4bd666a6 100644 --- a/Libraries/LibWeb/CSS/Interpolation.cpp +++ b/Libraries/LibWeb/CSS/Interpolation.cpp @@ -659,6 +659,13 @@ RefPtr interpolate_box_shadow(DOM::Element& element, Calcul StyleValueVector result_shadows; result_shadows.ensure_capacity(from_shadows.size()); + Optional layout_node; + CalculationResolutionContext resolution_context; + if (auto node = element.layout_node()) { + layout_node = *node; + resolution_context.length_resolution_context = Length::ResolutionContext::for_layout_node(*node); + } + for (size_t i = 0; i < from_shadows.size(); i++) { auto const& from_shadow = from_shadows[i]->as_shadow(); auto const& to_shadow = to_shadows[i]->as_shadow(); @@ -669,7 +676,7 @@ RefPtr interpolate_box_shadow(DOM::Element& element, Calcul if (!interpolated_offset_x || !interpolated_offset_y || !interpolated_blur_radius || !interpolated_spread_distance) return {}; auto result_shadow = ShadowStyleValue::create( - CSSColorValue::create_from_color(interpolate_color(from_shadow.color()->to_color({}, {}), to_shadow.color()->to_color({}, {}), delta), ColorSyntax::Modern), + CSSColorValue::create_from_color(interpolate_color(from_shadow.color()->to_color(layout_node, resolution_context), to_shadow.color()->to_color(layout_node, resolution_context), delta), ColorSyntax::Modern), *interpolated_offset_x, *interpolated_offset_y, *interpolated_blur_radius, @@ -781,9 +788,13 @@ static RefPtr interpolate_value_impl(DOM::Element& element, } case CSSStyleValue::Type::Color: { Optional layout_node; - if (auto node = element.layout_node()) + CalculationResolutionContext resolution_context {}; + if (auto node = element.layout_node()) { layout_node = *node; - return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node, {}), to.to_color(layout_node, {}), delta), ColorSyntax::Modern); + resolution_context.length_resolution_context = Length::ResolutionContext::for_layout_node(*node); + } + + return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node, resolution_context), to.to_color(layout_node, resolution_context), delta), ColorSyntax::Modern); } case CSSStyleValue::Type::Edge: { auto resolved_from = from.as_edge().resolved_value(calculation_context); diff --git a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp index e61512c7745..3beb4deee9b 100644 --- a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp @@ -5113,6 +5113,7 @@ RefPtr Parser::parse_filter_value_list_value(TokenStream color = {}; if (maybe_color) + // FIXME: We should support colors which require compute-time information (i.e. `em` and `vw` to `px` ratios). color = maybe_color->to_color({}, {}); return if_no_more_tokens_return(FilterOperation::DropShadow { x_offset.value(), y_offset.value(), maybe_radius, color }); diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index fde6c82accc..508a441552d 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1687,10 +1687,13 @@ void Document::obtain_theme_color() // 4. If color is not failure, then return color. if (!css_value.is_null() && css_value->has_color()) { Optional root_node; - if (html_element() && html_element()->layout_node()) + CSS::CalculationResolutionContext resolution_context; + if (html_element() && html_element()->layout_node()) { root_node = *html_element()->layout_node(); + resolution_context.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*html_element()->layout_node()); + } - theme_color = css_value->to_color(root_node, {}); + theme_color = css_value->to_color(root_node, resolution_context); return TraversalDecision::Break; } } diff --git a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp index d3f7891beac..824eb93f7b1 100644 --- a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp @@ -1174,7 +1174,8 @@ Optional effective_command_value(GC::Ptr node, FlyString cons if (!background_color.has_value()) return NumericLimits::max(); VERIFY(is(node->layout_node())); - return background_color.value()->to_color(*static_cast(node->layout_node()), {}).alpha(); + auto& layout_node = *static_cast(node->layout_node()); + return background_color.value()->to_color(layout_node, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(layout_node) }).alpha(); }; while (resolved_background_alpha() == 0 && node->parent() && is(*node->parent())) node = node->parent(); diff --git a/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.h b/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.h index 214c3a53132..4991abc51f7 100644 --- a/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.h +++ b/Libraries/LibWeb/HTML/Canvas/CanvasFillStrokeStyles.h @@ -14,6 +14,7 @@ #include #include #include +#include namespace Web::HTML { @@ -31,13 +32,27 @@ public: // 1. If the given value is a string, then: [&](String const& string) { // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null. + HTMLCanvasElement* context = my_canvas_element().visit( + [&](HTMLCanvasElement* canvas_element) -> HTMLCanvasElement* { + return canvas_element; + }, + [&](OffscreenCanvas*) -> HTMLCanvasElement* { + return nullptr; + }); // 2. Let parsedValue be the result of parsing the given value with context if non-null. // FIXME: Parse a color value // https://drafts.csswg.org/css-color/#parse-a-css-color-value auto style_value = parse_css_value(CSS::Parser::ParsingParams(), string, CSS::PropertyID::Color); if (style_value && style_value->has_color()) { - auto parsedValue = style_value->to_color(OptionalNone(), {}); + Optional layout_node; + CSS::CalculationResolutionContext resolution_context {}; + if (context && context->layout_node()) { + layout_node = *context->layout_node(); + resolution_context.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*context->layout_node()); + } + + auto parsedValue = style_value->to_color(layout_node, resolution_context); // 4. Set this's fill style to parsedValue. my_drawing_state().fill_style = parsedValue; @@ -70,13 +85,27 @@ public: // 1. If the given value is a string, then: [&](String const& string) { // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null. + HTMLCanvasElement* context = my_canvas_element().visit( + [&](HTMLCanvasElement* canvas_element) -> HTMLCanvasElement* { + return canvas_element; + }, + [&](OffscreenCanvas*) -> HTMLCanvasElement* { + return nullptr; + }); // 2. Let parsedValue be the result of parsing the given value with context if non-null. // FIXME: Parse a color value // https://drafts.csswg.org/css-color/#parse-a-css-color-value auto style_value = parse_css_value(CSS::Parser::ParsingParams(), string, CSS::PropertyID::Color); if (style_value && style_value->has_color()) { - auto parsedValue = style_value->to_color(OptionalNone(), {}); + Optional layout_node; + CSS::CalculationResolutionContext resolution_context {}; + if (context && context->layout_node()) { + layout_node = *context->layout_node(); + resolution_context.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*context->layout_node()); + } + + auto parsedValue = style_value->to_color(layout_node, resolution_context); // 4. Set this's stroke style to parsedValue. my_drawing_state().stroke_style = parsedValue; @@ -129,6 +158,7 @@ protected: CanvasFillStrokeStyles() = default; private: + Variant my_canvas_element() { return &reinterpret_cast(*this).canvas_element(); } CanvasState::DrawingState& my_drawing_state() { return reinterpret_cast(*this).drawing_state(); } CanvasState::DrawingState const& my_drawing_state() const { return reinterpret_cast(*this).drawing_state(); } }; diff --git a/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index d553ee7651e..e1ebfad40d6 100644 --- a/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -937,11 +937,20 @@ String CanvasRenderingContext2D::shadow_color() const void CanvasRenderingContext2D::set_shadow_color(String color) { // 1. Let context be this's canvas attribute's value, if that is an element; otherwise null. + auto& context = canvas_element(); // 2. Let parsedValue be the result of parsing the given value with context if non-null. auto style_value = parse_css_value(CSS::Parser::ParsingParams(), color, CSS::PropertyID::Color); if (style_value && style_value->has_color()) { - auto parsedValue = style_value->to_color(OptionalNone(), {}); + Optional layout_node; + CSS::CalculationResolutionContext resolution_context; + + if (auto node = context.layout_node()) { + layout_node = *node; + resolution_context.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*node); + } + + auto parsedValue = style_value->to_color(layout_node, resolution_context); // 4. Set this's shadow color to parsedValue. drawing_state().shadow_color = parsedValue; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 525dd8d882b..3cb3aece9cf 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -378,9 +378,6 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) } computed_values.set_color_scheme(computed_style.color_scheme(preferred_color_scheme, document().supported_color_schemes())); - // NOTE: color must be set second to ensure currentColor can be resolved in other properties (e.g. background-color). - computed_values.set_color(computed_style.color_or_fallback(CSS::PropertyID::Color, *this, CSS::InitialValues::color())); - // NOTE: We have to be careful that font-related properties get set in the right order. // m_font is used by Length::to_px() when resolving sizes against this layout node. // That's why it has to be set before everything else. @@ -390,6 +387,10 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) computed_values.set_font_kerning(computed_style.font_kerning()); computed_values.set_line_height(computed_style.line_height()); + // NOTE: color must be set after color-scheme to ensure currentColor can be resolved in other properties (e.g. background-color). + // NOTE: color must be set after font_size as `CalculatedStyleValue`s can rely on it being set for resolving lengths. + computed_values.set_color(computed_style.color_or_fallback(CSS::PropertyID::Color, *this, CSS::InitialValues::color())); + computed_values.set_vertical_align(computed_style.vertical_align()); { @@ -796,7 +797,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) do_border_style(computed_values.border_bottom(), CSS::PropertyID::BorderBottomWidth, CSS::PropertyID::BorderBottomColor, CSS::PropertyID::BorderBottomStyle); if (auto const& outline_color = computed_style.property(CSS::PropertyID::OutlineColor); outline_color.has_color()) - computed_values.set_outline_color(outline_color.to_color(*this, {})); + computed_values.set_outline_color(outline_color.to_color(*this, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) })); if (auto const& outline_offset = computed_style.property(CSS::PropertyID::OutlineOffset); outline_offset.is_length()) computed_values.set_outline_offset(outline_offset.as_length().length()); computed_values.set_outline_style(computed_style.outline_style()); @@ -836,16 +837,16 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style) auto const& fill = computed_style.property(CSS::PropertyID::Fill); if (fill.has_color()) - computed_values.set_fill(fill.to_color(*this, {})); + computed_values.set_fill(fill.to_color(*this, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) })); else if (fill.is_url()) computed_values.set_fill(fill.as_url().url()); auto const& stroke = computed_style.property(CSS::PropertyID::Stroke); if (stroke.has_color()) - computed_values.set_stroke(stroke.to_color(*this, {})); + computed_values.set_stroke(stroke.to_color(*this, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) })); else if (stroke.is_url()) computed_values.set_stroke(stroke.as_url().url()); if (auto const& stop_color = computed_style.property(CSS::PropertyID::StopColor); stop_color.has_color()) - computed_values.set_stop_color(stop_color.to_color(*this, {})); + computed_values.set_stop_color(stop_color.to_color(*this, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) })); auto const& stroke_width = computed_style.property(CSS::PropertyID::StrokeWidth); // FIXME: Converting to pixels isn't really correct - values should be in "user units" // https://svgwg.org/svg2-draft/coords.html#TermUserUnits diff --git a/Libraries/LibWeb/Painting/BorderPainting.cpp b/Libraries/LibWeb/Painting/BorderPainting.cpp index 918db75a7ad..087ba2c33a5 100644 --- a/Libraries/LibWeb/Painting/BorderPainting.cpp +++ b/Libraries/LibWeb/Painting/BorderPainting.cpp @@ -586,6 +586,7 @@ Optional borders_data_for_outline(Layout::Node const& layout_node, if (outline_style == CSS::OutlineStyle::Auto) { // `auto` lets us do whatever we want for the outline. 2px of the accent colour seems reasonable. line_style = CSS::LineStyle::Solid; + // NOTE: CalculationResolutionContext is not required here as Accentcolor keyword value is guaranteed to not rely on it to resolve. outline_color = CSS::CSSKeywordValue::create(CSS::Keyword::Accentcolor)->to_color(*static_cast(&layout_node), {}); outline_width = 2; } else { diff --git a/Libraries/LibWeb/Painting/GradientPainting.cpp b/Libraries/LibWeb/Painting/GradientPainting.cpp index d137b3e3141..8e92bb4bf5e 100644 --- a/Libraries/LibWeb/Painting/GradientPainting.cpp +++ b/Libraries/LibWeb/Painting/GradientPainting.cpp @@ -30,7 +30,7 @@ static ColorStopData resolve_color_stop_positions(Layout::NodeWithStyle const& n resolved_color_stops.ensure_capacity(expanded_size); for (auto& stop : color_stop_list) { - auto resolved_stop = Gfx::ColorStop { .color = stop.color_stop.color->to_color(node, {}) }; + auto resolved_stop = Gfx::ColorStop { .color = stop.color_stop.color->to_color(node, { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(node) }) }; for (int i = 0; i < color_stop_length(stop); i++) resolved_color_stops.append(resolved_stop); } diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/box-shadow-interpolation.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/box-shadow-interpolation.txt index 528ef6ce216..6ae0e73092d 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/box-shadow-interpolation.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-backgrounds/animations/box-shadow-interpolation.txt @@ -2,8 +2,8 @@ Harness status: OK Found 402 tests -222 Pass -180 Fail +230 Pass +172 Fail Pass CSS Transitions: property from neutral to [20px 20px 20px 20px black] at (-0.3) should be [rgb(0, 0, 0) 7px 33px 7px 33px] Pass CSS Transitions: property from neutral to [20px 20px 20px 20px black] at (0) should be [rgb(0, 0, 0) 10px 30px 10px 30px] Pass CSS Transitions: property from neutral to [20px 20px 20px 20px black] at (0.3) should be [rgb(0, 0, 0) 13px 27px 13px 27px] @@ -200,49 +200,49 @@ Fail CSS Transitions: property from [15px 10px 5px 6px black] to [- Pass CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0) should be [rgb(0, 0, 0) 15px 10px 5px 6px] Fail CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.3) should be [rgb(0, 38, 0) 6px 4px 11px 3px] Fail CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.6) should be [rgb(0, 77, 0) -3px -2px 17px 0px] -Fail CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] +Pass CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] Fail CSS Transitions: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1.5) should be [rgb(0, 192, 0) -30px -20px 35px -9px] Fail CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (-0.3) should be [rgb(0, 0, 0) 24px 16px 0px 9px] Pass CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0) should be [rgb(0, 0, 0) 15px 10px 5px 6px] Fail CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.3) should be [rgb(0, 38, 0) 6px 4px 11px 3px] Fail CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.6) should be [rgb(0, 77, 0) -3px -2px 17px 0px] -Fail CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] +Pass CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] Fail CSS Transitions with transition: all: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1.5) should be [rgb(0, 192, 0) -30px -20px 35px -9px] Fail CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (-0.3) should be [rgb(0, 0, 0) 24px 16px 0px 9px] Pass CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0) should be [rgb(0, 0, 0) 15px 10px 5px 6px] Fail CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.3) should be [rgb(0, 38, 0) 6px 4px 11px 3px] Fail CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.6) should be [rgb(0, 77, 0) -3px -2px 17px 0px] -Fail CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] +Pass CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] Fail CSS Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1.5) should be [rgb(0, 192, 0) -30px -20px 35px -9px] Fail Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (-0.3) should be [rgb(0, 0, 0) 24px 16px 0px 9px] Pass Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0) should be [rgb(0, 0, 0) 15px 10px 5px 6px] Fail Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.3) should be [rgb(0, 38, 0) 6px 4px 11px 3px] Fail Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (0.6) should be [rgb(0, 77, 0) -3px -2px 17px 0px] -Fail Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] +Pass Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1) should be [rgb(0, 128, 0) -15px -10px 25px -4px] Fail Web Animations: property from [15px 10px 5px 6px black] to [-15px -10px 25px -4px] at (1.5) should be [rgb(0, 192, 0) -30px -20px 35px -9px] Pass CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (-0.3) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Pass CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Fail CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.3) should be [rgb(0, 38, 0) 10px 10px 10px 10px] Fail CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.6) should be [rgb(0, 77, 0) 10px 10px 10px 10px] -Fail CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] +Pass CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] Fail CSS Transitions: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1.5) should be [rgb(0, 192, 0) 10px 10px 10px 10px] Pass CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (-0.3) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Pass CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Fail CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.3) should be [rgb(0, 38, 0) 10px 10px 10px 10px] Fail CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.6) should be [rgb(0, 77, 0) 10px 10px 10px 10px] -Fail CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] +Pass CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] Fail CSS Transitions with transition: all: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1.5) should be [rgb(0, 192, 0) 10px 10px 10px 10px] Pass CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (-0.3) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Pass CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Fail CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.3) should be [rgb(0, 38, 0) 10px 10px 10px 10px] Fail CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.6) should be [rgb(0, 77, 0) 10px 10px 10px 10px] -Fail CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] +Pass CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] Fail CSS Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1.5) should be [rgb(0, 192, 0) 10px 10px 10px 10px] Pass Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (-0.3) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Pass Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0) should be [rgb(0, 0, 0) 10px 10px 10px 10px] Fail Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.3) should be [rgb(0, 38, 0) 10px 10px 10px 10px] Fail Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (0.6) should be [rgb(0, 77, 0) 10px 10px 10px 10px] -Fail Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] +Pass Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1) should be [rgb(0, 128, 0) 10px 10px 10px 10px] Fail Web Animations: property from [10px 10px 10px 10px black] to [10px 10px 10px 10px currentColor] at (1.5) should be [rgb(0, 192, 0) 10px 10px 10px 10px] Fail CSS Transitions: property from [10px 20px rgba(255, 255, 0, 0.5), inset 5px 10em #008000] to [none] at (-0.3) should be [rgba(255, 255, 0, 0.65) 13px 26px 0px 0px, rgb(0, 166, 0) 6.5px 39px 0px 0px inset] Fail CSS Transitions: property from [10px 20px rgba(255, 255, 0, 0.5), inset 5px 10em #008000] to [none] at (0) should be [rgba(255, 255, 0, 0.5) 10px 20px 0px 0px, rgb(0, 128, 0) 5px 30px 0px 0px inset] diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt index 1d629bc7069..eb707359aba 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hsl.txt @@ -2,8 +2,8 @@ Harness status: OK Found 3753 tests -3735 Pass -18 Fail +3747 Pass +6 Fail Pass Property color value 'hsl(120 30% 50%)' Pass Property color value 'hsl(120 30% 50% / 0.5)' Pass Property color value 'hsl(120 30% 50% / 50%)' @@ -3739,21 +3739,21 @@ Pass Property color value 'hsla(360, 37.5%, 62.5%, 0.2)' [HSL/HSLA value should Pass Property color value 'hsla(360, 37.5%, 62.5%, 1)' [HSL/HSLA value should parse and round correctly] Pass Property color value 'hsl(360, 37.5%, 75%)' [HSL/HSLA value should parse and round correctly] Pass Property color value 'hsla(360, 37.5%, 75%, 0)' [HSL/HSLA value should parse and round correctly] -Fail Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' -Fail Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' +Pass Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' +Pass Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)), 100%, 37.5%, 50%)' Fail Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' Fail Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)), 100%, 37.5%, 50%)' -Fail Property color value 'hsl(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsla(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsl(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsla(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' -Fail Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' +Pass Property color value 'hsl(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsla(60deg, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsl(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsla(60, 100%, 37.5%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsl(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' +Pass Property color value 'hsla(calc(50deg + (sign(1em - 10px) * 10deg)) 100% 37.5% / 50%)' Fail Property color value 'hsl(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' Fail Property color value 'hsla(calc(50 + (sign(1em - 10px) * 10)) 100 37.5 / 0.5)' -Fail Property color value 'hsl(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsla(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hsl(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))' -Fail Property color value 'hsla(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'hsl(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsla(60deg 100% 37.5% / calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hsl(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'hsla(60 100 37.5 / calc(0.75 + (sign(1em - 10px) * 0.1)))' Fail Property color value 'hsla(calc(50deg + (sign(2cqw - 10px) * 10deg)), 100%, 37.5%, 51%)' Fail Property color value 'hsla(calc(50deg + (sign(2cqw - 10px) * 10deg)), 100%, 37.5%, 52%)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt index cca5264baa0..9902c65b690 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-hwb.txt @@ -2,8 +2,8 @@ Harness status: OK Found 56 tests -50 Pass -6 Fail +53 Pass +3 Fail Pass Property color value 'hwb(120 30% 50%)' Pass Property color value 'hwb(120 30% 50% / 0.5)' Pass Property color value 'hwb(120 30% 50% / 50%)' @@ -54,9 +54,9 @@ Pass Property color value 'hwb(90 50% 100%)' [HWB value should parse and round c Pass Property color value 'hwb(90 50% 50% / 0)' [HWB value should parse and round correctly] Pass Property color value 'hwb(90 50% 50% / 0.2)' [HWB value should parse and round correctly] Pass Property color value 'hwb(90 50% 50% / 1)' [HWB value should parse and round correctly] -Fail Property color value 'hwb(calc(110deg + (sign(1em - 10px) * 10deg)) 30% 50% / 50%)' +Pass Property color value 'hwb(calc(110deg + (sign(1em - 10px) * 10deg)) 30% 50% / 50%)' Fail Property color value 'hwb(calc(110 + (sign(1em - 10px) * 10)) 30 50 / 0.5)' -Fail Property color value 'hwb(120deg 30% 50% / calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'hwb(120 30 50 / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'hwb(120deg 30% 50% / calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'hwb(120 30 50 / calc(0.75 + (sign(1em - 10px) * 0.1)))' Fail Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 51%)' Fail Property color value 'hwb(calc(110deg + (sign(2cqw - 10px) * 10deg)) 30 50 / 52%)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-rgb.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-rgb.txt index 97e8af10314..7f59ad8057e 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-rgb.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-color/parsing/color-computed-rgb.txt @@ -2,8 +2,8 @@ Harness status: OK Found 99 tests -79 Pass -20 Fail +97 Pass +2 Fail Pass Property color value 'rgb(none none none)' Pass Property color value 'rgb(none none none / none)' Pass Property color value 'rgb(128 none none)' @@ -83,23 +83,23 @@ Pass Property color value 'rgb(0, 0, calc(0 / 0))' [Blue channel resolves NaN eq Pass Property color value 'rgba(0, 0, 0, calc(0 / 0))' [Alpha channel resolves NaN equivalent calc statements to zero] Pass Property color value 'rgb(var(--high), 0, 0)' [Variables above 255 get clamped to 255.] Pass Property color value 'rgb(var(--negative), 64, 128)' [Variables below 0 get clamped to 0.] -Fail Property color value 'rgb(calc(50% + (sign(1em - 10px) * 10%)), 0%, 0%, 50%)' -Fail Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)), 0%, 0%, 50%)' -Fail Property color value 'rgb(calc(50 + (sign(1em - 10px) * 10)), 0, 0, 0.5)' -Fail Property color value 'rgba(calc(50 + (sign(1em - 10px) * 10)), 0, 0, 0.5)' -Fail Property color value 'rgb(0%, 0%, 0%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'rgba(0%, 0%, 0%, calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'rgb(0, 0, 0, calc(0.75 + (sign(1em - 10px) * 0.1)))' -Fail Property color value 'rgba(0, 0, 0, calc(0.75 + (sign(1em - 10px) * 0.1)))' -Fail Property color value 'rgb(calc(50% + (sign(1em - 10px) * 10%)) 0% 0% / 50%)' -Fail Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)) 0% 0% / 50%)' -Fail Property color value 'rgb(calc(50 + (sign(1em - 10px) * 10)) 0 0 / 0.5)' -Fail Property color value 'rgba(calc(50 + (sign(1em - 10px) * 10)) 0 0 / 0.5)' -Fail Property color value 'rgb(0% 0% 0% / calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'rgba(0% 0% 0% / calc(50% + (sign(1em - 10px) * 10%)))' -Fail Property color value 'rgb(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))' -Fail Property color value 'rgba(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))' -Fail Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)) 0 0% / 0.5)' -Fail Property color value 'rgba(0% 0 0% / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'rgb(calc(50% + (sign(1em - 10px) * 10%)), 0%, 0%, 50%)' +Pass Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)), 0%, 0%, 50%)' +Pass Property color value 'rgb(calc(50 + (sign(1em - 10px) * 10)), 0, 0, 0.5)' +Pass Property color value 'rgba(calc(50 + (sign(1em - 10px) * 10)), 0, 0, 0.5)' +Pass Property color value 'rgb(0%, 0%, 0%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'rgba(0%, 0%, 0%, calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'rgb(0, 0, 0, calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'rgba(0, 0, 0, calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'rgb(calc(50% + (sign(1em - 10px) * 10%)) 0% 0% / 50%)' +Pass Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)) 0% 0% / 50%)' +Pass Property color value 'rgb(calc(50 + (sign(1em - 10px) * 10)) 0 0 / 0.5)' +Pass Property color value 'rgba(calc(50 + (sign(1em - 10px) * 10)) 0 0 / 0.5)' +Pass Property color value 'rgb(0% 0% 0% / calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'rgba(0% 0% 0% / calc(50% + (sign(1em - 10px) * 10%)))' +Pass Property color value 'rgb(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'rgba(0 0 0 / calc(0.75 + (sign(1em - 10px) * 0.1)))' +Pass Property color value 'rgba(calc(50% + (sign(1em - 10px) * 10%)) 0 0% / 0.5)' +Pass Property color value 'rgba(0% 0 0% / calc(0.75 + (sign(1em - 10px) * 0.1)))' Fail Property color value 'rgba(calc(50% + (sign(2cqw - 10px) * 10%)), 0%, 0%, 51%)' Fail Property color value 'rgba(calc(50% + (sign(2cqw - 10px) * 10%)), 0%, 0%, 52%)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.txt b/Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.txt new file mode 100644 index 00000000000..d03d8d009d7 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.txt @@ -0,0 +1,6 @@ +Harness status: OK + +Found 1 tests + +1 Pass +Pass currentColor is computed from the canvas element even when element is not rendered \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html b/Tests/LibWeb/Text/input/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html new file mode 100644 index 00000000000..82a7b21e1f4 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/canvas/element/manual/fill-and-stroke-styles/2d.fillStyle.parse.current.notrendered.html @@ -0,0 +1,31 @@ + +Canvas test: 2d.fillStyle.parse.current.notrendered + + + + + + +

2d.fillStyle.parse.current.basic

+

currentColor is computed from the canvas element

+ + +

Actual output:

+

FAIL (fallback content)

+

Expected output:

+

    + diff --git a/Tests/LibWeb/Text/input/wpt-import/images/green-100x50.png b/Tests/LibWeb/Text/input/wpt-import/images/green-100x50.png new file mode 100644 index 0000000000000000000000000000000000000000..2733836c998fa919d9f6880fd96a32026e82ca2c GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0y~yU`SzLU@+ofVqjoU4S)HPfq{W7$=lt9;Xep2*t>i( z0|P^or;B4qM&sKHj+_h%3