summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2022-01-14 12:23:54 +0000
committerAndreas Kling <kling@serenityos.org>2022-01-20 00:04:10 +0100
commit01b57fa8b7275cba91e476ea6ba3f079514c4ac7 (patch)
tree461312b68b372a8a1939afc2d1d203083995e444
parent71ab8fb757f560d50f1c324fbdfa5678597d0b69 (diff)
downloadserenity-01b57fa8b7275cba91e476ea6ba3f079514c4ac7.zip
LibWeb: Add CSS::Percentage, PercentageOr and LengthPercentage types
Length and Percentage are different types, and sometimes only one or the other is allowed in a given CSS property. This is a first step towards separating them.
-rw-r--r--Meta/Lagom/Tools/CodeGenerators/LibWeb/Generate_CSS_PropertyID_cpp.cpp3
-rw-r--r--Userland/Libraries/LibWeb/CSS/Length.cpp12
-rw-r--r--Userland/Libraries/LibWeb/CSS/Length.h1
-rw-r--r--Userland/Libraries/LibWeb/CSS/Percentage.h141
-rw-r--r--Userland/Libraries/LibWeb/Forward.h3
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;