diff options
author | George Hazan <george.hazan@gmail.com> | 2024-10-09 18:13:40 +0300 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2024-10-09 18:13:40 +0300 |
commit | 0e86b853be3b5f809ed1decbf636221c1144a386 (patch) | |
tree | 4ce84d9849646a559d5afece33fc6e64d39e4a50 /libs/litehtml/include | |
parent | 834cbb58d74215980165eab257538ba918a378cd (diff) |
litehtml update
Diffstat (limited to 'libs/litehtml/include')
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 |