| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-08-09 21:28:56 +02:00
										 |  |  |  * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> | 
					
						
							| 
									
										
										
										
											2022-01-19 17:00:50 +00:00
										 |  |  |  * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 00:50:16 +02:00
										 |  |  | #include <AK/NonnullOwnPtr.h>
 | 
					
						
							|  |  |  | #include <AK/Variant.h>
 | 
					
						
							| 
									
										
										
										
											2022-04-09 09:28:38 +02:00
										 |  |  | #include <LibGfx/Font/Font.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | #include <LibGfx/Rect.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | #include <LibWeb/CSS/Length.h>
 | 
					
						
							| 
									
										
										
										
											2022-01-14 12:23:54 +00:00
										 |  |  | #include <LibWeb/CSS/Percentage.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | #include <LibWeb/DOM/Document.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-18 15:01:28 +01:00
										 |  |  | #include <LibWeb/HTML/BrowsingContext.h>
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:08:16 +02:00
										 |  |  | #include <LibWeb/HTML/HTMLHtmlElement.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 20:01:35 +02:00
										 |  |  | namespace Web::CSS { | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 22:57:35 +02:00
										 |  |  | Length::Length(int value, Type type) | 
					
						
							|  |  |  |     : m_type(type) | 
					
						
							|  |  |  |     , m_value(value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | Length::Length(float value, Type type) | 
					
						
							|  |  |  |     : m_type(type) | 
					
						
							|  |  |  |     , m_value(value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-09-13 17:42:39 +02:00
										 |  |  | Length::~Length() = default; | 
					
						
							| 
									
										
										
										
											2021-09-30 22:57:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Length Length::make_auto() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Length(0, Type::Auto); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-01-14 12:23:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-24 17:16:08 +01:00
										 |  |  | Length Length::make_px(CSSPixels value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return Length(value.value(), Type::Px); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 12:11:23 +00:00
										 |  |  | Length Length::make_calculated(NonnullRefPtr<CalculatedStyleValue> calculated_style_value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Length length { 0, Type::Calculated }; | 
					
						
							|  |  |  |     length.m_calculated_style = move(calculated_style_value); | 
					
						
							|  |  |  |     return length; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-14 12:23:54 +00:00
										 |  |  | Length Length::percentage_of(Percentage const& percentage) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-21 17:35:52 +00:00
										 |  |  |     VERIFY(!is_calculated()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 16:50:17 +00:00
										 |  |  |     if (is_auto()) { | 
					
						
							|  |  |  |         dbgln("Attempting to get percentage of an auto length, this seems wrong? But for now we just return the original length."); | 
					
						
							| 
									
										
										
										
											2022-01-14 12:23:54 +00:00
										 |  |  |         return *this; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return Length { percentage.as_fraction() * raw_value(), m_type }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 16:17:27 +00:00
										 |  |  | Length Length::resolved(Layout::Node const& layout_node) const | 
					
						
							| 
									
										
										
										
											2021-09-30 22:57:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (is_calculated()) | 
					
						
							| 
									
										
										
										
											2022-01-24 17:38:29 +00:00
										 |  |  |         return m_calculated_style->resolve_length(layout_node).release_value(); | 
					
						
							| 
									
										
										
										
											2021-09-30 22:57:35 +02:00
										 |  |  |     if (is_relative()) | 
					
						
							|  |  |  |         return make_px(to_px(layout_node)); | 
					
						
							| 
									
										
										
										
											2022-07-06 13:05:31 +02:00
										 |  |  |     if (!isfinite(m_value)) | 
					
						
							|  |  |  |         return make_auto(); | 
					
						
							| 
									
										
										
										
											2021-09-30 22:57:35 +02:00
										 |  |  |     return *this; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-09 12:32:20 +00:00
										 |  |  | CSSPixels Length::relative_length_to_px(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (m_type) { | 
					
						
							| 
									
										
										
										
											2020-08-07 20:30:27 +02:00
										 |  |  |     case Type::Ex: | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |         return m_value * font_metrics.x_height; | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     case Type::Em: | 
					
						
							| 
									
										
										
										
											2022-02-21 16:24:12 +01:00
										 |  |  |         return m_value * font_size; | 
					
						
							| 
									
										
										
										
											2021-08-05 16:31:15 +02:00
										 |  |  |     case Type::Ch: | 
					
						
							| 
									
										
										
										
											2023-03-03 19:32:19 +01:00
										 |  |  |         // FIXME: Use layout_node.font().pixel_size() when writing-mode is not horizontal-tb (it has to be implemented first)
 | 
					
						
							| 
									
										
										
										
											2022-03-28 12:01:10 +02:00
										 |  |  |         return m_value * (font_metrics.advance_of_ascii_zero + font_metrics.glyph_spacing); | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     case Type::Rem: | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |         return m_value * root_font_size; | 
					
						
							| 
									
										
										
										
											2020-09-08 20:39:09 +02:00
										 |  |  |     case Type::Vw: | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |         return viewport_rect.width() * (m_value / 100); | 
					
						
							| 
									
										
										
										
											2020-09-08 20:39:09 +02:00
										 |  |  |     case Type::Vh: | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |         return viewport_rect.height() * (m_value / 100); | 
					
						
							|  |  |  |     case Type::Vmin: | 
					
						
							|  |  |  |         return min(viewport_rect.width(), viewport_rect.height()) * (m_value / 100); | 
					
						
							|  |  |  |     case Type::Vmax: | 
					
						
							|  |  |  |         return max(viewport_rect.width(), viewport_rect.height()) * (m_value / 100); | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |         VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-08 17:29:52 +00:00
										 |  |  | CSSPixels Length::to_px(Layout::Node const& layout_node) const | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-18 16:20:16 +00:00
										 |  |  |     if (is_calculated()) | 
					
						
							|  |  |  |         return m_calculated_style->resolve_length(layout_node)->to_px(layout_node); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 18:02:41 +01:00
										 |  |  |     if (is_absolute()) | 
					
						
							|  |  |  |         return absolute_length_to_px(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |     if (!layout_node.document().browsing_context()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2022-11-09 12:32:20 +00:00
										 |  |  |     auto const& viewport_rect = layout_node.document().browsing_context()->viewport_rect(); | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  |     auto* root_element = layout_node.document().document_element(); | 
					
						
							|  |  |  |     if (!root_element || !root_element->layout_node()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							| 
									
										
										
										
											2022-03-28 12:03:44 +02:00
										 |  |  |     return to_px(viewport_rect, layout_node.font().pixel_metrics(), layout_node.computed_values().font_size(), root_element->layout_node()->computed_values().font_size()); | 
					
						
							| 
									
										
										
										
											2021-09-23 13:13:51 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-06 19:02:26 +01:00
										 |  |  | ErrorOr<String> Length::to_string() const | 
					
						
							| 
									
										
										
										
											2022-02-21 17:35:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (is_calculated()) | 
					
						
							| 
									
										
										
										
											2023-01-06 19:02:26 +01:00
										 |  |  |         return m_calculated_style->to_string(); | 
					
						
							| 
									
										
										
										
											2022-02-21 17:35:52 +00:00
										 |  |  |     if (is_auto()) | 
					
						
							| 
									
										
										
										
											2023-02-25 16:40:37 +01:00
										 |  |  |         return "auto"_string; | 
					
						
							| 
									
										
										
										
											2023-01-06 19:02:26 +01:00
										 |  |  |     return String::formatted("{}{}", m_value, unit_name()); | 
					
						
							| 
									
										
										
										
											2022-02-21 17:35:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-01 20:58:27 +03:00
										 |  |  | char const* Length::unit_name() const | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (m_type) { | 
					
						
							| 
									
										
										
										
											2020-09-29 19:06:58 +01:00
										 |  |  |     case Type::Cm: | 
					
						
							|  |  |  |         return "cm"; | 
					
						
							|  |  |  |     case Type::In: | 
					
						
							|  |  |  |         return "in"; | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     case Type::Px: | 
					
						
							|  |  |  |         return "px"; | 
					
						
							| 
									
										
										
										
											2020-06-28 15:25:32 +02:00
										 |  |  |     case Type::Pt: | 
					
						
							|  |  |  |         return "pt"; | 
					
						
							| 
									
										
										
										
											2020-09-29 19:06:58 +01:00
										 |  |  |     case Type::Mm: | 
					
						
							|  |  |  |         return "mm"; | 
					
						
							|  |  |  |     case Type::Q: | 
					
						
							|  |  |  |         return "Q"; | 
					
						
							| 
									
										
										
										
											2020-10-05 16:18:07 +01:00
										 |  |  |     case Type::Pc: | 
					
						
							|  |  |  |         return "pc"; | 
					
						
							| 
									
										
										
										
											2020-08-07 20:30:27 +02:00
										 |  |  |     case Type::Ex: | 
					
						
							|  |  |  |         return "ex"; | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     case Type::Em: | 
					
						
							|  |  |  |         return "em"; | 
					
						
							| 
									
										
										
										
											2021-08-05 16:31:15 +02:00
										 |  |  |     case Type::Ch: | 
					
						
							|  |  |  |         return "ch"; | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     case Type::Rem: | 
					
						
							|  |  |  |         return "rem"; | 
					
						
							|  |  |  |     case Type::Auto: | 
					
						
							|  |  |  |         return "auto"; | 
					
						
							| 
									
										
										
										
											2020-09-08 20:39:09 +02:00
										 |  |  |     case Type::Vh: | 
					
						
							|  |  |  |         return "vh"; | 
					
						
							|  |  |  |     case Type::Vw: | 
					
						
							|  |  |  |         return "vw"; | 
					
						
							|  |  |  |     case Type::Vmax: | 
					
						
							|  |  |  |         return "vmax"; | 
					
						
							|  |  |  |     case Type::Vmin: | 
					
						
							|  |  |  |         return "vmin"; | 
					
						
							| 
									
										
										
										
											2021-06-12 00:03:15 +02:00
										 |  |  |     case Type::Calculated: | 
					
						
							|  |  |  |         return "calculated"; | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 12:10:48 +00:00
										 |  |  | Optional<Length::Type> Length::unit_from_name(StringView name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (name.equals_ignoring_case("px"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Px; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("pt"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Pt; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("pc"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Pc; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("mm"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Mm; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("rem"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Rem; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("em"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Em; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("ex"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Ex; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("ch"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Ch; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("vw"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Vw; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("vh"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Vh; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("vmax"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Vmax; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("vmin"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Vmin; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("cm"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Cm; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("in"sv)) { | 
					
						
							|  |  |  |         return Length::Type::In; | 
					
						
							|  |  |  |     } else if (name.equals_ignoring_case("Q"sv)) { | 
					
						
							|  |  |  |         return Length::Type::Q; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-27 13:45:05 +01:00
										 |  |  | NonnullRefPtr<CalculatedStyleValue> Length::calculated_style_value() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VERIFY(!m_calculated_style.is_null()); | 
					
						
							|  |  |  |     return *m_calculated_style; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-13 17:42:39 +02:00
										 |  |  | bool Length::operator==(Length const& other) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (is_calculated()) | 
					
						
							|  |  |  |         return m_calculated_style == other.m_calculated_style; | 
					
						
							|  |  |  |     return m_type == other.m_type && m_value == other.m_value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-07 17:55:46 +02:00
										 |  |  | } |