commit 9b2fb6c: [Project] Html/CSS: Add transform from a CSS rule to html block
Vsevolod Stakhov
vsevolod at highsecure.ru
Fri Jun 11 14:14:06 UTC 2021
Author: Vsevolod Stakhov
Date: 2021-06-10 15:15:45 +0100
URL: https://github.com/rspamd/rspamd/commit/9b2fb6ce7e647bdf719c6598098ecd0f112cb016
[Project] Html/CSS: Add transform from a CSS rule to html block
---
src/libserver/css/css_rule.cxx | 119 +++++++++++++++++++++++++++++++++++-
src/libserver/css/css_rule.hxx | 12 ++++
src/libserver/css/css_tokeniser.cxx | 6 +-
src/libserver/css/css_tokeniser.hxx | 14 ++---
src/libserver/css/css_value.cxx | 10 +--
src/libserver/html/html_block.hxx | 9 ++-
6 files changed, 150 insertions(+), 20 deletions(-)
diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx
index 2e84aaa1c..d06f0aec0 100644
--- a/src/libserver/css/css_rule.cxx
+++ b/src/libserver/css/css_rule.cxx
@@ -16,6 +16,7 @@
#include "css_rule.hxx"
#include "css.hxx"
+#include "libserver/html/html_block.hxx"
#include <limits>
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
@@ -349,10 +350,11 @@ auto process_declaration_tokens(rspamd_mempool_t *pool,
}
auto
-css_declarations_block::merge_block(const css_declarations_block &other, merge_type how)
--> void {
+css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) -> void
+{
const auto &other_rules = other.get_rules();
+
for (auto &rule : other_rules) {
auto &&found_it = rules.find(rule);
@@ -379,6 +381,119 @@ css_declarations_block::merge_block(const css_declarations_block &other, merge_t
}
}
+auto
+css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block *
+{
+ auto *block = rspamd_mempool_alloc0_type(pool, rspamd::html::html_block);
+ auto opacity = -1;
+ const css_rule *font_rule = nullptr, *background_rule = nullptr;
+
+ for (const auto &rule : rules) {
+ auto prop = rule->get_prop().type;
+ const auto &vals = rule->get_values();
+
+ if (vals.empty()) {
+ continue;
+ }
+
+ switch (prop) {
+ case css_property_type::PROPERTY_VISIBILITY:
+ case css_property_type::PROPERTY_DISPLAY: {
+ auto disp = vals.back().to_display().value_or(css_display_value::DISPLAY_NORMAL);
+ block->set_display(disp);
+ break;
+ }
+ case css_property_type::PROPERTY_FONT_SIZE: {
+ auto fs = vals.back().to_dimension();
+ if (fs) {
+ block->set_font_size(fs.value().dim, fs.value().is_percent);
+ }
+ }
+ case css_property_type::PROPERTY_OPACITY: {
+ opacity = vals.back().to_number().value_or(opacity);
+ break;
+ }
+ case css_property_type::PROPERTY_FONT_COLOR: {
+ auto color = vals.back().to_color();
+ if (color) {
+ block->set_fgcolor(color.value());
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_BGCOLOR: {
+ auto color = vals.back().to_color();
+ if (color) {
+ block->set_bgcolor(color.value());
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_HEIGHT: {
+ auto w = vals.back().to_dimension();
+ if (w) {
+ block->set_width(w.value().dim, w.value().is_percent);
+ }
+ break;
+ }
+ case css_property_type::PROPERTY_WIDTH: {
+ auto h = vals.back().to_dimension();
+ if (h) {
+ block->set_width(h.value().dim, h.value().is_percent);
+ }
+ break;
+ }
+ /* Optional attributes */
+ case css_property_type::PROPERTY_FONT:
+ font_rule = rule.get();
+ break;
+ case css_property_type::PROPERTY_BACKGROUND:
+ background_rule = rule.get();
+ break;
+ default:
+ /* Do nothing for now */
+ break;
+ }
+ }
+
+ /* Optional properties */
+ if (!(block->mask & rspamd::html::html_block::fg_color_mask) && font_rule) {
+ auto &vals = font_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_color = val.to_color();
+
+ if (maybe_color) {
+ block->set_fgcolor(maybe_color.value());
+ }
+ }
+ }
+
+ if (!(block->mask & rspamd::html::html_block::font_size_mask) && font_rule) {
+ auto &vals = font_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_dim = val.to_dimension();
+
+ if (maybe_dim) {
+ block->set_font_size(maybe_dim.value().dim, maybe_dim.value().is_percent);
+ }
+ }
+ }
+
+ if (!(block->mask & rspamd::html::html_block::bg_color_mask) && background_rule) {
+ auto &vals = background_rule->get_values();
+
+ for (const auto &val : vals) {
+ auto maybe_color = val.to_color();
+
+ if (maybe_color) {
+ block->set_bgcolor(maybe_color.value());
+ }
+ }
+ }
+
+ return block;
+}
+
void css_rule::add_value(const css_value &value)
{
values.push_back(value);
diff --git a/src/libserver/css/css_rule.hxx b/src/libserver/css/css_rule.hxx
index 3353382e7..b29bf298f 100644
--- a/src/libserver/css/css_rule.hxx
+++ b/src/libserver/css/css_rule.hxx
@@ -26,6 +26,11 @@
#include <vector>
#include <memory>
+namespace rspamd::html {
+/* Forward declaration */
+struct html_block;
+}
+
namespace rspamd::css {
class css_rule {
@@ -107,6 +112,13 @@ public:
return (rules.find(css_rule{prop}) != rules.end());
}
+ /**
+ * Compile CSS declaration to the html block
+ * @param pool used to carry memory requred for html_block
+ * @return html block structure
+ */
+ auto compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block *;
+
private:
robin_hood::unordered_flat_set<rule_shared_ptr, rule_shared_hash, rule_shared_eq> rules;
};
diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx
index 0b1467d8f..f31fdc009 100644
--- a/src/libserver/css/css_tokeniser.cxx
+++ b/src/libserver/css/css_tokeniser.cxx
@@ -75,7 +75,7 @@ auto make_token<css_parser_token::token_type::delim_token, char>(const char &c)
}
template<>
-auto make_token<css_parser_token::token_type::number_token, double>(const double &d)
+auto make_token<css_parser_token::token_type::number_token, float>(const float &d)
-> css_parser_token
{
return css_parser_token{css_parser_token::token_type::number_token, d};
@@ -145,13 +145,13 @@ constexpr frozen::unordered_map<frozen::string, css_dimension_data, max_dims> di
auto
css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool
{
- if (!std::holds_alternative<double>(value) ||
+ if (!std::holds_alternative<float>(value) ||
!std::holds_alternative<std::string_view>(dim_token.value)) {
/* Invalid tokens */
return false;
}
- auto num = std::get<double>(value);
+ auto num = std::get<float>(value);
auto sv = std::get<std::string_view>(dim_token.value);
auto dim_found = dimensions_map.find(sv);
diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx
index a45e56f3f..021284989 100644
--- a/src/libserver/css/css_tokeniser.hxx
+++ b/src/libserver/css/css_tokeniser.hxx
@@ -80,7 +80,7 @@ struct css_parser_token {
using value_type = std::variant<std::string_view, /* For strings and string like tokens */
char, /* For delimiters (might need to move to unicode point) */
- double, /* For numeric stuff */
+ float, /* For numeric stuff */
css_parser_token_placeholder /* For general no token stuff */
>;
@@ -119,9 +119,9 @@ struct css_parser_token {
return (char)-1;
}
- auto get_number_or_default(double def) const -> double {
- if (std::holds_alternative<double>(value)) {
- auto dbl = std::get<double>(value);
+ auto get_number_or_default(float def) const -> float {
+ if (std::holds_alternative<float>(value)) {
+ auto dbl = std::get<float>(value);
if (flags & css_parser_token::number_percent) {
dbl /= 100.0;
@@ -133,9 +133,9 @@ struct css_parser_token {
return def;
}
- auto get_normal_number_or_default(double def) const -> double {
- if (std::holds_alternative<double>(value)) {
- auto dbl = std::get<double>(value);
+ auto get_normal_number_or_default(float def) const -> float {
+ if (std::holds_alternative<float>(value)) {
+ auto dbl = std::get<float>(value);
if (flags & css_parser_token::number_percent) {
dbl /= 100.0;
diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx
index 9f1f4dd7f..f573e38be 100644
--- a/src/libserver/css/css_value.cxx
+++ b/src/libserver/css/css_value.cxx
@@ -98,7 +98,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token
std::uint8_t ret = 0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -129,7 +129,7 @@ constexpr static inline auto alpha_component_convert(const css_parser_token &tok
double ret = 1.0;
if (tok.type == css_parser_token::token_type::number_token) {
- auto dbl = std::get<double>(tok.value);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -160,7 +160,7 @@ constexpr static inline auto h_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);
+ auto dbl = std::get<float>(tok.value);
if (tok.flags & css_parser_token::number_percent) {
if (dbl > 100) {
@@ -276,8 +276,8 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function
auto css_value::maybe_dimension_from_number(const css_parser_token &tok)
-> std::optional<css_value> {
- if (std::holds_alternative<double>(tok.value)) {
- auto dbl = std::get<double>(tok.value);
+ if (std::holds_alternative<float>(tok.value)) {
+ auto dbl = std::get<float>(tok.value);
css_dimension dim;
dim.dim = dbl;
diff --git a/src/libserver/html/html_block.hxx b/src/libserver/html/html_block.hxx
index bc912a007..3978bcf1e 100644
--- a/src/libserver/html/html_block.hxx
+++ b/src/libserver/html/html_block.hxx
@@ -49,7 +49,8 @@ struct html_block {
bg_color = c;
mask |= bg_color_mask;
}
- auto set_height(float h) -> void {
+ auto set_height(float h, bool is_percent = false) -> void {
+ h = is_percent ? (-h) : h;
if (h < INT16_MIN) {
/* Negative numbers encode percents... */
height = -100;
@@ -62,7 +63,8 @@ struct html_block {
}
mask |= height_mask;
}
- auto set_width(double w) -> void {
+ auto set_width(float w, bool is_percent = false) -> void {
+ w = is_percent ? (-w) : w;
if (w < INT16_MIN) {
width = INT16_MIN;
}
@@ -87,7 +89,8 @@ struct html_block {
display = v;
mask |= display_mask;
}
- auto set_font_size(float fs) -> void {
+ auto set_font_size(float fs, bool is_percent = false) -> void {
+ fs = is_percent ? (-fs) : fs;
if (fs < INT8_MIN) {
font_size = -100;
}
More information about the Commits
mailing list