diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index f549b6dc34..3478edf973 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCES CSS/PropertyID.cpp CSS/PropertyID.h CSS/QuirksModeStyleSheetSource.cpp + CSS/Resolution.cpp CSS/ResolvedCSSStyleDeclaration.cpp CSS/Screen.cpp CSS/Selector.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 14974066a8..ea1f704084 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -4306,6 +4306,10 @@ Optional Parser::parse_calc_value(TokenStream + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "Resolution.h" +#include + +namespace Web::CSS { + +Resolution::Resolution(int value, Type type) + : m_type(type) + , m_value(value) +{ +} + +Resolution::Resolution(float value, Type type) + : m_type(type) + , m_value(value) +{ +} + +String Resolution::to_string() const +{ + return String::formatted("{}{}", m_value, unit_name()); +} + +float Resolution::to_dots_per_pixel() const +{ + switch (m_type) { + case Type::Dpi: + return m_value * 96; // 1in = 2.54cm = 96px + case Type::Dpcm: + return m_value * (96.0f / 2.54f); // 1cm = 96px/2.54 + case Type::Dppx: + return m_value; + } + VERIFY_NOT_REACHED(); +} + +StringView Resolution::unit_name() const +{ + switch (m_type) { + case Type::Dpi: + return "dpi"sv; + case Type::Dpcm: + return "dpcm"sv; + case Type::Dppx: + return "dppx"sv; + } + VERIFY_NOT_REACHED(); +} + +Optional Resolution::unit_from_name(StringView name) +{ + if (name.equals_ignoring_case("dpi"sv)) { + return Type::Dpi; + } else if (name.equals_ignoring_case("dpcm"sv)) { + return Type::Dpcm; + } else if (name.equals_ignoring_case("dppx"sv)) { + return Type::Dppx; + } + return {}; +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/Resolution.h b/Userland/Libraries/LibWeb/CSS/Resolution.h new file mode 100644 index 0000000000..589d070509 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/Resolution.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, Sam Atkins + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS { + +class Resolution { +public: + enum class Type { + Dpi, + Dpcm, + Dppx, + }; + + static Optional unit_from_name(StringView); + + Resolution(int value, Type type); + Resolution(float value, Type type); + + String to_string() const; + float to_dots_per_pixel() const; + + bool operator==(Resolution const& other) const + { + return m_type == other.m_type && m_value == other.m_value; + } + + bool operator!=(Resolution const& other) const + { + return !(*this == other); + } + +private: + StringView unit_name() const; + + Type m_type; + float m_value { 0 }; +}; +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 235096a2e0..aaf934842e 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -165,6 +165,12 @@ PositionStyleValue const& StyleValue::as_position() const return static_cast(*this); } +ResolutionStyleValue const& StyleValue::as_resolution() const +{ + VERIFY(is_resolution()); + return static_cast(*this); +} + StringStyleValue const& StyleValue::as_string() const { VERIFY(is_string()); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 0d3fe3cff6..b5e83d3630 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -310,6 +311,7 @@ public: Overflow, Percentage, Position, + Resolution, String, TextDecoration, Transformation, @@ -343,6 +345,7 @@ public: bool is_overflow() const { return type() == Type::Overflow; } bool is_percentage() const { return type() == Type::Percentage; } bool is_position() const { return type() == Type::Position; } + bool is_resolution() const { return type() == Type::Resolution; } bool is_string() const { return type() == Type::String; } bool is_text_decoration() const { return type() == Type::TextDecoration; } bool is_transformation() const { return type() == Type::Transformation; } @@ -375,6 +378,7 @@ public: OverflowStyleValue const& as_overflow() const; PercentageStyleValue const& as_percentage() const; PositionStyleValue const& as_position() const; + ResolutionStyleValue const& as_resolution() const; StringStyleValue const& as_string() const; TextDecorationStyleValue const& as_text_decoration() const; TransformationStyleValue const& as_transformation() const; @@ -405,6 +409,7 @@ public: OverflowStyleValue& as_overflow() { return const_cast(const_cast(*this).as_overflow()); } PercentageStyleValue& as_percentage() { return const_cast(const_cast(*this).as_percentage()); } PositionStyleValue& as_position() { return const_cast(const_cast(*this).as_position()); } + ResolutionStyleValue& as_resolution() { return const_cast(const_cast(*this).as_resolution()); } StringStyleValue& as_string() { return const_cast(const_cast(*this).as_string()); } TextDecorationStyleValue& as_text_decoration() { return const_cast(const_cast(*this).as_text_decoration()); } TransformationStyleValue& as_transformation() { return const_cast(const_cast(*this).as_transformation()); } @@ -1367,6 +1372,35 @@ private: LengthPercentage m_offset_y; }; +class ResolutionStyleValue : public StyleValue { +public: + static NonnullRefPtr create(Resolution resolution) + { + return adopt_ref(*new ResolutionStyleValue(move(resolution))); + } + virtual ~ResolutionStyleValue() override { } + + Resolution const& resolution() const { return m_resolution; } + + virtual String to_string() const override { return m_resolution.to_string(); } + + virtual bool equals(StyleValue const& other) const override + { + if (type() != other.type()) + return false; + return m_resolution == static_cast(other).m_resolution; + } + +private: + explicit ResolutionStyleValue(Resolution resolution) + : StyleValue(Type::Resolution) + , m_resolution(move(resolution)) + { + } + + Resolution m_resolution; +}; + class StringStyleValue : public StyleValue { public: static NonnullRefPtr create(String const& string) diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 89d521db3f..accdbfbaec 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -64,6 +64,8 @@ class Percentage; class PercentageStyleValue; class PositionStyleValue; class PropertyOwningCSSStyleDeclaration; +class Resolution; +class ResolutionStyleValue; class Screen; class Selector; class StringStyleValue;