diff options
-rw-r--r-- | Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Length.cpp | 12 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Length.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Percentage.h | 141 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 3 |
5 files changed, 158 insertions, 2 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp index 12b0a84e38..e1ac87163f 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp @@ -311,8 +311,9 @@ bool property_accepts_value(PropertyID property_id, StyleValue& style_value) return true; )~~~"); } else if (type_name == "percentage") { + // FIXME: Detecting lengths here is temporary until Length/Percentage are fully separated. property_generator.append(R"~~~( - if ((style_value.has_length() && style_value.to_length().is_percentage()) || style_value.is_calculated()) + if (style_value.is_percentage() || style_value.is_calculated() || (style_value.has_length() && !style_value.to_length().is_percentage())) return true; )~~~"); } else if (type_name == "number" || type_name == "integer") { diff --git a/Userland/Libraries/LibWeb/CSS/Length.cpp b/Userland/Libraries/LibWeb/CSS/Length.cpp index 9f51e56fc7..3cdd0117b6 100644 --- a/Userland/Libraries/LibWeb/CSS/Length.cpp +++ b/Userland/Libraries/LibWeb/CSS/Length.cpp @@ -10,6 +10,7 @@ #include <LibGfx/Font.h> #include <LibGfx/Rect.h> #include <LibWeb/CSS/Length.h> +#include <LibWeb/CSS/Percentage.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/HTML/HTMLHtmlElement.h> @@ -32,11 +33,22 @@ Length Length::make_auto() { return Length(0, Type::Auto); } + Length Length::make_px(float value) { return Length(value, Type::Px); } +Length Length::percentage_of(Percentage const& percentage) const +{ + if (is_undefined_or_auto()) { + dbgln("Attempting to get percentage of an undefined or auto length, this seems wrong? But for now we just return the original length."); + return *this; + } + + return Length { percentage.as_fraction() * raw_value(), m_type }; +} + Length Length::resolved(const Length& fallback_for_undefined, const Layout::Node& layout_node, float reference_for_percent) const { if (is_undefined()) diff --git a/Userland/Libraries/LibWeb/CSS/Length.h b/Userland/Libraries/LibWeb/CSS/Length.h index 349a1a7ad3..ddf620bced 100644 --- a/Userland/Libraries/LibWeb/CSS/Length.h +++ b/Userland/Libraries/LibWeb/CSS/Length.h @@ -44,6 +44,7 @@ public: static Length make_auto(); static Length make_px(float value); + Length percentage_of(Percentage const&) const; Length resolved(const Length& fallback_for_undefined, const Layout::Node& layout_node, float reference_for_percent) const; Length resolved_or_auto(const Layout::Node& layout_node, float reference_for_percent) const; diff --git a/Userland/Libraries/LibWeb/CSS/Percentage.h b/Userland/Libraries/LibWeb/CSS/Percentage.h new file mode 100644 index 0000000000..86dce08e6d --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/Percentage.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/String.h> +#include <AK/Variant.h> +#include <LibWeb/CSS/Length.h> + +namespace Web::CSS { + +class Percentage { +public: + explicit Percentage(int value) + : m_value(value) + { + } + + explicit Percentage(float value) + : m_value(value) + { + } + + float value() const { return m_value; } + float as_fraction() const { return m_value * 0.01f; } + + String to_string() const + { + return String::formatted("{}%", m_value); + } + + bool operator==(Percentage const& other) const { return m_value == other.m_value; } + bool operator!=(Percentage const& other) const { return !(*this == other); } + +private: + float m_value; +}; + +template<typename T> +class PercentageOr { +public: + PercentageOr(T t) + : m_value(move(t)) + { + } + + PercentageOr(Percentage percentage) + : m_value(move(percentage)) + { + } + + PercentageOr<T>& operator=(T t) + { + m_value = move(t); + return *this; + } + + PercentageOr<T>& operator=(Percentage percentage) + { + m_value = move(percentage); + return *this; + } + + bool is_percentage() const { return m_value.template has<Percentage>(); } + + Percentage const& percentage() const + { + VERIFY(is_percentage()); + return m_value.template get<Percentage>(); + } + + T resolved(T const& reference_value) const + { + if (is_percentage()) + return reference_value.percentage_of(m_value.template get<Percentage>()); + + return m_value.template get<T>(); + } + + String to_string() const + { + if (is_percentage()) + return m_value.template get<Percentage>().to_string(); + + return m_value.template get<T>().to_string(); + } + + bool operator==(PercentageOr<T> const& other) const + { + if (is_percentage() != other.is_percentage()) + return false; + if (is_percentage()) + return (m_value.template get<Percentage>() == other.m_value.template get<Percentage>()); + return (m_value.template get<T>() == other.m_value.template get<T>()); + } + bool operator!=(PercentageOr<T> const& other) const { return !(*this == other); } + +protected: + bool is_non_percentage_value() const { return m_value.template has<T>(); } + T const& non_percentage_value() const { return m_value.template get<T>(); } + +private: + Variant<T, Percentage> m_value; +}; + +template<typename T> +bool operator==(PercentageOr<T> const& percentage_or, T const& t) +{ + return percentage_or == PercentageOr<T> { t }; +} + +template<typename T> +bool operator==(T const& t, PercentageOr<T> const& percentage_or) +{ + return t == percentage_or; +} + +template<typename T> +bool operator==(PercentageOr<T> const& percentage_or, Percentage const& percentage) +{ + return percentage_or == PercentageOr<T> { percentage }; +} + +template<typename T> +bool operator==(Percentage const& percentage, PercentageOr<T> const& percentage_or) +{ + return percentage == percentage_or; +} + +class LengthPercentage : public PercentageOr<Length> { +public: + using PercentageOr<Length>::PercentageOr; + + bool is_length() const { return is_non_percentage_value(); } + Length const& length() const { return non_percentage_value(); } +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index ee116ffa0a..0454931ec4 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -26,7 +26,6 @@ class BorderRadiusStyleValue; class BorderStyleValue; class BoxShadowStyleValue; class CalculatedStyleValue; -class CalculatedStyleValue; class ColorStyleValue; class CSSImportRule; class CSSMediaRule; @@ -46,6 +45,7 @@ class ImageStyleValue; class InheritStyleValue; class InitialStyleValue; class Length; +class LengthPercentage; class LengthStyleValue; class ListStyleStyleValue; class MediaList; @@ -54,6 +54,7 @@ class MediaQueryList; class MediaQueryListEvent; class NumericStyleValue; class OverflowStyleValue; +class Percentage; class PositionStyleValue; class PropertyOwningCSSStyleDeclaration; class Screen; |