Serenity Operating System
at master 147 lines 4.5 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/RefPtr.h> 11#include <AK/String.h> 12#include <LibGfx/Forward.h> 13#include <LibWeb/Forward.h> 14#include <LibWeb/PixelUnits.h> 15 16namespace Web::CSS { 17 18class Length { 19public: 20 enum class Type { 21 Calculated, 22 Auto, 23 Cm, 24 In, 25 Mm, 26 Q, 27 Px, 28 Pt, 29 Pc, 30 Ex, 31 Em, 32 Ch, 33 Rem, 34 Vh, 35 Vw, 36 Vmax, 37 Vmin, 38 }; 39 40 static Optional<Type> unit_from_name(StringView); 41 42 // We have a RefPtr<CalculatedStyleValue> member, but can't include the header StyleValue.h as it includes 43 // this file already. To break the cyclic dependency, we must move all method definitions out. 44 Length(int value, Type type); 45 Length(float value, Type type); 46 ~Length(); 47 48 static Length make_auto(); 49 static Length make_px(CSSPixels value); 50 static Length make_calculated(NonnullRefPtr<CalculatedStyleValue>); 51 Length percentage_of(Percentage const&) const; 52 53 Length resolved(Layout::Node const& layout_node) const; 54 55 bool is_auto() const { return m_type == Type::Auto; } 56 bool is_calculated() const { return m_type == Type::Calculated; } 57 bool is_px() const { return m_type == Type::Px; } 58 59 bool is_absolute() const 60 { 61 return m_type == Type::Cm 62 || m_type == Type::In 63 || m_type == Type::Mm 64 || m_type == Type::Px 65 || m_type == Type::Pt 66 || m_type == Type::Pc 67 || m_type == Type::Q; 68 } 69 70 bool is_relative() const 71 { 72 return m_type == Type::Ex 73 || m_type == Type::Em 74 || m_type == Type::Ch 75 || m_type == Type::Rem 76 || m_type == Type::Vh 77 || m_type == Type::Vw 78 || m_type == Type::Vmax 79 || m_type == Type::Vmin; 80 } 81 82 float raw_value() const { return m_value; } 83 NonnullRefPtr<CalculatedStyleValue> calculated_style_value() const; 84 85 CSSPixels to_px(Layout::Node const&) const; 86 87 ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const 88 { 89 if (is_auto()) 90 return 0; 91 if (is_relative()) 92 return relative_length_to_px(viewport_rect, font_metrics, font_size, root_font_size); 93 if (is_calculated()) 94 VERIFY_NOT_REACHED(); // We can't resolve a calculated length from here. :^( 95 return absolute_length_to_px(); 96 } 97 98 ALWAYS_INLINE CSSPixels absolute_length_to_px() const 99 { 100 constexpr float inch_pixels = 96.0f; 101 constexpr float centimeter_pixels = (inch_pixels / 2.54f); 102 switch (m_type) { 103 case Type::Cm: 104 return m_value * centimeter_pixels; // 1cm = 96px/2.54 105 case Type::In: 106 return m_value * inch_pixels; // 1in = 2.54 cm = 96px 107 case Type::Px: 108 return m_value; // 1px = 1/96th of 1in 109 case Type::Pt: 110 return m_value * ((1.0f / 72.0f) * inch_pixels); // 1pt = 1/72th of 1in 111 case Type::Pc: 112 return m_value * ((1.0f / 6.0f) * inch_pixels); // 1pc = 1/6th of 1in 113 case Type::Mm: 114 return m_value * ((1.0f / 10.0f) * centimeter_pixels); // 1mm = 1/10th of 1cm 115 case Type::Q: 116 return m_value * ((1.0f / 40.0f) * centimeter_pixels); // 1Q = 1/40th of 1cm 117 default: 118 VERIFY_NOT_REACHED(); 119 } 120 } 121 122 ErrorOr<String> to_string() const; 123 124 // We have a RefPtr<CalculatedStyleValue> member, but can't include the header StyleValue.h as it includes 125 // this file already. To break the cyclic dependency, we must move all method definitions out. 126 bool operator==(Length const& other) const; 127 128 CSSPixels relative_length_to_px(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const; 129 130private: 131 char const* unit_name() const; 132 133 Type m_type; 134 float m_value { 0 }; 135 136 RefPtr<CalculatedStyleValue> m_calculated_style; 137}; 138 139} 140 141template<> 142struct AK::Formatter<Web::CSS::Length> : Formatter<StringView> { 143 ErrorOr<void> format(FormatBuilder& builder, Web::CSS::Length const& length) 144 { 145 return Formatter<StringView>::format(builder, TRY(length.to_string())); 146 } 147};