Skip to content

Commit c4b9e7e

Browse files
AtkinsSJgmta
authored andcommitted
LibWeb: Parse and propagate extended text-indent property values
CSS Text 3 gives `text-indent` a couple of optional keywords to control which lines are affected. This commit parses them, but doesn't yet do anything with them.
1 parent eea1d4e commit c4b9e7e

16 files changed

+199
-9
lines changed

Libraries/LibWeb/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ set(SOURCES
273273
CSS/StyleValues/StyleValue.cpp
274274
CSS/StyleValues/StyleValueList.cpp
275275
CSS/StyleValues/SuperellipseStyleValue.cpp
276+
CSS/StyleValues/TextIndentStyleValue.cpp
276277
CSS/StyleValues/TextUnderlinePositionStyleValue.cpp
277278
CSS/StyleValues/TransformationStyleValue.cpp
278279
CSS/StyleValues/TreeCountingFunctionStyleValue.cpp

Libraries/LibWeb/CSS/ComputedProperties.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
3737
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
3838
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
39+
#include <LibWeb/CSS/StyleValues/TextIndentStyleValue.h>
3940
#include <LibWeb/CSS/StyleValues/TextUnderlinePositionStyleValue.h>
4041
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
4142
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
@@ -1369,6 +1370,17 @@ Vector<ShadowData> ComputedProperties::text_shadow(Layout::Node const& layout_no
13691370
return shadow(PropertyID::TextShadow, layout_node);
13701371
}
13711372

1373+
TextIndentData ComputedProperties::text_indent() const
1374+
{
1375+
auto const& value = property(PropertyID::TextIndent).as_text_indent();
1376+
1377+
return TextIndentData {
1378+
.length_percentage = LengthPercentage::from_style_value(value.length_percentage()),
1379+
.each_line = value.each_line(),
1380+
.hanging = value.hanging(),
1381+
};
1382+
}
1383+
13721384
TextWrapMode ComputedProperties::text_wrap_mode() const
13731385
{
13741386
auto const& value = property(PropertyID::TextWrapMode);

Libraries/LibWeb/CSS/ComputedProperties.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class WEB_API ComputedProperties final : public JS::Cell {
122122
TextDecorationThickness text_decoration_thickness() const;
123123
TextTransform text_transform() const;
124124
Vector<ShadowData> text_shadow(Layout::Node const&) const;
125+
TextIndentData text_indent() const;
125126
TextWrapMode text_wrap_mode() const;
126127
ListStyleType list_style_type() const;
127128
ListStylePosition list_style_position() const;

Libraries/LibWeb/CSS/ComputedValues.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ struct ScrollbarColorData {
9494
Color track_color { Color::Transparent };
9595
};
9696

97+
struct TextIndentData {
98+
LengthPercentage length_percentage;
99+
bool each_line { false };
100+
bool hanging { false };
101+
};
102+
97103
struct TextUnderlinePosition {
98104
TextUnderlinePositionHorizontal horizontal { TextUnderlinePositionHorizontal::Auto };
99105
TextUnderlinePositionVertical vertical { TextUnderlinePositionVertical::Auto };
@@ -159,7 +165,7 @@ class InitialValues {
159165
static TextDecorationStyle text_decoration_style() { return TextDecorationStyle::Solid; }
160166
static TextTransform text_transform() { return TextTransform::None; }
161167
static TextOverflow text_overflow() { return TextOverflow::Clip; }
162-
static LengthPercentage text_indent() { return Length::make_px(0); }
168+
static TextIndentData text_indent() { return { Length::make_px(0) }; }
163169
static TextWrapMode text_wrap_mode() { return TextWrapMode::Wrap; }
164170
static CSSPixels text_underline_offset() { return 2; }
165171
static TextUnderlinePosition text_underline_position() { return { .horizontal = TextUnderlinePositionHorizontal::Auto, .vertical = TextUnderlinePositionVertical::Auto }; }
@@ -497,7 +503,7 @@ class ComputedValues {
497503
Variant<Length, double> tab_size() const { return m_inherited.tab_size; }
498504
TextAlign text_align() const { return m_inherited.text_align; }
499505
TextJustify text_justify() const { return m_inherited.text_justify; }
500-
LengthPercentage const& text_indent() const { return m_inherited.text_indent; }
506+
TextIndentData const& text_indent() const { return m_inherited.text_indent; }
501507
TextWrapMode text_wrap_mode() const { return m_inherited.text_wrap_mode; }
502508
CSSPixels text_underline_offset() const { return m_inherited.text_underline_offset; }
503509
TextUnderlinePosition text_underline_position() const { return m_inherited.text_underline_position; }
@@ -702,7 +708,7 @@ class ComputedValues {
702708
TextAlign text_align { InitialValues::text_align() };
703709
TextJustify text_justify { InitialValues::text_justify() };
704710
TextTransform text_transform { InitialValues::text_transform() };
705-
LengthPercentage text_indent { InitialValues::text_indent() };
711+
TextIndentData text_indent { InitialValues::text_indent() };
706712
TextWrapMode text_wrap_mode { InitialValues::text_wrap_mode() };
707713
CSSPixels text_underline_offset { InitialValues::text_underline_offset() };
708714
TextUnderlinePosition text_underline_position { InitialValues::text_underline_position() };
@@ -915,7 +921,7 @@ class MutableComputedValues final : public ComputedValues {
915921
void set_text_decoration_color(Color value) { m_noninherited.text_decoration_color = value; }
916922
void set_text_transform(TextTransform value) { m_inherited.text_transform = value; }
917923
void set_text_shadow(Vector<ShadowData>&& value) { m_inherited.text_shadow = move(value); }
918-
void set_text_indent(LengthPercentage value) { m_inherited.text_indent = move(value); }
924+
void set_text_indent(TextIndentData value) { m_inherited.text_indent = move(value); }
919925
void set_text_wrap_mode(TextWrapMode value) { m_inherited.text_wrap_mode = value; }
920926
void set_text_overflow(TextOverflow value) { m_noninherited.text_overflow = value; }
921927
void set_text_underline_offset(CSSPixels value) { m_inherited.text_underline_offset = value; }

Libraries/LibWeb/CSS/Interpolation.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <LibWeb/CSS/StyleValues/RectStyleValue.h>
3333
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
3434
#include <LibWeb/CSS/StyleValues/SuperellipseStyleValue.h>
35+
#include <LibWeb/CSS/StyleValues/TextIndentStyleValue.h>
3536
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
3637
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
3738
#include <LibWeb/CSS/Transformation.h>
@@ -1877,6 +1878,22 @@ static RefPtr<StyleValue const> interpolate_value_impl(DOM::Element& element, Ca
18771878
interpolate_length_or_auto(from_rect.left_edge, to_rect.left_edge, calculation_context, delta),
18781879
});
18791880
}
1881+
case StyleValue::Type::TextIndent: {
1882+
auto& from_text_indent = from.as_text_indent();
1883+
auto& to_text_indent = to.as_text_indent();
1884+
1885+
if (from_text_indent.each_line() != to_text_indent.each_line()
1886+
|| from_text_indent.hanging() != to_text_indent.hanging())
1887+
return {};
1888+
1889+
auto interpolated_length_percentage = interpolate_value(element, calculation_context, from_text_indent.length_percentage(), to_text_indent.length_percentage(), delta, allow_discrete);
1890+
if (!interpolated_length_percentage)
1891+
return {};
1892+
1893+
return TextIndentStyleValue::create(interpolated_length_percentage.release_nonnull(),
1894+
from_text_indent.hanging() ? TextIndentStyleValue::Hanging::Yes : TextIndentStyleValue::Hanging::No,
1895+
from_text_indent.each_line() ? TextIndentStyleValue::EachLine::Yes : TextIndentStyleValue::EachLine::No);
1896+
}
18801897
case StyleValue::Type::Superellipse: {
18811898
// https://drafts.csswg.org/css-borders-4/#corner-shape-interpolation
18821899

Libraries/LibWeb/CSS/Keywords.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
"down",
188188
"e",
189189
"e-resize",
190+
"each-line",
190191
"ease",
191192
"ease-in",
192193
"ease-in-out",
@@ -237,6 +238,7 @@
237238
"graytext",
238239
"grid",
239240
"groove",
241+
"hanging",
240242
"hard-light",
241243
"height",
242244
"help",

Libraries/LibWeb/CSS/Parser/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ class Parser {
506506
RefPtr<StyleValue const> parse_shape_outside_value(TokenStream<ComponentValue>&);
507507
RefPtr<StyleValue const> parse_text_decoration_value(TokenStream<ComponentValue>&);
508508
RefPtr<StyleValue const> parse_text_decoration_line_value(TokenStream<ComponentValue>&);
509+
RefPtr<StyleValue const> parse_text_indent_value(TokenStream<ComponentValue>&);
509510
RefPtr<StyleValue const> parse_text_underline_position_value(TokenStream<ComponentValue>&);
510511
RefPtr<StyleValue const> parse_rotate_value(TokenStream<ComponentValue>&);
511512
RefPtr<StyleValue const> parse_stroke_dasharray_value(TokenStream<ComponentValue>&);

Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
5858
#include <LibWeb/CSS/StyleValues/StyleValue.h>
5959
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
60+
#include <LibWeb/CSS/StyleValues/TextIndentStyleValue.h>
6061
#include <LibWeb/CSS/StyleValues/TextUnderlinePositionStyleValue.h>
6162
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
6263
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
@@ -721,6 +722,8 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue const>> Parser::parse_css_value(Pr
721722
return parse_all_as(tokens, [this](auto& tokens) { return parse_text_decoration_value(tokens); });
722723
case PropertyID::TextDecorationLine:
723724
return parse_all_as(tokens, [this](auto& tokens) { return parse_text_decoration_line_value(tokens); });
725+
case PropertyID::TextIndent:
726+
return parse_all_as(tokens, [this](auto& tokens) { return parse_text_indent_value(tokens); });
724727
case PropertyID::TextShadow:
725728
return parse_all_as(tokens, [this](auto& tokens) { return parse_shadow_value(tokens, ShadowStyleValue::ShadowType::Text); });
726729
case PropertyID::TextUnderlinePosition:
@@ -4731,6 +4734,51 @@ RefPtr<StyleValue const> Parser::parse_text_decoration_line_value(TokenStream<Co
47314734
return StyleValueList::create(move(style_values), StyleValueList::Separator::Space);
47324735
}
47334736

4737+
// https://drafts.csswg.org/css-text-3/#text-indent-property
4738+
RefPtr<StyleValue const> Parser::parse_text_indent_value(TokenStream<ComponentValue>& tokens)
4739+
{
4740+
// [ <length-percentage> ] && hanging? && each-line?
4741+
auto transaction = tokens.begin_transaction();
4742+
4743+
RefPtr<StyleValue const> length_percentage;
4744+
bool has_hanging = false;
4745+
bool has_each_line = false;
4746+
4747+
tokens.discard_whitespace();
4748+
4749+
while (tokens.has_next_token()) {
4750+
if (!length_percentage) {
4751+
if (auto parsed = parse_length_percentage_value(tokens)) {
4752+
length_percentage = parsed.release_nonnull();
4753+
tokens.discard_whitespace();
4754+
continue;
4755+
}
4756+
}
4757+
4758+
if (auto keyword = parse_keyword_value(tokens)) {
4759+
if (!has_hanging && keyword->to_keyword() == Keyword::Hanging) {
4760+
has_hanging = true;
4761+
continue;
4762+
}
4763+
if (!has_each_line && keyword->to_keyword() == Keyword::EachLine) {
4764+
has_each_line = true;
4765+
continue;
4766+
}
4767+
return nullptr;
4768+
}
4769+
4770+
return nullptr;
4771+
}
4772+
4773+
if (!length_percentage)
4774+
return nullptr;
4775+
4776+
transaction.commit();
4777+
return TextIndentStyleValue::create(length_percentage.release_nonnull(),
4778+
has_hanging ? TextIndentStyleValue::Hanging::Yes : TextIndentStyleValue::Hanging::No,
4779+
has_each_line ? TextIndentStyleValue::EachLine::Yes : TextIndentStyleValue::EachLine::No);
4780+
}
4781+
47344782
// https://drafts.csswg.org/css-text-decor-4/#text-underline-position-property
47354783
RefPtr<StyleValue const> Parser::parse_text_underline_position_value(TokenStream<ComponentValue>& tokens)
47364784
{

Libraries/LibWeb/CSS/Properties.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3680,6 +3680,10 @@
36803680
"length [-∞,∞]",
36813681
"percentage [-∞,∞]"
36823682
],
3683+
"valid-identifiers": [
3684+
"each-line",
3685+
"hanging"
3686+
],
36833687
"percentages-resolve-to": "length",
36843688
"quirks": [
36853689
"unitless-length"

Libraries/LibWeb/CSS/StyleValues/StyleValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
#include <LibGfx/Font/Font.h>
1111
#include <LibGfx/Font/FontStyleMapping.h>
12-
#include <LibGfx/Font/FontWeight.h>
1312
#include <LibWeb/CSS/CSSStyleValue.h>
1413
#include <LibWeb/CSS/ComputedProperties.h>
1514
#include <LibWeb/CSS/Parser/Parser.h>
@@ -68,6 +67,7 @@
6867
#include <LibWeb/CSS/StyleValues/StyleValue.h>
6968
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
7069
#include <LibWeb/CSS/StyleValues/SuperellipseStyleValue.h>
70+
#include <LibWeb/CSS/StyleValues/TextIndentStyleValue.h>
7171
#include <LibWeb/CSS/StyleValues/TextUnderlinePositionStyleValue.h>
7272
#include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
7373
#include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>

0 commit comments

Comments
 (0)