2020-01-18 11:38:21 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
2021-08-09 22:28:56 +03:00
|
|
|
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
LibWeb: Add CSS ValueListStyleValue
As the new CSS parser tokenizes its input, we can no longer easily
rely on a StringStyleValue for multi-value properties. (eg, border)
ValueListStyleValue lets us wrap all of the ComponentValues that
the Parser produced for one declaration, as a single StyleValue, to
then be parsed into StyleValues by the StyleResolver.
Originally, I wanted it to be a list of StyleValues, but several
properties use syntax that makes use of non-StyleValue tokens, eg:
```css
/* Syntax using a / */
font: 12px/14px sans-serif;
/* Multiple values separated by commas */
background: url(catdog.png), url(another-image.jpg), blue;
```
Passing the ComponentValue tokens themselves means that all that
information is carried over. The alternative might be to create a
StyleValue subclass for each property and parse them fully inside
the Parser. (eg, `FontStyleValue`)
I decided against `ListStyleValue` as a name, to avoid confusion
with list styles. It's not ideal, but names are hard.
2021-07-13 18:50:58 +03:00
|
|
|
* Copyright (c) 2021, Sam Atkins <atkinssj@gmail.com>
|
2020-01-18 11:38:21 +03:00
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-01-18 11:38:21 +03:00
|
|
|
*/
|
|
|
|
|
2019-06-21 00:25:25 +03:00
|
|
|
#pragma once
|
|
|
|
|
2021-07-23 00:01:39 +03:00
|
|
|
#include <AK/NonnullOwnPtr.h>
|
|
|
|
#include <AK/NonnullOwnPtrVector.h>
|
LibWeb: Add CSS ValueListStyleValue
As the new CSS parser tokenizes its input, we can no longer easily
rely on a StringStyleValue for multi-value properties. (eg, border)
ValueListStyleValue lets us wrap all of the ComponentValues that
the Parser produced for one declaration, as a single StyleValue, to
then be parsed into StyleValues by the StyleResolver.
Originally, I wanted it to be a list of StyleValues, but several
properties use syntax that makes use of non-StyleValue tokens, eg:
```css
/* Syntax using a / */
font: 12px/14px sans-serif;
/* Multiple values separated by commas */
background: url(catdog.png), url(another-image.jpg), blue;
```
Passing the ComponentValue tokens themselves means that all that
information is carried over. The alternative might be to create a
StyleValue subclass for each property and parse them fully inside
the Parser. (eg, `FontStyleValue`)
I decided against `ListStyleValue` as a name, to avoid confusion
with list styles. It's not ideal, but names are hard.
2021-07-13 18:50:58 +03:00
|
|
|
#include <AK/NonnullRefPtrVector.h>
|
2019-06-21 19:58:45 +03:00
|
|
|
#include <AK/RefCounted.h>
|
2019-06-22 22:48:21 +03:00
|
|
|
#include <AK/RefPtr.h>
|
2019-09-28 23:18:19 +03:00
|
|
|
#include <AK/String.h>
|
2019-06-22 22:48:21 +03:00
|
|
|
#include <AK/StringView.h>
|
2019-10-19 12:49:46 +03:00
|
|
|
#include <AK/URL.h>
|
2021-07-23 00:01:39 +03:00
|
|
|
#include <AK/Variant.h>
|
|
|
|
#include <AK/Vector.h>
|
2019-10-19 12:49:46 +03:00
|
|
|
#include <AK/WeakPtr.h>
|
2020-02-06 14:07:05 +03:00
|
|
|
#include <LibGfx/Bitmap.h>
|
2020-06-02 14:51:30 +03:00
|
|
|
#include <LibGfx/Color.h>
|
2020-03-07 12:32:51 +03:00
|
|
|
#include <LibWeb/CSS/Length.h>
|
LibWeb: Add CSS ValueListStyleValue
As the new CSS parser tokenizes its input, we can no longer easily
rely on a StringStyleValue for multi-value properties. (eg, border)
ValueListStyleValue lets us wrap all of the ComponentValues that
the Parser produced for one declaration, as a single StyleValue, to
then be parsed into StyleValues by the StyleResolver.
Originally, I wanted it to be a list of StyleValues, but several
properties use syntax that makes use of non-StyleValue tokens, eg:
```css
/* Syntax using a / */
font: 12px/14px sans-serif;
/* Multiple values separated by commas */
background: url(catdog.png), url(another-image.jpg), blue;
```
Passing the ComponentValue tokens themselves means that all that
information is carried over. The alternative might be to create a
StyleValue subclass for each property and parse them fully inside
the Parser. (eg, `FontStyleValue`)
I decided against `ListStyleValue` as a name, to avoid confusion
with list styles. It's not ideal, but names are hard.
2021-07-13 18:50:58 +03:00
|
|
|
#include <LibWeb/CSS/Parser/StyleComponentValueRule.h>
|
2020-03-07 12:32:51 +03:00
|
|
|
#include <LibWeb/CSS/PropertyID.h>
|
2020-12-15 22:39:09 +03:00
|
|
|
#include <LibWeb/CSS/ValueID.h>
|
2020-07-21 17:23:08 +03:00
|
|
|
#include <LibWeb/Forward.h>
|
2020-06-06 00:32:23 +03:00
|
|
|
#include <LibWeb/Loader/ImageResource.h>
|
2019-06-21 00:25:25 +03:00
|
|
|
|
2020-07-21 17:23:08 +03:00
|
|
|
namespace Web::CSS {
|
2019-10-06 11:25:08 +03:00
|
|
|
|
2020-03-23 19:29:15 +03:00
|
|
|
enum class Position {
|
|
|
|
Static,
|
|
|
|
Relative,
|
|
|
|
Absolute,
|
|
|
|
Fixed,
|
|
|
|
Sticky,
|
|
|
|
};
|
2020-06-24 00:28:40 +03:00
|
|
|
|
|
|
|
enum class TextAlign {
|
|
|
|
Left,
|
|
|
|
Center,
|
|
|
|
Right,
|
|
|
|
Justify,
|
2020-12-15 22:39:09 +03:00
|
|
|
LibwebCenter,
|
2020-06-24 00:28:40 +03:00
|
|
|
};
|
|
|
|
|
2020-12-15 15:36:27 +03:00
|
|
|
enum class TextDecorationLine {
|
|
|
|
None,
|
|
|
|
Underline,
|
|
|
|
Overline,
|
|
|
|
LineThrough,
|
|
|
|
Blink,
|
|
|
|
};
|
|
|
|
|
2020-12-15 16:15:49 +03:00
|
|
|
enum class TextTransform {
|
|
|
|
None,
|
|
|
|
Capitalize,
|
|
|
|
Uppercase,
|
|
|
|
Lowercase,
|
|
|
|
FullWidth,
|
|
|
|
FullSizeKana,
|
|
|
|
};
|
|
|
|
|
2020-06-24 17:22:16 +03:00
|
|
|
enum class Display {
|
|
|
|
None,
|
|
|
|
Block,
|
|
|
|
Inline,
|
|
|
|
InlineBlock,
|
|
|
|
ListItem,
|
|
|
|
Table,
|
|
|
|
TableRow,
|
|
|
|
TableCell,
|
2020-07-05 20:51:49 +03:00
|
|
|
TableHeaderGroup,
|
2020-06-24 17:22:16 +03:00
|
|
|
TableRowGroup,
|
2020-07-05 20:51:49 +03:00
|
|
|
TableFooterGroup,
|
2021-01-07 16:40:02 +03:00
|
|
|
TableColumn,
|
|
|
|
TableColumnGroup,
|
|
|
|
TableCaption,
|
2021-01-18 19:32:34 +03:00
|
|
|
Flex,
|
2020-06-24 17:22:16 +03:00
|
|
|
};
|
|
|
|
|
2021-01-18 19:41:57 +03:00
|
|
|
enum class FlexDirection {
|
|
|
|
Row,
|
|
|
|
RowReverse,
|
|
|
|
Column,
|
|
|
|
ColumnReverse,
|
|
|
|
};
|
|
|
|
|
2021-05-30 13:11:32 +03:00
|
|
|
enum class FlexWrap {
|
|
|
|
Nowrap,
|
|
|
|
Wrap,
|
|
|
|
WrapReverse
|
|
|
|
};
|
|
|
|
|
2021-05-30 15:23:43 +03:00
|
|
|
enum class FlexBasis {
|
|
|
|
Content,
|
2021-08-06 23:00:25 +03:00
|
|
|
Length,
|
|
|
|
Auto,
|
2021-05-30 15:23:43 +03:00
|
|
|
};
|
|
|
|
|
2020-06-24 17:37:44 +03:00
|
|
|
enum class WhiteSpace {
|
|
|
|
Normal,
|
|
|
|
Pre,
|
|
|
|
Nowrap,
|
|
|
|
PreLine,
|
|
|
|
PreWrap,
|
|
|
|
};
|
|
|
|
|
2020-06-26 16:08:42 +03:00
|
|
|
enum class Float {
|
|
|
|
None,
|
|
|
|
Left,
|
|
|
|
Right,
|
|
|
|
};
|
|
|
|
|
2020-12-06 03:45:51 +03:00
|
|
|
enum class Clear {
|
|
|
|
None,
|
|
|
|
Left,
|
|
|
|
Right,
|
|
|
|
Both,
|
|
|
|
};
|
|
|
|
|
2021-02-21 20:41:00 +03:00
|
|
|
enum class Cursor {
|
|
|
|
Auto,
|
|
|
|
Default,
|
|
|
|
None,
|
|
|
|
ContextMenu,
|
|
|
|
Help,
|
|
|
|
Pointer,
|
|
|
|
Progress,
|
|
|
|
Wait,
|
|
|
|
Cell,
|
|
|
|
Crosshair,
|
|
|
|
Text,
|
|
|
|
VerticalText,
|
|
|
|
Alias,
|
|
|
|
Copy,
|
|
|
|
Move,
|
|
|
|
NoDrop,
|
|
|
|
NotAllowed,
|
|
|
|
Grab,
|
|
|
|
Grabbing,
|
|
|
|
EResize,
|
|
|
|
NResize,
|
|
|
|
NeResize,
|
|
|
|
NwResize,
|
|
|
|
SResize,
|
|
|
|
SeResize,
|
|
|
|
SwResize,
|
|
|
|
WResize,
|
|
|
|
EwResize,
|
|
|
|
NsResize,
|
|
|
|
NeswResize,
|
|
|
|
NwseResize,
|
|
|
|
ColResize,
|
|
|
|
RowResize,
|
|
|
|
AllScroll,
|
|
|
|
ZoomIn,
|
|
|
|
ZoomOut,
|
|
|
|
};
|
|
|
|
|
2020-12-04 18:11:55 +03:00
|
|
|
enum class LineStyle {
|
|
|
|
None,
|
|
|
|
Hidden,
|
|
|
|
Dotted,
|
|
|
|
Dashed,
|
|
|
|
Solid,
|
|
|
|
Double,
|
|
|
|
Groove,
|
|
|
|
Ridge,
|
|
|
|
Inset,
|
|
|
|
Outset,
|
|
|
|
};
|
|
|
|
|
2020-12-15 18:50:39 +03:00
|
|
|
enum class ListStyleType {
|
|
|
|
None,
|
|
|
|
Disc,
|
|
|
|
Circle,
|
|
|
|
Square,
|
|
|
|
Decimal,
|
2021-04-22 23:14:24 +03:00
|
|
|
DecimalLeadingZero,
|
2021-04-23 00:39:18 +03:00
|
|
|
LowerAlpha,
|
|
|
|
LowerLatin,
|
2021-07-04 18:17:23 +03:00
|
|
|
LowerRoman,
|
2021-04-23 00:52:15 +03:00
|
|
|
UpperAlpha,
|
|
|
|
UpperLatin,
|
2021-07-04 18:17:23 +03:00
|
|
|
UpperRoman,
|
2020-12-15 18:50:39 +03:00
|
|
|
};
|
|
|
|
|
2021-02-22 17:20:31 +03:00
|
|
|
enum class Overflow : u8 {
|
|
|
|
Auto,
|
|
|
|
Clip,
|
|
|
|
Hidden,
|
|
|
|
Scroll,
|
|
|
|
Visible,
|
|
|
|
};
|
|
|
|
|
2021-04-02 22:41:29 +03:00
|
|
|
enum class Repeat : u8 {
|
|
|
|
NoRepeat,
|
|
|
|
Repeat,
|
|
|
|
Round,
|
|
|
|
Space,
|
|
|
|
};
|
|
|
|
|
2021-07-16 19:38:26 +03:00
|
|
|
enum class JustifyContent {
|
|
|
|
FlexStart,
|
|
|
|
FlexEnd,
|
|
|
|
Center,
|
|
|
|
SpaceBetween,
|
|
|
|
SpaceAround,
|
|
|
|
};
|
|
|
|
|
2019-06-21 16:29:31 +03:00
|
|
|
class StyleValue : public RefCounted<StyleValue> {
|
2019-06-21 00:25:25 +03:00
|
|
|
public:
|
|
|
|
virtual ~StyleValue();
|
|
|
|
|
2019-07-03 08:55:22 +03:00
|
|
|
enum class Type {
|
2019-06-21 00:25:25 +03:00
|
|
|
Invalid,
|
|
|
|
Inherit,
|
|
|
|
Initial,
|
2019-07-03 08:55:22 +03:00
|
|
|
String,
|
|
|
|
Length,
|
2019-09-28 23:18:19 +03:00
|
|
|
Color,
|
2019-10-06 11:25:08 +03:00
|
|
|
Identifier,
|
2019-10-19 12:49:46 +03:00
|
|
|
Image,
|
2021-05-24 23:46:19 +03:00
|
|
|
CustomProperty,
|
2021-06-03 22:59:41 +03:00
|
|
|
Numeric,
|
LibWeb: Add CSS ValueListStyleValue
As the new CSS parser tokenizes its input, we can no longer easily
rely on a StringStyleValue for multi-value properties. (eg, border)
ValueListStyleValue lets us wrap all of the ComponentValues that
the Parser produced for one declaration, as a single StyleValue, to
then be parsed into StyleValues by the StyleResolver.
Originally, I wanted it to be a list of StyleValues, but several
properties use syntax that makes use of non-StyleValue tokens, eg:
```css
/* Syntax using a / */
font: 12px/14px sans-serif;
/* Multiple values separated by commas */
background: url(catdog.png), url(another-image.jpg), blue;
```
Passing the ComponentValue tokens themselves means that all that
information is carried over. The alternative might be to create a
StyleValue subclass for each property and parse them fully inside
the Parser. (eg, `FontStyleValue`)
I decided against `ListStyleValue` as a name, to avoid confusion
with list styles. It's not ideal, but names are hard.
2021-07-13 18:50:58 +03:00
|
|
|
ValueList,
|
2021-07-23 00:01:39 +03:00
|
|
|
Calculated,
|
2021-07-23 22:17:09 +03:00
|
|
|
BoxShadow,
|
2019-06-21 00:25:25 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
Type type() const { return m_type; }
|
|
|
|
|
2019-07-08 08:14:23 +03:00
|
|
|
bool is_inherit() const { return type() == Type::Inherit; }
|
|
|
|
bool is_initial() const { return type() == Type::Initial; }
|
2019-09-29 19:05:37 +03:00
|
|
|
bool is_color() const { return type() == Type::Color; }
|
2021-08-09 18:02:26 +03:00
|
|
|
bool is_identifier() const { return type() == Type::Identifier || is_auto(); }
|
2019-10-19 12:49:46 +03:00
|
|
|
bool is_image() const { return type() == Type::Image; }
|
2019-11-18 13:49:19 +03:00
|
|
|
bool is_string() const { return type() == Type::String; }
|
LibWeb: Make '0' always be both a number and a length in CSS
A '0' token can be interpreted both as a Number, and as a Length. This
is problematic as in our CSS parser, we often call parse_css_value()
first, to figure out what something is, and then assign it. So we do not
know in advance whether we want a Length or not. Previously, it always
got parsed as a Length, and then every place that expected a
NumericStyleValue had to also check for a Length(0), which is easy to
forget to do.
In particular, this was causing issues with the `flex` property parsing.
To solve this, we now always parse 0 as a NumericStyleValue, and NSVs of
0 pretend to be a Length(0px) when asked. In two places, we were casting
to a LengthStyleValue* based on is_length(), which no longer works, so
those have been adjusted to use `StyleValue::to_length()` instead. They
also now check for `is_numeric()` first, to avoid the extra conversion
to a Length and back.
Possibly this opens up new issues elsewhere. In my testing it seems
fine, but until we can get CSS test suites running, it's hard to know
for certain.
2021-08-05 17:26:04 +03:00
|
|
|
virtual bool is_length() const { return type() == Type::Length; }
|
2021-05-24 23:46:19 +03:00
|
|
|
bool is_custom_property() const { return type() == Type::CustomProperty; }
|
2021-06-03 22:59:41 +03:00
|
|
|
bool is_numeric() const { return type() == Type::Numeric; }
|
2021-07-28 18:29:11 +03:00
|
|
|
bool is_value_list() const { return type() == Type::ValueList; }
|
2021-07-23 22:17:09 +03:00
|
|
|
bool is_box_shadow() const { return type() == Type::BoxShadow; }
|
2021-07-28 18:29:11 +03:00
|
|
|
bool is_calculated() const { return type() == Type::Calculated; }
|
2021-07-18 19:12:23 +03:00
|
|
|
|
2021-08-10 14:23:27 +03:00
|
|
|
bool is_builtin() const { return is_inherit() || is_initial(); }
|
|
|
|
|
2021-07-28 18:29:11 +03:00
|
|
|
bool is_builtin_or_dynamic() const
|
2021-07-23 00:01:39 +03:00
|
|
|
{
|
2021-07-28 18:29:11 +03:00
|
|
|
return is_inherit() || is_initial() || is_custom_property() || is_calculated();
|
2021-07-23 00:01:39 +03:00
|
|
|
}
|
|
|
|
|
2019-06-25 07:31:47 +03:00
|
|
|
virtual String to_string() const = 0;
|
2020-06-24 12:08:46 +03:00
|
|
|
virtual Length to_length() const { return Length::make_auto(); }
|
2020-07-26 20:37:56 +03:00
|
|
|
virtual Color to_color(const DOM::Document&) const { return {}; }
|
2019-06-25 07:31:47 +03:00
|
|
|
|
2020-12-15 15:36:27 +03:00
|
|
|
CSS::ValueID to_identifier() const;
|
|
|
|
|
2019-08-18 09:09:56 +03:00
|
|
|
virtual bool is_auto() const { return false; }
|
|
|
|
|
2020-12-14 17:04:13 +03:00
|
|
|
bool operator==(const StyleValue& other) const { return equals(other); }
|
|
|
|
bool operator!=(const StyleValue& other) const { return !(*this == other); }
|
|
|
|
|
|
|
|
virtual bool equals(const StyleValue& other) const
|
|
|
|
{
|
|
|
|
if (type() != other.type())
|
|
|
|
return false;
|
|
|
|
return to_string() == other.to_string();
|
|
|
|
}
|
|
|
|
|
2019-06-21 00:25:25 +03:00
|
|
|
protected:
|
|
|
|
explicit StyleValue(Type);
|
|
|
|
|
|
|
|
private:
|
|
|
|
Type m_type { Type::Invalid };
|
|
|
|
};
|
2019-06-22 22:48:21 +03:00
|
|
|
|
2021-05-24 23:46:19 +03:00
|
|
|
// FIXME: Allow for fallback
|
|
|
|
class CustomStyleValue : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<CustomStyleValue> create(const String& custom_property_name)
|
|
|
|
{
|
|
|
|
return adopt_ref(*new CustomStyleValue(custom_property_name));
|
|
|
|
}
|
|
|
|
String custom_property_name() const { return m_custom_property_name; }
|
|
|
|
String to_string() const override { return m_custom_property_name; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
explicit CustomStyleValue(const String& custom_property_name)
|
|
|
|
: StyleValue(Type::CustomProperty)
|
|
|
|
, m_custom_property_name(custom_property_name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
String m_custom_property_name {};
|
|
|
|
};
|
|
|
|
|
2021-06-03 22:59:41 +03:00
|
|
|
class NumericStyleValue : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<NumericStyleValue> create(float value)
|
|
|
|
{
|
|
|
|
return adopt_ref(*new NumericStyleValue(value));
|
|
|
|
}
|
|
|
|
|
LibWeb: Make '0' always be both a number and a length in CSS
A '0' token can be interpreted both as a Number, and as a Length. This
is problematic as in our CSS parser, we often call parse_css_value()
first, to figure out what something is, and then assign it. So we do not
know in advance whether we want a Length or not. Previously, it always
got parsed as a Length, and then every place that expected a
NumericStyleValue had to also check for a Length(0), which is easy to
forget to do.
In particular, this was causing issues with the `flex` property parsing.
To solve this, we now always parse 0 as a NumericStyleValue, and NSVs of
0 pretend to be a Length(0px) when asked. In two places, we were casting
to a LengthStyleValue* based on is_length(), which no longer works, so
those have been adjusted to use `StyleValue::to_length()` instead. They
also now check for `is_numeric()` first, to avoid the extra conversion
to a Length and back.
Possibly this opens up new issues elsewhere. In my testing it seems
fine, but until we can get CSS test suites running, it's hard to know
for certain.
2021-08-05 17:26:04 +03:00
|
|
|
virtual bool is_length() const override { return m_value == 0; }
|
|
|
|
virtual Length to_length() const override { return Length(0, Length::Type::Px); }
|
|
|
|
|
2021-06-03 22:59:41 +03:00
|
|
|
float value() const { return m_value; }
|
|
|
|
String to_string() const override { return String::formatted("{}", m_value); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
explicit NumericStyleValue(float value)
|
|
|
|
: StyleValue(Type::Numeric)
|
|
|
|
, m_value(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
float m_value { 0 };
|
|
|
|
};
|
|
|
|
|
2019-07-03 08:55:22 +03:00
|
|
|
class StringStyleValue : public StyleValue {
|
2019-06-22 22:48:21 +03:00
|
|
|
public:
|
2019-07-04 16:49:16 +03:00
|
|
|
static NonnullRefPtr<StringStyleValue> create(const String& string)
|
2019-06-22 22:48:21 +03:00
|
|
|
{
|
2021-04-23 17:46:57 +03:00
|
|
|
return adopt_ref(*new StringStyleValue(string));
|
2019-06-22 22:48:21 +03:00
|
|
|
}
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~StringStyleValue() override { }
|
2019-06-22 22:48:21 +03:00
|
|
|
|
2019-06-25 07:31:47 +03:00
|
|
|
String to_string() const override { return m_string; }
|
2019-06-22 22:48:21 +03:00
|
|
|
|
|
|
|
private:
|
2019-07-04 16:49:16 +03:00
|
|
|
explicit StringStyleValue(const String& string)
|
|
|
|
: StyleValue(Type::String)
|
|
|
|
, m_string(string)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-06-22 22:48:21 +03:00
|
|
|
String m_string;
|
|
|
|
};
|
2019-07-03 08:55:22 +03:00
|
|
|
|
2021-07-23 22:17:09 +03:00
|
|
|
class BoxShadowStyleValue : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<BoxShadowStyleValue> create(Length const& offset_x, Length const& offset_y, Length const& blur_radius, Color const& color)
|
|
|
|
{
|
|
|
|
return adopt_ref(*new BoxShadowStyleValue(offset_x, offset_y, blur_radius, color));
|
|
|
|
}
|
|
|
|
virtual ~BoxShadowStyleValue() override { }
|
|
|
|
|
|
|
|
Length const& offset_x() const { return m_offset_x; }
|
|
|
|
Length const& offset_y() const { return m_offset_y; }
|
|
|
|
Length const& blur_radius() const { return m_blur_radius; }
|
|
|
|
Color const& color() const { return m_color; }
|
|
|
|
|
|
|
|
String to_string() const override { return String::formatted("BoxShadow offset_x: {}, offset_y: {}, blur_radius: {}, color: {}",
|
|
|
|
m_offset_x.to_string(), m_offset_y.to_string(), m_blur_radius.to_string(), m_color.to_string()); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
explicit BoxShadowStyleValue(Length const& offset_x, Length const& offset_y, Length const& blur_radius, Color const& color)
|
|
|
|
: StyleValue(Type::BoxShadow)
|
|
|
|
, m_offset_x(offset_x)
|
|
|
|
, m_offset_y(offset_y)
|
|
|
|
, m_blur_radius(blur_radius)
|
|
|
|
, m_color(color)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Length m_offset_x;
|
|
|
|
Length m_offset_y;
|
|
|
|
Length m_blur_radius;
|
|
|
|
Color m_color;
|
|
|
|
};
|
|
|
|
|
2019-07-03 08:55:22 +03:00
|
|
|
class LengthStyleValue : public StyleValue {
|
|
|
|
public:
|
2019-07-04 16:49:16 +03:00
|
|
|
static NonnullRefPtr<LengthStyleValue> create(const Length& length)
|
2019-07-03 08:55:22 +03:00
|
|
|
{
|
2021-04-23 17:46:57 +03:00
|
|
|
return adopt_ref(*new LengthStyleValue(length));
|
2019-07-03 08:55:22 +03:00
|
|
|
}
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~LengthStyleValue() override { }
|
2019-07-03 08:55:22 +03:00
|
|
|
|
2019-07-26 09:05:14 +03:00
|
|
|
virtual String to_string() const override { return m_length.to_string(); }
|
|
|
|
virtual Length to_length() const override { return m_length; }
|
|
|
|
|
|
|
|
const Length& length() const { return m_length; }
|
2019-07-03 08:55:22 +03:00
|
|
|
|
2019-08-18 09:09:56 +03:00
|
|
|
virtual bool is_auto() const override { return m_length.is_auto(); }
|
|
|
|
|
2020-12-15 21:39:33 +03:00
|
|
|
virtual bool equals(const StyleValue& other) const override
|
|
|
|
{
|
|
|
|
if (type() != other.type())
|
|
|
|
return false;
|
|
|
|
return m_length == static_cast<const LengthStyleValue&>(other).m_length;
|
|
|
|
}
|
|
|
|
|
2019-07-03 08:55:22 +03:00
|
|
|
private:
|
2019-07-04 16:49:16 +03:00
|
|
|
explicit LengthStyleValue(const Length& length)
|
|
|
|
: StyleValue(Type::Length)
|
|
|
|
, m_length(length)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-07-03 08:55:22 +03:00
|
|
|
Length m_length;
|
|
|
|
};
|
2019-07-08 08:14:23 +03:00
|
|
|
|
2021-07-23 00:01:39 +03:00
|
|
|
class CalculatedStyleValue : public StyleValue {
|
|
|
|
public:
|
|
|
|
struct CalcSum;
|
|
|
|
struct CalcSumPartWithOperator;
|
|
|
|
struct CalcProduct;
|
|
|
|
struct CalcProductPartWithOperator;
|
|
|
|
struct CalcNumberSum;
|
|
|
|
struct CalcNumberSumPartWithOperator;
|
|
|
|
struct CalcNumberProduct;
|
|
|
|
struct CalcNumberProductPartWithOperator;
|
|
|
|
|
|
|
|
using CalcNumberValue = Variant<float, NonnullOwnPtr<CalcNumberSum>>;
|
|
|
|
using CalcValue = Variant<float, CSS::Length, NonnullOwnPtr<CalcSum>>;
|
|
|
|
|
|
|
|
// This represents that: https://drafts.csswg.org/css-values-3/#calc-syntax
|
|
|
|
struct CalcSum {
|
|
|
|
CalcSum(NonnullOwnPtr<CalcProduct> first_calc_product, NonnullOwnPtrVector<CalcSumPartWithOperator> additional)
|
|
|
|
: first_calc_product(move(first_calc_product))
|
|
|
|
, zero_or_more_additional_calc_products(move(additional)) {};
|
|
|
|
|
|
|
|
NonnullOwnPtr<CalcProduct> first_calc_product;
|
|
|
|
NonnullOwnPtrVector<CalcSumPartWithOperator> zero_or_more_additional_calc_products;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcNumberSum {
|
|
|
|
CalcNumberSum(NonnullOwnPtr<CalcNumberProduct> first_calc_number_product, NonnullOwnPtrVector<CalcNumberSumPartWithOperator> additional)
|
|
|
|
: first_calc_number_product(move(first_calc_number_product))
|
|
|
|
, zero_or_more_additional_calc_number_products(move(additional)) {};
|
|
|
|
|
|
|
|
NonnullOwnPtr<CalcNumberProduct> first_calc_number_product;
|
|
|
|
NonnullOwnPtrVector<CalcNumberSumPartWithOperator> zero_or_more_additional_calc_number_products;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcProduct {
|
|
|
|
CalcValue first_calc_value;
|
|
|
|
NonnullOwnPtrVector<CalcProductPartWithOperator> zero_or_more_additional_calc_values;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcSumPartWithOperator {
|
|
|
|
enum Operation {
|
|
|
|
Add,
|
|
|
|
Subtract,
|
|
|
|
};
|
|
|
|
|
|
|
|
CalcSumPartWithOperator(Operation op, NonnullOwnPtr<CalcProduct> calc_product)
|
|
|
|
: op(op)
|
|
|
|
, calc_product(move(calc_product)) {};
|
|
|
|
|
|
|
|
Operation op;
|
|
|
|
NonnullOwnPtr<CalcProduct> calc_product;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcProductPartWithOperator {
|
|
|
|
enum {
|
|
|
|
Multiply,
|
|
|
|
Divide,
|
|
|
|
} op;
|
|
|
|
Variant<CalcValue, CalcNumberValue> value;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcNumberProduct {
|
|
|
|
CalcNumberValue first_calc_number_value;
|
|
|
|
NonnullOwnPtrVector<CalcNumberProductPartWithOperator> zero_or_more_additional_calc_number_values;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcNumberProductPartWithOperator {
|
|
|
|
enum {
|
|
|
|
Multiply,
|
|
|
|
Divide,
|
|
|
|
} op;
|
|
|
|
CalcNumberValue value;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CalcNumberSumPartWithOperator {
|
|
|
|
enum Operation {
|
|
|
|
Add,
|
|
|
|
Subtract,
|
|
|
|
};
|
|
|
|
|
|
|
|
CalcNumberSumPartWithOperator(Operation op, NonnullOwnPtr<CalcNumberProduct> calc_number_product)
|
|
|
|
: op(op)
|
|
|
|
, calc_number_product(move(calc_number_product)) {};
|
|
|
|
|
|
|
|
Operation op;
|
|
|
|
NonnullOwnPtr<CalcNumberProduct> calc_number_product;
|
|
|
|
};
|
|
|
|
|
|
|
|
static NonnullRefPtr<CalculatedStyleValue> create(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum)
|
|
|
|
{
|
|
|
|
return adopt_ref(*new CalculatedStyleValue(expression_string, move(calc_sum)));
|
|
|
|
}
|
|
|
|
|
|
|
|
String to_string() const override { return m_expression_string; }
|
|
|
|
NonnullOwnPtr<CalcSum> const& expression() const { return m_expression; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
explicit CalculatedStyleValue(String const& expression_string, NonnullOwnPtr<CalcSum> calc_sum)
|
|
|
|
: StyleValue(Type::Calculated)
|
|
|
|
, m_expression_string(expression_string)
|
|
|
|
, m_expression(move(calc_sum))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
String m_expression_string;
|
|
|
|
NonnullOwnPtr<CalcSum> m_expression;
|
|
|
|
};
|
|
|
|
|
2019-07-08 08:14:23 +03:00
|
|
|
class InitialStyleValue final : public StyleValue {
|
|
|
|
public:
|
2021-04-23 17:46:57 +03:00
|
|
|
static NonnullRefPtr<InitialStyleValue> create() { return adopt_ref(*new InitialStyleValue); }
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~InitialStyleValue() override { }
|
2019-07-08 08:14:23 +03:00
|
|
|
|
|
|
|
String to_string() const override { return "initial"; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
InitialStyleValue()
|
|
|
|
: StyleValue(Type::Initial)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class InheritStyleValue final : public StyleValue {
|
|
|
|
public:
|
2021-04-23 17:46:57 +03:00
|
|
|
static NonnullRefPtr<InheritStyleValue> create() { return adopt_ref(*new InheritStyleValue); }
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~InheritStyleValue() override { }
|
2019-07-08 08:14:23 +03:00
|
|
|
|
|
|
|
String to_string() const override { return "inherit"; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
InheritStyleValue()
|
|
|
|
: StyleValue(Type::Inherit)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
2019-09-28 23:18:19 +03:00
|
|
|
|
|
|
|
class ColorStyleValue : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<ColorStyleValue> create(Color color)
|
|
|
|
{
|
2021-04-23 17:46:57 +03:00
|
|
|
return adopt_ref(*new ColorStyleValue(color));
|
2019-09-28 23:18:19 +03:00
|
|
|
}
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~ColorStyleValue() override { }
|
2019-09-28 23:18:19 +03:00
|
|
|
|
|
|
|
Color color() const { return m_color; }
|
2019-10-03 17:11:46 +03:00
|
|
|
String to_string() const override { return m_color.to_string(); }
|
2020-07-26 20:37:56 +03:00
|
|
|
Color to_color(const DOM::Document&) const override { return m_color; }
|
2019-09-28 23:18:19 +03:00
|
|
|
|
2020-12-15 21:39:33 +03:00
|
|
|
virtual bool equals(const StyleValue& other) const override
|
|
|
|
{
|
|
|
|
if (type() != other.type())
|
|
|
|
return false;
|
|
|
|
return m_color == static_cast<const ColorStyleValue&>(other).m_color;
|
|
|
|
}
|
|
|
|
|
2019-09-28 23:18:19 +03:00
|
|
|
private:
|
|
|
|
explicit ColorStyleValue(Color color)
|
|
|
|
: StyleValue(Type::Color)
|
|
|
|
, m_color(color)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Color m_color;
|
|
|
|
};
|
2019-10-06 11:25:08 +03:00
|
|
|
|
|
|
|
class IdentifierStyleValue final : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<IdentifierStyleValue> create(CSS::ValueID id)
|
|
|
|
{
|
2021-04-23 17:46:57 +03:00
|
|
|
return adopt_ref(*new IdentifierStyleValue(id));
|
2019-10-06 11:25:08 +03:00
|
|
|
}
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~IdentifierStyleValue() override { }
|
2019-10-06 11:25:08 +03:00
|
|
|
|
|
|
|
CSS::ValueID id() const { return m_id; }
|
|
|
|
|
|
|
|
virtual String to_string() const override;
|
2020-07-26 20:37:56 +03:00
|
|
|
virtual Color to_color(const DOM::Document&) const override;
|
2019-10-06 11:25:08 +03:00
|
|
|
|
2020-12-14 17:04:13 +03:00
|
|
|
virtual bool equals(const StyleValue& other) const override
|
|
|
|
{
|
|
|
|
if (type() != other.type())
|
|
|
|
return false;
|
|
|
|
return m_id == static_cast<const IdentifierStyleValue&>(other).m_id;
|
|
|
|
}
|
|
|
|
|
2019-10-06 11:25:08 +03:00
|
|
|
private:
|
|
|
|
explicit IdentifierStyleValue(CSS::ValueID id)
|
|
|
|
: StyleValue(Type::Identifier)
|
|
|
|
, m_id(id)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CSS::ValueID m_id { CSS::ValueID::Invalid };
|
|
|
|
};
|
2019-10-19 12:49:46 +03:00
|
|
|
|
2020-06-02 14:51:30 +03:00
|
|
|
class ImageStyleValue final
|
|
|
|
: public StyleValue
|
2020-06-06 00:32:23 +03:00
|
|
|
, public ImageResourceClient {
|
2019-10-19 12:49:46 +03:00
|
|
|
public:
|
2021-04-23 17:46:57 +03:00
|
|
|
static NonnullRefPtr<ImageStyleValue> create(const URL& url, DOM::Document& document) { return adopt_ref(*new ImageStyleValue(url, document)); }
|
2020-06-02 14:51:30 +03:00
|
|
|
virtual ~ImageStyleValue() override { }
|
2019-10-19 12:49:46 +03:00
|
|
|
|
2021-01-03 16:05:46 +03:00
|
|
|
String to_string() const override { return String::formatted("Image({})", m_url.to_string()); }
|
2019-10-19 12:49:46 +03:00
|
|
|
|
2020-02-06 13:56:38 +03:00
|
|
|
const Gfx::Bitmap* bitmap() const { return m_bitmap; }
|
2019-10-19 12:49:46 +03:00
|
|
|
|
|
|
|
private:
|
2020-07-26 20:37:56 +03:00
|
|
|
ImageStyleValue(const URL&, DOM::Document&);
|
2019-10-19 12:49:46 +03:00
|
|
|
|
2020-06-02 14:51:30 +03:00
|
|
|
// ^ResourceClient
|
|
|
|
virtual void resource_did_load() override;
|
|
|
|
|
2019-10-19 12:49:46 +03:00
|
|
|
URL m_url;
|
2020-07-26 20:37:56 +03:00
|
|
|
WeakPtr<DOM::Document> m_document;
|
2020-02-06 13:56:38 +03:00
|
|
|
RefPtr<Gfx::Bitmap> m_bitmap;
|
2019-10-19 12:49:46 +03:00
|
|
|
};
|
2020-03-07 12:27:02 +03:00
|
|
|
|
LibWeb: Add CSS ValueListStyleValue
As the new CSS parser tokenizes its input, we can no longer easily
rely on a StringStyleValue for multi-value properties. (eg, border)
ValueListStyleValue lets us wrap all of the ComponentValues that
the Parser produced for one declaration, as a single StyleValue, to
then be parsed into StyleValues by the StyleResolver.
Originally, I wanted it to be a list of StyleValues, but several
properties use syntax that makes use of non-StyleValue tokens, eg:
```css
/* Syntax using a / */
font: 12px/14px sans-serif;
/* Multiple values separated by commas */
background: url(catdog.png), url(another-image.jpg), blue;
```
Passing the ComponentValue tokens themselves means that all that
information is carried over. The alternative might be to create a
StyleValue subclass for each property and parse them fully inside
the Parser. (eg, `FontStyleValue`)
I decided against `ListStyleValue` as a name, to avoid confusion
with list styles. It's not ideal, but names are hard.
2021-07-13 18:50:58 +03:00
|
|
|
class ValueListStyleValue final : public StyleValue {
|
|
|
|
public:
|
|
|
|
static NonnullRefPtr<ValueListStyleValue> create(Vector<StyleComponentValueRule>&& values) { return adopt_ref(*new ValueListStyleValue(move(values))); }
|
|
|
|
virtual ~ValueListStyleValue() override { }
|
|
|
|
|
|
|
|
virtual String to_string() const override;
|
|
|
|
|
|
|
|
Vector<StyleComponentValueRule> const& values() const { return m_values; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
ValueListStyleValue(Vector<StyleComponentValueRule>&&);
|
|
|
|
|
|
|
|
Vector<StyleComponentValueRule> m_values;
|
|
|
|
};
|
|
|
|
|
2020-12-15 15:36:27 +03:00
|
|
|
inline CSS::ValueID StyleValue::to_identifier() const
|
|
|
|
{
|
|
|
|
if (is_identifier())
|
|
|
|
return static_cast<const IdentifierStyleValue&>(*this).id();
|
2021-08-09 18:02:26 +03:00
|
|
|
if (is_auto())
|
|
|
|
return CSS::ValueID::Auto;
|
2020-12-15 15:36:27 +03:00
|
|
|
return CSS::ValueID::Invalid;
|
|
|
|
}
|
2020-03-07 12:27:02 +03:00
|
|
|
}
|