mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 07:12:43 +00:00 
			
		
		
		
	 71baa8c31a
			
		
	
	
		71baa8c31a
		
	
	
	
	
		
			
			This is intended to annotate conversions from unknown floating-point values to CSSPixels, and make it more obvious the fp value will be rounded to the nearest fixed-point value.
		
			
				
	
	
		
			235 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
 | |
|  * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/String.h>
 | |
| #include <LibGfx/Forward.h>
 | |
| #include <LibGfx/Rect.h>
 | |
| #include <LibWeb/Forward.h>
 | |
| #include <LibWeb/PixelUnits.h>
 | |
| 
 | |
| namespace Web::CSS {
 | |
| 
 | |
| class Length {
 | |
| public:
 | |
|     enum class Type {
 | |
|         // Font-relative
 | |
|         Em,
 | |
|         Rem,
 | |
|         Ex,
 | |
|         Rex,
 | |
|         Cap,
 | |
|         Rcap,
 | |
|         Ch,
 | |
|         Rch,
 | |
|         Ic,
 | |
|         Ric,
 | |
|         Lh,
 | |
|         Rlh,
 | |
| 
 | |
|         // Viewport-relative
 | |
|         Vw,
 | |
|         Svw,
 | |
|         Lvw,
 | |
|         Dvw,
 | |
|         Vh,
 | |
|         Svh,
 | |
|         Lvh,
 | |
|         Dvh,
 | |
|         Vi,
 | |
|         Svi,
 | |
|         Lvi,
 | |
|         Dvi,
 | |
|         Vb,
 | |
|         Svb,
 | |
|         Lvb,
 | |
|         Dvb,
 | |
|         Vmin,
 | |
|         Svmin,
 | |
|         Lvmin,
 | |
|         Dvmin,
 | |
|         Vmax,
 | |
|         Svmax,
 | |
|         Lvmax,
 | |
|         Dvmax,
 | |
| 
 | |
|         // Absolute
 | |
|         Cm,
 | |
|         Mm,
 | |
|         Q,
 | |
|         In,
 | |
|         Pt,
 | |
|         Pc,
 | |
|         Px,
 | |
| 
 | |
|         // FIXME: Remove auto somehow
 | |
|         Auto,
 | |
|     };
 | |
| 
 | |
|     struct FontMetrics {
 | |
|         FontMetrics(CSSPixels font_size, Gfx::FontPixelMetrics const&, CSSPixels line_height);
 | |
| 
 | |
|         CSSPixels font_size;
 | |
|         CSSPixels x_height;
 | |
|         CSSPixels cap_height;
 | |
|         CSSPixels zero_advance;
 | |
|         CSSPixels line_height;
 | |
|     };
 | |
| 
 | |
|     static Optional<Type> unit_from_name(StringView);
 | |
| 
 | |
|     Length(double value, Type type);
 | |
|     ~Length();
 | |
| 
 | |
|     static Length make_auto();
 | |
|     static Length make_px(CSSPixels value);
 | |
|     Length percentage_of(Percentage const&) const;
 | |
| 
 | |
|     bool is_auto() const { return m_type == Type::Auto; }
 | |
|     bool is_px() const { return m_type == Type::Px; }
 | |
| 
 | |
|     bool is_absolute() const
 | |
|     {
 | |
|         return m_type == Type::Cm
 | |
|             || m_type == Type::Mm
 | |
|             || m_type == Type::Q
 | |
|             || m_type == Type::In
 | |
|             || m_type == Type::Pt
 | |
|             || m_type == Type::Pc
 | |
|             || m_type == Type::Px;
 | |
|     }
 | |
| 
 | |
|     bool is_font_relative() const
 | |
|     {
 | |
|         return m_type == Type::Em
 | |
|             || m_type == Type::Rem
 | |
|             || m_type == Type::Ex
 | |
|             || m_type == Type::Rex
 | |
|             || m_type == Type::Cap
 | |
|             || m_type == Type::Rcap
 | |
|             || m_type == Type::Ch
 | |
|             || m_type == Type::Rch
 | |
|             || m_type == Type::Ic
 | |
|             || m_type == Type::Ric
 | |
|             || m_type == Type::Lh
 | |
|             || m_type == Type::Rlh;
 | |
|     }
 | |
| 
 | |
|     bool is_viewport_relative() const
 | |
|     {
 | |
|         return m_type == Type::Vw
 | |
|             || m_type == Type::Svw
 | |
|             || m_type == Type::Lvw
 | |
|             || m_type == Type::Dvw
 | |
|             || m_type == Type::Vh
 | |
|             || m_type == Type::Svh
 | |
|             || m_type == Type::Lvh
 | |
|             || m_type == Type::Dvh
 | |
|             || m_type == Type::Vi
 | |
|             || m_type == Type::Svi
 | |
|             || m_type == Type::Lvi
 | |
|             || m_type == Type::Dvi
 | |
|             || m_type == Type::Vb
 | |
|             || m_type == Type::Svb
 | |
|             || m_type == Type::Lvb
 | |
|             || m_type == Type::Dvb
 | |
|             || m_type == Type::Vmin
 | |
|             || m_type == Type::Svmin
 | |
|             || m_type == Type::Lvmin
 | |
|             || m_type == Type::Dvmin
 | |
|             || m_type == Type::Vmax
 | |
|             || m_type == Type::Svmax
 | |
|             || m_type == Type::Lvmax
 | |
|             || m_type == Type::Dvmax;
 | |
|     }
 | |
| 
 | |
|     bool is_relative() const
 | |
|     {
 | |
|         return is_font_relative() || is_viewport_relative();
 | |
|     }
 | |
| 
 | |
|     Type type() const { return m_type; }
 | |
|     double raw_value() const { return m_value; }
 | |
| 
 | |
|     struct ResolutionContext {
 | |
|         [[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&);
 | |
| 
 | |
|         CSSPixelRect viewport_rect;
 | |
|         FontMetrics font_metrics;
 | |
|         FontMetrics root_font_metrics;
 | |
|     };
 | |
| 
 | |
|     [[nodiscard]] CSSPixels to_px(ResolutionContext const&) const;
 | |
| 
 | |
|     CSSPixels to_px(Layout::Node const&) const;
 | |
| 
 | |
|     ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const
 | |
|     {
 | |
|         if (is_auto())
 | |
|             return 0;
 | |
|         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);
 | |
|         return absolute_length_to_px();
 | |
|     }
 | |
| 
 | |
|     ALWAYS_INLINE CSSPixels absolute_length_to_px() const
 | |
|     {
 | |
|         constexpr double inch_pixels = 96.0;
 | |
|         constexpr double centimeter_pixels = (inch_pixels / 2.54);
 | |
|         switch (m_type) {
 | |
|         case Type::Cm:
 | |
|             return CSSPixels::nearest_value_for(m_value * centimeter_pixels); // 1cm = 96px/2.54
 | |
|         case Type::In:
 | |
|             return CSSPixels::nearest_value_for(m_value * inch_pixels); // 1in = 2.54 cm = 96px
 | |
|         case Type::Px:
 | |
|             return CSSPixels::nearest_value_for(m_value); // 1px = 1/96th of 1in
 | |
|         case Type::Pt:
 | |
|             return CSSPixels::nearest_value_for(m_value * ((1.0 / 72.0) * inch_pixels)); // 1pt = 1/72th of 1in
 | |
|         case Type::Pc:
 | |
|             return CSSPixels::nearest_value_for(m_value * ((1.0 / 6.0) * inch_pixels)); // 1pc = 1/6th of 1in
 | |
|         case Type::Mm:
 | |
|             return CSSPixels::nearest_value_for(m_value * ((1.0 / 10.0) * centimeter_pixels)); // 1mm = 1/10th of 1cm
 | |
|         case Type::Q:
 | |
|             return CSSPixels::nearest_value_for(m_value * ((1.0 / 40.0) * centimeter_pixels)); // 1Q = 1/40th of 1cm
 | |
|         default:
 | |
|             VERIFY_NOT_REACHED();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     String to_string() const;
 | |
| 
 | |
|     bool operator==(Length const& other) const
 | |
|     {
 | |
|         return m_type == other.m_type && m_value == other.m_value;
 | |
|     }
 | |
| 
 | |
|     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;
 | |
| 
 | |
|     // Returns empty optional if it's already absolute.
 | |
|     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;
 | |
| 
 | |
| private:
 | |
|     char const* unit_name() const;
 | |
| 
 | |
|     Type m_type;
 | |
|     double m_value { 0 };
 | |
| };
 | |
| 
 | |
| }
 | |
| 
 | |
| template<>
 | |
| struct AK::Formatter<Web::CSS::Length> : Formatter<StringView> {
 | |
|     ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Length const& length)
 | |
|     {
 | |
|         return Formatter<StringView>::format(builder, length.to_string());
 | |
|     }
 | |
| };
 |