summaryrefslogtreecommitdiff
path: root/libs/litehtml/include
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2024-10-09 18:13:40 +0300
committerGeorge Hazan <george.hazan@gmail.com>2024-10-09 18:13:40 +0300
commit0e86b853be3b5f809ed1decbf636221c1144a386 (patch)
tree4ce84d9849646a559d5afece33fc6e64d39e4a50 /libs/litehtml/include
parent834cbb58d74215980165eab257538ba918a378cd (diff)
litehtml update
Diffstat (limited to 'libs/litehtml/include')
-rw-r--r--libs/litehtml/include/litehtml.h12
-rw-r--r--libs/litehtml/include/litehtml/background.h175
-rw-r--r--libs/litehtml/include/litehtml/borders.h69
-rw-r--r--libs/litehtml/include/litehtml/css_length.h18
-rw-r--r--libs/litehtml/include/litehtml/css_margins.h9
-rw-r--r--libs/litehtml/include/litehtml/css_offsets.h9
-rw-r--r--libs/litehtml/include/litehtml/css_properties.h3
-rw-r--r--libs/litehtml/include/litehtml/css_selector.h136
-rw-r--r--libs/litehtml/include/litehtml/document.h53
-rw-r--r--libs/litehtml/include/litehtml/document_container.h9
-rw-r--r--libs/litehtml/include/litehtml/el_break.h2
-rw-r--r--libs/litehtml/include/litehtml/el_comment.h10
-rw-r--r--libs/litehtml/include/litehtml/el_space.h4
-rw-r--r--libs/litehtml/include/litehtml/el_text.h8
-rw-r--r--libs/litehtml/include/litehtml/element.h5
-rw-r--r--libs/litehtml/include/litehtml/encodings.h1
-rw-r--r--libs/litehtml/include/litehtml/gradient.h201
-rw-r--r--libs/litehtml/include/litehtml/html.h141
-rw-r--r--libs/litehtml/include/litehtml/html_tag.h32
-rw-r--r--libs/litehtml/include/litehtml/line_box.h4
-rw-r--r--libs/litehtml/include/litehtml/master_css.h147
-rw-r--r--libs/litehtml/include/litehtml/media_query.h141
-rw-r--r--libs/litehtml/include/litehtml/num_cvt.h3
-rw-r--r--libs/litehtml/include/litehtml/os_types.h17
-rw-r--r--libs/litehtml/include/litehtml/render_item.h4
-rw-r--r--libs/litehtml/include/litehtml/string_id.h95
-rw-r--r--libs/litehtml/include/litehtml/style.h91
-rw-r--r--libs/litehtml/include/litehtml/stylesheet.h92
-rw-r--r--libs/litehtml/include/litehtml/table.h16
-rw-r--r--libs/litehtml/include/litehtml/tstring_view.h2
-rw-r--r--libs/litehtml/include/litehtml/types.h224
-rw-r--r--libs/litehtml/include/litehtml/url.h2
-rw-r--r--libs/litehtml/include/litehtml/url_path.h2
-rw-r--r--libs/litehtml/include/litehtml/utf8_strings.h20
-rw-r--r--libs/litehtml/include/litehtml/web_color.h52
35 files changed, 969 insertions, 840 deletions
diff --git a/libs/litehtml/include/litehtml.h b/libs/litehtml/include/litehtml.h
index 9953170b6b..2537aee839 100644
--- a/libs/litehtml/include/litehtml.h
+++ b/libs/litehtml/include/litehtml.h
@@ -1,11 +1,11 @@
#ifndef LITEHTML_H
#define LITEHTML_H
-#include "litehtml/html.h"
-#include "litehtml/document.h"
-#include "litehtml/html_tag.h"
-#include "litehtml/stylesheet.h"
-#include "litehtml/element.h"
-#include "litehtml/utf8_strings.h"
+#include <litehtml/html.h>
+#include <litehtml/document.h>
+#include <litehtml/html_tag.h>
+#include <litehtml/stylesheet.h>
+#include <litehtml/element.h>
+#include <litehtml/utf8_strings.h>
#endif // LITEHTML_H
diff --git a/libs/litehtml/include/litehtml/background.h b/libs/litehtml/include/litehtml/background.h
index 93e0502cad..07b07aa3c2 100644
--- a/libs/litehtml/include/litehtml/background.h
+++ b/libs/litehtml/include/litehtml/background.h
@@ -6,161 +6,10 @@
#include "css_position.h"
#include "web_color.h"
#include "borders.h"
+#include "gradient.h"
namespace litehtml
{
- class background_gradient
- {
- public:
- enum gradient_type
- {
- no_gradient,
- linear_gradient,
- repeating_linear_gradient,
- radial_gradient,
- repeating_radial_gradient,
- conic_gradient,
- repeating_conic_gradient,
- };
- enum gradient_side
- {
- gradient_side_none = 0,
- gradient_side_left = 0x01,
- gradient_side_right = 0x02,
- gradient_side_top = 0x04,
- gradient_side_bottom = 0x08,
- gradient_side_x_center = 0x10,
- gradient_side_y_center = 0x20,
- gradient_side_x_length = 0x40,
- gradient_side_y_length = 0x80,
- };
- enum radial_shape_t
- {
- radial_shape_none,
- radial_shape_circle,
- radial_shape_ellipse,
- };
- enum radial_extent_t
- {
- radial_extent_none,
- radial_extent_closest_corner,
- radial_extent_closest_side,
- radial_extent_farthest_corner,
- radial_extent_farthest_side,
- };
- enum conic_color_space_t
- {
- conic_color_space_none,
- // rectangular-color-space
- conic_color_space_srgb,
- conic_color_space_srgb_linear,
- conic_color_space_display_p3,
- conic_color_space_a98_rgb,
- conic_color_space_prophoto_rgb,
- conic_color_space_rec2020,
- conic_color_space_lab,
- conic_color_space_oklab,
- conic_color_space_xyz,
- conic_color_space_xyz_d50,
- conic_color_space_xyz_d65,
-
- // polar-color-space
- conic_color_space_polar_start,
- conic_color_space_hsl,
- conic_color_space_hwb,
- conic_color_space_lch,
- conic_color_space_oklch,
- };
- enum interpolation_method_t
- {
- interpolation_method_none,
- interpolation_method_hue,
- interpolation_method_shorter_hue,
- interpolation_method_longer_hue,
- interpolation_method_increasing_hue,
- interpolation_method_decreasing_hue
- };
-
- class gradient_color
- {
- public:
- bool is_color_hint;
- web_color color;
- css_length length;
- def_value<float> angle;
-
- gradient_color() :
- is_color_hint(false), angle(0)
- {}
- };
- gradient_type m_type;
- uint32_t m_side;
- float angle;
- std::vector<gradient_color> m_colors;
- css_length radial_position_x;
- css_length radial_position_y;
- radial_extent_t radial_extent;
- radial_shape_t radial_shape;
- css_length radial_length_x;
- css_length radial_length_y;
- float conic_from_angle;
- conic_color_space_t conic_color_space;
- interpolation_method_t conic_interpolation;
-
-
- explicit background_gradient(gradient_type type = no_gradient)
- {
- m_type = type;
- m_side = gradient_side_none;
- angle = 180;
- radial_extent = radial_extent_none;
- radial_shape = radial_shape_ellipse;
- radial_length_x.predef(0);
- radial_length_y.predef(0);
- radial_position_x.predef(0);
- radial_position_y.predef(0);
- conic_from_angle = 0;
- conic_color_space = conic_color_space_none;
- conic_interpolation = interpolation_method_none;
- }
-
- bool is_empty() const
- {
- return m_type == no_gradient || m_colors.empty();
- }
-
- static background_gradient transparent;
- };
-
- class background_image
- {
- public:
- enum bg_image_type_t
- {
- bg_image_type_none,
- bg_image_type_url,
- bg_image_type_gradient,
- };
- bg_image_type_t type;
- std::string url;
- background_gradient gradient;
-
- background_image() : type(bg_image_type_none) {}
- bool is_empty() const
- {
- switch (type)
- {
- case bg_image_type_none:
- return false;
- case bg_image_type_url:
- return url.empty();
- case bg_image_type_gradient:
- return gradient.is_empty();
- }
- return true;
- }
- };
-
class background_layer
{
public:
@@ -186,14 +35,15 @@ namespace litehtml
class image
{
public:
- std::string url;
- std::string base_url;
+ string url;
+ string base_url;
};
struct color_point
{
float offset;
web_color color;
+ optional<float> hint;
color_point() { offset = 0.0; }
color_point(float _offset, web_color _color) : offset(_offset), color(_color) {}
};
@@ -207,11 +57,12 @@ namespace litehtml
class gradient_base
{
public:
- std::vector<color_point> color_points;
+ vector<color_point> color_points;
+ color_space_t color_space = color_space_none;
+ hue_interpolation_t hue_interpolation = hue_interpolation_none;
void color_points_transparent_fix();
- bool prepare_color_points(float len, background_gradient::gradient_type g_type, const std::vector<background_gradient::gradient_color>& colors);
- bool prepare_angle_color_points(background_gradient::gradient_type g_type, const std::vector<background_gradient::gradient_color>& colors);
+ bool prepare_color_points(float len, string_id grad_type, const vector<gradient::color_stop>& colors);
};
class linear_gradient : public gradient_base
@@ -232,13 +83,7 @@ namespace litehtml
{
public:
pointF position;
- float angle;
- background_gradient::conic_color_space_t color_space;
- background_gradient::interpolation_method_t interpolation;
- conic_gradient() : angle(0),
- color_space(background_gradient::conic_color_space_none),
- interpolation(background_gradient::interpolation_method_none)
- {}
+ float angle = 0;
};
};
@@ -255,7 +100,7 @@ namespace litehtml
type_conic_gradient,
};
- std::vector<background_image> m_image;
+ vector<image> m_image;
string m_baseurl;
web_color m_color;
int_vector m_attachment;
diff --git a/libs/litehtml/include/litehtml/borders.h b/libs/litehtml/include/litehtml/borders.h
index 9c47abca07..7a14e869c5 100644
--- a/libs/litehtml/include/litehtml/borders.h
+++ b/libs/litehtml/include/litehtml/borders.h
@@ -25,13 +25,7 @@ namespace litehtml
color = val.color;
}
- css_border& operator=(const css_border& val)
- {
- width = val.width;
- style = val.style;
- color = val.color;
- return *this;
- }
+ css_border& operator=(const css_border& val) = default;
string to_string() const;
};
@@ -45,6 +39,7 @@ namespace litehtml
border()
{
width = 0;
+ style = border_style_none;
}
border(const border& val)
{
@@ -58,13 +53,7 @@ namespace litehtml
style = val.style;
color = val.color;
}
- border& operator=(const border& val)
- {
- width = val.width;
- style = val.style;
- color = val.color;
- return *this;
- }
+ border& operator=(const border& val) = default;
border& operator=(const css_border& val)
{
width = (int) val.width.val();
@@ -110,18 +99,7 @@ namespace litehtml
bottom_left_x = val.bottom_left_x;
bottom_left_y = val.bottom_left_y;
}
- border_radiuses& operator = (const border_radiuses& val)
- {
- top_left_x = val.top_left_x;
- top_left_y = val.top_left_y;
- top_right_x = val.top_right_x;
- top_right_y = val.top_right_y;
- bottom_right_x = val.bottom_right_x;
- bottom_right_y = val.bottom_right_y;
- bottom_left_x = val.bottom_left_x;
- bottom_left_y = val.bottom_left_y;
- return *this;
- }
+ border_radiuses& operator = (const border_radiuses& val) = default;
void operator += (const margins& mg)
{
top_left_x += mg.left;
@@ -202,10 +180,7 @@ namespace litehtml
css_length bottom_left_x;
css_length bottom_left_y;
- css_border_radius()
- {
-
- }
+ css_border_radius() = default;
css_border_radius(const css_border_radius& val)
{
@@ -219,18 +194,8 @@ namespace litehtml
bottom_right_y = val.bottom_right_y;
}
- css_border_radius& operator=(const css_border_radius& val)
- {
- top_left_x = val.top_left_x;
- top_left_y = val.top_left_y;
- top_right_x = val.top_right_x;
- top_right_y = val.top_right_y;
- bottom_left_x = val.bottom_left_x;
- bottom_left_y = val.bottom_left_y;
- bottom_right_x = val.bottom_right_x;
- bottom_right_y = val.bottom_right_y;
- return *this;
- }
+ css_border_radius& operator=(const css_border_radius& val) = default;
+
border_radiuses calc_percents(int width, int height) const
{
border_radiuses ret;
@@ -271,15 +236,7 @@ namespace litehtml
radius = val.radius;
}
- css_borders& operator=(const css_borders& val)
- {
- left = val.left;
- right = val.right;
- top = val.top;
- bottom = val.bottom;
- radius = val.radius;
- return *this;
- }
+ css_borders& operator=(const css_borders& val) = default;
string to_string() const
{
return "left: " + left.to_string() +
@@ -321,15 +278,7 @@ namespace litehtml
return left.width != 0 || right.width != 0 || top.width != 0 || bottom.width != 0;
}
- borders& operator=(const borders& val)
- {
- left = val.left;
- right = val.right;
- top = val.top;
- bottom = val.bottom;
- radius = val.radius;
- return *this;
- }
+ borders& operator=(const borders& val) = default;
borders& operator=(const css_borders& val)
{
diff --git a/libs/litehtml/include/litehtml/css_length.h b/libs/litehtml/include/litehtml/css_length.h
index ae787105af..235ff54580 100644
--- a/libs/litehtml/include/litehtml/css_length.h
+++ b/libs/litehtml/include/litehtml/css_length.h
@@ -2,9 +2,22 @@
#define LH_CSS_LENGTH_H
#include "types.h"
+#include "css_tokenizer.h"
namespace litehtml
{
+ // from_token options (flags)
+ enum {
+ f_length = 1, // <length> (includes unitless zero)
+ f_percentage = 2, // <percentage>
+ f_length_percentage = f_length | f_percentage, // <length-percentage>
+ f_number = 4, // <number>
+ f_integer = 8, // <integer>
+ f_positive = 16 // ⩾0 (non-negative)
+ };
+
+ // <length> | <percentage> | <number> | auto | none | normal
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/length
class css_length
{
union
@@ -27,12 +40,11 @@ namespace litehtml
float val() const;
css_units units() const;
int calc_percent(int width) const;
- void fromString(const string& str, const string& predefs = "", int defValue = 0);
- static css_length from_string(const string& str, const string& predefs = "", int defValue = 0);
+ bool from_token(const css_token& token, int options, const string& predefined_keywords = "");
string to_string() const;
};
- using length_vector = std::vector<css_length>;
+ using length_vector = vector<css_length>;
// css_length inlines
diff --git a/libs/litehtml/include/litehtml/css_margins.h b/libs/litehtml/include/litehtml/css_margins.h
index 17dc7698da..f23ea64abb 100644
--- a/libs/litehtml/include/litehtml/css_margins.h
+++ b/libs/litehtml/include/litehtml/css_margins.h
@@ -22,14 +22,7 @@ namespace litehtml
bottom = val.bottom;
}
- css_margins& operator=(const css_margins& val)
- {
- left = val.left;
- right = val.right;
- top = val.top;
- bottom = val.bottom;
- return *this;
- }
+ css_margins& operator=(const css_margins& val) = default;
string to_string() const
{
diff --git a/libs/litehtml/include/litehtml/css_offsets.h b/libs/litehtml/include/litehtml/css_offsets.h
index 5ab175ce26..bff3c8711d 100644
--- a/libs/litehtml/include/litehtml/css_offsets.h
+++ b/libs/litehtml/include/litehtml/css_offsets.h
@@ -22,14 +22,7 @@ namespace litehtml
bottom = val.bottom;
}
- css_offsets& operator=(const css_offsets& val)
- {
- left = val.left;
- top = val.top;
- right = val.right;
- bottom = val.bottom;
- return *this;
- }
+ css_offsets& operator=(const css_offsets& val) = default;
string to_string() const
{
diff --git a/libs/litehtml/include/litehtml/css_properties.h b/libs/litehtml/include/litehtml/css_properties.h
index d6acc4419a..b7f8e7e784 100644
--- a/libs/litehtml/include/litehtml/css_properties.h
+++ b/libs/litehtml/include/litehtml/css_properties.h
@@ -48,7 +48,7 @@ namespace litehtml
uint_ptr m_font;
css_length m_font_size;
string m_font_family;
- font_weight m_font_weight;
+ css_length m_font_weight;
font_style m_font_style;
string m_text_decoration;
font_metrics m_font_metrics;
@@ -78,6 +78,7 @@ namespace litehtml
void compute_font(const html_tag* el, const std::shared_ptr<document>& doc);
void compute_background(const html_tag* el, const std::shared_ptr<document>& doc);
void compute_flex(const html_tag* el, const std::shared_ptr<document>& doc);
+ web_color get_color_property(const html_tag* el, string_id name, bool inherited, web_color default_value, uint_ptr member_offset) const;
public:
css_properties() :
diff --git a/libs/litehtml/include/litehtml/css_selector.h b/libs/litehtml/include/litehtml/css_selector.h
index 4fe7db9e50..042f1691e4 100644
--- a/libs/litehtml/include/litehtml/css_selector.h
+++ b/libs/litehtml/include/litehtml/css_selector.h
@@ -3,6 +3,7 @@
#include "style.h"
#include "media_query.h"
+#include "css_tokenizer.h"
namespace litehtml
{
@@ -121,105 +122,92 @@ namespace litehtml
{
select_class,
select_id,
-
- select_exists,
- select_equal,
- select_contain_str,
- select_start_str,
- select_end_str,
-
+ select_attr,
select_pseudo_class,
select_pseudo_element,
};
+ // https://www.w3.org/TR/selectors-4/#attribute-selectors
+ enum attr_matcher : char
+ {
+ attribute_exists = 0,
+ attribute_equals = '=',
+ attribute_contains_string = '*', // *=
+ attribute_contains_word = '~', // ~=
+ attribute_starts_with_string = '^', // ^=
+ attribute_starts_with_string_hyphen = '|', // |=
+ attribute_ends_with_string = '$', // $=
+ };
+
//////////////////////////////////////////////////////////////////////////
- class css_element_selector;
+ class css_selector;
+ class html_tag;
+ // <subclass-selector> | <pseudo-element-selector>
+ // = <id-selector> | <class-selector> | <attribute-selector> | <pseudo-class-selector> | <pseudo-element-selector>
struct css_attribute_selector
{
- typedef std::vector<css_attribute_selector> vector;
+ using vector = std::vector<css_attribute_selector>;
attr_select_type type;
- string_id name; // .name, #name, [name], :name
- string val; // [name=val], :lang(val)
+ string_id prefix; // [prefix|name]
+ string_id name; // .name, #name, [name], :name
+ string value; // [name=value], :lang(value)
+
+ attr_matcher matcher; // <attr-matcher> = ~= |= ^= $= *=
+ bool caseless_match; // value is matched ASCII case-insensitively
- std::shared_ptr<css_element_selector> sel; // :not(sel)
- int a, b; // :nth-child(an+b)
+ std::vector<shared_ptr<css_selector>> selector_list; // :not(selector_list)
+ int a, b; // :nth-child(an+b of selector_list)
- css_attribute_selector()
- {
- type = select_class;
- name = empty_id;
- a = b = 0;
- }
+ css_attribute_selector(attr_select_type type = select_class, string name = "")
+ : type(type), prefix(empty_id), name(_id(name)), matcher(), caseless_match(0), a(0), b(0) {}
+
+ operator bool() const { return name != empty_id; }
};
//////////////////////////////////////////////////////////////////////////
- class css_element_selector
+ class css_element_selector // compound selector: div.class:hover
{
public:
- string_id m_tag;
- css_attribute_selector::vector m_attrs;
+ using ptr = shared_ptr<css_element_selector>;
public:
-
- void parse(const string& txt);
- static void parse_nth_child_params(const string& param, int& num, int& off);
+ string_id m_prefix;
+ string_id m_tag;
+ css_attribute_selector::vector m_attrs; // subclass and pseudo-element selectors
};
//////////////////////////////////////////////////////////////////////////
enum css_combinator
{
- combinator_descendant,
- combinator_child,
- combinator_adjacent_sibling,
- combinator_general_sibling
+ combinator_descendant = ' ',
+ combinator_child = '>',
+ combinator_adjacent_sibling = '+',
+ combinator_general_sibling = '~'
};
//////////////////////////////////////////////////////////////////////////
- class css_selector
+ class css_selector // complex selector: div + p
{
public:
- typedef std::shared_ptr<css_selector> ptr;
- typedef std::vector<css_selector::ptr> vector;
- public:
- selector_specificity m_specificity;
- css_element_selector m_right;
- css_selector::ptr m_left;
- css_combinator m_combinator;
- style::ptr m_style;
- int m_order;
- media_query_list::ptr m_media_query;
- public:
- explicit css_selector(const media_query_list::ptr& media = nullptr)
- {
- m_media_query = media;
- m_combinator = combinator_descendant;
- m_order = 0;
- }
+ using ptr = shared_ptr<css_selector>;
+ using vector = std::vector<css_selector::ptr>;
- ~css_selector() = default;
-
- css_selector(const css_selector& val)
- {
- m_right = val.m_right;
- if(val.m_left)
- {
- m_left = std::make_shared<css_selector>(*val.m_left);
- } else
- {
- m_left = nullptr;
- }
- m_combinator = val.m_combinator;
- m_specificity = val.m_specificity;
- m_order = val.m_order;
- m_media_query = val.m_media_query;
- }
+ public:
+ selector_specificity m_specificity;
+ int m_order = 0;
+ css_selector::ptr m_left;
+ css_element_selector m_right;
+ css_combinator m_combinator = combinator_descendant;
+ media_query_list_list::ptr m_media_query;
+ style::ptr m_style;
- bool parse(const string& text);
+ public:
+ bool parse(const string& text, document_mode mode);
void calc_specificity();
bool is_media_valid() const;
void add_media_to_doc(document* doc) const;
@@ -281,20 +269,16 @@ namespace litehtml
m_used = used;
m_selector = selector;
}
+ };
- used_selector(const used_selector& val)
- {
- m_used = val.m_used;
- m_selector = val.m_selector;
- }
- used_selector& operator=(const used_selector& val)
- {
- m_used = val.m_used;
- m_selector = val.m_selector;
- return *this;
- }
+ enum {
+ strict_mode = 0,
+ forgiving_mode = 1,
+ forbid_pseudo_elements = 1 << 1,
};
+
+ css_selector::vector parse_selector_list(const css_token_vector& tokens, int options, document_mode mode);
}
#endif // LH_CSS_SELECTOR_H
diff --git a/libs/litehtml/include/litehtml/document.h b/libs/litehtml/include/litehtml/document.h
index 4871fc154f..3f94565655 100644
--- a/libs/litehtml/include/litehtml/document.h
+++ b/libs/litehtml/include/litehtml/document.h
@@ -25,28 +25,21 @@ namespace litehtml
baseurl = url ? url : "";
media = media_str ? media_str : "";
}
-
- css_text(const css_text& val)
- {
- text = val.text;
- baseurl = val.baseurl;
- media = val.media;
- }
};
- class dumper
- {
- public:
- virtual ~dumper() {}
- virtual void begin_node(const string& descr) = 0;
- virtual void end_node() = 0;
- virtual void begin_attrs_group(const string& descr) = 0;
- virtual void end_attrs_group() = 0;
- virtual void add_attr(const string& name, const string& value) = 0;
- };
+ class dumper
+ {
+ public:
+ virtual ~dumper() {}
+ virtual void begin_node(const string& descr) = 0;
+ virtual void end_node() = 0;
+ virtual void begin_attrs_group(const string& descr) = 0;
+ virtual void end_attrs_group() = 0;
+ virtual void add_attr(const string& name, const string& value) = 0;
+ };
class html_tag;
- class render_item;
+ class render_item;
class document : public std::enable_shared_from_this<document>
{
@@ -61,30 +54,31 @@ namespace litehtml
css_text::vector m_css;
litehtml::css m_styles;
litehtml::web_color m_def_color;
- litehtml::css m_master_css;
- litehtml::css m_user_css;
+ litehtml::css m_master_css;
+ litehtml::css m_user_css;
litehtml::size m_size;
litehtml::size m_content_size;
position::vector m_fixed_boxes;
- media_query_list::vector m_media_lists;
element::ptr m_over_element;
- std::list<std::shared_ptr<render_item>> m_tabular_elements;
+ std::list<shared_ptr<render_item>> m_tabular_elements;
+ media_query_list_list::vector m_media_lists;
media_features m_media;
string m_lang;
string m_culture;
string m_text;
+ document_mode m_mode = no_quirks_mode;
public:
document(document_container* objContainer);
virtual ~document();
document_container* container() { return m_container; }
+ document_mode mode() const { return m_mode; }
uint_ptr get_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm);
int render(int max_width, render_type rt = render_all);
void draw(uint_ptr hdc, int x, int y, const position* clip);
web_color get_def_color() { return m_def_color; }
- int to_pixels(const char* str, int fontSize, bool* is_percent = nullptr) const;
- void cvt_units(css_length& val, int fontSize, int size = 0) const;
- int to_pixels(const css_length& val, int fontSize, int size = 0) const;
+ void cvt_units(css_length& val, const font_metrics& metrics, int size) const;
+ int to_pixels(const css_length& val, const font_metrics& metrics, int size) const;
int width() const;
int height() const;
int content_width() const;
@@ -96,9 +90,10 @@ namespace litehtml
bool on_mouse_leave(position::vector& redraw_boxes);
element::ptr create_element(const char* tag_name, const string_map& attributes);
element::ptr root();
+ std::shared_ptr<render_item> root_render();
void get_fixed_boxes(position::vector& fixed_boxes);
void add_fixed_box(const position& pos);
- void add_media_list(const media_query_list::ptr& list);
+ void add_media_list(media_query_list_list::ptr list);
bool media_changed();
bool lang_changed();
bool match_lang(const string& lang);
@@ -130,6 +125,12 @@ namespace litehtml
{
return m_root;
}
+
+ inline std::shared_ptr<render_item> document::root_render()
+ {
+ return m_root_render;
+ }
+
inline void document::add_tabular(const std::shared_ptr<render_item>& el)
{
m_tabular_elements.push_back(el);
diff --git a/libs/litehtml/include/litehtml/document_container.h b/libs/litehtml/include/litehtml/document_container.h
index 1fc4713f9b..395c6cd1a7 100644
--- a/libs/litehtml/include/litehtml/document_container.h
+++ b/libs/litehtml/include/litehtml/document_container.h
@@ -22,6 +22,12 @@ namespace litehtml
int index;
uint_ptr font;
};
+
+ enum mouse_event
+ {
+ mouse_event_enter,
+ mouse_event_leave,
+ };
// call back interface to draw text, images and other elements
class document_container
@@ -48,6 +54,7 @@ namespace litehtml
virtual void set_base_url(const char* base_url) = 0;
virtual void link(const std::shared_ptr<litehtml::document>& doc, const litehtml::element::ptr& el) = 0;
virtual void on_anchor_click(const char* url, const litehtml::element::ptr& el) = 0;
+ virtual void on_mouse_event(const litehtml::element::ptr& el, litehtml::mouse_event event) = 0;
virtual void set_cursor(const char* cursor) = 0;
virtual void transform_text(litehtml::string& text, litehtml::text_transform tt) = 0;
virtual void import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl) = 0;
@@ -64,7 +71,7 @@ namespace litehtml
virtual void split_text(const char* text, const std::function<void(const char*)>& on_word, const std::function<void(const char*)>& on_space);
protected:
- ~document_container() = default;
+ virtual ~document_container() = default;
};
}
diff --git a/libs/litehtml/include/litehtml/el_break.h b/libs/litehtml/include/litehtml/el_break.h
index 2a4d8fe45b..81f38fec04 100644
--- a/libs/litehtml/include/litehtml/el_break.h
+++ b/libs/litehtml/include/litehtml/el_break.h
@@ -11,7 +11,7 @@ namespace litehtml
explicit el_break(const std::shared_ptr<litehtml::document>& doc);
bool is_break() const override;
- };
+ };
}
#endif // LH_EL_BREAK_H
diff --git a/libs/litehtml/include/litehtml/el_comment.h b/libs/litehtml/include/litehtml/el_comment.h
index 746238e9aa..379318ffbe 100644
--- a/libs/litehtml/include/litehtml/el_comment.h
+++ b/libs/litehtml/include/litehtml/el_comment.h
@@ -14,11 +14,11 @@ namespace litehtml
bool is_comment() const override;
void get_text(string& text) override;
void set_data(const char* data) override;
- std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& /*parent_ri*/) override
- {
- // Comments are not rendered
- return nullptr;
- }
+ std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& /*parent_ri*/) override
+ {
+ // Comments are not rendered
+ return nullptr;
+ }
};
}
diff --git a/libs/litehtml/include/litehtml/el_space.h b/libs/litehtml/include/litehtml/el_space.h
index 46a292ebcb..53c170f13a 100644
--- a/libs/litehtml/include/litehtml/el_space.h
+++ b/libs/litehtml/include/litehtml/el_space.h
@@ -13,8 +13,8 @@ namespace litehtml
bool is_white_space() const override;
bool is_break() const override;
- bool is_space() const override;
- string dump_get_name() override;
+ bool is_space() const override;
+ string dump_get_name() override;
};
}
diff --git a/libs/litehtml/include/litehtml/el_text.h b/libs/litehtml/include/litehtml/el_text.h
index 4b8a442f38..ea54cc9c66 100644
--- a/libs/litehtml/include/litehtml/el_text.h
+++ b/libs/litehtml/include/litehtml/el_text.h
@@ -18,11 +18,11 @@ namespace litehtml
void get_text(string& text) override;
void compute_styles(bool recursive) override;
- bool is_text() const override { return true; }
+ bool is_text() const override { return true; }
- void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override;
- string dump_get_name() override;
- std::vector<std::tuple<string, string>> dump_get_attrs() override;
+ void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override;
+ string dump_get_name() override;
+ std::vector<std::tuple<string, string>> dump_get_attrs() override;
protected:
void get_content_size(size& sz, int max_width) override;
};
diff --git a/libs/litehtml/include/litehtml/element.h b/libs/litehtml/include/litehtml/element.h
index b1aa8e30ae..67dd1ae251 100644
--- a/libs/litehtml/include/litehtml/element.h
+++ b/libs/litehtml/include/litehtml/element.h
@@ -105,6 +105,7 @@ namespace litehtml
virtual void get_text(string& text);
virtual void parse_attributes();
+ virtual int select(const css_selector::vector& selector_list, bool apply_pseudo = true);
virtual int select(const string& selector);
virtual int select(const css_selector& selector, bool apply_pseudo = true);
virtual int select(const css_element_selector& selector, bool apply_pseudo = true);
@@ -113,8 +114,8 @@ namespace litehtml
virtual element::ptr find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr);
virtual element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr);
virtual void get_content_size(size& sz, int max_width);
- virtual bool is_nth_child(const element::ptr& el, int num, int off, bool of_type) const;
- virtual bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const;
+ virtual bool is_nth_child(const element::ptr& el, int num, int off, bool of_type, const css_selector::vector& selector_list = {}) const;
+ virtual bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type, const css_selector::vector& selector_list = {}) const;
virtual bool is_only_child(const element::ptr& el, bool of_type) const;
virtual void add_style(const style& style);
virtual const background* get_background(bool own_only = false);
diff --git a/libs/litehtml/include/litehtml/encodings.h b/libs/litehtml/include/litehtml/encodings.h
index 82b0323b44..2dd9d5e0f5 100644
--- a/libs/litehtml/include/litehtml/encodings.h
+++ b/libs/litehtml/include/litehtml/encodings.h
@@ -84,6 +84,7 @@ encoding get_encoding(string label);
encoding extract_encoding_from_meta_element(string str);
void decode(string input, encoding coding, string& output);
+string decode(string input, encoding coding);
} // namespace litehtml
diff --git a/libs/litehtml/include/litehtml/gradient.h b/libs/litehtml/include/litehtml/gradient.h
index 782a764e28..6313eb75b2 100644
--- a/libs/litehtml/include/litehtml/gradient.h
+++ b/libs/litehtml/include/litehtml/gradient.h
@@ -1,13 +1,204 @@
#ifndef LITEHTML_GRADIENT_H
#define LITEHTML_GRADIENT_H
-#include "background.h"
-
namespace litehtml
{
- void parse_linear_gradient(const std::string& gradient_str, document_container *container, background_gradient& grad);
- void parse_radial_gradient(const std::string& gradient_str, document_container *container, background_gradient& grad);
- void parse_conic_gradient(const std::string& gradient_str, document_container *container, background_gradient& grad);
+ enum gradient_side
+ {
+ gradient_side_none = 0,
+ gradient_side_left = 0x01,
+ gradient_side_right = 0x02,
+ gradient_side_top = 0x04,
+ gradient_side_bottom = 0x08,
+ gradient_side_x_center = 0x10,
+ gradient_side_y_center = 0x20,
+ gradient_side_x_length = 0x40,
+ gradient_side_y_length = 0x80,
+ };
+ static_assert(gradient_side_left == (1 << background_position_left), "parse_bg_position is also used to parse radial gradient position");
+
+ enum radial_shape_t
+ {
+ radial_shape_none,
+ radial_shape_circle,
+ radial_shape_ellipse,
+ };
+
+#define radial_extent_strings "closest-corner;closest-side;farthest-corner;farthest-side"
+ enum radial_extent_t
+ {
+ radial_extent_none,
+ radial_extent_closest_corner,
+ radial_extent_closest_side,
+ radial_extent_farthest_corner,
+ radial_extent_farthest_side,
+ };
+
+#define color_space_strings \
+ "srgb;"\
+ "srgb-linear;"\
+ "display-p3;"\
+ "a98-rgb;"\
+ "prophoto-rgb;"\
+ "rec2020;"\
+ "lab;"\
+ "oklab;"\
+ "xyz;"\
+ "xyz-d50;"\
+ "xyz-d65;"\
+ "hsl;"\
+ "hwb;"\
+ "lch;"\
+ "oklch"
+
+ enum color_space_t
+ {
+ color_space_none,
+
+ // rectangular-color-space
+ color_space_srgb,
+ color_space_srgb_linear,
+ color_space_display_p3,
+ color_space_a98_rgb,
+ color_space_prophoto_rgb,
+ color_space_rec2020,
+ color_space_lab,
+ color_space_oklab,
+ color_space_xyz,
+ color_space_xyz_d50,
+ color_space_xyz_d65,
+
+ // polar-color-space
+ color_space_hsl, color_space_polar_start = color_space_hsl,
+ color_space_hwb,
+ color_space_lch,
+ color_space_oklch,
+ };
+
+#define hue_interpolation_strings "shorter;longer;increasing;decreasing"
+ enum hue_interpolation_t
+ {
+ hue_interpolation_none,
+ hue_interpolation_shorter,
+ hue_interpolation_longer,
+ hue_interpolation_increasing,
+ hue_interpolation_decreasing
+ };
+
+ class gradient
+ {
+ public:
+ // https://drafts.csswg.org/css-images-4/#typedef-color-stop-list
+ // color_stop represents <linear-color-stop> | <linear-color-hint> | <angular-color-stop> | <angular-color-hint>
+ // <linear-color-stop> = <color> <length-percentage>{1,2}?
+ // <linear-color-hint> = <length-percentage>
+ // <angular-color-stop> = <color> <angle-percentage>{1,2}?
+ // <angular-color-hint> = <angle-percentage>
+ // If two lengths/angles are specified they create two color-stops with the same color.
+ class color_stop
+ {
+ public:
+ bool is_color_hint = false;
+ web_color color;
+ optional<css_length> length;
+ optional<float> angle;
+
+ color_stop() {}
+ color_stop(web_color color) : color(color) {}
+ color_stop(web_color color, css_length length) : color(color), length(length) {}
+ color_stop(web_color color, float angle) : color(color), angle(angle) {}
+ color_stop(css_length length) : is_color_hint(true), length(length) {}
+ color_stop(float angle) : is_color_hint(true), angle(angle) {}
+ };
+
+ string_id m_type;
+ uint32_t m_side;
+ float angle;
+ vector<color_stop> m_colors;
+ css_length position_x;
+ css_length position_y;
+ radial_shape_t radial_shape;
+ radial_extent_t radial_extent;
+ css_length radial_radius_x;
+ css_length radial_radius_y;
+ float conic_from_angle;
+ color_space_t color_space;
+ hue_interpolation_t hue_interpolation;
+
+
+ explicit gradient(string_id type = empty_id)
+ {
+ m_type = type;
+
+ // linear gradient: m_side default is gradient_side_none (use angle)
+ // radial,conic gradient: m_side default is gradient_side_x_center | gradient_side_y_center (see parse_gradient)
+ m_side = gradient_side_none;
+ // linear gradient angle, used when m_side == gradient_side_none
+ angle = 180; // to bottom
+ // radial,conic position (together with m_side)
+ position_x.predef(0);
+ position_y.predef(0);
+
+ // actual default depends on the number of radii provided, see parse_radial_gradient_shape_size_position_interpolation
+ radial_shape = radial_shape_ellipse;
+
+ // <radial-size> https://drafts.csswg.org/css-images-3/#valdef-radial-gradient-radial-size
+ // if radius is specified radial_extent will be set to none, see parse_radial_size
+ radial_extent = radial_extent_farthest_corner;
+ radial_radius_x.predef(0);
+ radial_radius_y.predef(0);
+
+ conic_from_angle = 0;
+
+ // If the host syntax does not define what color space interpolation should take place in, it defaults to Oklab.
+ color_space = color_space_oklab;
+ // Unless otherwise specified, if no specific hue interpolation algorithm is selected by the host syntax, the default is shorter.
+ hue_interpolation = hue_interpolation_shorter;
+ }
+
+ bool is_empty() const
+ {
+ return m_type == empty_id || m_colors.empty();
+ }
+
+ bool is_linear() const { return m_type == _linear_gradient_ || m_type == _repeating_linear_gradient_; }
+ bool is_radial() const { return m_type == _radial_gradient_ || m_type == _repeating_radial_gradient_; }
+ bool is_conic() const { return m_type == _conic_gradient_ || m_type == _repeating_conic_gradient_; }
+
+ static gradient transparent;
+ };
+
+ class image
+ {
+ public:
+ enum type
+ {
+ type_none,
+ type_url,
+ type_gradient,
+ };
+ type type;
+ string url;
+ gradient m_gradient;
+
+ image() : type(type_none) {}
+
+ bool is_empty() const
+ {
+ switch (type)
+ {
+ case type_none:
+ return true;
+ case type_url:
+ return url.empty();
+ case type_gradient:
+ return m_gradient.is_empty();
+ }
+ return true;
+ }
+ };
+
+ bool parse_gradient(const css_token& token, gradient& gradient, document_container* container);
}
#endif //LITEHTML_GRADIENT_H
diff --git a/libs/litehtml/include/litehtml/html.h b/libs/litehtml/include/litehtml/html.h
index 0bde45d2bf..cd0500aabe 100644
--- a/libs/litehtml/include/litehtml/html.h
+++ b/libs/litehtml/include/litehtml/html.h
@@ -1,43 +1,127 @@
#ifndef LH_HTML_H
#define LH_HTML_H
-#include <stdlib.h>
-#include <string>
-#include <ctype.h>
-#include <vector>
-#include <map>
+#include <cstdlib>
+#include <cmath>
+#include <cctype>
#include <cstring>
#include <algorithm>
#include <functional>
#include "os_types.h"
-#include "string_id.h"
#include "types.h"
+#include "string_id.h"
#include "utf8_strings.h"
#include "background.h"
#include "borders.h"
#include "web_color.h"
#include "media_query.h"
+#include "html_microsyntaxes.h"
#include "html_tag.h"
#include "document_container.h"
#include "document.h"
namespace litehtml
{
- string& trim(string &s, const string& chars_to_trim = " \n\r\f\t");
- void lcase(string &s);
+ const string whitespace = " \n\r\t\f";
+ string& trim(string& s, const string& chars_to_trim = whitespace);
+ string trim(const string& s, const string& chars_to_trim = whitespace);
+ string& lcase(string& s);
int value_index(const string& val, const string& strings, int defValue = -1, char delim = ';');
- string index_value(int index, const string& strings, char delim = ';');
+ string index_value(int index, const string& strings, char delim = ';');
bool value_in_list(const string& val, const string& strings, char delim = ';');
- string::size_type find_close_bracket(const string &s, string::size_type off, char open_b = '(', char close_b = ')');
- void split_string(const string& str, string_vector& tokens, const string& delims, const string& delims_preserve = "", const string& quote = "\"");
+ string::size_type find_close_bracket(const string& s, string::size_type off, char open_b = '(', char close_b = ')');
+ void split_string(const string& str, string_vector& tokens, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"");
+ string_vector split_string(const string& str, const string& delims = whitespace, const string& delims_preserve = "", const string& quote = "\"");
void join_string(string& str, const string_vector& tokens, const string& delims);
- double t_strtod(const char* string, char** endPtr = nullptr);
- string get_escaped_string(const string& in_str);
+ double t_strtod(const char* string, char** endPtr = nullptr);
+ string get_escaped_string(const string& in_str);
+
+ template<typename X, typename A>
+ bool is_one_of(X x, A a)
+ {
+ return x == a;
+ }
+ template<typename X, typename A, typename... AA>
+ bool is_one_of(X x, A a, AA... aa)
+ {
+ return x == a || is_one_of(x, aa...);
+ }
+ template<class T>
+ const T& at(const vector<T>& vec, int index /*may be negative*/)
+ {
+ static T invalid_item; // T's default constructor must create invalid item
+ if (index < 0) index += (int)vec.size();
+ return index >= 0 && index < (int)vec.size() ? vec[index] : invalid_item;
+ }
+ template<class Map, class Key>
+ auto at(const Map& map, Key key)
+ {
+ static typename Map::mapped_type invalid_value; // mapped_type's default constructor must create invalid item
+ auto it = map.find(key);
+ return it != map.end() ? it->second : invalid_value;
+ }
+ template<typename T>
+ vector<T> slice(const vector<T>& vec, int index, int count = -1)
+ {
+ if (count == -1) count = (int)vec.size() - index;
+ return {vec.begin() + index, vec.begin() + index + count};
+ }
+ template<class C> // C == vector or string
+ void remove(C& vec, int index /*may be negative*/, int count = 1)
+ {
+ if (index < 0) index += (int)vec.size();
+
+ if (!(index >= 0 && index < (int)vec.size()))
+ return;
+
+ count = min(count, (int)vec.size() - index);
+ if (count <= 0) return;
+
+ vec.erase(vec.begin() + index, vec.begin() + index + count);
+ }
+ template<class T>
+ void insert(vector<T>& vec, int index, const vector<T>& x)
+ {
+ vec.insert(vec.begin() + index, x.begin(), x.end());
+ }
+ template<class T>
+ vector<T>& operator+=(vector<T>& vec, const vector<T>& x)
+ {
+ vec.insert(vec.end(), x.begin(), x.end());
+ return vec;
+ }
+ template<class C, class T>
+ bool contains(const C& coll, const T& item)
+ {
+ return std::find(coll.begin(), coll.end(), item) != coll.end();
+ }
+ inline bool contains(const string& str, const string& substr)
+ {
+ return str.find(substr) != string::npos;
+ }
+ template<class C> void sort(C& coll) { std::sort(coll.begin(), coll.end()); }
int t_strcasecmp(const char *s1, const char *s2);
int t_strncasecmp(const char *s1, const char *s2, size_t n);
+ inline bool equal_i(const string& s1, const string& s2)
+ {
+ if (s1.size() != s2.size()) return false;
+ return t_strncasecmp(s1.c_str(), s2.c_str(), s1.size()) == 0;
+ }
+ inline bool match(const string& str, int index /*may be negative*/, const string& substr)
+ {
+ if (index < 0) index += (int)str.size();
+ if (index < 0) return false;
+ return str.substr(index, substr.size()) == substr;
+ }
+ inline bool match_i(const string& str, int index /*may be negative*/, const string& substr)
+ {
+ if (index < 0) index += (int)str.size();
+ if (index < 0) return false;
+ return equal_i(str.substr(index, substr.size()), substr);
+ }
- bool is_number(const string& string, const bool allow_dot = 1);
+ bool is_number(const string& string, bool allow_dot = true);
// https://infra.spec.whatwg.org/#ascii-whitespace
inline bool is_whitespace(int c)
@@ -45,15 +129,11 @@ namespace litehtml
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f';
}
- inline int t_isdigit(int c)
- {
- return (c >= '0' && c <= '9');
- }
-
inline int t_isalpha(int c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
}
+ const auto is_letter = t_isalpha;
inline int t_tolower(int c)
{
@@ -64,6 +144,29 @@ namespace litehtml
{
return t_tolower(c);
}
+ inline string lowcase(string str)
+ {
+ for (char& c : str) c = (char)t_tolower(c);
+ return str;
+ }
+
+ inline int t_isdigit(int c)
+ {
+ return (c >= '0' && c <= '9');
+ }
+ const auto is_digit = t_isdigit;
+
+ inline bool is_hex_digit(int ch) {
+ return is_digit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
+ }
+
+ inline int digit_value(int ch) {
+ return is_digit(ch) ? ch - '0' : lowcase(ch) - 'a' + 10;
+ }
+
+ inline bool is_surrogate(int ch) {
+ return ch >= 0xD800 && ch < 0xE000;
+ }
inline int round_f(float val)
{
diff --git a/libs/litehtml/include/litehtml/html_tag.h b/libs/litehtml/include/litehtml/html_tag.h
index 4a7a9a78dc..63cd64498a 100644
--- a/libs/litehtml/include/litehtml/html_tag.h
+++ b/libs/litehtml/include/litehtml/html_tag.h
@@ -10,7 +10,6 @@
#include "stylesheet.h"
#include "line_box.h"
#include "table.h"
-#include <assert.h>
namespace litehtml
{
@@ -22,31 +21,33 @@ namespace litehtml
friend class table_grid;
friend class line_box;
public:
- typedef std::shared_ptr<html_tag> ptr;
+ typedef shared_ptr<html_tag> ptr;
protected:
string_id m_tag;
string_id m_id;
string_vector m_str_classes;
- std::vector<string_id> m_classes;
- litehtml::style m_style;
+ vector<string_id> m_classes;
+ style m_style;
string_map m_attrs;
- std::vector<string_id> m_pseudo_classes;
+ vector<string_id> m_pseudo_classes;
void select_all(const css_selector& selector, elements_list& res) override;
public:
- explicit html_tag(const std::shared_ptr<document>& doc);
+ explicit html_tag(const shared_ptr<document>& doc);
// constructor for anonymous wrapper boxes
explicit html_tag(const element::ptr& parent, const string& style = "display: block");
- bool appendChild(const element::ptr &el) override;
- bool removeChild(const element::ptr &el) override;
+ bool appendChild(const element::ptr& el) override;
+ bool removeChild(const element::ptr& el) override;
void clearRecursive() override;
string_id tag() const override;
string_id id() const override;
const char* get_tagName() const override;
void set_tagName(const char* tag) override;
void set_data(const char* data) override;
+ const vector<string_id>& classes() const { return m_classes; }
+ const string_vector& str_classes() const { return m_str_classes; }
void set_attr(const char* name, const char* val) override;
const char* get_attr(const char* name, const char* def = nullptr) const override;
@@ -72,10 +73,11 @@ namespace litehtml
template<class Type>
const Type& get_property(string_id name, bool inherited, const Type& default_value, uint_ptr css_properties_member_offset) const;
- string get_custom_property(string_id name, const string& default_value) const;
+ bool get_custom_property(string_id name, css_token_vector& result) const;
elements_list& children();
+ int select(const css_selector::vector& selector_list, bool apply_pseudo = true) override;
int select(const string& selector) override;
int select(const css_selector& selector, bool apply_pseudo = true) override;
int select(const css_element_selector& selector, bool apply_pseudo = true) override;
@@ -97,8 +99,8 @@ namespace litehtml
void get_content_size(size& sz, int max_width) override;
void add_style(const style& style) override;
- bool is_nth_child(const element::ptr& el, int num, int off, bool of_type) const override;
- bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const override;
+ bool is_nth_child(const element::ptr& el, int num, int off, bool of_type, const css_selector::vector& selector_list) const override;
+ bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type, const css_selector::vector& selector_list) const override;
bool is_only_child(const element::ptr& el, bool of_type) const override;
const background* get_background(bool own_only = false) override;
@@ -110,6 +112,11 @@ namespace litehtml
element::ptr get_element_before(const style& style, bool create);
element::ptr get_element_after(const style& style, bool create);
+ void map_to_pixel_length_property(string_id prop_name, string attr_value);
+ void map_to_pixel_length_property_with_default_value(string_id prop_name, string attr_value, int default_value);
+ void map_to_dimension_property(string_id prop_name, string attr_value);
+ void map_to_dimension_property_ignoring_zero(string_id prop_name, string attr_value);
+
private:
void handle_counter_properties();
@@ -119,7 +126,7 @@ namespace litehtml
/* Inline Functions */
/************************************************************************/
- inline elements_list& litehtml::html_tag::children()
+ inline elements_list& html_tag::children()
{
return m_children;
}
@@ -141,7 +148,6 @@ namespace litehtml
}
return default_value;
}
- assert(value.is<invalid>());
return default_value;
}
diff --git a/libs/litehtml/include/litehtml/line_box.h b/libs/litehtml/include/litehtml/line_box.h
index a1e4969c96..6e945c9fdc 100644
--- a/libs/litehtml/include/litehtml/line_box.h
+++ b/libs/litehtml/include/litehtml/line_box.h
@@ -46,6 +46,7 @@ namespace litehtml
line_box_item() : m_element(), m_rendered_min_width(0) {};
line_box_item(const line_box_item& el) = default;
line_box_item(line_box_item&&) = default;
+ virtual ~line_box_item();
int height() const { return right() - left(); }
const std::shared_ptr<render_item>& get_el() const { return m_element; }
@@ -67,6 +68,7 @@ namespace litehtml
position m_pos;
public:
explicit lbi_start(const std::shared_ptr<render_item>& element);
+ virtual ~lbi_start() override;
void place_to(int x, int y) override;
int width() const override;
@@ -83,6 +85,7 @@ namespace litehtml
{
public:
explicit lbi_end(const std::shared_ptr<render_item>& element);
+ virtual ~lbi_end() override;
void place_to(int x, int y) override;
int right() const override;
@@ -94,6 +97,7 @@ namespace litehtml
{
public:
explicit lbi_continue(const std::shared_ptr<render_item>& element);
+ virtual ~lbi_continue() override;
void place_to(int x, int y) override;
int right() const override;
diff --git a/libs/litehtml/include/litehtml/master_css.h b/libs/litehtml/include/litehtml/master_css.h
index 0e7b0ca4e3..ea532922d7 100644
--- a/libs/litehtml/include/litehtml/master_css.h
+++ b/libs/litehtml/include/litehtml/master_css.h
@@ -4,32 +4,31 @@ namespace litehtml{ const char* const master_css = R"##(
html {
- display: block;
- position: relative;
+ display: block;
}
head {
- display: none
+ display: none
}
meta {
- display: none
+ display: none
}
title {
- display: none
+ display: none
}
link {
- display: none
+ display: none
}
style {
- display: none
+ display: none
}
script {
- display: none
+ display: none
}
body {
@@ -157,29 +156,29 @@ img[align="left"]
}
hr {
- display: block;
- margin-top: 0.5em;
- margin-bottom: 0.5em;
- margin-left: auto;
- margin-right: auto;
- border-style: inset;
- border-width: 1px
+ display: block;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ margin-left: auto;
+ margin-right: auto;
+ border-style: inset;
+ border-width: 1px
}
/***************** TABLES ********************/
table {
- display: table;
- border-collapse: separate;
- border-spacing: 2px;
- border-top-color:gray;
- border-left-color:gray;
- border-bottom-color:black;
- border-right-color:black;
- font-size: medium;
- font-weight: normal;
- font-style: normal;
+ display: table;
+ border-collapse: separate;
+ border-spacing: 2px;
+ border-top-color:gray;
+ border-left-color:gray;
+ border-bottom-color:black;
+ border-right-color:black;
+ font-size: medium;
+ font-weight: normal;
+ font-style: normal;
}
tbody, tfoot, thead {
@@ -188,16 +187,16 @@ tbody, tfoot, thead {
}
tr {
- display: table-row;
- vertical-align: inherit;
- border-color: inherit;
+ display: table-row;
+ vertical-align: inherit;
+ border-color: inherit;
}
td, th {
- display: table-cell;
- vertical-align: inherit;
- border-width:1px;
- padding:1px;
+ display: table-cell;
+ vertical-align: inherit;
+ border-width:1px;
+ padding:1px;
}
th {
@@ -205,23 +204,23 @@ th {
}
table[border] {
- border-style:solid;
+ border-style:solid;
}
-table[border|=0] {
- border-style:none;
+table[border^="0"] {
+ border-style:none;
}
table[border] td, table[border] th {
- border-style:solid;
- border-top-color:black;
- border-left-color:black;
- border-bottom-color:gray;
- border-right-color:gray;
+ border-style:solid;
+ border-top-color:black;
+ border-left-color:black;
+ border-bottom-color:gray;
+ border-right-color:gray;
}
-table[border|=0] td, table[border|=0] th {
- border-style:none;
+table[border^="0"] td, table[border^="0"] th {
+ border-style:none;
}
table[align=left] {
@@ -246,70 +245,70 @@ td[nowrap], th[nowrap] {
}
tt, code, kbd, samp {
- font-family: monospace
+ font-family: monospace
}
pre, xmp, plaintext, listing {
- display: block;
- font-family: monospace;
- white-space: pre;
- margin: 1em 0
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ margin: 1em 0
}
/***************** LISTS ********************/
ul, menu, dir {
- display: block;
- list-style-type: disc;
- margin-top: 1em;
- margin-bottom: 1em;
- margin-left: 0;
- margin-right: 0;
- padding-left: 40px
+ display: block;
+ list-style-type: disc;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 40px
}
ol {
- display: block;
- list-style-type: decimal;
- margin-top: 1em;
- margin-bottom: 1em;
- margin-left: 0;
- margin-right: 0;
- padding-left: 40px
+ display: block;
+ list-style-type: decimal;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 40px
}
li {
- display: list-item;
+ display: list-item;
}
ul ul, ol ul {
- list-style-type: circle;
+ list-style-type: circle;
}
ol ol ul, ol ul ul, ul ol ul, ul ul ul {
- list-style-type: square;
+ list-style-type: square;
}
dd {
- display: block;
- margin-left: 40px;
+ display: block;
+ margin-left: 40px;
}
dl {
- display: block;
- margin-top: 1em;
- margin-bottom: 1em;
- margin-left: 0;
- margin-right: 0;
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
}
dt {
- display: block;
+ display: block;
}
ol ul, ul ol, ul ul, ol ol {
- margin-top: 0;
- margin-bottom: 0
+ margin-top: 0;
+ margin-bottom: 0
}
blockquote {
diff --git a/libs/litehtml/include/litehtml/media_query.h b/libs/litehtml/include/litehtml/media_query.h
index 4cb21fc2f6..94ed205e52 100644
--- a/libs/litehtml/include/litehtml/media_query.h
+++ b/libs/litehtml/include/litehtml/media_query.h
@@ -3,74 +3,113 @@
namespace litehtml
{
- struct media_query_expression
+ // https://drafts.csswg.org/mediaqueries/#evaluating
+ enum trilean
{
- typedef std::vector<media_query_expression> vector;
- media_feature feature;
- int val;
- int val2;
- bool check_as_bool;
-
- media_query_expression()
- {
- check_as_bool = false;
- feature = media_feature_none;
- val = 0;
- val2 = 0;
- }
+ False,
+ True,
+ Unknown
+ };
+ static_assert(False == false && True == true); // for casting bool to trilean
- bool check(const media_features& features) const;
+ inline trilean operator!(trilean x)
+ {
+ if (x == False) return True;
+ if (x == True) return False;
+ return Unknown;
+ }
+
+ inline trilean operator&&(trilean a, trilean b)
+ {
+ if (a == False || b == False) return False;
+ if (a == True && b == True) return True;
+ return Unknown;
+ }
+
+ inline trilean operator||(trilean a, trilean b)
+ {
+ if (a == True || b == True) return True;
+ if (a == False && b == False) return False;
+ return Unknown;
+ }
+
+
+ struct media_condition;
+
+ // <media-query> = <media-condition> | [ not | only ]? <media-type> [ and <media-condition-without-or> ]?
+ struct media_query
+ {
+ bool m_not = true;
+ media_type m_media_type = media_type_all;
+ vector<media_condition> m_conditions;
+
+ trilean check(const media_features& features) const;
};
- class media_query
+ struct media_in_parens;
+
+ // <media-condition> = not <media-in-parens> | <media-in-parens> [ [and <media-in-parens>]* | [or <media-in-parens>]* ]
+ struct media_condition
{
- public:
- typedef std::shared_ptr<media_query> ptr;
- typedef std::vector<media_query::ptr> vector;
- private:
- media_query_expression::vector m_expressions;
- bool m_not;
- media_type m_media_type;
- public:
- media_query();
- media_query(const media_query& val);
+ string_id op = _and_; // _not_ _and_ _or_
+ vector<media_in_parens> m_conditions;
+
+ trilean check(const media_features& features) const;
+ };
- static media_query::ptr create_from_string(const string& str, const std::shared_ptr<document>& doc);
+ // <media-feature> = ( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
+ // <mf-plain> = <mf-name> : <mf-value>
+ struct media_feature
+ {
+ string name;
+ float value = 0;
+ float value2 = 0;
+ short op = 0;
+ short op2 = 0;
+
+ bool verify_and_convert_units(string_id syntax, css_token val[2] = 0, css_token val2[2] = 0, shared_ptr<document> doc = 0);
+
+ bool compare(int x) const { return compare((float)x); }
+ bool compare(float x) const;
bool check(const media_features& features) const;
};
- class media_query_list
+ // <media-in-parens> = ( <media-condition> ) | <media-feature> | <general-enclosed>
+ struct unknown {}; // <general-enclosed>
+ struct media_in_parens : variant<media_condition, media_feature, unknown>
{
- public:
- typedef std::shared_ptr<media_query_list> ptr;
- typedef std::vector<media_query_list::ptr> vector;
- private:
- media_query::vector m_queries;
- bool m_is_used;
- public:
- media_query_list();
- media_query_list(const media_query_list& val);
+ using base::base; // inherit ctors
- static media_query_list::ptr create_from_string(const string& str, const std::shared_ptr<document>& doc);
- bool is_used() const;
- bool apply_media_features(const media_features& features); // returns true if the m_is_used changed
+ trilean check(const media_features& features) const;
};
- inline media_query_list::media_query_list(const media_query_list& val)
+ struct media_query_list
{
- m_is_used = val.m_is_used;
- m_queries = val.m_queries;
- }
+ vector<media_query> m_queries;
+ bool empty() const { return m_queries.empty(); }
+ bool check(const media_features& features) const;
+ };
+ media_query_list parse_media_query_list(const css_token_vector& tokens, shared_ptr<document> doc);
+ media_query_list parse_media_query_list(const string& str, shared_ptr<document> doc);
- inline media_query_list::media_query_list()
+
+ class media_query_list_list
{
- m_is_used = false;
- }
+ public:
+ using ptr = shared_ptr<media_query_list_list>;
+ using vector = std::vector<ptr>;
+ private:
+ std::vector<media_query_list> m_media_query_lists;
+ bool m_is_used = false;
+ public:
+ void add(const media_query_list& mq_list)
+ {
+ m_media_query_lists.push_back(mq_list);
+ }
+ bool is_used() const { return m_is_used; }
- inline bool media_query_list::is_used() const
- {
- return m_is_used;
- }
+ bool apply_media_features(const media_features& features); // returns true if the m_is_used changed
+ };
}
diff --git a/libs/litehtml/include/litehtml/num_cvt.h b/libs/litehtml/include/litehtml/num_cvt.h
index 0eaaa68868..bdfad8ecdb 100644
--- a/libs/litehtml/include/litehtml/num_cvt.h
+++ b/libs/litehtml/include/litehtml/num_cvt.h
@@ -1,8 +1,7 @@
#ifndef NUM_CVT_H
#define NUM_CVT_H
-#include <string>
-#include "os_types.h"
+#include "types.h"
namespace litehtml
{
diff --git a/libs/litehtml/include/litehtml/os_types.h b/libs/litehtml/include/litehtml/os_types.h
index bf674b25b5..7300a49fae 100644
--- a/libs/litehtml/include/litehtml/os_types.h
+++ b/libs/litehtml/include/litehtml/os_types.h
@@ -1,24 +1,8 @@
#ifndef LH_OS_TYPES_H
#define LH_OS_TYPES_H
-#include <string>
-#include <memory>
-#include <cstdint>
-
-namespace litehtml
-{
- using std::string;
- using std::shared_ptr;
- using std::make_shared;
- using uint_ptr = std::uintptr_t;
-
#if defined( WIN32 ) || defined( _WIN32 ) || defined( WINCE )
-// noexcept appeared since Visual Studio 2015
-#if defined(_MSC_VER) && _MSC_VER < 1900
-#define noexcept
-#endif
-
#define t_itoa(value, buffer, size, radix) _itoa_s(value, buffer, size, radix)
#define t_snprintf(s, n, format, ...) _snprintf_s(s, _TRUNCATE, n, format, __VA_ARGS__)
@@ -28,6 +12,5 @@ namespace litehtml
#define t_snprintf(s, n, format, ...) snprintf(s, n, format, __VA_ARGS__)
#endif
-}
#endif // LH_OS_TYPES_H
diff --git a/libs/litehtml/include/litehtml/render_item.h b/libs/litehtml/include/litehtml/render_item.h
index d3535429cb..d67fc42624 100644
--- a/libs/litehtml/include/litehtml/render_item.h
+++ b/libs/litehtml/include/litehtml/render_item.h
@@ -404,7 +404,9 @@ namespace litehtml
std::shared_ptr<litehtml::render_item>
> split_inlines();
bool fetch_positioned();
- void render_positioned(render_type rt = render_all);
+ void render_positioned(render_type width = render_all);
+ // returns element offset related to the containing block
+ std::tuple<int, int> element_static_offset(const std::shared_ptr<litehtml::render_item> &el);
void add_positioned(const std::shared_ptr<litehtml::render_item> &el);
void get_redraw_box(litehtml::position& pos, int x = 0, int y = 0);
void calc_document_size( litehtml::size& sz, litehtml::size& content_size, int x = 0, int y = 0 );
diff --git a/libs/litehtml/include/litehtml/string_id.h b/libs/litehtml/include/litehtml/string_id.h
index 46f8194727..a488b32792 100644
--- a/libs/litehtml/include/litehtml/string_id.h
+++ b/libs/litehtml/include/litehtml/string_id.h
@@ -153,6 +153,7 @@ STRING_ID(
_nth_of_type_,
_nth_last_child_,
_nth_last_of_type_,
+ _is_,
_not_,
_lang_,
@@ -160,6 +161,9 @@ STRING_ID(
_hover_,
// CSS property names
+ // Side properties must go in this order: top, right, bottom, left (clockwise starting from the top).
+ // Corner properties must go in this order: top-left, top-right, bottom-right, bottom-left (clockwise starting from the top-left).
+ // This is used in style::add_four_properties() for margin-*, padding-*, border-*-{width,style,color} and border-*-*-radius{,-x,-y}.
_background_,
_background_color_,
_background_image_,
@@ -183,45 +187,44 @@ STRING_ID(
__litehtml_border_spacing_x_,
__litehtml_border_spacing_y_,
- _border_left_,
- _border_right_,
_border_top_,
+ _border_right_,
_border_bottom_,
+ _border_left_,
- _border_left_style_,
- _border_right_style_,
_border_top_style_,
+ _border_right_style_,
_border_bottom_style_,
+ _border_left_style_,
- _border_left_width_,
- _border_right_width_,
_border_top_width_,
+ _border_right_width_,
_border_bottom_width_,
+ _border_left_width_,
- _border_left_color_,
- _border_right_color_,
_border_top_color_,
+ _border_right_color_,
_border_bottom_color_,
+ _border_left_color_,
_border_radius_,
_border_radius_x_,
_border_radius_y_,
+ _border_top_left_radius_,
+ _border_top_right_radius_,
+ _border_bottom_right_radius_,
_border_bottom_left_radius_,
- _border_bottom_left_radius_x_,
- _border_bottom_left_radius_y_,
- _border_bottom_right_radius_,
+ _border_top_left_radius_x_,
+ _border_top_right_radius_x_,
_border_bottom_right_radius_x_,
- _border_bottom_right_radius_y_,
+ _border_bottom_left_radius_x_,
- _border_top_left_radius_,
- _border_top_left_radius_x_,
_border_top_left_radius_y_,
-
- _border_top_right_radius_,
- _border_top_right_radius_x_,
_border_top_right_radius_y_,
+ _border_bottom_right_radius_y_,
+ _border_bottom_left_radius_y_,
_list_style_,
_list_style_type_,
@@ -230,15 +233,16 @@ STRING_ID(
_list_style_image_baseurl_,
_margin_,
- _margin_left_,
- _margin_right_,
_margin_top_,
+ _margin_right_,
_margin_bottom_,
+ _margin_left_,
+
_padding_,
- _padding_left_,
- _padding_right_,
_padding_top_,
+ _padding_right_,
_padding_bottom_,
+ _padding_left_,
_font_,
_font_family_,
@@ -268,10 +272,10 @@ STRING_ID(
_float_,
_clear_,
_text_indent_,
- _left_,
- _right_,
_top_,
+ _right_,
_bottom_,
+ _left_,
_cursor_,
_content_,
_border_collapse_,
@@ -292,8 +296,51 @@ STRING_ID(
_caption_side_,
_order_,
- _counter_reset_,
+ _counter_reset_,
_counter_increment_,
+
+ // some CSS dimensions
+ _deg_,
+ _grad_,
+ _rad_,
+ _turn_,
+
+ // some CSS property values
+ _initial_,
+ _auto_,
+ _none_,
+ _linear_gradient_,
+ _repeating_linear_gradient_,
+ _radial_gradient_,
+ _repeating_radial_gradient_,
+ _conic_gradient_,
+ _repeating_conic_gradient_,
+
+ // at-rules and their components
+ _charset_,
+ _layer_,
+ _import_,
+ _media_,
+ _and_,
+ _or_,
+ _boolean_,
+ _plain_,
+ _range_,
+ _discrete_,
+ _integer_,
+ _length_,
+ _resolution_,
+ _ratio_,
+ _keyword_,
+ _orientation_,
+ _portrait_,
+ _landscape_,
+ _device_width_,
+ _device_height_,
+ _aspect_ratio_,
+ _device_aspect_ratio_,
+ _color_index_,
+ _monochrome_,
)
#undef STRING_ID
extern const string_id empty_id; // _id("")
diff --git a/libs/litehtml/include/litehtml/style.h b/libs/litehtml/include/litehtml/style.h
index 6014f02dd0..256fd8f3ca 100644
--- a/libs/litehtml/include/litehtml/style.h
+++ b/libs/litehtml/include/litehtml/style.h
@@ -1,12 +1,14 @@
#ifndef LH_STYLE_H
#define LH_STYLE_H
-#include <variant>
+
+#include "css_tokenizer.h"
namespace litehtml
{
struct invalid {}; // indicates "not found" condition in style::get_property
struct inherit {}; // "inherit" was specified as the value of this property
- using property_value_base = std::variant<
+
+ struct property_value : variant<
invalid,
inherit,
int,
@@ -15,28 +17,25 @@ namespace litehtml
length_vector,
float,
web_color,
- std::vector<background_image>,
+ vector<image>,
string,
string_vector,
- size_vector
- >;
-
- struct property_value : property_value_base
+ size_vector,
+ css_token_vector
+ >
{
bool m_important = false;
- bool m_has_var = false; // string; parsing is delayed because of var()
+ bool m_has_var = false; // css_token_vector, parsing is delayed because of var()
property_value() {}
template<class T> property_value(const T& val, bool important, bool has_var = false)
- : property_value_base(val), m_important(important), m_has_var(has_var) {}
-
- template<class T> bool is() const { return std::holds_alternative<T>(*this); }
- template<class T> const T& get() const { return std::get<T>(*this); }
+ : base(val), m_important(important), m_has_var(has_var) {}
};
class html_tag;
typedef std::map<string_id, property_value> props_map;
+ // represents a style block, eg. "color: black; display: inline"
class style
{
public:
@@ -46,12 +45,11 @@ namespace litehtml
props_map m_properties;
static std::map<string_id, string> m_valid_values;
public:
- void add(const string& txt, const string& baseurl = "", document_container* container = nullptr)
- {
- parse(txt, baseurl, container);
- }
+ void add(const css_token_vector& tokens, const string& baseurl = "", document_container* container = nullptr);
+ void add(const string& txt, const string& baseurl = "", document_container* container = nullptr);
- void add_property(string_id name, const string& val, const string& baseurl = "", bool important = false, document_container* container = nullptr);
+ void add_property(string_id name, const css_token_vector& tokens, const string& baseurl = "", bool important = false, document_container* container = nullptr);
+ void add_property(string_id name, const string& val, const string& baseurl = "", bool important = false, document_container* container = nullptr);
const property_value& get_property(string_id name) const;
@@ -65,28 +63,51 @@ namespace litehtml
private:
void inherit_property(string_id name, bool important);
- void parse_property(const string& txt, const string& baseurl, document_container* container);
- void parse(const string& txt, const string& baseurl, document_container* container);
- void parse_background(const string& val, const string& baseurl, bool important, document_container* container);
- bool parse_one_background(const string& val, document_container* container, background& bg);
- void parse_background_image(const string& val, document_container* container, const string& baseurl, bool important);
+
+ void parse_background(const css_token_vector& tokens, const string& baseurl, bool important, document_container* container);
+ bool parse_bg_layer(const css_token_vector& tokens, document_container* container, background& bg, bool final_layer);
+ // parse the value of background-image property, which is comma-separated list of <bg-image>s
+ void parse_background_image(const css_token_vector& tokens, const string& baseurl, bool important, document_container* container);
+
// parse comma-separated list of keywords
- void parse_keyword_comma_list(string_id name, const string& val, bool important);
- void parse_background_position(const string& val, bool important);
- bool parse_one_background_position(const string& val, css_length& x, css_length& y);
- void parse_background_size(const string& val, bool important);
- bool parse_one_background_size(const string& val, css_size& size);
- void parse_font(const string& val, bool important);
- void parse_flex(const string& val, bool important);
- void parse_align_self(string_id name, const string& val, bool important);
- static css_length parse_border_width(const string& str);
- static void parse_two_lengths(const string& str, css_length len[2]);
- static int parse_four_lengths(const string& str, css_length len[4]);
- static void subst_vars_(string& str, const html_tag* el);
+ void parse_keyword_comma_list(string_id name, const css_token_vector& tokens, bool important);
+ void parse_background_position(const css_token_vector& tokens, bool important);
+ void parse_background_size(const css_token_vector& tokens, bool important);
+
+ void parse_border(const css_token_vector& tokens, bool important, document_container* container);
+ void parse_border_side(string_id name, const css_token_vector& tokens, bool important, document_container* container);
+ void parse_border_radius(const css_token_vector& tokens, bool important);
+
+ bool parse_list_style_image(const css_token& tok, string& url);
+ void parse_list_style(const css_token_vector& tokens, string baseurl, bool important);
+ void parse_font(css_token_vector tokens, bool important);
+
+ void parse_flex_flow(const css_token_vector& tokens, bool important);
+ void parse_flex(const css_token_vector& tokens, bool important);
+ void parse_align_self(string_id name, const css_token_vector& tokens, bool important);
+
void add_parsed_property(string_id name, const property_value& propval);
+ void add_length_property(string_id name, css_token val, string keywords, int options, bool important);
+ template<class T> void add_four_properties(string_id top_name, T val[4], int n, bool important);
void remove_property(string_id name, bool important);
};
-}
+
+ bool parse_url(const css_token& token, string& url);
+ bool parse_length(const css_token& tok, css_length& length, int options, string keywords = "");
+ bool parse_angle(const css_token& tok, float& angle, bool percents_allowed = false);
+ bool parse_bg_position(const css_token_vector& tokens, int& index, css_length& x, css_length& y, bool convert_keywords_to_percents);
+
+ template<typename Enum>
+ bool parse_keyword(const css_token& tok, Enum& val, string keywords, int first_keyword_value = 0)
+ {
+ int value_index(const string& val, const string& strings, int defValue = -1, char delim = ';');
+ int idx = value_index(tok.ident(), keywords);
+ if (idx == -1) return false;
+ val = (Enum)(first_keyword_value + idx);
+ return true;
+ }
+
+} // namespace litehtml
#endif // LH_STYLE_H
diff --git a/libs/litehtml/include/litehtml/stylesheet.h b/libs/litehtml/include/litehtml/stylesheet.h
index e614a28310..179f2de69b 100644
--- a/libs/litehtml/include/litehtml/stylesheet.h
+++ b/libs/litehtml/include/litehtml/stylesheet.h
@@ -3,46 +3,72 @@
#include "style.h"
#include "css_selector.h"
+#include "css_tokenizer.h"
namespace litehtml
{
- class document_container;
- class css
- {
- css_selector::vector m_selectors;
- public:
- css() = default;
- ~css() = default;
-
- const css_selector::vector& selectors() const
- {
- return m_selectors;
- }
-
- void clear()
- {
- m_selectors.clear();
- }
-
- void parse_stylesheet(const char* str, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media);
- void sort_selectors();
- static void parse_css_url(const string& str, string& url);
- static void parse_gradient(const string &token, document_container *container, background_gradient& grad);
-
- private:
- void parse_atrule(const string& text, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media);
- void add_selector(const css_selector::ptr& selector);
- bool parse_selectors(const string& txt, const style::ptr& styles, const media_query_list::ptr& media);
-
- };
-
- inline void litehtml::css::add_selector( const css_selector::ptr& selector )
+// https://www.w3.org/TR/cssom-1/#css-declarations
+struct raw_declaration
+{
+ using vector = std::vector<raw_declaration>;
+
+ string name; // property name
+ css_token_vector value = {}; // default value is specified here to get rid of gcc warning "missing initializer for member"
+ bool important = false;
+
+ operator bool() const { return name != ""; }
+};
+
+// intermediate half-parsed rule that is used internally by the parser
+class raw_rule
+{
+public:
+ using ptr = shared_ptr<raw_rule>;
+ using vector = std::vector<ptr>;
+
+ enum rule_type { qualified, at };
+
+ raw_rule(rule_type type, string name = "") : type(type), name(name) {}
+
+ rule_type type;
+ // An at-rule has a name, a prelude consisting of a list of component values, and an optional block consisting of a simple {} block.
+ string name;
+ // https://www.w3.org/TR/css-syntax-3/#qualified-rule
+ // A qualified rule has a prelude consisting of a list of component values, and a block consisting of a simple {} block.
+ // Note: Most qualified rules will be style rules, where the prelude is a selector and the block a list of declarations.
+ css_token_vector prelude;
+ css_token block;
+};
+
+class css
+{
+ css_selector::vector m_selectors;
+public:
+
+ const css_selector::vector& selectors() const
{
- selector->m_order = (int) m_selectors.size();
- m_selectors.push_back(selector);
+ return m_selectors;
}
+ template<class Input>
+ void parse_css_stylesheet(const Input& input, string baseurl, shared_ptr<document> doc, media_query_list_list::ptr media = nullptr, bool top_level = true);
+
+ void sort_selectors();
+
+private:
+ bool parse_style_rule(raw_rule::ptr rule, string baseurl, shared_ptr<document> doc, media_query_list_list::ptr media);
+ void parse_import_rule(raw_rule::ptr rule, string baseurl, shared_ptr<document> doc, media_query_list_list::ptr media);
+ void add_selector(const css_selector::ptr& selector);
+};
+
+inline void css::add_selector(const css_selector::ptr& selector)
+{
+ selector->m_order = (int)m_selectors.size();
+ m_selectors.push_back(selector);
}
+
+} // namespace litehtml
+
#endif // LH_STYLESHEET_H
diff --git a/libs/litehtml/include/litehtml/table.h b/libs/litehtml/include/litehtml/table.h
index d738b63ebf..2d251d6146 100644
--- a/libs/litehtml/include/litehtml/table.h
+++ b/libs/litehtml/include/litehtml/table.h
@@ -7,16 +7,16 @@
namespace litehtml
{
- class render_item;
+ class render_item;
struct table_row
{
- typedef std::vector<table_row> vector;
+ using vector = std::vector<table_row>;
int height;
int border_top;
int border_bottom;
- std::shared_ptr<render_item> el_row;
+ std::shared_ptr<render_item> el_row;
int top;
int bottom;
css_length css_height;
@@ -63,7 +63,7 @@ namespace litehtml
struct table_column
{
- typedef std::vector<table_column> vector;
+ using vector = std::vector<table_column>;
int min_width;
int max_width;
@@ -140,7 +140,7 @@ namespace litehtml
struct table_cell
{
- std::shared_ptr<render_item> el;
+ std::shared_ptr<render_item> el;
int colspan;
int rowspan;
int min_width;
@@ -179,7 +179,7 @@ namespace litehtml
}
table_cell(table_cell&& val) noexcept
- {
+ {
el = std::move(val.el);
colspan = val.colspan;
rowspan = val.rowspan;
@@ -196,7 +196,7 @@ namespace litehtml
class table_grid
{
public:
- typedef std::vector< std::vector<table_cell> > rows;
+ using rows = std::vector<std::vector<table_cell>>;
private:
int m_rows_count;
int m_cols_count;
@@ -224,7 +224,7 @@ namespace litehtml
table_cell* cell(int t_col, int t_row);
table_column& column(int c) { return m_columns[c]; }
table_row& row(int r) { return m_rows[r]; }
- std::vector<std::shared_ptr<render_item>>& captions() { return m_captions; }
+ std::vector<std::shared_ptr<render_item>>& captions() { return m_captions; }
int rows_count() const { return m_rows_count; }
int cols_count() const { return m_cols_count; }
diff --git a/libs/litehtml/include/litehtml/tstring_view.h b/libs/litehtml/include/litehtml/tstring_view.h
index 384c8d7df5..74bf5d3241 100644
--- a/libs/litehtml/include/litehtml/tstring_view.h
+++ b/libs/litehtml/include/litehtml/tstring_view.h
@@ -33,7 +33,7 @@
#include <cstddef>
#include <ostream>
-#include "os_types.h"
+#include "types.h"
namespace litehtml {
diff --git a/libs/litehtml/include/litehtml/types.h b/libs/litehtml/include/litehtml/types.h
index 415092b28a..76427f7215 100644
--- a/libs/litehtml/include/litehtml/types.h
+++ b/libs/litehtml/include/litehtml/types.h
@@ -1,29 +1,61 @@
#ifndef LH_TYPES_H
#define LH_TYPES_H
-#include <cstdlib>
+#include <cstdint>
#include <memory>
-#include <map>
+#include <string>
#include <vector>
+#include <map>
#include <list>
+#include <set>
+#include <variant>
+#include <optional>
namespace litehtml
{
+ using uint_ptr = std::uintptr_t;
+ using std::string;
+ using std::vector;
+ using std::shared_ptr;
+ using std::make_shared;
+ using std::optional;
+ using std::min;
+ using std::max;
+ using std::swap;
+ using std::abs;
+
class document;
class element;
- typedef std::map<string, string> string_map;
- typedef std::list< std::shared_ptr<element> > elements_list;
- typedef std::vector<int> int_vector;
- typedef std::vector<string> string_vector;
+ using string_map = std::map<string, string>;
+ using elements_list = std::list<std::shared_ptr<element>>;
+ using int_vector = std::vector<int>;
+ using string_vector = std::vector<string>;
+
+ template <class... Types>
+ struct variant : std::variant<Types...>
+ {
+ using base = variant<Types...>; // for derived class ctors
+ using std::variant<Types...>::variant; // inherit ctors
+ template<class T> bool is() const { return std::holds_alternative<T>(*this); }
+ template<class T> const T& get() const { return std::get<T>(*this); }
+ template<class T> T& get() { return std::get<T>(*this); }
+ };
+
+ enum document_mode
+ {
+ no_quirks_mode,
+ quirks_mode,
+ limited_quirks_mode
+ };
const unsigned int font_decoration_none = 0x00;
const unsigned int font_decoration_underline = 0x01;
const unsigned int font_decoration_linethrough = 0x02;
const unsigned int font_decoration_overline = 0x04;
- typedef unsigned char byte;
- typedef unsigned int ucode_t;
+ using byte = unsigned char;
+ using ucode_t = unsigned int;
struct margins
{
@@ -37,8 +69,8 @@ namespace litehtml
left = right = top = bottom = 0;
}
- int width() const { return left + right; }
- int height() const { return top + bottom; }
+ int width() const { return left + right; }
+ int height() const { return top + bottom; }
};
struct pointF
@@ -68,7 +100,7 @@ namespace litehtml
struct position
{
- typedef std::vector<position> vector;
+ using vector = std::vector<position>;
int x;
int y;
@@ -130,14 +162,14 @@ namespace litehtml
if(!val) return true;
return (
- left() <= val->right() &&
- right() >= val->left() &&
- bottom() >= val->top() &&
+ left() <= val->right() &&
+ right() >= val->left() &&
+ bottom() >= val->top() &&
top() <= val->bottom() )
|| (
- val->left() <= right() &&
- val->right() >= left() &&
- val->bottom() >= top() &&
+ val->left() <= right() &&
+ val->right() >= left() &&
+ val->bottom() >= top() &&
val->top() <= bottom() );
}
@@ -152,7 +184,7 @@ namespace litehtml
bool is_point_inside(int _x, int _y) const
{
- if(_x >= left() && _x <= right() && _y >= top() && _y <= bottom())
+ if(_x >= left() && _x < right() && _y >= top() && _y < bottom())
{
return true;
}
@@ -162,18 +194,22 @@ namespace litehtml
struct font_metrics
{
+ int font_size;
int height;
int ascent;
int descent;
int x_height;
+ int ch_width;
bool draw_spaces;
font_metrics()
{
+ font_size = 0;
height = 0;
ascent = 0;
descent = 0;
x_height = 0;
+ ch_width = 0;
draw_spaces = true;
}
int base_line() const { return descent; }
@@ -185,7 +221,7 @@ namespace litehtml
font_metrics metrics;
};
- typedef std::map<string, font_item> fonts_map;
+ using fonts_map = std::map<string, font_item>;
enum draw_flag
{
@@ -219,6 +255,8 @@ namespace litehtml
int value;
cbc_value_type type;
+ typed_int(const typed_int& v) = default;
+
typed_int(int val, cbc_value_type tp)
{
value = val;
@@ -236,12 +274,7 @@ namespace litehtml
return *this;
}
- typed_int& operator=(const typed_int& v)
- {
- value = v.value;
- type = v.type;
- return *this;
- }
+ typed_int& operator=(const typed_int& v) = default;
};
typed_int width; // width of the containing block
@@ -342,6 +375,8 @@ namespace litehtml
font_style_italic
};
+#define font_system_family_name_strings "caption;icon;menu;message-box;small-caption;status-bar"
+
#define font_variant_strings "normal;small-caps"
enum font_variant
@@ -350,7 +385,7 @@ namespace litehtml
font_variant_small_caps
};
-#define font_weight_strings "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900"
+#define font_weight_strings "normal;bold;bolder;lighter"
enum font_weight
{
@@ -358,15 +393,6 @@ namespace litehtml
font_weight_bold,
font_weight_bolder,
font_weight_lighter,
- font_weight_100,
- font_weight_200,
- font_weight_300,
- font_weight_400,
- font_weight_500,
- font_weight_600,
- font_weight_700,
- font_weight_800,
- font_weight_900
};
#define list_style_type_strings "none;circle;disc;square;armenian;cjk-ideographic;decimal;decimal-leading-zero;georgian;hebrew;hiragana;hiragana-iroha;katakana;katakana-iroha;lower-alpha;lower-greek;lower-latin;lower-roman;upper-alpha;upper-latin;upper-roman"
@@ -467,9 +493,9 @@ namespace litehtml
clear_both
};
-#define css_units_strings "none;%;in;cm;mm;em;ex;pt;pc;px;dpi;dpcm;vw;vh;vmin;vmax;rem"
+#define css_units_strings "none;%;in;cm;mm;em;ex;pt;pc;px;vw;vh;vmin;vmax;rem;ch"
- enum css_units : byte
+ enum css_units : byte // see css_length
{
css_units_none,
css_units_percentage,
@@ -481,13 +507,12 @@ namespace litehtml
css_units_pt,
css_units_pc,
css_units_px,
- css_units_dpi,
- css_units_dpcm,
css_units_vw,
css_units_vh,
css_units_vmin,
css_units_vmax,
css_units_rem,
+ css_units_ch,
};
#define background_attachment_strings "scroll;fixed"
@@ -508,6 +533,7 @@ namespace litehtml
background_repeat_no_repeat
};
+// https://drafts.csswg.org/css-box-4/#typedef-visual-box
#define background_box_strings "border-box;padding-box;content-box"
enum background_box
@@ -517,14 +543,15 @@ namespace litehtml
background_box_content
};
-#define background_position_strings "top;bottom;left;right;center"
+#define background_position_strings "left;right;top;bottom;center"
+ const float background_position_percentages[] = {0, 100, 0, 100, 50};
enum background_position
{
- background_position_top,
- background_position_bottom,
background_position_left,
background_position_right,
+ background_position_top,
+ background_position_bottom,
background_position_center,
};
@@ -585,7 +612,7 @@ namespace litehtml
enum background_size
{
- background_size_auto,
+ background_size_auto, // must be first, see parse_bg_size
background_size_cover,
background_size_contain,
};
@@ -640,16 +667,9 @@ namespace litehtml
context = val.context;
min_width = val.min_width;
}
- floated_box& operator=(const floated_box& val)
- {
- pos = val.pos;
- float_side = val.float_side;
- clear_floats = val.clear_floats;
- el = val.el;
- context = val.context;
- min_width = val.min_width;
- return *this;
- }
+
+ floated_box& operator=(const floated_box& val) = default;
+
floated_box(floated_box&& val)
{
pos = val.pos;
@@ -810,63 +830,6 @@ namespace litehtml
};
-#define media_orientation_strings "portrait;landscape"
-
- enum media_orientation
- {
- media_orientation_portrait,
- media_orientation_landscape,
- };
-
-#define media_feature_strings "none;width;min-width;max-width;height;min-height;max-height;device-width;min-device-width;max-device-width;device-height;min-device-height;max-device-height;orientation;aspect-ratio;min-aspect-ratio;max-aspect-ratio;device-aspect-ratio;min-device-aspect-ratio;max-device-aspect-ratio;color;min-color;max-color;color-index;min-color-index;max-color-index;monochrome;min-monochrome;max-monochrome;resolution;min-resolution;max-resolution"
-
- enum media_feature
- {
- media_feature_none,
-
- media_feature_width,
- media_feature_min_width,
- media_feature_max_width,
-
- media_feature_height,
- media_feature_min_height,
- media_feature_max_height,
-
- media_feature_device_width,
- media_feature_min_device_width,
- media_feature_max_device_width,
-
- media_feature_device_height,
- media_feature_min_device_height,
- media_feature_max_device_height,
-
- media_feature_orientation,
-
- media_feature_aspect_ratio,
- media_feature_min_aspect_ratio,
- media_feature_max_aspect_ratio,
-
- media_feature_device_aspect_ratio,
- media_feature_min_device_aspect_ratio,
- media_feature_max_device_aspect_ratio,
-
- media_feature_color,
- media_feature_min_color,
- media_feature_max_color,
-
- media_feature_color_index,
- media_feature_min_color_index,
- media_feature_max_color_index,
-
- media_feature_monochrome,
- media_feature_min_monochrome,
- media_feature_max_monochrome,
-
- media_feature_resolution,
- media_feature_min_resolution,
- media_feature_max_resolution,
- };
-
#define box_sizing_strings "content-box;border-box"
enum box_sizing
@@ -875,22 +838,18 @@ namespace litehtml
box_sizing_border_box,
};
-
-#define media_type_strings "none;all;screen;print;braille;embossed;handheld;projection;speech;tty;tv"
+// https://drafts.csswg.org/mediaqueries/#media-types
+// User agents must recognize the following media types as valid, but must make them match nothing.
+#define deprecated_media_type_strings "tty;tv;projection;handheld;braille;embossed;aural;speech"
+#define media_type_strings "all;print;screen;" deprecated_media_type_strings
enum media_type
{
- media_type_none,
+ media_type_unknown,
media_type_all,
- media_type_screen,
media_type_print,
- media_type_braille,
- media_type_embossed,
- media_type_handheld,
- media_type_projection,
- media_type_speech,
- media_type_tty,
- media_type_tv,
+ media_type_screen,
+ media_type_first_deprecated
};
struct media_features
@@ -907,8 +866,8 @@ namespace litehtml
media_features()
{
- type = media_type::media_type_none,
- width =0;
+ type = media_type_unknown;
+ width = 0;
height = 0;
device_width = 0;
device_height = 0;
@@ -968,19 +927,24 @@ namespace litehtml
flex_justify_content_stretch,
};
-#define flex_align_items_strings "normal;flex-start;flex-end;center;start;end;baseline;stretch;auto"
+#define self_position_strings "center;start;end;self-start;self-end;flex-start;flex-end"
+#define flex_align_items_strings "auto;normal;stretch;baseline;" self_position_strings
enum flex_align_items
{
- flex_align_items_flex_normal,
- flex_align_items_flex_start,
- flex_align_items_flex_end,
+ flex_align_items_auto, // used for align-self property only
+ flex_align_items_normal,
+ flex_align_items_stretch,
+ flex_align_items_baseline,
+
flex_align_items_center,
flex_align_items_start,
flex_align_items_end,
- flex_align_items_baseline,
- flex_align_items_stretch,
- flex_align_items_auto, // used for align-self property only
+ flex_align_items_self_start,
+ flex_align_items_self_end,
+ flex_align_items_flex_start,
+ flex_align_items_flex_end,
+
flex_align_items_first = 0x100,
flex_align_items_last = 0x200,
flex_align_items_unsafe = 0x400,
diff --git a/libs/litehtml/include/litehtml/url.h b/libs/litehtml/include/litehtml/url.h
index bd0cdc63c9..83f98a752e 100644
--- a/libs/litehtml/include/litehtml/url.h
+++ b/libs/litehtml/include/litehtml/url.h
@@ -32,7 +32,7 @@
#include <ostream>
-#include "os_types.h"
+#include "types.h"
// https://datatracker.ietf.org/doc/html/rfc3986
diff --git a/libs/litehtml/include/litehtml/url_path.h b/libs/litehtml/include/litehtml/url_path.h
index 6b102139d4..6ba68b03b8 100644
--- a/libs/litehtml/include/litehtml/url_path.h
+++ b/libs/litehtml/include/litehtml/url_path.h
@@ -32,7 +32,7 @@
#include <ostream>
-#include "os_types.h"
+#include "types.h"
namespace litehtml {
diff --git a/libs/litehtml/include/litehtml/utf8_strings.h b/libs/litehtml/include/litehtml/utf8_strings.h
index a4f1a78fa8..7930a437a7 100644
--- a/libs/litehtml/include/litehtml/utf8_strings.h
+++ b/libs/litehtml/include/litehtml/utf8_strings.h
@@ -1,47 +1,35 @@
#ifndef LH_UTF8_STRINGS_H
#define LH_UTF8_STRINGS_H
-#include "os_types.h"
#include "types.h"
namespace litehtml
{
// converts UTF-32 ch to UTF-8 and appends it to str
void append_char(string& str, char32_t ch);
+ char32_t read_utf8_char(const string& str, int& index);
+ void prev_utf8_char(const string& str, int& index);
class utf8_to_utf32
{
- const byte* m_utf8;
std::u32string m_str;
public:
- utf8_to_utf32(const char* val);
+ utf8_to_utf32(const string& val);
operator const char32_t*() const
{
return m_str.c_str();
}
- private:
- char32_t getb()
- {
- if (!(*m_utf8)) return 0;
- return *m_utf8++;
- }
- char32_t get_next_utf8(char32_t val)
- {
- return (val & 0x3f);
- }
- char32_t get_char();
};
class utf32_to_utf8
{
- std::string m_str;
+ string m_str;
public:
utf32_to_utf8(const std::u32string& val);
operator const char*() const
{
return m_str.c_str();
}
-
const char* c_str() const
{
return m_str.c_str();
diff --git a/libs/litehtml/include/litehtml/web_color.h b/libs/litehtml/include/litehtml/web_color.h
index 145a4157c3..9bc198dbcd 100644
--- a/libs/litehtml/include/litehtml/web_color.h
+++ b/libs/litehtml/include/litehtml/web_color.h
@@ -3,63 +3,33 @@
namespace litehtml
{
- struct def_color
- {
- const char* name;
- const char* rgb;
- };
-
- extern def_color g_def_colors[];
-
class document_container;
struct web_color
{
- byte red;
- byte green;
- byte blue;
- byte alpha;
+ byte red = 0;
+ byte green = 0;
+ byte blue = 0;
+ byte alpha = 255;
+ bool is_current_color = false;
static const web_color transparent;
static const web_color black;
static const web_color white;
+ static const web_color current_color;
- web_color(byte r, byte g, byte b, byte a = 255)
- {
- red = r;
- green = g;
- blue = b;
- alpha = a;
- }
-
- web_color()
- {
- red = 0;
- green = 0;
- blue = 0;
- alpha = 0xFF;
- }
+ web_color() {}
+ web_color(byte r, byte g, byte b, byte a = 255) : red(r), green(g), blue(b), alpha(a) {}
+ web_color(bool is_current_color) : is_current_color(is_current_color) {}
bool operator==(web_color color) const { return red == color.red && green == color.green && blue == color.blue && alpha == color.alpha; }
bool operator!=(web_color color) const { return !(*this == color); }
+ web_color darken(double fraction) const;
string to_string() const;
- static web_color from_string(const string& str, document_container* callback);
- static string resolve_name(const string& name, document_container* callback);
- static bool is_color(const string& str, document_container* callback);
- web_color darken(double fraction) const
- {
- int v_red = (int) red;
- int v_blue = (int) blue;
- int v_green = (int) green;
- v_red = (int) std::max(v_red - (v_red * fraction), 0.0);
- v_blue = (int) std::max(v_blue - (v_blue * fraction), 0.0);
- v_green = (int) std::max(v_green - (v_green * fraction), 0.0);
- return {(byte) v_red, (byte) v_green, (byte) v_blue, alpha};
- }
};
- typedef std::vector<web_color> web_color_vector;
+ bool parse_color(const css_token& token, web_color& color, document_container* container);
}
#endif // LH_WEB_COLOR_H