/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021-2023, Sam Atkins * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2022-2023, MacDue * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Web::CSS { StyleValue::StyleValue(Type type) : m_type(type) { } AbstractImageStyleValue const& StyleValue::as_abstract_image() const { VERIFY(is_abstract_image()); return static_cast(*this); } AngleStyleValue const& StyleValue::as_angle() const { VERIFY(is_angle()); return static_cast(*this); } BackgroundStyleValue const& StyleValue::as_background() const { VERIFY(is_background()); return static_cast(*this); } BackgroundRepeatStyleValue const& StyleValue::as_background_repeat() const { VERIFY(is_background_repeat()); return static_cast(*this); } BackgroundSizeStyleValue const& StyleValue::as_background_size() const { VERIFY(is_background_size()); return static_cast(*this); } BorderStyleValue const& StyleValue::as_border() const { VERIFY(is_border()); return static_cast(*this); } BorderRadiusStyleValue const& StyleValue::as_border_radius() const { VERIFY(is_border_radius()); return static_cast(*this); } BorderRadiusShorthandStyleValue const& StyleValue::as_border_radius_shorthand() const { VERIFY(is_border_radius_shorthand()); return static_cast(*this); } ShadowStyleValue const& StyleValue::as_shadow() const { VERIFY(is_shadow()); return static_cast(*this); } CalculatedStyleValue const& StyleValue::as_calculated() const { VERIFY(is_calculated()); return static_cast(*this); } ColorStyleValue const& StyleValue::as_color() const { VERIFY(is_color()); return static_cast(*this); } ConicGradientStyleValue const& StyleValue::as_conic_gradient() const { VERIFY(is_conic_gradient()); return static_cast(*this); } ContentStyleValue const& StyleValue::as_content() const { VERIFY(is_content()); return static_cast(*this); } FilterValueListStyleValue const& StyleValue::as_filter_value_list() const { VERIFY(is_filter_value_list()); return static_cast(*this); } FlexStyleValue const& StyleValue::as_flex() const { VERIFY(is_flex()); return static_cast(*this); } FlexFlowStyleValue const& StyleValue::as_flex_flow() const { VERIFY(is_flex_flow()); return static_cast(*this); } FontStyleValue const& StyleValue::as_font() const { VERIFY(is_font()); return static_cast(*this); } FrequencyStyleValue const& StyleValue::as_frequency() const { VERIFY(is_frequency()); return static_cast(*this); } GridTrackPlacementShorthandStyleValue const& StyleValue::as_grid_track_placement_shorthand() const { VERIFY(is_grid_track_placement_shorthand()); return static_cast(*this); } GridAreaShorthandStyleValue const& StyleValue::as_grid_area_shorthand() const { VERIFY(is_grid_area_shorthand()); return static_cast(*this); } GridTemplateAreaStyleValue const& StyleValue::as_grid_template_area() const { VERIFY(is_grid_template_area()); return static_cast(*this); } GridTrackPlacementStyleValue const& StyleValue::as_grid_track_placement() const { VERIFY(is_grid_track_placement()); return static_cast(*this); } IdentifierStyleValue const& StyleValue::as_identifier() const { VERIFY(is_identifier()); return static_cast(*this); } ImageStyleValue const& StyleValue::as_image() const { VERIFY(is_image()); return static_cast(*this); } InheritStyleValue const& StyleValue::as_inherit() const { VERIFY(is_inherit()); return static_cast(*this); } InitialStyleValue const& StyleValue::as_initial() const { VERIFY(is_initial()); return static_cast(*this); } LengthStyleValue const& StyleValue::as_length() const { VERIFY(is_length()); return static_cast(*this); } GridTrackSizeStyleValue const& StyleValue::as_grid_track_size_list() const { VERIFY(is_grid_track_size_list()); return static_cast(*this); } LinearGradientStyleValue const& StyleValue::as_linear_gradient() const { VERIFY(is_linear_gradient()); return static_cast(*this); } ListStyleStyleValue const& StyleValue::as_list_style() const { VERIFY(is_list_style()); return static_cast(*this); } NumericStyleValue const& StyleValue::as_numeric() const { VERIFY(is_numeric()); return static_cast(*this); } OverflowStyleValue const& StyleValue::as_overflow() const { VERIFY(is_overflow()); return static_cast(*this); } PercentageStyleValue const& StyleValue::as_percentage() const { VERIFY(is_percentage()); return static_cast(*this); } PositionStyleValue const& StyleValue::as_position() const { VERIFY(is_position()); return static_cast(*this); } RadialGradientStyleValue const& StyleValue::as_radial_gradient() const { VERIFY(is_radial_gradient()); return static_cast(*this); } RectStyleValue const& StyleValue::as_rect() const { VERIFY(is_rect()); return static_cast(*this); } ResolutionStyleValue const& StyleValue::as_resolution() const { VERIFY(is_resolution()); return static_cast(*this); } StringStyleValue const& StyleValue::as_string() const { VERIFY(is_string()); return static_cast(*this); } TextDecorationStyleValue const& StyleValue::as_text_decoration() const { VERIFY(is_text_decoration()); return static_cast(*this); } TimeStyleValue const& StyleValue::as_time() const { VERIFY(is_time()); return static_cast(*this); } TransformationStyleValue const& StyleValue::as_transformation() const { VERIFY(is_transformation()); return static_cast(*this); } UnresolvedStyleValue const& StyleValue::as_unresolved() const { VERIFY(is_unresolved()); return static_cast(*this); } UnsetStyleValue const& StyleValue::as_unset() const { VERIFY(is_unset()); return static_cast(*this); } StyleValueList const& StyleValue::as_value_list() const { VERIFY(is_value_list()); return static_cast(*this); } void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) { add_or_subtract_internal(SumOperation::Add, other, layout_node, percentage_basis); } void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) { add_or_subtract_internal(SumOperation::Subtract, other, layout_node, percentage_basis); } void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) { // We know from validation when resolving the type, that "both sides have the same type, or that one side is a and the other is an ". // Though, having the same type may mean that one side is a and the other a . // Note: This is almost identical to ::add() m_value.visit( [&](Number const& number) { auto other_number = other.m_value.get(); if (op == SumOperation::Add) { m_value = number + other_number; } else { m_value = number - other_number; } }, [&](Angle const& angle) { auto this_degrees = angle.to_degrees(); if (other.m_value.has()) { auto other_degrees = other.m_value.get().to_degrees(); if (op == SumOperation::Add) m_value = Angle::make_degrees(this_degrees + other_degrees); else m_value = Angle::make_degrees(this_degrees - other_degrees); } else { VERIFY(percentage_basis.has()); auto other_degrees = percentage_basis.get().percentage_of(other.m_value.get()).to_degrees(); if (op == SumOperation::Add) m_value = Angle::make_degrees(this_degrees + other_degrees); else m_value = Angle::make_degrees(this_degrees - other_degrees); } }, [&](Frequency const& frequency) { auto this_hertz = frequency.to_hertz(); if (other.m_value.has()) { auto other_hertz = other.m_value.get().to_hertz(); if (op == SumOperation::Add) m_value = Frequency::make_hertz(this_hertz + other_hertz); else m_value = Frequency::make_hertz(this_hertz - other_hertz); } else { VERIFY(percentage_basis.has()); auto other_hertz = percentage_basis.get().percentage_of(other.m_value.get()).to_hertz(); if (op == SumOperation::Add) m_value = Frequency::make_hertz(this_hertz + other_hertz); else m_value = Frequency::make_hertz(this_hertz - other_hertz); } }, [&](Length const& length) { auto this_px = length.to_px(*layout_node); if (other.m_value.has()) { auto other_px = other.m_value.get().to_px(*layout_node); if (op == SumOperation::Add) m_value = Length::make_px(this_px + other_px); else m_value = Length::make_px(this_px - other_px); } else { VERIFY(percentage_basis.has()); auto other_px = percentage_basis.get().percentage_of(other.m_value.get()).to_px(*layout_node); if (op == SumOperation::Add) m_value = Length::make_px(this_px + other_px); else m_value = Length::make_px(this_px - other_px); } }, [&](Time const& time) { auto this_seconds = time.to_seconds(); if (other.m_value.has