commit f0de57d: [Project] Css: Add opacity support
Vsevolod Stakhov
vsevolod at highsecure.ru
Tue Mar 9 13:00:06 UTC 2021
Author: Vsevolod Stakhov
Date: 2021-03-09 12:07:27 +0000
URL: https://github.com/rspamd/rspamd/commit/f0de57da10d978a4ceea1dcfad01c6a50d04b467
[Project] Css: Add opacity support
---
src/libserver/css/css_colors_list.hxx | 1 +
src/libserver/css/css_property.cxx | 2 ++
src/libserver/css/css_property.hxx | 12 ++++++++++++
src/libserver/css/css_rule.cxx | 20 ++++++++++++++++++++
src/libserver/css/css_tokeniser.hxx | 35 +++++++++++++++++++++++++++++++++++
src/libserver/css/css_value.cxx | 22 +---------------------
src/libserver/css/css_value.hxx | 12 ++++++------
test/lua/unit/css.lua | 5 +++++
8 files changed, 82 insertions(+), 27 deletions(-)
diff --git a/src/libserver/css/css_colors_list.hxx b/src/libserver/css/css_colors_list.hxx
index dc7f60960..b1fc5d6ee 100644
--- a/src/libserver/css/css_colors_list.hxx
+++ b/src/libserver/css/css_colors_list.hxx
@@ -727,6 +727,7 @@ static const robin_hood::unordered_flat_map<std::string_view, css_color> css_col
{"threedhighlight", {0, 0, 0}},
{"threedlightshadow", {0, 0, 0}},
{"threedshadow", {0, 0, 0}},
+ {"transparent", {0, 0, 0, 0}},
{"window", {255, 255, 255}},
{"windowframe", {100, 100, 100}},
{"windowtext", {0, 0, 0}},
diff --git a/src/libserver/css/css_property.cxx b/src/libserver/css/css_property.cxx
index b2578a367..54e927057 100644
--- a/src/libserver/css/css_property.cxx
+++ b/src/libserver/css/css_property.cxx
@@ -23,6 +23,7 @@ namespace rspamd::css {
constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_property_type>({
{"font", css_property_type::PROPERTY_FONT},
{"font-color", css_property_type::PROPERTY_FONT_COLOR},
+ {"font-size", css_property_type::PROPERTY_FONT_SIZE},
{"color", css_property_type::PROPERTY_COLOR},
{"bgcolor", css_property_type::PROPERTY_BGCOLOR},
{"background", css_property_type::PROPERTY_BACKGROUND},
@@ -30,6 +31,7 @@ constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_p
{"width", css_property_type::PROPERTY_WIDTH},
{"display", css_property_type::PROPERTY_DISPLAY},
{"visibility", css_property_type::PROPERTY_VISIBILITY},
+ {"opacity", css_property_type::PROPERTY_OPACITY},
});
auto token_string_to_property(const std::string_view &inp)
diff --git a/src/libserver/css/css_property.hxx b/src/libserver/css/css_property.hxx
index 670dfaddb..3908c6d16 100644
--- a/src/libserver/css/css_property.hxx
+++ b/src/libserver/css/css_property.hxx
@@ -32,6 +32,7 @@ namespace rspamd::css {
enum class css_property_type : std::uint16_t {
PROPERTY_FONT = 0,
PROPERTY_FONT_COLOR,
+ PROPERTY_FONT_SIZE,
PROPERTY_COLOR,
PROPERTY_BGCOLOR,
PROPERTY_BACKGROUND,
@@ -39,6 +40,7 @@ enum class css_property_type : std::uint16_t {
PROPERTY_WIDTH,
PROPERTY_DISPLAY,
PROPERTY_VISIBILITY,
+ PROPERTY_OPACITY,
PROPERTY_NYI,
};
@@ -65,6 +67,9 @@ struct alignas(int) css_property {
case css_property_type::PROPERTY_FONT_COLOR:
ret = "font-color";
break;
+ case css_property_type::PROPERTY_FONT_SIZE:
+ ret = "font-size";
+ break;
case css_property_type::PROPERTY_COLOR:
ret = "color";
break;
@@ -86,6 +91,9 @@ struct alignas(int) css_property {
case css_property_type::PROPERTY_VISIBILITY:
ret = "visibility";
break;
+ case css_property_type::PROPERTY_OPACITY:
+ ret = "opacity";
+ break;
default:
break;
}
@@ -93,6 +101,7 @@ struct alignas(int) css_property {
return ret;
}
+ /* Helpers to define which values are valid for which properties */
constexpr auto is_color(void) const -> bool {
return type == css_property_type::PROPERTY_COLOR ||
type == css_property_type::PROPERTY_BACKGROUND ||
@@ -103,6 +112,9 @@ struct alignas(int) css_property {
return type == css_property_type::PROPERTY_HEIGHT ||
type == css_property_type::PROPERTY_WIDTH;
}
+ constexpr auto is_normal_number(void) const -> bool {
+ return type == css_property_type::PROPERTY_OPACITY;
+ }
};
diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx
index 5bd99bd0e..511c226d2 100644
--- a/src/libserver/css/css_rule.cxx
+++ b/src/libserver/css/css_rule.cxx
@@ -40,6 +40,26 @@ allowed_property_value(const css_property &prop, const css_consumed_block &parse
return css_value::maybe_color_from_function(func);
}
}
+ else if (prop.is_dimension()) {
+ if (parser_block.is_token()) {
+ /* A single token */
+ const auto &tok = parser_block.get_token_or_empty();
+
+ if (tok.type == css_parser_token::token_type::number_token) {
+ return css_value{tok.get_number_or_default(0)};
+ }
+ }
+ }
+ else if (prop.is_normal_number()) {
+ if (parser_block.is_token()) {
+ /* A single token */
+ const auto &tok = parser_block.get_token_or_empty();
+
+ if (tok.type == css_parser_token::token_type::number_token) {
+ return css_value{tok.get_normal_number_or_default(0)};
+ }
+ }
+ }
return std::nullopt;
}
diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx
index 3776b36e5..53ec4f2db 100644
--- a/src/libserver/css/css_tokeniser.hxx
+++ b/src/libserver/css/css_tokeniser.hxx
@@ -111,6 +111,41 @@ struct css_parser_token {
return def;
}
+ auto get_number_or_default(double def) const -> double {
+ if (std::holds_alternative<double>(value)) {
+ auto dbl = std::get<double>(value);
+
+ if (flags & css_parser_token::number_percent) {
+ dbl /= 100.0;
+ }
+
+ return dbl;
+ }
+
+ return def;
+ }
+
+ auto get_normal_number_or_default(double def) const -> double {
+ if (std::holds_alternative<double>(value)) {
+ auto dbl = std::get<double>(value);
+
+ if (flags & css_parser_token::number_percent) {
+ dbl /= 100.0;
+ }
+
+ if (dbl < 0) {
+ return 0.0;
+ }
+ else if (dbl > 1.0) {
+ return 1.0;
+ }
+
+ return dbl;
+ }
+
+ return def;
+ }
+
/* Debugging routines */
constexpr auto get_token_type() -> const char *;
/* This function might be slow */
diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx
index aa842e2e2..719633e68 100644
--- a/src/libserver/css/css_value.cxx
+++ b/src/libserver/css/css_value.cxx
@@ -182,27 +182,7 @@ constexpr static inline auto sl_component_convert(const css_parser_token &tok)
double ret = 0.0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
-
- if (tok.flags & css_parser_token::number_percent) {
- if (dbl > 100) {
- dbl = 100;
- }
- else if (dbl < 0) {
- dbl = 0;
- }
- ret = (dbl / 100.0);
- }
- else {
- if (dbl > 1) {
- dbl = 1;
- }
- else if (dbl < 0) {
- dbl = 0;
- }
-
- ret = (dbl);
- }
+ ret = tok.get_normal_number_or_default(ret);
}
return ret;
diff --git a/src/libserver/css/css_value.hxx b/src/libserver/css/css_value.hxx
index 0e675e0ca..8fa450e73 100644
--- a/src/libserver/css/css_value.hxx
+++ b/src/libserver/css/css_value.hxx
@@ -56,9 +56,9 @@ enum class css_display_value {
struct css_value {
enum class css_value_type {
CSS_VALUE_COLOR,
- CSS_VALUE_SIZE,
+ CSS_VALUE_NUMBER,
CSS_VALUE_DISPLAY,
- CSS_VALUE_FLAG,
+ CSS_VALUE_OPACITY,
CSS_VALUE_NYI,
} type;
@@ -69,8 +69,8 @@ struct css_value {
css_value(const css_color &color) :
type(css_value_type::CSS_VALUE_COLOR), value(color) {}
- css_value(double sz) :
- type(css_value_type::CSS_VALUE_SIZE), value(sz) {}
+ css_value(double num) :
+ type(css_value_type::CSS_VALUE_NUMBER), value(num) {}
constexpr std::optional<css_color> to_color(void) const {
if (type == css_value_type::CSS_VALUE_COLOR) {
@@ -80,8 +80,8 @@ struct css_value {
return std::nullopt;
}
- constexpr std::optional<double> to_size(void) const {
- if (type == css_value_type::CSS_VALUE_SIZE) {
+ constexpr std::optional<double> to_number(void) const {
+ if (type == css_value_type::CSS_VALUE_NUMBER) {
return std::get<double>(value);
}
diff --git a/test/lua/unit/css.lua b/test/lua/unit/css.lua
index 86119641e..9f9201191 100644
--- a/test/lua/unit/css.lua
+++ b/test/lua/unit/css.lua
@@ -100,6 +100,11 @@ body {
]],
[[
/* Colors */
+p { color: rgb(100%, 50%, 0%); opacity: -1; } /* very transparent solid orange */
+p { color: rgb(100%, 50%, 0%); opacity: 2; } /* very transparent solid orange */
+p { color: rgb(100%, 50%, 0%); opacity: 0.5; } /* very transparent solid orange */
+p { color: rgb(100%, 50%, 0%); opacity: 1; width: 99%; } /* very transparent solid orange */
+p { color: rgb(100%, 50%, 0%); opacity: 10%; width: 99%; } /* very transparent solid orange */
* { color: hsl(0, 100%, 50%) !important } /* red */
* { color: hsl(120, 100%, 50%) important } /* lime */
* { color: hsl(120, 100%, 25%) } /* dark green */
More information about the Commits
mailing list