| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-08-02 14:28:24 +02:00
										 |  |  |  * Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2025-05-16 20:02:16 +01:00
										 |  |  |  * Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-01 17:17:32 +02:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 19:02:26 +01:00
										 |  |  | #include <AK/String.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | #include <LibGfx/Forward.h>
 | 
					
						
							| 
									
										
										
										
											2023-06-02 12:39:39 +02:00
										 |  |  | #include <LibGfx/Rect.h>
 | 
					
						
							| 
									
										
										
										
											2025-05-16 20:02:16 +01:00
										 |  |  | #include <LibWeb/CSS/SerializationMode.h>
 | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  | #include <LibWeb/CSS/Units.h>
 | 
					
						
							| 
									
										
										
										
											2025-07-19 19:35:33 -07:00
										 |  |  | #include <LibWeb/Export.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | #include <LibWeb/Forward.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-24 17:16:08 +01:00
										 |  |  | #include <LibWeb/PixelUnits.h>
 | 
					
						
							| 
									
										
										
										
											2019-07-03 07:55:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  | namespace Web::CSS { | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-19 19:35:33 -07:00
										 |  |  | class WEB_API Length { | 
					
						
							| 
									
										
										
										
											2019-07-01 17:17:32 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  |     struct FontMetrics { | 
					
						
							| 
									
										
										
										
											2025-09-23 00:18:51 +12:00
										 |  |  |         FontMetrics(CSSPixels font_size, Gfx::FontPixelMetrics const&, CSSPixels line_height); | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         CSSPixels font_size; | 
					
						
							|  |  |  |         CSSPixels x_height; | 
					
						
							| 
									
										
										
										
											2023-04-28 17:10:30 +01:00
										 |  |  |         CSSPixels cap_height; | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  |         CSSPixels zero_advance; | 
					
						
							|  |  |  |         CSSPixels line_height; | 
					
						
							| 
									
										
										
										
											2025-02-21 16:45:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         bool operator==(FontMetrics const&) const = default; | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-23 12:24:14 +02:00
										 |  |  |     Length(double value, LengthUnit unit) | 
					
						
							|  |  |  |         : m_unit(unit) | 
					
						
							|  |  |  |         , m_value(value) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     ~Length() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] static Length make_px(double value) { return Length(value, LengthUnit::Px); } | 
					
						
							|  |  |  |     [[nodiscard]] static Length make_px(CSSPixels value) { return make_px(value.to_double()); } | 
					
						
							| 
									
										
										
										
											2022-01-14 12:23:54 +00:00
										 |  |  |     Length percentage_of(Percentage const&) const; | 
					
						
							| 
									
										
										
										
											2020-06-24 11:08:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  |     bool is_px() const { return m_unit == LengthUnit::Px; } | 
					
						
							| 
									
										
										
										
											2023-04-26 17:37:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  |     bool is_absolute() const { return CSS::is_absolute(m_unit); } | 
					
						
							|  |  |  |     bool is_font_relative() const { return CSS::is_font_relative(m_unit); } | 
					
						
							|  |  |  |     bool is_viewport_relative() const { return CSS::is_viewport_relative(m_unit); } | 
					
						
							|  |  |  |     bool is_relative() const { return CSS::is_relative(m_unit); } | 
					
						
							| 
									
										
										
										
											2023-04-26 17:37:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-24 10:50:57 +02:00
										 |  |  |     double raw_value() const { return m_value; } | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  |     LengthUnit unit() const { return m_unit; } | 
					
						
							| 
									
										
										
										
											2025-09-11 11:50:59 +01:00
										 |  |  |     FlyString unit_name() const { return CSS::to_string(m_unit); } | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-02 12:39:39 +02:00
										 |  |  |     struct ResolutionContext { | 
					
						
							| 
									
										
										
										
											2025-10-07 00:54:19 +13:00
										 |  |  |         [[nodiscard]] static ResolutionContext for_document(DOM::Document const&); | 
					
						
							| 
									
										
										
										
											2025-07-19 15:38:16 +12:00
										 |  |  |         [[nodiscard]] static ResolutionContext for_element(DOM::AbstractElement const&); | 
					
						
							| 
									
										
										
										
											2025-10-07 00:54:19 +13:00
										 |  |  |         // FIXME: Anywhere we use this we probably want to use `for_document` instead since this uses the window's
 | 
					
						
							|  |  |  |         //        viewport rather than the documents which can differ e.g. with iframes.
 | 
					
						
							| 
									
										
										
										
											2025-02-21 16:45:07 +00:00
										 |  |  |         [[nodiscard]] static ResolutionContext for_window(HTML::Window const&); | 
					
						
							|  |  |  |         [[nodiscard]] static ResolutionContext for_layout_node(Layout::Node const&); | 
					
						
							| 
									
										
										
										
											2023-06-02 12:39:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         CSSPixelRect viewport_rect; | 
					
						
							|  |  |  |         FontMetrics font_metrics; | 
					
						
							|  |  |  |         FontMetrics root_font_metrics; | 
					
						
							| 
									
										
										
										
											2025-02-21 16:45:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         bool operator==(ResolutionContext const&) const = default; | 
					
						
							| 
									
										
										
										
											2023-06-02 12:39:39 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     [[nodiscard]] CSSPixels to_px(ResolutionContext const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-02 11:17:06 +01:00
										 |  |  |     [[nodiscard]] ALWAYS_INLINE CSSPixels to_px(Layout::Node const& node) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_absolute()) | 
					
						
							|  |  |  |             return absolute_length_to_px(); | 
					
						
							|  |  |  |         return to_px_slow_case(node); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  |     ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const | 
					
						
							| 
									
										
										
										
											2020-06-23 23:21:58 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-10-16 15:00:25 +02:00
										 |  |  |         if (is_absolute()) | 
					
						
							|  |  |  |             return absolute_length_to_px(); | 
					
						
							| 
									
										
										
										
											2023-04-28 20:07:41 +01:00
										 |  |  |         if (is_font_relative()) | 
					
						
							|  |  |  |             return font_relative_length_to_px(font_metrics, root_font_metrics); | 
					
						
							|  |  |  |         if (is_viewport_relative()) | 
					
						
							|  |  |  |             return viewport_relative_length_to_px(viewport_rect); | 
					
						
							| 
									
										
										
										
											2024-10-16 15:00:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2021-10-05 15:39:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 17:29:52 +00:00
										 |  |  |     ALWAYS_INLINE CSSPixels absolute_length_to_px() const | 
					
						
							| 
									
										
										
										
											2025-07-31 21:07:03 +12:00
										 |  |  |     { | 
					
						
							|  |  |  |         return CSSPixels::nearest_value_for(absolute_length_to_px_without_rounding()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ALWAYS_INLINE double absolute_length_to_px_without_rounding() const | 
					
						
							| 
									
										
										
										
											2021-10-05 15:39:40 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-04 12:27:20 +01:00
										 |  |  |         return ratio_between_units(m_unit, LengthUnit::Px) * m_value; | 
					
						
							| 
									
										
										
										
											2020-06-23 23:21:58 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-07-01 17:17:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-16 20:02:16 +01:00
										 |  |  |     String to_string(SerializationMode = SerializationMode::Normal) const; | 
					
						
							| 
									
										
										
										
											2019-07-24 07:34:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-30 15:46:05 +01:00
										 |  |  |     bool operator==(Length const& other) const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  |         return m_unit == other.m_unit && m_value == other.m_value; | 
					
						
							| 
									
										
										
										
											2023-03-30 15:46:05 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-15 19:39:33 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-28 20:07:41 +01:00
										 |  |  |     CSSPixels font_relative_length_to_px(FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; | 
					
						
							|  |  |  |     CSSPixels viewport_relative_length_to_px(CSSPixelRect const& viewport_rect) const; | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-30 15:01:23 +01:00
										 |  |  |     // Returns empty optional if it's already absolute.
 | 
					
						
							| 
									
										
										
										
											2023-04-28 16:29:12 +01:00
										 |  |  |     Optional<Length> absolutize(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; | 
					
						
							|  |  |  |     Length absolutized(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const; | 
					
						
							| 
									
										
										
										
											2023-03-30 15:01:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-15 15:18:27 -06:00
										 |  |  |     static Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue const> const&, Layout::Node const&, Length const& reference_value); | 
					
						
							|  |  |  |     static Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue const> const&, Layout::Node const&, CSSPixels reference_value); | 
					
						
							| 
									
										
										
										
											2024-08-02 14:28:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-01 17:17:32 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2024-03-02 11:17:06 +01:00
										 |  |  |     [[nodiscard]] CSSPixels to_px_slow_case(Layout::Node const&) const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-02 13:48:49 +01:00
										 |  |  |     LengthUnit m_unit; | 
					
						
							| 
									
										
										
										
											2023-05-24 10:50:57 +02:00
										 |  |  |     double m_value { 0 }; | 
					
						
							| 
									
										
										
										
											2019-07-01 17:17:32 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2019-08-18 08:09:56 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-28 13:40:39 +01:00
										 |  |  | class LengthOrAuto { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     LengthOrAuto(Length length) | 
					
						
							| 
									
										
										
										
											2025-09-01 14:03:25 +01:00
										 |  |  |         : m_length(move(length)) | 
					
						
							| 
									
										
										
										
											2025-08-28 13:40:39 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static LengthOrAuto make_auto() { return LengthOrAuto { OptionalNone {} }; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool is_length() const { return m_length.has_value(); } | 
					
						
							|  |  |  |     bool is_auto() const { return !m_length.has_value(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Length const& length() const { return m_length.value(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     String to_string(SerializationMode mode = SerializationMode::Normal) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_auto()) | 
					
						
							|  |  |  |             return "auto"_string; | 
					
						
							|  |  |  |         return m_length->to_string(mode); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     CSSPixels to_px_or_zero(Layout::Node const& node) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (is_auto()) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |         return m_length->to_px(node); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool operator==(LengthOrAuto const&) const = default; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     explicit LengthOrAuto(Optional<Length> maybe_length) | 
					
						
							|  |  |  |         : m_length(move(maybe_length)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Optional<Length> m_length; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-19 17:30:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							|  |  |  | struct AK::Formatter<Web::CSS::Length> : Formatter<StringView> { | 
					
						
							|  |  |  |     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Length const& length) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-08-22 12:25:30 +01:00
										 |  |  |         return Formatter<StringView>::format(builder, length.to_string()); | 
					
						
							| 
									
										
										
										
											2022-01-19 17:30:29 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2025-08-28 13:40:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<> | 
					
						
							|  |  |  | struct AK::Formatter<Web::CSS::LengthOrAuto> : Formatter<StringView> { | 
					
						
							|  |  |  |     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::LengthOrAuto const& length_or_auto) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return Formatter<StringView>::format(builder, length_or_auto.to_string()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; |