diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 1ae996f905..02bfcb6787 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -299,15 +299,8 @@ BackgroundStyleValue::BackgroundStyleValue( NonnullRefPtr attachment, NonnullRefPtr origin, NonnullRefPtr clip) - : StyleValue(Type::Background) - , m_color(color) - , m_image(image) - , m_position(position) - , m_size(size) - , m_repeat(repeat) - , m_attachment(attachment) - , m_origin(origin) - , m_clip(clip) + : StyleValueWithDefaultOperators(Type::Background) + , m_properties { .color = color, .image = image, .position = position, .size = size, .repeat = repeat, .attachment = attachment, .origin = origin, .clip = clip, .layer_count = 0 } { auto layer_count = [](auto style_value) -> size_t { if (style_value->is_value_list()) @@ -316,20 +309,20 @@ BackgroundStyleValue::BackgroundStyleValue( return 1; }; - m_layer_count = max(layer_count(m_image), layer_count(m_position)); - m_layer_count = max(m_layer_count, layer_count(m_size)); - m_layer_count = max(m_layer_count, layer_count(m_repeat)); - m_layer_count = max(m_layer_count, layer_count(m_attachment)); - m_layer_count = max(m_layer_count, layer_count(m_origin)); - m_layer_count = max(m_layer_count, layer_count(m_clip)); + m_properties.layer_count = max(layer_count(m_properties.image), layer_count(m_properties.position)); + m_properties.layer_count = max(m_properties.layer_count, layer_count(m_properties.size)); + m_properties.layer_count = max(m_properties.layer_count, layer_count(m_properties.repeat)); + m_properties.layer_count = max(m_properties.layer_count, layer_count(m_properties.attachment)); + m_properties.layer_count = max(m_properties.layer_count, layer_count(m_properties.origin)); + m_properties.layer_count = max(m_properties.layer_count, layer_count(m_properties.clip)); - VERIFY(!m_color->is_value_list()); + VERIFY(!m_properties.color->is_value_list()); } ErrorOr BackgroundStyleValue::to_string() const { - if (m_layer_count == 1) { - return String::formatted("{} {} {} {} {} {} {} {}", TRY(m_color->to_string()), TRY(m_image->to_string()), TRY(m_position->to_string()), TRY(m_size->to_string()), TRY(m_repeat->to_string()), TRY(m_attachment->to_string()), TRY(m_origin->to_string()), TRY(m_clip->to_string())); + if (m_properties.layer_count == 1) { + return String::formatted("{} {} {} {} {} {} {} {}", TRY(m_properties.color->to_string()), TRY(m_properties.image->to_string()), TRY(m_properties.position->to_string()), TRY(m_properties.size->to_string()), TRY(m_properties.repeat->to_string()), TRY(m_properties.attachment->to_string()), TRY(m_properties.origin->to_string()), TRY(m_properties.clip->to_string())); } auto get_layer_value_string = [](NonnullRefPtr const& style_value, size_t index) { @@ -339,104 +332,42 @@ ErrorOr BackgroundStyleValue::to_string() const }; StringBuilder builder; - for (size_t i = 0; i < m_layer_count; i++) { + for (size_t i = 0; i < m_properties.layer_count; i++) { if (i) TRY(builder.try_append(", "sv)); - if (i == m_layer_count - 1) - TRY(builder.try_appendff("{} ", TRY(m_color->to_string()))); - TRY(builder.try_appendff("{} {} {} {} {} {} {}", TRY(get_layer_value_string(m_image, i)), TRY(get_layer_value_string(m_position, i)), TRY(get_layer_value_string(m_size, i)), TRY(get_layer_value_string(m_repeat, i)), TRY(get_layer_value_string(m_attachment, i)), TRY(get_layer_value_string(m_origin, i)), TRY(get_layer_value_string(m_clip, i)))); + if (i == m_properties.layer_count - 1) + TRY(builder.try_appendff("{} ", TRY(m_properties.color->to_string()))); + TRY(builder.try_appendff("{} {} {} {} {} {} {}", TRY(get_layer_value_string(m_properties.image, i)), TRY(get_layer_value_string(m_properties.position, i)), TRY(get_layer_value_string(m_properties.size, i)), TRY(get_layer_value_string(m_properties.repeat, i)), TRY(get_layer_value_string(m_properties.attachment, i)), TRY(get_layer_value_string(m_properties.origin, i)), TRY(get_layer_value_string(m_properties.clip, i)))); } return builder.to_string(); } -bool BackgroundStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_background(); - return m_color->equals(typed_other.m_color) - && m_image->equals(typed_other.m_image) - && m_position->equals(typed_other.m_position) - && m_size->equals(typed_other.m_size) - && m_repeat->equals(typed_other.m_repeat) - && m_attachment->equals(typed_other.m_attachment) - && m_origin->equals(typed_other.m_origin) - && m_clip->equals(typed_other.m_clip); -} - ErrorOr BackgroundRepeatStyleValue::to_string() const { - return String::formatted("{} {}", CSS::to_string(m_repeat_x), CSS::to_string(m_repeat_y)); -} - -bool BackgroundRepeatStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_background_repeat(); - return m_repeat_x == typed_other.m_repeat_x && m_repeat_y == typed_other.m_repeat_y; + return String::formatted("{} {}", CSS::to_string(m_properties.repeat_x), CSS::to_string(m_properties.repeat_y)); } ErrorOr BackgroundSizeStyleValue::to_string() const { - return String::formatted("{} {}", TRY(m_size_x.to_string()), TRY(m_size_y.to_string())); -} - -bool BackgroundSizeStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_background_size(); - return m_size_x == typed_other.m_size_x && m_size_y == typed_other.m_size_y; + return String::formatted("{} {}", TRY(m_properties.size_x.to_string()), TRY(m_properties.size_y.to_string())); } ErrorOr BorderStyleValue::to_string() const { - return String::formatted("{} {} {}", TRY(m_border_width->to_string()), TRY(m_border_style->to_string()), TRY(m_border_color->to_string())); -} - -bool BorderStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_border(); - return m_border_width->equals(typed_other.m_border_width) - && m_border_style->equals(typed_other.m_border_style) - && m_border_color->equals(typed_other.m_border_color); + return String::formatted("{} {} {}", TRY(m_properties.border_width->to_string()), TRY(m_properties.border_style->to_string()), TRY(m_properties.border_color->to_string())); } ErrorOr BorderRadiusStyleValue::to_string() const { - if (m_horizontal_radius == m_vertical_radius) - return m_horizontal_radius.to_string(); - return String::formatted("{} / {}", TRY(m_horizontal_radius.to_string()), TRY(m_vertical_radius.to_string())); -} - -bool BorderRadiusStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_border_radius(); - return m_is_elliptical == typed_other.m_is_elliptical - && m_horizontal_radius == typed_other.m_horizontal_radius - && m_vertical_radius == typed_other.m_vertical_radius; + if (m_properties.horizontal_radius == m_properties.vertical_radius) + return m_properties.horizontal_radius.to_string(); + return String::formatted("{} / {}", TRY(m_properties.horizontal_radius.to_string()), TRY(m_properties.vertical_radius.to_string())); } ErrorOr BorderRadiusShorthandStyleValue::to_string() const { - return String::formatted("{} {} {} {} / {} {} {} {}", TRY(m_top_left->horizontal_radius().to_string()), TRY(m_top_right->horizontal_radius().to_string()), TRY(m_bottom_right->horizontal_radius().to_string()), TRY(m_bottom_left->horizontal_radius().to_string()), TRY(m_top_left->vertical_radius().to_string()), TRY(m_top_right->vertical_radius().to_string()), TRY(m_bottom_right->vertical_radius().to_string()), TRY(m_bottom_left->vertical_radius().to_string())); -} - -bool BorderRadiusShorthandStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_border_radius_shorthand(); - return m_top_left->equals(typed_other.m_top_left) - && m_top_right->equals(typed_other.m_top_right) - && m_bottom_right->equals(typed_other.m_bottom_right) - && m_bottom_left->equals(typed_other.m_bottom_left); + return String::formatted("{} {} {} {} / {} {} {} {}", TRY(m_properties.top_left->horizontal_radius().to_string()), TRY(m_properties.top_right->horizontal_radius().to_string()), TRY(m_properties.bottom_right->horizontal_radius().to_string()), TRY(m_properties.bottom_left->horizontal_radius().to_string()), TRY(m_properties.top_left->vertical_radius().to_string()), TRY(m_properties.top_right->vertical_radius().to_string()), TRY(m_properties.bottom_right->vertical_radius().to_string()), TRY(m_properties.bottom_left->vertical_radius().to_string())); } void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) @@ -633,7 +564,7 @@ ErrorOr CalculatedStyleValue::to_string() const return String::formatted("calc({})", TRY(m_expression->to_string())); } -bool CalculatedStyleValue::equals(StyleValue const& other) const +bool CalculatedStyleValue::operator==(StyleValue const& other) const { if (type() != other.type()) return false; @@ -1167,32 +1098,11 @@ ErrorOr ColorStyleValue::to_string() const return serialize_a_srgb_value(m_color); } -bool ColorStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_color == other.as_color().m_color; -} - ErrorOr ContentStyleValue::to_string() const { if (has_alt_text()) - return String::formatted("{} / {}", TRY(m_content->to_string()), TRY(m_alt_text->to_string())); - return m_content->to_string(); -} - -bool ContentStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_content(); - if (!m_content->equals(typed_other.m_content)) - return false; - if (m_alt_text.is_null() != typed_other.m_alt_text.is_null()) - return false; - if (!m_alt_text.is_null()) - return m_alt_text->equals(*typed_other.m_alt_text); - return true; + return String::formatted("{} / {}", TRY(m_properties.content->to_string()), TRY(m_properties.alt_text->to_string())); + return m_properties.content->to_string(); } float Filter::Blur::resolved_radius(Layout::Node const& node) const @@ -1306,127 +1216,47 @@ ErrorOr FilterValueListStyleValue::to_string() const return builder.to_string(); } -bool FilterValueListStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_filter_value_list(); - if (m_filter_value_list.size() != typed_other.m_filter_value_list.size()) - return false; - for (size_t i = 0; i < m_filter_value_list.size(); i++) { - if (m_filter_value_list[i] != typed_other.m_filter_value_list[i]) - return false; - } - return true; -} - ErrorOr FlexStyleValue::to_string() const { - return String::formatted("{} {} {}", TRY(m_grow->to_string()), TRY(m_shrink->to_string()), TRY(m_basis->to_string())); -} - -bool FlexStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_flex(); - return m_grow->equals(typed_other.m_grow) - && m_shrink->equals(typed_other.m_shrink) - && m_basis->equals(typed_other.m_basis); + return String::formatted("{} {} {}", TRY(m_properties.grow->to_string()), TRY(m_properties.shrink->to_string()), TRY(m_properties.basis->to_string())); } ErrorOr FlexFlowStyleValue::to_string() const { - return String::formatted("{} {}", TRY(m_flex_direction->to_string()), TRY(m_flex_wrap->to_string())); -} - -bool FlexFlowStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_flex_flow(); - return m_flex_direction->equals(typed_other.m_flex_direction) - && m_flex_wrap->equals(typed_other.m_flex_wrap); + return String::formatted("{} {}", TRY(m_properties.flex_direction->to_string()), TRY(m_properties.flex_wrap->to_string())); } ErrorOr FontStyleValue::to_string() const { - return String::formatted("{} {} {} / {} {}", TRY(m_font_style->to_string()), TRY(m_font_weight->to_string()), TRY(m_font_size->to_string()), TRY(m_line_height->to_string()), TRY(m_font_families->to_string())); -} - -bool FontStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_font(); - return m_font_style->equals(typed_other.m_font_style) - && m_font_weight->equals(typed_other.m_font_weight) - && m_font_size->equals(typed_other.m_font_size) - && m_line_height->equals(typed_other.m_line_height) - && m_font_families->equals(typed_other.m_font_families); -} - -bool FrequencyStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_frequency == other.as_frequency().m_frequency; + return String::formatted("{} {} {} / {} {}", TRY(m_properties.font_style->to_string()), TRY(m_properties.font_weight->to_string()), TRY(m_properties.font_size->to_string()), TRY(m_properties.line_height->to_string()), TRY(m_properties.font_families->to_string())); } ErrorOr GridTrackPlacementShorthandStyleValue::to_string() const { - if (m_end->grid_track_placement().is_auto()) - return String::formatted("{}", TRY(m_start->grid_track_placement().to_string())); - return String::formatted("{} / {}", TRY(m_start->grid_track_placement().to_string()), TRY(m_end->grid_track_placement().to_string())); -} - -bool GridTrackPlacementShorthandStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_grid_track_placement_shorthand(); - return m_start->equals(typed_other.m_start) - && m_end->equals(typed_other.m_end); + if (m_properties.end->grid_track_placement().is_auto()) + return String::formatted("{}", TRY(m_properties.start->grid_track_placement().to_string())); + return String::formatted("{} / {}", TRY(m_properties.start->grid_track_placement().to_string()), TRY(m_properties.end->grid_track_placement().to_string())); } ErrorOr GridAreaShorthandStyleValue::to_string() const { StringBuilder builder; - if (!m_row_start->as_grid_track_placement().grid_track_placement().is_auto()) - TRY(builder.try_appendff("{}", TRY(m_row_start->as_grid_track_placement().grid_track_placement().to_string()))); - if (!m_column_start->as_grid_track_placement().grid_track_placement().is_auto()) - TRY(builder.try_appendff(" / {}", TRY(m_column_start->as_grid_track_placement().grid_track_placement().to_string()))); - if (!m_row_end->as_grid_track_placement().grid_track_placement().is_auto()) - TRY(builder.try_appendff(" / {}", TRY(m_row_end->as_grid_track_placement().grid_track_placement().to_string()))); - if (!m_column_end->as_grid_track_placement().grid_track_placement().is_auto()) - TRY(builder.try_appendff(" / {}", TRY(m_column_end->as_grid_track_placement().grid_track_placement().to_string()))); + if (!m_properties.row_start->as_grid_track_placement().grid_track_placement().is_auto()) + TRY(builder.try_appendff("{}", TRY(m_properties.row_start->as_grid_track_placement().grid_track_placement().to_string()))); + if (!m_properties.column_start->as_grid_track_placement().grid_track_placement().is_auto()) + TRY(builder.try_appendff(" / {}", TRY(m_properties.column_start->as_grid_track_placement().grid_track_placement().to_string()))); + if (!m_properties.row_end->as_grid_track_placement().grid_track_placement().is_auto()) + TRY(builder.try_appendff(" / {}", TRY(m_properties.row_end->as_grid_track_placement().grid_track_placement().to_string()))); + if (!m_properties.column_end->as_grid_track_placement().grid_track_placement().is_auto()) + TRY(builder.try_appendff(" / {}", TRY(m_properties.column_end->as_grid_track_placement().grid_track_placement().to_string()))); return builder.to_string(); } -bool GridAreaShorthandStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_grid_area_shorthand(); - return m_row_start->equals(typed_other.m_row_start) - && m_column_start->equals(typed_other.m_column_start) - && m_row_end->equals(typed_other.m_row_end) - && m_column_end->equals(typed_other.m_column_end); -} - ErrorOr GridTrackPlacementStyleValue::to_string() const { return m_grid_track_placement.to_string(); } -bool GridTrackPlacementStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_grid_track_placement(); - return m_grid_track_placement == typed_other.grid_track_placement(); -} - ErrorOr GridTemplateAreaStyleValue::to_string() const { StringBuilder builder; @@ -1442,39 +1272,16 @@ ErrorOr GridTemplateAreaStyleValue::to_string() const return builder.to_string(); } -bool GridTemplateAreaStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_grid_template_area(); - return m_grid_template_area == typed_other.grid_template_area(); -} - ErrorOr GridTrackSizeStyleValue::to_string() const { return m_grid_track_size_list.to_string(); } -bool GridTrackSizeStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_grid_track_size_list(); - return m_grid_track_size_list == typed_other.grid_track_size_list(); -} - ErrorOr IdentifierStyleValue::to_string() const { return String::from_utf8(CSS::string_from_value_id(m_id)); } -bool IdentifierStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_id == other.as_identifier().m_id; -} - bool IdentifierStyleValue::has_color() const { switch (m_id) { @@ -1732,7 +1539,7 @@ ErrorOr ImageStyleValue::to_string() const return serialize_a_url(m_url.to_deprecated_string()); } -bool ImageStyleValue::equals(StyleValue const& other) const +bool ImageStyleValue::operator==(StyleValue const& other) const { if (type() != other.type()) return false; @@ -1805,33 +1612,30 @@ ErrorOr LinearGradientStyleValue::to_string() const } }; - if (m_gradient_type == GradientType::WebKit) + if (m_properties.gradient_type == GradientType::WebKit) TRY(builder.try_append("-webkit-"sv)); if (is_repeating()) TRY(builder.try_append("repeating-"sv)); TRY(builder.try_append("linear-gradient("sv)); - TRY(m_direction.visit( + TRY(m_properties.direction.visit( [&](SideOrCorner side_or_corner) -> ErrorOr { - return builder.try_appendff("{}{}, "sv, m_gradient_type == GradientType::Standard ? "to "sv : ""sv, side_or_corner_to_string(side_or_corner)); + return builder.try_appendff("{}{}, "sv, m_properties.gradient_type == GradientType::Standard ? "to "sv : ""sv, side_or_corner_to_string(side_or_corner)); }, [&](Angle const& angle) -> ErrorOr { return builder.try_appendff("{}, "sv, TRY(angle.to_string())); })); - TRY(serialize_color_stop_list(builder, m_color_stop_list)); + TRY(serialize_color_stop_list(builder, m_properties.color_stop_list)); TRY(builder.try_append(")"sv)); return builder.to_string(); } -bool LinearGradientStyleValue::equals(StyleValue const& other_) const +bool LinearGradientStyleValue::operator==(StyleValue const& other_) const { if (type() != other_.type()) return false; auto& other = other_.as_linear_gradient(); - return (m_gradient_type == other.m_gradient_type - && m_repeating == other.m_repeating - && m_direction == other.m_direction - && m_color_stop_list == other.m_color_stop_list); + return m_properties == other.m_properties; } float LinearGradientStyleValue::angle_degrees(CSSPixelSize gradient_size) const @@ -1839,7 +1643,7 @@ float LinearGradientStyleValue::angle_degrees(CSSPixelSize gradient_size) const auto corner_angle_degrees = [&] { return static_cast(atan2(gradient_size.height().value(), gradient_size.width().value())) * 180 / AK::Pi; }; - return m_direction.visit( + return m_properties.direction.visit( [&](SideOrCorner side_or_corner) { auto angle = [&] { switch (side_or_corner) { @@ -1864,7 +1668,7 @@ float LinearGradientStyleValue::angle_degrees(CSSPixelSize gradient_size) const } }(); // Note: For unknowable reasons the angles are opposite on the -webkit- version - if (m_gradient_type == GradientType::WebKit) + if (m_properties.gradient_type == GradientType::WebKit) return angle + 180.0f; return angle; }, @@ -1980,24 +1784,15 @@ ErrorOr PositionValue::serialize(StringBuilder& builder) const return {}; } -bool PositionValue::operator==(PositionValue const& other) const -{ - return ( - x_relative_to == other.x_relative_to - && y_relative_to == other.y_relative_to - && horizontal_position == other.horizontal_position - && vertical_position == other.vertical_position); -} - ErrorOr RadialGradientStyleValue::to_string() const { StringBuilder builder; if (is_repeating()) TRY(builder.try_append("repeating-"sv)); TRY(builder.try_appendff("radial-gradient({} "sv, - m_ending_shape == EndingShape::Circle ? "circle"sv : "ellipse"sv)); + m_properties.ending_shape == EndingShape::Circle ? "circle"sv : "ellipse"sv)); - TRY(m_size.visit( + TRY(m_properties.size.visit( [&](Extent extent) -> ErrorOr { return builder.try_append([&] { switch (extent) { @@ -2021,13 +1816,13 @@ ErrorOr RadialGradientStyleValue::to_string() const return builder.try_appendff("{} {}", TRY(ellipse_size.radius_a.to_string()), TRY(ellipse_size.radius_b.to_string())); })); - if (m_position != PositionValue::center()) { + if (m_properties.position != PositionValue::center()) { TRY(builder.try_appendff(" at "sv)); - TRY(m_position.serialize(builder)); + TRY(m_properties.position.serialize(builder)); } TRY(builder.try_append(", "sv)); - TRY(serialize_color_stop_list(builder, m_color_stop_list)); + TRY(serialize_color_stop_list(builder, m_properties.color_stop_list)); TRY(builder.try_append(')')); return builder.to_string(); } @@ -2040,7 +1835,7 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, }; auto x_dist = distance_from(center.x(), size.left(), size.right(), distance_function); auto y_dist = distance_from(center.y(), size.top(), size.bottom(), distance_function); - if (m_ending_shape == EndingShape::Circle) { + if (m_properties.ending_shape == EndingShape::Circle) { auto dist = distance_function(x_dist, y_dist); return Gfx::FloatSize { dist, dist }; } else { @@ -2088,7 +1883,7 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, auto const corner_shape = [&](auto corner_distance, auto get_shape) { Gfx::FloatPoint corner {}; auto distance = corner_distance(corner); - if (m_ending_shape == EndingShape::Ellipse) { + if (m_properties.ending_shape == EndingShape::Ellipse) { auto shape = get_shape(); auto aspect_ratio = shape.width() / shape.height(); auto p = corner - center; @@ -2100,7 +1895,7 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, }; // https://w3c.github.io/csswg-drafts/css-images/#radial-gradient-syntax - auto resolved_size = m_size.visit( + auto resolved_size = m_properties.size.visit( [&](Extent extent) { switch (extent) { case Extent::ClosestSide: @@ -2139,7 +1934,7 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, constexpr auto arbitrary_large_number = 1e10; // If the ending shape is a circle with zero radius: - if (m_ending_shape == EndingShape::Circle && resolved_size.is_empty()) { + if (m_properties.ending_shape == EndingShape::Circle && resolved_size.is_empty()) { // Render as if the ending shape was a circle whose radius was an arbitrary very small number greater than zero. // This will make the gradient continue to look like a circle. return Gfx::FloatSize { arbitrary_small_number, arbitrary_small_number }; @@ -2165,7 +1960,7 @@ Gfx::FloatSize RadialGradientStyleValue::resolve_size(Layout::Node const& node, void RadialGradientStyleValue::resolve_for_size(Layout::Node const& node, CSSPixelSize paint_size) const { CSSPixelRect gradient_box { { 0, 0 }, paint_size }; - auto center = m_position.resolved(node, gradient_box).to_type(); + auto center = m_properties.position.resolved(node, gradient_box).to_type(); auto gradient_size = resolve_size(node, center, gradient_box.to_type()); if (m_resolved.has_value() && m_resolved->gradient_size == gradient_size) return; @@ -2176,15 +1971,12 @@ void RadialGradientStyleValue::resolve_for_size(Layout::Node const& node, CSSPix }; } -bool RadialGradientStyleValue::equals(StyleValue const& other) const +bool RadialGradientStyleValue::operator==(StyleValue const& other) const { if (type() != other.type()) return false; auto& other_gradient = other.as_radial_gradient(); - return (m_ending_shape == other_gradient.m_ending_shape - && m_size == other_gradient.m_size - && m_position == other_gradient.m_position - && m_color_stop_list == other_gradient.m_color_stop_list); + return m_properties == other_gradient.m_properties; } void RadialGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const @@ -2203,17 +1995,17 @@ ErrorOr ConicGradientStyleValue::to_string() const TRY(builder.try_append("conic-gradient("sv)); bool has_from_angle = false; bool has_at_position = false; - if ((has_from_angle = m_from_angle.to_degrees() != 0)) - TRY(builder.try_appendff("from {}", TRY(m_from_angle.to_string()))); - if ((has_at_position = m_position != PositionValue::center())) { + if ((has_from_angle = m_properties.from_angle.to_degrees() != 0)) + TRY(builder.try_appendff("from {}", TRY(m_properties.from_angle.to_string()))); + if ((has_at_position = m_properties.position != PositionValue::center())) { if (has_from_angle) TRY(builder.try_append(' ')); TRY(builder.try_appendff("at "sv)); - TRY(m_position.serialize(builder)); + TRY(m_properties.position.serialize(builder)); } if (has_from_angle || has_at_position) TRY(builder.try_append(", "sv)); - TRY(serialize_color_stop_list(builder, m_color_stop_list)); + TRY(serialize_color_stop_list(builder, m_properties.color_stop_list)); TRY(builder.try_append(')')); return builder.to_string(); } @@ -2222,7 +2014,7 @@ void ConicGradientStyleValue::resolve_for_size(Layout::Node const& node, CSSPixe { if (!m_resolved.has_value()) m_resolved = ResolvedData { Painting::resolve_conic_gradient_data(node, *this), {} }; - m_resolved->position = m_position.resolved(node, CSSPixelRect { { 0, 0 }, size }); + m_resolved->position = m_properties.position.resolved(node, CSSPixelRect { { 0, 0 }, size }); } void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering) const @@ -2231,88 +2023,35 @@ void ConicGradientStyleValue::paint(PaintContext& context, DevicePixelRect const Painting::paint_conic_gradient(context, dest_rect, m_resolved->data, context.rounded_device_point(m_resolved->position)); } -bool ConicGradientStyleValue::equals(StyleValue const& other) const +bool ConicGradientStyleValue::operator==(StyleValue const& other) const { if (type() != other.type()) return false; auto& other_gradient = other.as_conic_gradient(); - return (m_from_angle == other_gradient.m_from_angle - && m_position == other_gradient.m_position - && m_color_stop_list == other_gradient.m_color_stop_list - && m_repeating == other_gradient.m_repeating); + return m_properties == other_gradient.m_properties; } float ConicGradientStyleValue::angle_degrees() const { - return m_from_angle.to_degrees(); -} - -bool InheritStyleValue::equals(StyleValue const& other) const -{ - return type() == other.type(); -} - -bool InitialStyleValue::equals(StyleValue const& other) const -{ - return type() == other.type(); -} - -bool LengthStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_length == other.as_length().m_length; + return m_properties.from_angle.to_degrees(); } ErrorOr ListStyleStyleValue::to_string() const { - return String::formatted("{} {} {}", TRY(m_position->to_string()), TRY(m_image->to_string()), TRY(m_style_type->to_string())); -} - -bool ListStyleStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_list_style(); - return m_position->equals(typed_other.m_position) - && m_image->equals(typed_other.m_image) - && m_style_type->equals(typed_other.m_style_type); + return String::formatted("{} {} {}", TRY(m_properties.position->to_string()), TRY(m_properties.image->to_string()), TRY(m_properties.style_type->to_string())); } ErrorOr NumericStyleValue::to_string() const { return m_value.visit( - [](float value) { - return String::formatted("{}", value); - }, - [](i64 value) { + [](auto value) { return String::formatted("{}", value); }); } -bool NumericStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - if (has_integer() != other.has_integer()) - return false; - if (has_integer()) - return m_value.get() == other.as_numeric().m_value.get(); - return m_value.get() == other.as_numeric().m_value.get(); -} - ErrorOr OverflowStyleValue::to_string() const { - return String::formatted("{} {}", TRY(m_overflow_x->to_string()), TRY(m_overflow_y->to_string())); -} - -bool OverflowStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_overflow(); - return m_overflow_x->equals(typed_other.m_overflow_x) - && m_overflow_y->equals(typed_other.m_overflow_y); + return String::formatted("{} {}", TRY(m_properties.overflow_x->to_string()), TRY(m_properties.overflow_y->to_string())); } ErrorOr PercentageStyleValue::to_string() const @@ -2320,13 +2059,6 @@ ErrorOr PercentageStyleValue::to_string() const return m_percentage.to_string(); } -bool PercentageStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_percentage == other.as_percentage().m_percentage; -} - ErrorOr PositionStyleValue::to_string() const { auto to_string = [](PositionEdge edge) { @@ -2343,18 +2075,7 @@ ErrorOr PositionStyleValue::to_string() const VERIFY_NOT_REACHED(); }; - return String::formatted("{} {} {} {}", to_string(m_edge_x), TRY(m_offset_x.to_string()), to_string(m_edge_y), TRY(m_offset_y.to_string())); -} - -bool PositionStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_position(); - return m_edge_x == typed_other.m_edge_x - && m_offset_x == typed_other.m_offset_x - && m_edge_y == typed_other.m_edge_y - && m_offset_y == typed_other.m_offset_y; + return String::formatted("{} {} {} {}", to_string(m_properties.edge_x), TRY(m_properties.offset_x.to_string()), to_string(m_properties.edge_y), TRY(m_properties.offset_y.to_string())); } ErrorOr RectStyleValue::to_string() const @@ -2362,98 +2083,34 @@ ErrorOr RectStyleValue::to_string() const return String::formatted("rect({} {} {} {})", m_rect.top_edge, m_rect.right_edge, m_rect.bottom_edge, m_rect.left_edge); } -bool RectStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_rect(); - return m_rect == typed_other.rect(); -} - -bool ResolutionStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_resolution == other.as_resolution().m_resolution; -} - ErrorOr ShadowStyleValue::to_string() const { StringBuilder builder; - TRY(builder.try_appendff("{} {} {} {} {}", m_color.to_deprecated_string(), TRY(m_offset_x.to_string()), TRY(m_offset_y.to_string()), TRY(m_blur_radius.to_string()), TRY(m_spread_distance.to_string()))); - if (m_placement == ShadowPlacement::Inner) + TRY(builder.try_appendff("{} {} {} {} {}", m_properties.color.to_deprecated_string(), TRY(m_properties.offset_x.to_string()), TRY(m_properties.offset_y.to_string()), TRY(m_properties.blur_radius.to_string()), TRY(m_properties.spread_distance.to_string()))); + if (m_properties.placement == ShadowPlacement::Inner) TRY(builder.try_append(" inset"sv)); return builder.to_string(); } -bool ShadowStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_shadow(); - return m_color == typed_other.m_color - && m_offset_x == typed_other.m_offset_x - && m_offset_y == typed_other.m_offset_y - && m_blur_radius == typed_other.m_blur_radius - && m_spread_distance == typed_other.m_spread_distance - && m_placement == typed_other.m_placement; -} - -bool StringStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_string == other.as_string().m_string; -} - ErrorOr TextDecorationStyleValue::to_string() const { - return String::formatted("{} {} {} {}", TRY(m_line->to_string()), TRY(m_thickness->to_string()), TRY(m_style->to_string()), TRY(m_color->to_string())); -} - -bool TextDecorationStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_text_decoration(); - return m_line->equals(typed_other.m_line) - && m_thickness->equals(typed_other.m_thickness) - && m_style->equals(typed_other.m_style) - && m_color->equals(typed_other.m_color); -} - -bool TimeStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_time == other.as_time().m_time; + return String::formatted("{} {} {} {}", TRY(m_properties.line->to_string()), TRY(m_properties.thickness->to_string()), TRY(m_properties.style->to_string()), TRY(m_properties.color->to_string())); } ErrorOr TransformationStyleValue::to_string() const { StringBuilder builder; - TRY(builder.try_append(CSS::to_string(m_transform_function))); + TRY(builder.try_append(CSS::to_string(m_properties.transform_function))); TRY(builder.try_append('(')); - TRY(builder.try_join(", "sv, m_values)); + TRY(builder.try_join(", "sv, m_properties.values)); TRY(builder.try_append(')')); return builder.to_string(); } -bool TransformationStyleValue::equals(StyleValue const& other) const +bool TransformationStyleValue::Properties::operator==(Properties const& other) const { - if (type() != other.type()) - return false; - auto const& typed_other = other.as_transformation(); - if (m_transform_function != typed_other.m_transform_function) - return false; - if (m_values.size() != typed_other.m_values.size()) - return false; - for (size_t i = 0; i < m_values.size(); ++i) { - if (!m_values[i].equals(typed_other.m_values[i])) - return false; - } - return true; + return transform_function == other.transform_function && values.span() == other.values.span(); } ErrorOr UnresolvedStyleValue::to_string() const @@ -2464,7 +2121,7 @@ ErrorOr UnresolvedStyleValue::to_string() const return builder.to_string(); } -bool UnresolvedStyleValue::equals(StyleValue const& other) const +bool UnresolvedStyleValue::operator==(StyleValue const& other) const { if (type() != other.type()) return false; @@ -2472,15 +2129,15 @@ bool UnresolvedStyleValue::equals(StyleValue const& other) const return to_string().release_value_but_fixme_should_propagate_errors() == other.to_string().release_value_but_fixme_should_propagate_errors(); } -bool UnsetStyleValue::equals(StyleValue const& other) const +bool StyleValueList::Properties::operator==(Properties const& other) const { - return type() == other.type(); + return separator == other.separator && values.span() == other.values.span(); } ErrorOr StyleValueList::to_string() const { auto separator = ""sv; - switch (m_separator) { + switch (m_properties.separator) { case Separator::Space: separator = " "sv; break; @@ -2491,23 +2148,7 @@ ErrorOr StyleValueList::to_string() const VERIFY_NOT_REACHED(); } - return String::from_deprecated_string(DeprecatedString::join(separator, m_values)); -} - -bool StyleValueList::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - auto const& typed_other = other.as_value_list(); - if (m_separator != typed_other.m_separator) - return false; - if (m_values.size() != typed_other.m_values.size()) - return false; - for (size_t i = 0; i < m_values.size(); ++i) { - if (!m_values[i].equals(typed_other.m_values[i])) - return false; - } - return true; + return String::from_deprecated_string(DeprecatedString::join(separator, m_properties.values)); } NonnullRefPtr ColorStyleValue::create(Color color) @@ -2599,23 +2240,23 @@ NonnullRefPtr LengthStyleValue::absolutized(CSSPixelRect const& view NonnullRefPtr ShadowStyleValue::absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const { - auto absolutized_offset_x = absolutized_length(m_offset_x, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_offset_x); - auto absolutized_offset_y = absolutized_length(m_offset_y, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_offset_y); - auto absolutized_blur_radius = absolutized_length(m_blur_radius, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_blur_radius); - auto absolutized_spread_distance = absolutized_length(m_spread_distance, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_spread_distance); - return ShadowStyleValue::create(m_color, absolutized_offset_x, absolutized_offset_y, absolutized_blur_radius, absolutized_spread_distance, m_placement); + auto absolutized_offset_x = absolutized_length(m_properties.offset_x, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.offset_x); + auto absolutized_offset_y = absolutized_length(m_properties.offset_y, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.offset_y); + auto absolutized_blur_radius = absolutized_length(m_properties.blur_radius, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.blur_radius); + auto absolutized_spread_distance = absolutized_length(m_properties.spread_distance, viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.spread_distance); + return ShadowStyleValue::create(m_properties.color, absolutized_offset_x, absolutized_offset_y, absolutized_blur_radius, absolutized_spread_distance, m_properties.placement); } NonnullRefPtr BorderRadiusStyleValue::absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const { - if (m_horizontal_radius.is_percentage() && m_vertical_radius.is_percentage()) + if (m_properties.horizontal_radius.is_percentage() && m_properties.vertical_radius.is_percentage()) return *this; - auto absolutized_horizontal_radius = m_horizontal_radius; - auto absolutized_vertical_radius = m_vertical_radius; - if (!m_horizontal_radius.is_percentage()) - absolutized_horizontal_radius = absolutized_length(m_horizontal_radius.length(), viewport_rect, font_metrics, font_size, root_font_size).value_or(m_horizontal_radius.length()); - if (!m_vertical_radius.is_percentage()) - absolutized_vertical_radius = absolutized_length(m_vertical_radius.length(), viewport_rect, font_metrics, font_size, root_font_size).value_or(m_vertical_radius.length()); + auto absolutized_horizontal_radius = m_properties.horizontal_radius; + auto absolutized_vertical_radius = m_properties.vertical_radius; + if (!m_properties.horizontal_radius.is_percentage()) + absolutized_horizontal_radius = absolutized_length(m_properties.horizontal_radius.length(), viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.horizontal_radius.length()); + if (!m_properties.vertical_radius.is_percentage()) + absolutized_vertical_radius = absolutized_length(m_properties.vertical_radius.length(), viewport_rect, font_metrics, font_size, root_font_size).value_or(m_properties.vertical_radius.length()); return BorderRadiusStyleValue::create(absolutized_horizontal_radius, absolutized_vertical_radius); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 024bc354dd..7f13d54a2f 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -134,7 +134,7 @@ struct PositionValue { CSSPixelPoint resolved(Layout::Node const& node, CSSPixelRect const& rect) const; ErrorOr serialize(StringBuilder&) const; - bool operator==(PositionValue const&) const; + bool operator==(PositionValue const&) const = default; }; struct EdgeRect { @@ -422,9 +422,7 @@ public: virtual float to_integer() const { return 0; } virtual ErrorOr to_string() const = 0; - bool operator==(StyleValue const& other) const { return equals(other); } - - virtual bool equals(StyleValue const& other) const = 0; + virtual bool operator==(StyleValue const& other) const = 0; protected: explicit StyleValue(Type); @@ -433,7 +431,20 @@ private: Type m_type { Type::Invalid }; }; -class AngleStyleValue : public StyleValue { +template +struct StyleValueWithDefaultOperators : public StyleValue { + using StyleValue::StyleValue; + + bool operator==(StyleValue const& other) const override + { + if (type() != other.type()) + return false; + auto const& typed_other = static_cast(other); + return static_cast(*this).equals(typed_other); + } +}; + +class AngleStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Angle angle) { @@ -445,16 +456,11 @@ public: virtual ErrorOr to_string() const override { return m_angle.to_string(); } - virtual bool equals(StyleValue const& other) const override - { - if (type() != other.type()) - return false; - return m_angle == static_cast(other).m_angle; - } + bool equals(AngleStyleValue const& other) const { return m_angle == other.m_angle; } private: explicit AngleStyleValue(Angle angle) - : StyleValue(Type::Angle) + : StyleValueWithDefaultOperators(Type::Angle) , m_angle(move(angle)) { } @@ -462,7 +468,7 @@ private: Angle m_angle; }; -class BackgroundStyleValue final : public StyleValue { +class BackgroundStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( NonnullRefPtr color, @@ -478,19 +484,20 @@ public: } virtual ~BackgroundStyleValue() override = default; - size_t layer_count() const { return m_layer_count; } + size_t layer_count() const { return m_properties.layer_count; } - NonnullRefPtr attachment() const { return m_attachment; } - NonnullRefPtr clip() const { return m_clip; } - NonnullRefPtr color() const { return m_color; } - NonnullRefPtr image() const { return m_image; } - NonnullRefPtr origin() const { return m_origin; } - NonnullRefPtr position() const { return m_position; } - NonnullRefPtr repeat() const { return m_repeat; } - NonnullRefPtr size() const { return m_size; } + NonnullRefPtr attachment() const { return m_properties.attachment; } + NonnullRefPtr clip() const { return m_properties.clip; } + NonnullRefPtr color() const { return m_properties.color; } + NonnullRefPtr image() const { return m_properties.image; } + NonnullRefPtr origin() const { return m_properties.origin; } + NonnullRefPtr position() const { return m_properties.position; } + NonnullRefPtr repeat() const { return m_properties.repeat; } + NonnullRefPtr size() const { return m_properties.size; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BackgroundStyleValue const& other) const { return m_properties == other.m_properties; } private: BackgroundStyleValue( @@ -503,19 +510,21 @@ private: NonnullRefPtr origin, NonnullRefPtr clip); - NonnullRefPtr m_color; - NonnullRefPtr m_image; - NonnullRefPtr m_position; - NonnullRefPtr m_size; - NonnullRefPtr m_repeat; - NonnullRefPtr m_attachment; - NonnullRefPtr m_origin; - NonnullRefPtr m_clip; - - size_t m_layer_count; + struct Properties { + NonnullRefPtr color; + NonnullRefPtr image; + NonnullRefPtr position; + NonnullRefPtr size; + NonnullRefPtr repeat; + NonnullRefPtr attachment; + NonnullRefPtr origin; + NonnullRefPtr clip; + size_t layer_count; + bool operator==(Properties const&) const = default; + } m_properties; }; -class BackgroundRepeatStyleValue final : public StyleValue { +class BackgroundRepeatStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Repeat repeat_x, Repeat repeat_y) { @@ -523,26 +532,29 @@ public: } virtual ~BackgroundRepeatStyleValue() override = default; - Repeat repeat_x() const { return m_repeat_x; } - Repeat repeat_y() const { return m_repeat_y; } + Repeat repeat_x() const { return m_properties.repeat_x; } + Repeat repeat_y() const { return m_properties.repeat_y; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BackgroundRepeatStyleValue const& other) const { return m_properties == other.m_properties; } private: BackgroundRepeatStyleValue(Repeat repeat_x, Repeat repeat_y) - : StyleValue(Type::BackgroundRepeat) - , m_repeat_x(repeat_x) - , m_repeat_y(repeat_y) + : StyleValueWithDefaultOperators(Type::BackgroundRepeat) + , m_properties { .repeat_x = repeat_x, .repeat_y = repeat_y } { } - Repeat m_repeat_x; - Repeat m_repeat_y; + struct Properties { + Repeat repeat_x; + Repeat repeat_y; + bool operator==(Properties const&) const = default; + } m_properties; }; // NOTE: This is not used for identifier sizes, like `cover` and `contain`. -class BackgroundSizeStyleValue final : public StyleValue { +class BackgroundSizeStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(LengthPercentage size_x, LengthPercentage size_y) { @@ -550,25 +562,28 @@ public: } virtual ~BackgroundSizeStyleValue() override = default; - LengthPercentage size_x() const { return m_size_x; } - LengthPercentage size_y() const { return m_size_y; } + LengthPercentage size_x() const { return m_properties.size_x; } + LengthPercentage size_y() const { return m_properties.size_y; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BackgroundSizeStyleValue const& other) const { return m_properties == other.m_properties; } private: BackgroundSizeStyleValue(LengthPercentage size_x, LengthPercentage size_y) - : StyleValue(Type::BackgroundSize) - , m_size_x(size_x) - , m_size_y(size_y) + : StyleValueWithDefaultOperators(Type::BackgroundSize) + , m_properties { .size_x = size_x, .size_y = size_y } { } - LengthPercentage m_size_x; - LengthPercentage m_size_y; + struct Properties { + LengthPercentage size_x; + LengthPercentage size_y; + bool operator==(Properties const&) const = default; + } m_properties; }; -class BorderStyleValue final : public StyleValue { +class BorderStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( NonnullRefPtr border_width, @@ -579,31 +594,33 @@ public: } virtual ~BorderStyleValue() override = default; - NonnullRefPtr border_width() const { return m_border_width; } - NonnullRefPtr border_style() const { return m_border_style; } - NonnullRefPtr border_color() const { return m_border_color; } + NonnullRefPtr border_width() const { return m_properties.border_width; } + NonnullRefPtr border_style() const { return m_properties.border_style; } + NonnullRefPtr border_color() const { return m_properties.border_color; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BorderStyleValue const& other) const { return m_properties == other.m_properties; } private: BorderStyleValue( NonnullRefPtr border_width, NonnullRefPtr border_style, NonnullRefPtr border_color) - : StyleValue(Type::Border) - , m_border_width(border_width) - , m_border_style(border_style) - , m_border_color(border_color) + : StyleValueWithDefaultOperators(Type::Border) + , m_properties { .border_width = border_width, .border_style = border_style, .border_color = border_color } { } - NonnullRefPtr m_border_width; - NonnullRefPtr m_border_style; - NonnullRefPtr m_border_color; + struct Properties { + NonnullRefPtr border_width; + NonnullRefPtr border_style; + NonnullRefPtr border_color; + bool operator==(Properties const&) const = default; + } m_properties; }; -class BorderRadiusStyleValue final : public StyleValue { +class BorderRadiusStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(LengthPercentage const& horizontal_radius, LengthPercentage const& vertical_radius) { @@ -611,30 +628,32 @@ public: } virtual ~BorderRadiusStyleValue() override = default; - LengthPercentage const& horizontal_radius() const { return m_horizontal_radius; } - LengthPercentage const& vertical_radius() const { return m_vertical_radius; } - bool is_elliptical() const { return m_is_elliptical; } + LengthPercentage const& horizontal_radius() const { return m_properties.horizontal_radius; } + LengthPercentage const& vertical_radius() const { return m_properties.vertical_radius; } + bool is_elliptical() const { return m_properties.is_elliptical; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BorderRadiusStyleValue const& other) const { return m_properties == other.m_properties; } private: BorderRadiusStyleValue(LengthPercentage const& horizontal_radius, LengthPercentage const& vertical_radius) - : StyleValue(Type::BorderRadius) - , m_horizontal_radius(horizontal_radius) - , m_vertical_radius(vertical_radius) + : StyleValueWithDefaultOperators(Type::BorderRadius) + , m_properties { .is_elliptical = horizontal_radius != vertical_radius, .horizontal_radius = horizontal_radius, .vertical_radius = vertical_radius } { - m_is_elliptical = (m_horizontal_radius != m_vertical_radius); } virtual NonnullRefPtr absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override; - bool m_is_elliptical; - LengthPercentage m_horizontal_radius; - LengthPercentage m_vertical_radius; + struct Properties { + bool is_elliptical; + LengthPercentage horizontal_radius; + LengthPercentage vertical_radius; + bool operator==(Properties const&) const = default; + } m_properties; }; -class BorderRadiusShorthandStyleValue final : public StyleValue { +class BorderRadiusShorthandStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr top_left, NonnullRefPtr top_right, NonnullRefPtr bottom_right, NonnullRefPtr bottom_left) { @@ -642,28 +661,29 @@ public: } virtual ~BorderRadiusShorthandStyleValue() override = default; - NonnullRefPtr top_left() const { return m_top_left; } - NonnullRefPtr top_right() const { return m_top_right; } - NonnullRefPtr bottom_right() const { return m_bottom_right; } - NonnullRefPtr bottom_left() const { return m_bottom_left; } + NonnullRefPtr top_left() const { return m_properties.top_left; } + NonnullRefPtr top_right() const { return m_properties.top_right; } + NonnullRefPtr bottom_right() const { return m_properties.bottom_right; } + NonnullRefPtr bottom_left() const { return m_properties.bottom_left; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(BorderRadiusShorthandStyleValue const& other) const { return m_properties == other.m_properties; } private: BorderRadiusShorthandStyleValue(NonnullRefPtr top_left, NonnullRefPtr top_right, NonnullRefPtr bottom_right, NonnullRefPtr bottom_left) - : StyleValue(Type::BorderRadiusShorthand) - , m_top_left(top_left) - , m_top_right(top_right) - , m_bottom_right(bottom_right) - , m_bottom_left(bottom_left) + : StyleValueWithDefaultOperators(Type::BorderRadiusShorthand) + , m_properties { .top_left = top_left, .top_right = top_right, .bottom_right = bottom_right, .bottom_left = bottom_left } { } - NonnullRefPtr m_top_left; - NonnullRefPtr m_top_right; - NonnullRefPtr m_bottom_right; - NonnullRefPtr m_bottom_left; + struct Properties { + NonnullRefPtr top_left; + NonnullRefPtr top_right; + NonnullRefPtr bottom_right; + NonnullRefPtr bottom_left; + bool operator==(Properties const&) const = default; + } m_properties; }; class CalculatedStyleValue : public StyleValue { @@ -833,7 +853,7 @@ public: } ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + virtual bool operator==(StyleValue const& other) const override; ResolvedType resolved_type() const { return m_resolved_type; } NonnullOwnPtr const& expression() const { return m_expression; } @@ -875,7 +895,7 @@ private: NonnullOwnPtr m_expression; }; -class ColorStyleValue : public StyleValue { +class ColorStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Color color); virtual ~ColorStyleValue() override = default; @@ -885,11 +905,11 @@ public: virtual bool has_color() const override { return true; } virtual Color to_color(Layout::NodeWithStyle const&) const override { return m_color; } - virtual bool equals(StyleValue const& other) const override; + bool equals(ColorStyleValue const& other) const { return m_color == other.m_color; }; private: explicit ColorStyleValue(Color color) - : StyleValue(Type::Color) + : StyleValueWithDefaultOperators(Type::Color) , m_color(color) { } @@ -897,33 +917,36 @@ private: Color m_color; }; -class ContentStyleValue final : public StyleValue { +class ContentStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr content, RefPtr alt_text) { return adopt_ref(*new ContentStyleValue(move(content), move(alt_text))); } - StyleValueList const& content() const { return *m_content; } - bool has_alt_text() const { return !m_alt_text.is_null(); } - StyleValueList const* alt_text() const { return m_alt_text; } + StyleValueList const& content() const { return *m_properties.content; } + bool has_alt_text() const { return !m_properties.alt_text.is_null(); } + StyleValueList const* alt_text() const { return m_properties.alt_text; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(ContentStyleValue const& other) const { return m_properties == other.m_properties; }; private: ContentStyleValue(NonnullRefPtr content, RefPtr alt_text) - : StyleValue(Type::Content) - , m_content(move(content)) - , m_alt_text(move(alt_text)) + : StyleValueWithDefaultOperators(Type::Content) + , m_properties { .content = move(content), .alt_text = move(alt_text) } { } - NonnullRefPtr m_content; - RefPtr m_alt_text; + struct Properties { + NonnullRefPtr content; + RefPtr alt_text; + bool operator==(Properties const&) const = default; + } m_properties; }; -class FilterValueListStyleValue final : public StyleValue { +class FilterValueListStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( Vector filter_value_list) @@ -935,13 +958,14 @@ public: Vector const& filter_value_list() const { return m_filter_value_list; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; virtual ~FilterValueListStyleValue() override = default; + bool equals(FilterValueListStyleValue const& other) const { return m_filter_value_list == other.m_filter_value_list; }; + private: FilterValueListStyleValue(Vector filter_value_list) - : StyleValue(Type::FilterValueList) + : StyleValueWithDefaultOperators(Type::FilterValueList) , m_filter_value_list(move(filter_value_list)) { } @@ -950,7 +974,7 @@ private: Vector m_filter_value_list; }; -class FlexStyleValue final : public StyleValue { +class FlexStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( NonnullRefPtr grow, @@ -961,31 +985,33 @@ public: } virtual ~FlexStyleValue() override = default; - NonnullRefPtr grow() const { return m_grow; } - NonnullRefPtr shrink() const { return m_shrink; } - NonnullRefPtr basis() const { return m_basis; } + NonnullRefPtr grow() const { return m_properties.grow; } + NonnullRefPtr shrink() const { return m_properties.shrink; } + NonnullRefPtr basis() const { return m_properties.basis; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(FlexStyleValue const& other) const { return m_properties == other.m_properties; }; private: FlexStyleValue( NonnullRefPtr grow, NonnullRefPtr shrink, NonnullRefPtr basis) - : StyleValue(Type::Flex) - , m_grow(grow) - , m_shrink(shrink) - , m_basis(basis) + : StyleValueWithDefaultOperators(Type::Flex) + , m_properties { .grow = grow, .shrink = shrink, .basis = basis } { } - NonnullRefPtr m_grow; - NonnullRefPtr m_shrink; - NonnullRefPtr m_basis; + struct Properties { + NonnullRefPtr grow; + NonnullRefPtr shrink; + NonnullRefPtr basis; + bool operator==(Properties const&) const = default; + } m_properties; }; -class FlexFlowStyleValue final : public StyleValue { +class FlexFlowStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr flex_direction, NonnullRefPtr flex_wrap) { @@ -993,61 +1019,63 @@ public: } virtual ~FlexFlowStyleValue() override = default; - NonnullRefPtr flex_direction() const { return m_flex_direction; } - NonnullRefPtr flex_wrap() const { return m_flex_wrap; } + NonnullRefPtr flex_direction() const { return m_properties.flex_direction; } + NonnullRefPtr flex_wrap() const { return m_properties.flex_wrap; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(FlexFlowStyleValue const& other) const { return m_properties == other.m_properties; }; private: FlexFlowStyleValue(NonnullRefPtr flex_direction, NonnullRefPtr flex_wrap) - : StyleValue(Type::FlexFlow) - , m_flex_direction(flex_direction) - , m_flex_wrap(flex_wrap) + : StyleValueWithDefaultOperators(Type::FlexFlow) + , m_properties { .flex_direction = flex_direction, .flex_wrap = flex_wrap } { } - NonnullRefPtr m_flex_direction; - NonnullRefPtr m_flex_wrap; + struct Properties { + NonnullRefPtr flex_direction; + NonnullRefPtr flex_wrap; + bool operator==(Properties const&) const = default; + } m_properties; }; -class FontStyleValue final : public StyleValue { +class FontStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr font_stretch, NonnullRefPtr font_style, NonnullRefPtr font_weight, NonnullRefPtr font_size, NonnullRefPtr line_height, NonnullRefPtr font_families) { return adopt_ref(*new FontStyleValue(font_stretch, font_style, font_weight, font_size, line_height, font_families)); } virtual ~FontStyleValue() override = default; - NonnullRefPtr font_stretch() const { return m_font_stretch; } - NonnullRefPtr font_style() const { return m_font_style; } - NonnullRefPtr font_weight() const { return m_font_weight; } - NonnullRefPtr font_size() const { return m_font_size; } - NonnullRefPtr line_height() const { return m_line_height; } - NonnullRefPtr font_families() const { return m_font_families; } + NonnullRefPtr font_stretch() const { return m_properties.font_stretch; } + NonnullRefPtr font_style() const { return m_properties.font_style; } + NonnullRefPtr font_weight() const { return m_properties.font_weight; } + NonnullRefPtr font_size() const { return m_properties.font_size; } + NonnullRefPtr line_height() const { return m_properties.line_height; } + NonnullRefPtr font_families() const { return m_properties.font_families; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(FontStyleValue const& other) const { return m_properties == other.m_properties; }; private: FontStyleValue(NonnullRefPtr font_stretch, NonnullRefPtr font_style, NonnullRefPtr font_weight, NonnullRefPtr font_size, NonnullRefPtr line_height, NonnullRefPtr font_families) - : StyleValue(Type::Font) - , m_font_stretch(font_stretch) - , m_font_style(font_style) - , m_font_weight(font_weight) - , m_font_size(font_size) - , m_line_height(line_height) - , m_font_families(font_families) + : StyleValueWithDefaultOperators(Type::Font) + , m_properties { .font_stretch = font_stretch, .font_style = font_style, .font_weight = font_weight, .font_size = font_size, .line_height = line_height, .font_families = font_families } { } - NonnullRefPtr m_font_stretch; - NonnullRefPtr m_font_style; - NonnullRefPtr m_font_weight; - NonnullRefPtr m_font_size; - NonnullRefPtr m_line_height; - NonnullRefPtr m_font_families; - // FIXME: Implement font-variant. + struct Properties { + NonnullRefPtr font_stretch; + NonnullRefPtr font_style; + NonnullRefPtr font_weight; + NonnullRefPtr font_size; + NonnullRefPtr line_height; + NonnullRefPtr font_families; + // FIXME: Implement font-variant. + bool operator==(Properties const&) const = default; + } m_properties; }; -class FrequencyStyleValue : public StyleValue { +class FrequencyStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Frequency frequency) { @@ -1058,11 +1086,12 @@ public: Frequency const& frequency() const { return m_frequency; } virtual ErrorOr to_string() const override { return m_frequency.to_string(); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(FrequencyStyleValue const& other) const { return m_frequency == other.m_frequency; }; private: explicit FrequencyStyleValue(Frequency frequency) - : StyleValue(Type::Frequency) + : StyleValueWithDefaultOperators(Type::Frequency) , m_frequency(move(frequency)) { } @@ -1070,18 +1099,19 @@ private: Frequency m_frequency; }; -class GridTemplateAreaStyleValue final : public StyleValue { +class GridTemplateAreaStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Vector> grid_template_area); virtual ~GridTemplateAreaStyleValue() override = default; Vector> const& grid_template_area() const { return m_grid_template_area; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(GridTemplateAreaStyleValue const& other) const { return m_grid_template_area == other.m_grid_template_area; }; private: explicit GridTemplateAreaStyleValue(Vector> grid_template_area) - : StyleValue(Type::GridTemplateArea) + : StyleValueWithDefaultOperators(Type::GridTemplateArea) , m_grid_template_area(grid_template_area) { } @@ -1089,18 +1119,19 @@ private: Vector> m_grid_template_area; }; -class GridTrackPlacementStyleValue final : public StyleValue { +class GridTrackPlacementStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(CSS::GridTrackPlacement grid_track_placement); virtual ~GridTrackPlacementStyleValue() override = default; CSS::GridTrackPlacement const& grid_track_placement() const { return m_grid_track_placement; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(GridTrackPlacementStyleValue const& other) const { return m_grid_track_placement == other.m_grid_track_placement; }; private: explicit GridTrackPlacementStyleValue(CSS::GridTrackPlacement grid_track_placement) - : StyleValue(Type::GridTrackPlacement) + : StyleValueWithDefaultOperators(Type::GridTrackPlacement) , m_grid_track_placement(grid_track_placement) { } @@ -1108,7 +1139,7 @@ private: CSS::GridTrackPlacement m_grid_track_placement; }; -class GridTrackPlacementShorthandStyleValue final : public StyleValue { +class GridTrackPlacementShorthandStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr start, NonnullRefPtr end) { @@ -1120,25 +1151,28 @@ public: } virtual ~GridTrackPlacementShorthandStyleValue() override = default; - NonnullRefPtr start() const { return m_start; } - NonnullRefPtr end() const { return m_end; } + NonnullRefPtr start() const { return m_properties.start; } + NonnullRefPtr end() const { return m_properties.end; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(GridTrackPlacementShorthandStyleValue const& other) const { return m_properties == other.m_properties; }; private: GridTrackPlacementShorthandStyleValue(NonnullRefPtr start, NonnullRefPtr end) - : StyleValue(Type::GridTrackPlacementShorthand) - , m_start(start) - , m_end(end) + : StyleValueWithDefaultOperators(Type::GridTrackPlacementShorthand) + , m_properties { .start = start, .end = end } { } - NonnullRefPtr m_start; - NonnullRefPtr m_end; + struct Properties { + NonnullRefPtr start; + NonnullRefPtr end; + bool operator==(Properties const&) const = default; + } m_properties; }; -class GridAreaShorthandStyleValue final : public StyleValue { +class GridAreaShorthandStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr row_start, NonnullRefPtr column_start, NonnullRefPtr row_end, NonnullRefPtr column_end) { @@ -1150,31 +1184,32 @@ public: } virtual ~GridAreaShorthandStyleValue() override = default; - NonnullRefPtr row_start() const { return m_row_start; } - NonnullRefPtr column_start() const { return m_column_start; } - NonnullRefPtr row_end() const { return m_row_end; } - NonnullRefPtr column_end() const { return m_column_end; } + NonnullRefPtr row_start() const { return m_properties.row_start; } + NonnullRefPtr column_start() const { return m_properties.column_start; } + NonnullRefPtr row_end() const { return m_properties.row_end; } + NonnullRefPtr column_end() const { return m_properties.column_end; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(GridAreaShorthandStyleValue const& other) const { return m_properties == other.m_properties; } private: GridAreaShorthandStyleValue(NonnullRefPtr row_start, NonnullRefPtr column_start, NonnullRefPtr row_end, NonnullRefPtr column_end) - : StyleValue(Type::GridAreaShorthand) - , m_row_start(row_start) - , m_column_start(column_start) - , m_row_end(row_end) - , m_column_end(column_end) + : StyleValueWithDefaultOperators(Type::GridAreaShorthand) + , m_properties { .row_start = row_start, .column_start = column_start, .row_end = row_end, .column_end = column_end } { } - NonnullRefPtr m_row_start; - NonnullRefPtr m_column_start; - NonnullRefPtr m_row_end; - NonnullRefPtr m_column_end; + struct Properties { + NonnullRefPtr row_start; + NonnullRefPtr column_start; + NonnullRefPtr row_end; + NonnullRefPtr column_end; + bool operator==(Properties const&) const = default; + } m_properties; }; -class GridTrackSizeStyleValue final : public StyleValue { +class GridTrackSizeStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(CSS::GridTrackSizeList grid_track_size_list); virtual ~GridTrackSizeStyleValue() override = default; @@ -1184,11 +1219,12 @@ public: CSS::GridTrackSizeList grid_track_size_list() const { return m_grid_track_size_list; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(GridTrackSizeStyleValue const& other) const { return m_grid_track_size_list == other.m_grid_track_size_list; } private: explicit GridTrackSizeStyleValue(CSS::GridTrackSizeList grid_track_size_list) - : StyleValue(Type::GridTrackSizeList) + : StyleValueWithDefaultOperators(Type::GridTrackSizeList) , m_grid_track_size_list(grid_track_size_list) { } @@ -1196,7 +1232,7 @@ private: CSS::GridTrackSizeList m_grid_track_size_list; }; -class IdentifierStyleValue final : public StyleValue { +class IdentifierStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(CSS::ValueID id) { @@ -1212,11 +1248,12 @@ public: virtual bool has_color() const override; virtual Color to_color(Layout::NodeWithStyle const& node) const override; virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(IdentifierStyleValue const& other) const { return m_id == other.m_id; } private: explicit IdentifierStyleValue(CSS::ValueID id) - : StyleValue(Type::Identifier) + : StyleValueWithDefaultOperators(Type::Identifier) , m_id(id) { } @@ -1246,7 +1283,7 @@ public: virtual ~ImageStyleValue() override = default; virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + virtual bool operator==(StyleValue const& other) const override; virtual void load_any_resources(DOM::Document&) override; @@ -1317,11 +1354,11 @@ public: void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override; - virtual bool equals(StyleValue const& other) const override; + virtual bool operator==(StyleValue const& other) const override; Vector const& color_stop_list() const { - return m_color_stop_list; + return m_properties.color_stop_list; } bool is_paintable() const override { return true; } @@ -1330,26 +1367,25 @@ public: Gfx::FloatSize resolve_size(Layout::Node const&, Gfx::FloatPoint, Gfx::FloatRect const&) const; - bool is_repeating() const { return m_repeating == GradientRepeating::Yes; } + bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; } virtual ~RadialGradientStyleValue() override = default; private: RadialGradientStyleValue(EndingShape ending_shape, Size size, PositionValue position, Vector color_stop_list, GradientRepeating repeating) : AbstractImageStyleValue(Type::RadialGradient) - , m_ending_shape(ending_shape) - , m_size(size) - , m_position(position) - , m_color_stop_list(move(color_stop_list)) - , m_repeating(repeating) + , m_properties { .ending_shape = ending_shape, .size = size, .position = position, .color_stop_list = move(color_stop_list), .repeating = repeating } { } - EndingShape m_ending_shape; - Size m_size; - PositionValue m_position; - Vector m_color_stop_list; - GradientRepeating m_repeating; + struct Properties { + EndingShape ending_shape; + Size size; + PositionValue position; + Vector color_stop_list; + GradientRepeating repeating; + bool operator==(Properties const&) const = default; + } m_properties; struct ResolvedData { Painting::RadialGradientData data; @@ -1372,11 +1408,11 @@ public: void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override; - virtual bool equals(StyleValue const& other) const override; + virtual bool operator==(StyleValue const& other) const override; Vector const& color_stop_list() const { - return m_color_stop_list; + return m_properties.color_stop_list; } float angle_degrees() const; @@ -1387,23 +1423,23 @@ public: virtual ~ConicGradientStyleValue() override = default; - bool is_repeating() const { return m_repeating == GradientRepeating::Yes; } + bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; } private: ConicGradientStyleValue(Angle from_angle, PositionValue position, Vector color_stop_list, GradientRepeating repeating) : AbstractImageStyleValue(Type::ConicGradient) - , m_from_angle(from_angle) - , m_position(position) - , m_color_stop_list(move(color_stop_list)) - , m_repeating(repeating) + , m_properties { .from_angle = from_angle, .position = position, .color_stop_list = move(color_stop_list), .repeating = repeating } { } - // FIXME: Support - Angle m_from_angle; - PositionValue m_position; - Vector m_color_stop_list; - GradientRepeating m_repeating; + struct Properties { + // FIXME: Support + Angle from_angle; + PositionValue position; + Vector color_stop_list; + GradientRepeating repeating; + bool operator==(Properties const&) const = default; + } m_properties; struct ResolvedData { Painting::ConicGradientData data; @@ -1430,14 +1466,14 @@ public: virtual ErrorOr to_string() const override; virtual ~LinearGradientStyleValue() override = default; - virtual bool equals(StyleValue const& other) const override; + virtual bool operator==(StyleValue const& other) const override; Vector const& color_stop_list() const { - return m_color_stop_list; + return m_properties.color_stop_list; } - bool is_repeating() const { return m_repeating == GradientRepeating::Yes; } + bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; } float angle_degrees(CSSPixelSize gradient_size) const; @@ -1449,17 +1485,17 @@ public: private: LinearGradientStyleValue(GradientDirection direction, Vector color_stop_list, GradientType type, GradientRepeating repeating) : AbstractImageStyleValue(Type::LinearGradient) - , m_direction(direction) - , m_color_stop_list(move(color_stop_list)) - , m_gradient_type(type) - , m_repeating(repeating) + , m_properties { .direction = direction, .color_stop_list = move(color_stop_list), .gradient_type = type, .repeating = repeating } { } - GradientDirection m_direction; - Vector m_color_stop_list; - GradientType m_gradient_type; - GradientRepeating m_repeating; + struct Properties { + GradientDirection direction; + Vector color_stop_list; + GradientType gradient_type; + GradientRepeating repeating; + bool operator==(Properties const&) const = default; + } m_properties; struct ResolvedData { Painting::LinearGradientData data; @@ -1469,7 +1505,7 @@ private: mutable Optional m_resolved; }; -class InheritStyleValue final : public StyleValue { +class InheritStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr the() { @@ -1479,16 +1515,17 @@ public: virtual ~InheritStyleValue() override = default; ErrorOr to_string() const override { return String::from_utf8("inherit"sv); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(InheritStyleValue const&) const { return true; } private: InheritStyleValue() - : StyleValue(Type::Inherit) + : StyleValueWithDefaultOperators(Type::Inherit) { } }; -class InitialStyleValue final : public StyleValue { +class InitialStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr the() { @@ -1498,16 +1535,17 @@ public: virtual ~InitialStyleValue() override = default; ErrorOr to_string() const override { return String::from_utf8("initial"sv); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(InitialStyleValue const&) const { return true; } private: InitialStyleValue() - : StyleValue(Type::Initial) + : StyleValueWithDefaultOperators(Type::Initial) { } }; -class LengthStyleValue : public StyleValue { +class LengthStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Length const&); virtual ~LengthStyleValue() override = default; @@ -1521,11 +1559,12 @@ public: virtual Length to_length() const override { return m_length; } virtual ValueID to_identifier() const override { return has_auto() ? ValueID::Auto : ValueID::Invalid; } virtual NonnullRefPtr absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(LengthStyleValue const& other) const { return m_length == other.m_length; } private: explicit LengthStyleValue(Length const& length) - : StyleValue(Type::Length) + : StyleValueWithDefaultOperators(Type::Length) , m_length(length) { } @@ -1533,7 +1572,7 @@ private: Length m_length; }; -class ListStyleStyleValue final : public StyleValue { +class ListStyleStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( NonnullRefPtr position, @@ -1544,31 +1583,33 @@ public: } virtual ~ListStyleStyleValue() override = default; - NonnullRefPtr position() const { return m_position; } - NonnullRefPtr image() const { return m_image; } - NonnullRefPtr style_type() const { return m_style_type; } + NonnullRefPtr position() const { return m_properties.position; } + NonnullRefPtr image() const { return m_properties.image; } + NonnullRefPtr style_type() const { return m_properties.style_type; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(ListStyleStyleValue const& other) const { return m_properties == other.m_properties; } private: ListStyleStyleValue( NonnullRefPtr position, NonnullRefPtr image, NonnullRefPtr style_type) - : StyleValue(Type::ListStyle) - , m_position(position) - , m_image(image) - , m_style_type(style_type) + : StyleValueWithDefaultOperators(Type::ListStyle) + , m_properties { .position = position, .image = image, .style_type = style_type } { } - NonnullRefPtr m_position; - NonnullRefPtr m_image; - NonnullRefPtr m_style_type; + struct Properties { + NonnullRefPtr position; + NonnullRefPtr image; + NonnullRefPtr style_type; + bool operator==(Properties const&) const = default; + } m_properties; }; -class NumericStyleValue : public StyleValue { +class NumericStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create_float(float value) { @@ -1595,11 +1636,12 @@ public: virtual float to_integer() const override { return m_value.get(); } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(NumericStyleValue const& other) const { return m_value == other.m_value; } private: explicit NumericStyleValue(Variant value) - : StyleValue(Type::Numeric) + : StyleValueWithDefaultOperators(Type::Numeric) , m_value(move(value)) { } @@ -1607,7 +1649,7 @@ private: Variant m_value { (i64)0 }; }; -class OverflowStyleValue final : public StyleValue { +class OverflowStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y) { @@ -1615,25 +1657,28 @@ public: } virtual ~OverflowStyleValue() override = default; - NonnullRefPtr overflow_x() const { return m_overflow_x; } - NonnullRefPtr overflow_y() const { return m_overflow_y; } + NonnullRefPtr overflow_x() const { return m_properties.overflow_x; } + NonnullRefPtr overflow_y() const { return m_properties.overflow_y; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(OverflowStyleValue const& other) const { return m_properties == other.m_properties; } private: OverflowStyleValue(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y) - : StyleValue(Type::Overflow) - , m_overflow_x(overflow_x) - , m_overflow_y(overflow_y) + : StyleValueWithDefaultOperators(Type::Overflow) + , m_properties { .overflow_x = overflow_x, .overflow_y = overflow_y } { } - NonnullRefPtr m_overflow_x; - NonnullRefPtr m_overflow_y; + struct Properties { + NonnullRefPtr overflow_x; + NonnullRefPtr overflow_y; + bool operator==(Properties const&) const = default; + } m_properties; }; -class PercentageStyleValue final : public StyleValue { +class PercentageStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Percentage percentage) { @@ -1645,11 +1690,12 @@ public: Percentage& percentage() { return m_percentage; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(PercentageStyleValue const& other) const { return m_percentage == other.m_percentage; } private: PercentageStyleValue(Percentage&& percentage) - : StyleValue(Type::Percentage) + : StyleValueWithDefaultOperators(Type::Percentage) , m_percentage(percentage) { } @@ -1657,7 +1703,7 @@ private: Percentage m_percentage; }; -class PositionStyleValue final : public StyleValue { +class PositionStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(PositionEdge edge_x, LengthPercentage const& offset_x, PositionEdge edge_y, LengthPercentage const& offset_y) { @@ -1665,31 +1711,32 @@ public: } virtual ~PositionStyleValue() override = default; - PositionEdge edge_x() const { return m_edge_x; } - LengthPercentage const& offset_x() const { return m_offset_x; } - PositionEdge edge_y() const { return m_edge_y; } - LengthPercentage const& offset_y() const { return m_offset_y; } + PositionEdge edge_x() const { return m_properties.edge_x; } + LengthPercentage const& offset_x() const { return m_properties.offset_x; } + PositionEdge edge_y() const { return m_properties.edge_y; } + LengthPercentage const& offset_y() const { return m_properties.offset_y; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(PositionStyleValue const& other) const { return m_properties == other.m_properties; } private: PositionStyleValue(PositionEdge edge_x, LengthPercentage const& offset_x, PositionEdge edge_y, LengthPercentage const& offset_y) - : StyleValue(Type::Position) - , m_edge_x(edge_x) - , m_offset_x(offset_x) - , m_edge_y(edge_y) - , m_offset_y(offset_y) + : StyleValueWithDefaultOperators(Type::Position) + , m_properties { .edge_x = edge_x, .offset_x = offset_x, .edge_y = edge_y, .offset_y = offset_y } { } - PositionEdge m_edge_x; - LengthPercentage m_offset_x; - PositionEdge m_edge_y; - LengthPercentage m_offset_y; + struct Properties { + PositionEdge edge_x; + LengthPercentage offset_x; + PositionEdge edge_y; + LengthPercentage offset_y; + bool operator==(Properties const&) const = default; + } m_properties; }; -class ResolutionStyleValue : public StyleValue { +class ResolutionStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Resolution resolution) { @@ -1700,11 +1747,12 @@ public: Resolution const& resolution() const { return m_resolution; } virtual ErrorOr to_string() const override { return m_resolution.to_string(); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(ResolutionStyleValue const& other) const { return m_resolution == other.m_resolution; } private: explicit ResolutionStyleValue(Resolution resolution) - : StyleValue(Type::Resolution) + : StyleValueWithDefaultOperators(Type::Resolution) , m_resolution(move(resolution)) { } @@ -1712,7 +1760,7 @@ private: Resolution m_resolution; }; -class ShadowStyleValue final : public StyleValue { +class ShadowStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Color color, Length const& offset_x, Length const& offset_y, Length const& blur_radius, Length const& spread_distance, ShadowPlacement placement) @@ -1721,39 +1769,38 @@ public: } virtual ~ShadowStyleValue() override = default; - Color color() const { return m_color; } - Length const& offset_x() const { return m_offset_x; } - Length const& offset_y() const { return m_offset_y; } - Length const& blur_radius() const { return m_blur_radius; } - Length const& spread_distance() const { return m_spread_distance; } - ShadowPlacement placement() const { return m_placement; } + Color color() const { return m_properties.color; } + Length const& offset_x() const { return m_properties.offset_x; } + Length const& offset_y() const { return m_properties.offset_y; } + Length const& blur_radius() const { return m_properties.blur_radius; } + Length const& spread_distance() const { return m_properties.spread_distance; } + ShadowPlacement placement() const { return m_properties.placement; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(ShadowStyleValue const& other) const { return m_properties == other.m_properties; } private: explicit ShadowStyleValue(Color color, Length const& offset_x, Length const& offset_y, Length const& blur_radius, Length const& spread_distance, ShadowPlacement placement) - : StyleValue(Type::Shadow) - , m_color(color) - , m_offset_x(offset_x) - , m_offset_y(offset_y) - , m_blur_radius(blur_radius) - , m_spread_distance(spread_distance) - , m_placement(placement) + : StyleValueWithDefaultOperators(Type::Shadow) + , m_properties { .color = color, .offset_x = offset_x, .offset_y = offset_y, .blur_radius = blur_radius, .spread_distance = spread_distance, .placement = placement } { } virtual NonnullRefPtr absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override; - Color m_color; - Length m_offset_x; - Length m_offset_y; - Length m_blur_radius; - Length m_spread_distance; - ShadowPlacement m_placement; + struct Properties { + Color color; + Length offset_x; + Length offset_y; + Length blur_radius; + Length spread_distance; + ShadowPlacement placement; + bool operator==(Properties const&) const = default; + } m_properties; }; -class StringStyleValue : public StyleValue { +class StringStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(String const& string) { @@ -1762,11 +1809,12 @@ public: virtual ~StringStyleValue() override = default; ErrorOr to_string() const override { return m_string; } - virtual bool equals(StyleValue const& other) const override; + + bool equals(StringStyleValue const& other) const { return m_string == other.m_string; } private: explicit StringStyleValue(String const& string) - : StyleValue(Type::String) + : StyleValueWithDefaultOperators(Type::String) , m_string(string) { } @@ -1774,7 +1822,7 @@ private: String m_string; }; -class TextDecorationStyleValue final : public StyleValue { +class TextDecorationStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create( NonnullRefPtr line, @@ -1786,13 +1834,14 @@ public: } virtual ~TextDecorationStyleValue() override = default; - NonnullRefPtr line() const { return m_line; } - NonnullRefPtr thickness() const { return m_thickness; } - NonnullRefPtr style() const { return m_style; } - NonnullRefPtr color() const { return m_color; } + NonnullRefPtr line() const { return m_properties.line; } + NonnullRefPtr thickness() const { return m_properties.thickness; } + NonnullRefPtr style() const { return m_properties.style; } + NonnullRefPtr color() const { return m_properties.color; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(TextDecorationStyleValue const& other) const { return m_properties == other.m_properties; } private: TextDecorationStyleValue( @@ -1800,21 +1849,21 @@ private: NonnullRefPtr thickness, NonnullRefPtr style, NonnullRefPtr color) - : StyleValue(Type::TextDecoration) - , m_line(line) - , m_thickness(thickness) - , m_style(style) - , m_color(color) + : StyleValueWithDefaultOperators(Type::TextDecoration) + , m_properties { .line = line, .thickness = thickness, .style = style, .color = color } { } - NonnullRefPtr m_line; - NonnullRefPtr m_thickness; - NonnullRefPtr m_style; - NonnullRefPtr m_color; + struct Properties { + NonnullRefPtr line; + NonnullRefPtr thickness; + NonnullRefPtr style; + NonnullRefPtr color; + bool operator==(Properties const&) const = default; + } m_properties; }; -class TimeStyleValue : public StyleValue { +class TimeStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(Time time) { @@ -1825,11 +1874,12 @@ public: Time const& time() const { return m_time; } virtual ErrorOr to_string() const override { return m_time.to_string(); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(TimeStyleValue const& other) const { return m_time == other.m_time; } private: explicit TimeStyleValue(Time time) - : StyleValue(Type::Time) + : StyleValueWithDefaultOperators(Type::Time) , m_time(move(time)) { } @@ -1837,7 +1887,7 @@ private: Time m_time; }; -class TransformationStyleValue final : public StyleValue { +class TransformationStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(CSS::TransformFunction transform_function, NonnullRefPtrVector&& values) { @@ -1845,22 +1895,25 @@ public: } virtual ~TransformationStyleValue() override = default; - CSS::TransformFunction transform_function() const { return m_transform_function; } - NonnullRefPtrVector values() const { return m_values; } + CSS::TransformFunction transform_function() const { return m_properties.transform_function; } + NonnullRefPtrVector values() const { return m_properties.values; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(TransformationStyleValue const& other) const { return m_properties == other.m_properties; } private: TransformationStyleValue(CSS::TransformFunction transform_function, NonnullRefPtrVector&& values) - : StyleValue(Type::Transformation) - , m_transform_function(transform_function) - , m_values(move(values)) + : StyleValueWithDefaultOperators(Type::Transformation) + , m_properties { .transform_function = transform_function, .values = move(values) } { } - CSS::TransformFunction m_transform_function; - NonnullRefPtrVector m_values; + struct Properties { + CSS::TransformFunction transform_function; + NonnullRefPtrVector values; + bool operator==(Properties const& other) const; + } m_properties; }; class UnresolvedStyleValue final : public StyleValue { @@ -1872,11 +1925,12 @@ public: virtual ~UnresolvedStyleValue() override = default; virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; Vector const& values() const { return m_values; } bool contains_var_or_attr() const { return m_contains_var_or_attr; } + virtual bool operator==(StyleValue const& other) const override; + private: UnresolvedStyleValue(Vector&& values, bool contains_var_or_attr) : StyleValue(Type::Unresolved) @@ -1889,7 +1943,7 @@ private: bool m_contains_var_or_attr { false }; }; -class UnsetStyleValue final : public StyleValue { +class UnsetStyleValue final : public StyleValueWithDefaultOperators { public: static NonnullRefPtr the() { @@ -1899,16 +1953,17 @@ public: virtual ~UnsetStyleValue() override = default; ErrorOr to_string() const override { return String::from_utf8("unset"sv); } - virtual bool equals(StyleValue const& other) const override; + + bool equals(UnsetStyleValue const&) const { return true; } private: UnsetStyleValue() - : StyleValue(Type::Unset) + : StyleValueWithDefaultOperators(Type::Unset) { } }; -class StyleValueList final : public StyleValue { +class StyleValueList final : public StyleValueWithDefaultOperators { public: enum class Separator { Space, @@ -1916,31 +1971,34 @@ public: }; static NonnullRefPtr create(NonnullRefPtrVector&& values, Separator separator) { return adopt_ref(*new StyleValueList(move(values), separator)); } - size_t size() const { return m_values.size(); } - NonnullRefPtrVector const& values() const { return m_values; } + size_t size() const { return m_properties.values.size(); } + NonnullRefPtrVector const& values() const { return m_properties.values; } NonnullRefPtr value_at(size_t i, bool allow_loop) const { if (allow_loop) - return m_values[i % size()]; - return m_values[i]; + return m_properties.values[i % size()]; + return m_properties.values[i]; } virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; + + bool equals(StyleValueList const& other) const { return m_properties == other.m_properties; } private: StyleValueList(NonnullRefPtrVector&& values, Separator separator) - : StyleValue(Type::ValueList) - , m_separator(separator) - , m_values(move(values)) + : StyleValueWithDefaultOperators(Type::ValueList) + , m_properties { .separator = separator, .values = move(values) } { } - Separator m_separator; - NonnullRefPtrVector m_values; + struct Properties { + Separator separator; + NonnullRefPtrVector values; + bool operator==(Properties const&) const; + } m_properties; }; -class RectStyleValue : public StyleValue { +class RectStyleValue : public StyleValueWithDefaultOperators { public: static NonnullRefPtr create(EdgeRect rect); virtual ~RectStyleValue() override = default; @@ -1949,11 +2007,12 @@ public: virtual ErrorOr to_string() const override; virtual bool has_rect() const override { return true; } virtual EdgeRect to_rect() const override { return m_rect; } - virtual bool equals(StyleValue const& other) const override; + + bool equals(RectStyleValue const& other) const { return m_rect == other.m_rect; } private: explicit RectStyleValue(EdgeRect rect) - : StyleValue(Type::Rect) + : StyleValueWithDefaultOperators(Type::Rect) , m_rect(rect) { }