From b81bee492743258de211d0400642c5275a986f15 Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Fri, 28 Nov 2025 12:57:30 +0100 Subject: [PATCH 1/5] vaev-webdriver: Added a simple print sandbox. --- src/vaev-webdriver/res/print.html | 414 ++++++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 src/vaev-webdriver/res/print.html diff --git a/src/vaev-webdriver/res/print.html b/src/vaev-webdriver/res/print.html new file mode 100644 index 00000000..d314efbc --- /dev/null +++ b/src/vaev-webdriver/res/print.html @@ -0,0 +1,414 @@ + + + + + PDF Sandbox (WebDriver2) + + + +
+ +
+
Code
+
+
+ + +
+
+ +
+
+
+ +
+ + +
+
PDF Output
+
+
+ Rendering… +
+ +
+
+ +
+ + +
+
Print Settings
+
+
+ Page +
+ +
+
+ +
+
+ +
+
+ +
+ Margins (cm) +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ Options +
+ +
+
+ +
+
+
+
+
+ + + + From 21741e5ec78c3395562ca71c9d53a3b942a0f49e Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Wed, 3 Dec 2025 13:35:12 +0100 Subject: [PATCH 2/5] (wip) vaev-style: Added support for dynamic property registration. --- src/vaev-engine/css/lexer.cpp | 18 +- src/vaev-engine/css/parser.cpp | 56 +- src/vaev-engine/manifest.json | 1 + src/vaev-engine/props/align.cpp | 291 ++ src/vaev-engine/props/background.cpp | 301 ++ src/vaev-engine/props/base.cpp | 495 +++ src/vaev-engine/props/baseline.cpp | 156 + src/vaev-engine/props/border.cpp | 1179 +++++++ src/vaev-engine/props/breaks.cpp | 120 + src/vaev-engine/props/defs/properties.inc | 517 +++ src/vaev-engine/props/display.cpp | 119 + src/vaev-engine/props/flex.cpp | 339 ++ src/vaev-engine/props/floats.cpp | 84 + src/vaev-engine/props/fonts.cpp | 304 ++ src/vaev-engine/props/margin.cpp | 402 +++ src/vaev-engine/props/mod.cpp | 24 + src/vaev-engine/props/outline.cpp | 228 ++ src/vaev-engine/props/overflow.cpp | 209 ++ src/vaev-engine/props/padding.cpp | 260 ++ src/vaev-engine/props/positioned.cpp | 222 ++ src/vaev-engine/props/registry.cpp | 227 ++ src/vaev-engine/props/sizing.cpp | 284 ++ src/vaev-engine/props/svg.cpp | 580 ++++ src/vaev-engine/props/table.cpp | 88 + src/vaev-engine/props/text.cpp | 183 + src/vaev-engine/props/transform.cpp | 174 + src/vaev-engine/props/visibility.cpp | 140 + src/vaev-engine/style/computer.cpp | 74 +- src/vaev-engine/style/decls.cpp | 212 +- src/vaev-engine/style/page.cpp | 11 +- src/vaev-engine/style/props-impl.cpp | 163 - src/vaev-engine/style/props.cpp | 3751 --------------------- src/vaev-engine/style/rules.cpp | 43 +- src/vaev-engine/style/specified-impl.cpp | 10 +- src/vaev-engine/style/specified.cpp | 4 +- src/vaev-engine/style/stylesheet.cpp | 8 +- src/vaev-engine/values/background.cpp | 14 +- src/vaev-engine/values/base.cpp | 6 +- src/vaev-engine/values/defs/keywords.inc | 2 + 39 files changed, 7086 insertions(+), 4213 deletions(-) create mode 100644 src/vaev-engine/props/align.cpp create mode 100644 src/vaev-engine/props/background.cpp create mode 100644 src/vaev-engine/props/base.cpp create mode 100644 src/vaev-engine/props/baseline.cpp create mode 100644 src/vaev-engine/props/border.cpp create mode 100644 src/vaev-engine/props/breaks.cpp create mode 100644 src/vaev-engine/props/defs/properties.inc create mode 100644 src/vaev-engine/props/display.cpp create mode 100644 src/vaev-engine/props/flex.cpp create mode 100644 src/vaev-engine/props/floats.cpp create mode 100644 src/vaev-engine/props/fonts.cpp create mode 100644 src/vaev-engine/props/margin.cpp create mode 100644 src/vaev-engine/props/mod.cpp create mode 100644 src/vaev-engine/props/outline.cpp create mode 100644 src/vaev-engine/props/overflow.cpp create mode 100644 src/vaev-engine/props/padding.cpp create mode 100644 src/vaev-engine/props/positioned.cpp create mode 100644 src/vaev-engine/props/registry.cpp create mode 100644 src/vaev-engine/props/sizing.cpp create mode 100644 src/vaev-engine/props/svg.cpp create mode 100644 src/vaev-engine/props/table.cpp create mode 100644 src/vaev-engine/props/text.cpp create mode 100644 src/vaev-engine/props/transform.cpp create mode 100644 src/vaev-engine/props/visibility.cpp delete mode 100644 src/vaev-engine/style/props-impl.cpp delete mode 100644 src/vaev-engine/style/props.cpp diff --git a/src/vaev-engine/css/lexer.cpp b/src/vaev-engine/css/lexer.cpp index 6c64dab8..a1a5a40a 100644 --- a/src/vaev-engine/css/lexer.cpp +++ b/src/vaev-engine/css/lexer.cpp @@ -65,7 +65,7 @@ export struct Token { } void repr(Io::Emit& e) const { - if (not *this) { + if (not*this) { e("nil"); return; } @@ -207,19 +207,21 @@ static auto const RE_NUMBER = Re::chain( export struct Lexer { Io::SScan _scan; - Token _curr; Lexer(Str text) : _scan(text) { - _curr = _next(_scan); } Lexer(Io::SScan const& scan) : _scan(scan) { - _curr = _next(_scan); } - Token peek() const { - return _curr; + Token peek(usize offset = 1) const { + Io::SScan scan = _scan; + Token res = Token::NIL; + for (auto _ : range(offset)) { + res = _next(scan); + } + return res; } Token _nextIdent(Io::SScan& s) const { @@ -392,9 +394,7 @@ export struct Lexer { } Token next() { - auto res = _curr; - _curr = _next(_scan); - return res; + return _next(_scan); } bool ended() const { diff --git a/src/vaev-engine/css/parser.cpp b/src/vaev-engine/css/parser.cpp index c87f83d2..391ae44a 100644 --- a/src/vaev-engine/css/parser.cpp +++ b/src/vaev-engine/css/parser.cpp @@ -17,6 +17,11 @@ export struct Sst; export using Content = Vec; +export enum struct Important { + UNSET, + YES, +}; + #define FOREACH_SST(SST) \ SST(RULE) \ SST(FUNC) \ @@ -40,6 +45,7 @@ export struct Sst { Token token = Token(Token::NIL); Opt> prefix{}; Content content{}; + Important important = Important::UNSET; Sst(Type type) : type(type) {} @@ -47,6 +53,11 @@ export struct Sst { Sst(Content content) : type(LIST), content(content) {} + // https://drafts.csswg.org/css-variables-2/#guaranteed-invalid + static Sst guaranteedInvalid() { + return Token::badString(""); + } + void repr(Io::Emit& e) const { if (type == TOKEN) { e("{}", token); @@ -200,18 +211,48 @@ Sst consumeAtRule(Lexer& lex) { } } -export Content consumeDeclarationValue(Lexer& lex) { +Important consumeImportant(Lexer& lex) { + if (lex.peek() != Css::Token::delim("!")) + return Important::UNSET; + lex.next(); + + auto copy = lex; + eatWhitespace(copy); + if (copy.next() != Css::Token::ident("important")) + return Important::UNSET; + lex = copy; + return Important::YES; +} + +export bool endedDeclarationValue(Lexer& lex) { + return lex.peek() == Token::END_OF_FILE or + lex.peek() == Token::SEMICOLON or + lex.peek() == Token::RIGHT_CURLY_BRACKET; +} + +export Tuple consumeDeclarationValue(Lexer& lex) { Content value; + // 3. While the next input token is a , consume the next input token. eatWhitespace(lex); // 4. As long as the next input token is anything other than an , // consume a component value and append it to the declaration’s value. - while ((lex.peek() != Token::END_OF_FILE and lex.peek() != Token::SEMICOLON and lex.peek() != Token::RIGHT_CURLY_BRACKET)) { - value.pushBack(consumeComponentValue(lex)); - eatWhitespace(lex); + while (endedDeclarationValue(lex)) { + // 5. If the last two non-s in the declaration’s + // value are a with the value "!" followed by an + // with a value that is an ASCII case-insensitive match + // for "important", remove them from the declaration’s value + // and set the declaration’s important flag to true. + if (consumeImportant(lex) == Important::YES) { + eatWhitespace(lex); + return {std::move(value), Important::UNSET}; + } else { + value.pushBack(consumeComponentValue(lex)); + eatWhitespace(lex); + } } - return value; + return {std::move(value), Important::UNSET}; } // https://www.w3.org/TR/css-syntax-3/#consume-style-block @@ -286,6 +327,7 @@ Content consumeDeclarationBlock(Lexer& lex) { return res; } +// https://www.w3.org/TR/css-syntax-3/#consume-declaration export Opt consumeDeclaration(Lexer& lex) { Sst decl{Sst::DECL}; decl.token = lex.next(); @@ -303,7 +345,9 @@ export Opt consumeDeclaration(Lexer& lex) { lex.next(); // Parse the declaration’s value. - decl.content = consumeDeclarationValue(lex); + auto [content, important] = consumeDeclarationValue(lex); + decl.content = std::move(content); + decl.important = important; return decl; } diff --git a/src/vaev-engine/manifest.json b/src/vaev-engine/manifest.json index ec55a676..28159bdc 100644 --- a/src/vaev-engine/manifest.json +++ b/src/vaev-engine/manifest.json @@ -12,6 +12,7 @@ "layout/base", "layout/builder", "loader", + "props", "style", "values", "xml" diff --git a/src/vaev-engine/props/align.cpp b/src/vaev-engine/props/align.cpp new file mode 100644 index 00000000..2bb0517b --- /dev/null +++ b/src/vaev-engine/props/align.cpp @@ -0,0 +1,291 @@ +module; + +#include + +export module Vaev.Engine:props.align; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Align ----------------------------------------------------------------- +// https://drafts.csswg.org/css-align-3 + +// https://drafts.csswg.org/css-align-3/#propdef-align-content +export struct AlignContentProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ALIGN_CONTENT; + } + + Rc initial() const override { + return makeRc(self(), Align::Keywords::STRETCH); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.alignContent); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + AlignContentProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.alignContent = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#propdef-justify-content +export struct JustifyContentProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::JUSTIFY_CONTENT; + } + + Rc initial() const override { + return makeRc(self(), Align::Keywords::FLEX_START); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.justifyContent); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + JustifyContentProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.justifyContent = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#propdef-justify-self +export struct JustifySelfProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::JUSTIFY_ITEMS; + } + + Rc initial() const override { + return makeRc(self(), Align{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.justifySelf); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + JustifySelfProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.justifySelf = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#propdef-align-self +export struct AlignSelfProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ALIGN_SELF; + } + + Rc initial() const override { + return makeRc(self(), Align::Keywords::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.alignSelf); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + AlignSelfProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.alignSelf = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#propdef-justify-items +export struct JustifyItemsProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::JUSTIFY_ITEMS; + } + + Rc initial() const override { + return makeRc(self(), Align{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.justifyItems); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + JustifyItemsProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.justifyItems = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#propdef-align-items +export struct AlignItemsProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ALIGN_ITEMS; + } + + Rc initial() const override { + return makeRc(self(), Align::Keywords::STRETCH); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.aligns.alignItems); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Align _value; + + AlignItemsProperty(Rc registration, Align value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.aligns.alignItems = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#column-row-gap +export struct RowGapProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ROW_GAP; + } + + Rc initial() const override { + return makeRc(self(), Keywords::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.gaps->y); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gap _value; + + RowGapProperty(Rc registration, Gap value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.gaps.cow().y = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-align-3/#column-row-gap +export struct ColumnGapProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::COLUMN_GAP; + } + + Rc initial() const override { + return makeRc(self(), Keywords::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.gaps->x); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gap _value; + + ColumnGapProperty(Rc registration, Gap value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.gaps.cow().x = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/background.cpp b/src/vaev-engine/props/background.cpp new file mode 100644 index 00000000..d2fd450a --- /dev/null +++ b/src/vaev-engine/props/background.cpp @@ -0,0 +1,301 @@ +module; + +#include + +export module Vaev.Engine:props.background; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; +import :values.base; +import :values.primitives; +import :values.background; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Background Color ------------------------------------------------------ + +// https://www.w3.org/TR/CSS22/colors.html#propdef-background-color +export struct BackgroundColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND_COLOR; + } + + Rc initial() const override { + return makeRc(self(), TRANSPARENT); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.backgrounds->color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + BackgroundColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.backgrounds.cow().color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// MARK: Background Image ------------------------------------------------------ + +// https://www.w3.org/TR/CSS22/colors.html#propdef-background-attachment +export struct BackgroundAttachmentProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND_ATTACHMENT; + } + + Rc initial() const override { + return makeRc(self(), Vec{Keywords::SCROLL}); + } + + Rc load(SpecifiedValues const& c) const override { + Vec layers; + for (auto const& l : c.backgrounds->layers) + layers.pushBack(l.attachment); + return makeRc(self(), std::move(layers)); + } + + Res> parse(Cursor& c) const override { + + Vec value; + while (not c.ended()) { + value.pushBack(try$(parseValue(c))); + eatWhitespace(c); + } + + return Ok(makeRc(self(), std::move(value))); + } + }; + + Vec _value; + + BackgroundAttachmentProperty(Rc registration, Vec value) + : Property(registration), _value(std::move(value)) {} + + void apply(SpecifiedValues& c) const override { + auto& layers = c.backgrounds.cow().layers; + layers.resize(max(layers.len(), _value.len())); + for (usize i = 0; i < _value.len(); ++i) + layers[i].attachment = _value[i]; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/colors.html#propdef-background-image +export struct BackgroundImageProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND_IMAGE; + } + + Rc initial() const override { + return makeRc(self(), Vec{}); + } + + Rc load(SpecifiedValues const&) const override { + return makeRc(self(), Vec{}); + } + + Res> parse(Cursor&) const override { + // TODO + return Ok(makeRc(self(), Vec{})); + } + }; + + Vec _value; + + BackgroundImageProperty(Rc registration, Vec value) + : Property(registration), _value(std::move(value)) {} + + void apply(SpecifiedValues&) const override { + // TODO + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/colors.html#propdef-background-position +export struct BackgroundPositionProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND_POSITION; + } + + Rc initial() const override { + return makeRc(self(), Vec{}); + } + + Rc load(SpecifiedValues const&) const override { + return makeRc(self(), Vec{}); + } + + Res> parse(Cursor&) const override { + // TODO + return Ok(makeRc(self(), Vec{})); + } + }; + + Vec _value; + + BackgroundPositionProperty(Rc registration, Vec value) + : Property(registration), _value(std::move(value)) {} + + void apply(SpecifiedValues&) const override { + // TODO + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/colors.html#propdef-background-repeat +export struct BackgroundRepeatProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND_REPEAT; + } + + Rc initial() const override { + return makeRc(self(), Vec{BackgroundRepeat::REPEAT}); + } + + Rc load(SpecifiedValues const&) const override { + return makeRc(self(), Vec{}); + } + + Res> parse(Cursor&) const override { + // TODO + return Ok(makeRc(self(), Vec{})); + } + }; + + Vec _value; + + BackgroundRepeatProperty(Rc registration, Vec value) + : Property(registration), + _value(std::move(value)) {} + + void apply(SpecifiedValues&) const override { + // TODO + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/colors.html#x10 +export struct BackgroundProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BACKGROUND; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), BackgroundProps{TRANSPARENT}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), *c.backgrounds); + } + + Res> parse(Cursor& c) const override { + BackgroundProps value; + value.color = try$(parseValue(c)); + return Ok(makeRc(self(), std::move(value))); + } + }; + + BackgroundProps _value; + + BackgroundProperty(Rc registration, BackgroundProps value) + : Property(registration), _value(std::move(value)) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc( + registry.resolveRegistration(Properties::BACKGROUND_COLOR).unwrap(), + _value.color + ), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/colors.html#propdef-color +export struct ColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::COLOR; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), BLACK); + } + + void inherit(SpecifiedValues const& parent, SpecifiedValues& child) override { + child.color = parent.color; + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + ColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.color = resolve(_value, Gfx::BLACK); + } + + void apply(SpecifiedValues const& parent, SpecifiedValues& c) const override { + c.color = resolve(_value, parent.color); + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/base.cpp b/src/vaev-engine/props/base.cpp new file mode 100644 index 00000000..31b9811b --- /dev/null +++ b/src/vaev-engine/props/base.cpp @@ -0,0 +1,495 @@ +module; + +#include + +export module Vaev.Engine:props.base; + +import Karm.Core; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +namespace Properties { + +#define PROPERTY(NAME, VALUE) export Symbol NAME = Symbol::from(VALUE); +#include "defs/properties.inc" +#undef PROPERTY + +} // namespace Properties + +export struct PropertyRegistry; + +export struct Property : Meta::NoCopy { + enum struct Options : u8 { + // https://drafts.csswg.org/css-cascade-5/#inherited-value + INHERITED = 1 << 0, + + // https://drafts.csswg.org/css-cascade-5/#shorthand + SHORTHAND = 1 << 1, + + // https://drafts.csswg.org/css-variables-2/#custom-property + CUSTOM_PROPERTY = 1 << 2, + + // https://svgwg.org/svg2-draft/styling.html#PresentationAttributes + PRESENTATION_ATTRIBUTE = 1 << 3, + + // Represent a miss-parsed property + BOGUS = 1 << 4, + + // The property is not reset by all: + // https://drafts.csswg.org/css-cascade/#all-shorthand + ALL_EXCLUDED = 1 << 5 + }; + + using enum Options; + + // https://drafts.css-houdini.org/css-properties-values-api/#custom-property-registration + struct Registration : Meta::NoCopy { + Opt> _self; + + Rc self() const { + return _self + .unwrap("node not self bound") + .upgrade() + .unwrap(); + } + + virtual ~Registration() = default; + + virtual Symbol name() const = 0; + + virtual Flags flags() const { + return {}; + } + + virtual Rc initial() const = 0; + + virtual Rc load(SpecifiedValues const& c) const = 0; + + virtual void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { + // NOTE: This is the slow fallback path for properties that are not + // commonly inherited. Any property marked with the INHERITED + // flag should override this method with a faster implementation. + if (flags().has(INHERITED)) + panic("property marked as INHERITED is using the slow fallback path. override inherit()!"); + load(parent)->apply(child); + } + + virtual Res> parse(Cursor& c) const = 0; + + // https://svgwg.org/svg2-draft/styling.html#PresentationAttributes + virtual Res> parsePresentationAttribute(Str style) { + Css::Lexer lex{style}; + auto [content, _] = Css::consumeDeclarationValue(lex); + Cursor cursor = content; + return parse(cursor); + } + }; + + Rc registration; + Css::Important important = Css::Important::UNSET; + + Property(Rc registration) + : registration(registration) {} + + virtual ~Property() = default; + + virtual Vec> explodeShorthand(PropertyRegistry&) const { + panic("shorthand property is missing explodeShorthand() implementation"); + } + + virtual void apply(SpecifiedValues& child) const { + (void)child; + panic("longhand property is missing apply() implementation"); + } + + virtual void apply(SpecifiedValues const& parent, SpecifiedValues& child) const { + (void)parent; + apply(child); + } + + virtual void repr(Io::Emit& e) const = 0; + + // Helpers + bool isCustomProperty() const { + return registration->flags().has(CUSTOM_PROPERTY); + } + + bool isBogusOr +}; + +// MARK: Custom Property ------------------------------------------------------- + +// https://drafts.csswg.org/css-variables/#defining-variables +// this symbolizes a custom property, it starts with `--` and can be used to store a value that can be reused in the stylesheet +struct CustomProperty : Property { + struct Registration : Property::Registration { + Symbol _name; + + Registration(Symbol name) : _name(name) { + } + + Symbol name() const override { + return _name; + } + + Flags flags() const override { + return {INHERITED, CUSTOM_PROPERTY, ALL_EXCLUDED}; + } + + Rc initial() const override { + return makeRc( + self(), Css::Content{Css::Sst::guaranteedInvalid()} + ); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.getCustomProp(_name)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), Css::Content{c.rem()})); + }; + }; + + Css::Content _value; + + CustomProperty(Rc registration, Css::Content value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& child) const override { + child.setCustomProp(registration->name(), _value); + } + + void repr(Io::Emit& e) const override { + e("(custom {})", _value); + } +}; + +// MARK: Deferred Property ------------------------------------------------------ + +// NOTE: A property that could not be parsed, it's used to store the value +// as-is and apply it with the cascade and custom properties +struct DeferredProperty : Property { + enum struct Policy { + ALLOW, + DISALLOW, + }; + + Css::Content _value; + + DeferredProperty(Rc registration, Css::Content value) + : Property(registration), _value(value) {} + + static bool _expandVariable(Cursor& c, Map const& env, Css::Content& out) { + if (not(c->type == Css::Sst::FUNC and + c->prefix == Css::Token::function("var("))) { + return false; + } + + Cursor content = c->content; + + eatWhitespace(content); + if (content.ended()) + return true; + + if (content.peek() != Css::Token::IDENT) + return true; + + Symbol varName = Symbol::from(content->token.data); + if (auto ref = env.access(varName)) { + Cursor varContent = *ref; + _expandContent(varContent, env, out); + return true; + } + content.next(); + + eatWhitespace(content); + + if (not content.skip(Css::Token::COMMA)) + return true; + + _expandContent(content, env, out); + return true; + } + + static bool _expandFunction(Cursor& c, Map const& env, Css::Content& out) { + if (c->type != Css::Sst::FUNC) + return false; + + auto& func = out.emplaceBack(Css::Sst::FUNC); + func.prefix = c->prefix; + Cursor content = c->content; + _expandContent(content, env, func.content); + + return true; + } + + static void _expandContent(Cursor& c, Map const& env, Css::Content& out) { + // NOTE: Hint that we will add all the remaining elements + out.ensure(out.len() + c.rem()); + + while (not c.ended()) { + if (not _expandVariable(c, env, out) and + not _expandFunction(c, env, out)) { + out.pushBack(*c); + } + + c.next(); + } + } + + void apply(SpecifiedValues const& parent, SpecifiedValues& child) const override { + Cursor cursor = _value; + Css::Content out; + _expandContent(cursor, *child.variables, out); + + cursor = out; + auto prop = registration->parse(cursor); + if (not prop) { + logWarn("failed to parse declaration: {}: {}", registration->name(), prop); + return; + } + prop.unwrap()->apply(parent, child); + } + + void repr(Io::Emit& e) const override { + e("(deferred {})", _value); + } +}; + +// MARK: Defaulted Property ---------------------------------------------------- + +enum struct Default { + INITIAL, //< represents the value defined as the property’s initial value. + INHERIT, //< represents the property’s computed value on the parent element. + UNSET, //< acts as either inherit or initial, depending on whether the property is inherited or not. + REVERT, //< rolls back the cascade to the cascaded value of the earlier origin. + + _LEN, +}; + +struct DefaultedProperty : Property { + Default _value; + + DefaultedProperty(Rc registration, Default value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues const& parent, SpecifiedValues& child) const override { + if (_value == Default::INITIAL) { + // The initial CSS-wide keyword represents the value + // defined as the property’s initial value. + // https://drafts.csswg.org/css-cascade/#initial + registration->initial()->apply(parent, child); + } else if (_value == Default::INHERIT) { + // The inherit CSS-wide keyword represents the property’s + // computed value on the parent element. + // https://drafts.csswg.org/css-cascade/#inherit + registration->load(parent)->apply(child); + } else if (_value == Default::UNSET) { + // The unset CSS-wide keyword acts as either inherit or initial, + // depending on whether the property is inherited or not. + // https://drafts.csswg.org/css-cascade/#inherit-initial + if (registration->flags().has(INHERITED)) + registration->load(parent)->apply(child); + else + registration->initial()->apply(parent, child); + + } else { + unreachable(); + } + } + + void repr(Io::Emit& e) const override { + e("(defaulted {})", _value); + } +}; + +// MARK: Buggus Property ------------------------------------------------------- + +// Represent a property that could not be parsed +struct BogusProperty : Property { + struct Registration : Property::Registration { + Symbol _name; + + Registration(Symbol name) + : _name(name) {} + + Flags flags() const override { + return {BOGUS}; + } + + Symbol name() const override { + return _name; + } + + Rc initial() const override { + unreachable(); + } + + Rc load(SpecifiedValues const&) const override { + unreachable(); + } + + Res> parse(Cursor&) const override { + unreachable(); + } + }; + + Css::Content _value; + Error _error; + + BogusProperty(Rc registration, Css::Content value, Error error) + : Property(registration), + _value(value), + _error(error) {} + + void repr(Io::Emit& e) const override { + e("{} (error:{})", _value, _error); + } +}; + +// MARK: Property Registry ----------------------------------------------------- + +static Map LEGACY_ALIAS = { + // https://drafts.csswg.org/css-align-3/#gap-legacy + {"grid-row-gap"_sym, "row-gap"_sym}, + {"grid-column-gap"_sym, "column-gap"_sym}, + {"grid-gap"_sym, "gap"_sym}, +}; + +export struct PropertyRegistry { + Map> _registrations; + Vec> _presentationAttributes; + + template + void registerProperty() { + auto registration = makeRc(); + registration->_self = registration; + _registrations.put(registration->name(), registration); + } + + Rc registerCustomProperty(Symbol propertyName) { + auto registration = makeRc(propertyName); + if (registration->flags().has(Property::PRESENTATION_ATTRIBUTE)) + _presentationAttributes.pushBack(registration); + _registrations.put(propertyName, registration); + return registration; + } + + Rc resolveRegistration(Symbol propertyName) { + propertyName = LEGACY_ALIAS.tryGet(propertyName).unwrapOr(propertyName); + + if (auto maybeRegistration = _registrations.tryGet(propertyName)) + return maybeRegistration.take(); + + if (startWith(propertyName.str(), "--"s) != Match::NO) + return registerCustomProperty(propertyName); + + return makeRc(propertyName); + } + + Opt> resolveRegistration(Str propertyName) { + return resolveRegistration(Symbol::from(propertyName)); + } + + // MARK: Value Parsing ----------------------------------------------------- + + Res> _parseDefaulted(Rc registration, Cursor& content) { + Default value; + if (content.skip(Css::Token::ident("initial"))) { + value = Default::INITIAL; + } else if (content.skip(Css::Token::ident("inherit"))) { + value = Default::INHERIT; + } else if (content.skip(Css::Token::ident("unset"))) { + value = Default::UNSET; + } else if (content.skip(Css::Token::ident("revert"))) { + value = Default::REVERT; + } else { + return Error::invalidData("unknown declaration"); + } + + return Ok(makeRc(registration, value)); + } + + Rc _deferProperty(Rc registration, Slice content) { + return makeRc(registration, content); + } + + Rc parseValue(Symbol propertyName, Slice content) { + Cursor cursor = content; + + auto registration = resolveRegistration(propertyName); + + eatWhitespace(cursor); + if (auto defaulted = _parseDefaulted(registration, cursor)) + return defaulted.take(); + + auto maybeProp = registration->parse(cursor); + if (not maybeProp) + return _deferProperty(registration, content); + + eatWhitespace(cursor); + if (not cursor.ended()) { + auto registration = makeRc(propertyName); + return makeRc(registration, content, Error::invalidData("un-consumed token in property value")); + } + + return maybeProp.take(); + } + + // MARK: Declaration Parsing ----------------------------------------------- + + Res> parseDeclaration(Css::Sst const& sst) { + if (sst != Css::Sst::DECL) + panic("expected declaration"); + + if (sst.token != Css::Token::IDENT) + panic("expected ident"); + + auto propertyName = Symbol::from(sst.token.data); + Cursor content = sst.content; + auto prop = parseValue(propertyName, content); + prop->important = sst.important; + return Ok(prop); + } + + Rc parseDeclaration(Symbol propertyName, Str propertyValue) { + Css::Lexer lex{propertyValue}; + auto [content, _] = Css::consumeDeclarationValue(lex); + return parseValue(propertyName, content); + } + + Vec> parseDeclarations(Css::Content const& sst) { + Vec> res; + + for (auto const& item : sst) { + if (item != Css::Sst::DECL) + continue; + + auto prop = parseDeclaration(item); + + if (not prop) + continue; + + res.pushBack(prop.take()); + } + + return res; + } + + Vec> parseDeclarations(Css::Sst const& sst) { + return parseDeclarations(sst.content); + } + + Vec> parseDeclarations(Str style) { + Css::Lexer lex{style}; + auto sst = Css::consumeDeclarationList(lex, true); + return parseDeclarations(sst); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/baseline.cpp b/src/vaev-engine/props/baseline.cpp new file mode 100644 index 00000000..cae54ad8 --- /dev/null +++ b/src/vaev-engine/props/baseline.cpp @@ -0,0 +1,156 @@ +module; + +#include + +export module Vaev.Engine:props.baseline; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// https://drafts.csswg.org/css-inline/#line-height-property +export struct LineHeightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::LINE_HEIGHT; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), LineHeight::NORMAL); + } + + Rc load(SpecifiedValues const&) const override { + return makeRc(self(), LineHeight::NORMAL); // TODO + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + LineHeight _value; + + LineHeightProperty(Rc registration, LineHeight value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues&) const override { + // TODO + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-inline-3/#dominant-baseline-property +export struct DominantBaselineProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::DOMINANT_BASELINE; + } + + Rc initial() const override { + return makeRc(self(), Keywords::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.baseline->dominant); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + DominantBaseline _value; + + DominantBaselineProperty(Rc registration, DominantBaseline value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.baseline.cow().dominant = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-inline-3/#baseline-source +export struct BaselineSourceProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BASELINE_SOURCE; + } + + Rc initial() const override { + return makeRc(self(), Keywords::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.baseline->source); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BaselineSource _value; + + BaselineSourceProperty(Rc registration, BaselineSource value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.baseline.cow().source = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-inline-3/#alignment-baseline-property +export struct AlignmentBaselineProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ALIGNMENT_BASELINE; + } + + Rc initial() const override { + return makeRc(self(), Keywords::BASELINE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.baseline->alignment); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + AlignmentBaseline _value; + + AlignmentBaselineProperty(Rc registration, AlignmentBaseline value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.baseline.cow().alignment = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/border.cpp b/src/vaev-engine/props/border.cpp new file mode 100644 index 00000000..6bbad3e5 --- /dev/null +++ b/src/vaev-engine/props/border.cpp @@ -0,0 +1,1179 @@ +module; + +#include + +export module Vaev.Engine:props.border; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Borders --------------------------------------------------------------- + +// https://www.w3.org/TR/CSS22/box.html#propdef-border-color +export struct BorderTopColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_top-color"_sym; + } + + Rc initial() const override { + return makeRc(self(), BLACK); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->top.color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + BorderTopColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().top.color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#propdef-border-color +export struct BorderRightColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_right-color"_sym; + } + + Rc initial() const override { + return makeRc(self(), BLACK); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->end.color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + BorderRightColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().end.color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#propdef-border-color +export struct BorderBottomColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_bottom-color"_sym; + } + + Rc initial() const override { + return makeRc(self(), BLACK); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->bottom.color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + BorderBottomColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().bottom.color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#propdef-border-color +export struct BorderLeftColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_left-color"_sym; + } + + Rc initial() const override { + return makeRc(self(), BLACK); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->start.color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Color _value; + + BorderLeftColorProperty(Rc registration, Color value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().start.color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct BorderColorProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_COLOR; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{BLACK}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc( + self(), + Math::Insets{ + c.borders->start.color, + c.borders->end.color, + c.borders->top.color, + c.borders->bottom.color, + } + ); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + BorderColorProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.top), + makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.end), + makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.start), + }; + } + + void apply(SpecifiedValues& c) const override { + auto& borders = c.borders.cow(); + borders.start.color = _value.start; + borders.end.color = _value.end; + borders.top.color = _value.top; + borders.bottom.color = _value.bottom; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#border-style-properties +export struct BorderLeftStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_left-style"_sym; + } + + Rc initial() const override { + return makeRc(self(), Gfx::BorderStyle::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->start.style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gfx::BorderStyle _value; + + BorderLeftStyleProperty(Rc registration, Gfx::BorderStyle value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().start.style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#border-style-properties +export struct BorderTopStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_top-style"_sym; + } + + Rc initial() const override { + return makeRc(self(), Gfx::BorderStyle::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->top.style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gfx::BorderStyle _value; + + BorderTopStyleProperty(Rc registration, Gfx::BorderStyle value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().top.style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#border-style-properties +export struct BorderRightStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_right-style"_sym; + } + + Rc initial() const override { + return makeRc(self(), Gfx::BorderStyle::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->end.style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gfx::BorderStyle _value; + + BorderRightStyleProperty(Rc registration, Gfx::BorderStyle value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().end.style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#border-style-properties +export struct BorderBottomStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_bottom-style"_sym; + } + + Rc initial() const override { + return makeRc(self(), Gfx::BorderStyle::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->bottom.style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Gfx::BorderStyle _value; + + BorderBottomStyleProperty(Rc registration, Gfx::BorderStyle value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().bottom.style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/box.html#border-style-properties + +export struct BorderStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_STYLE; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{Gfx::BorderStyle::NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc( + self(), + Math::Insets{ + c.borders->start.style, + c.borders->end.style, + c.borders->top.style, + c.borders->bottom.style, + } + ); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + BorderStyleProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.top), + makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.end), + makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.start), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-width +export struct BorderTopWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_top-width"_sym; + } + + Rc initial() const override { + return makeRc(self(), Keywords::MEDIUM); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->top.width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + LineWidth _value; + + BorderTopWidthProperty(Rc registration, LineWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().top.width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-width +export struct BorderRightWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_right-width"_sym; + } + + Rc initial() const override { + return makeRc(self(), Keywords::MEDIUM); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->end.width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + LineWidth _value; + + BorderRightWidthProperty(Rc registration, LineWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().end.width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-width +export struct BorderBottomWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_bottom-width"_sym; + } + + Rc initial() const override { + return makeRc(self(), Keywords::MEDIUM); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->bottom.width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + LineWidth _value; + + BorderBottomWidthProperty(Rc registration, LineWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().bottom.width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-width +export struct BorderLeftWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_left-width"_sym; + } + + Rc initial() const override { + return makeRc(self(), Keywords::MEDIUM); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->start.width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + LineWidth _value; + + BorderLeftWidthProperty(Rc registration, LineWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().start.width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-backgrounds/#the-border-radius +export struct BorderRadiusTopRightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_top-right-radius"_sym; + } + + Rc initial() const override { + return makeRc(self(), makeArray>, 2>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Array{ + c.borders->radii.c, + c.borders->radii.d, + }); + } + + Res> parse(Cursor& c) const override { + auto first = try$(parseValue>>(c)); + Array value{first, first}; + if (not c.ended()) + value[1] = try$(parseValue>>(c)); + return Ok(makeRc(self(), value)); + } + }; + + Array>, 2> _value; + + BorderRadiusTopRightProperty(Rc registration, Array>, 2> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().radii.c = _value[0]; + c.borders.cow().radii.d = _value[1]; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-backgrounds/#the-border-radius +export struct BorderRadiusTopLeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_top-left-radius"_sym; + } + + Rc initial() const override { + return makeRc(self(), makeArray>, 2>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc( + self(), + Array{ + c.borders->radii.a, + c.borders->radii.b, + } + ); + } + + Res> parse(Cursor& c) const override { + auto first = try$(parseValue>>(c)); + Array value{first, first}; + if (not c.ended()) + value[1] = try$(parseValue>>(c)); + return Ok(makeRc(self(), value)); + } + }; + + Array>, 2> _value; + + BorderRadiusTopLeftProperty(Rc registration, Array>, 2> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().radii.a = _value[1]; + c.borders.cow().radii.b = _value[0]; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-backgrounds/#the-border-radius +export struct BorderRadiusBottomRightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_bottom-right-radius"_sym; + } + + Rc initial() const override { + return makeRc(self(), makeArray>, 2>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Array{ + c.borders->radii.e, + c.borders->radii.f, + }); + } + + Res> parse(Cursor& c) const override { + auto first = try$(parseValue>>(c)); + Array value{first, first}; + if (not c.ended()) + value[1] = try$(parseValue>>(c)); + return Ok(makeRc(self(), value)); + } + }; + + Array>, 2> _value; + + BorderRadiusBottomRightProperty(Rc registration, Array>, 2> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().radii.e = _value[1]; + c.borders.cow().radii.f = _value[0]; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-backgrounds/#the-border-radius +export struct BorderRadiusBottomLeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "border_bottom-left-radius"_sym; + } + + Rc initial() const override { + return makeRc(self(), makeArray>, 2>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc( + self(), + Array{ + c.borders->radii.g, + c.borders->radii.h, + } + ); + } + + Res> parse(Cursor& c) const override { + auto first = try$(parseValue>>(c)); + Array value{first, first}; + if (not c.ended()) + value[1] = try$(parseValue>>(c)); + return Ok(makeRc(self(), value)); + } + }; + + Array>, 2> _value; + + BorderRadiusBottomLeftProperty(Rc registration, Array>, 2> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().radii.g = _value[0]; + c.borders.cow().radii.h = _value[1]; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-backgrounds/#the-border-radius +export struct BorderRadiusProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_RADIUS; + } + + Rc initial() const override { + return makeRc(self(), Math::Radii{CalcValue>(Length{})}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->radii); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>>(c)))); + } + }; + + Math::Radii>> _value; + + BorderRadiusProperty(Rc registration, Math::Radii>> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.borders.cow().radii = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands +export struct BorderTopProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_TOP; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Border{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->top); + } + + Res> parse(Cursor& c) const override { + Border value; + while (not c.ended()) { + auto width = parseValue>(c); + if (width) { + value.width = width.unwrap(); + continue; + } + + auto color = parseValue(c); + if (color) { + value.color = color.unwrap(); + continue; + } + + auto style = parseValue(c); + if (style) { + value.style = style.unwrap(); + continue; + } + + break; + } + return Ok(makeRc(self(), value)); + } + }; + + Border _value; + + BorderTopProperty(Rc registration, Border value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands +export struct BorderRightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_RIGHT; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Border{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->end); + } + + Res> parse(Cursor& c) const override { + Border value; + while (not c.ended()) { + auto width = parseValue>(c); + if (width) { + value.width = width.unwrap(); + continue; + } + + auto color = parseValue(c); + if (color) { + value.color = color.unwrap(); + continue; + } + + auto style = parseValue(c); + if (style) { + value.style = style.unwrap(); + continue; + } + + break; + } + return Ok(makeRc(self(), value)); + } + }; + + Border _value; + + BorderRightProperty(Rc registration, Border value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands +export struct BorderBottomProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_BOTTOM; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Border{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->bottom); + } + + Res> parse(Cursor& c) const override { + Border value; + while (not c.ended()) { + auto width = parseValue>(c); + if (width) { + value.width = width.unwrap(); + continue; + } + + auto color = parseValue(c); + if (color) { + value.color = color.unwrap(); + continue; + } + + auto style = parseValue(c); + if (style) { + value.style = style.unwrap(); + continue; + } + + break; + } + return Ok(makeRc(self(), value)); + } + }; + + Border _value; + + BorderBottomProperty(Rc registration, Border value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands +export struct BorderLeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_LEFT; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Border{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->start); + } + + Res> parse(Cursor& c) const override { + Border value; + while (not c.ended()) { + auto width = parseValue>(c); + if (width) { + value.width = width.unwrap(); + continue; + } + + auto color = parseValue(c); + if (color) { + value.color = color.unwrap(); + continue; + } + + auto style = parseValue(c); + if (style) { + value.style = style.unwrap(); + continue; + } + + break; + } + return Ok(makeRc(self(), value)); + } + }; + + Border _value; + + BorderLeftProperty(Rc registration, Border value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands +export struct BorderProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Border{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.borders->top); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Border _value; + + BorderProperty(Rc registration, Border value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.color), + + makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.color), + + makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.color), + + makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-backgrounds-3/#border-width +export struct BorderWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_WIDTH; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{LineWidth{Keywords::MEDIUM}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc( + self(), + Math::Insets{ + c.borders->start.width, + c.borders->end.width, + c.borders->top.width, + c.borders->bottom.width, + } + ); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + BorderWidthProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.top), + makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.end), + makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.start), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// MARK: Borders - Table ------------------------------------------------------- + +// https://www.w3.org/TR/CSS22/tables.html#propdef-border-collapse +export struct BorderCollapseProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_COLLAPSE; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), BorderCollapse::SEPARATE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.table->collapse); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BorderCollapse _value; + + BorderCollapseProperty(Rc registration, BorderCollapse value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.table.cow().collapse = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/tables.html#propdef-border-spacing +export struct BorderSpacingProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BORDER_SPACING; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), BorderSpacing{0_au, 0_au}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.table->spacing); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BorderSpacing _value; + + BorderSpacingProperty(Rc registration, BorderSpacing value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.table.cow().spacing = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/breaks.cpp b/src/vaev-engine/props/breaks.cpp new file mode 100644 index 00000000..062024a5 --- /dev/null +++ b/src/vaev-engine/props/breaks.cpp @@ -0,0 +1,120 @@ +module; + +#include + +export module Vaev.Engine:props.breaks; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Breaks ---------------------------------------------------------------- + +// https://www.w3.org/TR/css-break-3/#propdef-break-after +export struct BreakAfterProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BREAK_AFTER; + } + + Rc initial() const override { + return makeRc(self(), BreakBetween::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.break_->after); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BreakBetween _value; + + BreakAfterProperty(Rc registration, BreakBetween value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.break_.cow().after = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-break-3/#propdef-break-before +export struct BreakBeforeProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BREAK_BEFORE; + } + + Rc initial() const override { + return makeRc(self(), BreakBetween::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.break_->before); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BreakBetween _value; + + BreakBeforeProperty(Rc registration, BreakBetween value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.break_.cow().before = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-break-3/#break-within +export struct BreakInsideProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BREAK_INSIDE; + } + + Rc initial() const override { + return makeRc(self(), BreakInside::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.break_->inside); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + BreakInside _value; + + BreakInsideProperty(Rc registration, BreakInside value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.break_.cow().inside = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/defs/properties.inc b/src/vaev-engine/props/defs/properties.inc new file mode 100644 index 00000000..78310af5 --- /dev/null +++ b/src/vaev-engine/props/defs/properties.inc @@ -0,0 +1,517 @@ +PROPERTY(ACCENT_COLOR, "accent-color") +PROPERTY(ALIGN_CONTENT, "align-content") +PROPERTY(ALIGN_ITEMS, "align-items") +PROPERTY(ALIGN_SELF, "align-self") +PROPERTY(ALIGNMENT_BASELINE, "alignment-baseline") +PROPERTY(ALL, "all") +PROPERTY(ANCHOR_NAME, "anchor-name") +PROPERTY(ANIMATION_COMPOSITION, "animation-composition") +PROPERTY(ANIMATION_DELAY, "animation-delay") +PROPERTY(ANIMATION_DIRECTION, "animation-direction") +PROPERTY(ANIMATION_DURATION, "animation-duration") +PROPERTY(ANIMATION_FILL_MODE, "animation-fill-mode") +PROPERTY(ANIMATION_ITERATION_COUNT, "animation-iteration-count") +PROPERTY(ANIMATION_NAME, "animation-name") +PROPERTY(ANIMATION_PLAY_STATE, "animation-play-state") +PROPERTY(ANIMATION_RANGE_END, "animation-range-end") +PROPERTY(ANIMATION_RANGE_START, "animation-range-start") +PROPERTY(ANIMATION_RANGE, "animation-range") +PROPERTY(ANIMATION_TIMELINE, "animation-timeline") +PROPERTY(ANIMATION_TIMING_FUNCTION, "animation-timing-function") +PROPERTY(ANIMATION, "animation") +PROPERTY(APPEARANCE, "appearance") +PROPERTY(ASPECT_RATIO, "aspect-ratio") +PROPERTY(BACKDROP_FILTER, "backdrop-filter") +PROPERTY(BACKFACE_VISIBILITY, "backface-visibility") +PROPERTY(BACKGROUND_ATTACHMENT, "background-attachment") +PROPERTY(BACKGROUND_BLEND_MODE, "background-blend-mode") +PROPERTY(BACKGROUND_CLIP, "background-clip") +PROPERTY(BACKGROUND_COLOR, "background-color") +PROPERTY(BACKGROUND_IMAGE, "background-image") +PROPERTY(BACKGROUND_ORIGIN, "background-origin") +PROPERTY(BACKGROUND_POSITION_X, "background-position-x") +PROPERTY(BACKGROUND_POSITION_Y, "background-position-y") +PROPERTY(BACKGROUND_POSITION, "background-position") +PROPERTY(BACKGROUND_REPEAT, "background-repeat") +PROPERTY(BACKGROUND_SIZE, "background-size") +PROPERTY(BACKGROUND, "background") +PROPERTY(BLOCK_SIZE, "block-size") +PROPERTY(BORDER_BLOCK_COLOR, "border-block-color") +PROPERTY(BORDER_BLOCK_END_COLOR, "border-block-end-color") +PROPERTY(BORDER_BLOCK_END_STYLE, "border-block-end-style") +PROPERTY(BORDER_BLOCK_END_WIDTH, "border-block-end-width") +PROPERTY(BORDER_BLOCK_END, "border-block-end") +PROPERTY(BORDER_BLOCK_START_COLOR, "border-block-start-color") +PROPERTY(BORDER_BLOCK_START_STYLE, "border-block-start-style") +PROPERTY(BORDER_BLOCK_START_WIDTH, "border-block-start-width") +PROPERTY(BORDER_BLOCK_START, "border-block-start") +PROPERTY(BORDER_BLOCK_STYLE, "border-block-style") +PROPERTY(BORDER_BLOCK_WIDTH, "border-block-width") +PROPERTY(BORDER_BLOCK, "border-block") +PROPERTY(BORDER_BOTTOM_COLOR, "border-bottom-color") +PROPERTY(BORDER_BOTTOM_LEFT_RADIUS, "border-bottom-left-radius") +PROPERTY(BORDER_BOTTOM_RIGHT_RADIUS, "border-bottom-right-radius") +PROPERTY(BORDER_BOTTOM_STYLE, "border-bottom-style") +PROPERTY(BORDER_BOTTOM_WIDTH, "border-bottom-width") +PROPERTY(BORDER_BOTTOM, "border-bottom") +PROPERTY(BORDER_COLLAPSE, "border-collapse") +PROPERTY(BORDER_COLOR, "border-color") +PROPERTY(BORDER_END_END_RADIUS, "border-end-end-radius") +PROPERTY(BORDER_END_START_RADIUS, "border-end-start-radius") +PROPERTY(BORDER_IMAGE_OUTSET, "border-image-outset") +PROPERTY(BORDER_IMAGE_REPEAT, "border-image-repeat") +PROPERTY(BORDER_IMAGE_SLICE, "border-image-slice") +PROPERTY(BORDER_IMAGE_SOURCE, "border-image-source") +PROPERTY(BORDER_IMAGE_WIDTH, "border-image-width") +PROPERTY(BORDER_IMAGE, "border-image") +PROPERTY(BORDER_INLINE_COLOR, "border-inline-color") +PROPERTY(BORDER_INLINE_END_COLOR, "border-inline-end-color") +PROPERTY(BORDER_INLINE_END_STYLE, "border-inline-end-style") +PROPERTY(BORDER_INLINE_END_WIDTH, "border-inline-end-width") +PROPERTY(BORDER_INLINE_END, "border-inline-end") +PROPERTY(BORDER_INLINE_START_COLOR, "border-inline-start-color") +PROPERTY(BORDER_INLINE_START_STYLE, "border-inline-start-style") +PROPERTY(BORDER_INLINE_START_WIDTH, "border-inline-start-width") +PROPERTY(BORDER_INLINE_START, "border-inline-start") +PROPERTY(BORDER_INLINE_STYLE, "border-inline-style") +PROPERTY(BORDER_INLINE_WIDTH, "border-inline-width") +PROPERTY(BORDER_INLINE, "border-inline") +PROPERTY(BORDER_LEFT_COLOR, "border-left-color") +PROPERTY(BORDER_LEFT_STYLE, "border-left-style") +PROPERTY(BORDER_LEFT_WIDTH, "border-left-width") +PROPERTY(BORDER_LEFT, "border-left") +PROPERTY(BORDER_RADIUS, "border-radius") +PROPERTY(BORDER_RIGHT_COLOR, "border-right-color") +PROPERTY(BORDER_RIGHT_STYLE, "border-right-style") +PROPERTY(BORDER_RIGHT_WIDTH, "border-right-width") +PROPERTY(BORDER_RIGHT, "border-right") +PROPERTY(BORDER_SPACING, "border-spacing") +PROPERTY(BORDER_START_END_RADIUS, "border-start-end-radius") +PROPERTY(BORDER_START_START_RADIUS, "border-start-start-radius") +PROPERTY(BORDER_STYLE, "border-style") +PROPERTY(BORDER_TOP_COLOR, "border-top-color") +PROPERTY(BORDER_TOP_LEFT_RADIUS, "border-top-left-radius") +PROPERTY(BORDER_TOP_RIGHT_RADIUS, "border-top-right-radius") +PROPERTY(BORDER_TOP_STYLE, "border-top-style") +PROPERTY(BORDER_TOP_WIDTH, "border-top-width") +PROPERTY(BORDER_TOP, "border-top") +PROPERTY(BORDER_WIDTH, "border-width") +PROPERTY(BORDER, "border") +PROPERTY(BOTTOM, "bottom") +PROPERTY(BOX_ALIGN, "box-align") +PROPERTY(BOX_DECORATION_BREAK, "box-decoration-break") +PROPERTY(BOX_DIRECTION, "box-direction") +PROPERTY(BOX_FLEX_GROUP, "box-flex-group") +PROPERTY(BOX_FLEX, "box-flex") +PROPERTY(BOX_LINES, "box-lines") +PROPERTY(BOX_ORDINAL_GROUP, "box-ordinal-group") +PROPERTY(BOX_ORIENT, "box-orient") +PROPERTY(BOX_PACK, "box-pack") +PROPERTY(BOX_SHADOW, "box-shadow") +PROPERTY(BOX_SIZING, "box-sizing") +PROPERTY(BREAK_AFTER, "break-after") +PROPERTY(BREAK_BEFORE, "break-before") +PROPERTY(BREAK_INSIDE, "break-inside") +PROPERTY(CAPTION_SIDE, "caption-side") +PROPERTY(CARET_ANIMATION, "caret-animation") +PROPERTY(CARET_COLOR, "caret-color") +PROPERTY(CARET_SHAPE, "caret-shape") +PROPERTY(CARET, "caret") +PROPERTY(CLEAR, "clear") +PROPERTY(CLIP_PATH, "clip-path") +PROPERTY(CLIP_RULE, "clip-rule") +PROPERTY(CLIP, "clip") +PROPERTY(COLOR_INTERPOLATION_FILTERS, "color-interpolation-filters") +PROPERTY(COLOR_INTERPOLATION, "color-interpolation") +PROPERTY(COLOR_SCHEME, "color-scheme") +PROPERTY(COLOR, "color") +PROPERTY(COLUMN_COUNT, "column-count") +PROPERTY(COLUMN_FILL, "column-fill") +PROPERTY(COLUMN_GAP, "column-gap") +PROPERTY(COLUMN_RULE_COLOR, "column-rule-color") +PROPERTY(COLUMN_RULE_STYLE, "column-rule-style") +PROPERTY(COLUMN_RULE_WIDTH, "column-rule-width") +PROPERTY(COLUMN_RULE, "column-rule") +PROPERTY(COLUMN_SPAN, "column-span") +PROPERTY(COLUMN_WIDTH, "column-width") +PROPERTY(COLUMNS, "columns") +PROPERTY(CONTAIN_INTRINSIC_BLOCK_SIZE, "contain-intrinsic-block-size") +PROPERTY(CONTAIN_INTRINSIC_HEIGHT, "contain-intrinsic-height") +PROPERTY(CONTAIN_INTRINSIC_INLINE_SIZE, "contain-intrinsic-inline-size") +PROPERTY(CONTAIN_INTRINSIC_SIZE, "contain-intrinsic-size") +PROPERTY(CONTAIN_INTRINSIC_WIDTH, "contain-intrinsic-width") +PROPERTY(CONTAIN, "contain") +PROPERTY(CONTAINER_NAME, "container-name") +PROPERTY(CONTAINER_TYPE, "container-type") +PROPERTY(CONTAINER, "container") +PROPERTY(CONTENT_VISIBILITY, "content-visibility") +PROPERTY(CONTENT, "content") +PROPERTY(CORNER_BLOCK_END_SHAPE, "corner-block-end-shape") +PROPERTY(CORNER_BLOCK_START_SHAPE, "corner-block-start-shape") +PROPERTY(CORNER_BOTTOM_LEFT_SHAPE, "corner-bottom-left-shape") +PROPERTY(CORNER_BOTTOM_RIGHT_SHAPE, "corner-bottom-right-shape") +PROPERTY(CORNER_BOTTOM_SHAPE, "corner-bottom-shape") +PROPERTY(CORNER_END_END_SHAPE, "corner-end-end-shape") +PROPERTY(CORNER_END_START_SHAPE, "corner-end-start-shape") +PROPERTY(CORNER_INLINE_END_SHAPE, "corner-inline-end-shape") +PROPERTY(CORNER_INLINE_START_SHAPE, "corner-inline-start-shape") +PROPERTY(CORNER_LEFT_SHAPE, "corner-left-shape") +PROPERTY(CORNER_RIGHT_SHAPE, "corner-right-shape") +PROPERTY(CORNER_SHAPE, "corner-shape") +PROPERTY(CORNER_START_END_SHAPE, "corner-start-end-shape") +PROPERTY(CORNER_START_START_SHAPE, "corner-start-start-shape") +PROPERTY(CORNER_TOP_LEFT_SHAPE, "corner-top-left-shape") +PROPERTY(CORNER_TOP_RIGHT_SHAPE, "corner-top-right-shape") +PROPERTY(CORNER_TOP_SHAPE, "corner-top-shape") +PROPERTY(COUNTER_INCREMENT, "counter-increment") +PROPERTY(COUNTER_RESET, "counter-reset") +PROPERTY(COUNTER_SET, "counter-set") +PROPERTY(CURSOR, "cursor") +PROPERTY(CX, "cx") +PROPERTY(CY, "cy") +PROPERTY(D, "d") +PROPERTY(DIRECTION, "direction") +PROPERTY(DISPLAY, "display") +PROPERTY(DOMINANT_BASELINE, "dominant-baseline") +PROPERTY(DYNAMIC_RANGE_LIMIT, "dynamic-range-limit") +PROPERTY(EMPTY_CELLS, "empty-cells") +PROPERTY(FIELD_SIZING, "field-sizing") +PROPERTY(FILL_OPACITY, "fill-opacity") +PROPERTY(FILL_RULE, "fill-rule") +PROPERTY(FILL, "fill") +PROPERTY(FILTER, "filter") +PROPERTY(FLEX_BASIS, "flex-basis") +PROPERTY(FLEX_DIRECTION, "flex-direction") +PROPERTY(FLEX_FLOW, "flex-flow") +PROPERTY(FLEX_GROW, "flex-grow") +PROPERTY(FLEX_SHRINK, "flex-shrink") +PROPERTY(FLEX_WRAP, "flex-wrap") +PROPERTY(FLEX, "flex") +PROPERTY(FLOAT, "float") +PROPERTY(FLOOD_COLOR, "flood-color") +PROPERTY(FLOOD_OPACITY, "flood-opacity") +PROPERTY(FONT_FAMILY, "font-family") +PROPERTY(FONT_FEATURE_SETTINGS, "font-feature-settings") +PROPERTY(FONT_KERNING, "font-kerning") +PROPERTY(FONT_LANGUAGE_OVERRIDE, "font-language-override") +PROPERTY(FONT_OPTICAL_SIZING, "font-optical-sizing") +PROPERTY(FONT_PALETTE, "font-palette") +PROPERTY(FONT_SIZE_ADJUST, "font-size-adjust") +PROPERTY(FONT_SIZE, "font-size") +PROPERTY(FONT_SMOOTH, "font-smooth") +PROPERTY(FONT_STRETCH, "font-stretch") +PROPERTY(FONT_STYLE, "font-style") +PROPERTY(FONT_SYNTHESIS_POSITION, "font-synthesis-position") +PROPERTY(FONT_SYNTHESIS_SMALL_CAPS, "font-synthesis-small-caps") +PROPERTY(FONT_SYNTHESIS_STYLE, "font-synthesis-style") +PROPERTY(FONT_SYNTHESIS_WEIGHT, "font-synthesis-weight") +PROPERTY(FONT_SYNTHESIS, "font-synthesis") +PROPERTY(FONT_VARIANT_ALTERNATES, "font-variant-alternates") +PROPERTY(FONT_VARIANT_CAPS, "font-variant-caps") +PROPERTY(FONT_VARIANT_EAST_ASIAN, "font-variant-east-asian") +PROPERTY(FONT_VARIANT_EMOJI, "font-variant-emoji") +PROPERTY(FONT_VARIANT_LIGATURES, "font-variant-ligatures") +PROPERTY(FONT_VARIANT_NUMERIC, "font-variant-numeric") +PROPERTY(FONT_VARIANT_POSITION, "font-variant-position") +PROPERTY(FONT_VARIANT, "font-variant") +PROPERTY(FONT_VARIATION_SETTINGS, "font-variation-settings") +PROPERTY(FONT_WEIGHT, "font-weight") +PROPERTY(FONT, "font") +PROPERTY(FORCED_COLOR_ADJUST, "forced-color-adjust") +PROPERTY(GAP, "gap") +PROPERTY(GRID_AREA, "grid-area") +PROPERTY(GRID_AUTO_COLUMNS, "grid-auto-columns") +PROPERTY(GRID_AUTO_FLOW, "grid-auto-flow") +PROPERTY(GRID_AUTO_ROWS, "grid-auto-rows") +PROPERTY(GRID_COLUMN_END, "grid-column-end") +PROPERTY(GRID_COLUMN_START, "grid-column-start") +PROPERTY(GRID_COLUMN, "grid-column") +PROPERTY(GRID_ROW_END, "grid-row-end") +PROPERTY(GRID_ROW_START, "grid-row-start") +PROPERTY(GRID_ROW, "grid-row") +PROPERTY(GRID_TEMPLATE_AREAS, "grid-template-areas") +PROPERTY(GRID_TEMPLATE_COLUMNS, "grid-template-columns") +PROPERTY(GRID_TEMPLATE_ROWS, "grid-template-rows") +PROPERTY(GRID_TEMPLATE, "grid-template") +PROPERTY(GRID, "grid") +PROPERTY(HANGING_PUNCTUATION, "hanging-punctuation") +PROPERTY(HEIGHT, "height") +PROPERTY(HYPHENATE_CHARACTER, "hyphenate-character") +PROPERTY(HYPHENATE_LIMIT_CHARS, "hyphenate-limit-chars") +PROPERTY(HYPHENS, "hyphens") +PROPERTY(IMAGE_ORIENTATION, "image-orientation") +PROPERTY(IMAGE_RENDERING, "image-rendering") +PROPERTY(IMAGE_RESOLUTION, "image-resolution") +PROPERTY(INITIAL_LETTER, "initial-letter") +PROPERTY(INLINE_SIZE, "inline-size") +PROPERTY(INSET_BLOCK_END, "inset-block-end") +PROPERTY(INSET_BLOCK_START, "inset-block-start") +PROPERTY(INSET_BLOCK, "inset-block") +PROPERTY(INSET_BLOCK, "inset-block") +PROPERTY(INSET_INLINE_END, "inset-inline-end") +PROPERTY(INSET_INLINE_START, "inset-inline-start") +PROPERTY(INSET_INLINE, "inset-inline") +PROPERTY(INSET_INLINE, "inset-inline") +PROPERTY(INSET, "inset") +PROPERTY(INSET, "inset") +PROPERTY(INTERACTIVITY, "interactivity") +PROPERTY(INTERPOLATE_SIZE, "interpolate-size") +PROPERTY(ISOLATION, "isolation") +PROPERTY(JUSTIFY_CONTENT, "justify-content") +PROPERTY(JUSTIFY_ITEMS, "justify-items") +PROPERTY(JUSTIFY_SELF, "justify-self") +PROPERTY(LEFT, "left") +PROPERTY(LETTER_SPACING, "letter-spacing") +PROPERTY(LIGHTING_COLOR, "lighting-color") +PROPERTY(LINE_BREAK, "line-break") +PROPERTY(LINE_CLAMP, "line-clamp") +PROPERTY(LINE_HEIGHT_STEP, "line-height-step") +PROPERTY(LINE_HEIGHT, "line-height") +PROPERTY(LIST_STYLE_IMAGE, "list-style-image") +PROPERTY(LIST_STYLE_POSITION, "list-style-position") +PROPERTY(LIST_STYLE_TYPE, "list-style-type") +PROPERTY(LIST_STYLE, "list-style") +PROPERTY(LIST_STYLE, "list-style") +PROPERTY(MARGIN_BLOCK_END, "margin-block-end") +PROPERTY(MARGIN_BLOCK_START, "margin-block-start") +PROPERTY(MARGIN_BLOCK, "margin-block") +PROPERTY(MARGIN_BOTTOM, "margin-bottom") +PROPERTY(MARGIN_INLINE_END, "margin-inline-end") +PROPERTY(MARGIN_INLINE_START, "margin-inline-start") +PROPERTY(MARGIN_INLINE, "margin-inline") +PROPERTY(MARGIN_LEFT, "margin-left") +PROPERTY(MARGIN_RIGHT, "margin-right") +PROPERTY(MARGIN_TOP, "margin-top") +PROPERTY(MARGIN_TRIM, "margin-trim") +PROPERTY(MARGIN, "margin") +PROPERTY(MARKER_END, "marker-end") +PROPERTY(MARKER_MID, "marker-mid") +PROPERTY(MARKER_START, "marker-start") +PROPERTY(MARKER, "marker") +PROPERTY(MASK_BORDER_MODE, "mask-border-mode") +PROPERTY(MASK_BORDER_OUTSET, "mask-border-outset") +PROPERTY(MASK_BORDER_REPEAT, "mask-border-repeat") +PROPERTY(MASK_BORDER_SLICE, "mask-border-slice") +PROPERTY(MASK_BORDER_SOURCE, "mask-border-source") +PROPERTY(MASK_BORDER_WIDTH, "mask-border-width") +PROPERTY(MASK_BORDER, "mask-border") +PROPERTY(MASK_CLIP, "mask-clip") +PROPERTY(MASK_COMPOSITE, "mask-composite") +PROPERTY(MASK_IMAGE, "mask-image") +PROPERTY(MASK_MODE, "mask-mode") +PROPERTY(MASK_ORIGIN, "mask-origin") +PROPERTY(MASK_POSITION, "mask-position") +PROPERTY(MASK_REPEAT, "mask-repeat") +PROPERTY(MASK_SIZE, "mask-size") +PROPERTY(MASK_TYPE, "mask-type") +PROPERTY(MASK, "mask") +PROPERTY(MATH_DEPTH, "math-depth") +PROPERTY(MATH_SHIFT, "math-shift") +PROPERTY(MATH_STYLE, "math-style") +PROPERTY(MAX_BLOCK_SIZE, "max-block-size") +PROPERTY(MAX_HEIGHT, "max-height") +PROPERTY(MAX_INLINE_SIZE, "max-inline-size") +PROPERTY(MAX_WIDTH, "max-width") +PROPERTY(MIN_BLOCK_SIZE, "min-block-size") +PROPERTY(MIN_HEIGHT, "min-height") +PROPERTY(MIN_INLINE_SIZE, "min-inline-size") +PROPERTY(MIN_WIDTH, "min-width") +PROPERTY(MIX_BLEND_MODE, "mix-blend-mode") +PROPERTY(OBJECT_FIT, "object-fit") +PROPERTY(OBJECT_POSITION, "object-position") +PROPERTY(OBJECT_VIEW_BOX, "object-view-box") +PROPERTY(OFFSET_ANCHOR, "offset-anchor") +PROPERTY(OFFSET_DISTANCE, "offset-distance") +PROPERTY(OFFSET_PATH, "offset-path") +PROPERTY(OFFSET_POSITION, "offset-position") +PROPERTY(OFFSET_ROTATE, "offset-rotate") +PROPERTY(OFFSET, "offset") +PROPERTY(OPACITY, "opacity") +PROPERTY(ORDER, "order") +PROPERTY(ORPHANS, "orphans") +PROPERTY(OUTLINE_COLOR, "outline-color") +PROPERTY(OUTLINE_OFFSET, "outline-offset") +PROPERTY(OUTLINE_STYLE, "outline-style") +PROPERTY(OUTLINE_WIDTH, "outline-width") +PROPERTY(OUTLINE, "outline") +PROPERTY(OVERFLOW_ANCHOR, "overflow-anchor") +PROPERTY(OVERFLOW_BLOCK, "overflow-block") +PROPERTY(OVERFLOW_CLIP_MARGIN, "overflow-clip-margin") +PROPERTY(OVERFLOW_INLINE, "overflow-inline") +PROPERTY(OVERFLOW_WRAP, "overflow-wrap") +PROPERTY(OVERFLOW_X, "overflow-x") +PROPERTY(OVERFLOW_Y, "overflow-y") +PROPERTY(OVERFLOW, "overflow") +PROPERTY(OVERLAY, "overlay") +PROPERTY(OVERSCROLL_BEHAVIOR_BLOCK, "overscroll-behavior-block") +PROPERTY(OVERSCROLL_BEHAVIOR_INLINE, "overscroll-behavior-inline") +PROPERTY(OVERSCROLL_BEHAVIOR_X, "overscroll-behavior-x") +PROPERTY(OVERSCROLL_BEHAVIOR_Y, "overscroll-behavior-y") +PROPERTY(OVERSCROLL_BEHAVIOR, "overscroll-behavior") +PROPERTY(PADDING_BLOCK_END, "padding-block-end") +PROPERTY(PADDING_BLOCK_START, "padding-block-start") +PROPERTY(PADDING_BLOCK, "padding-block") +PROPERTY(PADDING_BOTTOM, "padding-bottom") +PROPERTY(PADDING_INLINE_END, "padding-inline-end") +PROPERTY(PADDING_INLINE_START, "padding-inline-start") +PROPERTY(PADDING_INLINE, "padding-inline") +PROPERTY(PADDING_LEFT, "padding-left") +PROPERTY(PADDING_RIGHT, "padding-right") +PROPERTY(PADDING_TOP, "padding-top") +PROPERTY(PADDING, "padding") +PROPERTY(PAGE_BREAK_AFTER, "page-break-after") +PROPERTY(PAGE_BREAK_BEFORE, "page-break-before") +PROPERTY(PAGE_BREAK_INSIDE, "page-break-inside") +PROPERTY(PAGE, "page") +PROPERTY(PAINT_ORDER, "paint-order") +PROPERTY(PERSPECTIVE_ORIGIN, "perspective-origin") +PROPERTY(PERSPECTIVE, "perspective") +PROPERTY(PLACE_CONTENT, "place-content") +PROPERTY(PLACE_ITEMS, "place-items") +PROPERTY(PLACE_SELF, "place-self") +PROPERTY(POINTER_EVENTS, "pointer-events") +PROPERTY(POSITION_ANCHOR, "position-anchor") +PROPERTY(POSITION_AREA, "position-area") +PROPERTY(POSITION_TRY_FALLBACKS, "position-try-fallbacks") +PROPERTY(POSITION_TRY_ORDER, "position-try-order") +PROPERTY(POSITION_TRY, "position-try") +PROPERTY(POSITION_VISIBILITY, "position-visibility") +PROPERTY(POSITION, "position") +PROPERTY(PRINT_COLOR_ADJUST, "print-color-adjust") +PROPERTY(QUOTES, "quotes") +PROPERTY(R, "r") +PROPERTY(READING_FLOW, "reading-flow") +PROPERTY(READING_ORDER, "reading-order") +PROPERTY(RESIZE, "resize") +PROPERTY(RIGHT, "right") +PROPERTY(ROTATE, "rotate") +PROPERTY(ROW_GAP, "row-gap") +PROPERTY(RUBY_ALIGN, "ruby-align") +PROPERTY(RUBY_OVERHANG, "ruby-overhang") +PROPERTY(RUBY_POSITION, "ruby-position") +PROPERTY(RX, "rx") +PROPERTY(RY, "ry") +PROPERTY(SCALE, "scale") +PROPERTY(SCROLL_BEHAVIOR, "scroll-behavior") +PROPERTY(SCROLL_MARGIN_BLOCK_END, "scroll-margin-block-end") +PROPERTY(SCROLL_MARGIN_BLOCK_START, "scroll-margin-block-start") +PROPERTY(SCROLL_MARGIN_BLOCK, "scroll-margin-block") +PROPERTY(SCROLL_MARGIN_BOTTOM, "scroll-margin-bottom") +PROPERTY(SCROLL_MARGIN_INLINE_END, "scroll-margin-inline-end") +PROPERTY(SCROLL_MARGIN_INLINE_START, "scroll-margin-inline-start") +PROPERTY(SCROLL_MARGIN_INLINE, "scroll-margin-inline") +PROPERTY(SCROLL_MARGIN_LEFT, "scroll-margin-left") +PROPERTY(SCROLL_MARGIN_RIGHT, "scroll-margin-right") +PROPERTY(SCROLL_MARGIN_TOP, "scroll-margin-top") +PROPERTY(SCROLL_MARGIN, "scroll-margin") +PROPERTY(SCROLL_MARKER_GROUP, "scroll-marker-group") +PROPERTY(SCROLL_PADDING_BLOCK_END, "scroll-padding-block-end") +PROPERTY(SCROLL_PADDING_BLOCK_START, "scroll-padding-block-start") +PROPERTY(SCROLL_PADDING_BLOCK, "scroll-padding-block") +PROPERTY(SCROLL_PADDING_BOTTOM, "scroll-padding-bottom") +PROPERTY(SCROLL_PADDING_INLINE_END, "scroll-padding-inline-end") +PROPERTY(SCROLL_PADDING_INLINE_START, "scroll-padding-inline-start") +PROPERTY(SCROLL_PADDING_INLINE, "scroll-padding-inline") +PROPERTY(SCROLL_PADDING_LEFT, "scroll-padding-left") +PROPERTY(SCROLL_PADDING_RIGHT, "scroll-padding-right") +PROPERTY(SCROLL_PADDING_TOP, "scroll-padding-top") +PROPERTY(SCROLL_PADDING, "scroll-padding") +PROPERTY(SCROLL_SNAP_ALIGN, "scroll-snap-align") +PROPERTY(SCROLL_SNAP_STOP, "scroll-snap-stop") +PROPERTY(SCROLL_SNAP_TYPE, "scroll-snap-type") +PROPERTY(SCROLL_TARGET_GROUP, "scroll-target-group") +PROPERTY(SCROLL_TIMELINE_AXIS, "scroll-timeline-axis") +PROPERTY(SCROLL_TIMELINE_NAME, "scroll-timeline-name") +PROPERTY(SCROLL_TIMELINE, "scroll-timeline") +PROPERTY(SCROLLBAR_COLOR, "scrollbar-color") +PROPERTY(SCROLLBAR_GUTTER, "scrollbar-gutter") +PROPERTY(SCROLLBAR_WIDTH, "scrollbar-width") +PROPERTY(SHAPE_IMAGE_THRESHOLD, "shape-image-threshold") +PROPERTY(SHAPE_MARGIN, "shape-margin") +PROPERTY(SHAPE_OUTSIDE, "shape-outside") +PROPERTY(SHAPE_RENDERING, "shape-rendering") +PROPERTY(SPEAK_AS, "speak-as") +PROPERTY(STOP_COLOR, "stop-color") +PROPERTY(STOP_OPACITY, "stop-opacity") +PROPERTY(STROKE_DASHARRAY, "stroke-dasharray") +PROPERTY(STROKE_DASHOFFSET, "stroke-dashoffset") +PROPERTY(STROKE_LINECAP, "stroke-linecap") +PROPERTY(STROKE_LINEJOIN, "stroke-linejoin") +PROPERTY(STROKE_MITERLIMIT, "stroke-miterlimit") +PROPERTY(STROKE_OPACITY, "stroke-opacity") +PROPERTY(STROKE_WIDTH, "stroke-width") +PROPERTY(STROKE, "stroke") +PROPERTY(TAB_SIZE, "tab-size") +PROPERTY(TABLE_LAYOUT, "table-layout") +PROPERTY(TEXT_ALIGN_LAST, "text-align-last") +PROPERTY(TEXT_ALIGN, "text-align") +PROPERTY(TEXT_ANCHOR, "text-anchor") +PROPERTY(TEXT_AUTOSPACE, "text-autospace") +PROPERTY(TEXT_BOX_EDGE, "text-box-edge") +PROPERTY(TEXT_BOX_TRIM, "text-box-trim") +PROPERTY(TEXT_BOX, "text-box") +PROPERTY(TEXT_COMBINE_UPRIGHT, "text-combine-upright") +PROPERTY(TEXT_DECORATION_COLOR, "text-decoration-color") +PROPERTY(TEXT_DECORATION_INSET, "text-decoration-inset") +PROPERTY(TEXT_DECORATION_LINE, "text-decoration-line") +PROPERTY(TEXT_DECORATION_SKIP_INK, "text-decoration-skip-ink") +PROPERTY(TEXT_DECORATION_SKIP, "text-decoration-skip") +PROPERTY(TEXT_DECORATION_STYLE, "text-decoration-style") +PROPERTY(TEXT_DECORATION_THICKNESS, "text-decoration-thickness") +PROPERTY(TEXT_DECORATION, "text-decoration") +PROPERTY(TEXT_EMPHASIS_COLOR, "text-emphasis-color") +PROPERTY(TEXT_EMPHASIS_POSITION, "text-emphasis-position") +PROPERTY(TEXT_EMPHASIS_STYLE, "text-emphasis-style") +PROPERTY(TEXT_EMPHASIS, "text-emphasis") +PROPERTY(TEXT_INDENT, "text-indent") +PROPERTY(TEXT_JUSTIFY, "text-justify") +PROPERTY(TEXT_ORIENTATION, "text-orientation") +PROPERTY(TEXT_OVERFLOW, "text-overflow") +PROPERTY(TEXT_RENDERING, "text-rendering") +PROPERTY(TEXT_SHADOW, "text-shadow") +PROPERTY(TEXT_SIZE_ADJUST, "text-size-adjust") +PROPERTY(TEXT_SPACING_TRIM, "text-spacing-trim") +PROPERTY(TEXT_TRANSFORM, "text-transform") +PROPERTY(TEXT_UNDERLINE_OFFSET, "text-underline-offset") +PROPERTY(TEXT_UNDERLINE_POSITION, "text-underline-position") +PROPERTY(TEXT_WRAP_MODE, "text-wrap-mode") +PROPERTY(TEXT_WRAP_STYLE, "text-wrap-style") +PROPERTY(TEXT_WRAP, "text-wrap") +PROPERTY(TIMELINE_SCOPE, "timeline-scope") +PROPERTY(TOP, "top") +PROPERTY(TOUCH_ACTION, "touch-action") +PROPERTY(TRANSFORM_BOX, "transform-box") +PROPERTY(TRANSFORM_ORIGIN, "transform-origin") +PROPERTY(TRANSFORM_STYLE, "transform-style") +PROPERTY(TRANSFORM, "transform") +PROPERTY(TRANSITION_BEHAVIOR, "transition-behavior") +PROPERTY(TRANSITION_DELAY, "transition-delay") +PROPERTY(TRANSITION_DURATION, "transition-duration") +PROPERTY(TRANSITION_PROPERTY, "transition-property") +PROPERTY(TRANSITION_TIMING_FUNCTION, "transition-timing-function") +PROPERTY(TRANSITION, "transition") +PROPERTY(TRANSLATE, "translate") +PROPERTY(UNICODE_BIDI, "unicode-bidi") +PROPERTY(USER_MODIFY, "user-modify") +PROPERTY(USER_SELECT, "user-select") +PROPERTY(VECTOR_EFFECT, "vector-effect") +PROPERTY(VERTICAL_ALIGN, "vertical-align") +PROPERTY(VIEW_TIMELINE_AXIS, "view-timeline-axis") +PROPERTY(VIEW_TIMELINE_INSET, "view-timeline-inset") +PROPERTY(VIEW_TIMELINE_NAME, "view-timeline-name") +PROPERTY(VIEW_TIMELINE, "view-timeline") +PROPERTY(VIEW_TRANSITION_CLASS, "view-transition-class") +PROPERTY(VIEW_TRANSITION_NAME, "view-transition-name") +PROPERTY(VISIBILITY, "visibility") +PROPERTY(WHITE_SPACE_COLLAPSE, "white-space-collapse") +PROPERTY(WHITE_SPACE, "white-space") +PROPERTY(WIDOWS, "widows") +PROPERTY(WIDTH, "width") +PROPERTY(WILL_CHANGE, "will-change") +PROPERTY(WORD_BREAK, "word-break") +PROPERTY(WORD_SPACING, "word-spacing") +PROPERTY(WRITING_MODE, "writing-mode") +PROPERTY(X, "x") +PROPERTY(Y, "y") +PROPERTY(Z_INDEX, "z-index") +PROPERTY(ZOOM, "zoom") diff --git a/src/vaev-engine/props/display.cpp b/src/vaev-engine/props/display.cpp new file mode 100644 index 00000000..18b4ae53 --- /dev/null +++ b/src/vaev-engine/props/display.cpp @@ -0,0 +1,119 @@ +module; + +#include + +export module Vaev.Engine:props.display; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// https://www.w3.org/TR/CSS22/visuren.html#propdef-display +export struct DisplayProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::DISPLAY; + } + + Rc initial() const override { + return makeRc(self(), Display{Display::FLOW, Display::INLINE}); + } + + Rc load(SpecifiedValues const& s) const override { + return makeRc(self(), s.display); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Display _value; + + DisplayProperty(Rc registration, Display value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& s) const override { + s.display = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-gcpm-3/ +// https://drafts.csswg.org/css-content/#content-property +export struct ContentProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CONTENT; + } + + Rc initial() const override { + return makeRc(self(), Keywords::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.content); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Content _value; + + ContentProperty(Rc registration, Content value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.content = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-display-3/#order-property +export struct OrderProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::ORDER; + } + + Rc initial() const override { + return makeRc(self(), Integer{0}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.order); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Integer _value; + + OrderProperty(Rc registration, Integer value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.order = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/flex.cpp b/src/vaev-engine/props/flex.cpp new file mode 100644 index 00000000..12d3811c --- /dev/null +++ b/src/vaev-engine/props/flex.cpp @@ -0,0 +1,339 @@ +module; + +#include + +export module Vaev.Engine:props.flex; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Flex ------------------------------------------------------------------ + +// https://www.w3.org/TR/css-flexbox-1/#flex-basis-property +export struct FlexBasisProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_BASIS; + } + + Rc initial() const override { + return makeRc(self(), Keywords::AUTO); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.flex->basis); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FlexBasis _value; + + FlexBasisProperty(Rc registration, FlexBasis value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.flex.cow().basis = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-direction +export struct FlexDirectionProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_DIRECTION; + } + + Rc initial() const override { + return makeRc(self(), FlexDirection::ROW); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.flex->direction); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FlexDirection _value; + + FlexDirectionProperty(Rc registration, FlexDirection value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.flex.cow().direction = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#flex-grow-property +export struct FlexGrowProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_GROW; + } + + Rc initial() const override { + return makeRc(self(), Number{0}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.flex->grow); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Number _value; + + FlexGrowProperty(Rc registration, Number value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.flex.cow().grow = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-shrink +export struct FlexShrinkProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_SHRINK; + } + + Rc initial() const override { + return makeRc(self(), Number{1}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.flex->shrink); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Number _value; + + FlexShrinkProperty(Rc registration, Number value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.flex.cow().shrink = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-wrap +export struct FlexWrapProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_WRAP; + } + + Rc initial() const override { + return makeRc(self(), FlexWrap::NOWRAP); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.flex->wrap); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FlexWrap _value; + + FlexWrapProperty(Rc registration, FlexWrap value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.flex.cow().wrap = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-flow +export struct FlexFlowProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX_FLOW; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Tuple{FlexDirection::ROW, FlexWrap::NOWRAP}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Tuple{c.flex->direction, c.flex->wrap}); + } + + Res> parse(Cursor& c) const override { + if (c.ended()) + return Error::invalidData("unexpected end of input"); + + Tuple value{FlexDirection::ROW, FlexWrap::NOWRAP}; + + auto direction = parseValue(c); + if (direction) { + value.v0 = direction.unwrap(); + + auto wrap = parseValue(c); + if (wrap) + value.v1 = wrap.unwrap(); + } else { + auto wrap = parseValue(c); + if (not wrap) + return Error::invalidData("expected flex direction or wrap"); + value.v1 = wrap.unwrap(); + + direction = parseValue(c); + if (direction) + value.v0 = direction.unwrap(); + } + + return Ok(makeRc(self(), value)); + } + }; + + Tuple _value; + + FlexFlowProperty(Rc registration, Tuple value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("flex-direction"s).unwrap(), _value.v0), + makeRc(registry.resolveRegistration("flex-wrap"s).unwrap(), _value.v1), + }; + } + + void repr(Io::Emit& e) const override { + e("{} {}", _value.v0, _value.v1); + } +}; + +// https://www.w3.org/TR/css-flexbox-1/#propdef-flex +export struct FlexProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLEX; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), FlexItemProps{Keywords::AUTO, 0, 1}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), FlexItemProps{c.flex->basis, c.flex->grow, c.flex->shrink}); + } + + Res> parse(Cursor& c) const override { + if (c.ended()) + return Error::invalidData("unexpected end of input"); + + FlexItemProps value{Keywords::AUTO, 0, 1}; + + if (c.skip(Css::Token::ident("none"))) { + value = {Keywords::AUTO, 0, 0}; + return Ok(makeRc(self(), value)); + } else if (c.skip(Css::Token::ident("initial"))) { + value = {Keywords::AUTO, 0, 1}; + return Ok(makeRc(self(), value)); + } + + // deafult values if these parameters are omitted + value.flexGrow = value.flexShrink = 1; + value.flexBasis = CalcValue>(Length{}); + + auto parseGrowShrink = [](Cursor& c, FlexItemProps& value) -> Res<> { + auto grow = parseValue(c); + if (not grow) + return Error::invalidData("expected flex item grow"); + + value.flexGrow = grow.unwrap(); + + auto shrink = parseValue(c); + if (shrink) + value.flexShrink = shrink.unwrap(); + + return Ok(); + }; + + auto parsedGrowAndMaybeShrink = parseGrowShrink(c, value); + if (parsedGrowAndMaybeShrink) { + auto basis = parseValue(c); + if (basis) + value.flexBasis = basis.unwrap(); + } else { + auto basis = parseValue(c); + if (basis) + value.flexBasis = basis.unwrap(); + else + return Error::invalidData("expected flex item grow or basis"); + + auto parsedGrowAndMaybeShrink = parseGrowShrink(c, value); + } + return Ok(makeRc(self(), value)); + } + }; + + FlexItemProps _value; + + FlexProperty(Rc registration, FlexItemProps value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("flex-basis"s).unwrap(), _value.flexBasis), + makeRc(registry.resolveRegistration("flex-grow"s).unwrap(), _value.flexGrow), + makeRc(registry.resolveRegistration("flex-shrink"s).unwrap(), _value.flexShrink), + }; + } + + void repr(Io::Emit& e) const override { + e("{} {} {}", _value.flexGrow, _value.flexShrink, _value.flexBasis); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/floats.cpp b/src/vaev-engine/props/floats.cpp new file mode 100644 index 00000000..a7ed6858 --- /dev/null +++ b/src/vaev-engine/props/floats.cpp @@ -0,0 +1,84 @@ +module; + +#include + +export module Vaev.Engine:props.floats; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Float & Clear --------------------------------------------------------- + +export struct FloatProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FLOAT; + } + + Rc initial() const override { + return makeRc(self(), Float::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.float_); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Float _value; + + FloatProperty(Rc registration, Float value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.float_ = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct ClearProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CLEAR; + } + + Rc initial() const override { + return makeRc(self(), Clear::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.clear); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Clear _value; + + ClearProperty(Rc registration, Clear value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.clear = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/fonts.cpp b/src/vaev-engine/props/fonts.cpp new file mode 100644 index 00000000..53ef53d4 --- /dev/null +++ b/src/vaev-engine/props/fonts.cpp @@ -0,0 +1,304 @@ +module; + +#include + +export module Vaev.Engine:props.fonts; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Fonts ----------------------------------------------------------------- + +// https://www.w3.org/TR/css-fonts-4/#font-family-prop +export struct FontFamilyProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT_FAMILY; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), Vec{"sans-serif"_sym}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.font->families); + } + + Res> parse(Cursor& c) const override { + Vec value{}; + eatWhitespace(c); + while (not c.ended()) { + value.pushBack(try$(parseValue(c))); + + eatWhitespace(c); + c.skip(Css::Token::comma()); + eatWhitespace(c); + } + return Ok(makeRc(self(), std::move(value))); + } + }; + + Vec _value; + + FontFamilyProperty(Rc registration, Vec value) + : Property(registration), _value(std::move(value)) {} + + void apply(SpecifiedValues& c) const override { + c.font.cow().families = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-fonts-4/#font-weight-prop +export struct FontWeightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT_WEIGHT; + } + + Rc initial() const override { + return makeRc(self(), FontWeight{Gfx::FontWeight::REGULAR}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.font->weight); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FontWeight _value; + + FontWeightProperty(Rc registration, FontWeight value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.font.cow().weight = _value.resolve(); + } + + void apply(SpecifiedValues const& parent, SpecifiedValues& c) const override { + c.font.cow().weight = _value.resolve(parent.font->weight); + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-fonts-4/#font-width-prop +export struct FontWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT_WIDTH; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), FontWidth::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.font->width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FontWidth _value; + + FontWidthProperty(Rc registration, FontWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.font.cow().width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-fonts-4/#font-style-prop +export struct FontStyleProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT_STYLE; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), FontStyle::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.font->style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FontStyle _value; + + FontStyleProperty(Rc registration, FontStyle value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.font.cow().style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-fonts-4/#font-size-prop +export struct FontSizeProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT_SIZE; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), FontSize::MEDIUM); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.font->size); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + FontSize _value; + + FontSizeProperty(Rc registration, FontSize value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.font.cow().size = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-fonts-4/#font-prop +export struct FontProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FONT; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), FontProps{}, None{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), *c.font, None{}); + } + + Res> parse(Cursor& c) const override { + // TODO: system family name + FontProps value; + Opt unresolvedWeight; + + while (true) { + auto fontStyle = parseValue(c); + if (fontStyle) { + value.style = fontStyle.unwrap(); + continue; + } + + auto fontWeight = parseValue(c); + if (fontWeight) { + unresolvedWeight = fontWeight.unwrap(); + continue; + } + + // TODO: font variant https://www.w3.org/TR/css-fonts-4/#font-variant-css21-values + + auto fontWidth = parseValue(c); + if (fontWidth) { + value.width = fontWidth.unwrap(); + continue; + } + + auto fontSize = parseValue(c); + if (fontSize) { + value.size = fontSize.unwrap(); + break; + } + + return Error::invalidData("expected font-style, font-weight, font-width or font-size"); + } + + if (c.skip(Css::Token::delim("/"))) { + auto lh = Ok(parseValue(c)); + // TODO: use lineheight parsed value + } + + value.families = {try$(parseValue(c))}; + + return Ok(makeRc(self(), std::move(value), unresolvedWeight)); + } + }; + + FontProps _value; + Opt _unresolvedWeight; + + FontProperty(Rc registration, FontProps value, Opt unresolvedWeight) + : Property(registration), _value(std::move(value)), _unresolvedWeight(unresolvedWeight) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + Vec> result; + result.pushBack(makeRc(registry.resolveRegistration("font-style"s).unwrap(), _value.style)); + result.pushBack(makeRc(registry.resolveRegistration("font-width"s).unwrap(), _value.width)); + result.pushBack(makeRc(registry.resolveRegistration("font-size"s).unwrap(), _value.size)); + result.pushBack(makeRc(registry.resolveRegistration("font-family"s).unwrap(), _value.families)); + if (_unresolvedWeight) + result.pushBack(makeRc(registry.resolveRegistration("font-weight"s).unwrap(), *_unresolvedWeight)); + return result; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/margin.cpp b/src/vaev-engine/props/margin.cpp new file mode 100644 index 00000000..e69512e1 --- /dev/null +++ b/src/vaev-engine/props/margin.cpp @@ -0,0 +1,402 @@ +module; + +#include + +export module Vaev.Engine:props.margin; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Margin ---------------------------------------------------------------- + +// https://www.w3.org/TR/css-box-3/#propdef-margin + +export struct MarginTopProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_TOP; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->top); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginTopProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.margin.cow().top = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginRightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_RIGHT; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->end); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginRightProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.margin.cow().end = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginBottomProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_BOTTOM; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->bottom); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginBottomProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.margin.cow().bottom = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginLeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_LEFT; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->start); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginLeftProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.margin.cow().start = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{CalcValue>(Length{})}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), *c.margin); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + MarginProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("margin-top"s).unwrap(), _value.top), + makeRc(registry.resolveRegistration("margin-bottom"s).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration("margin-left"s).unwrap(), _value.start), + makeRc(registry.resolveRegistration("margin-right"s).unwrap(), _value.end), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-logical/#margin-properties + +export struct MarginInlineStartProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "margin_inline-start"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->start); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginInlineStartProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().start = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginInlineEndProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "margin_inline-end"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->end); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginInlineEndProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().end = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginInlineProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_INLINE; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{CalcValue>(Length{})}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Math::Insets{c.margin->start, c.margin->end}); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + MarginInlineProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().start = _value.start; + c.margin.cow().end = _value.end; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginBlockStartProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "margin_block-start"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->top); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginBlockStartProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().top = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginBlockEndProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "margin_block-end"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>(Length{})); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.margin->bottom); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + MarginBlockEndProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().bottom = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct MarginBlockProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MARGIN_BLOCK; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets{CalcValue>(Length{})}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Math::Insets{c.margin->top, c.margin->bottom}); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + Math::Insets _value; + + MarginBlockProperty(Rc registration, Math::Insets value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + // FIXME: Take writing mode into account + c.margin.cow().top = _value.top; + c.margin.cow().bottom = _value.bottom; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/mod.cpp b/src/vaev-engine/props/mod.cpp new file mode 100644 index 00000000..d0f0b0c1 --- /dev/null +++ b/src/vaev-engine/props/mod.cpp @@ -0,0 +1,24 @@ +export module Vaev.Engine:props; + +import :props.align; +import :props.background; +import :props.base; +import :props.baseline; +import :props.border; +import :props.breaks; +import :props.display; +import :props.flex; +import :props.floats; +import :props.fonts; +import :props.margin; +import :props.outline; +import :props.overflow; +import :props.padding; +import :props.positioned; +import :props.sizing; +import :props.svg; +import :props.table; +import :props.text; +import :props.transform; +import :props.visibility; +import :props.registry; diff --git a/src/vaev-engine/props/outline.cpp b/src/vaev-engine/props/outline.cpp new file mode 100644 index 00000000..5cde7b2d --- /dev/null +++ b/src/vaev-engine/props/outline.cpp @@ -0,0 +1,228 @@ +module; + +#include + +export module Vaev.Engine:props.outline; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Outline -------------------------------------------------------------- + +// https://drafts.csswg.org/css-ui/#outline-width +export struct OutlineWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OUTLINE_WIDTH; + } + + Rc initial() const override { + return makeRc(self(), LineWidth{Keywords::MEDIUM}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.outline->width); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + LineWidth _value; + + OutlineWidthProperty(Rc registration, LineWidth value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.outline.cow().width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-ui/#outline-style +export struct OutlineStyleProperty : Property { + using Value = Union; + + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OUTLINE_STYLE; + } + + Rc initial() const override { + return makeRc(self(), Value{Gfx::BorderStyle::NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.outline->style); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Value _value; + + OutlineStyleProperty(Rc registration, Value value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.outline.cow().style = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-ui/#outline-color +export struct OutlineColorProperty : Property { + using Value = Union; + + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OUTLINE_COLOR; + } + + Rc initial() const override { + return makeRc(self(), Value{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.outline->color); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Value _value; + + OutlineColorProperty(Rc registration, Value value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.outline.cow().color = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-ui/#outline-offset +export struct OutlineOffsetProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OUTLINE_OFFSET; + } + + Rc initial() const override { + return makeRc(self(), CalcValue{0_au}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.outline->offset); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + CalcValue _value; + + OutlineOffsetProperty(Rc registration, CalcValue value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.outline.cow().offset = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-ui/#outline +export struct OutlineProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OUTLINE; + } + + Rc initial() const override { + return makeRc(self(), Outline{}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), *c.outline); + } + + Res> parse(Cursor& c) const override { + Outline value; + bool styleSet = false; + while (not c.ended()) { + auto width = parseValue>(c); + if (width) { + value.width = width.unwrap(); + continue; + } + + auto color = parseValue(c); + if (color) { + value.color = color.unwrap(); + continue; + } + + auto style = parseValue(c); + if (style) { + value.style = style.unwrap(); + styleSet = true; + continue; + } + + if (c.skip(Css::Token::ident("auto"))) { + if (not styleSet) + value.style = Keywords::AUTO; + value.color = Keywords::AUTO; + continue; + } + + break; + } + + return Ok(makeRc(self(), value)); + } + }; + + Outline _value; + + OutlineProperty(Rc registration, Outline value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("outline-width"s).unwrap(), _value.width), + makeRc(registry.resolveRegistration("outline-style"s).unwrap(), _value.style), + makeRc(registry.resolveRegistration("outline-color"s).unwrap(), _value.color), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/overflow.cpp b/src/vaev-engine/props/overflow.cpp new file mode 100644 index 00000000..a999d77b --- /dev/null +++ b/src/vaev-engine/props/overflow.cpp @@ -0,0 +1,209 @@ +module; + +#include + +export module Vaev.Engine:props.overflow; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Overflow -------------------------------------------------------------- + +// https://www.w3.org/TR/css-overflow/#overflow-control +export struct OverflowXProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OVERFLOW_X; + } + + Rc initial() const override { + return makeRc(self(), Overflow::VISIBLE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.overflows.x); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Overflow _value; + + OverflowXProperty(Rc registration, Overflow value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.overflows.x = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-overflow/#overflow-control +export struct OverflowYProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OVERFLOW_Y; + } + + Rc initial() const override { + return makeRc(self(), Overflow::VISIBLE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.overflows.y); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Overflow _value; + + OverflowYProperty(Rc registration, Overflow value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.overflows.y = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-overflow/#overflow-block +export struct OverflowBlockProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OVERFLOW_BLOCK; + } + + Rc initial() const override { + return makeRc(self(), Overflow::VISIBLE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.overflows.block); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Overflow _value; + + OverflowBlockProperty(Rc registration, Overflow value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.overflows.block = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-overflow/#overflow-inline +export struct OverflowInlineProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OVERFLOW_INLINE; + } + + Rc initial() const override { + return makeRc(self(), Overflow::VISIBLE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.overflows.inline_); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Overflow _value; + + OverflowInlineProperty(Rc registration, Overflow value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.overflows.inline_ = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-overflow-3/#propdef-overflow +export struct OverflowProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OVERFLOW; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Pair{Overflow::VISIBLE, Overflow::VISIBLE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), Pair{c.overflows.x, c.overflows.y}); + } + + Res> parse(Cursor& c) const override { + eatWhitespace(c); + if (c.ended()) + return Error::invalidData("unexpected end of input"); + + Pair value; + value.v0 = try$(parseValue(c)); + + eatWhitespace(c); + if (c.ended()) { + value.v1 = value.v0; + } else { + value.v1 = try$(parseValue(c)); + } + + return Ok(makeRc(self(), value)); + } + }; + + Pair _value; + + OverflowProperty(Rc registration, Pair value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("overflow-x"s).unwrap(), _value.v0), + makeRc(registry.resolveRegistration("overflow-y"s).unwrap(), _value.v1), + }; + } + + void repr(Io::Emit& e) const override { + e("{} {}", _value.v0, _value.v1); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/padding.cpp b/src/vaev-engine/props/padding.cpp new file mode 100644 index 00000000..4ff610c9 --- /dev/null +++ b/src/vaev-engine/props/padding.cpp @@ -0,0 +1,260 @@ +module; + +#include + +export module Vaev.Engine:props.padding; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Padding --------------------------------------------------------------- + +// https://www.w3.org/TR/css-box-3/#propdef-padding + +export struct PaddingTopProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::PADDING_TOP; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->top); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingTopProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().top = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingRightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::PADDING_RIGHT; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->end); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingRightProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().end = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingBottomProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::PADDING_BOTTOM; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->bottom); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingBottomProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().bottom = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingLeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::PADDING_LEFT; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->start); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingLeftProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().start = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingInlineStartProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "padding_inline-start"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->start); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingInlineStartProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().start = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingInlineEndProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return "padding_inline-end"_sym; + } + + Rc initial() const override { + return makeRc(self(), CalcValue>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.padding->end); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>(c)))); + } + }; + + CalcValue> _value; + + PaddingInlineEndProperty(Rc registration, CalcValue> value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.padding.cow().end = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +export struct PaddingProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::PADDING; + } + + Flags flags() const override { + return {SHORTHAND}; + } + + Rc initial() const override { + return makeRc(self(), Math::Insets>>{Length{}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), *c.padding); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>>>(c)))); + } + }; + + Math::Insets>> _value; + + PaddingProperty(Rc registration, Math::Insets>> value) + : Property(registration), _value(value) {} + + Vec> explodeShorthand(PropertyRegistry& registry) const override { + return { + makeRc(registry.resolveRegistration("padding-top"s).unwrap(), _value.top), + makeRc(registry.resolveRegistration("padding-right"s).unwrap(), _value.end), + makeRc(registry.resolveRegistration("padding-bottom"s).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration("padding-left"s).unwrap(), _value.start), + }; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/positioned.cpp b/src/vaev-engine/props/positioned.cpp new file mode 100644 index 00000000..228ad159 --- /dev/null +++ b/src/vaev-engine/props/positioned.cpp @@ -0,0 +1,222 @@ +module; + +#include + +export module Vaev.Engine:props.positioned; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Positioning ----------------------------------------------------------- + +// https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme +export struct PositionProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::POSITION; + } + + Rc initial() const override { + return makeRc(self(), Position{Keywords::STATIC}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.position); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Position _value; + + PositionProperty(Rc registration, Position value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.position = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/visuren.html#propdef-top +export struct TopProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TOP; + } + + Rc initial() const override { + return makeRc(self(), Width{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.offsets->top); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + TopProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.offsets.cow().top = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/visuren.html#propdef-right +export struct RightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::RIGHT; + } + + Rc initial() const override { + return makeRc(self(), Width{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.offsets->end); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + RightProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.offsets.cow().end = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/visuren.html#propdef-bottom +export struct BottomProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BOTTOM; + } + + Rc initial() const override { + return makeRc(self(), Width{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.offsets->bottom); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + BottomProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.offsets.cow().bottom = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS22/visuren.html#propdef-left +export struct LeftProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::LEFT; + } + + Rc initial() const override { + return makeRc(self(), Width{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.offsets->start); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Width _value; + + LeftProperty(Rc registration, Width value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.offsets.cow().start = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css2/#z-index +export struct ZIndexProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::Z_INDEX; + } + + Rc initial() const override { + return makeRc(self(), ZIndex{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.zIndex); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + ZIndex _value; + + ZIndexProperty(Rc registration, ZIndex value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.zIndex = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/registry.cpp b/src/vaev-engine/props/registry.cpp new file mode 100644 index 00000000..ad39bd17 --- /dev/null +++ b/src/vaev-engine/props/registry.cpp @@ -0,0 +1,227 @@ +export module Vaev.Engine:props.registry; + +import Karm.Core; + +import :props.align; +import :props.background; +import :props.base; +import :props.baseline; +import :props.border; +import :props.breaks; +import :props.display; +import :props.flex; +import :props.floats; +import :props.fonts; +import :props.margin; +import :props.outline; +import :props.overflow; +import :props.padding; +import :props.positioned; +import :props.sizing; +import :props.svg; +import :props.table; +import :props.text; +import :props.transform; +import :props.visibility; + +using namespace Karm; + +namespace Vaev::Style { + +export PropertyRegistry defaultRegistry() { + PropertyRegistry registry; + + // Align + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Gaps + registry.registerProperty(); + registry.registerProperty(); + + // Baseline + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Background + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Transform + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Visibility + registry.registerProperty(); + + // Borders – Colors + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Borders – Widths + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Borders – Styles + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Borders – Radius + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Borders – Shorthand + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + registry.registerProperty(); + + // Table Borders + registry.registerProperty(); + registry.registerProperty(); + + // Clip + registry.registerProperty(); + + // Content + registry.registerProperty(); + + // Breaks + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Flex + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Float & Clear + registry.registerProperty(); + registry.registerProperty(); + + // Font + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Line + registry.registerProperty(); + + // Margin + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Outline + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Overflow + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + registry.registerProperty(); + + // Padding + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Positioning + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Sizing + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // Text + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + // ZIndex + registry.registerProperty(); + + // SVG + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + registry.registerProperty(); + + return registry; +} + +} // namespace Vaev::Style \ No newline at end of file diff --git a/src/vaev-engine/props/sizing.cpp b/src/vaev-engine/props/sizing.cpp new file mode 100644 index 00000000..fe21880d --- /dev/null +++ b/src/vaev-engine/props/sizing.cpp @@ -0,0 +1,284 @@ +module; + +#include + +export module Vaev.Engine:props.sizing; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Sizing ---------------------------------------------------------------- +// https://www.w3.org/TR/css-sizing-3 + +// https://www.w3.org/TR/css-sizing-3/#box-sizing +export struct BoxSizingProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::BOX_SIZING; + } + + Rc initial() const override { + return makeRc(self(), BoxSizing::CONTENT_BOX); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.boxSizing); + } + + Res> parse(Cursor& c) const override { + BoxSizing value; + if (c.skip(Css::Token::ident("border-box"))) + value = BoxSizing::BORDER_BOX; + else if (c.skip(Css::Token::ident("content-box"))) + value = BoxSizing::CONTENT_BOX; + else + return Error::invalidData("expected 'border-box' or 'content-box'"); + + return Ok(makeRc(self(), value)); + } + }; + + BoxSizing _value; + + BoxSizingProperty(Rc registration, BoxSizing value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.boxSizing = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-width + +export struct WidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::WIDTH; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Size{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->width); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Size _value; + + WidthProperty(Rc registration, Size value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().width = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-height + +export struct HeightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::HEIGHT; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Size{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->height); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Size _value; + + HeightProperty(Rc registration, Size value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().height = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-min-width +export struct MinWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MIN_WIDTH; + } + + Rc initial() const override { + return makeRc(self(), Size{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->minWidth); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Size _value; + + MinWidthProperty(Rc registration, Size value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().minWidth = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-min-height +export struct MinHeightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MIN_HEIGHT; + } + + Rc initial() const override { + return makeRc(self(), Size{Keywords::AUTO}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->minHeight); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Size _value; + + MinHeightProperty(Rc registration, Size value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().minHeight = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-max-width + +export struct MaxWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MAX_WIDTH; + } + + Rc initial() const override { + return makeRc(self(), MaxSize{Keywords::NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->maxWidth); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + MaxSize _value; + + MaxWidthProperty(Rc registration, MaxSize value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().maxWidth = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-sizing-3/#propdef-max-height +export struct MaxHeightProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::MAX_HEIGHT; + } + + Rc initial() const override { + return makeRc(self(), MaxSize{Keywords::NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.sizing->maxHeight); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + MaxSize _value; + + MaxHeightProperty(Rc registration, MaxSize value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.sizing.cow().maxHeight = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/svg.cpp b/src/vaev-engine/props/svg.cpp new file mode 100644 index 00000000..fad916a7 --- /dev/null +++ b/src/vaev-engine/props/svg.cpp @@ -0,0 +1,580 @@ +module; + +#include + +export module Vaev.Engine:props.svg; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: SVG ---------------------------------------------------------------- + +// https://svgwg.org/svg2-draft/geometry.html#XProperty +export struct SvgXProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::X; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{0_au}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->x); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + SvgXProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().x = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/geometry.html#YProperty +export struct SvgYProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::Y; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{0_au}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->y); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + SvgYProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().y = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/geometry.html#CXProperty +export struct SvgCXProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CX; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{0_au}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->cx); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + SvgCXProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().cx = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/geometry.html#CYProperty +export struct SvgCYProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CY; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{0_au}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->cy); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + SvgCYProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().cy = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/geometry.html#RProperty +export struct SvgRProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::R; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{0_au}}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->r); + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + SvgRProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().r = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/painting.html#FillProperty +export struct SvgFillProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FILL; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Paint{Color{Gfx::BLACK}}); + } + + void inherit(SpecifiedValues const& parent, SpecifiedValues& child) override { + // NOTE: We bail out early if the parent has the default SVG values. + // This avoids needlessly writing into the child's style, which would + // trigger a copy-on-write of the whole property group for nothing. + if (parent.svg.defaulted()) + return; + child.svg.cow().fill = parent.svg->fill; + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->fill); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Paint _value; + + SvgFillProperty(Rc registration, Paint value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().fill = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/paths.html#TheDProperty +export struct SvgDProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::D; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Union{NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->d); + } + + static String _wrapPathAsCSSStyle(Str style) { + StringBuilder sb; + sb.append("path(\""s); + for (auto r : iterRunes(style)) { + if (r == '\n') + continue; + sb.append(r); + } + sb.append("\")"s); + return sb.take(); + } + + Res> parsePresentationAttribute(Str style) override { + auto fixedStyle = _wrapPathAsCSSStyle(style); + Css::Lexer lex{fixedStyle}; + auto [sst, _] = Css::consumeDeclarationValue(lex); + Cursor content = sst; + return parse(content); + } + + Res> parse(Cursor& c) const override { + eatWhitespace(c); + if (c.peek() != Css::Sst::FUNC or c.peek().prefix != Css::Token::function("path(")) { + return Error::invalidData("expected path function"); + } + + auto pathFunc = c.next(); + Cursor scanPath{pathFunc.content}; + return Ok(makeRc(self(), try$(parseValue(scanPath)))); + } + }; + + Union _value; + + SvgDProperty(Rc registration, Union value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().d = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/coords.html#ViewBoxAttribute +export struct SvgViewBoxProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::VIEWBOX; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Opt{NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->viewBox); + } + + Res> parse(Cursor& c) const override { + ViewBox viewBox; + + viewBox.minX = try$(parseValue(c)); + + c.skip(Css::Token::comma()); + viewBox.minY = try$(parseValue(c)); + + c.skip(Css::Token::comma()); + viewBox.width = try$(parseValue(c)); + + c.skip(Css::Token::comma()); + viewBox.height = try$(parseValue(c)); + + return Ok(makeRc(self(), Opt{std::move(viewBox)})); + } + }; + + Opt _value; + + SvgViewBoxProperty(Rc registration, Opt value) + : Property(registration), _value(std::move(value)) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().viewBox = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint +export struct SvgStrokeProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::STROKE; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Paint{NONE}); + } + + void inherit(SpecifiedValues const& parent, SpecifiedValues& child) override { + // NOTE: We bail out early if the parent has the default SVG values. + // This avoids needlessly writing into the child's style, which would + // trigger a copy-on-write of the whole property group for nothing. + if (parent.svg.defaulted()) + return; + child.svg.cow().fillOpacity = parent.svg->fillOpacity; + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->stroke); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Paint _value; + + SvgStrokeProperty(Rc registration, Paint value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().stroke = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/painting.html#StrokeOpacity +export struct SvgStrokeOpacityProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::STROKE_OPACITY; + } + + Rc initial() const override { + return makeRc(self(), Number{1}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->strokeOpacity); + } + + Res> parse(Cursor& c) const override { + auto maybePercent = parseValue(c); + if (maybePercent) { + return Ok(makeRc(self(), maybePercent.unwrap().value() / 100)); + } else { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + } + }; + + Number _value; + + SvgStrokeOpacityProperty(Rc registration, Number value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().strokeOpacity = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/painting.html#FillOpacity +export struct FillOpacityProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::FILL_OPACITY; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Number{1}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->fillOpacity); + } + + void inherit(SpecifiedValues const& parent, SpecifiedValues& child) override { + // NOTE: We bail out early if the parent has the default SVG values. + // This avoids needlessly writing into the child's style, which would + // trigger a copy-on-write of the whole property group for nothing. + if (parent.svg.defaulted()) + return; + child.svg.cow().fillOpacity = parent.svg->fillOpacity; + } + + Res> parse(Cursor& c) const override { + auto maybePercent = parseValue(c); + if (maybePercent) { + return Ok(makeRc(self(), maybePercent.unwrap().value() / 100)); + } else { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + } + }; + + Number _value; + + FillOpacityProperty(Rc registration, Number value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().fillOpacity = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://svgwg.org/svg2-draft/painting.html#StrokeWidth +export struct StrokeWidthProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::STROKE_WIDTH; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), PercentOr{Length{1_au}}); + } + + void inherit(SpecifiedValues const& parent, SpecifiedValues& child) override { + // NOTE: We bail out early if the parent has the default SVG values. + // This avoids needlessly writing into the child's style, which would + // trigger a copy-on-write of the whole property group for nothing. + if (parent.svg.defaulted()) + return; + child.svg.cow().strokeWidth = parent.svg->strokeWidth; + } + + Res> parsePresentationAttribute(Str style) override { + return Property::Registration::parsePresentationAttribute(Io::format("{}px", style)); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.svg->strokeWidth); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue>(c)))); + } + }; + + PercentOr _value; + + StrokeWidthProperty(Rc registration, PercentOr value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.svg.cow().strokeWidth = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/table.cpp b/src/vaev-engine/props/table.cpp new file mode 100644 index 00000000..2a264464 --- /dev/null +++ b/src/vaev-engine/props/table.cpp @@ -0,0 +1,88 @@ +module; + +#include + +export module Vaev.Engine:props.table; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// https://www.w3.org/TR/CSS21/tables.html#propdef-table-layout +export struct TableLayoutProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TABLE_LAYOUT; + } + + Rc initial() const override { + return makeRc(self(), TableLayout::AUTO); + } + + Rc load(SpecifiedValues const& s) const override { + return makeRc(self(), s.table->tableLayout); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + TableLayout _value; + + TableLayoutProperty(Rc registration, TableLayout value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& s) const override { + s.table.cow().tableLayout = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/CSS21/tables.html#caption-position +export struct CaptionSideProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CAPTION_SIDE; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), CaptionSide::TOP); + } + + Rc load(SpecifiedValues const& s) const override { + return makeRc(self(), s.table->captionSide); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + CaptionSide _value; + + CaptionSideProperty(Rc registration, CaptionSide value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& s) const override { + s.table.cow().captionSide = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/text.cpp b/src/vaev-engine/props/text.cpp new file mode 100644 index 00000000..96647a5b --- /dev/null +++ b/src/vaev-engine/props/text.cpp @@ -0,0 +1,183 @@ +module; + +#include + +export module Vaev.Engine:props.text; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Text +// https://drafts.csswg.org/css-text-4 + +// https://drafts.csswg.org/css-text/#text-align-property + +export struct TextAlignProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TEXT_ALIGN; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), TextAlign::LEFT); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.text->align); + } + + Res> parse(Cursor& c) const override { + TextAlign value; + if (c.skip(Css::Token::ident("left"))) { + value = TextAlign::LEFT; + } else if (c.skip(Css::Token::ident("right"))) { + value = TextAlign::RIGHT; + } else if (c.skip(Css::Token::ident("center"))) { + value = TextAlign::CENTER; + } else if (c.skip(Css::Token::ident("justify"))) { + value = TextAlign::JUSTIFY; + } else if (c.skip(Css::Token::ident("start"))) { + value = TextAlign::START; + } else if (c.skip(Css::Token::ident("end"))) { + value = TextAlign::END; + } else { + return Error::invalidData("expected text-align"); + } + return Ok(makeRc(self(), value)); + } + }; + + TextAlign _value; + + TextAlignProperty(Rc registration, TextAlign value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.text.cow().align = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-text-4/#text-transform-property + +export struct TextTransformProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TEXT_TRANSFORM; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), TextTransform::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.text->transform); + } + + Res> parse(Cursor& c) const override { + if (c.ended()) + return Error::invalidData("unexpected end of input"); + + TextTransform value; + if (c.skip(Css::Token::ident("none"))) { + value = TextTransform::NONE; + } else if (c.skip(Css::Token::ident("uppercase"))) { + value = TextTransform::UPPERCASE; + } else if (c.skip(Css::Token::ident("lowsercase"))) { + value = TextTransform::LOWERCASE; + } else { + return Error::invalidData("expected text-transform"); + } + + return Ok(makeRc(self(), value)); + } + }; + + TextTransform _value; + + TextTransformProperty(Rc registration, TextTransform value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.text.cow().transform = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-text/#white-space-property + +export struct WhiteSpaceProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::WHITE_SPACE; + } + + Flags flags() const override { + return {INHERITED}; + } + + Rc initial() const override { + return makeRc(self(), WhiteSpace::NORMAL); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.text->whiteSpace); + } + + Res> parse(Cursor& c) const override { + WhiteSpace value; + if (c.skip(Css::Token::ident("normal"))) { + value = WhiteSpace::NORMAL; + } else if (c.skip(Css::Token::ident("nowrap"))) { + value = WhiteSpace::NOWRAP; + } else if (c.skip(Css::Token::ident("pre"))) { + value = WhiteSpace::PRE; + } else if (c.skip(Css::Token::ident("pre-wrap"))) { + value = WhiteSpace::PRE_WRAP; + } else if (c.skip(Css::Token::ident("pre-line"))) { + value = WhiteSpace::PRE_LINE; + } else if (c.skip(Css::Token::ident("break-spaces"))) { + value = WhiteSpace::BREAK_SPACES; + } else { + return Error::invalidData("expected white-space"); + } + + return Ok(makeRc(self(), value)); + } + }; + + WhiteSpace _value; + + WhiteSpaceProperty(Rc registration, WhiteSpace value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.text.cow().whiteSpace = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/transform.cpp b/src/vaev-engine/props/transform.cpp new file mode 100644 index 00000000..f111154e --- /dev/null +++ b/src/vaev-engine/props/transform.cpp @@ -0,0 +1,174 @@ +module; + +#include + +export module Vaev.Engine:props.transform; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// MARK: Transform ------------------------------------------------------------- +// https://drafts.csswg.org/css-transforms/#transform-property + +// https://drafts.csswg.org/css-transforms/#transform-origin-property +export struct TransformOriginProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TRANSFORM_ORIGIN; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc( + self(), + TransformOrigin{ + .xOffset = CalcValue>{Percent{50}}, + .yOffset = CalcValue>{Percent{50}}, + } + ); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.transform->origin); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + TransformOrigin _value; + + TransformOriginProperty(Rc registration, TransformOrigin value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.transform.cow().origin = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-transforms/#transform-box +export struct TransformBoxProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TRANSFORM_BOX; + } + + Rc initial() const override { + return makeRc(self(), TransformBox{Keywords::VIEW_BOX}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.transform->box); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + TransformBox _value; + + TransformBoxProperty(Rc registration, TransformBox value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.transform.cow().box = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.csswg.org/css-transforms/#propdef-transform +export struct TransformProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::TRANSFORM; + } + + Flags flags() const override { + return {PRESENTATION_ATTRIBUTE}; + } + + Rc initial() const override { + return makeRc(self(), Transform{Keywords::NONE}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.transform->transform); + } + + static void _fixTransformNumberToDimensions(Vec& sst) { + auto appendSuffix = [](String const& a, Str const& b) { + StringBuilder sb; + sb.append(a); + sb.append(b); + return sb.take(); + }; + + for (auto& c : sst) { + if (c.prefix == Css::Token::function("translate(")) { + for (auto& tc : c.content) { + if (tc.token.type != Css::Token::NUMBER) + continue; + + tc.token = {Css::Token::DIMENSION, appendSuffix(tc.token.data, "px"s)}; + } + } else if ( + c.prefix == Css::Token::function("rotate(") or + c.prefix == Css::Token::function("skewX(") or + c.prefix == Css::Token::function("skewY(") + ) { + for (auto& tc : c.content) { + if (tc.token.type != Css::Token::NUMBER) + continue; + + tc.token = {Css::Token::DIMENSION, appendSuffix(tc.token.data, "deg"s)}; + } + } + } + } + + Res> parsePresentationAttribute(Str style) override { + Css::Lexer lex{style}; + auto [sst, _] = Css::consumeDeclarationValue(lex); + _fixTransformNumberToDimensions(sst); + Cursor content{sst}; + return parse(content); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Transform _value; + + TransformProperty(Rc registration, Transform value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.transform.cow().transform = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/props/visibility.cpp b/src/vaev-engine/props/visibility.cpp new file mode 100644 index 00000000..4cd010d9 --- /dev/null +++ b/src/vaev-engine/props/visibility.cpp @@ -0,0 +1,140 @@ +module; + +#include + +export module Vaev.Engine:props.visibility; + +import Karm.Core; +import :props.base; +import :css.parser; +import :style.specified; + +using namespace Karm; + +namespace Vaev::Style { + +// https://drafts.csswg.org/css-display/#visibility +export struct VisibilityProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::VISIBILITY; + } + + Rc initial() const override { + return makeRc(self(), Visibility::VISIBLE); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.visibility); + } + + Res> parse(Cursor& c) const override { + Visibility value; + if (c.skip(Css::Token::ident("visible"))) { + value = Visibility::VISIBLE; + } else if (c.skip(Css::Token::ident("hidden"))) { + value = Visibility::HIDDEN; + } else if (c.skip(Css::Token::ident("collapse"))) { + value = Visibility::COLLAPSE; + } else { + return Error::invalidData("expected visibility"); + } + + return Ok(makeRc(self(), value)); + } + }; + + Visibility _value; + + VisibilityProperty(Rc registration, Visibility value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.visibility = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://www.w3.org/TR/css-color-4/#propdef-opacity +export struct OpacityProperty : Property { + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::OPACITY; + } + + Rc initial() const override { + return makeRc(self(), Number{1}); + } + + Rc load(SpecifiedValues const& c) const override { + return makeRc(self(), c.opacity); + } + + Res> parse(Cursor& c) const override { + auto maybePercent = parseValue(c); + if (maybePercent) { + return Ok(makeRc(self(), maybePercent.unwrap().value() / 100)); + } + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Number _value; + + OpacityProperty(Rc registration, Number value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + c.opacity = _value; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +// https://drafts.fxtf.org/css-masking/#the-clip-path +export struct ClipPathProperty : Property { + using Value = Union; + + struct Registration : Property::Registration { + Symbol name() const override { + return Properties::CLIP_PATH; + } + + Rc initial() const override { + return makeRc(self(), Keywords::NONE); + } + + Rc load(SpecifiedValues const& c) const override { + if (c.clip->has()) + return makeRc(self(), c.clip->unwrap()); + return makeRc(self(), Keywords::NONE); + } + + Res> parse(Cursor& c) const override { + return Ok(makeRc(self(), try$(parseValue(c)))); + } + }; + + Value _value; + + ClipPathProperty(Rc registration, Value value) + : Property(registration), _value(value) {} + + void apply(SpecifiedValues& c) const override { + if (auto clipShape = _value.is()) + c.clip.cow() = *clipShape; + else + c.clip.cow() = NONE; + } + + void repr(Io::Emit& e) const override { + e("{}", _value); + } +}; + +} // namespace Vaev::Style diff --git a/src/vaev-engine/style/computer.cpp b/src/vaev-engine/style/computer.cpp index 5fbecbbe..1c9b14b6 100644 --- a/src/vaev-engine/style/computer.cpp +++ b/src/vaev-engine/style/computer.cpp @@ -17,6 +17,7 @@ namespace Vaev::Style { export struct Computer { Media _media; + PropertyRegistry& _propertyRegistry; StyleSheetList const& _stylesheets; Rc _fontDatabase; RuleIndex _ruleIndex = {}; @@ -54,23 +55,23 @@ export struct Computer { // Compute computed style auto computed = makeRc(SpecifiedValues::initial()); computed->inherit(parent); - Vec> importantProps; + Vec> importantProps; // HACK: Apply custom properties first for (auto const& [styleRule, _] : matchingRules) { for (auto& prop : styleRule->props) { - if (prop.is()) - prop.apply(parent, *computed); + if (prop->isCustomProperty()) + prop->apply(parent, *computed); } } for (auto const& [styleRule, _] : matchingRules) { for (auto& prop : styleRule->props) { - if (not prop.is()) { - if (prop.important == Important::NO) - prop.apply(parent, *computed); + if (not prop->isCustomProperty()) { + if (prop->important == Css::Important::UNSET) + prop->apply(parent, *computed); else - importantProps.pushBack(&prop); + importantProps.pushBack(prop); } } } @@ -101,44 +102,57 @@ export struct Computer { } // https://www.w3.org/TR/css-cascade-4/#author-presentational-hint-origin - static Vec _considerPresentationalHint(Gc::Ref el) { + Vec> _considerPresentationalHint(Gc::Ref el) { if (el->namespaceUri() != Html::NAMESPACE) return {}; - Vec res; + Vec> res; // https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-fgcolor if (auto fgcolor = el->getAttribute(Html::FGCOLOR_ATTR)) { - auto value = parseValue(fgcolor.unwrap()); - if (value) - res.pushBack(ColorProp{value.take()}); + if (auto p = _propertyRegistry.parseDeclaration("color"_sym, fgcolor.unwrap())) + res.pushBack(p.take()); } // https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-bgcolor if (auto bgcolor = el->getAttribute(Html::BGCOLOR_ATTR)) { - auto value = parseValue(bgcolor.unwrap()); - if (value) - res.pushBack(BackgroundColorProp{value.take()}); + if (auto p = _propertyRegistry.parseDeclaration("background-color"_sym, bgcolor.unwrap())) + res.pushBack(p.take()); } // https://html.spec.whatwg.org/multipage/images.html#sizes-attributes if (auto width = el->getAttribute(Html::WIDTH_ATTR)) { auto value = parseValue(width.unwrap()); if (value) - res.pushBack(WidthProp{value.take()}); + res.pushBack( + makeRc( + _propertyRegistry.resolveRegistration("width").unwrap(), + value.take() + ) + ); } // https://html.spec.whatwg.org/multipage/images.html#sizes-attributes if (auto height = el->getAttribute(Html::HEIGHT_ATTR)) { auto value = parseValue(height.unwrap()); if (value) - res.pushBack(HeightProp{value.take()}); + res.pushBack( + makeRc( + _propertyRegistry.resolveRegistration("height").unwrap(), + value.take() + ) + ); } // https://html.spec.whatwg.org/multipage/input.html#the-size-attribute if (auto size = el->getAttribute(Html::SIZE_ATTR)) { auto value = parseValue(size.unwrap()); if (value) - res.pushBack(WidthProp{CalcValue>{Length{static_cast(value.take()), Length::CH}}}); + res.pushBack( + makeRc( + _propertyRegistry.resolveRegistration("width").unwrap(), + CalcValue>{Length{static_cast(value.take()), Length::CH}} + ) + ); } return res; @@ -206,7 +220,7 @@ export struct Computer { } // https://svgwg.org/specs/integration/#svg-css-sizing - static void _applySVGElementSizingRules(Gc::Ref svgEl, Vec& styleProps) { + void _applySVGElementSizingRules(Gc::Ref svgEl, Vec>& styleProps) { if (auto parentEl = svgEl->parentNode()->is()) { // **If we have an element inside a CSS context** if (parentEl->qualifiedName.ns == Svg::NAMESPACE) @@ -216,23 +230,23 @@ export struct Computer { // - ... // - If any of the sizing attributes are missing, resolve the missing ‘svg’ element width to '300px' and missing // height to '150px' (using CSS 2.1 replaced elements size calculation). - if (not svgEl->hasAttribute(Svg::VIEW_BOX_ATTR)) { - if (not svgEl->hasAttribute(Svg::WIDTH_ATTR)) { - styleProps.pushBack(WidthProp{CalcValue>{PercentOr{Length{Au{300}}}}}); - } - if (not svgEl->hasAttribute(Svg::HEIGHT_ATTR)) { - styleProps.pushBack(HeightProp{CalcValue>{PercentOr{Length{Au{150}}}}}); - } - } + if (svgEl->hasAttribute(Svg::VIEW_BOX_ATTR)) + return; + + if (not svgEl->hasAttribute(Svg::WIDTH_ATTR)) + styleProps.pushBack(_propertyRegistry.parseDeclaration("width"_sym, "300px").unwrap()); + + if (not svgEl->hasAttribute(Svg::HEIGHT_ATTR)) + styleProps.pushBack(_propertyRegistry.parseDeclaration("height"_sym, "150px").unwrap()); } } // https://svgwg.org/svg2-draft/styling.html#PresentationAttributes - Vec _considerPresentationAttributes(Gc::Ref el) { + Vec> _considerPresentationAttributes(Gc::Ref el) { if (el->qualifiedName.ns != Svg::NAMESPACE) return {}; - Vec styleProps; + Vec> styleProps; for (auto [attr, attrValue] : el->attributes.iterUnordered()) { parseSVGPresentationAttribute(attr.name, attrValue->value, styleProps); } @@ -258,7 +272,7 @@ export struct Computer { // Get the style attribute if any auto styleAttr = el->style(); StyleRule styleRule{ - .props = parseDeclarations(styleAttr ? *styleAttr : ""), + .props = parseStyleDeclaration(styleAttr ? *styleAttr : ""), .origin = Origin::INLINE, }; matchingRules.pushBack({&styleRule, INLINE_SPEC}); diff --git a/src/vaev-engine/style/decls.cpp b/src/vaev-engine/style/decls.cpp index cc89c40e..20a7923a 100644 --- a/src/vaev-engine/style/decls.cpp +++ b/src/vaev-engine/style/decls.cpp @@ -8,13 +8,10 @@ import Karm.Math; import Karm.Logger; import :css; -import :style.props; +import :props; namespace Vaev::Style { -[[gnu::used]] -static bool DEBUG_DECL = false; - template Res _parseDeclarationValue(Cursor& c) { if constexpr (requires { T{}.parse(c); }) { @@ -23,41 +20,10 @@ Res _parseDeclarationValue(Cursor& c) { return Ok(std::move(t)); } else { - logErrorIf(DEBUG_DECL, "missing parser for declaration: {}", T::name()); return Error::notImplemented("missing parser for declaration"); } } -Important _consumeImportant(Cursor& c, bool eatEverything) { - eatWhitespace(c); - while (not c.ended()) { - if (c.skip(Css::Token::delim("!")) and - c.skip(Css::Token::ident("important"))) { - - eatWhitespace(c); - return Important::YES; - } - if (not eatEverything) - break; - c.next(); - } - - return Important::NO; -} - -template -P _deferProperty(Css::Sst const& sst) { - P prop = DeferredProp{ - Symbol::from(sst.token.data), - sst.content, - }; - if constexpr (requires { P::important; }) { - Cursor content = sst.content; - prop.important = _consumeImportant(content, true); - } - return prop; -} - template Res

_parseDeclaration(Css::Sst const& sst) { Cursor content = sst.content; @@ -66,34 +32,17 @@ Res

_parseDeclaration(Css::Sst const& sst) { P prop = try$(_parseDeclarationValue(content)); if constexpr (requires { P::important; }) - prop.important = _consumeImportant(content, false); + prop.important = sst.important; if (not content.ended()) { - logDebugIf(DEBUG_DECL, "unknown tokens in content: {}", content); return Error::invalidData("unknown tokens in content"); } return Ok(std::move(prop)); } -template -Res

_parseDefaulted(Css::Sst const& sst) { - Cursor content = sst.content; - Res

res = Error::invalidData("unknown declaration"); - if (content.skip(Css::Token::ident("initial"))) { - res = Ok(DefaultedProp{sst.token.data, Default::INITIAL}); - } else if (content.skip(Css::Token::ident("inherit"))) { - res = Ok(DefaultedProp{sst.token.data, Default::INHERIT}); - } else if (content.skip(Css::Token::ident("unset"))) { - res = Ok(DefaultedProp{sst.token.data, Default::UNSET}); - } else if (content.skip(Css::Token::ident("revert"))) { - res = Ok(DefaultedProp{sst.token.data, Default::REVERT}); - } - return res; -} - export template -Res

parseDeclaration(Css::Sst const& sst, bool allowDeferred = true) { +Res

parseDeclaration(Css::Sst const& sst) { if (sst != Css::Sst::DECL) panic("expected declaration"); @@ -104,65 +53,30 @@ Res

parseDeclaration(Css::Sst const& sst, bool allowDeferred = true) { P::any( Visitor{ - [&]>() -> bool { - if constexpr (requires(P& p) { p.template unwrap(); }) { - if (startWith(sst.token.data, "--"s) == Match::NO) { - return false; - } - - resDecl = Ok(CustomProp{ - Symbol::from(sst.token.data), - sst.content, - }); - return true; - } - return false; - }, [&]() -> bool { if (sst.token != Css::Token::ident(T::name())) return false; - resDecl = _parseDeclaration(sst); - - if constexpr (Meta::Constructible) { - if (not resDecl) { - auto resDefault = _parseDefaulted

(sst); - if (resDefault) - resDecl = std::move(resDefault); - } - } - - if constexpr (Meta::Constructible) { - if (not resDecl and allowDeferred) { - resDecl = Ok(_deferProperty

(sst)); - } - } - return true; } } ); - if (not resDecl) - logWarnIf(DEBUG_DECL, "failed to parse declaration: {} - {}", sst, resDecl); - return resDecl; } export template -Vec

parseDeclarations(Css::Content const& sst, bool allowDeferred = true) { +Vec

parseDeclarations(Css::Content const& sst) { Vec

res; for (auto const& item : sst) { if (item != Css::Sst::DECL) { - logWarnIf(DEBUG_DECL, "unexpected item in declaration: {}", item.type); continue; } - auto prop = parseDeclaration

(item, allowDeferred); + auto prop = parseDeclaration

(item); if (not prop) { - logWarnIf(DEBUG_DECL, "failed to parse declaration: {}", prop.none()); continue; } res.pushBack(prop.take()); @@ -172,123 +86,15 @@ Vec

parseDeclarations(Css::Content const& sst, bool allowDeferred = true) { } export template -Vec

parseDeclarations(Css::Sst const& sst, bool allowDeferred = true) { - return parseDeclarations

(sst.content, allowDeferred); +Vec

parseDeclarations(Css::Sst const& sst) { + return parseDeclarations

(sst.content); } export template -Vec

parseDeclarations(Str style, bool allowDeferred = true) { +Vec

parseDeclarations(Str style) { Css::Lexer lex{style}; auto sst = Css::consumeDeclarationList(lex, true); - return parseDeclarations

(sst, allowDeferred); -} - -// MARK: SVG Presentation Attributes ------------------------------------------- - -String wrapPathAsCSSStyle(Str style) { - StringBuilder sb; - sb.append("path(\""s); - for (auto r : iterRunes(style)) { - if (r == '\n') - continue; - sb.append(r); - } - sb.append("\")"s); - return sb.take(); -} - -void fixTransformNumberToDimensions(Vec& sst) { - auto appendSuffix = [](String const& a, Str const& b) { - StringBuilder sb; - sb.append(a); - sb.append(b); - return sb.take(); - }; - - for (auto& c : sst) { - if (c.prefix == Css::Token::function("translate(")) { - for (auto& tc : c.content) { - if (tc.token.type != Css::Token::NUMBER) - continue; - - tc.token = {Css::Token::DIMENSION, appendSuffix(tc.token.data, "px"s)}; - } - } else if ( - c.prefix == Css::Token::function("rotate(") or - c.prefix == Css::Token::function("skewX(") or - c.prefix == Css::Token::function("skewY(") - ) { - for (auto& tc : c.content) { - if (tc.token.type != Css::Token::NUMBER) - continue; - - tc.token = {Css::Token::DIMENSION, appendSuffix(tc.token.data, "deg"s)}; - } - } - } -} - -// https://svgwg.org/svg2-draft/styling.html#PresentationAttributes -export void parseSVGPresentationAttribute(Symbol presentationAttr, Str style, Vec& styleProps) { - SVGStyleProp::any( - Visitor{ - [&]>() -> bool { - if (presentationAttr.str() != TransformProp::name()) - return false; - - TransformProp t; - - Css::Lexer lex{style}; - auto sst = Css::consumeDeclarationValue(lex); - fixTransformNumberToDimensions(sst); - Cursor content = sst; - - if (t.parse(content)) - styleProps.pushBack(std::move(t)); - return true; - }, - [&]>() -> bool { - if (presentationAttr != SVGDProp::name()) - return false; - SVGDProp d; - - auto fixedStyle = wrapPathAsCSSStyle(style); - Css::Lexer lex{fixedStyle}; - auto sst = Css::consumeDeclarationValue(lex); - Cursor content = sst; - - if (d.parse(content)) - styleProps.pushBack(std::move(d)); - return true; - }, - [&]() -> bool { - if (presentationAttr != T::name()) - return false; - - Css::Lexer lex{style}; - auto sst = Css::consumeDeclarationValue(lex); - - Cursor content = sst; - if (auto prop = _parseDeclarationValue(content)) { - styleProps.pushBack(std::move(prop.take())); - } else if (auto maybeNumber = parseValue(content)) { - T propAsNumber; - - if constexpr (Meta::Constructible) { - propAsNumber.value = Length{Au{maybeNumber.take()}}; - } else if constexpr (Meta::Constructible>>) { - propAsNumber.value = CalcValue>{Length{Au{maybeNumber.take()}}}; - } else { - return true; - } - - styleProps.pushBack(std::move(propAsNumber)); - } - - return true; - } - } - ); + return parseDeclarations

(sst); } } // namespace Vaev::Style diff --git a/src/vaev-engine/style/page.cpp b/src/vaev-engine/style/page.cpp index 57928204..e5c5b94e 100644 --- a/src/vaev-engine/style/page.cpp +++ b/src/vaev-engine/style/page.cpp @@ -177,7 +177,7 @@ export struct PageSelector { export struct PageAreaRule { PageArea area; - Vec props; + Vec> props; static Opt _parsePageArea(Css::Token tok) { Str name = next(tok.data); @@ -193,16 +193,15 @@ export struct PageAreaRule { return NONE; } - static Opt parse(Css::Sst const& sst) { + static Opt parse(PropertyRegistry& propertyRegistry, Css::Sst const& sst) { PageAreaRule res; res.area = try$(_parsePageArea(sst.token)); for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - auto prop = parseDeclaration(item); - if (prop) - res.props.pushBack(prop.take()); + if (auto p = propertyRegistry.parseDeclaration(item)) + res.props.pushBack(p.take()); } else { logWarnIf(DEBUG_PAGE, "unexpected item in style rule: {}", item); } @@ -213,7 +212,7 @@ export struct PageAreaRule { void apply(SpecifiedValues& c) const { for (auto const& prop : props) { - prop.apply(c, c); + prop->apply(c, c); } } diff --git a/src/vaev-engine/style/props-impl.cpp b/src/vaev-engine/style/props-impl.cpp deleted file mode 100644 index 26b00696..00000000 --- a/src/vaev-engine/style/props-impl.cpp +++ /dev/null @@ -1,163 +0,0 @@ -module Vaev.Engine; - -import Karm.Core; -import Karm.Logger; - -import :css; -import :values; -import :style.decls; -import :style.specified; - -namespace Vaev::Style { - -static bool DEBUG_PROPS = false; - -// MARK: DeferredProp ---------------------------------------------------------- - -bool DeferredProp::_expandVariable(Cursor& c, Map const& env, Css::Content& out) { - if (not(c->type == Css::Sst::FUNC and - c->prefix == Css::Token::function("var("))) { - return false; - } - - Cursor content = c->content; - - eatWhitespace(content); - if (content.ended()) - return true; - - if (content.peek() != Css::Token::IDENT) - return true; - - Symbol varName = Symbol::from(content->token.data); - if (auto ref = env.access(varName)) { - Cursor varContent = *ref; - _expandContent(varContent, env, out); - return true; - } - content.next(); - - eatWhitespace(content); - - if (not content.skip(Css::Token::COMMA)) - return true; - - _expandContent(content, env, out); - return true; -} - -bool DeferredProp::_expandFunction(Cursor& c, Map const& env, Css::Content& out) { - if (c->type != Css::Sst::FUNC) - return false; - - auto& func = out.emplaceBack(Css::Sst::FUNC); - func.prefix = c->prefix; - Cursor content = c->content; - _expandContent(content, env, func.content); - - return true; -} - -void DeferredProp::_expandContent(Cursor& c, Map const& env, Css::Content& out) { - // NOTE: Hint that we will add all the remaining elements - out.ensure(out.len() + c.rem()); - - while (not c.ended()) { - if (not _expandVariable(c, env, out) and - not _expandFunction(c, env, out)) { - out.pushBack(*c); - } - - c.next(); - } -} - -void DeferredProp::apply(SpecifiedValues const& parent, SpecifiedValues& c) const { - Css::Sst decl{Css::Sst::DECL}; - decl.token = Css::Token::ident(propName.str()); - Cursor cursor = value; - _expandContent(cursor, *c.variables, decl.content); - - // Parse the expanded content - Res computed = parseDeclaration(decl, false); - if (not computed) { - logWarnIf(DEBUG_PROPS, "failed to parse declaration: {}: {}", decl, computed); - } else { - computed.unwrap().apply(parent, c); - } -} - -// MARK: DefaultedProp --------------------------------------------------------- - -void DefaultedProp::apply(SpecifiedValues const& parent, SpecifiedValues& c) const { - if (value == Default::INITIAL) { - StyleProp::any([&]() { - if (T::name() != propName) - return false; - if constexpr (requires { T::initial(); }) - StyleProp{T{T::initial()}}.apply(parent, c); - return true; - }); - } else if (value == Default::INHERIT) { - StyleProp::any([&]() { - if (T::name() != propName) - return false; - if constexpr (requires { T::load(parent); }) - StyleProp{T{T::load(parent)}}.apply(parent, c); - return true; - }); - } else if (value == Default::UNSET) { - StyleProp::any([&]() { - if (T::name() != propName) - return false; - if constexpr (requires { T::inherit; T::load(parent); }) - StyleProp{T{T::load(parent)}}.apply(parent, c); - else if constexpr (requires { T::initial(); }) - StyleProp{T{T::initial()}}.apply(parent, c); - return true; - }); - } else { - logDebug("defaulted: unsupported value '{}'", value); - } -} - -void DefaultedProp::repr(Io::Emit& e) const { - e("(Defaulted {#} = {})", propName, value); -} - -// MARK: Style Property ------------------------------------------------------- - -Str StyleProp::name() const { - return visit([](auto const& p) { - return p.name(); - }); -} - -void StyleProp::inherit(SpecifiedValues const& parent, SpecifiedValues& child) const { - visit([&](auto const& p) { - if constexpr (requires { p.inherit(parent, child); }) - p.inherit(parent, child); - }); -} - -void StyleProp::apply(SpecifiedValues const& parent, SpecifiedValues& c) const { - visit([&](auto const& p) { - if constexpr (requires { p.apply(c); }) - p.apply(c); - - if constexpr (requires { p.apply(parent, c); }) - p.apply(parent, c); - }); -} - -void StyleProp::repr(Io::Emit& e) const { - e("({}", name()); - visit([&](auto const& p) { - e(" {#}", p.value); - if (important == Important::YES) - e(" !important"); - }); - e(")"); -} - -} // namespace Vaev::Style diff --git a/src/vaev-engine/style/props.cpp b/src/vaev-engine/style/props.cpp deleted file mode 100644 index 7a8bc86f..00000000 --- a/src/vaev-engine/style/props.cpp +++ /dev/null @@ -1,3751 +0,0 @@ -module; - -#include - -export module Vaev.Engine:style.props; - -import Karm.Core; -import Karm.Ref; -import Karm.Gfx; -import Karm.Math; - -import :values; -import :css; -import :style.specified; - -using namespace Karm; - -// https://www.w3.org/TR/CSS22/propidx.html - -namespace Vaev::Style { - -// MARK: Props ----------------------------------------------------------------- - -// NOTE: This list should be kept alphabetically sorted. - -// MARK: Align ----------------------------------------------------------------- -// https://drafts.csswg.org/css-align-3 - -// https://drafts.csswg.org/css-align-3/#propdef-align-content -export struct AlignContentProp { - Align value = initial(); - - static constexpr Str name() { return "align-content"; } - - static constexpr Align initial() { return Align::Keywords::STRETCH; } - - void apply(SpecifiedValues& c) const { - c.aligns.alignContent = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.alignContent; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#propdef-justify-content -export struct JustifyContentProp { - Align value = initial(); - - static constexpr Str name() { return "justify-content"; } - - static constexpr Align initial() { return Align::Keywords::FLEX_START; } - - void apply(SpecifiedValues& c) const { - c.aligns.justifyContent = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.justifyContent; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#propdef-justify-self -export struct JustifySelfProp { - Align value = initial(); - - static constexpr Str name() { return "justify-self"; } - - static constexpr Align initial() { return {}; } - - void apply(SpecifiedValues& c) const { - c.aligns.justifySelf = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.justifySelf; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#propdef-align-self -export struct AlignSelfProp { - Align value = initial(); - - static constexpr Str name() { return "align-self"; } - - static constexpr Align initial() { return Align::Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.aligns.alignSelf = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.alignSelf; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#propdef-justify-items -export struct JustifyItemsProp { - Align value = initial(); - - static constexpr Str name() { return "justify-items"; } - - static constexpr Align initial() { return {}; } - - void apply(SpecifiedValues& c) const { - c.aligns.justifyItems = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.justifyItems; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#propdef-align-items -export struct AlignItemsProp { - Align value = initial(); - - static constexpr Str name() { return "align-items"; } - - static constexpr Align initial() { return Align::Keywords::STRETCH; } - - void apply(SpecifiedValues& c) const { - c.aligns.alignItems = value; - } - - static Align load(SpecifiedValues const& c) { - return c.aligns.alignItems; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#column-row-gap -export struct RowGapProp { - Gap value = initial(); - - static constexpr Str name() { return "row-gap"; } - - static constexpr Keywords::Normal initial() { return Keywords::NORMAL; } - - void apply(SpecifiedValues& c) const { - c.gaps.cow().y = value; - } - - static Gap load(SpecifiedValues const& c) { - return c.gaps->y; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-align-3/#column-row-gap -export struct ColumnGapProp { - Gap value = initial(); - - static constexpr Str name() { return "column-gap"; } - - static constexpr Keywords::Normal initial() { return Keywords::NORMAL; } - - void apply(SpecifiedValues& c) const { - c.gaps.cow().x = value; - } - - static Gap load(SpecifiedValues const& c) { - return c.gaps->x; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Baselines ------------------------------------------------------ - -// https://www.w3.org/TR/css-inline-3/#dominant-baseline-property -export struct DominantBaselineProp { - DominantBaseline value = initial(); - - static constexpr Str name() { return "dominant-baseline"; } - - static constexpr Keywords::Auto initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.baseline.cow().dominant = value; - } - - static DominantBaseline load(SpecifiedValues const& c) { - return c.baseline->dominant; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-inline-3/#baseline-source -export struct BaselineSourceProp { - BaselineSource value = initial(); - - static constexpr Str name() { return "baseline-source"; } - - static constexpr Keywords::Auto initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.baseline.cow().source = value; - } - - static BaselineSource load(SpecifiedValues const& c) { - return c.baseline->source; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-inline-3/#alignment-baseline-property -export struct AlignmentBaselineProp { - AlignmentBaseline value = initial(); - - static constexpr Str name() { return "alignment-baseline"; } - - static constexpr Keywords::Baseline initial() { return Keywords::BASELINE; } - - void apply(SpecifiedValues& c) const { - c.baseline.cow().alignment = value; - } - - static AlignmentBaseline load(SpecifiedValues const& c) { - return c.baseline->alignment; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Background Color ------------------------------------------------------ - -// https://www.w3.org/TR/CSS22/colors.html#propdef-background-color -export struct BackgroundColorProp { - Color value = initial(); - - static constexpr Str name() { return "background-color"; } - - static constexpr Color initial() { return TRANSPARENT; } - - void apply(SpecifiedValues& c) const { - c.backgrounds.cow().color = value; - } - - static Color load(SpecifiedValues const& c) { - return c.backgrounds->color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Background Image ------------------------------------------------------ - -// https://www.w3.org/TR/CSS22/colors.html#propdef-background-attachment -export struct BackgroundAttachmentProp { - Vec value = initial(); - - static constexpr Str name() { return "background-attachment"; } - - static constexpr Array initial() { - return {BackgroundAttachment::SCROLL}; - } - - void apply(SpecifiedValues& c) const { - auto& layers = c.backgrounds.cow().layers; - layers.resize(max(layers.len(), value.len())); - for (usize i = 0; i < value.len(); ++i) - layers[i].attachment = value[i]; - } - - static Vec load(SpecifiedValues const& c) { - Vec layers; - for (auto const& l : c.backgrounds->layers) - layers.pushBack(l.attachment); - return layers; - } -}; - -// https://www.w3.org/TR/CSS22/colors.html#propdef-background-image -export struct BackgroundImageProp { - Vec value = initial(); - - static constexpr Str name() { return "background-image"; } - - static Vec initial() { return {}; } - - void apply(SpecifiedValues&) const { - // TODO - } - - static Vec load(SpecifiedValues const&) { - return {}; - } - - Res<> parse(Cursor&) { - // TODO - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/colors.html#propdef-background-position -export struct BackgroundPositionProp { - Vec value = initial(); - - static constexpr Str name() { return "background-position"; } - - static constexpr Vec initial() { - return {}; - } - - void apply(SpecifiedValues&) const { - // TODO - } - - static Vec load(SpecifiedValues const&) { - return {}; - } - - Res<> parse(Cursor&) { - // TODO - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/colors.html#propdef-background-repeat -export struct BackgroundRepeatProp { - Vec value = initial(); - - static constexpr Str name() { return "background-repeat"; } - - static constexpr Array initial() { - return {BackgroundRepeat::REPEAT}; - } - - void apply(SpecifiedValues&) const { - // TODO - } - - static Vec load(SpecifiedValues const&) { - return {}; - } - - Res<> parse(Cursor&) { - // TODO - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/colors.html#x10 -export struct BackgroundProp { - // FIXME: this should cover everything else - BackgroundProps value = initial(); - - static constexpr Str name() { return "background"; } - - static BackgroundProps initial() { return {TRANSPARENT}; } - - void apply(SpecifiedValues& c) const { - c.backgrounds.cow() = value; - } - - static BackgroundProps load(SpecifiedValues const& c) { - return *c.backgrounds; - } - - Res<> parse(Cursor& c) { - value.color = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/colors.html#propdef-color -export struct ColorProp { - Color value = initial(); - - static constexpr Str name() { return "color"; } - - static constexpr Color initial() { return BLACK; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - child.color = parent.color; - } - - void apply(SpecifiedValues& c) const { - c.color = resolve(value, Gfx::BLACK); - } - - void apply(SpecifiedValues const& parent, SpecifiedValues& c) const { - c.color = resolve(value, parent.color); - } - - static Color load(SpecifiedValues const& c) { - return c.color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/visuren.html#propdef-display -export struct DisplayProp { - Display value = initial(); - - static constexpr Str name() { return "display"; } - - static constexpr Display initial() { return {Display::FLOW, Display::INLINE}; } - - void apply(SpecifiedValues& s) const { - s.display = value; - } - - static Display load(SpecifiedValues const& s) { - return s.display; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS21/tables.html#propdef-table-layout -export struct TableLayoutProp { - TableLayout value = initial(); - - static constexpr Str name() { return "table-layout"; } - - static constexpr TableLayout initial() { return TableLayout::AUTO; } - - void apply(SpecifiedValues& s) const { - s.table.cow().tableLayout = value; - } - - static TableLayout load(SpecifiedValues const& s) { - return s.table->tableLayout; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS21/tables.html#caption-position -export struct CaptionSideProp { - CaptionSide value = initial(); - - static constexpr Str name() { return "caption-side"; } - - static constexpr CaptionSide initial() { return CaptionSide::TOP; } - - void apply(SpecifiedValues& s) const { - s.table.cow().captionSide = value; - } - - static CaptionSide load(SpecifiedValues const& s) { - return s.table->captionSide; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Borders --------------------------------------------------------------- - -// https://www.w3.org/TR/CSS22/box.html#propdef-border-color -export struct BorderTopColorProp { - Color value = initial(); - - static constexpr Str name() { return "border-top-color"; } - - static constexpr Color initial() { return BLACK; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().top.color = value; - } - - static Color load(SpecifiedValues const& c) { - return c.borders->top.color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#propdef-border-color -export struct BorderRightColorProp { - Color value = initial(); - - static constexpr Str name() { return "border-right-color"; } - - static constexpr Color initial() { return BLACK; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().end.color = value; - } - - static Color load(SpecifiedValues const& c) { - return c.borders->end.color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#propdef-border-color -export struct BorderBottomColorProp { - Color value = initial(); - - static constexpr Str name() { return "border-bottom-color"; } - - static constexpr Color initial() { return BLACK; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().bottom.color = value; - } - - static Color load(SpecifiedValues const& c) { - return c.borders->bottom.color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#propdef-border-color -export struct BorderLeftColorProp { - Color value = initial(); - - static constexpr Str name() { return "border-left-color"; } - - static constexpr Color initial() { return BLACK; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().start.color = value; - } - - static Color load(SpecifiedValues const& c) { - return c.borders->start.color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct BorderColorProp { - Math::Insets value = initial(); - - static constexpr Str name() { return "border-color"; } - - static constexpr Math::Insets initial() { return {BLACK}; } - - void apply(SpecifiedValues& c) const { - auto& borders = c.borders.cow(); - borders.start.color = value.start; - borders.end.color = value.end; - borders.top.color = value.top; - borders.bottom.color = value.bottom; - } - - static Math::Insets load(SpecifiedValues const& c) { - return { - c.borders->start.color, - c.borders->end.color, - c.borders->top.color, - c.borders->bottom.color, - }; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#border-style-properties - -export struct BorderStyle { - Math::Insets value = initial(); - - static constexpr Str name() { return "border-style"; } - - static constexpr Math::Insets initial() { - return {Gfx::BorderStyle::NONE}; - } - - void apply(SpecifiedValues& c) const { - c.borders.cow().start.style = value.start; - c.borders.cow().end.style = value.end; - c.borders.cow().top.style = value.top; - c.borders.cow().bottom.style = value.bottom; - } - - static Math::Insets load(SpecifiedValues const& c) { - return { - c.borders->start.style, - c.borders->end.style, - c.borders->top.style, - c.borders->bottom.style, - }; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#border-style-properties -export struct BorderLeftStyleProp { - Gfx::BorderStyle value = initial(); - - static constexpr Str name() { return "border-left-style"; } - - static constexpr Gfx::BorderStyle initial() { return Gfx::BorderStyle::NONE; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().start.style = value; - } - - static Gfx::BorderStyle load(SpecifiedValues const& c) { - return c.borders->start.style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#border-style-properties -export struct BorderTopStyleProp { - Gfx::BorderStyle value = initial(); - - static constexpr Str name() { return "border-top-style"; } - - static constexpr Gfx::BorderStyle initial() { return Gfx::BorderStyle::NONE; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().top.style = value; - } - - static Gfx::BorderStyle load(SpecifiedValues const& c) { - return c.borders->top.style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#border-style-properties -export struct BorderRightStyleProp { - Gfx::BorderStyle value = initial(); - - static constexpr Str name() { return "border-right-style"; } - - static constexpr Gfx::BorderStyle initial() { return Gfx::BorderStyle::NONE; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().end.style = value; - } - - static Gfx::BorderStyle load(SpecifiedValues const& c) { - return c.borders->end.style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/box.html#border-style-properties -export struct BorderBottomStyleProp { - Gfx::BorderStyle value = initial(); - - static constexpr Str name() { return "border-bottom-style"; } - - static constexpr Gfx::BorderStyle initial() { return Gfx::BorderStyle::NONE; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().bottom.style = value; - } - - static Gfx::BorderStyle load(SpecifiedValues const& c) { - return c.borders->bottom.style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-width -export struct BorderTopWidthProp { - LineWidth value = initial(); - - static constexpr Str name() { return "border-top-width"; } - - static constexpr LineWidth initial() { return Keywords::MEDIUM; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().top.width = value; - } - - static LineWidth load(SpecifiedValues const& c) { - return c.borders->top.width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-width -export struct BorderRightWidthProp { - LineWidth value = initial(); - - static constexpr Str name() { return "border-right-width"; } - - static constexpr LineWidth initial() { return Keywords::MEDIUM; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().end.width = value; - } - - static LineWidth load(SpecifiedValues const& c) { - return c.borders->end.width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-width -export struct BorderBottomWidthProp { - LineWidth value = initial(); - - static constexpr Str name() { return "border-bottom-width"; } - - static constexpr LineWidth initial() { return Keywords::MEDIUM; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().bottom.width = value; - } - - static LineWidth load(SpecifiedValues const& c) { - return c.borders->bottom.width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-width -export struct BorderLeftWidthProp { - LineWidth value = initial(); - - static constexpr Str name() { return "border-left-width"; } - - static constexpr LineWidth initial() { return Keywords::MEDIUM; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().start.width = value; - } - - static LineWidth load(SpecifiedValues const& c) { - return c.borders->start.width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-backgrounds/#the-border-radius -export struct BorderRadiusTopRight { - Array>, 2> value = initial(); - - static constexpr Str name() { return "border-top-right-radius"; } - - static constexpr Array>, 2> initial() { - return makeArray>, 2>(Length{}); - } - - void apply(SpecifiedValues& c) const { - c.borders.cow().radii.c = value[0]; - c.borders.cow().radii.d = value[1]; - } - - static Array>, 2> load(SpecifiedValues const& c) { - return { - c.borders->radii.c, - c.borders->radii.d, - }; - } - - Res<> parse(Cursor& c) { - value[0] = try$(parseValue>>(c)); - if (c.ended()) { - value[1] = value[0]; - } else { - value[1] = try$(parseValue>>(c)); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-backgrounds/#the-border-radius -export struct BorderRadiusTopLeft { - Array>, 2> value = initial(); - - static constexpr Str name() { return "border-top-left-radius"; } - - static constexpr Array>, 2> initial() { - return makeArray>, 2>(Length{}); - } - - void apply(SpecifiedValues& c) const { - c.borders.cow().radii.a = value[1]; - c.borders.cow().radii.b = value[0]; - } - - static Array>, 2> load(SpecifiedValues const& c) { - return { - c.borders->radii.a, - c.borders->radii.b, - }; - } - - Res<> parse(Cursor& c) { - value[0] = try$(parseValue>>(c)); - eatWhitespace(c); - if (c.ended()) { - value[1] = value[0]; - } else { - value[1] = try$(parseValue>>(c)); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-backgrounds/#the-border-radius -export struct BorderRadiusBottomRight { - Array>, 2> value = initial(); - - static constexpr Str name() { return "border-bottom-right-radius"; } - - static constexpr Array>, 2> initial() { - return makeArray>, 2>(Length{}); - } - - void apply(SpecifiedValues& c) const { - c.borders.cow().radii.e = value[1]; - c.borders.cow().radii.f = value[0]; - } - - static Array>, 2> load(SpecifiedValues const& c) { - return { - c.borders->radii.e, - c.borders->radii.f, - }; - } - - Res<> parse(Cursor& c) { - value[0] = try$(parseValue>>(c)); - if (c.ended()) { - value[1] = value[0]; - } else { - value[1] = try$(parseValue>>(c)); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-backgrounds/#the-border-radius -export struct BorderRadiusBottomLeft { - Array>, 2> value = initial(); - - static constexpr Str name() { return "border-bottom-left-radius"; } - - static constexpr Array>, 2> initial() { - return makeArray>, 2>(Length{}); - } - - void apply(SpecifiedValues& c) const { - c.borders.cow().radii.g = value[0]; - c.borders.cow().radii.h = value[1]; - } - - static Array>, 2> load(SpecifiedValues const& c) { - return { - c.borders->radii.g, - c.borders->radii.h, - }; - } - - Res<> parse(Cursor& c) { - value[0] = try$(parseValue>>(c)); - if (c.ended()) { - value[1] = value[0]; - } else { - value[1] = try$(parseValue>>(c)); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-backgrounds/#the-border-radius -export struct BorderRadius { - Math::Radii>> value = initial(); - - static constexpr Str name() { return "border-radius"; } - - static Math::Radii>> initial() { return {CalcValue>(Length{})}; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().radii = value; - } - - static Math::Radii>> load(SpecifiedValues const& c) { - return c.borders->radii; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands -export struct BorderTopProp { - Border value; - - static constexpr Str name() { return "border-top"; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().top = value; - } - - static Border load(SpecifiedValues const& c) { - return c.borders->top; - } - - Res<> parse(Cursor& c) { - while (not c.ended()) { - auto width = parseValue>(c); - if (width) { - value.width = width.unwrap(); - continue; - } - - auto color = parseValue(c); - if (color) { - value.color = color.unwrap(); - continue; - } - - auto style = parseValue(c); - if (style) { - value.style = style.unwrap(); - continue; - } - - break; - } - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands -export struct BorderRightProp { - Border value; - - static constexpr Str name() { return "border-right"; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().end = value; - } - - static Border load(SpecifiedValues const& c) { - return c.borders->end; - } - - Res<> parse(Cursor& c) { - while (not c.ended()) { - auto width = parseValue>(c); - if (width) { - value.width = width.unwrap(); - continue; - } - - auto color = parseValue(c); - if (color) { - value.color = color.unwrap(); - continue; - } - - auto style = parseValue(c); - if (style) { - value.style = style.unwrap(); - continue; - } - - break; - } - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands -export struct BorderBottomProp { - Border value; - - static constexpr Str name() { return "border-bottom"; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().bottom = value; - } - - static Border load(SpecifiedValues const& c) { - return c.borders->bottom; - } - - Res<> parse(Cursor& c) { - while (not c.ended()) { - auto width = parseValue>(c); - if (width) { - value.width = width.unwrap(); - continue; - } - - auto color = parseValue(c); - if (color) { - value.color = color.unwrap(); - continue; - } - - auto style = parseValue(c); - if (style) { - value.style = style.unwrap(); - continue; - } - - break; - } - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands -export struct BorderLeftProp { - Border value; - - static constexpr Str name() { return "border-left"; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().start = value; - } - - static Border load(SpecifiedValues const& c) { - return c.borders->start; - } - - Res<> parse(Cursor& c) { - while (not c.ended()) { - auto width = parseValue>(c); - if (width) { - value.width = width.unwrap(); - continue; - } - - auto color = parseValue(c); - if (color) { - value.color = color.unwrap(); - continue; - } - - auto style = parseValue(c); - if (style) { - value.style = style.unwrap(); - continue; - } - - break; - } - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-shorthands -export struct BorderProp { - Border value; - - static constexpr Str name() { return "border"; } - - void apply(SpecifiedValues& c) const { - c.borders.cow().top = value; - c.borders.cow().bottom = value; - c.borders.cow().start = value; - c.borders.cow().end = value; - } - - static Border load(SpecifiedValues const& c) { - return c.borders->top; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-backgrounds-3/#border-width -export struct BorderWidthProp { - Math::Insets value = LineWidth{Keywords::MEDIUM}; - - static constexpr Str name() { return "border-width"; } - - void apply(SpecifiedValues& c) const { - auto& borders = c.borders.cow(); - borders.start.width = value.start; - borders.end.width = value.end; - borders.top.width = value.top; - borders.bottom.width = value.bottom; - } - - static Math::Insets load(SpecifiedValues const& c) { - return { - c.borders->start.width, - c.borders->end.width, - c.borders->top.width, - c.borders->bottom.width, - }; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - - return Ok(); - } -}; - -// MARK: Content --------------------------------------------------------------- - -// https://www.w3.org/TR/css-gcpm-3/ -// https://drafts.csswg.org/css-content/#content-property -export struct ContentProp { - Content value = initial(); - - static constexpr Str name() { return "content"; } - - static constexpr Content initial() { return Keywords::NORMAL; } - - void apply(SpecifiedValues& c) const { - c.content = value; - } - - static Content load(SpecifiedValues const& c) { - return c.content; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Clip Path ------------------------------------------------------------- - -// https://drafts.fxtf.org/css-masking/#the-clip-path -export struct ClipPathProp { - using Value = Union; - Value value = initial(); - - static constexpr Str name() { return "clip-path"; } - - static Keywords::None initial() { return Keywords::NONE; } - - void apply(SpecifiedValues& c) const { - if (auto clipShape = value.is()) - c.clip.cow() = *clipShape; - else - c.clip.cow() = NONE; - } - - static Value load(SpecifiedValues const& c) { - if (c.clip->has()) - return c.clip->unwrap(); - return Keywords::NONE; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Borders - Table ------------------------------------------------------- - -// https://www.w3.org/TR/CSS22/tables.html#propdef-border-collapse -export struct BorderCollapseProp { - BorderCollapse value = initial(); - - static constexpr Str name() { return "border-collapse"; } - - static constexpr BorderCollapse initial() { return BorderCollapse::SEPARATE; } - - void apply(SpecifiedValues& c) const { - c.table.cow().collapse = value; - } - - static BorderCollapse load(SpecifiedValues const& c) { - return c.table->collapse; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/tables.html#propdef-border-spacing -export struct BorderSpacingProp { - BorderSpacing value = initial(); - - static constexpr Str name() { return "border-spacing"; } - - static constexpr BorderSpacing initial() { return {0_au, 0_au}; } - - void apply(SpecifiedValues& c) const { - c.table.cow().spacing = value; - } - - static BorderSpacing load(SpecifiedValues const& c) { - return c.table->spacing; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Breaks ---------------------------------------------------------------- - -// https://www.w3.org/TR/css-break-3/#propdef-break-after -export struct BreakAfterProp { - BreakBetween value = initial(); - - static constexpr Str name() { return "break-after"; } - - static constexpr BreakBetween initial() { return BreakBetween::AUTO; } - - void apply(SpecifiedValues& c) const { - c.break_.cow().after = value; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-break-3/#propdef-break-before -export struct BreakBeforeProp { - BreakBetween value = initial(); - - static constexpr Str name() { return "break-before"; } - - static constexpr BreakBetween initial() { return BreakBetween::AUTO; } - - void apply(SpecifiedValues& c) const { - c.break_.cow().before = value; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-break-3/#break-within -export struct BreakInsideProp { - BreakInside value = initial(); - - static constexpr Str name() { return "break-inside"; } - - static constexpr BreakInside initial() { return BreakInside::AUTO; } - - void apply(SpecifiedValues& c) const { - c.break_.cow().inside = value; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Flex ------------------------------------------------------------------ - -// https://www.w3.org/TR/css-flexbox-1/#flex-basis-property -export struct FlexBasisProp { - FlexBasis value = initial(); - - static constexpr Str name() { return "flex-basis"; } - - static FlexBasis initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().basis = value; - } - - static FlexBasis load(SpecifiedValues const& c) { - return c.flex->basis; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-direction -export struct FlexDirectionProp { - FlexDirection value = initial(); - - static constexpr Str name() { return "flex-direction"; } - - static constexpr FlexDirection initial() { return FlexDirection::ROW; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().direction = value; - } - - static FlexDirection load(SpecifiedValues const& c) { - return c.flex->direction; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#flex-grow-property -export struct FlexGrowProp { - Number value = initial(); - - static constexpr Str name() { return "flex-grow"; } - - static constexpr f64 initial() { return 0; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().grow = value; - } - - static Number load(SpecifiedValues const& c) { - return c.flex->grow; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-shrink -export struct FlexShrinkProp { - Number value = initial(); - - static constexpr Str name() { return "flex-shrink"; } - - static constexpr Number initial() { return 1; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().shrink = value; - } - - static Number load(SpecifiedValues const& c) { - return c.flex->shrink; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-wrap -export struct FlexWrapProp { - FlexWrap value = initial(); - - static constexpr Str name() { return "flex-wrap"; } - - static constexpr FlexWrap initial() { return FlexWrap::NOWRAP; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().wrap = value; - } - - static FlexWrap load(SpecifiedValues const& c) { - return c.flex->wrap; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#propdef-flex-flow -export struct FlexFlowProp { - Tuple value = initial(); - - static Tuple initial() { - return { - FlexDirection::ROW, - FlexWrap::NOWRAP, - }; - } - - static constexpr Str name() { return "flex-flow"; } - - void apply(SpecifiedValues& c) const { - c.flex.cow().direction = value.v0; - c.flex.cow().wrap = value.v1; - } - - static Tuple load(SpecifiedValues const& c) { - return { - c.flex->direction, - c.flex->wrap, - }; - } - - Res<> parse(Cursor& c) { - if (c.ended()) - return Error::invalidData("unexpected end of input"); - - auto direction = parseValue(c); - if (direction) { - value.v0 = direction.unwrap(); - - auto wrap = parseValue(c); - if (wrap) - value.v1 = wrap.unwrap(); - } else { - auto wrap = parseValue(c); - if (not wrap) - return Error::invalidData("expected flex direction or wrap"); - value.v1 = wrap.unwrap(); - - direction = parseValue(c); - if (direction) - value.v0 = direction.unwrap(); - } - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-flexbox-1/#propdef-flex -export struct FlexProp { - FlexItemProps value = initial(); - - static constexpr Str name() { return "flex"; } - - static FlexItemProps initial() { - return { - Keywords::AUTO, - 0, - 1, - }; - } - - void apply(SpecifiedValues& c) const { - auto& flex = c.flex.cow(); - flex.basis = value.flexBasis; - flex.grow = value.flexGrow; - flex.shrink = value.flexShrink; - } - - static FlexItemProps load(SpecifiedValues const& c) { - return { - c.flex->basis, - c.flex->grow, - c.flex->shrink, - }; - } - - Res<> parse(Cursor& c) { - if (c.ended()) - return Error::invalidData("unexpected end of input"); - - if (c.skip(Css::Token::ident("none"))) { - value = { - Keywords::AUTO, - 0, - 0, - }; - return Ok(); - } else if (c.skip(Css::Token::ident("initial"))) { - value = { - Keywords::AUTO, - 0, - 1, - }; - return Ok(); - } - - // deafult values if these parameters are omitted - value.flexGrow = value.flexShrink = 1; - value.flexBasis = CalcValue>(Length{}); - - auto parseGrowShrink = [](Cursor& c, FlexItemProps& value) -> Res<> { - auto grow = parseValue(c); - if (not grow) - return Error::invalidData("expected flex item grow"); - - value.flexGrow = grow.unwrap(); - - auto shrink = parseValue(c); - if (shrink) - value.flexShrink = shrink.unwrap(); - - return Ok(); - }; - - auto parsedGrowAndMaybeShrink = parseGrowShrink(c, value); - if (parsedGrowAndMaybeShrink) { - auto basis = parseValue(c); - if (basis) - value.flexBasis = basis.unwrap(); - } else { - auto basis = parseValue(c); - if (basis) - value.flexBasis = basis.unwrap(); - else - return Error::invalidData("expected flex item grow or basis"); - - auto parsedGrowAndMaybeShrink = parseGrowShrink(c, value); - } - return Ok(); - } -}; - -// MARK: Float & Clear --------------------------------------------------------- - -export struct FloatProp { - Float value = initial(); - - static constexpr Str name() { return "float"; } - - static Float initial() { return Float::NONE; } - - void apply(SpecifiedValues& c) const { - c.float_ = value; - } - - static Float load(SpecifiedValues const& c) { - return c.float_; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct ClearProp { - Clear value = initial(); - - static constexpr Str name() { return "clear"; } - - static Clear initial() { return Clear::NONE; } - - void apply(SpecifiedValues& c) const { - c.clear = value; - } - - static Clear load(SpecifiedValues const& c) { - return c.clear; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Fonts ----------------------------------------------------------------- - -// https://www.w3.org/TR/css-fonts-4/#font-family-prop -export struct FontFamilyProp { - Vec value = initial(); - - static constexpr Str name() { return "font-family"; } - - static Array initial() { return {"sans-serif"_sym}; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - if (not child.font.sameInstance(parent.font)) - child.font.cow().families = parent.font->families; - } - - void apply(SpecifiedValues& c) const { - c.font.cow().families = value; - } - - static Vec load(SpecifiedValues const& c) { - return c.font->families; - } - - Res<> parse(Cursor& c) { - value = {}; - eatWhitespace(c); - while (not c.ended()) { - value.pushBack(try$(parseValue(c))); - - eatWhitespace(c); - c.skip(Css::Token::comma()); - eatWhitespace(c); - } - return Ok(); - } -}; - -// https://www.w3.org/TR/css-fonts-4/#font-weight-prop -export struct FontWeightProp { - FontWeight value = initial(); - - static constexpr Str name() { return "font-weight"; } - - static FontWeight initial() { return Gfx::FontWeight::REGULAR; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - if (not child.font.sameInstance(parent.font)) - child.font.cow().weight = parent.font->weight; - } - - void apply(SpecifiedValues& child) const { - child.font.cow().weight = value.resolve(); - } - - void apply(SpecifiedValues const& parent, SpecifiedValues& child) const { - child.font.cow().weight = value.resolve(parent.font->weight); - } - - static FontWeight load(SpecifiedValues const& c) { - return c.font->weight; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-fonts-4/#font-width-prop -export struct FontWidthProp { - FontWidth value = initial(); - - static constexpr Str name() { return "font-width"; } - - static constexpr FontWidth initial() { return FontWidth::NORMAL; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - if (not child.font.sameInstance(parent.font)) - child.font.cow().width = parent.font->width; - } - - void apply(SpecifiedValues& c) const { - c.font.cow().width = value; - } - - static FontWidth load(SpecifiedValues const& c) { - return c.font->width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-fonts-4/#font-style-prop -export struct FontStyleProp { - FontStyle value = initial(); - - static constexpr Str name() { return "font-style"; } - - static constexpr FontStyle initial() { return FontStyle::NORMAL; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - if (not child.font.sameInstance(parent.font)) - child.font.cow().style = parent.font->style; - } - - void apply(SpecifiedValues& c) const { - c.font.cow().style = value; - } - - static FontStyle load(SpecifiedValues const& c) { - return c.font->style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-fonts-4/#font-prop -export struct FontProp { - FontProps value; - Opt unresolvedWeight; - - static constexpr Str name() { return "font"; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - child.font.cow() = *parent.font; - } - - void apply(SpecifiedValues& c) const { - c.font.cow() = value; - if (unresolvedWeight) - c.font.cow().weight = unresolvedWeight->resolve(); - } - - void apply(SpecifiedValues const& parent, SpecifiedValues& child) const { - child.font.cow() = value; - if (unresolvedWeight) - child.font.cow().weight = unresolvedWeight->resolve(parent.font->weight); - } - - Res<> parse(Cursor& c) { - // TODO: system family name - - while (true) { - auto fontStyle = parseValue(c); - if (fontStyle) { - value.style = fontStyle.unwrap(); - continue; - } - - auto fontWeight = parseValue(c); - if (fontWeight) { - unresolvedWeight = fontWeight.unwrap(); - continue; - } - - // TODO: font variant https://www.w3.org/TR/css-fonts-4/#font-variant-css21-values - - auto fontWidth = parseValue(c); - if (fontWidth) { - value.width = fontWidth.unwrap(); - continue; - } - - auto fontSize = parseValue(c); - if (fontSize) { - value.size = fontSize.unwrap(); - break; - } - - return Error::invalidData("expected font-style, font-weight, font-width or font-size"); - } - - if (c.skip(Css::Token::delim("/"))) { - auto lh = Ok(parseValue(c)); - // TODO: use lineheight parsed value - } - - value.families = {try$(parseValue(c))}; - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-fonts-4/#font-size-prop -export struct FontSizeProp { - FontSize value = initial(); - - static constexpr Str name() { return "font-size"; } - - static constexpr FontSize initial() { return FontSize::MEDIUM; } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - if (not child.font.sameInstance(parent.font)) - child.font.cow().size = parent.font->size; - } - - void apply(SpecifiedValues& c) const { - c.font.cow().size = value; - } - - static FontSize load(SpecifiedValues const& c) { - return c.font->size; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Line ------------------------------------------------------------------ - -export struct LineHeightProp { - LineHeight value = initial(); - - static constexpr Str name() { return "line-height"; } - - static LineHeight initial() { return LineHeight::NORMAL; } - - void apply(SpecifiedValues&) const { - // TODO - } - - static LineHeight load(SpecifiedValues const&) { - return initial(); // TODO - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Margin ---------------------------------------------------------------- - -// https://www.w3.org/TR/css-box-3/#propdef-margin - -export struct MarginTopProp { - Width value = initial(); - - static Str name() { return "margin-top"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - c.margin.cow().top = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->top; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginRightProp { - Width value = initial(); - - static Str name() { return "margin-right"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - c.margin.cow().end = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->end; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginBottomProp { - Width value = initial(); - - static constexpr Str name() { return "margin-bottom"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - c.margin.cow().bottom = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->bottom; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginLeftProp { - Width value = initial(); - - static Str name() { return "margin-left"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - c.margin.cow().start = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginProp { - Math::Insets value = initial(); - - static Str name() { return "margin"; } - - static Math::Insets initial() { return {CalcValue>(Length{})}; } - - void apply(SpecifiedValues& c) const { - c.margin.cow() = value; - } - - static Math::Insets load(SpecifiedValues const& c) { - return c.margin->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-logical/#margin-properties - -export struct MarginInlineStartProp { - Width value = initial(); - - static Str name() { return "margin-inline-start"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().start = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginInlineEndProp { - Width value = initial(); - - static Str name() { return "margin-inline-end"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().end = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->end; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginInlineProp { - Math::Insets value = initial(); - - static Str name() { return "margin-inline"; } - - static Math::Insets initial() { return {CalcValue>(Length{})}; } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().start = value.start; - c.margin.cow().end = value.end; - } - - static Math::Insets load(SpecifiedValues const& c) { - return { - c.margin->start, - c.margin->end, - }; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -export struct MarginBlockStartProp { - Width value = initial(); - - static Str name() { return "margin-block-start"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().top = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->top; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginBlockEndProp { - Width value = initial(); - - static Str name() { return "margin-block-end"; } - - static Width initial() { return CalcValue>(Length{}); } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().bottom = value; - } - - static Width load(SpecifiedValues const& c) { - return c.margin->bottom; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -export struct MarginBlockProp { - Math::Insets value = initial(); - - static Str name() { return "margin-block"; } - - static Math::Insets initial() { return {CalcValue>(Length{})}; } - - void apply(SpecifiedValues& c) const { - // FIXME: Take writing mode into account - c.margin.cow().top = value.top; - c.margin.cow().bottom = value.bottom; - } - - static Math::Insets load(SpecifiedValues const& c) { - return { - c.margin->top, - c.margin->bottom, - }; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-color-4/#propdef-opacity -export struct OpacityProp { - Number value = initial(); - - static Str name() { return "opacity"; } - - static f64 initial() { return 1; } - - void apply(SpecifiedValues& c) const { - c.opacity = value; - } - - static f64 load(SpecifiedValues const& c) { - return c.opacity; - } - - Res<> parse(Cursor& c) { - auto maybePercent = parseValue(c); - if (maybePercent) { - value = maybePercent.unwrap().value() / 100; - } else { - value = try$(parseValue(c)); - } - return Ok(); - } -}; - -// MARK: Outline -------------------------------------------------------------- - -// https://drafts.csswg.org/css-ui/#outline -export struct OutlineProp { - Outline value; - - static Str name() { return "outline"; } - - void apply(SpecifiedValues& c) const { - c.outline.cow() = value; - } - - static Outline load(SpecifiedValues const& c) { - return *c.outline; - } - - Res<> parse(Cursor& c) { - bool styleSet = false; - while (not c.ended()) { - auto width = parseValue>(c); - if (width) { - value.width = width.unwrap(); - continue; - } - - auto color = parseValue(c); - if (color) { - value.color = color.unwrap(); - continue; - } - - auto style = parseValue(c); - if (style) { - value.style = style.unwrap(); - styleSet = true; - continue; - } - - if (c.skip(Css::Token::ident("auto"))) { - if (not styleSet) - value.style = Keywords::AUTO; - value.color = Keywords::AUTO; - continue; - } - - break; - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-ui/#outline-width -export struct OutlineWidthProp { - LineWidth value = initial(); - - static Str name() { return "outline-width"; } - - static LineWidth initial() { return Keywords::MEDIUM; } - - void apply(SpecifiedValues& c) const { - c.outline.cow().width = value; - } - - static LineWidth load(SpecifiedValues const& c) { - return c.outline->width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-ui/#outline-style -export struct OutlineStyleProp { - using Value = Union; - Value value = initial(); - - static Str name() { return "outline-style"; } - - static Gfx::BorderStyle initial() { return Gfx::BorderStyle::NONE; } - - void apply(SpecifiedValues& c) const { - c.outline.cow().style = value; - } - - static Value load(SpecifiedValues const& c) { - return c.outline->style; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-ui/#outline-color -export struct OutlineColorProp { - using Value = Union; - Value value = initial(); - - static Str name() { return "outline-color"; } - - static Keywords::Auto initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.outline.cow().color = value; - } - - static Value load(SpecifiedValues const& c) { - return c.outline->color; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-ui/#outline-offset -export struct OutlineOffsetProp { - CalcValue value = initial(); - - static Str name() { return "outline-offset"; } - - static Length initial() { return 0_au; } - - void apply(SpecifiedValues& c) const { - c.outline.cow().offset = value; - } - - static CalcValue load(SpecifiedValues const& c) { - return c.outline->offset; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// MARK: Overflow -------------------------------------------------------------- - -// https://www.w3.org/TR/css-overflow/#overflow-control -export struct OverflowXProp { - Overflow value = initial(); - - static Str name() { return "overflow-x"; } - - static Overflow initial() { return Overflow::VISIBLE; } - - void apply(SpecifiedValues& c) const { - c.overflows.x = value; - } - - static Overflow load(SpecifiedValues const& c) { - return c.overflows.x; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-overflow/#overflow-control -export struct OverflowYProp { - Overflow value = initial(); - - static Str name() { return "overflow-y"; } - - static Overflow initial() { return Overflow::VISIBLE; } - - void apply(SpecifiedValues& c) const { - c.overflows.y = value; - } - - static Overflow load(SpecifiedValues const& c) { - return c.overflows.y; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-overflow/#overflow-block -export struct OverflowBlockProp { - Overflow value = initial(); - - static Str name() { return "overflow-block"; } - - static Overflow initial() { return Overflow::VISIBLE; } - - void apply(SpecifiedValues& c) const { - c.overflows.block = value; - } - - static Overflow load(SpecifiedValues const& c) { - return c.overflows.block; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-overflow/#overflow-inline -export struct OverflowInlineProp { - Overflow value = initial(); - - static Str name() { return "overflow-inline"; } - - static Overflow initial() { return Overflow::VISIBLE; } - - void apply(SpecifiedValues& c) const { - c.overflows.inline_ = value; - } - - static Overflow load(SpecifiedValues const& c) { - return c.overflows.inline_; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-overflow-3/#propdef-overflow -export struct OverflowProp { - Pair value = initial(); - - static Str name() { return "overflow"; } - - static Pair initial() { return {Overflow::VISIBLE, Overflow::VISIBLE}; } - - void apply(SpecifiedValues& c) const { - c.overflows.x = value.v0; - c.overflows.y = value.v1; - } - - static Pair load(SpecifiedValues const& c) { - return {c.overflows.x, c.overflows.y}; - } - - Res<> parse(Cursor& c) { - eatWhitespace(c); - if (c.ended()) - return Error::invalidData("unexpected end of input"); - - value.v0 = try$(parseValue(c)); - - eatWhitespace(c); - if (c.ended()) { - value.v1 = value.v0; - } else { - value.v1 = try$(parseValue(c)); - } - - return Ok(); - } -}; - -// MARK: Padding --------------------------------------------------------------- - -// https://www.w3.org/TR/css-box-3/#propdef-padding - -export struct PaddingTopProp { - CalcValue> value = initial(); - - static Str name() { return "padding-top"; } - - static Length initial() { return Length{}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().top = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->top; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingRightProp { - CalcValue> value = initial(); - - static Str name() { return "padding-right"; } - - static Length initial() { return Length{}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().end = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->end; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingBottomProp { - CalcValue> value = initial(); - - static Str name() { return "padding-bottom"; } - - static Length initial() { return Length{}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().bottom = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->bottom; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingLeftProp { - CalcValue> value = initial(); - - static Str name() { return "padding-left"; } - - static Length initial() { return {}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().start = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingInlineStart { - CalcValue> value = initial(); - - static Str name() { return "padding-inline-start"; } - - static Length initial() { return Length{}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().start = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingInlineEnd { - CalcValue> value = initial(); - - static Str name() { return "padding-inline-end"; } - - static Length initial() { return Length{}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow().end = value; - } - - static CalcValue> load(SpecifiedValues const& c) { - return c.padding->end; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>(c)); - return Ok(); - } -}; - -export struct PaddingProp { - Math::Insets>> value = initial(); - - static Str name() { return "padding"; } - - static Math::Insets>> initial() { return {Length{}}; } - - void apply(SpecifiedValues& c) const { - c.padding.cow() = value; - } - - static Math::Insets>> load(SpecifiedValues const& c) { - return *c.padding; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>>>(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-display-3/#order-property -export struct OrderProp { - Integer value = initial(); - - static Str name() { return "order"; } - - static Integer initial() { return 0; } - - void apply(SpecifiedValues& c) const { - c.order = value; - } - - static Integer load(SpecifiedValues const& c) { - return c.order; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Positioning ----------------------------------------------------------- - -// https://www.w3.org/TR/CSS22/visuren.html#positioning-scheme -export struct PositionProp { - Position value = initial(); - - static Str name() { return "position"; } - - static Position initial() { return Keywords::STATIC; } - - void apply(SpecifiedValues& c) const { - c.position = value; - } - - static Position load(SpecifiedValues const& c) { - return c.position; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/visuren.html#propdef-top -export struct TopProp { - Width value = initial(); - - static Str name() { return "top"; } - - static Width initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.offsets.cow().top = value; - } - - static Width load(SpecifiedValues const& c) { - return c.offsets->top; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/visuren.html#propdef-right -export struct RightProp { - Width value = initial(); - - static Str name() { return "right"; } - - static Width initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.offsets.cow().end = value; - } - - static Width load(SpecifiedValues const& c) { - return c.offsets->end; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/visuren.html#propdef-bottom -export struct BottomProp { - Width value = initial(); - - static Str name() { return "bottom"; } - - static Width initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.offsets.cow().bottom = value; - } - - static Width load(SpecifiedValues const& c) { - return c.offsets->bottom; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/CSS22/visuren.html#propdef-left -export struct LeftProp { - Width value = initial(); - - static Str name() { return "left"; } - - static Width initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.offsets.cow().start = value; - } - - static Width load(SpecifiedValues const& c) { - return c.offsets->start; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Sizing ---------------------------------------------------------------- -// https://www.w3.org/TR/css-sizing-3 - -// https://www.w3.org/TR/css-sizing-3/#box-sizing -export struct BoxSizingProp { - BoxSizing value = initial(); - - static constexpr Str name() { return "box-sizing"; } - - static constexpr BoxSizing initial() { return BoxSizing::CONTENT_BOX; } - - void apply(SpecifiedValues& c) const { - c.boxSizing = value; - } - - static BoxSizing load(SpecifiedValues const& c) { - return c.boxSizing; - } - - Res<> parse(Cursor& c) { - if (c.skip(Css::Token::ident("border-box"))) - value = BoxSizing::BORDER_BOX; - else if (c.skip(Css::Token::ident("content-box"))) - value = BoxSizing::CONTENT_BOX; - else - return Error::invalidData("expected 'border-box' or 'content-box'"); - - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-width - -export struct WidthProp { - Size value = initial(); - - static constexpr Str name() { return "width"; } - - static Size initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().width = value; - } - - static Size load(SpecifiedValues const& c) { - return c.sizing->width; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-height - -export struct HeightProp { - Size value = initial(); - - static constexpr Str name() { return "height"; } - - static Size initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().height = value; - } - - static Size load(SpecifiedValues const& c) { - return c.sizing->height; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-min-width - -export struct MinWidthProp { - Size value = initial(); - - static constexpr Str name() { return "min-width"; } - - static Size initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().minWidth = value; - } - - static Size load(SpecifiedValues const& c) { - return c.sizing->minWidth; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-min-height - -export struct MinHeightProp { - Size value = initial(); - - static constexpr Str name() { return "min-height"; } - - static Size initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().minHeight = value; - } - - static Size load(SpecifiedValues const& c) { - return c.sizing->minHeight; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-max-width - -export struct MaxWidthProp { - MaxSize value = initial(); - - static constexpr Str name() { return "max-width"; } - - static MaxSize initial() { return Keywords::NONE; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().maxWidth = value; - } - - static MaxSize load(SpecifiedValues const& c) { - return c.sizing->maxWidth; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://www.w3.org/TR/css-sizing-3/#propdef-max-height - -export struct MaxHeightProp { - MaxSize value = initial(); - - static constexpr Str name() { return "max-height"; } - - static MaxSize initial() { return Keywords::NONE; } - - void apply(SpecifiedValues& c) const { - c.sizing.cow().maxHeight = value; - } - - static MaxSize load(SpecifiedValues const& c) { - return c.sizing->maxHeight; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: Text -// https://drafts.csswg.org/css-text-4 - -// https://drafts.csswg.org/css-text/#text-align-property - -export struct TextAlignProp { - TextAlign value = initial(); - - static constexpr Str name() { return "text-align"; } - - static TextAlign initial() { return TextAlign::LEFT; } - - void apply(SpecifiedValues& c) const { - c.text.cow().align = value; - } - - static TextAlign load(SpecifiedValues const& c) { - return c.text->align; - } - - Res<> parse(Cursor& c) { - if (c.skip(Css::Token::ident("left"))) { - value = TextAlign::LEFT; - } else if (c.skip(Css::Token::ident("right"))) { - value = TextAlign::RIGHT; - } else if (c.skip(Css::Token::ident("center"))) { - value = TextAlign::CENTER; - } else if (c.skip(Css::Token::ident("justify"))) { - value = TextAlign::JUSTIFY; - } else if (c.skip(Css::Token::ident("start"))) { - value = TextAlign::START; - } else if (c.skip(Css::Token::ident("end"))) { - value = TextAlign::END; - } else { - return Error::invalidData("expected text-align"); - } - return Ok(); - } -}; - -// https://drafts.csswg.org/css-text-4/#text-transform-property - -export struct TextTransformProp { - TextTransform value = initial(); - - static constexpr Str name() { return "text-transform"; } - - static TextTransform initial() { return TextTransform::NONE; } - - void apply(SpecifiedValues& c) const { - c.text.cow().transform = value; - } - - static TextTransform load(SpecifiedValues const& c) { - return c.text->transform; - } - - Res<> parse(Cursor& c) { - if (c.ended()) - return Error::invalidData("unexpected end of input"); - - if (c.skip(Css::Token::ident("none"))) { - value = TextTransform::NONE; - } else if (c.skip(Css::Token::ident("uppercase"))) { - value = TextTransform::UPPERCASE; - } else if (c.skip(Css::Token::ident("lowsercase"))) { - value = TextTransform::LOWERCASE; - } else { - return Error::invalidData("expected text-transform"); - } - - return Ok(); - } -}; - -// MARK: Transform ------------------------------------------------------------- -// https://drafts.csswg.org/css-transforms/#transform-property - -// https://drafts.csswg.org/css-transforms/#transform-origin-property -export struct TransformOriginProp { - TransformOrigin value = initial(); - - static constexpr Str name() { return "transform-origin"; } - - static TransformOrigin initial() { - return { - .xOffset = CalcValue>{Percent{50}}, - .yOffset = CalcValue>{Percent{50}}, - }; - } - - void apply(SpecifiedValues& c) const { - c.transform.cow().origin = value; - } - - static TransformOrigin load(SpecifiedValues const& c) { - return c.transform->origin; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-transforms/#transform-box -export struct TransformBoxProp { - TransformBox value = initial(); - - static constexpr Str name() { return "transform-box"; } - - static TransformBox initial() { return Keywords::VIEW_BOX; } - - void apply(SpecifiedValues& c) const { - c.transform.cow().box = value; - } - - static TransformBox load(SpecifiedValues const& c) { - return c.transform->box; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-transforms/#propdef-transform -export struct TransformProp { - Transform value = initial(); - - static constexpr Str name() { return "transform"; } - - static Transform initial() { return Keywords::NONE; } - - void apply(SpecifiedValues& c) const { - c.transform.cow().transform = value; - } - - static Transform load(SpecifiedValues const& c) { - return c.transform->transform; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://drafts.csswg.org/css-display/#visibility -export struct VisibilityProp { - Visibility value = initial(); - - static constexpr Str name() { return "visibility"; } - - static Visibility initial() { return Visibility::VISIBLE; } - - void apply(SpecifiedValues& c) const { - c.visibility = value; - } - - static Visibility load(SpecifiedValues const& c) { - return c.visibility; - } - - static void inherit(SpecifiedValues const& parent, SpecifiedValues& child) { - child.visibility = parent.visibility; - } - - Res<> parse(Cursor& c) { - if (c.skip(Css::Token::ident("visible"))) { - value = Visibility::VISIBLE; - } else if (c.skip(Css::Token::ident("hidden"))) { - value = Visibility::HIDDEN; - } else if (c.skip(Css::Token::ident("collapse"))) { - value = Visibility::COLLAPSE; - } else { - return Error::invalidData("expected visibility"); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css-text/#white-space-property - -export struct WhiteSpaceProp { - WhiteSpace value = initial(); - - static constexpr Str name() { return "white-space"; } - - static WhiteSpace initial() { return WhiteSpace::NORMAL; } - - void apply(SpecifiedValues& c) const { - c.text.cow().whiteSpace = value; - } - - static WhiteSpace load(SpecifiedValues const& c) { - return c.text->whiteSpace; - } - - Res<> parse(Cursor& c) { - if (c.skip(Css::Token::ident("normal"))) { - value = WhiteSpace::NORMAL; - } else if (c.skip(Css::Token::ident("nowrap"))) { - value = WhiteSpace::NOWRAP; - } else if (c.skip(Css::Token::ident("pre"))) { - value = WhiteSpace::PRE; - } else if (c.skip(Css::Token::ident("pre-wrap"))) { - value = WhiteSpace::PRE_WRAP; - } else if (c.skip(Css::Token::ident("pre-line"))) { - value = WhiteSpace::PRE_LINE; - } else if (c.skip(Css::Token::ident("break-spaces"))) { - value = WhiteSpace::BREAK_SPACES; - } else { - return Error::invalidData("expected white-space"); - } - - return Ok(); - } -}; - -// https://drafts.csswg.org/css2/#z-index - -export struct ZIndexProp { - ZIndex value = initial(); - - static constexpr Str name() { return "z-index"; } - - static constexpr ZIndex initial() { return Keywords::AUTO; } - - void apply(SpecifiedValues& c) const { - c.zIndex = value; - } - - static ZIndex load(SpecifiedValues const& c) { - return c.zIndex; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// MARK: SVG ---------------------------------------------------------------- - -// https://svgwg.org/svg2-draft/geometry.html#XProperty -export struct SVGXProp { - PercentOr value = initial(); - - static constexpr Str name() { return "x"; } - - static constexpr Length initial() { return Length{0_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().x = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->x; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/geometry.html#YProperty -export struct SVGYProp { - PercentOr value = initial(); - - static constexpr Str name() { return "y"; } - - static constexpr Length initial() { return Length{0_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().y = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->y; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/geometry.html#CXProperty -export struct SVGCXProp { - PercentOr value = initial(); - - static constexpr Str name() { return "cx"; } - - static constexpr Length initial() { return Length{0_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().cx = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->cx; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/geometry.html#CYProperty -export struct SVGCYProp { - PercentOr value = initial(); - - static constexpr Str name() { return "cy"; } - - static constexpr Length initial() { return Length{0_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().cy = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->cy; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/geometry.html#RProperty -export struct SVGRProp { - PercentOr value = initial(); - - static constexpr Str name() { return "r"; } - - static constexpr Length initial() { return Length{0_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().r = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->r; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/painting.html#FillProperty -export struct SVGFillProp { - Paint value = initial(); - - static constexpr Str name() { return "fill"; } - - static constexpr Paint initial() { return Color{Gfx::BLACK}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().fill = value; - } - - static Paint load(SpecifiedValues const& c) { - return c.svg->fill; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/paths.html#TheDProperty -export struct SVGDProp { - Union value = initial(); - - static constexpr Str name() { return "d"; } - - static constexpr Union initial() { return NONE; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().d = value; - } - - static Union load(SpecifiedValues const& c) { - return c.svg->d; - } - - Res<> parse(Cursor& c) { - eatWhitespace(c); - if (c.peek() != Css::Sst::FUNC or c.peek().prefix != Css::Token::function("path(")) { - return Error::invalidData("expected path function"); - } - - auto pathFunc = c.next(); - Cursor scanPath{pathFunc.content}; - value = try$(parseValue(scanPath)); - - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/coords.html#ViewBoxAttribute -export struct SVGViewBoxProp { - Opt value = initial(); - - static constexpr Str name() { return "viewBox"; } - - static Opt initial() { return NONE; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().viewBox = value; - } - - static Opt load(SpecifiedValues const& c) { - return c.svg->viewBox; - } - - Res<> parse(Cursor& c) { - ViewBox viewBox; - - viewBox.minX = try$(parseValue(c)); - - c.skip(Css::Token::comma()); - viewBox.minY = try$(parseValue(c)); - - c.skip(Css::Token::comma()); - viewBox.width = try$(parseValue(c)); - - c.skip(Css::Token::comma()); - viewBox.height = try$(parseValue(c)); - - value = std::move(viewBox); - - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint -export struct SVGStrokeProp { - Paint value = initial(); - - static constexpr Str name() { return "stroke"; } - - static Paint initial() { return NONE; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().stroke = value; - } - - static Paint load(SpecifiedValues const& c) { - return c.svg->stroke; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue(c)); - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/painting.html#StrokeOpacity -export struct SvgStrokeOpacityProp { - Number value = initial(); - - static Str name() { return "stroke-opacity"; } - - static f64 initial() { return 1; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().strokeOpacity = value; - } - - static f64 load(SpecifiedValues const& c) { - return c.svg->strokeOpacity; - } - - Res<> parse(Cursor& c) { - auto maybePercent = parseValue(c); - if (maybePercent) { - value = maybePercent.unwrap().value() / 100; - } else { - value = try$(parseValue(c)); - } - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/painting.html#FillOpacity -export struct FillOpacityProp { - Number value = initial(); - - static Str name() { return "fill-opacity"; } - - static f64 initial() { return 1; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().fillOpacity = value; - } - - static f64 load(SpecifiedValues const& c) { - return c.svg->fillOpacity; - } - - Res<> parse(Cursor& c) { - auto maybePercent = parseValue(c); - if (maybePercent) { - value = maybePercent.unwrap().value() / 100; - } else { - value = try$(parseValue(c)); - } - return Ok(); - } -}; - -// https://svgwg.org/svg2-draft/painting.html#StrokeWidth -export struct StrokeWidthProp { - PercentOr value = initial(); - - static constexpr Str name() { return "stroke-width"; } - - static constexpr Length initial() { return Length{1_au}; } - - void apply(SpecifiedValues& c) const { - c.svg.cow().strokeWidth = value; - } - - static PercentOr load(SpecifiedValues const& c) { - return c.svg->strokeWidth; - } - - Res<> parse(Cursor& c) { - value = try$(parseValue>(c)); - return Ok(); - } -}; - -// MARK: OTHER ----------------------------------------------------------------- -// These are no specs or behave differently than the others, you can find more details for each one in the comments. - -// https://drafts.csswg.org/css-variables/#defining-variables -// this symbolizes a custom property, it starts with `--` and can be used to store a value that can be reused in the stylesheet -export struct CustomProp { - Symbol varName; - Css::Content value; - - CustomProp(Symbol varName, Css::Content value) - : varName(varName), value(value) { - } - - static constexpr Str name() { return "custom prop"; } - - void apply(SpecifiedValues& c) const { - c.setCustomProp(varName, value); - } - - void repr(Io::Emit& e) const { - e("(var {#} = {})", varName, value); - } -}; - -// NOTE: A property that could not be parsed, it's used to store the value -// as-is and apply it with the cascade and custom properties -export struct DeferredProp { - Symbol propName; - Css::Content value; - - static constexpr Str name() { return "deferred prop"; } - - static bool _expandVariable(Cursor& c, Map const& env, Css::Content& out); - - static bool _expandFunction(Cursor& c, Map const& env, Css::Content& out); - - static void _expandContent(Cursor& c, Map const& env, Css::Content& out); - - void apply(SpecifiedValues const& parent, SpecifiedValues& c) const; - - void repr(Io::Emit& e) const { - e("(deferred {#} = {})", propName, value); - } -}; - -enum struct Default { - INITIAL, //< represents the value defined as the property’s initial value. - INHERIT, //< represents the property’s computed value on the parent element. - UNSET, //< acts as either inherit or initial, depending on whether the property is inherited or not. - REVERT, //< rolls back the cascade to the cascaded value of the earlier origin. - - _LEN, -}; - -export struct DefaultedProp { - String propName; - Default value; - - static constexpr Str name() { return "defaulted prop"; } - - void apply(SpecifiedValues const& parent, SpecifiedValues& c) const; - - void repr(Io::Emit&) const; -}; - -// MARK: Style Property ------------------------------------------------------- - -using _StyleProp = Union< - // Align - AlignContentProp, - JustifyContentProp, - JustifySelfProp, - AlignSelfProp, - JustifyItemsProp, - AlignItemsProp, - - RowGapProp, - ColumnGapProp, - - // Baseline - DominantBaselineProp, - BaselineSourceProp, - AlignmentBaselineProp, - - // Background - BackgroundAttachmentProp, - BackgroundColorProp, - BackgroundImageProp, - BackgroundPositionProp, - BackgroundRepeatProp, - BackgroundProp, - ColorProp, - DisplayProp, - TableLayoutProp, - CaptionSideProp, - - // Transform - TransformOriginProp, - TransformBoxProp, - TransformProp, - - // Visibility - VisibilityProp, - - // Borders - BorderTopColorProp, - BorderRightColorProp, - BorderBottomColorProp, - BorderLeftColorProp, - BorderColorProp, - - BorderTopWidthProp, - BorderRightWidthProp, - BorderBottomWidthProp, - BorderLeftWidthProp, - - BorderStyle, - BorderTopStyleProp, - BorderRightStyleProp, - BorderBottomStyleProp, - BorderLeftStyleProp, - - BorderRadiusTopRight, - BorderRadiusTopLeft, - BorderRadiusBottomRight, - BorderRadiusBottomLeft, - BorderRadius, - - BorderTopProp, - BorderRightProp, - BorderBottomProp, - BorderLeftProp, - BorderProp, - - BorderWidthProp, - - // Borders - Table - BorderCollapseProp, - BorderSpacingProp, - - // Clip - ClipPathProp, - - // Content - ContentProp, - - // Breaks - BreakAfterProp, - BreakBeforeProp, - BreakInsideProp, - - // Flex - FlexBasisProp, - FlexDirectionProp, - FlexGrowProp, - FlexShrinkProp, - FlexWrapProp, - FlexFlowProp, - FlexProp, - - // Float & Clear - FloatProp, - ClearProp, - - // Font - FontFamilyProp, - FontWeightProp, - FontWidthProp, - FontStyleProp, - FontSizeProp, - FontProp, - - // Line - LineHeightProp, - - // Margin - MarginTopProp, - MarginRightProp, - MarginBottomProp, - MarginLeftProp, - MarginProp, - - MarginInlineStartProp, - MarginInlineEndProp, - MarginInlineProp, - - MarginBlockStartProp, - MarginBlockEndProp, - MarginBlockProp, - - // Outline - OutlineProp, - OutlineColorProp, - OutlineOffsetProp, - OutlineStyleProp, - OutlineWidthProp, - - // Overflow - OverflowXProp, - OverflowYProp, - OverflowBlockProp, - OverflowInlineProp, - OverflowProp, - - OpacityProp, - - // Padding - PaddingTopProp, - PaddingRightProp, - PaddingBottomProp, - PaddingLeftProp, - PaddingInlineStart, - PaddingInlineEnd, - PaddingProp, - - // Positioning - PositionProp, - TopProp, - RightProp, - BottomProp, - LeftProp, - - // Sizing - BoxSizingProp, - WidthProp, - HeightProp, - MinWidthProp, - MinHeightProp, - MaxWidthProp, - MaxHeightProp, - - // Text - TextAlignProp, - TextTransformProp, - WhiteSpaceProp, - - // ZIndex - ZIndexProp, - - // Other - CustomProp, - DeferredProp, - DefaultedProp, - - // SVG - SVGXProp, - SVGYProp, - SVGCXProp, - SVGCYProp, - SVGRProp, - SVGFillProp, - SVGDProp, - SVGStrokeProp, - SvgStrokeOpacityProp, - SVGViewBoxProp, - FillOpacityProp, - StrokeWidthProp - /**/ - >; - -// FIXME: should be targeted in style computing refactoring -using SVGStyleProp = Union< - SVGXProp, - SVGYProp, - SVGFillProp, - SVGDProp, - SVGCXProp, - SVGCYProp, - SVGRProp, - SVGStrokeProp, - SVGViewBoxProp, - HeightProp, - FillOpacityProp, - WidthProp, - StrokeWidthProp, - TransformProp, - TransformOriginProp>; - -export enum struct Important { - NO, - YES, -}; - -export struct StyleProp : _StyleProp { - using _StyleProp::_StyleProp; - Important important = Important::NO; - - static constexpr Array LEGACY_ALIAS = { - // https://drafts.csswg.org/css-align-3/#gap-legacy - Pair{"grid-row-gap", "row-gap"}, - Pair{"grid-column-gap", "column-gap"}, - Pair{"grid-gap", "gap"}, - }; - - Str name() const; - - void inherit(SpecifiedValues const& parent, SpecifiedValues& child) const; - - void apply(SpecifiedValues const& parent, SpecifiedValues& c) const; - - void repr(Io::Emit& e) const; -}; - -} // namespace Vaev::Style diff --git a/src/vaev-engine/style/rules.cpp b/src/vaev-engine/style/rules.cpp index ef21d3bb..438303c3 100644 --- a/src/vaev-engine/style/rules.cpp +++ b/src/vaev-engine/style/rules.cpp @@ -10,7 +10,6 @@ import :style.fonts; import :style.media; import :style.origin; import :style.page; -import :style.props; import :style.selector; import :style.namespace_; import :style.matcher; @@ -26,10 +25,10 @@ export struct Rule; // https://www.w3.org/TR/cssom-1/#the-cssstylerule-interface export struct StyleRule { Selector selector = TypeSelector::universal(); - Vec props; + Vec> props; Origin origin = Origin::AUTHOR; - static StyleRule parse(Css::Sst const& sst, Origin origin, Namespace& ns) { + static StyleRule parse(PropertyRegistry& propertyRegistry, Css::Sst const& sst, Origin origin, Namespace& ns) { if (sst != Css::Sst::RULE) panic("expected rule"); @@ -41,20 +40,18 @@ export struct StyleRule { // Parse the selector. auto& prefix = sst.prefix.unwrap(); Cursor prefixContent = prefix->content; - auto maybeSelector = Selector::parse(prefixContent, ns); - if (maybeSelector) { - res.selector = maybeSelector.take(); + if (auto s = Selector::parse(prefixContent, ns)) { + res.selector = s.take(); } else { - logWarnIf(debugRule, "failed to parse selector: {}: {}", prefix->content, maybeSelector); + logWarnIf(debugRule, "failed to parse selector: {}: {}", prefix->content, s); res.selector = EmptySelector{}; } // Parse the properties. for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - auto prop = parseDeclaration(item); - if (prop) - res.props.pushBack(prop.take()); + if (auto p = propertyRegistry.parseDeclaration(item)) + res.props.pushBack(p.take()); } else { logWarnIf(debugRule, "unexpected item in style rule: {}", item); } @@ -105,7 +102,7 @@ export struct MediaRule { MediaQuery media; Vec rules; - static MediaRule parse(Css::Sst const& sst, Origin origin, Namespace& ns); + static MediaRule parse(PropertyRegistry& registry, Css::Sst const& sst, Origin origin, Namespace& ns); bool match(Media const& m) const { return media.match(m); @@ -119,7 +116,7 @@ export struct FontFaceRule { Vec descs; static FontFaceRule parse(Css::Sst const& sst) { - return {parseDeclarations(sst, false)}; + return {parseDeclarations(sst)}; } void repr(Io::Emit& e) const { @@ -175,10 +172,10 @@ export struct NamespaceRule { export struct PageRule { Vec selectors; - Vec props; + Vec> props; Vec areas; - static PageRule parse(Css::Sst const& sst) { + static PageRule parse(PropertyRegistry& registry, Css::Sst const& sst) { if (sst != Css::Sst::RULE) panic("expected rule"); @@ -195,12 +192,12 @@ export struct PageRule { // Parse the properties. for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - auto prop = parseDeclaration(item); + auto prop = registry.parseDeclaration(item); if (prop) res.props.pushBack(prop.take()); } else if (item == Css::Sst::RULE and item.token == Css::Token::AT_KEYWORD) { - auto rule = PageAreaRule::parse(item); + auto rule = PageAreaRule::parse(registry, item); if (rule) res.areas.pushBack(*rule); } else { @@ -225,7 +222,7 @@ export struct PageRule { void apply(PageSpecifiedValues& c) const { for (auto const& prop : props) { - prop.apply(*c.style, *c.style); + prop->apply(*c.style, *c.style); } for (auto const& area : areas) { @@ -251,26 +248,26 @@ using _Rule = Union< export struct Rule : _Rule { using _Rule::_Rule; - static Rule parse(Css::Sst const& sst, Origin origin, Namespace& ns) { + static Rule parse(PropertyRegistry& registry, Css::Sst const& sst, Origin origin, Namespace& ns) { if (sst != Css::Sst::RULE) panic("expected rule"); auto tok = sst.token; if (tok.data == "@media") - return MediaRule::parse(sst, origin, ns); + return MediaRule::parse(registry, sst, origin, ns); else if (tok.data == "@import") return ImportRule::parse(sst); else if (tok.data == "@font-face") return FontFaceRule::parse(sst); else if (tok.data == "@page") - return PageRule::parse(sst); + return PageRule::parse(registry, sst); else if (tok.data == "@supports") { logWarnIf(debugRule, "cannot parse '@supports' at-rule"); return StyleRule{}; } else if (tok.data == "@namespace") { return NamespaceRule::parse(sst, ns); } else - return StyleRule::parse(sst, origin, ns); + return StyleRule::parse(registry, sst, origin, ns); } void repr(Io::Emit& e) const { @@ -280,7 +277,7 @@ export struct Rule : _Rule { } }; -MediaRule MediaRule::parse(Css::Sst const& sst, Origin origin, Namespace& ns) { +MediaRule MediaRule::parse(PropertyRegistry& registry, Css::Sst const& sst, Origin origin, Namespace& ns) { if (sst != Css::Sst::RULE) panic("expected rule"); @@ -297,7 +294,7 @@ MediaRule MediaRule::parse(Css::Sst const& sst, Origin origin, Namespace& ns) { // Parse the rules. for (auto const& item : sst.content) { if (item == Css::Sst::RULE) { - res.rules.pushBack(Rule::parse(item, origin, ns)); + res.rules.pushBack(Rule::parse(registry, item, origin, ns)); } else { logWarnIf(debugRule, "unexpected item in media rule: {}", item.type); } diff --git a/src/vaev-engine/style/specified-impl.cpp b/src/vaev-engine/style/specified-impl.cpp index 29aa81e1..8f6e38dc 100644 --- a/src/vaev-engine/style/specified-impl.cpp +++ b/src/vaev-engine/style/specified-impl.cpp @@ -1,16 +1,16 @@ module Vaev.Engine; -import :style.props; +import :props.registry; namespace Vaev::Style { SpecifiedValues const& SpecifiedValues::initial() { static SpecifiedValues computed = [] { SpecifiedValues res{}; - StyleProp::any([&]() { - if constexpr (requires { T::initial(); }) - T{}.apply(res); - }); + auto registry = defaultRegistry(); + for (auto& [_, v] : registry._registrations.iterUnordered()) + if (not v->flags().has(Property::SHORTHAND)) + v->initial()->apply(res, res); return res; }(); return computed; diff --git a/src/vaev-engine/style/specified.cpp b/src/vaev-engine/style/specified.cpp index 78bcf4ed..997f39a1 100644 --- a/src/vaev-engine/style/specified.cpp +++ b/src/vaev-engine/style/specified.cpp @@ -95,8 +95,8 @@ export struct SpecifiedValues { variables.cow().put(varName, value); } - Css::Content getCustomProp(Str varName) const { - auto value = variables->access(Symbol::from(varName)); + Css::Content getCustomProp(Symbol varName) const { + auto value = variables->access(varName); if (value) return *value; return {}; diff --git a/src/vaev-engine/style/stylesheet.cpp b/src/vaev-engine/style/stylesheet.cpp index 414a5430..c258282d 100644 --- a/src/vaev-engine/style/stylesheet.cpp +++ b/src/vaev-engine/style/stylesheet.cpp @@ -16,7 +16,7 @@ export struct StyleSheet { Vec rules; Origin origin = Origin::AUTHOR; - static StyleSheet parse(Css::Sst const& sst, Ref::Url href, Origin origin) { + static StyleSheet parse(PropertyRegistry& registry, Css::Sst const& sst, Ref::Url href, Origin origin) { Namespace ns; if (sst != Css::Sst::LIST) @@ -25,7 +25,7 @@ export struct StyleSheet { StyleSheet res; for (auto const& item : sst.content) { if (item == Css::Sst::RULE) { - res.rules.pushBack(Rule::parse(item, origin, ns)); + res.rules.pushBack(Rule::parse(registry, item, origin, ns)); } else { logWarn("unexpected item in stylesheet: {}", item.type); } @@ -37,10 +37,10 @@ export struct StyleSheet { return res; } - static StyleSheet parse(Io::SScan& s, Ref::Url href, Origin origin = Origin::AUTHOR) { + static StyleSheet parse(PropertyRegistry& registry, Io::SScan& s, Ref::Url href, Origin origin = Origin::AUTHOR) { Css::Lexer lex{s}; Css::Sst sst = consumeRuleList(lex, true); - return parse(sst, href, origin); + return parse(registry, sst, href, origin); } void add(Rule&& rule) { diff --git a/src/vaev-engine/values/background.cpp b/src/vaev-engine/values/background.cpp index 36803395..849ae7db 100644 --- a/src/vaev-engine/values/background.cpp +++ b/src/vaev-engine/values/background.cpp @@ -19,13 +19,11 @@ using namespace Karm; namespace Vaev { -export enum struct BackgroundAttachment { - SCROLL, - FIXED, - LOCAL, - - _LEN -}; +// https://drafts.csswg.org/css-backgrounds/#background-attachment +using BackgroundAttachment = Union< + Keywords::Scroll, + Keywords::Fixed, + Keywords::Local>; // MARK: Background Position --------------------------------------------------- // https://www.w3.org/TR/css-backgrounds-3/#typedef-bg-position @@ -265,7 +263,7 @@ export struct BackgroundRepeat { export struct BackgroundLayer { Opt image; - BackgroundAttachment attachment; + BackgroundAttachment attachment = Keywords::FIXED; BackgroundPosition position; BackgroundRepeat repeat; diff --git a/src/vaev-engine/values/base.cpp b/src/vaev-engine/values/base.cpp index 3ba2e403..e049290c 100644 --- a/src/vaev-engine/values/base.cpp +++ b/src/vaev-engine/values/base.cpp @@ -31,9 +31,9 @@ Res parseValue(Cursor& c) { export template Res parseValue(Str str) { Css::Lexer lex{str}; - auto content = Css::consumeDeclarationValue(lex); - Cursor c{content}; - return ValueParser::parse(c); + auto [sst, _] = Css::consumeDeclarationValue(lex); + Cursor content{sst}; + return ValueParser::parse(content); } export template diff --git a/src/vaev-engine/values/defs/keywords.inc b/src/vaev-engine/values/defs/keywords.inc index bce20a3f..97d93d97 100644 --- a/src/vaev-engine/values/defs/keywords.inc +++ b/src/vaev-engine/values/defs/keywords.inc @@ -40,3 +40,5 @@ KEYWORD(Sticky, "sticky", STICKY) KEYWORD(Absolute, "absolute", ABSOLUTE) KEYWORD(Relative, "relative", RELATIVE) KEYWORD(Static, "static", STATIC) +KEYWORD(Scroll, "scroll", SCROLL) +KEYWORD(Local, "local", LOCAL) From 9e538a8c4fecfb094ad99de42a43102c906c8319 Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Wed, 3 Dec 2025 20:57:32 +0100 Subject: [PATCH 3/5] wip --- src/vaev-engine/props/background.cpp | 2 +- src/vaev-engine/props/base.cpp | 116 ++++++++------ src/vaev-engine/props/border.cpp | 32 ++-- src/vaev-engine/props/defs/properties.inc | 176 +++++++++++----------- src/vaev-engine/props/flex.cpp | 6 +- src/vaev-engine/props/fonts.cpp | 10 +- src/vaev-engine/props/margin.cpp | 16 +- src/vaev-engine/props/outline.cpp | 6 +- src/vaev-engine/props/overflow.cpp | 4 +- src/vaev-engine/props/padding.cpp | 12 +- src/vaev-engine/style/computer.cpp | 68 ++++----- 11 files changed, 235 insertions(+), 213 deletions(-) diff --git a/src/vaev-engine/props/background.cpp b/src/vaev-engine/props/background.cpp index d2fd450a..f9d7cf58 100644 --- a/src/vaev-engine/props/background.cpp +++ b/src/vaev-engine/props/background.cpp @@ -241,7 +241,7 @@ export struct BackgroundProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { makeRc( - registry.resolveRegistration(Properties::BACKGROUND_COLOR).unwrap(), + registry.resolveRegistration(Properties::BACKGROUND_COLOR, {}).take(), _value.color ), }; diff --git a/src/vaev-engine/props/base.cpp b/src/vaev-engine/props/base.cpp index 31b9811b..acc235ae 100644 --- a/src/vaev-engine/props/base.cpp +++ b/src/vaev-engine/props/base.cpp @@ -117,8 +117,6 @@ export struct Property : Meta::NoCopy { bool isCustomProperty() const { return registration->flags().has(CUSTOM_PROPERTY); } - - bool isBogusOr }; // MARK: Custom Property ------------------------------------------------------- @@ -174,11 +172,6 @@ struct CustomProperty : Property { // NOTE: A property that could not be parsed, it's used to store the value // as-is and apply it with the cascade and custom properties struct DeferredProperty : Property { - enum struct Policy { - ALLOW, - DISALLOW, - }; - Css::Content _value; DeferredProperty(Rc registration, Css::Content value) @@ -356,44 +349,67 @@ struct BogusProperty : Property { static Map LEGACY_ALIAS = { // https://drafts.csswg.org/css-align-3/#gap-legacy - {"grid-row-gap"_sym, "row-gap"_sym}, - {"grid-column-gap"_sym, "column-gap"_sym}, - {"grid-gap"_sym, "gap"_sym}, + {"grid-row-gap"_sym, Properties::ROW_GAP}, + {"grid-column-gap"_sym, Properties::COLUMN_GAP}, + {"grid-gap"_sym, Properties::GAP}, + + // https://drafts.csswg.org/css-fonts/#font-stretch-prop + {"font-stretch"_sym, Properties::FONT_WIDTH} }; export struct PropertyRegistry { Map> _registrations; - Vec> _presentationAttributes; + Map> _presentationAttributes; + + enum struct Options : u8 { + GENERATE_BOGUS = 1 << 0, + GENERATE_CUSTOM_PROPERTY = 1 << 1, + DEFER_UNPARSABLE = 1 << 2, + ALLOW_DEFAULTING = 1 << 3, + }; + + using enum Options; + + void registerProperty(Symbol propertyName, Rc registration) { + if (registration->flags().has(Property::PRESENTATION_ATTRIBUTE)) + _presentationAttributes.put(propertyName, registration); + _registrations.put(propertyName, registration); + } template void registerProperty() { auto registration = makeRc(); registration->_self = registration; - _registrations.put(registration->name(), registration); + registerProperty(registration->name(), registration); } Rc registerCustomProperty(Symbol propertyName) { auto registration = makeRc(propertyName); - if (registration->flags().has(Property::PRESENTATION_ATTRIBUTE)) - _presentationAttributes.pushBack(registration); - _registrations.put(propertyName, registration); + registration->_self = registration; + registerProperty(propertyName, registration); return registration; } - Rc resolveRegistration(Symbol propertyName) { + Opt> resolveRegistration(Symbol propertyName, Flags options) { propertyName = LEGACY_ALIAS.tryGet(propertyName).unwrapOr(propertyName); if (auto maybeRegistration = _registrations.tryGet(propertyName)) return maybeRegistration.take(); - if (startWith(propertyName.str(), "--"s) != Match::NO) - return registerCustomProperty(propertyName); + if (options.has(GENERATE_CUSTOM_PROPERTY)) { + if (startWith(propertyName.str(), "--"s) != Match::NO) + return registerCustomProperty(propertyName); + } + + if (options.has(GENERATE_BOGUS)) { + return makeRc(propertyName); + } - return makeRc(propertyName); + return NONE; } - Opt> resolveRegistration(Str propertyName) { - return resolveRegistration(Symbol::from(propertyName)); + Opt> resolveRegistration(Str propertyName, Flags options) { + return resolveRegistration(Symbol::from(propertyName), options); } // MARK: Value Parsing ----------------------------------------------------- @@ -419,31 +435,39 @@ export struct PropertyRegistry { return makeRc(registration, content); } - Rc parseValue(Symbol propertyName, Slice content) { + Res> parseValue(Symbol propertyName, Slice content, Flags options) { Cursor cursor = content; - auto registration = resolveRegistration(propertyName); + auto registration = try$(resolveRegistration(propertyName, options)); eatWhitespace(cursor); - if (auto defaulted = _parseDefaulted(registration, cursor)) - return defaulted.take(); + if (options.has(ALLOW_DEFAULTING)) { + if (auto defaulted = _parseDefaulted(registration, cursor)) + return Ok(defaulted.take()); + } auto maybeProp = registration->parse(cursor); - if (not maybeProp) - return _deferProperty(registration, content); + + if (options.has(DEFER_UNPARSABLE)) { + if (not maybeProp) + return Ok(_deferProperty(registration, content)); + } eatWhitespace(cursor); - if (not cursor.ended()) { - auto registration = makeRc(propertyName); - return makeRc(registration, content, Error::invalidData("un-consumed token in property value")); + + if (options.has(GENERATE_BOGUS)) { + if (not cursor.ended()) { + auto registration = makeRc(propertyName); + return Ok(makeRc(registration, content, Error::invalidData("un-consumed token in property value"))); + } } - return maybeProp.take(); + return maybeProp; } // MARK: Declaration Parsing ----------------------------------------------- - Res> parseDeclaration(Css::Sst const& sst) { + Res> parseDeclaration(Css::Sst const& sst, Flags options) { if (sst != Css::Sst::DECL) panic("expected declaration"); @@ -452,43 +476,49 @@ export struct PropertyRegistry { auto propertyName = Symbol::from(sst.token.data); Cursor content = sst.content; - auto prop = parseValue(propertyName, content); + auto prop = try$(parseValue(propertyName, content, options)); prop->important = sst.important; return Ok(prop); } - Rc parseDeclaration(Symbol propertyName, Str propertyValue) { + Res> parseDeclaration(Symbol propertyName, Str propertyValue, Flags options) { Css::Lexer lex{propertyValue}; auto [content, _] = Css::consumeDeclarationValue(lex); - return parseValue(propertyName, content); + return parseValue(propertyName, content, options); } - Vec> parseDeclarations(Css::Content const& sst) { + Vec> parseDeclarations(Css::Content const& sst, Flags options) { Vec> res; for (auto const& item : sst) { if (item != Css::Sst::DECL) continue; - auto prop = parseDeclaration(item); - + auto prop = parseDeclaration(item, options); if (not prop) continue; - res.pushBack(prop.take()); } return res; } - Vec> parseDeclarations(Css::Sst const& sst) { - return parseDeclarations(sst.content); + Vec> parseDeclarations(Css::Sst const& sst, Flags options) { + return parseDeclarations(sst.content, options); } - Vec> parseDeclarations(Str style) { + Vec> parseDeclarations(Str style, Flags options) { Css::Lexer lex{style}; auto sst = Css::consumeDeclarationList(lex, true); - return parseDeclarations(sst); + return parseDeclarations(sst, options); + } + + Opt> parsePresentationAttribute(Symbol attrName, Str value) const { + auto registration = try$(_presentationAttributes.tryGet(attrName)); + Css::Lexer lex{value}; + auto [content, _] = Css::consumeDeclarationValue(lex); + Cursor cursor = content; + return registration->parse(cursor).ok(); } }; diff --git a/src/vaev-engine/props/border.cpp b/src/vaev-engine/props/border.cpp index 6bbad3e5..c341a672 100644 --- a/src/vaev-engine/props/border.cpp +++ b/src/vaev-engine/props/border.cpp @@ -19,7 +19,7 @@ namespace Vaev::Style { export struct BorderTopColorProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_top-color"_sym; + return Properties::BORDER_TOP_COLOR; } Rc initial() const override { @@ -53,7 +53,7 @@ export struct BorderTopColorProperty : Property { export struct BorderRightColorProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_right-color"_sym; + return Properties::BORDER_RIGHT_COLOR; } Rc initial() const override { @@ -87,7 +87,7 @@ export struct BorderRightColorProperty : Property { export struct BorderBottomColorProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_bottom-color"_sym; + return Properties::BORDER_BOTTOM_COLOR; } Rc initial() const override { @@ -121,7 +121,7 @@ export struct BorderBottomColorProperty : Property { export struct BorderLeftColorProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_left-color"_sym; + return Properties::BORDER_LEFT_COLOR; } Rc initial() const override { @@ -213,7 +213,7 @@ export struct BorderColorProperty : Property { export struct BorderLeftStyleProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_left-style"_sym; + return Properties::BORDER_LEFT_STYLE; } Rc initial() const override { @@ -247,7 +247,7 @@ export struct BorderLeftStyleProperty : Property { export struct BorderTopStyleProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_top-style"_sym; + return Properties::BORDER_TOP_STYLE; } Rc initial() const override { @@ -281,7 +281,7 @@ export struct BorderTopStyleProperty : Property { export struct BorderRightStyleProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_right-style"_sym; + return Properties::BORDER_RIGHT_STYLE; } Rc initial() const override { @@ -315,7 +315,7 @@ export struct BorderRightStyleProperty : Property { export struct BorderBottomStyleProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_bottom-style"_sym; + return Properties::BORDER_BOTTOM_STYLE; } Rc initial() const override { @@ -401,7 +401,7 @@ export struct BorderStyleProperty : Property { export struct BorderTopWidthProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_top-width"_sym; + return Properties::BORDER_TOP_WIDTH; } Rc initial() const override { @@ -435,7 +435,7 @@ export struct BorderTopWidthProperty : Property { export struct BorderRightWidthProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_right-width"_sym; + return Properties::BORDER_RIGHT_WIDTH; } Rc initial() const override { @@ -469,7 +469,7 @@ export struct BorderRightWidthProperty : Property { export struct BorderBottomWidthProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_bottom-width"_sym; + return Properties::BORDER_BOTTOM_WIDTH; } Rc initial() const override { @@ -503,7 +503,7 @@ export struct BorderBottomWidthProperty : Property { export struct BorderLeftWidthProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_left-width"_sym; + return Properties::BORDER_LEFT_WIDTH; } Rc initial() const override { @@ -537,7 +537,7 @@ export struct BorderLeftWidthProperty : Property { export struct BorderRadiusTopRightProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_top-right-radius"_sym; + return Properties::BORDER_TOP_RIGHT_RADIUS; } Rc initial() const override { @@ -579,7 +579,7 @@ export struct BorderRadiusTopRightProperty : Property { export struct BorderRadiusTopLeftProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_top-left-radius"_sym; + return Properties::BORDER_TOP_LEFT_RADIUS; } Rc initial() const override { @@ -624,7 +624,7 @@ export struct BorderRadiusTopLeftProperty : Property { export struct BorderRadiusBottomRightProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_bottom-right-radius"_sym; + return Properties::BORDER_BOTTOM_RIGHT_RADIUS; } Rc initial() const override { @@ -666,7 +666,7 @@ export struct BorderRadiusBottomRightProperty : Property { export struct BorderRadiusBottomLeftProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "border_bottom-left-radius"_sym; + return Properties::BORDER_BOTTOM_LEFT_RADIUS; } Rc initial() const override { diff --git a/src/vaev-engine/props/defs/properties.inc b/src/vaev-engine/props/defs/properties.inc index 78310af5..5fa1dd44 100644 --- a/src/vaev-engine/props/defs/properties.inc +++ b/src/vaev-engine/props/defs/properties.inc @@ -1,10 +1,11 @@ PROPERTY(ACCENT_COLOR, "accent-color") +PROPERTY(ALIGNMENT_BASELINE, "alignment-baseline") PROPERTY(ALIGN_CONTENT, "align-content") PROPERTY(ALIGN_ITEMS, "align-items") PROPERTY(ALIGN_SELF, "align-self") -PROPERTY(ALIGNMENT_BASELINE, "alignment-baseline") PROPERTY(ALL, "all") PROPERTY(ANCHOR_NAME, "anchor-name") +PROPERTY(ANIMATION, "animation") PROPERTY(ANIMATION_COMPOSITION, "animation-composition") PROPERTY(ANIMATION_DELAY, "animation-delay") PROPERTY(ANIMATION_DIRECTION, "animation-direction") @@ -13,96 +14,96 @@ PROPERTY(ANIMATION_FILL_MODE, "animation-fill-mode") PROPERTY(ANIMATION_ITERATION_COUNT, "animation-iteration-count") PROPERTY(ANIMATION_NAME, "animation-name") PROPERTY(ANIMATION_PLAY_STATE, "animation-play-state") +PROPERTY(ANIMATION_RANGE, "animation-range") PROPERTY(ANIMATION_RANGE_END, "animation-range-end") PROPERTY(ANIMATION_RANGE_START, "animation-range-start") -PROPERTY(ANIMATION_RANGE, "animation-range") PROPERTY(ANIMATION_TIMELINE, "animation-timeline") PROPERTY(ANIMATION_TIMING_FUNCTION, "animation-timing-function") -PROPERTY(ANIMATION, "animation") PROPERTY(APPEARANCE, "appearance") PROPERTY(ASPECT_RATIO, "aspect-ratio") PROPERTY(BACKDROP_FILTER, "backdrop-filter") PROPERTY(BACKFACE_VISIBILITY, "backface-visibility") +PROPERTY(BACKGROUND, "background") PROPERTY(BACKGROUND_ATTACHMENT, "background-attachment") PROPERTY(BACKGROUND_BLEND_MODE, "background-blend-mode") PROPERTY(BACKGROUND_CLIP, "background-clip") PROPERTY(BACKGROUND_COLOR, "background-color") PROPERTY(BACKGROUND_IMAGE, "background-image") PROPERTY(BACKGROUND_ORIGIN, "background-origin") +PROPERTY(BACKGROUND_POSITION, "background-position") PROPERTY(BACKGROUND_POSITION_X, "background-position-x") PROPERTY(BACKGROUND_POSITION_Y, "background-position-y") -PROPERTY(BACKGROUND_POSITION, "background-position") PROPERTY(BACKGROUND_REPEAT, "background-repeat") PROPERTY(BACKGROUND_SIZE, "background-size") -PROPERTY(BACKGROUND, "background") +PROPERTY(BASELINE_SOURCE, "baseline-source") PROPERTY(BLOCK_SIZE, "block-size") +PROPERTY(BORDER, "border") +PROPERTY(BORDER_BLOCK, "border-block") PROPERTY(BORDER_BLOCK_COLOR, "border-block-color") +PROPERTY(BORDER_BLOCK_END, "border-block-end") PROPERTY(BORDER_BLOCK_END_COLOR, "border-block-end-color") PROPERTY(BORDER_BLOCK_END_STYLE, "border-block-end-style") PROPERTY(BORDER_BLOCK_END_WIDTH, "border-block-end-width") -PROPERTY(BORDER_BLOCK_END, "border-block-end") +PROPERTY(BORDER_BLOCK_START, "border-block-start") PROPERTY(BORDER_BLOCK_START_COLOR, "border-block-start-color") PROPERTY(BORDER_BLOCK_START_STYLE, "border-block-start-style") PROPERTY(BORDER_BLOCK_START_WIDTH, "border-block-start-width") -PROPERTY(BORDER_BLOCK_START, "border-block-start") PROPERTY(BORDER_BLOCK_STYLE, "border-block-style") PROPERTY(BORDER_BLOCK_WIDTH, "border-block-width") -PROPERTY(BORDER_BLOCK, "border-block") +PROPERTY(BORDER_BOTTOM, "border-bottom") PROPERTY(BORDER_BOTTOM_COLOR, "border-bottom-color") PROPERTY(BORDER_BOTTOM_LEFT_RADIUS, "border-bottom-left-radius") PROPERTY(BORDER_BOTTOM_RIGHT_RADIUS, "border-bottom-right-radius") PROPERTY(BORDER_BOTTOM_STYLE, "border-bottom-style") PROPERTY(BORDER_BOTTOM_WIDTH, "border-bottom-width") -PROPERTY(BORDER_BOTTOM, "border-bottom") PROPERTY(BORDER_COLLAPSE, "border-collapse") PROPERTY(BORDER_COLOR, "border-color") PROPERTY(BORDER_END_END_RADIUS, "border-end-end-radius") PROPERTY(BORDER_END_START_RADIUS, "border-end-start-radius") +PROPERTY(BORDER_IMAGE, "border-image") PROPERTY(BORDER_IMAGE_OUTSET, "border-image-outset") PROPERTY(BORDER_IMAGE_REPEAT, "border-image-repeat") PROPERTY(BORDER_IMAGE_SLICE, "border-image-slice") PROPERTY(BORDER_IMAGE_SOURCE, "border-image-source") PROPERTY(BORDER_IMAGE_WIDTH, "border-image-width") -PROPERTY(BORDER_IMAGE, "border-image") +PROPERTY(BORDER_INLINE, "border-inline") PROPERTY(BORDER_INLINE_COLOR, "border-inline-color") +PROPERTY(BORDER_INLINE_END, "border-inline-end") PROPERTY(BORDER_INLINE_END_COLOR, "border-inline-end-color") PROPERTY(BORDER_INLINE_END_STYLE, "border-inline-end-style") PROPERTY(BORDER_INLINE_END_WIDTH, "border-inline-end-width") -PROPERTY(BORDER_INLINE_END, "border-inline-end") +PROPERTY(BORDER_INLINE_START, "border-inline-start") PROPERTY(BORDER_INLINE_START_COLOR, "border-inline-start-color") PROPERTY(BORDER_INLINE_START_STYLE, "border-inline-start-style") PROPERTY(BORDER_INLINE_START_WIDTH, "border-inline-start-width") -PROPERTY(BORDER_INLINE_START, "border-inline-start") PROPERTY(BORDER_INLINE_STYLE, "border-inline-style") PROPERTY(BORDER_INLINE_WIDTH, "border-inline-width") -PROPERTY(BORDER_INLINE, "border-inline") +PROPERTY(BORDER_LEFT, "border-left") PROPERTY(BORDER_LEFT_COLOR, "border-left-color") PROPERTY(BORDER_LEFT_STYLE, "border-left-style") PROPERTY(BORDER_LEFT_WIDTH, "border-left-width") -PROPERTY(BORDER_LEFT, "border-left") PROPERTY(BORDER_RADIUS, "border-radius") +PROPERTY(BORDER_RIGHT, "border-right") PROPERTY(BORDER_RIGHT_COLOR, "border-right-color") PROPERTY(BORDER_RIGHT_STYLE, "border-right-style") PROPERTY(BORDER_RIGHT_WIDTH, "border-right-width") -PROPERTY(BORDER_RIGHT, "border-right") PROPERTY(BORDER_SPACING, "border-spacing") PROPERTY(BORDER_START_END_RADIUS, "border-start-end-radius") PROPERTY(BORDER_START_START_RADIUS, "border-start-start-radius") PROPERTY(BORDER_STYLE, "border-style") +PROPERTY(BORDER_TOP, "border-top") PROPERTY(BORDER_TOP_COLOR, "border-top-color") PROPERTY(BORDER_TOP_LEFT_RADIUS, "border-top-left-radius") PROPERTY(BORDER_TOP_RIGHT_RADIUS, "border-top-right-radius") PROPERTY(BORDER_TOP_STYLE, "border-top-style") PROPERTY(BORDER_TOP_WIDTH, "border-top-width") -PROPERTY(BORDER_TOP, "border-top") PROPERTY(BORDER_WIDTH, "border-width") -PROPERTY(BORDER, "border") PROPERTY(BOTTOM, "bottom") PROPERTY(BOX_ALIGN, "box-align") PROPERTY(BOX_DECORATION_BREAK, "box-decoration-break") PROPERTY(BOX_DIRECTION, "box-direction") -PROPERTY(BOX_FLEX_GROUP, "box-flex-group") PROPERTY(BOX_FLEX, "box-flex") +PROPERTY(BOX_FLEX_GROUP, "box-flex-group") PROPERTY(BOX_LINES, "box-lines") PROPERTY(BOX_ORDINAL_GROUP, "box-ordinal-group") PROPERTY(BOX_ORIENT, "box-orient") @@ -113,39 +114,39 @@ PROPERTY(BREAK_AFTER, "break-after") PROPERTY(BREAK_BEFORE, "break-before") PROPERTY(BREAK_INSIDE, "break-inside") PROPERTY(CAPTION_SIDE, "caption-side") +PROPERTY(CARET, "caret") PROPERTY(CARET_ANIMATION, "caret-animation") PROPERTY(CARET_COLOR, "caret-color") PROPERTY(CARET_SHAPE, "caret-shape") -PROPERTY(CARET, "caret") PROPERTY(CLEAR, "clear") +PROPERTY(CLIP, "clip") PROPERTY(CLIP_PATH, "clip-path") PROPERTY(CLIP_RULE, "clip-rule") -PROPERTY(CLIP, "clip") -PROPERTY(COLOR_INTERPOLATION_FILTERS, "color-interpolation-filters") +PROPERTY(COLOR, "color") PROPERTY(COLOR_INTERPOLATION, "color-interpolation") +PROPERTY(COLOR_INTERPOLATION_FILTERS, "color-interpolation-filters") PROPERTY(COLOR_SCHEME, "color-scheme") -PROPERTY(COLOR, "color") +PROPERTY(COLUMNS, "columns") PROPERTY(COLUMN_COUNT, "column-count") PROPERTY(COLUMN_FILL, "column-fill") PROPERTY(COLUMN_GAP, "column-gap") +PROPERTY(COLUMN_RULE, "column-rule") PROPERTY(COLUMN_RULE_COLOR, "column-rule-color") PROPERTY(COLUMN_RULE_STYLE, "column-rule-style") PROPERTY(COLUMN_RULE_WIDTH, "column-rule-width") -PROPERTY(COLUMN_RULE, "column-rule") PROPERTY(COLUMN_SPAN, "column-span") PROPERTY(COLUMN_WIDTH, "column-width") -PROPERTY(COLUMNS, "columns") +PROPERTY(CONTAIN, "contain") +PROPERTY(CONTAINER, "container") +PROPERTY(CONTAINER_NAME, "container-name") +PROPERTY(CONTAINER_TYPE, "container-type") PROPERTY(CONTAIN_INTRINSIC_BLOCK_SIZE, "contain-intrinsic-block-size") PROPERTY(CONTAIN_INTRINSIC_HEIGHT, "contain-intrinsic-height") PROPERTY(CONTAIN_INTRINSIC_INLINE_SIZE, "contain-intrinsic-inline-size") PROPERTY(CONTAIN_INTRINSIC_SIZE, "contain-intrinsic-size") PROPERTY(CONTAIN_INTRINSIC_WIDTH, "contain-intrinsic-width") -PROPERTY(CONTAIN, "contain") -PROPERTY(CONTAINER_NAME, "container-name") -PROPERTY(CONTAINER_TYPE, "container-type") -PROPERTY(CONTAINER, "container") -PROPERTY(CONTENT_VISIBILITY, "content-visibility") PROPERTY(CONTENT, "content") +PROPERTY(CONTENT_VISIBILITY, "content-visibility") PROPERTY(CORNER_BLOCK_END_SHAPE, "corner-block-end-shape") PROPERTY(CORNER_BLOCK_START_SHAPE, "corner-block-start-shape") PROPERTY(CORNER_BOTTOM_LEFT_SHAPE, "corner-bottom-left-shape") @@ -176,36 +177,37 @@ PROPERTY(DOMINANT_BASELINE, "dominant-baseline") PROPERTY(DYNAMIC_RANGE_LIMIT, "dynamic-range-limit") PROPERTY(EMPTY_CELLS, "empty-cells") PROPERTY(FIELD_SIZING, "field-sizing") +PROPERTY(FILL, "fill") PROPERTY(FILL_OPACITY, "fill-opacity") PROPERTY(FILL_RULE, "fill-rule") -PROPERTY(FILL, "fill") PROPERTY(FILTER, "filter") +PROPERTY(FLEX, "flex") PROPERTY(FLEX_BASIS, "flex-basis") PROPERTY(FLEX_DIRECTION, "flex-direction") PROPERTY(FLEX_FLOW, "flex-flow") PROPERTY(FLEX_GROW, "flex-grow") PROPERTY(FLEX_SHRINK, "flex-shrink") PROPERTY(FLEX_WRAP, "flex-wrap") -PROPERTY(FLEX, "flex") PROPERTY(FLOAT, "float") PROPERTY(FLOOD_COLOR, "flood-color") PROPERTY(FLOOD_OPACITY, "flood-opacity") +PROPERTY(FONT, "font") PROPERTY(FONT_FAMILY, "font-family") PROPERTY(FONT_FEATURE_SETTINGS, "font-feature-settings") PROPERTY(FONT_KERNING, "font-kerning") PROPERTY(FONT_LANGUAGE_OVERRIDE, "font-language-override") PROPERTY(FONT_OPTICAL_SIZING, "font-optical-sizing") PROPERTY(FONT_PALETTE, "font-palette") -PROPERTY(FONT_SIZE_ADJUST, "font-size-adjust") PROPERTY(FONT_SIZE, "font-size") +PROPERTY(FONT_SIZE_ADJUST, "font-size-adjust") PROPERTY(FONT_SMOOTH, "font-smooth") -PROPERTY(FONT_STRETCH, "font-stretch") PROPERTY(FONT_STYLE, "font-style") +PROPERTY(FONT_SYNTHESIS, "font-synthesis") PROPERTY(FONT_SYNTHESIS_POSITION, "font-synthesis-position") PROPERTY(FONT_SYNTHESIS_SMALL_CAPS, "font-synthesis-small-caps") PROPERTY(FONT_SYNTHESIS_STYLE, "font-synthesis-style") PROPERTY(FONT_SYNTHESIS_WEIGHT, "font-synthesis-weight") -PROPERTY(FONT_SYNTHESIS, "font-synthesis") +PROPERTY(FONT_VARIANT, "font-variant") PROPERTY(FONT_VARIANT_ALTERNATES, "font-variant-alternates") PROPERTY(FONT_VARIANT_CAPS, "font-variant-caps") PROPERTY(FONT_VARIANT_EAST_ASIAN, "font-variant-east-asian") @@ -213,27 +215,26 @@ PROPERTY(FONT_VARIANT_EMOJI, "font-variant-emoji") PROPERTY(FONT_VARIANT_LIGATURES, "font-variant-ligatures") PROPERTY(FONT_VARIANT_NUMERIC, "font-variant-numeric") PROPERTY(FONT_VARIANT_POSITION, "font-variant-position") -PROPERTY(FONT_VARIANT, "font-variant") PROPERTY(FONT_VARIATION_SETTINGS, "font-variation-settings") PROPERTY(FONT_WEIGHT, "font-weight") -PROPERTY(FONT, "font") +PROPERTY(FONT_WIDTH, "font-width") PROPERTY(FORCED_COLOR_ADJUST, "forced-color-adjust") PROPERTY(GAP, "gap") +PROPERTY(GRID, "grid") PROPERTY(GRID_AREA, "grid-area") PROPERTY(GRID_AUTO_COLUMNS, "grid-auto-columns") PROPERTY(GRID_AUTO_FLOW, "grid-auto-flow") PROPERTY(GRID_AUTO_ROWS, "grid-auto-rows") +PROPERTY(GRID_COLUMN, "grid-column") PROPERTY(GRID_COLUMN_END, "grid-column-end") PROPERTY(GRID_COLUMN_START, "grid-column-start") -PROPERTY(GRID_COLUMN, "grid-column") +PROPERTY(GRID_ROW, "grid-row") PROPERTY(GRID_ROW_END, "grid-row-end") PROPERTY(GRID_ROW_START, "grid-row-start") -PROPERTY(GRID_ROW, "grid-row") +PROPERTY(GRID_TEMPLATE, "grid-template") PROPERTY(GRID_TEMPLATE_AREAS, "grid-template-areas") PROPERTY(GRID_TEMPLATE_COLUMNS, "grid-template-columns") PROPERTY(GRID_TEMPLATE_ROWS, "grid-template-rows") -PROPERTY(GRID_TEMPLATE, "grid-template") -PROPERTY(GRID, "grid") PROPERTY(HANGING_PUNCTUATION, "hanging-punctuation") PROPERTY(HEIGHT, "height") PROPERTY(HYPHENATE_CHARACTER, "hyphenate-character") @@ -244,16 +245,13 @@ PROPERTY(IMAGE_RENDERING, "image-rendering") PROPERTY(IMAGE_RESOLUTION, "image-resolution") PROPERTY(INITIAL_LETTER, "initial-letter") PROPERTY(INLINE_SIZE, "inline-size") +PROPERTY(INSET, "inset") +PROPERTY(INSET_BLOCK, "inset-block") PROPERTY(INSET_BLOCK_END, "inset-block-end") PROPERTY(INSET_BLOCK_START, "inset-block-start") -PROPERTY(INSET_BLOCK, "inset-block") -PROPERTY(INSET_BLOCK, "inset-block") +PROPERTY(INSET_INLINE, "inset-inline") PROPERTY(INSET_INLINE_END, "inset-inline-end") PROPERTY(INSET_INLINE_START, "inset-inline-start") -PROPERTY(INSET_INLINE, "inset-inline") -PROPERTY(INSET_INLINE, "inset-inline") -PROPERTY(INSET, "inset") -PROPERTY(INSET, "inset") PROPERTY(INTERACTIVITY, "interactivity") PROPERTY(INTERPOLATE_SIZE, "interpolate-size") PROPERTY(ISOLATION, "isolation") @@ -265,36 +263,36 @@ PROPERTY(LETTER_SPACING, "letter-spacing") PROPERTY(LIGHTING_COLOR, "lighting-color") PROPERTY(LINE_BREAK, "line-break") PROPERTY(LINE_CLAMP, "line-clamp") -PROPERTY(LINE_HEIGHT_STEP, "line-height-step") PROPERTY(LINE_HEIGHT, "line-height") +PROPERTY(LINE_HEIGHT_STEP, "line-height-step") +PROPERTY(LIST_STYLE, "list-style") PROPERTY(LIST_STYLE_IMAGE, "list-style-image") PROPERTY(LIST_STYLE_POSITION, "list-style-position") PROPERTY(LIST_STYLE_TYPE, "list-style-type") -PROPERTY(LIST_STYLE, "list-style") -PROPERTY(LIST_STYLE, "list-style") +PROPERTY(MARGIN, "margin") +PROPERTY(MARGIN_BLOCK, "margin-block") PROPERTY(MARGIN_BLOCK_END, "margin-block-end") PROPERTY(MARGIN_BLOCK_START, "margin-block-start") -PROPERTY(MARGIN_BLOCK, "margin-block") PROPERTY(MARGIN_BOTTOM, "margin-bottom") +PROPERTY(MARGIN_INLINE, "margin-inline") PROPERTY(MARGIN_INLINE_END, "margin-inline-end") PROPERTY(MARGIN_INLINE_START, "margin-inline-start") -PROPERTY(MARGIN_INLINE, "margin-inline") PROPERTY(MARGIN_LEFT, "margin-left") PROPERTY(MARGIN_RIGHT, "margin-right") PROPERTY(MARGIN_TOP, "margin-top") PROPERTY(MARGIN_TRIM, "margin-trim") -PROPERTY(MARGIN, "margin") +PROPERTY(MARKER, "marker") PROPERTY(MARKER_END, "marker-end") PROPERTY(MARKER_MID, "marker-mid") PROPERTY(MARKER_START, "marker-start") -PROPERTY(MARKER, "marker") +PROPERTY(MASK, "mask") +PROPERTY(MASK_BORDER, "mask-border") PROPERTY(MASK_BORDER_MODE, "mask-border-mode") PROPERTY(MASK_BORDER_OUTSET, "mask-border-outset") PROPERTY(MASK_BORDER_REPEAT, "mask-border-repeat") PROPERTY(MASK_BORDER_SLICE, "mask-border-slice") PROPERTY(MASK_BORDER_SOURCE, "mask-border-source") PROPERTY(MASK_BORDER_WIDTH, "mask-border-width") -PROPERTY(MASK_BORDER, "mask-border") PROPERTY(MASK_CLIP, "mask-clip") PROPERTY(MASK_COMPOSITE, "mask-composite") PROPERTY(MASK_IMAGE, "mask-image") @@ -304,7 +302,6 @@ PROPERTY(MASK_POSITION, "mask-position") PROPERTY(MASK_REPEAT, "mask-repeat") PROPERTY(MASK_SIZE, "mask-size") PROPERTY(MASK_TYPE, "mask-type") -PROPERTY(MASK, "mask") PROPERTY(MATH_DEPTH, "math-depth") PROPERTY(MATH_SHIFT, "math-shift") PROPERTY(MATH_STYLE, "math-style") @@ -320,20 +317,21 @@ PROPERTY(MIX_BLEND_MODE, "mix-blend-mode") PROPERTY(OBJECT_FIT, "object-fit") PROPERTY(OBJECT_POSITION, "object-position") PROPERTY(OBJECT_VIEW_BOX, "object-view-box") +PROPERTY(OFFSET, "offset") PROPERTY(OFFSET_ANCHOR, "offset-anchor") PROPERTY(OFFSET_DISTANCE, "offset-distance") PROPERTY(OFFSET_PATH, "offset-path") PROPERTY(OFFSET_POSITION, "offset-position") PROPERTY(OFFSET_ROTATE, "offset-rotate") -PROPERTY(OFFSET, "offset") PROPERTY(OPACITY, "opacity") PROPERTY(ORDER, "order") PROPERTY(ORPHANS, "orphans") +PROPERTY(OUTLINE, "outline") PROPERTY(OUTLINE_COLOR, "outline-color") PROPERTY(OUTLINE_OFFSET, "outline-offset") PROPERTY(OUTLINE_STYLE, "outline-style") PROPERTY(OUTLINE_WIDTH, "outline-width") -PROPERTY(OUTLINE, "outline") +PROPERTY(OVERFLOW, "overflow") PROPERTY(OVERFLOW_ANCHOR, "overflow-anchor") PROPERTY(OVERFLOW_BLOCK, "overflow-block") PROPERTY(OVERFLOW_CLIP_MARGIN, "overflow-clip-margin") @@ -341,42 +339,41 @@ PROPERTY(OVERFLOW_INLINE, "overflow-inline") PROPERTY(OVERFLOW_WRAP, "overflow-wrap") PROPERTY(OVERFLOW_X, "overflow-x") PROPERTY(OVERFLOW_Y, "overflow-y") -PROPERTY(OVERFLOW, "overflow") PROPERTY(OVERLAY, "overlay") +PROPERTY(OVERSCROLL_BEHAVIOR, "overscroll-behavior") PROPERTY(OVERSCROLL_BEHAVIOR_BLOCK, "overscroll-behavior-block") PROPERTY(OVERSCROLL_BEHAVIOR_INLINE, "overscroll-behavior-inline") PROPERTY(OVERSCROLL_BEHAVIOR_X, "overscroll-behavior-x") PROPERTY(OVERSCROLL_BEHAVIOR_Y, "overscroll-behavior-y") -PROPERTY(OVERSCROLL_BEHAVIOR, "overscroll-behavior") +PROPERTY(PADDING, "padding") +PROPERTY(PADDING_BLOCK, "padding-block") PROPERTY(PADDING_BLOCK_END, "padding-block-end") PROPERTY(PADDING_BLOCK_START, "padding-block-start") -PROPERTY(PADDING_BLOCK, "padding-block") PROPERTY(PADDING_BOTTOM, "padding-bottom") +PROPERTY(PADDING_INLINE, "padding-inline") PROPERTY(PADDING_INLINE_END, "padding-inline-end") PROPERTY(PADDING_INLINE_START, "padding-inline-start") -PROPERTY(PADDING_INLINE, "padding-inline") PROPERTY(PADDING_LEFT, "padding-left") PROPERTY(PADDING_RIGHT, "padding-right") PROPERTY(PADDING_TOP, "padding-top") -PROPERTY(PADDING, "padding") +PROPERTY(PAGE, "page") PROPERTY(PAGE_BREAK_AFTER, "page-break-after") PROPERTY(PAGE_BREAK_BEFORE, "page-break-before") PROPERTY(PAGE_BREAK_INSIDE, "page-break-inside") -PROPERTY(PAGE, "page") PROPERTY(PAINT_ORDER, "paint-order") -PROPERTY(PERSPECTIVE_ORIGIN, "perspective-origin") PROPERTY(PERSPECTIVE, "perspective") +PROPERTY(PERSPECTIVE_ORIGIN, "perspective-origin") PROPERTY(PLACE_CONTENT, "place-content") PROPERTY(PLACE_ITEMS, "place-items") PROPERTY(PLACE_SELF, "place-self") PROPERTY(POINTER_EVENTS, "pointer-events") +PROPERTY(POSITION, "position") PROPERTY(POSITION_ANCHOR, "position-anchor") PROPERTY(POSITION_AREA, "position-area") +PROPERTY(POSITION_TRY, "position-try") PROPERTY(POSITION_TRY_FALLBACKS, "position-try-fallbacks") PROPERTY(POSITION_TRY_ORDER, "position-try-order") -PROPERTY(POSITION_TRY, "position-try") PROPERTY(POSITION_VISIBILITY, "position-visibility") -PROPERTY(POSITION, "position") PROPERTY(PRINT_COLOR_ADJUST, "print-color-adjust") PROPERTY(QUOTES, "quotes") PROPERTY(R, "r") @@ -392,40 +389,40 @@ PROPERTY(RUBY_POSITION, "ruby-position") PROPERTY(RX, "rx") PROPERTY(RY, "ry") PROPERTY(SCALE, "scale") +PROPERTY(SCROLLBAR_COLOR, "scrollbar-color") +PROPERTY(SCROLLBAR_GUTTER, "scrollbar-gutter") +PROPERTY(SCROLLBAR_WIDTH, "scrollbar-width") PROPERTY(SCROLL_BEHAVIOR, "scroll-behavior") +PROPERTY(SCROLL_MARGIN, "scroll-margin") +PROPERTY(SCROLL_MARGIN_BLOCK, "scroll-margin-block") PROPERTY(SCROLL_MARGIN_BLOCK_END, "scroll-margin-block-end") PROPERTY(SCROLL_MARGIN_BLOCK_START, "scroll-margin-block-start") -PROPERTY(SCROLL_MARGIN_BLOCK, "scroll-margin-block") PROPERTY(SCROLL_MARGIN_BOTTOM, "scroll-margin-bottom") +PROPERTY(SCROLL_MARGIN_INLINE, "scroll-margin-inline") PROPERTY(SCROLL_MARGIN_INLINE_END, "scroll-margin-inline-end") PROPERTY(SCROLL_MARGIN_INLINE_START, "scroll-margin-inline-start") -PROPERTY(SCROLL_MARGIN_INLINE, "scroll-margin-inline") PROPERTY(SCROLL_MARGIN_LEFT, "scroll-margin-left") PROPERTY(SCROLL_MARGIN_RIGHT, "scroll-margin-right") PROPERTY(SCROLL_MARGIN_TOP, "scroll-margin-top") -PROPERTY(SCROLL_MARGIN, "scroll-margin") PROPERTY(SCROLL_MARKER_GROUP, "scroll-marker-group") +PROPERTY(SCROLL_PADDING, "scroll-padding") +PROPERTY(SCROLL_PADDING_BLOCK, "scroll-padding-block") PROPERTY(SCROLL_PADDING_BLOCK_END, "scroll-padding-block-end") PROPERTY(SCROLL_PADDING_BLOCK_START, "scroll-padding-block-start") -PROPERTY(SCROLL_PADDING_BLOCK, "scroll-padding-block") PROPERTY(SCROLL_PADDING_BOTTOM, "scroll-padding-bottom") +PROPERTY(SCROLL_PADDING_INLINE, "scroll-padding-inline") PROPERTY(SCROLL_PADDING_INLINE_END, "scroll-padding-inline-end") PROPERTY(SCROLL_PADDING_INLINE_START, "scroll-padding-inline-start") -PROPERTY(SCROLL_PADDING_INLINE, "scroll-padding-inline") PROPERTY(SCROLL_PADDING_LEFT, "scroll-padding-left") PROPERTY(SCROLL_PADDING_RIGHT, "scroll-padding-right") PROPERTY(SCROLL_PADDING_TOP, "scroll-padding-top") -PROPERTY(SCROLL_PADDING, "scroll-padding") PROPERTY(SCROLL_SNAP_ALIGN, "scroll-snap-align") PROPERTY(SCROLL_SNAP_STOP, "scroll-snap-stop") PROPERTY(SCROLL_SNAP_TYPE, "scroll-snap-type") PROPERTY(SCROLL_TARGET_GROUP, "scroll-target-group") +PROPERTY(SCROLL_TIMELINE, "scroll-timeline") PROPERTY(SCROLL_TIMELINE_AXIS, "scroll-timeline-axis") PROPERTY(SCROLL_TIMELINE_NAME, "scroll-timeline-name") -PROPERTY(SCROLL_TIMELINE, "scroll-timeline") -PROPERTY(SCROLLBAR_COLOR, "scrollbar-color") -PROPERTY(SCROLLBAR_GUTTER, "scrollbar-gutter") -PROPERTY(SCROLLBAR_WIDTH, "scrollbar-width") PROPERTY(SHAPE_IMAGE_THRESHOLD, "shape-image-threshold") PROPERTY(SHAPE_MARGIN, "shape-margin") PROPERTY(SHAPE_OUTSIDE, "shape-outside") @@ -433,6 +430,7 @@ PROPERTY(SHAPE_RENDERING, "shape-rendering") PROPERTY(SPEAK_AS, "speak-as") PROPERTY(STOP_COLOR, "stop-color") PROPERTY(STOP_OPACITY, "stop-opacity") +PROPERTY(STROKE, "stroke") PROPERTY(STROKE_DASHARRAY, "stroke-dasharray") PROPERTY(STROKE_DASHOFFSET, "stroke-dashoffset") PROPERTY(STROKE_LINECAP, "stroke-linecap") @@ -440,29 +438,28 @@ PROPERTY(STROKE_LINEJOIN, "stroke-linejoin") PROPERTY(STROKE_MITERLIMIT, "stroke-miterlimit") PROPERTY(STROKE_OPACITY, "stroke-opacity") PROPERTY(STROKE_WIDTH, "stroke-width") -PROPERTY(STROKE, "stroke") -PROPERTY(TAB_SIZE, "tab-size") PROPERTY(TABLE_LAYOUT, "table-layout") -PROPERTY(TEXT_ALIGN_LAST, "text-align-last") +PROPERTY(TAB_SIZE, "tab-size") PROPERTY(TEXT_ALIGN, "text-align") +PROPERTY(TEXT_ALIGN_LAST, "text-align-last") PROPERTY(TEXT_ANCHOR, "text-anchor") PROPERTY(TEXT_AUTOSPACE, "text-autospace") +PROPERTY(TEXT_BOX, "text-box") PROPERTY(TEXT_BOX_EDGE, "text-box-edge") PROPERTY(TEXT_BOX_TRIM, "text-box-trim") -PROPERTY(TEXT_BOX, "text-box") PROPERTY(TEXT_COMBINE_UPRIGHT, "text-combine-upright") +PROPERTY(TEXT_DECORATION, "text-decoration") PROPERTY(TEXT_DECORATION_COLOR, "text-decoration-color") PROPERTY(TEXT_DECORATION_INSET, "text-decoration-inset") PROPERTY(TEXT_DECORATION_LINE, "text-decoration-line") -PROPERTY(TEXT_DECORATION_SKIP_INK, "text-decoration-skip-ink") PROPERTY(TEXT_DECORATION_SKIP, "text-decoration-skip") +PROPERTY(TEXT_DECORATION_SKIP_INK, "text-decoration-skip-ink") PROPERTY(TEXT_DECORATION_STYLE, "text-decoration-style") PROPERTY(TEXT_DECORATION_THICKNESS, "text-decoration-thickness") -PROPERTY(TEXT_DECORATION, "text-decoration") +PROPERTY(TEXT_EMPHASIS, "text-emphasis") PROPERTY(TEXT_EMPHASIS_COLOR, "text-emphasis-color") PROPERTY(TEXT_EMPHASIS_POSITION, "text-emphasis-position") PROPERTY(TEXT_EMPHASIS_STYLE, "text-emphasis-style") -PROPERTY(TEXT_EMPHASIS, "text-emphasis") PROPERTY(TEXT_INDENT, "text-indent") PROPERTY(TEXT_JUSTIFY, "text-justify") PROPERTY(TEXT_ORIENTATION, "text-orientation") @@ -474,37 +471,38 @@ PROPERTY(TEXT_SPACING_TRIM, "text-spacing-trim") PROPERTY(TEXT_TRANSFORM, "text-transform") PROPERTY(TEXT_UNDERLINE_OFFSET, "text-underline-offset") PROPERTY(TEXT_UNDERLINE_POSITION, "text-underline-position") +PROPERTY(TEXT_WRAP, "text-wrap") PROPERTY(TEXT_WRAP_MODE, "text-wrap-mode") PROPERTY(TEXT_WRAP_STYLE, "text-wrap-style") -PROPERTY(TEXT_WRAP, "text-wrap") PROPERTY(TIMELINE_SCOPE, "timeline-scope") PROPERTY(TOP, "top") PROPERTY(TOUCH_ACTION, "touch-action") +PROPERTY(TRANSFORM, "transform") PROPERTY(TRANSFORM_BOX, "transform-box") PROPERTY(TRANSFORM_ORIGIN, "transform-origin") PROPERTY(TRANSFORM_STYLE, "transform-style") -PROPERTY(TRANSFORM, "transform") +PROPERTY(TRANSITION, "transition") PROPERTY(TRANSITION_BEHAVIOR, "transition-behavior") PROPERTY(TRANSITION_DELAY, "transition-delay") PROPERTY(TRANSITION_DURATION, "transition-duration") PROPERTY(TRANSITION_PROPERTY, "transition-property") PROPERTY(TRANSITION_TIMING_FUNCTION, "transition-timing-function") -PROPERTY(TRANSITION, "transition") PROPERTY(TRANSLATE, "translate") PROPERTY(UNICODE_BIDI, "unicode-bidi") PROPERTY(USER_MODIFY, "user-modify") PROPERTY(USER_SELECT, "user-select") PROPERTY(VECTOR_EFFECT, "vector-effect") PROPERTY(VERTICAL_ALIGN, "vertical-align") +PROPERTY(VIEW_TIMELINE, "view-timeline") PROPERTY(VIEW_TIMELINE_AXIS, "view-timeline-axis") PROPERTY(VIEW_TIMELINE_INSET, "view-timeline-inset") PROPERTY(VIEW_TIMELINE_NAME, "view-timeline-name") -PROPERTY(VIEW_TIMELINE, "view-timeline") PROPERTY(VIEW_TRANSITION_CLASS, "view-transition-class") PROPERTY(VIEW_TRANSITION_NAME, "view-transition-name") +PROPERTY(VIEWBOX, "viewbox") PROPERTY(VISIBILITY, "visibility") -PROPERTY(WHITE_SPACE_COLLAPSE, "white-space-collapse") PROPERTY(WHITE_SPACE, "white-space") +PROPERTY(WHITE_SPACE_COLLAPSE, "white-space-collapse") PROPERTY(WIDOWS, "widows") PROPERTY(WIDTH, "width") PROPERTY(WILL_CHANGE, "will-change") @@ -513,5 +511,5 @@ PROPERTY(WORD_SPACING, "word-spacing") PROPERTY(WRITING_MODE, "writing-mode") PROPERTY(X, "x") PROPERTY(Y, "y") -PROPERTY(Z_INDEX, "z-index") PROPERTY(ZOOM, "zoom") +PROPERTY(Z_INDEX, "z-index") diff --git a/src/vaev-engine/props/flex.cpp b/src/vaev-engine/props/flex.cpp index 12d3811c..950b9c67 100644 --- a/src/vaev-engine/props/flex.cpp +++ b/src/vaev-engine/props/flex.cpp @@ -325,9 +325,9 @@ export struct FlexProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("flex-basis"s).unwrap(), _value.flexBasis), - makeRc(registry.resolveRegistration("flex-grow"s).unwrap(), _value.flexGrow), - makeRc(registry.resolveRegistration("flex-shrink"s).unwrap(), _value.flexShrink), + makeRc(registry.resolveRegistration(Properties::FLEX_BASIS, {}).unwrap(), _value.flexBasis), + makeRc(registry.resolveRegistration(Properties::FLEX_GROW, {}).unwrap(), _value.flexGrow), + makeRc(registry.resolveRegistration(Properties::FLEX_SHRINK, {}).unwrap(), _value.flexShrink), }; } diff --git a/src/vaev-engine/props/fonts.cpp b/src/vaev-engine/props/fonts.cpp index 53ef53d4..b33a4927 100644 --- a/src/vaev-engine/props/fonts.cpp +++ b/src/vaev-engine/props/fonts.cpp @@ -287,12 +287,12 @@ export struct FontProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { Vec> result; - result.pushBack(makeRc(registry.resolveRegistration("font-style"s).unwrap(), _value.style)); - result.pushBack(makeRc(registry.resolveRegistration("font-width"s).unwrap(), _value.width)); - result.pushBack(makeRc(registry.resolveRegistration("font-size"s).unwrap(), _value.size)); - result.pushBack(makeRc(registry.resolveRegistration("font-family"s).unwrap(), _value.families)); + result.pushBack(makeRc(registry.resolveRegistration(Properties::FONT_STYLE, {}).unwrap(), _value.style)); + result.pushBack(makeRc(registry.resolveRegistration(Properties::FONT_WIDTH, {}).unwrap(), _value.width)); + result.pushBack(makeRc(registry.resolveRegistration(Properties::FONT_SIZE, {}).unwrap(), _value.size)); + result.pushBack(makeRc(registry.resolveRegistration(Properties::FONT_FAMILY, {}).unwrap(), _value.families)); if (_unresolvedWeight) - result.pushBack(makeRc(registry.resolveRegistration("font-weight"s).unwrap(), *_unresolvedWeight)); + result.pushBack(makeRc(registry.resolveRegistration(Properties::FONT_WEIGHT, {}).unwrap(), *_unresolvedWeight)); return result; } diff --git a/src/vaev-engine/props/margin.cpp b/src/vaev-engine/props/margin.cpp index e69512e1..17a42540 100644 --- a/src/vaev-engine/props/margin.cpp +++ b/src/vaev-engine/props/margin.cpp @@ -179,10 +179,10 @@ export struct MarginProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("margin-top"s).unwrap(), _value.top), - makeRc(registry.resolveRegistration("margin-bottom"s).unwrap(), _value.bottom), - makeRc(registry.resolveRegistration("margin-left"s).unwrap(), _value.start), - makeRc(registry.resolveRegistration("margin-right"s).unwrap(), _value.end), + makeRc(registry.resolveRegistration(Properties::MARGIN_TOP, {}).unwrap(), _value.top), + makeRc(registry.resolveRegistration(Properties::MARGIN_BOTTOM, {}).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration(Properties::MARGIN_LEFT, {}).unwrap(), _value.start), + makeRc(registry.resolveRegistration(Properties::MARGIN_RIGHT, {}).unwrap(), _value.end), }; } @@ -196,7 +196,7 @@ export struct MarginProperty : Property { export struct MarginInlineStartProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "margin_inline-start"_sym; + return Properties::MARGIN_INLINE_START; } Rc initial() const override { @@ -230,7 +230,7 @@ export struct MarginInlineStartProperty : Property { export struct MarginInlineEndProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "margin_inline-end"_sym; + return Properties::MARGIN_INLINE_END; } Rc initial() const override { @@ -299,7 +299,7 @@ export struct MarginInlineProperty : Property { export struct MarginBlockStartProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "margin_block-start"_sym; + return Properties::MARGIN_BLOCK_START; } Rc initial() const override { @@ -333,7 +333,7 @@ export struct MarginBlockStartProperty : Property { export struct MarginBlockEndProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "margin_block-end"_sym; + return Properties::MARGIN_BLOCK_END; } Rc initial() const override { diff --git a/src/vaev-engine/props/outline.cpp b/src/vaev-engine/props/outline.cpp index 5cde7b2d..4c369cdf 100644 --- a/src/vaev-engine/props/outline.cpp +++ b/src/vaev-engine/props/outline.cpp @@ -214,9 +214,9 @@ export struct OutlineProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("outline-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("outline-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("outline-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::OUTLINE_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::OUTLINE_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::OUTLINE_COLOR, {}).unwrap(), _value.color), }; } diff --git a/src/vaev-engine/props/overflow.cpp b/src/vaev-engine/props/overflow.cpp index a999d77b..fc9cb9ff 100644 --- a/src/vaev-engine/props/overflow.cpp +++ b/src/vaev-engine/props/overflow.cpp @@ -196,8 +196,8 @@ export struct OverflowProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("overflow-x"s).unwrap(), _value.v0), - makeRc(registry.resolveRegistration("overflow-y"s).unwrap(), _value.v1), + makeRc(registry.resolveRegistration(Properties::OVERFLOW_X, {}).unwrap(), _value.v0), + makeRc(registry.resolveRegistration(Properties::OVERFLOW_Y, {}).unwrap(), _value.v1), }; } diff --git a/src/vaev-engine/props/padding.cpp b/src/vaev-engine/props/padding.cpp index 4ff610c9..3a17d4b7 100644 --- a/src/vaev-engine/props/padding.cpp +++ b/src/vaev-engine/props/padding.cpp @@ -152,7 +152,7 @@ export struct PaddingLeftProperty : Property { export struct PaddingInlineStartProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "padding_inline-start"_sym; + return Properties::PADDING_INLINE_START; } Rc initial() const override { @@ -185,7 +185,7 @@ export struct PaddingInlineStartProperty : Property { export struct PaddingInlineEndProperty : Property { struct Registration : Property::Registration { Symbol name() const override { - return "padding_inline-end"_sym; + return Properties::PADDING_INLINE_END; } Rc initial() const override { @@ -245,10 +245,10 @@ export struct PaddingProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("padding-top"s).unwrap(), _value.top), - makeRc(registry.resolveRegistration("padding-right"s).unwrap(), _value.end), - makeRc(registry.resolveRegistration("padding-bottom"s).unwrap(), _value.bottom), - makeRc(registry.resolveRegistration("padding-left"s).unwrap(), _value.start), + makeRc(registry.resolveRegistration(Properties::PADDING_TOP, {}).unwrap(), _value.top), + makeRc(registry.resolveRegistration(Properties::PADDING_RIGHT, {}).unwrap(), _value.end), + makeRc(registry.resolveRegistration(Properties::PADDING_BOTTOM, {}).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration(Properties::PADDING_LEFT, {}).unwrap(), _value.start), }; } diff --git a/src/vaev-engine/style/computer.cpp b/src/vaev-engine/style/computer.cpp index 1c9b14b6..3ecab166 100644 --- a/src/vaev-engine/style/computer.cpp +++ b/src/vaev-engine/style/computer.cpp @@ -109,50 +109,42 @@ export struct Computer { Vec> res; // https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-fgcolor if (auto fgcolor = el->getAttribute(Html::FGCOLOR_ATTR)) { - if (auto p = _propertyRegistry.parseDeclaration("color"_sym, fgcolor.unwrap())) - res.pushBack(p.take()); + if (auto property = _propertyRegistry.parseDeclaration( + Properties::COLOR, fgcolor.unwrap(), {} + )) + res.pushBack(property.take()); } // https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-bgcolor if (auto bgcolor = el->getAttribute(Html::BGCOLOR_ATTR)) { - if (auto p = _propertyRegistry.parseDeclaration("background-color"_sym, bgcolor.unwrap())) - res.pushBack(p.take()); + if (auto property = _propertyRegistry.parseDeclaration( + Properties::BACKGROUND_COLOR, bgcolor.unwrap(), {} + )) + res.pushBack(property.take()); } // https://html.spec.whatwg.org/multipage/images.html#sizes-attributes if (auto width = el->getAttribute(Html::WIDTH_ATTR)) { - auto value = parseValue(width.unwrap()); - if (value) - res.pushBack( - makeRc( - _propertyRegistry.resolveRegistration("width").unwrap(), - value.take() - ) - ); + if (auto property = _propertyRegistry.parseDeclaration( + Properties::WIDTH, width.unwrap(), {} + )) + res.pushBack(property.take()); } // https://html.spec.whatwg.org/multipage/images.html#sizes-attributes if (auto height = el->getAttribute(Html::HEIGHT_ATTR)) { - auto value = parseValue(height.unwrap()); - if (value) - res.pushBack( - makeRc( - _propertyRegistry.resolveRegistration("height").unwrap(), - value.take() - ) - ); + if (auto property = _propertyRegistry.parseDeclaration( + Properties::HEIGHT, height.unwrap(), {} + )) + res.pushBack(property.take()); } // https://html.spec.whatwg.org/multipage/input.html#the-size-attribute if (auto size = el->getAttribute(Html::SIZE_ATTR)) { - auto value = parseValue(size.unwrap()); - if (value) - res.pushBack( - makeRc( - _propertyRegistry.resolveRegistration("width").unwrap(), - CalcValue>{Length{static_cast(value.take()), Length::CH}} - ) - ); + if (auto property = _propertyRegistry.parseDeclaration( + Properties::WIDTH, Io::format("{}ch", size), {} + )) + res.pushBack(property.take()); } return res; @@ -234,10 +226,10 @@ export struct Computer { return; if (not svgEl->hasAttribute(Svg::WIDTH_ATTR)) - styleProps.pushBack(_propertyRegistry.parseDeclaration("width"_sym, "300px").unwrap()); + styleProps.pushBack(_propertyRegistry.parseDeclaration(Properties::WIDTH, "300px", {})); if (not svgEl->hasAttribute(Svg::HEIGHT_ATTR)) - styleProps.pushBack(_propertyRegistry.parseDeclaration("height"_sym, "150px").unwrap()); + styleProps.pushBack(_propertyRegistry.parseDeclaration(Properties::HEIGHT, "150px", {})); } } @@ -248,7 +240,8 @@ export struct Computer { Vec> styleProps; for (auto [attr, attrValue] : el->attributes.iterUnordered()) { - parseSVGPresentationAttribute(attr.name, attrValue->value, styleProps); + if (auto property = _propertyRegistry.parsePresentationAttribute(attr.name, attrValue->value)) + styleProps.pushBack(property.take()); } if (el->qualifiedName == Svg::SVG_TAG) @@ -270,12 +263,13 @@ export struct Computer { matchingRules.pushBack({&presentationHints, PRESENTATION_HINT_SPEC}); // Get the style attribute if any - auto styleAttr = el->style(); - StyleRule styleRule{ - .props = parseStyleDeclaration(styleAttr ? *styleAttr : ""), - .origin = Origin::INLINE, - }; - matchingRules.pushBack({&styleRule, INLINE_SPEC}); + if (auto styleAttr = el->style()) { + StyleRule styleRule{ + .props = _propertyRegistry.parseDeclarations(styleAttr ? *styleAttr : ""), + .origin = Origin::INLINE, + }; + matchingRules.pushBack({&styleRule, INLINE_SPEC}); + } // https://svgwg.org/svg2-draft/styling.html#PresentationAttributes // Presentation attributes contribute to the author level of the cascade, followed by all other author-level From ceea45ac429ee55fe049eaa02c24d4287b848c9c Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Thu, 4 Dec 2025 12:25:22 +0100 Subject: [PATCH 4/5] wip --- src/vaev-engine/props/base.cpp | 2 + src/vaev-engine/props/border.cpp | 72 +++++++++++++++--------------- src/vaev-engine/props/flex.cpp | 6 +-- src/vaev-engine/style/computer.cpp | 13 ++++-- src/vaev-engine/style/mod.cpp | 1 - src/vaev-engine/style/page.cpp | 2 +- src/vaev-engine/style/rules.cpp | 4 +- 7 files changed, 54 insertions(+), 46 deletions(-) diff --git a/src/vaev-engine/props/base.cpp b/src/vaev-engine/props/base.cpp index acc235ae..0a5f4626 100644 --- a/src/vaev-engine/props/base.cpp +++ b/src/vaev-engine/props/base.cpp @@ -366,6 +366,8 @@ export struct PropertyRegistry { GENERATE_CUSTOM_PROPERTY = 1 << 1, DEFER_UNPARSABLE = 1 << 2, ALLOW_DEFAULTING = 1 << 3, + + TOP_LEVEL = GENERATE_BOGUS | GENERATE_CUSTOM_PROPERTY | DEFER_UNPARSABLE | ALLOW_DEFAULTING, }; using enum Options; diff --git a/src/vaev-engine/props/border.cpp b/src/vaev-engine/props/border.cpp index c341a672..5de80976 100644 --- a/src/vaev-engine/props/border.cpp +++ b/src/vaev-engine/props/border.cpp @@ -189,10 +189,10 @@ export struct BorderColorProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.top), - makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.end), - makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.bottom), - makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.start), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_COLOR, {}).unwrap(), _value.top), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_COLOR, {}).unwrap(), _value.end), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_COLOR, {}).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_COLOR, {}).unwrap(), _value.start), }; } @@ -385,10 +385,10 @@ export struct BorderStyleProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.top), - makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.end), - makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.bottom), - makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.start), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_STYLE, {}).unwrap(), _value.top), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_STYLE, {}).unwrap(), _value.end), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_STYLE, {}).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_STYLE, {}).unwrap(), _value.start), }; } @@ -794,9 +794,9 @@ export struct BorderTopProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_COLOR, {}).unwrap(), _value.color), }; } @@ -858,9 +858,9 @@ export struct BorderRightProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_COLOR, {}).unwrap(), _value.color), }; } @@ -922,9 +922,9 @@ export struct BorderBottomProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_COLOR, {}).unwrap(), _value.color), }; } @@ -986,9 +986,9 @@ export struct BorderLeftProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_COLOR, {}).unwrap(), _value.color), }; } @@ -1028,21 +1028,21 @@ export struct BorderProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-top-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-top-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_COLOR, {}).unwrap(), _value.color), - makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-right-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-right-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_COLOR, {}).unwrap(), _value.color), - makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-bottom-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-bottom-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_COLOR, {}).unwrap(), _value.color), - makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.width), - makeRc(registry.resolveRegistration("border-left-style"s).unwrap(), _value.style), - makeRc(registry.resolveRegistration("border-left-color"s).unwrap(), _value.color), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_WIDTH, {}).unwrap(), _value.width), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_STYLE, {}).unwrap(), _value.style), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_COLOR, {}).unwrap(), _value.color), }; } @@ -1086,10 +1086,10 @@ export struct BorderWidthProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("border-top-width"s).unwrap(), _value.top), - makeRc(registry.resolveRegistration("border-right-width"s).unwrap(), _value.end), - makeRc(registry.resolveRegistration("border-bottom-width"s).unwrap(), _value.bottom), - makeRc(registry.resolveRegistration("border-left-width"s).unwrap(), _value.start), + makeRc(registry.resolveRegistration(Properties::BORDER_TOP_WIDTH, {}).unwrap(), _value.top), + makeRc(registry.resolveRegistration(Properties::BORDER_RIGHT_WIDTH, {}).unwrap(), _value.end), + makeRc(registry.resolveRegistration(Properties::BORDER_BOTTOM_WIDTH, {}).unwrap(), _value.bottom), + makeRc(registry.resolveRegistration(Properties::BORDER_LEFT_WIDTH, {}).unwrap(), _value.start), }; } diff --git a/src/vaev-engine/props/flex.cpp b/src/vaev-engine/props/flex.cpp index 950b9c67..ba356318 100644 --- a/src/vaev-engine/props/flex.cpp +++ b/src/vaev-engine/props/flex.cpp @@ -239,8 +239,8 @@ export struct FlexFlowProperty : Property { Vec> explodeShorthand(PropertyRegistry& registry) const override { return { - makeRc(registry.resolveRegistration("flex-direction"s).unwrap(), _value.v0), - makeRc(registry.resolveRegistration("flex-wrap"s).unwrap(), _value.v1), + makeRc(registry.resolveRegistration(Properties::FLEX_DIRECTION, {}).unwrap(), _value.v0), + makeRc(registry.resolveRegistration(Properties::FLEX_WRAP, {}).unwrap(), _value.v1), }; } @@ -282,7 +282,7 @@ export struct FlexProperty : Property { return Ok(makeRc(self(), value)); } - // deafult values if these parameters are omitted + // default values if these parameters are omitted value.flexGrow = value.flexShrink = 1; value.flexBasis = CalcValue>(Length{}); diff --git a/src/vaev-engine/style/computer.cpp b/src/vaev-engine/style/computer.cpp index 3ecab166..7b1edf7b 100644 --- a/src/vaev-engine/style/computer.cpp +++ b/src/vaev-engine/style/computer.cpp @@ -226,10 +226,14 @@ export struct Computer { return; if (not svgEl->hasAttribute(Svg::WIDTH_ATTR)) - styleProps.pushBack(_propertyRegistry.parseDeclaration(Properties::WIDTH, "300px", {})); + styleProps.pushBack( + _propertyRegistry.parseDeclaration(Properties::WIDTH, "300px", {}).unwrap() + ); if (not svgEl->hasAttribute(Svg::HEIGHT_ATTR)) - styleProps.pushBack(_propertyRegistry.parseDeclaration(Properties::HEIGHT, "150px", {})); + styleProps.pushBack( + _propertyRegistry.parseDeclaration(Properties::HEIGHT, "150px", {}).unwrap() + ); } } @@ -265,7 +269,10 @@ export struct Computer { // Get the style attribute if any if (auto styleAttr = el->style()) { StyleRule styleRule{ - .props = _propertyRegistry.parseDeclarations(styleAttr ? *styleAttr : ""), + .props = _propertyRegistry.parseDeclarations( + styleAttr ? *styleAttr : "", + PropertyRegistry::TOP_LEVEL + ), .origin = Origin::INLINE, }; matchingRules.pushBack({&styleRule, INLINE_SPEC}); diff --git a/src/vaev-engine/style/mod.cpp b/src/vaev-engine/style/mod.cpp index 5bde44cd..771cbb66 100644 --- a/src/vaev-engine/style/mod.cpp +++ b/src/vaev-engine/style/mod.cpp @@ -8,7 +8,6 @@ export import :style.matcher; export import :style.media; export import :style.origin; export import :style.page; -export import :style.props; export import :style.rules; export import :style.selector; export import :style.stylesheet; diff --git a/src/vaev-engine/style/page.cpp b/src/vaev-engine/style/page.cpp index e5c5b94e..ebbbe535 100644 --- a/src/vaev-engine/style/page.cpp +++ b/src/vaev-engine/style/page.cpp @@ -200,7 +200,7 @@ export struct PageAreaRule { for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - if (auto p = propertyRegistry.parseDeclaration(item)) + if (auto p = propertyRegistry.parseDeclaration(item, PropertyRegistry::TOP_LEVEL)) res.props.pushBack(p.take()); } else { logWarnIf(DEBUG_PAGE, "unexpected item in style rule: {}", item); diff --git a/src/vaev-engine/style/rules.cpp b/src/vaev-engine/style/rules.cpp index 438303c3..98c82e8e 100644 --- a/src/vaev-engine/style/rules.cpp +++ b/src/vaev-engine/style/rules.cpp @@ -50,7 +50,7 @@ export struct StyleRule { // Parse the properties. for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - if (auto p = propertyRegistry.parseDeclaration(item)) + if (auto p = propertyRegistry.parseDeclaration(item, PropertyRegistry::TOP_LEVEL)) res.props.pushBack(p.take()); } else { logWarnIf(debugRule, "unexpected item in style rule: {}", item); @@ -192,7 +192,7 @@ export struct PageRule { // Parse the properties. for (auto const& item : sst.content) { if (item == Css::Sst::DECL) { - auto prop = registry.parseDeclaration(item); + auto prop = registry.parseDeclaration(item, PropertyRegistry::TOP_LEVEL); if (prop) res.props.pushBack(prop.take()); } else if (item == Css::Sst::RULE and From cbbca4426e16378bf6a598ee9ad7a3791ae2a173 Mon Sep 17 00:00:00 2001 From: sleepy-monax Date: Thu, 4 Dec 2025 15:20:23 +0100 Subject: [PATCH 5/5] wip --- src/vaev-engine/dom/document.cpp | 9 +++++++++ src/vaev-engine/res/missing.qoi | Bin 498 -> 157 bytes 2 files changed, 9 insertions(+) diff --git a/src/vaev-engine/dom/document.cpp b/src/vaev-engine/dom/document.cpp index fbe559a2..ff5da4f4 100644 --- a/src/vaev-engine/dom/document.cpp +++ b/src/vaev-engine/dom/document.cpp @@ -5,6 +5,8 @@ import Karm.Ref; import Karm.Font; import :dom.node; import :dom.element; +import :props.base; +import :props.registry; namespace Vaev::Style { export struct StyleSheetList; @@ -12,6 +14,8 @@ export struct StyleSheetList; namespace Vaev::Dom { +export struct Window; + export enum struct QuirkMode { NO, LIMITED, @@ -29,7 +33,12 @@ export struct Document : Node { String xmlEncoding; String xmlStandalone = "no"s; // https://www.w3.org/TR/xml/#NT-SDDecl + // https://drafts.csswg.org/cssom/#dom-documentorshadowroot-stylesheets Gc::Ptr styleSheets; + + // https://drafts.css-houdini.org/css-properties-values-api/#dom-window-registeredpropertyset-slot + Style::PropertyRegistry registeredPropertySet = Style::defaultRegistry(); + Opt> fontDatabase; Document(Ref::Url url) diff --git a/src/vaev-engine/res/missing.qoi b/src/vaev-engine/res/missing.qoi index 092773bc43b5286ff1a22e7df3e2b499f876341a..650d85d0b99bfec227c997c01b849e7bba739359 100644 GIT binary patch literal 157 zcmXwz%LxN93`CV71*8gJ=H^>E*$NhN3aQEW)F6L$O&|rNkeuyE3lR)&(1<~g`)w7G zi|Z^SrSy`Dv46fDDh2Eqb52MGHB>5sLKF-e5i;bz-uQ+dYGZj`mCd3W3yWWu*r?u- V<8Dx@lV+UJ%)yLqX|-p3PCvb7I$;0+ literal 498 zcmXAmZ%7ky9LBHJ%ZMPzK`<)f2XREqUew++5R@S7g`m-b=*^C1f%qyq+ips?yKBAE z+L>+h?wBjGs8JF2<~KdCR)K9=mK65SnprNR61{uY&A#w`^E}@NJ`dl{ju6K%%qC|y zZ(yJeYU+q!3YR!omTgFRB(5X?RNG7sl$f027(=4Cs;c;0u`u<1SxB~rjG?2L`)Q#& zA`tNWxmuQBpkKxGoOLc#k8?mFiXtrAX7T2WB0%42+LN$Lsl*ZD zsqy)N>M^@yti-XwMG4AzE2^o V1ZUb$Ly5#2Q!SZ&&WCHW?jI_)F?av~