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