mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:47:47 +00:00
LibWeb: Implement CSSNumericType
This represents the type of a calculation, which may involve multiplying or dividing the various numeric types together (eg, length*length, or length/time, or whatever). For now, I've made "Return failure" in each algorithm return an empty Optional. This may or may not be a good solution but we'll see. :^)
This commit is contained in:
parent
434bac3c67
commit
be7093ab0d
3 changed files with 542 additions and 0 deletions
|
@ -26,6 +26,7 @@ set(SOURCES
|
|||
CSS/CSSKeyframesRule.cpp
|
||||
CSS/CSSFontFaceRule.cpp
|
||||
CSS/CSSMediaRule.cpp
|
||||
CSS/CSSNumericType.cpp
|
||||
CSS/CSSRule.cpp
|
||||
CSS/CSSRuleList.cpp
|
||||
CSS/CSSStyleDeclaration.cpp
|
||||
|
|
432
Userland/Libraries/LibWeb/CSS/CSSNumericType.cpp
Normal file
432
Userland/Libraries/LibWeb/CSS/CSSNumericType.cpp
Normal file
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "CSSNumericType.h"
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibWeb/CSS/Angle.h>
|
||||
#include <LibWeb/CSS/Frequency.h>
|
||||
#include <LibWeb/CSS/Length.h>
|
||||
#include <LibWeb/CSS/Percentage.h>
|
||||
#include <LibWeb/CSS/Resolution.h>
|
||||
#include <LibWeb/CSS/Time.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
Optional<CSSNumericType::BaseType> CSSNumericType::base_type_from_value_type(ValueType value_type)
|
||||
{
|
||||
switch (value_type) {
|
||||
case ValueType::Angle:
|
||||
return BaseType::Angle;
|
||||
case ValueType::Frequency:
|
||||
return BaseType::Frequency;
|
||||
case ValueType::Length:
|
||||
return BaseType::Length;
|
||||
case ValueType::Percentage:
|
||||
return BaseType::Percent;
|
||||
case ValueType::Resolution:
|
||||
return BaseType::Resolution;
|
||||
case ValueType::Time:
|
||||
return BaseType::Time;
|
||||
|
||||
case ValueType::Color:
|
||||
case ValueType::CustomIdent:
|
||||
case ValueType::FilterValueList:
|
||||
case ValueType::Image:
|
||||
case ValueType::Integer:
|
||||
case ValueType::Paint:
|
||||
case ValueType::Number:
|
||||
case ValueType::Position:
|
||||
case ValueType::Ratio:
|
||||
case ValueType::Rect:
|
||||
case ValueType::String:
|
||||
case ValueType::Url:
|
||||
return {};
|
||||
}
|
||||
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-create-a-type
|
||||
Optional<CSSNumericType> CSSNumericType::create_from_unit(StringView unit)
|
||||
{
|
||||
// To create a type from a string unit, follow the appropriate branch of the following:
|
||||
|
||||
// unit is "number"
|
||||
if (unit == "number"sv) {
|
||||
// Return «[ ]» (empty map)
|
||||
return CSSNumericType {};
|
||||
}
|
||||
|
||||
// unit is "percent"
|
||||
if (unit == "percent"sv) {
|
||||
// Return «[ "percent" → 1 ]»
|
||||
return CSSNumericType { BaseType::Percent, 1 };
|
||||
}
|
||||
|
||||
// unit is a <length> unit
|
||||
if (Length::unit_from_name(unit).has_value()) {
|
||||
// Return «[ "length" → 1 ]»
|
||||
return CSSNumericType { BaseType::Length, 1 };
|
||||
}
|
||||
|
||||
// unit is an <angle> unit
|
||||
if (Angle::unit_from_name(unit).has_value()) {
|
||||
// Return «[ "angle" → 1 ]»
|
||||
return CSSNumericType { BaseType::Angle, 1 };
|
||||
}
|
||||
|
||||
// unit is a <time> unit
|
||||
if (Time::unit_from_name(unit).has_value()) {
|
||||
// Return «[ "time" → 1 ]»
|
||||
return CSSNumericType { BaseType::Time, 1 };
|
||||
}
|
||||
|
||||
// unit is a <frequency> unit
|
||||
if (Frequency::unit_from_name(unit).has_value()) {
|
||||
// Return «[ "frequency" → 1 ]»
|
||||
return CSSNumericType { BaseType::Frequency, 1 };
|
||||
}
|
||||
|
||||
// unit is a <resolution> unit
|
||||
if (Resolution::unit_from_name(unit).has_value()) {
|
||||
// Return «[ "resolution" → 1 ]»
|
||||
return CSSNumericType { BaseType::Resolution, 1 };
|
||||
}
|
||||
|
||||
// unit is a <flex> unit
|
||||
// FIXME: We don't have <flex> as a type yet.
|
||||
// Return «[ "flex" → 1 ]»
|
||||
|
||||
// anything else
|
||||
// Return failure.
|
||||
return {};
|
||||
|
||||
// In all cases, the associated percent hint is null.
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-add-two-types
|
||||
Optional<CSSNumericType> CSSNumericType::added_to(CSSNumericType const& other) const
|
||||
{
|
||||
// To add two types type1 and type2, perform the following steps:
|
||||
|
||||
// 1. Replace type1 with a fresh copy of type1, and type2 with a fresh copy of type2.
|
||||
// Let finalType be a new type with an initially empty ordered map and an initially null percent hint.
|
||||
CSSNumericType type1 = *this;
|
||||
CSSNumericType type2 = other;
|
||||
CSSNumericType final_type {};
|
||||
|
||||
// 2. If both type1 and type2 have non-null percent hints with different values
|
||||
if (type1.percent_hint().has_value() && type2.percent_hint().has_value() && type1.percent_hint() != type2.percent_hint()) {
|
||||
// The types can’t be added. Return failure.
|
||||
return {};
|
||||
}
|
||||
// If type1 has a non-null percent hint hint and type2 doesn’t
|
||||
else if (type1.percent_hint().has_value() && !type2.percent_hint().has_value()) {
|
||||
// Apply the percent hint hint to type2.
|
||||
type2.apply_percent_hint(type1.percent_hint().value());
|
||||
}
|
||||
// Vice versa if type2 has a non-null percent hint and type1 doesn’t.
|
||||
else if (type2.percent_hint().has_value() && !type1.percent_hint().has_value()) {
|
||||
type1.apply_percent_hint(type2.percent_hint().value());
|
||||
}
|
||||
// Otherwise
|
||||
// Continue to the next step.
|
||||
|
||||
// 3. If all the entries of type1 with non-zero values are contained in type2 with the same value, and vice-versa
|
||||
if (type2.contains_all_the_non_zero_entries_of_other_with_the_same_value(type1)
|
||||
&& type1.contains_all_the_non_zero_entries_of_other_with_the_same_value(type2)) {
|
||||
// Copy all of type1’s entries to finalType, and then copy all of type2’s entries to finalType that
|
||||
// finalType doesn’t already contain. Set finalType’s percent hint to type1’s percent hint. Return finalType.
|
||||
final_type.copy_all_entries_from(type1, SkipIfAlreadyPresent::No);
|
||||
final_type.copy_all_entries_from(type2, SkipIfAlreadyPresent::Yes);
|
||||
final_type.set_percent_hint(type1.percent_hint());
|
||||
return final_type;
|
||||
}
|
||||
// If type1 and/or type2 contain "percent" with a non-zero value,
|
||||
// and type1 and/or type2 contain a key other than "percent" with a non-zero value
|
||||
else if ((type1.exponent(BaseType::Percent) != 0 || type2.exponent(BaseType::Percent) != 0)
|
||||
&& (type1.contains_a_key_other_than_percent_with_a_non_zero_value() || type2.contains_a_key_other_than_percent_with_a_non_zero_value())) {
|
||||
// For each base type other than "percent" hint:
|
||||
for (auto hint_int = 0; hint_int < to_underlying(BaseType::__Count); ++hint_int) {
|
||||
auto hint = static_cast<BaseType>(hint_int);
|
||||
if (hint == BaseType::Percent)
|
||||
continue;
|
||||
|
||||
// 1. Provisionally apply the percent hint hint to both type1 and type2.
|
||||
auto provisional_type1 = type1;
|
||||
provisional_type1.apply_percent_hint(hint);
|
||||
auto provisional_type2 = type2;
|
||||
provisional_type2.apply_percent_hint(hint);
|
||||
|
||||
// 2. If, afterwards, all the entries of type1 with non-zero values are contained in type2
|
||||
// with the same value, and vice versa, then copy all of type1’s entries to finalType,
|
||||
// and then copy all of type2’s entries to finalType that finalType doesn’t already contain.
|
||||
// Set finalType’s percent hint to hint. Return finalType.
|
||||
if (provisional_type2.contains_all_the_non_zero_entries_of_other_with_the_same_value(provisional_type1)
|
||||
&& provisional_type1.contains_all_the_non_zero_entries_of_other_with_the_same_value(provisional_type2)) {
|
||||
|
||||
final_type.copy_all_entries_from(provisional_type1, SkipIfAlreadyPresent::No);
|
||||
final_type.copy_all_entries_from(provisional_type2, SkipIfAlreadyPresent::Yes);
|
||||
final_type.set_percent_hint(hint);
|
||||
return final_type;
|
||||
}
|
||||
|
||||
// 3. Otherwise, revert type1 and type2 to their state at the start of this loop.
|
||||
// NOTE: We did the modifications to provisional_type1/2 so this is a no-op.
|
||||
}
|
||||
|
||||
// If the loop finishes without returning finalType, then the types can’t be added. Return failure.
|
||||
return {};
|
||||
}
|
||||
// Otherwise
|
||||
// The types can’t be added. Return failure.
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-multiply-two-types
|
||||
Optional<CSSNumericType> CSSNumericType::multiplied_by(CSSNumericType const& other) const
|
||||
{
|
||||
// To multiply two types type1 and type2, perform the following steps:
|
||||
|
||||
// 1. Replace type1 with a fresh copy of type1, and type2 with a fresh copy of type2.
|
||||
// Let finalType be a new type with an initially empty ordered map and an initially null percent hint.
|
||||
CSSNumericType type1 = *this;
|
||||
CSSNumericType type2 = other;
|
||||
CSSNumericType final_type {};
|
||||
|
||||
// 2. If both type1 and type2 have non-null percent hints with different values,
|
||||
// the types can’t be multiplied. Return failure.
|
||||
if (type1.percent_hint().has_value() && type2.percent_hint().has_value() && type1.percent_hint() != type2.percent_hint())
|
||||
return {};
|
||||
|
||||
// 3. If type1 has a non-null percent hint hint and type2 doesn’t, apply the percent hint hint to type2.
|
||||
if (type1.percent_hint().has_value() && !type2.percent_hint().has_value()) {
|
||||
type2.apply_percent_hint(type1.percent_hint().value());
|
||||
}
|
||||
// Vice versa if type2 has a non-null percent hint and type1 doesn’t.
|
||||
else if (type2.percent_hint().has_value() && !type1.percent_hint().has_value()) {
|
||||
type1.apply_percent_hint(type2.percent_hint().value());
|
||||
}
|
||||
|
||||
// 4. Copy all of type1’s entries to finalType, then for each baseType → power of type2:
|
||||
final_type.copy_all_entries_from(type1, SkipIfAlreadyPresent::No);
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
if (!type2.exponent(base_type).has_value())
|
||||
continue;
|
||||
auto power = type2.exponent(base_type).value();
|
||||
|
||||
// 1. If finalType[baseType] exists, increment its value by power.
|
||||
if (auto exponent = final_type.exponent(base_type); exponent.has_value()) {
|
||||
final_type.set_exponent(base_type, exponent.value() + power);
|
||||
}
|
||||
// 2. Otherwise, set finalType[baseType] to power.
|
||||
else {
|
||||
final_type.set_exponent(base_type, power);
|
||||
}
|
||||
}
|
||||
// Set finalType’s percent hint to type1’s percent hint.
|
||||
final_type.set_percent_hint(type1.percent_hint());
|
||||
|
||||
// 5. Return finalType.
|
||||
return final_type;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-invert-a-type
|
||||
CSSNumericType CSSNumericType::inverted() const
|
||||
{
|
||||
// To invert a type type, perform the following steps:
|
||||
|
||||
// 1. Let result be a new type with an initially empty ordered map and an initially null percent hint
|
||||
CSSNumericType result;
|
||||
|
||||
// 2. For each unit → exponent of type, set result[unit] to (-1 * exponent).
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
if (!exponent(base_type).has_value())
|
||||
continue;
|
||||
auto power = exponent(base_type).value();
|
||||
result.set_exponent(base_type, -1 * power);
|
||||
}
|
||||
|
||||
// 3. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#apply-the-percent-hint
|
||||
void CSSNumericType::apply_percent_hint(BaseType hint)
|
||||
{
|
||||
// To apply the percent hint hint to a type, perform the following steps:
|
||||
|
||||
// 1. If type doesn’t contain hint, set type[hint] to 0.
|
||||
if (!exponent(hint).has_value())
|
||||
set_exponent(hint, 0);
|
||||
|
||||
// 2. If type contains "percent", add type["percent"] to type[hint], then set type["percent"] to 0.
|
||||
if (exponent(BaseType::Percent).has_value()) {
|
||||
set_exponent(hint, exponent(BaseType::Percent).value() + exponent(hint).value());
|
||||
set_exponent(BaseType::Percent, 0);
|
||||
}
|
||||
|
||||
// 3. Set type’s percent hint to hint.
|
||||
set_percent_hint(hint);
|
||||
}
|
||||
|
||||
bool CSSNumericType::contains_all_the_non_zero_entries_of_other_with_the_same_value(CSSNumericType const& other) const
|
||||
{
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto other_exponent = other.exponent(static_cast<BaseType>(i));
|
||||
if (other_exponent.has_value() && other_exponent != 0
|
||||
&& this->exponent(static_cast<BaseType>(i)) != other_exponent) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSSNumericType::contains_a_key_other_than_percent_with_a_non_zero_value() const
|
||||
{
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
if (i == to_underlying(BaseType::Percent))
|
||||
continue;
|
||||
if (m_type_exponents[i].has_value() && m_type_exponents[i] != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CSSNumericType::copy_all_entries_from(CSSNumericType const& other, SkipIfAlreadyPresent ignore_existing_values)
|
||||
{
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto exponent = other.exponent(base_type);
|
||||
if (!exponent.has_value())
|
||||
continue;
|
||||
if (ignore_existing_values == SkipIfAlreadyPresent::Yes && this->exponent(base_type).has_value())
|
||||
continue;
|
||||
set_exponent(base_type, *exponent);
|
||||
}
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-match
|
||||
bool CSSNumericType::matches_dimension(BaseType type) const
|
||||
{
|
||||
// A type matches <length> if its only non-zero entry is «[ "length" → 1 ]» and its percent hint is null.
|
||||
// Similarly for <angle>, <time>, <frequency>, <resolution>, and <flex>.
|
||||
|
||||
if (percent_hint().has_value())
|
||||
return false;
|
||||
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
if (base_type == type) {
|
||||
if (type_exponent != 1)
|
||||
return false;
|
||||
} else {
|
||||
if (type_exponent.has_value() && type_exponent != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-match
|
||||
bool CSSNumericType::matches_percentage() const
|
||||
{
|
||||
// A type matches <percentage> if its only non-zero entry is «[ "percent" → 1 ]».
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
if (base_type == BaseType::Percent) {
|
||||
if (!type_exponent.has_value() || type_exponent == 0)
|
||||
return false;
|
||||
} else {
|
||||
if (type_exponent.has_value() && type_exponent != 0)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-match
|
||||
bool CSSNumericType::matches_dimension_percentage(BaseType type) const
|
||||
{
|
||||
// A type matches <length-percentage> if its only non-zero entry is either «[ "length" → 1 ]»
|
||||
// or «[ "percent" → 1 ]» Same for <angle-percentage>, <time-percentage>, etc.
|
||||
|
||||
// Check for percent -> 1 or type -> 1, but not both
|
||||
if ((exponent(type) == 1) == (exponent(BaseType::Percent) == 1))
|
||||
return false;
|
||||
|
||||
// Ensure all other types are absent or 0
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
if (base_type == type || base_type == BaseType::Percent)
|
||||
continue;
|
||||
|
||||
if (type_exponent.has_value() && type_exponent != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-match
|
||||
bool CSSNumericType::matches_number() const
|
||||
{
|
||||
// A type matches <number> if it has no non-zero entries and its percent hint is null.
|
||||
if (percent_hint().has_value())
|
||||
return false;
|
||||
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
if (type_exponent.has_value() && type_exponent != 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-match
|
||||
bool CSSNumericType::matches_number_percentage() const
|
||||
{
|
||||
// A type matches <number-percentage> if it has no non-zero entries, or its only non-zero entry is «[ "percent" → 1 ]».
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
|
||||
if (base_type == BaseType::Percent && type_exponent.has_value() && type_exponent != 0 && type_exponent != 1) {
|
||||
return false;
|
||||
} else if (type_exponent.has_value() && type_exponent != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorOr<String> CSSNumericType::dump() const
|
||||
{
|
||||
StringBuilder builder;
|
||||
TRY(builder.try_appendff("{{ hint: {}", m_percent_hint.map([](auto base_type) { return base_type_name(base_type); })));
|
||||
|
||||
for (auto i = 0; i < to_underlying(BaseType::__Count); ++i) {
|
||||
auto base_type = static_cast<BaseType>(i);
|
||||
auto type_exponent = exponent(base_type);
|
||||
|
||||
if (type_exponent.has_value())
|
||||
TRY(builder.try_appendff(", \"{}\" → {}", base_type_name(base_type), type_exponent.value()));
|
||||
}
|
||||
|
||||
TRY(builder.try_append(" }"sv));
|
||||
return builder.to_string();
|
||||
}
|
||||
|
||||
}
|
109
Userland/Libraries/LibWeb/CSS/CSSNumericType.h
Normal file
109
Userland/Libraries/LibWeb/CSS/CSSNumericType.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Array.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <LibWeb/CSS/PropertyID.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#numeric-typing
|
||||
// FIXME: Add IDL for this.
|
||||
class CSSNumericType {
|
||||
public:
|
||||
// https://drafts.css-houdini.org/css-typed-om-1/#cssnumericvalue-base-type
|
||||
enum class BaseType {
|
||||
Length,
|
||||
Angle,
|
||||
Time,
|
||||
Frequency,
|
||||
Resolution,
|
||||
Flex,
|
||||
Percent,
|
||||
__Count,
|
||||
};
|
||||
|
||||
static Optional<BaseType> base_type_from_value_type(ValueType);
|
||||
static constexpr StringView base_type_name(BaseType base_type)
|
||||
{
|
||||
switch (base_type) {
|
||||
case BaseType::Length:
|
||||
return "length"sv;
|
||||
case BaseType::Angle:
|
||||
return "angle"sv;
|
||||
case BaseType::Time:
|
||||
return "time"sv;
|
||||
case BaseType::Frequency:
|
||||
return "frequency"sv;
|
||||
case BaseType::Resolution:
|
||||
return "resolution"sv;
|
||||
case BaseType::Flex:
|
||||
return "flex"sv;
|
||||
case BaseType::Percent:
|
||||
return "percent"sv;
|
||||
case BaseType::__Count:
|
||||
break;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
static Optional<CSSNumericType> create_from_unit(StringView unit);
|
||||
CSSNumericType() = default;
|
||||
CSSNumericType(BaseType type, i32 power)
|
||||
{
|
||||
set_exponent(type, power);
|
||||
}
|
||||
|
||||
Optional<CSSNumericType> added_to(CSSNumericType const& other) const;
|
||||
Optional<CSSNumericType> multiplied_by(CSSNumericType const& other) const;
|
||||
CSSNumericType inverted() const;
|
||||
|
||||
bool matches_angle() const { return matches_dimension(BaseType::Angle); }
|
||||
bool matches_angle_percentage() const { return matches_dimension_percentage(BaseType::Angle); }
|
||||
bool matches_flex() const { return matches_dimension(BaseType::Flex); }
|
||||
bool matches_flex_percentage() const { return matches_dimension_percentage(BaseType::Flex); }
|
||||
bool matches_frequency() const { return matches_dimension(BaseType::Frequency); }
|
||||
bool matches_frequency_percentage() const { return matches_dimension_percentage(BaseType::Frequency); }
|
||||
bool matches_length() const { return matches_dimension(BaseType::Length); }
|
||||
bool matches_length_percentage() const { return matches_dimension_percentage(BaseType::Length); }
|
||||
bool matches_number() const;
|
||||
bool matches_number_percentage() const;
|
||||
bool matches_percentage() const;
|
||||
bool matches_resolution() const { return matches_dimension(BaseType::Resolution); }
|
||||
bool matches_resolution_percentage() const { return matches_dimension_percentage(BaseType::Resolution); }
|
||||
bool matches_time() const { return matches_dimension(BaseType::Time); }
|
||||
bool matches_time_percentage() const { return matches_dimension_percentage(BaseType::Time); }
|
||||
|
||||
Optional<i32> const& exponent(BaseType type) const { return m_type_exponents[to_underlying(type)]; }
|
||||
void set_exponent(BaseType type, i32 exponent) { m_type_exponents[to_underlying(type)] = exponent; }
|
||||
|
||||
Optional<BaseType> const& percent_hint() const { return m_percent_hint; }
|
||||
void set_percent_hint(Optional<BaseType> hint) { m_percent_hint = hint; }
|
||||
void apply_percent_hint(BaseType hint);
|
||||
|
||||
bool operator==(CSSNumericType const& other) const = default;
|
||||
|
||||
ErrorOr<String> dump() const;
|
||||
|
||||
private:
|
||||
bool contains_all_the_non_zero_entries_of_other_with_the_same_value(CSSNumericType const& other) const;
|
||||
bool contains_a_key_other_than_percent_with_a_non_zero_value() const;
|
||||
enum class SkipIfAlreadyPresent {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
void copy_all_entries_from(CSSNumericType const& other, SkipIfAlreadyPresent);
|
||||
|
||||
bool matches_dimension(BaseType) const;
|
||||
bool matches_dimension_percentage(BaseType) const;
|
||||
|
||||
Array<Optional<i32>, to_underlying(BaseType::__Count)> m_type_exponents;
|
||||
Optional<BaseType> m_percent_hint;
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue