diff options
Diffstat (limited to 'libs/litehtml')
92 files changed, 1588 insertions, 1016 deletions
diff --git a/libs/litehtml/include/litehtml.h b/libs/litehtml/include/litehtml.h index 2537aee839..5687703dff 100644 --- a/libs/litehtml/include/litehtml.h +++ b/libs/litehtml/include/litehtml.h @@ -7,5 +7,6 @@ #include <litehtml/stylesheet.h> #include <litehtml/element.h> #include <litehtml/utf8_strings.h> +#include <litehtml/document_container.h> #endif // LITEHTML_H diff --git a/libs/litehtml/include/litehtml/codepoint.h b/libs/litehtml/include/litehtml/codepoint.h index 52dd495559..3e06e86e00 100644 --- a/libs/litehtml/include/litehtml/codepoint.h +++ b/libs/litehtml/include/litehtml/codepoint.h @@ -30,10 +30,6 @@ #ifndef LITEHTML_CODEPOINT_H__ #define LITEHTML_CODEPOINT_H__ -#include <string> - -#include "os_types.h" - namespace litehtml { bool is_ascii_codepoint(char c); diff --git a/libs/litehtml/include/litehtml/css_parser.h b/libs/litehtml/include/litehtml/css_parser.h index cbd88e3b84..eb49099fb9 100644 --- a/libs/litehtml/include/litehtml/css_parser.h +++ b/libs/litehtml/include/litehtml/css_parser.h @@ -3,6 +3,7 @@ #include "css_tokenizer.h" #include "stylesheet.h" +#include <functional> namespace litehtml { diff --git a/libs/litehtml/include/litehtml/css_properties.h b/libs/litehtml/include/litehtml/css_properties.h index b7f8e7e784..a904b9cced 100644 --- a/libs/litehtml/include/litehtml/css_properties.h +++ b/libs/litehtml/include/litehtml/css_properties.h @@ -1,7 +1,7 @@ #ifndef LITEHTML_CSS_PROPERTIES_H #define LITEHTML_CSS_PROPERTIES_H -#include "os_types.h" +#include "string_id.h" #include "types.h" #include "css_margins.h" #include "borders.h" @@ -13,6 +13,19 @@ namespace litehtml class html_tag; class document; + template<class CssT, class CompT> + class css_property + { + public: + CssT css_value; + CompT computed_value; + + css_property(const CssT& css_val, const CompT& computed_val) : css_value(css_val), computed_value(computed_val) {} + }; + + // CSS Properties types + using css_line_height_t = css_property<css_length, int>; + class css_properties { private: @@ -22,6 +35,7 @@ namespace litehtml white_space m_white_space; style_display m_display; visibility m_visibility; + appearance m_appearance; box_sizing m_box_sizing; css_length m_z_index; vertical_align m_vertical_align; @@ -39,7 +53,7 @@ namespace litehtml css_offsets m_css_offsets; css_length m_css_text_indent; css_length m_css_line_height; - int m_line_height; + css_line_height_t m_line_height {{}, 0}; list_style_type m_list_style_type; list_style_position m_list_style_position; string m_list_style_image; @@ -50,7 +64,13 @@ namespace litehtml string m_font_family; css_length m_font_weight; font_style m_font_style; - string m_text_decoration; + int m_text_decoration_line = text_decoration_line_none; + text_decoration_style m_text_decoration_style = text_decoration_style_solid; + css_length m_text_decoration_thickness; + web_color m_text_decoration_color; + string m_text_emphasis_style; + web_color m_text_emphasis_color; + int m_text_emphasis_position; font_metrics m_font_metrics; text_transform m_text_transform; web_color m_color; @@ -88,6 +108,7 @@ namespace litehtml m_white_space(white_space_normal), m_display(display_inline), m_visibility(visibility_visible), + m_appearance(appearance_none), m_box_sizing(box_sizing_content_box), m_z_index(0), m_vertical_align(va_baseline), @@ -105,7 +126,6 @@ namespace litehtml m_css_offsets(), m_css_text_indent(), m_css_line_height(0), - m_line_height(0), m_list_style_type(list_style_type_none), m_list_style_position(list_style_position_outside), m_bg(), @@ -148,6 +168,9 @@ namespace litehtml visibility get_visibility() const; void set_visibility(visibility mVisibility); + appearance get_appearance() const; + void set_appearance(appearance mAppearance); + box_sizing get_box_sizing() const; void set_box_sizing(box_sizing mBoxSizing); @@ -196,8 +219,8 @@ namespace litehtml const css_length &get_text_indent() const; void set_text_indent(const css_length &mCssTextIndent); - int get_line_height() const; - void set_line_height(int mLineHeight); + const css_line_height_t& line_height() const; + css_line_height_t& line_height_w(); list_style_type get_list_style_type() const; void set_list_style_type(list_style_type mListStyleType); @@ -205,10 +228,10 @@ namespace litehtml list_style_position get_list_style_position() const; void set_list_style_position(list_style_position mListStylePosition); - string get_list_style_image() const; + const string& get_list_style_image() const; void set_list_style_image(const string& url); - string get_list_style_image_baseurl() const; + const string& get_list_style_image_baseurl() const; void set_list_style_image_baseurl(const string& url); const background &get_bg() const; @@ -229,10 +252,10 @@ namespace litehtml web_color get_color() const; void set_color(web_color color); - string get_cursor() const; + const string& get_cursor() const; void set_cursor(const string& cursor); - string get_content() const; + const string& get_content() const; void set_content(const string& content); border_collapse get_border_collapse() const; @@ -259,6 +282,15 @@ namespace litehtml int get_order() const; void set_order(int order); + + int get_text_decoration_line() const; + text_decoration_style get_text_decoration_style() const; + const css_length& get_text_decoration_thickness() const; + const web_color& get_text_decoration_color() const; + + string get_text_emphasis_style() const; + web_color get_text_emphasis_color() const; + int get_text_emphasis_position() const; }; inline element_position css_properties::get_position() const @@ -321,6 +353,16 @@ namespace litehtml m_visibility = mVisibility; } + inline appearance css_properties::get_appearance() const + { + return m_appearance; + } + + inline void css_properties::set_appearance(appearance mAppearance) + { + m_appearance = mAppearance; + } + inline box_sizing css_properties::get_box_sizing() const { return m_box_sizing; @@ -481,14 +523,14 @@ namespace litehtml m_css_text_indent = mCssTextIndent; } - inline int css_properties::get_line_height() const + inline const css_line_height_t& css_properties::line_height() const { return m_line_height; } - inline void css_properties::set_line_height(int mLineHeight) + inline css_line_height_t& css_properties::line_height_w() { - m_line_height = mLineHeight; + return m_line_height; } inline list_style_type css_properties::get_list_style_type() const @@ -511,10 +553,10 @@ namespace litehtml m_list_style_position = mListStylePosition; } - inline string css_properties::get_list_style_image() const { return m_list_style_image; } + inline const string& css_properties::get_list_style_image() const { return m_list_style_image; } inline void css_properties::set_list_style_image(const string& url) { m_list_style_image = url; } - inline string css_properties::get_list_style_image_baseurl() const { return m_list_style_image_baseurl; } + inline const string& css_properties::get_list_style_image_baseurl() const { return m_list_style_image_baseurl; } inline void css_properties::set_list_style_image_baseurl(const string& url) { m_list_style_image_baseurl = url; } inline const background &css_properties::get_bg() const @@ -570,10 +612,10 @@ namespace litehtml inline web_color css_properties::get_color() const { return m_color; } inline void css_properties::set_color(web_color color) { m_color = color; } - inline string css_properties::get_cursor() const { return m_cursor; } + inline const string& css_properties::get_cursor() const { return m_cursor; } inline void css_properties::set_cursor(const string& cursor) { m_cursor = cursor; } - inline string css_properties::get_content() const { return m_content; } + inline const string& css_properties::get_content() const { return m_content; } inline void css_properties::set_content(const string& content) { m_content = content; } inline border_collapse css_properties::get_border_collapse() const @@ -669,6 +711,41 @@ namespace litehtml { m_order = order; } + + inline int css_properties::get_text_decoration_line() const + { + return m_text_decoration_line; + } + + inline text_decoration_style css_properties::get_text_decoration_style() const + { + return m_text_decoration_style; + } + + inline const css_length& css_properties::get_text_decoration_thickness() const + { + return m_text_decoration_thickness; + } + + inline const web_color& css_properties::get_text_decoration_color() const + { + return m_text_decoration_color; + } + + inline string css_properties::get_text_emphasis_style() const + { + return m_text_emphasis_style; + } + + inline web_color css_properties::get_text_emphasis_color() const + { + return m_text_emphasis_color; + } + + inline int css_properties::get_text_emphasis_position() const + { + return m_text_emphasis_position; + } } #endif //LITEHTML_CSS_PROPERTIES_H diff --git a/libs/litehtml/include/litehtml/css_selector.h b/libs/litehtml/include/litehtml/css_selector.h index 042f1691e4..57aa2846b5 100644 --- a/libs/litehtml/include/litehtml/css_selector.h +++ b/libs/litehtml/include/litehtml/css_selector.h @@ -1,6 +1,7 @@ #ifndef LH_CSS_SELECTOR_H #define LH_CSS_SELECTOR_H +#include "string_id.h" #include "style.h" #include "media_query.h" #include "css_tokenizer.h" @@ -154,7 +155,7 @@ namespace litehtml 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 diff --git a/libs/litehtml/include/litehtml/css_tokenizer.h b/libs/litehtml/include/litehtml/css_tokenizer.h index 119c925c79..f4a61af49c 100644 --- a/libs/litehtml/include/litehtml/css_tokenizer.h +++ b/libs/litehtml/include/litehtml/css_tokenizer.h @@ -1,6 +1,9 @@ #ifndef LH_CSS_TOKENIZER_H #define LH_CSS_TOKENIZER_H +#include "types.h" +#include <cstdio> + namespace litehtml { @@ -11,7 +14,7 @@ namespace litehtml enum css_token_type { WHITESPACE = ' ', - + // Giving EOF and some chars explicit names to facilitate debugging and to get rid of warning C4063: case '41' is not a valid value for switch of enum 'litehtml::css_token_type' _EOF = EOF, LEFT_BRACE = '{', @@ -26,7 +29,7 @@ enum css_token_type BANG = '!', DOT = '.', AMPERSAND = '&', - + IDENT = -20, // do not collide with any unicode chars FUNCTION, // calc( AT_KEYWORD, // @media @@ -62,12 +65,12 @@ enum css_hash_type }; // css_token: CSS token or component value ("fat" token) -// Tokens exist in uncomponentized form only a short time after tokenization, most of the time they are "fat". +// Tokens exist in uncomponentized form only a short time after tokenization, most of the time they are "fat". // All functions in css_parser work regardless of whether tokens are fat or not, as per standard. // All functions outside of css_parser that parse media queries, selectors, property values assume tokens are componentized. struct css_token { - css_token(css_token_type type = css_token_type(), + css_token(css_token_type type = css_token_type(), float number = 0, css_number_type number_type = css_number_integer, string str = "") : type(type), str(str), n{number, number_type} { @@ -87,13 +90,13 @@ struct css_token case HASH: hash_type = token.hash_type; break; - + case NUMBER: case PERCENTAGE: case DIMENSION: n = token.n; break; - + case CV_FUNCTION: case CURLY_BLOCK: case ROUND_BLOCK: @@ -104,17 +107,17 @@ struct css_token default:; } } - + css_token& operator=(const css_token& token) { this->~css_token(); new(this) css_token(token); return *this; } - + ~css_token() - { - str.~string(); + { + str.~string(); if (is_component_value()) value.~vector(); } @@ -132,7 +135,7 @@ struct css_token }; union { string str; // STRING, URL - string name; // HASH, IDENT, AT_KEYWORD, FUNCTION, CV_FUNCTION + string name; // HASH, IDENT, AT_KEYWORD, FUNCTION, CV_FUNCTION string unit; // DIMENSION }; struct number { @@ -144,7 +147,7 @@ struct css_token number n; vector<css_token> value; // CV_FUNCTION, XXX_BLOCK }; - + string repr; // https://www.w3.org/TR/css-syntax-3/#representation }; @@ -155,7 +158,7 @@ class css_tokenizer { public: css_tokenizer(const string& input) : str(input), index(0), current_char(0) {} - + css_token_vector tokenize(); private: @@ -188,7 +191,7 @@ private: void consume_comments(); int consume_escaped_code_point(); css_token consume_string_token(int ending_code_point); - + static bool would_start_ident_sequence(three_chars chars); string consume_ident_sequence(); diff --git a/libs/litehtml/include/litehtml/document.h b/libs/litehtml/include/litehtml/document.h index 7119636ffe..9be8465411 100644 --- a/libs/litehtml/include/litehtml/document.h +++ b/libs/litehtml/include/litehtml/document.h @@ -1,10 +1,12 @@ #ifndef LH_DOCUMENT_H #define LH_DOCUMENT_H -#include "style.h" +#include "stylesheet.h" #include "types.h" #include "master_css.h" #include "encodings.h" +#include "font_description.h" + typedef struct GumboInternalOutput GumboOutput; namespace litehtml @@ -16,7 +18,7 @@ namespace litehtml string text; string baseurl; string media; - + css_text() = default; css_text(const char* txt, const char* url, const char* media_str) @@ -50,6 +52,7 @@ namespace litehtml std::shared_ptr<element> m_root; std::shared_ptr<render_item> m_root_render; document_container* m_container; + fonts_map m_fonts; css_text::vector m_css; litehtml::css m_styles; litehtml::web_color m_def_color; @@ -58,7 +61,8 @@ namespace litehtml litehtml::size m_size; litehtml::size m_content_size; position::vector m_fixed_boxes; - element::ptr m_over_element; + std::shared_ptr<element> m_over_element; + std::shared_ptr<element> m_active_element; std::list<shared_ptr<render_item>> m_tabular_elements; media_query_list_list::vector m_media_lists; media_features m_media; @@ -72,7 +76,7 @@ namespace litehtml 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); + uint_ptr get_font(const font_description& descr, 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; } @@ -86,9 +90,10 @@ namespace litehtml bool on_mouse_over(int x, int y, int client_x, int client_y, position::vector& redraw_boxes); bool on_lbutton_down(int x, int y, int client_x, int client_y, position::vector& redraw_boxes); bool on_lbutton_up(int x, int y, int client_x, int client_y, position::vector& redraw_boxes); + bool on_button_cancel(position::vector& redraw_boxes); 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<element> create_element(const char* tag_name, const string_map& attributes); + std::shared_ptr<element> root(); std::shared_ptr<render_item> root_render(); void get_fixed_boxes(position::vector& fixed_boxes); void add_fixed_box(const position& pos); @@ -97,7 +102,7 @@ namespace litehtml bool lang_changed(); bool match_lang(const string& lang); void add_tabular(const std::shared_ptr<render_item>& el); - element::const_ptr get_over_element() const { return m_over_element; } + std::shared_ptr<const element> get_over_element() const { return m_over_element; } void append_children_from_string(element& parent, const char* str); void dump(dumper& cout); @@ -108,9 +113,9 @@ namespace litehtml document_container* container, const string& master_styles = litehtml::master_css, const string& user_styles = ""); - + private: - uint_ptr add_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm); + uint_ptr add_font(const font_description& descr, font_metrics* fm); GumboOutput* parse_html(estring str); void create_node(void* gnode, elements_list& elements, bool parseTextNode); @@ -120,7 +125,7 @@ namespace litehtml void fix_table_parent(const std::shared_ptr<render_item> & el_ptr, style_display disp, const char* disp_str); }; - inline element::ptr document::root() + inline std::shared_ptr<element> document::root() { return m_root; } diff --git a/libs/litehtml/include/litehtml/document_container.h b/libs/litehtml/include/litehtml/document_container.h index 95efe1eb6b..47cdc4b9d3 100644 --- a/libs/litehtml/include/litehtml/document_container.h +++ b/libs/litehtml/include/litehtml/document_container.h @@ -1,12 +1,12 @@ #ifndef LH_DOCUMENT_CONTAINER_H #define LH_DOCUMENT_CONTAINER_H -#include "os_types.h" #include "types.h" #include "web_color.h" #include "background.h" #include "borders.h" #include "element.h" +#include "font_description.h" #include <memory> #include <functional> @@ -22,7 +22,7 @@ namespace litehtml int index; uint_ptr font; }; - + enum mouse_event { mouse_event_enter, @@ -35,7 +35,7 @@ namespace litehtml public: fonts_map m_fonts; - virtual litehtml::uint_ptr create_font(const char* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm) = 0; + virtual litehtml::uint_ptr create_font(const font_description& descr, const document* doc, litehtml::font_metrics* fm) = 0; virtual void delete_font(litehtml::uint_ptr hFont) = 0; virtual int text_width(const char* text, litehtml::uint_ptr hFont) = 0; virtual void draw_text(litehtml::uint_ptr hdc, const char* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos) = 0; @@ -56,13 +56,14 @@ 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 bool on_element_click(const litehtml::element::ptr& /*el*/) { return false; }; 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; virtual void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius) = 0; virtual void del_clip() = 0; - virtual void get_client_rect(litehtml::position& client) const = 0; + virtual void get_viewport(litehtml::position& viewport) const = 0; virtual litehtml::element::ptr create_element( const char* tag_name, const litehtml::string_map& attributes, const std::shared_ptr<litehtml::document>& doc) = 0; diff --git a/libs/litehtml/include/litehtml/el_cdata.h b/libs/litehtml/include/litehtml/el_cdata.h index 838cd92b1e..3e9db43b88 100644 --- a/libs/litehtml/include/litehtml/el_cdata.h +++ b/libs/litehtml/include/litehtml/el_cdata.h @@ -1,7 +1,7 @@ #ifndef LH_EL_CDATA_H #define LH_EL_CDATA_H -#include "html_tag.h" +#include "element.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/el_comment.h b/libs/litehtml/include/litehtml/el_comment.h index 379318ffbe..fa8e72fc91 100644 --- a/libs/litehtml/include/litehtml/el_comment.h +++ b/libs/litehtml/include/litehtml/el_comment.h @@ -1,7 +1,7 @@ #ifndef LH_EL_COMMENT_H #define LH_EL_COMMENT_H -#include "html_tag.h" +#include "element.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/el_image.h b/libs/litehtml/include/litehtml/el_image.h index 2b73940815..b67de11941 100644 --- a/libs/litehtml/include/litehtml/el_image.h +++ b/libs/litehtml/include/litehtml/el_image.h @@ -2,6 +2,7 @@ #define LH_EL_IMAGE_H #include "html_tag.h" +#include "document.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/el_script.h b/libs/litehtml/include/litehtml/el_script.h index e0a0374057..0353b15796 100644 --- a/libs/litehtml/include/litehtml/el_script.h +++ b/libs/litehtml/include/litehtml/el_script.h @@ -1,7 +1,7 @@ #ifndef LH_EL_SCRIPT_H #define LH_EL_SCRIPT_H -#include "html_tag.h" +#include "element.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/el_space.h b/libs/litehtml/include/litehtml/el_space.h index 53c170f13a..6d447f7103 100644 --- a/libs/litehtml/include/litehtml/el_space.h +++ b/libs/litehtml/include/litehtml/el_space.h @@ -1,7 +1,6 @@ #ifndef LH_EL_SPACE_H #define LH_EL_SPACE_H -#include "html_tag.h" #include "el_text.h" namespace litehtml diff --git a/libs/litehtml/include/litehtml/el_style.h b/libs/litehtml/include/litehtml/el_style.h index 62f1546259..60c0b50c67 100644 --- a/libs/litehtml/include/litehtml/el_style.h +++ b/libs/litehtml/include/litehtml/el_style.h @@ -1,7 +1,7 @@ #ifndef LH_EL_STYLE_H #define LH_EL_STYLE_H -#include "html_tag.h" +#include "element.h" namespace litehtml { @@ -13,6 +13,7 @@ namespace litehtml void parse_attributes() override; bool appendChild(const ptr &el) override; + void compute_styles(bool recursive) override; string_id tag() const override; const char* get_tagName() const override; }; diff --git a/libs/litehtml/include/litehtml/el_text.h b/libs/litehtml/include/litehtml/el_text.h index ea54cc9c66..f3da930825 100644 --- a/libs/litehtml/include/litehtml/el_text.h +++ b/libs/litehtml/include/litehtml/el_text.h @@ -1,7 +1,8 @@ #ifndef LH_EL_TEXT_H #define LH_EL_TEXT_H -#include "html_tag.h" +#include "element.h" +#include "document.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/element.h b/libs/litehtml/include/litehtml/element.h index 67dd1ae251..d18976c9f0 100644 --- a/libs/litehtml/include/litehtml/element.h +++ b/libs/litehtml/include/litehtml/element.h @@ -1,12 +1,12 @@ #ifndef LH_ELEMENT_H #define LH_ELEMENT_H +#include <functional> #include <memory> #include <tuple> #include <list> +#include "types.h" #include "stylesheet.h" -#include "css_offsets.h" -#include "css_margins.h" #include "css_properties.h" namespace litehtml @@ -94,7 +94,7 @@ namespace litehtml virtual bool on_mouse_over(); virtual bool on_mouse_leave(); virtual bool on_lbutton_down(); - virtual bool on_lbutton_up(); + virtual bool on_lbutton_up(bool is_click = true); virtual void on_click(); virtual bool set_pseudo_class(string_id cls, bool add); virtual bool set_class(const char* pclass, bool add); @@ -155,7 +155,9 @@ namespace litehtml inline bool litehtml::element::in_normal_flow() const { - if(css().get_position() != element_position_absolute && css().get_display() != display_none) + if(css().get_position() != element_position_absolute && + css().get_display() != display_none && + css().get_position() != element_position_fixed) { return true; } @@ -207,8 +209,7 @@ namespace litehtml if (css().get_display() == display_block || css().get_display() == display_flex || css().get_display() == display_table || - css().get_display() == display_list_item || - css().get_display() == display_flex) + css().get_display() == display_list_item) { return true; } diff --git a/libs/litehtml/include/litehtml/encodings.h b/libs/litehtml/include/litehtml/encodings.h index 2dd9d5e0f5..ec5cb03e83 100644 --- a/libs/litehtml/include/litehtml/encodings.h +++ b/libs/litehtml/include/litehtml/encodings.h @@ -1,6 +1,7 @@ #ifndef LH_ENCODINGS_H #define LH_ENCODINGS_H +#include "types.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/flex_item.h b/libs/litehtml/include/litehtml/flex_item.h index 0c4244ae2d..4ad53ac11a 100644 --- a/libs/litehtml/include/litehtml/flex_item.h +++ b/libs/litehtml/include/litehtml/flex_item.h @@ -1,8 +1,8 @@ #ifndef LITEHTML_FLEX_ITEM_H #define LITEHTML_FLEX_ITEM_H -#include <functional> #include "formatting_context.h" +#include "render_item.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/font_description.h b/libs/litehtml/include/litehtml/font_description.h new file mode 100644 index 0000000000..c4c3ee7224 --- /dev/null +++ b/libs/litehtml/include/litehtml/font_description.h @@ -0,0 +1,45 @@ +#ifndef LITEHTML_FONT_DESCRIPTION +#define LITEHTML_FONT_DESCRIPTION + +#include <string> +#include "types.h" +#include "css_length.h" +#include "web_color.h" + +namespace litehtml +{ + struct font_description + { + std::string family; // Font Family + int size = 0; // Font size + font_style style = font_style_normal; // Font stype, see the enum font_style + int weight; // Font weight. + int decoration_line = text_decoration_line_none; // Decoration line. A bitset of flags of the enum text_decoration_line + css_length decoration_thickness; // Decoration line thickness in pixels. See predefined values in enumtext_decoration_thickness + text_decoration_style decoration_style = text_decoration_style_solid; // Decoration line style. See enum text_decoration_style + web_color decoration_color = web_color::current_color; // Decoration line color + std::string emphasis_style; // Text emphasis style + web_color emphasis_color = web_color::current_color; // Text emphasis color + int emphasis_position = text_emphasis_position_over; // Text emphasis position + + std::string hash() const + { + std::string out; + out += family; + out += ":sz=" + std::to_string(size); + out += ":st=" + std::to_string(style); + out += ":w=" + std::to_string(weight); + out += ":dl=" + std::to_string(decoration_line); + out += ":dt=" + decoration_thickness.to_string(); + out += ":ds=" + std::to_string(decoration_style); + out += ":dc=" + decoration_color.to_string(); + out += ":ephs=" + emphasis_style; + out += ":ephc=" + emphasis_color.to_string(); + out += ":ephp=" + std::to_string(emphasis_position); + + return out; + } + }; +} + +#endif
\ No newline at end of file diff --git a/libs/litehtml/include/litehtml/gradient.h b/libs/litehtml/include/litehtml/gradient.h index 6313eb75b2..1bfe77cde0 100644 --- a/libs/litehtml/include/litehtml/gradient.h +++ b/libs/litehtml/include/litehtml/gradient.h @@ -1,6 +1,11 @@ #ifndef LITEHTML_GRADIENT_H #define LITEHTML_GRADIENT_H +#include "css_length.h" +#include "string_id.h" +#include "types.h" +#include "web_color.h" + namespace litehtml { enum gradient_side @@ -129,7 +134,7 @@ namespace litehtml 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; @@ -144,7 +149,7 @@ namespace litehtml // <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_extent = radial_extent_farthest_corner; radial_radius_x.predef(0); radial_radius_y.predef(0); @@ -182,7 +187,7 @@ namespace litehtml gradient m_gradient; image() : type(type_none) {} - + bool is_empty() const { switch (type) diff --git a/libs/litehtml/include/litehtml/html.h b/libs/litehtml/include/litehtml/html.h index cd0500aabe..9b725d9a66 100644 --- a/libs/litehtml/include/litehtml/html.h +++ b/libs/litehtml/include/litehtml/html.h @@ -6,19 +6,8 @@ #include <cctype> #include <cstring> #include <algorithm> -#include <functional> -#include "os_types.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 { @@ -36,15 +25,10 @@ namespace litehtml 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) + template<typename T, typename... Opts> + bool is_one_of(T val, Opts ...opts) { - 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...); + return (... || (val == opts)); } template<class T> const T& at(const vector<T>& vec, int index /*may be negative*/) @@ -155,7 +139,7 @@ namespace litehtml 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'); } diff --git a/libs/litehtml/include/litehtml/html_microsyntaxes.h b/libs/litehtml/include/litehtml/html_microsyntaxes.h index 193dd20d62..04c7445ee5 100644 --- a/libs/litehtml/include/litehtml/html_microsyntaxes.h +++ b/libs/litehtml/include/litehtml/html_microsyntaxes.h @@ -1,20 +1,22 @@ #ifndef LH_HTML_MICROSYNTAXES_H #define LH_HTML_MICROSYNTAXES_H +#include "types.h" + namespace litehtml { -bool html_parse_integer(const string& str, int& val); -bool html_parse_non_negative_integer(const string& str, int& val); + bool html_parse_integer(const string& str, int& val); + bool html_parse_non_negative_integer(const string& str, int& val); -enum html_dimension_type -{ - html_length, - html_percentage -}; + enum html_dimension_type + { + html_length, + html_percentage + }; -bool html_parse_dimension_value(const string& str, float& val, html_dimension_type& type); -bool html_parse_nonzero_dimension_value(const string& str, float& val, html_dimension_type& type); + bool html_parse_dimension_value(const string& str, float& val, html_dimension_type& type); + bool html_parse_nonzero_dimension_value(const string& str, float& val, html_dimension_type& type); } // namespace litehtml diff --git a/libs/litehtml/include/litehtml/html_tag.h b/libs/litehtml/include/litehtml/html_tag.h index 63cd64498a..d8c9dfa40b 100644 --- a/libs/litehtml/include/litehtml/html_tag.h +++ b/libs/litehtml/include/litehtml/html_tag.h @@ -4,8 +4,6 @@ #include "element.h" #include "style.h" #include "background.h" -#include "css_margins.h" -#include "borders.h" #include "css_selector.h" #include "stylesheet.h" #include "line_box.h" @@ -61,7 +59,7 @@ namespace litehtml bool on_mouse_over() override; bool on_mouse_leave() override; bool on_lbutton_down() override; - bool on_lbutton_up() override; + bool on_lbutton_up(bool is_click) override; void on_click() override; bool set_pseudo_class(string_id cls, bool add) override; bool set_class(const char* pclass, bool add) override; diff --git a/libs/litehtml/include/litehtml/iterators.h b/libs/litehtml/include/litehtml/iterators.h index b1a678d7b4..b7e1887c16 100644 --- a/libs/litehtml/include/litehtml/iterators.h +++ b/libs/litehtml/include/litehtml/iterators.h @@ -2,7 +2,6 @@ #define LH_ITERATORS_H #include "types.h" -#include <list> #include <functional> namespace litehtml @@ -45,7 +44,7 @@ namespace litehtml ~elements_iterator() = default; void process(const std::shared_ptr<render_item>& container, const std::function<void (std::shared_ptr<render_item>&, iterator_item_type)>& func); - + private: void next_idx(); }; diff --git a/libs/litehtml/include/litehtml/line_box.h b/libs/litehtml/include/litehtml/line_box.h index 6e945c9fdc..eac00d13d3 100644 --- a/libs/litehtml/include/litehtml/line_box.h +++ b/libs/litehtml/include/litehtml/line_box.h @@ -1,9 +1,8 @@ #ifndef LH_LINE_BOX_H #define LH_LINE_BOX_H -#include <vector> #include <memory> -#include "os_types.h" +#include "css_properties.h" #include "types.h" namespace litehtml @@ -40,15 +39,16 @@ namespace litehtml }; protected: std::shared_ptr<render_item> m_element; - int m_rendered_min_width; + int m_rendered_min_width = 0; + int m_items_top = 0; + int m_items_bottom = 0; public: - explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element), m_rendered_min_width(0) {} - line_box_item() : m_element(), m_rendered_min_width(0) {}; + explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element) {} 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(); } + virtual int height() const; const std::shared_ptr<render_item>& get_el() const { return m_element; } virtual position& pos(); virtual void place_to(int x, int y); @@ -60,6 +60,15 @@ namespace litehtml virtual element_type get_type() const { return type_text_part; } virtual int get_rendered_min_width() const { return m_rendered_min_width; } virtual void set_rendered_min_width(int min_width) { m_rendered_min_width = min_width; } + + void reset_items_height() { m_items_top = m_items_bottom = 0; } + void add_item_height(int item_top, int item_bottom) + { + m_items_top = std::min(m_items_top, item_top); + m_items_bottom = std::max(m_items_bottom, item_bottom); + } + int get_items_top() const { return m_items_top; } + int get_items_bottom() const { return m_items_bottom; } }; class lbi_start : public line_box_item @@ -68,9 +77,10 @@ namespace litehtml position m_pos; public: explicit lbi_start(const std::shared_ptr<render_item>& element); - virtual ~lbi_start() override; + ~lbi_start() override; void place_to(int x, int y) override; + int height() const override; int width() const override; position& pos() override { return m_pos; } int top() const override; @@ -110,10 +120,10 @@ namespace litehtml { struct va_context { - int baseline; + int line_height = 0; + int baseline = 0; font_metrics fm; - - va_context() : baseline(0) {} + line_box_item* start_lbi = nullptr; }; int m_top; @@ -121,21 +131,19 @@ namespace litehtml int m_right; int m_height; int m_width; - int m_line_height; - int m_default_line_height; + css_line_height_t m_default_line_height; font_metrics m_font_metrics; int m_baseline; text_align m_text_align; int m_min_width; std::list< std::unique_ptr<line_box_item> > m_items; public: - line_box(int top, int left, int right, int line_height, const font_metrics& fm, text_align align) : + line_box(int top, int left, int right, const css_line_height_t& line_height, const font_metrics& fm, text_align align) : m_top(top), m_left(left), m_right(right), m_height(0), m_width(0), - m_line_height(0), m_default_line_height(line_height), m_font_metrics(fm), m_baseline(0), diff --git a/libs/litehtml/include/litehtml/media_query.h b/libs/litehtml/include/litehtml/media_query.h index 94ed205e52..163191a512 100644 --- a/libs/litehtml/include/litehtml/media_query.h +++ b/libs/litehtml/include/litehtml/media_query.h @@ -1,6 +1,10 @@ #ifndef LH_MEDIA_QUERY_H #define LH_MEDIA_QUERY_H +#include "css_tokenizer.h" +#include "string_id.h" +#include "types.h" + namespace litehtml { // https://drafts.csswg.org/mediaqueries/#evaluating @@ -53,7 +57,7 @@ namespace litehtml { string_id op = _and_; // _not_ _and_ _or_ vector<media_in_parens> m_conditions; - + trilean check(const media_features& features) const; }; @@ -68,7 +72,7 @@ namespace litehtml 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; @@ -92,7 +96,7 @@ namespace litehtml 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); - + class media_query_list_list { public: diff --git a/libs/litehtml/include/litehtml/render_item.h b/libs/litehtml/include/litehtml/render_item.h index d67fc42624..fedc1f3887 100644 --- a/libs/litehtml/include/litehtml/render_item.h +++ b/libs/litehtml/include/litehtml/render_item.h @@ -2,13 +2,14 @@ #define LH_RENDER_ITEM_H #include <memory> -#include <utility> #include <list> #include <tuple> +#include "html.h" #include "types.h" #include "line_box.h" #include "table.h" #include "formatting_context.h" +#include "element.h" namespace litehtml { @@ -348,7 +349,8 @@ namespace litehtml m_element->css().get_float() == float_none && m_margins.top >= 0 && !is_flex_item() && - !is_root(); + !is_root() && + !is_one_of(css().get_overflow(), overflow_hidden, overflow_scroll, overflow_auto); } bool collapse_bottom_margin() const @@ -358,7 +360,8 @@ namespace litehtml m_element->in_normal_flow() && m_element->css().get_float() == float_none && m_margins.bottom >= 0 && - !is_root(); + !is_root() && + !is_one_of(css().get_overflow(), overflow_hidden, overflow_scroll, overflow_auto); } bool is_visible() const diff --git a/libs/litehtml/include/litehtml/string_id.h b/libs/litehtml/include/litehtml/string_id.h index a488b32792..6373ec9e4d 100644 --- a/libs/litehtml/include/litehtml/string_id.h +++ b/libs/litehtml/include/litehtml/string_id.h @@ -1,6 +1,8 @@ #ifndef LH_STRING_ID_H #define LH_STRING_ID_H +#include <string> + namespace litehtml { @@ -252,6 +254,14 @@ STRING_ID( _font_size_, _line_height_, _text_decoration_, + _text_decoration_style_, + _text_decoration_line_, + _text_decoration_color_, + _text_decoration_thickness_, + _text_emphasis_, + _text_emphasis_style_, + _text_emphasis_color_, + _text_emphasis_position_, _white_space_, _text_align_, @@ -267,6 +277,7 @@ STRING_ID( _overflow_, _display_, _visibility_, + _appearance_, _box_sizing_, _z_index_, _float_, @@ -346,8 +357,8 @@ STRING_ID( extern const string_id empty_id; // _id("") extern const string_id star_id; // _id("*") -string_id _id(const string& str); -const string& _s(string_id id); +string_id _id(const std::string& str); +const std::string& _s(string_id id); } // namespace litehtml diff --git a/libs/litehtml/include/litehtml/style.h b/libs/litehtml/include/litehtml/style.h index 256fd8f3ca..e68a05b725 100644 --- a/libs/litehtml/include/litehtml/style.h +++ b/libs/litehtml/include/litehtml/style.h @@ -1,7 +1,12 @@ #ifndef LH_STYLE_H #define LH_STYLE_H +#include "background.h" +#include "css_length.h" +#include "css_position.h" #include "css_tokenizer.h" +#include "gradient.h" +#include "web_color.h" namespace litehtml { @@ -28,7 +33,7 @@ namespace litehtml 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) + template<class T> property_value(const T& val, bool important, bool has_var = false) : base(val), m_important(important), m_has_var(has_var) {} }; @@ -73,26 +78,33 @@ namespace litehtml 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_text_decoration(const css_token_vector& tokens, bool important, document_container* container); + bool parse_text_decoration_color(const css_token& token, bool important, document_container* container); + void parse_text_decoration_line(const css_token_vector& tokens, bool important); + + void parse_text_emphasis(const css_token_vector& tokens, bool important, document_container* container); + bool parse_text_emphasis_color(const css_token& token, bool important, document_container* container); + void parse_text_emphasis_position(const 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); diff --git a/libs/litehtml/include/litehtml/stylesheet.h b/libs/litehtml/include/litehtml/stylesheet.h index 179f2de69b..f81bac7121 100644 --- a/libs/litehtml/include/litehtml/stylesheet.h +++ b/libs/litehtml/include/litehtml/stylesheet.h @@ -1,7 +1,6 @@ #ifndef LH_STYLESHEET_H #define LH_STYLESHEET_H -#include "style.h" #include "css_selector.h" #include "css_tokenizer.h" @@ -28,7 +27,7 @@ public: using vector = std::vector<ptr>; enum rule_type { qualified, at }; - + raw_rule(rule_type type, string name = "") : type(type), name(name) {} rule_type type; diff --git a/libs/litehtml/include/litehtml/tstring_view.h b/libs/litehtml/include/litehtml/tstring_view.h index 74bf5d3241..9c3c74f5fe 100644 --- a/libs/litehtml/include/litehtml/tstring_view.h +++ b/libs/litehtml/include/litehtml/tstring_view.h @@ -33,8 +33,6 @@ #include <cstddef> #include <ostream> -#include "types.h" - namespace litehtml { // tstring_view is a string reference type that provides a view into a string diff --git a/libs/litehtml/include/litehtml/types.h b/libs/litehtml/include/litehtml/types.h index c92998cd43..43cafc3bff 100644 --- a/libs/litehtml/include/litehtml/types.h +++ b/libs/litehtml/include/litehtml/types.h @@ -7,7 +7,6 @@ #include <vector> #include <map> #include <list> -#include <set> #include <variant> #include <optional> #include <algorithm> @@ -50,10 +49,46 @@ namespace litehtml 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; + #define style_text_decoration_line_strings "none;underline;overline;line-through" + + enum text_decoration_line + { + text_decoration_line_none = 0x00, + text_decoration_line_underline = 0x01, + text_decoration_line_overline = 0x02, + text_decoration_line_line_through = 0x04, + }; + + #define style_text_decoration_style_strings "solid;double;dotted;dashed;wavy" + + enum text_decoration_style + { + text_decoration_style_solid, + text_decoration_style_double, + text_decoration_style_dotted, + text_decoration_style_dashed, + text_decoration_style_wavy, + text_decoration_style_max, + }; + + #define style_text_decoration_thickness_strings "auto;from-font" + + enum text_decoration_thickness + { + text_decoration_thickness_auto, + text_decoration_thickness_from_font, + }; + + #define style_text_emphasis_position_strings "over;under;left;right" + + enum text_emphasis_position + { + text_emphasis_position_over = 0x00, + text_emphasis_position_under = 0x01, + text_emphasis_position_left = 0x02, + text_emphasis_position_right = 0x04, + }; + using byte = unsigned char; using ucode_t = unsigned int; @@ -103,23 +138,19 @@ namespace litehtml { using vector = std::vector<position>; - int x; - int y; - int width; - int height; + int x = 0; + int y = 0; + int width = 0; + int height = 0; - position() - { - x = y = width = height = 0; - } + position() = default; - position(int x, int y, int width, int height) - { - this->x = x; - this->y = y; - this->width = width; - this->height = height; - } + position(int _x, int _y, int _width, int _height) : + x(_x), + y(_y), + width(_width), + height(_height) + {} int right() const { return x + width; } int bottom() const { return y + height; } @@ -152,12 +183,18 @@ namespace litehtml height = sz.height; } + bool operator==(const position& val) + { + return x == val.x && y == val.y && width == val.width && height == val.height; + } + void move_to(int _x, int _y) { x = _x; y = _y; } + [[nodiscard]] bool does_intersect(const position* val) const { if(!val) return true; @@ -174,45 +211,56 @@ namespace litehtml val->top() <= bottom() ); } - bool empty() const + [[nodiscard]] + position intersect(const position& src) const { - if(!width && !height) + position dest; + int dest_x = std::max(src.x, x); + int dest_y = std::max(src.y, y); + int dest_x2 = std::min(src.right(), right()); + int dest_y2 = std::min(src.bottom(), bottom()); + + if (dest_x2 > dest_x && dest_y2 > dest_y) { - return true; + dest.x = dest_x; + dest.y = dest_y; + dest.width = dest_x2 - dest_x; + dest.height = dest_y2 - dest_y; } - return false; + else + { + dest.width = 0; + dest.height = 0; + } + + return dest; } + [[nodiscard]] + bool empty() const + { + return !width && !height; + } + + [[nodiscard]] bool is_point_inside(int _x, int _y) const { - if(_x >= left() && _x < right() && _y >= top() && _y < bottom()) - { - return true; - } - return false; + return (_x >= left() && _x < right() && _y >= top() && _y < bottom()); } }; 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 font_size = 0; // Font size in pixels. The same as size argument of the create_font function + int height = 0; // Font height in pixels. + int ascent = 0; // The distance from the baseline to the top of a line of text. + int descent = 0; // The distance from the baseline to the bottom of a line of text. + int x_height = 0; // Height of the symbol x + int ch_width = 0; // Height of the symbol 0 + bool draw_spaces = true; // True to call draw text function for spaces. If False, just use space width without draw. + int sub_shift = 0; // The baseline shift for subscripts. + int super_shift = 0; // The baseline shift for superscripts. + int base_line() const { return descent; } }; @@ -830,6 +878,27 @@ namespace litehtml _baseline_type m_type; }; +#define appearance_strings "none;auto;menulist-button;textfield;button;checkbox;listbox;menulist;meter;progress-bar;push-button;radio;searchfield;slider-horizontal;square-button;textarea" + + enum appearance + { + appearance_none, + appearance_auto, + appearance_menulist_button, + appearance_textfield, + appearance_button, + appearance_checkbox, + appearance_listbox, + appearance_menulist, + appearance_meter, + appearance_progress_bar, + appearance_push_button, + appearance_radio, + appearance_searchfield, + appearance_slider_horizontal, + appearance_square_button, + appearance_textarea, + }; #define box_sizing_strings "content-box;border-box" diff --git a/libs/litehtml/include/litehtml/url.h b/libs/litehtml/include/litehtml/url.h index 83f98a752e..fae3db0a01 100644 --- a/libs/litehtml/include/litehtml/url.h +++ b/libs/litehtml/include/litehtml/url.h @@ -30,8 +30,6 @@ #ifndef LITEHTML_URL_H__ #define LITEHTML_URL_H__ -#include <ostream> - #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 6ba68b03b8..f936659186 100644 --- a/libs/litehtml/include/litehtml/url_path.h +++ b/libs/litehtml/include/litehtml/url_path.h @@ -30,8 +30,6 @@ #ifndef LITEHTML_URL_PATH_H__ #define LITEHTML_URL_PATH_H__ -#include <ostream> - #include "types.h" namespace litehtml { diff --git a/libs/litehtml/include/litehtml/web_color.h b/libs/litehtml/include/litehtml/web_color.h index 9bc198dbcd..ba59ae66db 100644 --- a/libs/litehtml/include/litehtml/web_color.h +++ b/libs/litehtml/include/litehtml/web_color.h @@ -1,6 +1,9 @@ #ifndef LH_WEB_COLOR_H #define LH_WEB_COLOR_H +#include "css_tokenizer.h" +#include "types.h" + namespace litehtml { class document_container; diff --git a/libs/litehtml/src/background.cpp b/libs/litehtml/src/background.cpp index 3ef69b862d..eaf115da72 100644 --- a/libs/litehtml/src/background.cpp +++ b/libs/litehtml/src/background.cpp @@ -1,8 +1,9 @@ #include <cmath> -#include "html.h" #include "background.h" #include "render_item.h" +#include "document.h" +#include "document_container.h" #ifndef M_PI # define M_PI 3.14159265358979323846 @@ -807,7 +808,7 @@ bool litehtml::background_layer::gradient_base::prepare_color_points(float line_ { if (!color_points.empty()) { - color_points.back().hint = item.length ? + color_points.back().hint = item.length ? normalize_length(*item.length, line_len) : *item.angle / 360; } diff --git a/libs/litehtml/src/css_parser.cpp b/libs/litehtml/src/css_parser.cpp index 24e49a78c8..3a78b00645 100644 --- a/libs/litehtml/src/css_parser.cpp +++ b/libs/litehtml/src/css_parser.cpp @@ -1,3 +1,4 @@ +#include "encodings.h" #include "html.h" #include "css_parser.h" @@ -38,7 +39,48 @@ void filter_code_points(string& input) input = result; } -void remove_whitespace(css_token_vector& tokens, keep_whitespace_fn keep_whitespace) +static const size_t kLargeSize = 50; +static void remove_whitespace_large(css_token_vector& tokens, keep_whitespace_fn keep_whitespace); +static void remove_whitespace_small(css_token_vector& tokens, keep_whitespace_fn keep_whitespace); + +void remove_whitespace_large(css_token_vector& tokens, keep_whitespace_fn keep_whitespace) +{ + std::vector<int> keep_idx; + keep_idx.reserve(tokens.size()); + for (int i = 0; i < static_cast<int>(tokens.size()); ++i) + { + auto &tok = tokens[i]; + bool keep = true; + if (tok.type == ' ') + { + const auto &left = i > 0 ? tokens[i - 1] : css_token(); + const auto &right = at(tokens, i + 1); + keep = keep_whitespace && keep_whitespace(left, right); + } + else if (tok.is_component_value()) + { + if (tok.value.size() > kLargeSize) + remove_whitespace_large(tok.value, keep_whitespace); + else + remove_whitespace_small(tok.value, keep_whitespace); + } + if (keep) + keep_idx.push_back(i); + } + + if (keep_idx.size() == tokens.size()) + return; + else + { + css_token_vector tmp; + tmp.reserve(keep_idx.size()); + for (auto idx : keep_idx) + tmp.push_back(tokens[idx]); + tokens.swap(tmp); + } +} + +void remove_whitespace_small(css_token_vector& tokens, keep_whitespace_fn keep_whitespace) { for (int i = 0; i < (int)tokens.size(); i++) { @@ -48,13 +90,27 @@ void remove_whitespace(css_token_vector& tokens, keep_whitespace_fn keep_whitesp const auto& left = i > 0 ? tokens[i - 1] : css_token(); const auto& right = at(tokens, i + 1); bool keep = keep_whitespace && keep_whitespace(left, right); - if (!keep) remove(tokens, i), i--; + if (!keep) + remove(tokens, i), i--; } else if (tok.is_component_value()) - remove_whitespace(tok.value, keep_whitespace); + { + if (tok.value.size() > kLargeSize) + remove_whitespace_large(tok.value, keep_whitespace); + else + remove_whitespace_small(tok.value, keep_whitespace); + } } } +void remove_whitespace(css_token_vector& tokens, keep_whitespace_fn keep_whitespace) +{ + if (tokens.size() > kLargeSize) + remove_whitespace_large(tokens, keep_whitespace); + else + remove_whitespace_small(tokens, keep_whitespace); +} + void componentize(css_token_vector& tokens) { css_parser parser(tokens); @@ -85,17 +141,17 @@ css_token_vector normalize(string input, int options, keep_whitespace_fn keep_wh } // https://www.w3.org/TR/css-syntax-3/#parse-stylesheet -// I don't create a stylesheet because its only perpose is to pass a list of rules to +// I don't create a stylesheet because its only perpose is to pass a list of rules to // parse_css_stylesheet. I just return the list of rules directly instead. raw_rule::vector css_parser::parse_stylesheet(const string& input, bool top_level) { // 1. If input is a byte stream for stylesheet, decode bytes from input, and set input to the result. // not implemented, utf-8 is always assumed string str = decode(input, encoding::utf_8); // decoding potentially broken UTF-8 into valid UTF-8 - + // 2. Normalize input, and set input to the result. auto tokens = normalize(str); - + return parse_stylesheet(tokens, top_level); } raw_rule::vector css_parser::parse_stylesheet(const css_token_vector& input, bool top_level) @@ -147,7 +203,7 @@ raw_rule::vector css_parser::consume_list_of_rules(bool top_level) // If the top-level flag is set, do nothing. if (top_level) break; - // Otherwise, reconsume the current input token. Consume a qualified rule. + // Otherwise, reconsume the current input token. Consume a qualified rule. // If anything is returned, append it to the list of rules. m_index--; rule = consume_qualified_rule(); @@ -208,7 +264,7 @@ raw_rule::ptr css_parser::consume_qualified_rule() // https://www.w3.org/TR/css-syntax-3/#consume-at-rule raw_rule::ptr css_parser::consume_at_rule() { - // Consume the next input token. Create a new at-rule with its name set to the value of the current input token, + // Consume the next input token. Create a new at-rule with its name set to the value of the current input token, // its prelude initially set to an empty list, and its value initially set to nothing. css_token token = next_token(); raw_rule::ptr rule = make_shared<raw_rule>(raw_rule::at, token.str); @@ -251,7 +307,7 @@ css_token css_parser::consume_simple_block(char opening_bracket) // Create a simple block with its associated token set to the current input token and with its value initially set to an empty list. auto block_type = css_token_type(-100 - opening_bracket); // see css_token_type css_token block(block_type); - + char closing_bracket = mirror(opening_bracket); while (true) @@ -289,11 +345,11 @@ css_token css_parser::consume_component_value() // If the current input token is a <{-token>, <[-token>, or <(-token>, consume a simple block and return it. case '{': case '[': case '(': return consume_simple_block((char)token.ch); - + // Otherwise, if the current input token is a <function-token>, consume a function and return it. case FUNCTION: return consume_function(token.name); - + // Otherwise, return the current input token. default: return token; @@ -343,7 +399,7 @@ void trim_whitespace(css_token_vector& tokens) // next token is guaranteed to be IDENT raw_declaration css_parser::consume_declaration() { - // Consume the next input token. Create a new declaration with its name set to the value of + // Consume the next input token. Create a new declaration with its name set to the value of // the current input token and its value initially set to an empty list. css_token token = next_token(); raw_declaration decl = {token.name}; @@ -364,13 +420,13 @@ raw_declaration css_parser::consume_declaration() // 3. While the next input token is a <whitespace-token>, consume the next input token. while (peek_token().type == ' ') next_token(); - // 4. As long as the next input token is anything other than an <EOF-token>, + // 4. As long as the next input token is anything other than an <EOF-token>, // consume a component value and append it to the declaration’s value. while (peek_token().type != EOF) value.push_back(consume_component_value()); - // 5. If the last two non-<whitespace-token>s in the declaration’s value are a <delim-token> with the value "!" - // followed by an <ident-token> with a value that is an ASCII case-insensitive match for "important", + // 5. If the last two non-<whitespace-token>s in the declaration’s value are a <delim-token> with the value "!" + // followed by an <ident-token> with a value that is an ASCII case-insensitive match for "important", // remove them from the declaration’s value and set the declaration’s important flag to true. trim_whitespace(value); // deviation from standard: removing leading whitespace as well @@ -417,7 +473,7 @@ void css_parser::consume_style_block_contents(/*out*/ raw_declaration::vector& d case IDENT: { // Initialize a temporary list initially filled with the current input token. css_token_vector temp = { token }; - // As long as the next input token is anything other than a <semicolon-token> or <EOF-token>, + // As long as the next input token is anything other than a <semicolon-token> or <EOF-token>, // consume a component value and append it to the temporary list. while (!is_one_of(peek_token().type, ';', EOF)) temp.push_back(consume_component_value()); @@ -437,7 +493,7 @@ void css_parser::consume_style_block_contents(/*out*/ raw_declaration::vector& d break; } default: - // This is a parse error. Reconsume the current input token. As long as the next input token is + // This is a parse error. Reconsume the current input token. As long as the next input token is // anything other than a <;> or <EOF>, consume a component value and throw away the returned value. css_parse_error("unexpected token in a style block"); m_index--; @@ -511,4 +567,4 @@ bool skip_whitespace(const css_token_vector& tokens, int& index) return index != start; } -} // namespace litehtml
\ No newline at end of file +} // namespace litehtml diff --git a/libs/litehtml/src/css_properties.cpp b/libs/litehtml/src/css_properties.cpp index 9100a998e0..6014babb3b 100644 --- a/libs/litehtml/src/css_properties.cpp +++ b/libs/litehtml/src/css_properties.cpp @@ -1,13 +1,15 @@ #include "html.h" #include "css_properties.h" #include <cmath> +#include "document.h" +#include "html_tag.h" +#include "document_container.h" #define offset(member) ((uint_ptr)&this->member - (uint_ptr)this) +//#define offset(func) [](const css_properties& css) { return css.func; } void litehtml::css_properties::compute(const html_tag* el, const document::ptr& doc) { - compute_font(el, doc); - int font_size = get_font_size(); m_color = el->get_property<web_color>(_color_, true, web_color::black, offset(m_color)); m_el_position = (element_position) el->get_property<int>( _position_, false, element_position_static, offset(m_el_position)); @@ -15,6 +17,7 @@ void litehtml::css_properties::compute(const html_tag* el, const document::ptr& m_visibility = (visibility) el->get_property<int>( _visibility_, true, visibility_visible, offset(m_visibility)); m_float = (element_float) el->get_property<int>( _float_, false, float_none, offset(m_float)); m_clear = (element_clear) el->get_property<int>( _clear_, false, clear_none, offset(m_clear)); + m_appearance = (appearance) el->get_property<int>( _appearance_, false, appearance_none, offset(m_appearance)); m_box_sizing = (box_sizing) el->get_property<int>( _box_sizing_, false, box_sizing_content_box, offset(m_box_sizing)); m_overflow = (overflow) el->get_property<int>( _overflow_, false, overflow_visible, offset(m_overflow)); m_text_align = (text_align) el->get_property<int>( _text_align_, true, text_align_left, offset(m_text_align)); @@ -97,10 +100,16 @@ void litehtml::css_properties::compute(const html_tag* el, const document::ptr& { m_display = display_block; } + } else if(el->is_replaced() && m_display == display_inline) + { + m_display = display_inline_block; } } // 5. Otherwise, the remaining 'display' property values apply as specified. + compute_font(el, doc); + int font_size = get_font_size(); + const css_length _auto = css_length::predef_value(0); const css_length none = _auto, normal = _auto; @@ -217,17 +226,17 @@ void litehtml::css_properties::compute(const html_tag* el, const document::ptr& m_css_text_indent = el->get_property<css_length>(_text_indent_, true, 0, offset(m_css_text_indent)); doc->cvt_units(m_css_text_indent, m_font_metrics, 0); - m_css_line_height = el->get_property<css_length>(_line_height_, true, normal, offset(m_css_line_height)); - if(m_css_line_height.is_predefined()) + m_line_height.css_value = el->get_property<css_length>(_line_height_, true, normal, offset(m_line_height.css_value)); + if(m_line_height.css_value.is_predefined()) { - m_line_height = m_font_metrics.height; - } else if(m_css_line_height.units() == css_units_none) + m_line_height.computed_value = m_font_metrics.height; + } else if(m_line_height.css_value.units() == css_units_none) { - m_line_height = (int) std::nearbyint(m_css_line_height.val() * font_size); + m_line_height.computed_value = (int) std::nearbyint(m_line_height.css_value.val() * font_size); } else { - m_line_height = doc->to_pixels(m_css_line_height, m_font_metrics, m_font_metrics.font_size); - m_css_line_height = (float) m_line_height; + m_line_height.computed_value = doc->to_pixels(m_line_height.css_value, m_font_metrics, m_font_metrics.font_size); + m_line_height.css_value = (float) m_line_height.computed_value; } m_list_style_type = (list_style_type) el->get_property<int>(_list_style_type_, true, list_style_type_disc, offset(m_list_style_type)); @@ -281,7 +290,7 @@ void litehtml::css_properties::compute_font(const html_tag* el, const document:: { parent_sz = doc_font_size; } - + int font_size = parent_sz; if(sz.is_predefined()) @@ -347,22 +356,96 @@ void litehtml::css_properties::compute_font(const html_tag* el, const document:: font_size = doc->to_pixels(sz, fm, 0); } } - + m_font_size = (float)font_size; // initialize font m_font_family = el->get_property<string>( _font_family_, true, doc->container()->get_default_font_name(), offset(m_font_family)); m_font_weight = el->get_property<css_length>(_font_weight_, true, css_length::predef_value(font_weight_normal), offset(m_font_weight)); m_font_style = (font_style) el->get_property<int>( _font_style_, true, font_style_normal, offset(m_font_style)); - m_text_decoration = el->get_property<string>( _text_decoration_, true, "none", offset(m_text_decoration)); - - m_font = doc->get_font( - m_font_family.c_str(), - font_size, - m_font_weight.is_predefined() ? index_value(m_font_weight.predef(), font_weight_strings).c_str() : std::to_string(m_font_weight.val()).c_str(), - index_value(m_font_style, font_style_strings).c_str(), - m_text_decoration.c_str(), - &m_font_metrics); + bool propagate_decoration = !is_one_of(m_display, display_inline_block, display_inline_table, display_inline_flex) && + m_float == float_none && !is_one_of(m_el_position, element_position_absolute, element_position_fixed); + + m_text_decoration_line = el->get_property<int>(_text_decoration_line_, propagate_decoration, text_decoration_line_none, offset(m_text_decoration_line)); + + // Merge parent text decoration with child text decoration + if (propagate_decoration && el->parent()) + { + m_text_decoration_line |= el->parent()->css().get_text_decoration_line(); + } + + if(m_text_decoration_line) + { + m_text_decoration_thickness = el->get_property<css_length>(_text_decoration_thickness_, propagate_decoration, css_length::predef_value(text_decoration_thickness_auto), offset(m_text_decoration_thickness)); + m_text_decoration_style = (text_decoration_style) el->get_property<int>(_text_decoration_style_, propagate_decoration, text_decoration_style_solid, offset(m_text_decoration_style)); + m_text_decoration_color = get_color_property(el, _text_decoration_color_, propagate_decoration, web_color::current_color, offset(m_text_decoration_color)); + } else + { + m_text_decoration_thickness = css_length::predef_value(text_decoration_thickness_auto); + m_text_decoration_color = web_color::current_color; + } + + // text-emphasis + m_text_emphasis_style = el->get_property<string>(_text_emphasis_style_, true, "", offset(m_text_emphasis_style)); + m_text_emphasis_position = el->get_property<int>(_text_emphasis_position_, true, text_emphasis_position_over, offset(m_text_emphasis_position)); + m_text_emphasis_color = get_color_property(el, _text_emphasis_color_, true, web_color::current_color, offset(m_text_emphasis_color)); + + if(el->parent()) + { + if(m_text_emphasis_style.empty() || m_text_emphasis_style == "initial" || m_text_emphasis_style == "unset") + { + m_text_emphasis_style = el->parent()->css().get_text_emphasis_style(); + } + if(m_text_emphasis_color == web_color::current_color) + { + m_text_emphasis_color = el->parent()->css().get_text_emphasis_color(); + } + m_text_emphasis_position |= el->parent()->css().get_text_emphasis_position(); + } + + if(m_font_weight.is_predefined()) + { + switch(m_font_weight.predef()) + { + case font_weight_bold: + m_font_weight = 700; + break; + case font_weight_bolder: + { + const int inherited = (int) el->parent()->css().m_font_weight.val(); + if(inherited < 400) m_font_weight = 400; + else if(inherited >= 400 && inherited < 600) m_font_weight = 700; + else m_font_weight = 900; + } + break; + case font_weight_lighter: + { + const int inherited = (int) el->parent()->css().m_font_weight.val(); + if(inherited < 600) m_font_weight = 100; + else if(inherited >= 600 && inherited < 800) m_font_weight = 400; + else m_font_weight = 700; + } + break; + default: + m_font_weight = 400; + break; + } + } + + font_description descr; + descr.family = m_font_family; + descr.size = font_size; + descr.style = m_font_style; + descr.weight = (int) m_font_weight.val(); + descr.decoration_line = m_text_decoration_line; + descr.decoration_thickness = m_text_decoration_thickness; + descr.decoration_style = m_text_decoration_style; + descr.decoration_color = m_text_decoration_color; + descr.emphasis_style = m_text_emphasis_style; + descr.emphasis_color = m_text_emphasis_color; + descr.emphasis_position = m_text_emphasis_position; + + m_font = doc->get_font(descr, &m_font_metrics); } void litehtml::css_properties::compute_background(const html_tag* el, const document::ptr& doc) @@ -462,6 +545,7 @@ std::vector<std::tuple<litehtml::string, litehtml::string>> litehtml::css_proper ret.emplace_back("overflow", index_value(m_overflow, overflow_strings)); ret.emplace_back("white_space", index_value(m_white_space, white_space_strings)); ret.emplace_back("visibility", index_value(m_visibility, visibility_strings)); + ret.emplace_back("appearance", index_value(m_appearance, appearance_strings)); ret.emplace_back("box_sizing", index_value(m_box_sizing, box_sizing_strings)); ret.emplace_back("z_index", m_z_index.to_string()); ret.emplace_back("vertical_align", index_value(m_vertical_align, vertical_align_strings)); @@ -478,7 +562,7 @@ std::vector<std::tuple<litehtml::string, litehtml::string>> litehtml::css_proper ret.emplace_back("max_height", m_css_max_width.to_string()); ret.emplace_back("offsets", m_css_offsets.to_string()); ret.emplace_back("text_indent", m_css_text_indent.to_string()); - ret.emplace_back("line_height", std::to_string(m_line_height)); + ret.emplace_back("line_height", std::to_string(m_line_height.computed_value)); ret.emplace_back("list_style_type", index_value(m_list_style_type, list_style_type_strings)); ret.emplace_back("list_style_position", index_value(m_list_style_position, list_style_position_strings)); ret.emplace_back("border_spacing_x", m_css_border_spacing_x.to_string()); diff --git a/libs/litehtml/src/css_selector.cpp b/libs/litehtml/src/css_selector.cpp index 43e5a5e33d..56a11e337d 100644 --- a/libs/litehtml/src/css_selector.cpp +++ b/libs/litehtml/src/css_selector.cpp @@ -2,6 +2,8 @@ #include "css_selector.h" #include "css_parser.h" #include "internal.h" +#include "document.h" +#include <set> namespace litehtml { @@ -20,7 +22,7 @@ void css_selector::calc_specificity() } else { m_specificity.c++; - } + } } if(m_left) { @@ -273,17 +275,17 @@ bool to_int(string s, int& number) const char* ptr = s.c_str(); char* end; int n = strtol(ptr, &end, 10); - + if (end != ptr + s.size()) return false; - + number = n; return true; } // https://www.w3.org/TR/css-syntax-3/#anb-syntax // I don't use the formal grammar because it creates a lot of unnecessary complexity. -// Deviations from the standard: +// Deviations from the standard: // * escapes are not allowed // * comments are allowed inside numbers and identifiers: ev/**/en an_b parse_an_b(string s) @@ -336,9 +338,9 @@ int find_of_keyword(const css_token_vector& tokens) } // :nth-child(An+B [of S]?) https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo -// :nth-last-child(An+B [of S]?) +// :nth-last-child(An+B [of S]?) // where S is a forgiving <complex-selector-list> -// +// // :nth-of-type(An+B) https://www.w3.org/TR/selectors-4/#the-nth-of-type-pseudo // :nth-last-of-type(An+B) // @@ -356,7 +358,7 @@ css_attribute_selector parse_nth_child(const css_token& token, bool of_keyword, // The standard doesn't specify if pseudo-elements are allowed in this selector list. // But specifying them will make selector match nothing anyway because - // "The structural pseudo-classes only apply to elements in the document tree; + // "The structural pseudo-classes only apply to elements in the document tree; // they must never match pseudo-elements." https://www.w3.org/TR/selectors-4/#structural-pseudos // So I parse as if they were not allowed. selector.selector_list = parse_selector_list(selector_tokens, forgiving_mode + forbid_pseudo_elements, mode); @@ -374,10 +376,10 @@ css_attribute_selector parse_nth_child(const css_token& token, bool of_keyword, an_b x = parse_an_b(str); if (!x.valid) return {}; - + selector.a = x.a; selector.b = x.b; - + return selector; } @@ -540,7 +542,7 @@ css_attribute_selector parse_pseudo_element(const css_token_vector& tokens, int& { if (!is_one_of(b.ident(), "before", "after")) // first-line/letter are not supported return {}; - + index += 2; return {select_pseudo_element, b.ident()}; } @@ -575,7 +577,7 @@ css_element_selector::ptr parse_compound_selector(const css_token_vector& tokens // <subclass-selector>* while (css_attribute_selector sel = parse_subclass_selector(tokens, index, mode)) selector->m_attrs.push_back(sel); - + // [ <pseudo-element-selector> <pseudo-class-selector>* ]* while (true) { @@ -613,7 +615,7 @@ int parse_combinator(const css_token_vector& tokens, int& index) skip_whitespace(tokens, index); return tok.ch; } - + return ws ? ' ' : 0; } @@ -662,10 +664,10 @@ bool has_selector(const css_selector& selector, attr_select_type type, const str if (sel.type == type && (name == "" || equal_i(_s(sel.name), name))) return true; } - + if (selector.m_left) return has_selector(*selector.m_left, type, name); - + return false; } @@ -691,7 +693,7 @@ css_selector::vector parse_selector_list(const css_token_vector& tokens, int opt // in forgiving mode, ignore the bad selector if (options & forgiving_mode) continue; - + // in strict mode, entire selector-list fails to parse because of one bad selector return {}; } diff --git a/libs/litehtml/src/css_tokenizer.cpp b/libs/litehtml/src/css_tokenizer.cpp index b2b8761fa4..3daf31f7d0 100644 --- a/libs/litehtml/src/css_tokenizer.cpp +++ b/libs/litehtml/src/css_tokenizer.cpp @@ -1,4 +1,5 @@ #include "html.h" +#include "utf8_strings.h" #include "css_tokenizer.h" namespace litehtml @@ -118,7 +119,7 @@ void css_tokenizer::consume_comments() if (str[index] == '/' && str[index + 1] == '*') { int i = (int)str.find("*/", index + 2); - + if (i != -1) index = i + 2; else @@ -199,7 +200,7 @@ css_token css_tokenizer::consume_string_token(int ending_code_point) // Otherwise, if the next input code point is a newline, consume it. else if (str[index] == '\n') index++; - // Otherwise, (the stream starts with a valid escape) consume an escaped code point and + // Otherwise, (the stream starts with a valid escape) consume an escaped code point and // append the returned code point to the <string-token>’s value. else append_char(token.str, consume_escaped_code_point()); @@ -224,7 +225,7 @@ bool css_tokenizer::would_start_ident_sequence(three_chars chars) if (c1 == '-') { - // If the second code point is an ident-start code point or a U+002D HYPHEN-MINUS, or + // If the second code point is an ident-start code point or a U+002D HYPHEN-MINUS, or // the second and third code points are a valid escape, return true. Otherwise, return false. return is_ident_start_code_point(c2) || c2 == '-' || (c2 == '\\' && c3 != '\n'); } @@ -291,13 +292,13 @@ double css_tokenizer::convert_string_to_number(const string& str) // Divide the string into seven components, in order from left to right: - // 1. A sign: a single U+002B (+) or U+002D (-), or the empty string. + // 1. A sign: a single U+002B (+) or U+002D (-), or the empty string. // Let s be the number -1 if the sign is U+002D (-); otherwise, let s be the number 1. double s = 1; if (*p == '-') s = -1, p++; else if (*p == '+') p++; - // 2. An integer part: zero or more digits. If there is at least one digit, let i be the number formed by + // 2. An integer part: zero or more digits. If there is at least one digit, let i be the number formed by // interpreting the digits as a base-10 integer; otherwise, let i be the number 0. double i = 0; while (is_digit(*p)) i = i * 10 + digit_value(*p++); @@ -305,8 +306,8 @@ double css_tokenizer::convert_string_to_number(const string& str) // 3. A decimal point: a single U+002E (.), or the empty string. if (*p == '.') p++; - // 4. A fractional part: zero or more digits. If there is at least one digit, let f be the number formed by - // interpreting the digits as a base-10 integer and d be the number of digits; + // 4. A fractional part: zero or more digits. If there is at least one digit, let f be the number formed by + // interpreting the digits as a base-10 integer and d be the number of digits; // otherwise, let f and d be the number 0. double f = 0, d = 0; while (is_digit(*p)) f = f * 10 + digit_value(*p++), d++; @@ -314,13 +315,13 @@ double css_tokenizer::convert_string_to_number(const string& str) // 5. An exponent indicator: a single U+0045 (E) or U+0065 (e), or the empty string. if (*p == 'e' || *p == 'E') p++; - // 6. An exponent sign: a single U+002B (+) or U+002D (-), or the empty string. + // 6. An exponent sign: a single U+002B (+) or U+002D (-), or the empty string. // Let t be the number -1 if the sign is U+002D (-); otherwise, let t be the number 1. double t = 1; if (*p == '-') t = -1, p++; else if (*p == '+') p++; - // 7. An exponent: zero or more digits. If there is at least one digit, let e be the number formed by + // 7. An exponent: zero or more digits. If there is at least one digit, let e be the number formed by // interpreting the digits as a base-10 integer; otherwise, let e be the number 0. double e = 0; while (is_digit(*p)) e = e * 10 + digit_value(*p++); @@ -358,11 +359,11 @@ double css_tokenizer::consume_number(css_number_type& type) append_char(repr, str[index++]); } - // 5. If the next 2 or 3 input code points are U+0045 (E) or U+0065 (e), + // 5. If the next 2 or 3 input code points are U+0045 (E) or U+0065 (e), // optionally followed by U+002D (-) or U+002B (+), followed by a digit, then: bool a = lowcase(str[index]) == 'e' && is_one_of(str[index+1], '+', '-') && is_digit(str[index+2]); bool b = lowcase(str[index]) == 'e' && is_digit(str[index+1]); - + if (a || b) { // 1. Consume them. @@ -394,7 +395,7 @@ css_token css_tokenizer::consume_numeric_token() // If the next 3 input code points would start an ident sequence, then: if (would_start_ident_sequence(peek_chars())) { - // 1. Create a <dimension-token> with the same value and type flag as number, and + // 1. Create a <dimension-token> with the same value and type flag as number, and // a unit set initially to the empty string. css_token token(DIMENSION, number, type); @@ -405,7 +406,7 @@ css_token css_tokenizer::consume_numeric_token() return token; } - // Otherwise, if the next input code point is U+0025 (%), consume it. + // Otherwise, if the next input code point is U+0025 (%), consume it. // Create a <percentage-token> with the same value as number, and return it. if (str[index] == '%') { @@ -491,7 +492,7 @@ css_token css_tokenizer::consume_url_token() return {BAD_URL}; case '\\': - // If the stream starts with a valid escape, consume an escaped code point and + // If the stream starts with a valid escape, consume an escaped code point and // append the returned code point to the <url-token>’s value. if (str[index] != '\n') append_char(token.str, consume_escaped_code_point()); @@ -522,7 +523,7 @@ css_token css_tokenizer::consume_ident_like_token() // Consume an ident sequence, and let string be the result. auto string = consume_ident_sequence(); - // If string’s value is an ASCII case-insensitive match for "url", and the next input code point is + // If string’s value is an ASCII case-insensitive match for "url", and the next input code point is // U+0028 ((), consume it. if (lowcase(string) == "url" && str[index] == '(') { @@ -543,7 +544,7 @@ css_token css_tokenizer::consume_ident_like_token() } } - // Otherwise, if the next input code point is U+0028 ((), consume it. + // Otherwise, if the next input code point is U+0028 ((), consume it. // Create a <function-token> with its value set to string and return it. else if (str[index] == '(') { @@ -629,7 +630,7 @@ css_token css_tokenizer::consume_token() index += 2; token.type = CDC; } - // Otherwise, if the input stream starts with an ident sequence, reconsume the current input code point, + // Otherwise, if the input stream starts with an ident sequence, reconsume the current input code point, // consume an ident-like token, and return it. else if (would_start_ident_sequence({ ch, next._1, next._2 })) { @@ -654,7 +655,7 @@ css_token css_tokenizer::consume_token() break; case '@': - // If the next 3 input code points would start an ident sequence, consume an ident sequence, + // If the next 3 input code points would start an ident sequence, consume an ident sequence, // create an <at-keyword-token> with its value set to the returned value, and return it. if (would_start_ident_sequence(peek_chars())) { @@ -667,7 +668,7 @@ css_token css_tokenizer::consume_token() break; case '\\': - // If the input stream starts with a valid escape, reconsume the current input code point, + // If the input stream starts with a valid escape, reconsume the current input code point, // consume an ident-like token, and return it. if (str[index] != '\n') { diff --git a/libs/litehtml/src/document.cpp b/libs/litehtml/src/document.cpp index 13bfe0e991..d498914081 100644 --- a/libs/litehtml/src/document.cpp +++ b/libs/litehtml/src/document.cpp @@ -25,6 +25,7 @@ #include "render_item.h" #include "render_table.h" #include "render_block.h" +#include "document_container.h" namespace litehtml { @@ -36,13 +37,20 @@ document::document(document_container* container) document::~document() { - m_over_element = nullptr; + m_over_element = m_active_element = nullptr; + if(m_container) + { + for(auto& font : m_fonts) + { + m_container->delete_font(font.second.font); + } + } } document::ptr document::createFromString( - const estring& str, - document_container* container, - const string& master_styles, + const estring& str, + document_container* container, + const string& master_styles, const string& user_styles ) { // Create litehtml::document @@ -125,7 +133,7 @@ document::ptr document::createFromString( doc->m_root_render = doc->m_root->create_render_item(nullptr); // Now the m_tabular_elements is filled with tabular elements. - // We have to check the tabular elements for missing table elements + // We have to check the tabular elements for missing table elements // and create the anonymous boxes in visual table layout doc->fix_tables_layout(); @@ -209,7 +217,7 @@ GumboOutput* document::parse_html(estring str) { // https://html.spec.whatwg.org/multipage/parsing.html#the-input-byte-stream encoding_sniffing_algorithm(str); - // cannot store output in local variable because gumbo keeps pointers into it, + // cannot store output in local variable because gumbo keeps pointers into it, // which will be accessed later in gumbo_tag_from_original_text if (str.encoding == encoding::utf_8) m_text = str; @@ -434,83 +442,18 @@ element::ptr document::create_element(const char* tag_name, const string_map& at return newTag; } -uint_ptr document::add_font( const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm ) +uint_ptr document::add_font( const font_description& descr, font_metrics* fm ) { uint_ptr ret = 0; - if(!name) - { - name = m_container->get_default_font_name(); - } - - char strSize[20]; - t_itoa(size, strSize, 20, 10); + std::string key = descr.hash(); - string key = name; - key += ":"; - key += strSize; - key += ":"; - key += weight; - key += ":"; - key += style; - key += ":"; - key += decoration; - - if(m_container->m_fonts.find(key) == m_container->m_fonts.end()) + if(m_fonts.find(key) == m_fonts.end()) { - font_style fs = (font_style) value_index(style, font_style_strings, font_style_normal); - int fw = value_index(weight, font_weight_strings, -1); - if(fw >= 0) - { - switch(fw) - { - case font_weight_bold: - fw = 700; - break; - case font_weight_bolder: - fw = 600; - break; - case font_weight_lighter: - fw = 300; - break; - case font_weight_normal: - fw = 400; - break; - } - } else - { - fw = atoi(weight); - if(fw < 100) - { - fw = 400; - } - } - - unsigned int decor = 0; + font_item fi = {0, {}}; - if(decoration) - { - std::vector<string> tokens; - split_string(decoration, tokens, " "); - for(auto & token : tokens) - { - if(!t_strcasecmp(token.c_str(), "underline")) - { - decor |= font_decoration_underline; - } else if(!t_strcasecmp(token.c_str(), "line-through")) - { - decor |= font_decoration_linethrough; - } else if(!t_strcasecmp(token.c_str(), "overline")) - { - decor |= font_decoration_overline; - } - } - } - - font_item fi= {0, {}}; - - fi.font = m_container->create_font(name, size, fw, fs, decor, &fi.metrics); - m_container->m_fonts[key] = fi; + fi.font = m_container->create_font(descr, this, &fi.metrics); + m_fonts[key] = fi; ret = fi.font; if(fm) { @@ -520,33 +463,18 @@ uint_ptr document::add_font( const char* name, int size, const char* weight, con return ret; } -uint_ptr document::get_font( const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm ) +uint_ptr document::get_font( const font_description& descr, font_metrics* fm ) { - if(!size) + if(!descr.size) { return 0; } - if(!name) - { - name = m_container->get_default_font_name(); - } - - char strSize[20]; - t_itoa(size, strSize, 20, 10); - string key = name; - key += ":"; - key += strSize; - key += ":"; - key += weight; - key += ":"; - key += style; - key += ":"; - key += decoration; + auto key = descr.hash(); - auto el = m_container->m_fonts.find(key); + auto el = m_fonts.find(key); - if(el != m_container->m_fonts.end()) + if(el != m_fonts.end()) { if(fm) { @@ -554,7 +482,7 @@ uint_ptr document::get_font( const char* name, int size, const char* weight, con } return el->second.font; } - return add_font(name, size, weight, style, decoration, fm); + return add_font(descr, fm); } int document::render( int max_width, render_type rt ) @@ -562,12 +490,12 @@ int document::render( int max_width, render_type rt ) int ret = 0; if(m_root && m_root_render) { - position client_rc; - m_container->get_client_rect(client_rc); + position viewport; + m_container->get_viewport(viewport); containing_block_context cb_context; cb_context.width = max_width; cb_context.width.type = containing_block_context::cbc_value_type_absolute; - cb_context.height = client_rc.height; + cb_context.height = viewport.height; cb_context.height.type = containing_block_context::cbc_value_type_absolute; if(rt == render_fixed_only) @@ -737,9 +665,9 @@ bool document::on_mouse_over( int x, int y, int client_x, int client_y, position } cursor = m_over_element->css().get_cursor(); } - + m_container->set_cursor(cursor.c_str()); - + if(state_was_changed) { m_container->on_mouse_event(m_over_element, mouse_event_enter); @@ -773,6 +701,7 @@ bool document::on_lbutton_down( int x, int y, int client_x, int client_y, positi } element::ptr over_el = m_root_render->get_element_by_point(x, y, client_x, client_y); + m_active_element = over_el; bool state_was_changed = false; @@ -826,7 +755,7 @@ bool document::on_lbutton_up( int /*x*/, int /*y*/, int /*client_x*/, int /*clie } if(m_over_element) { - if(m_over_element->on_lbutton_up()) + if(m_over_element->on_lbutton_up(m_active_element == m_over_element)) { return m_root->find_styles_changes(redraw_boxes); } @@ -834,6 +763,26 @@ bool document::on_lbutton_up( int /*x*/, int /*y*/, int /*client_x*/, int /*clie return false; } +bool document::on_button_cancel(position::vector& redraw_boxes) { + if(!m_root || !m_root_render) + { + return false; + } + m_active_element = nullptr; + if(m_over_element) + { + if(m_over_element->on_mouse_leave()) + { + m_container->on_mouse_event(m_over_element, mouse_event_leave); + } + if(m_over_element->on_lbutton_up(false)) + { + return m_root->find_styles_changes(redraw_boxes); + } + } + return false; +} + void document::get_fixed_boxes( position::vector& fixed_boxes ) { fixed_boxes = m_fixed_boxes; @@ -1129,7 +1078,7 @@ void document::append_children_from_string(element& parent, const char* str) child->compute_styles(); // Now the m_tabular_elements is filled with tabular elements. - // We have to check the tabular elements for missing table elements + // We have to check the tabular elements for missing table elements // and create the anonymous boxes in visual table layout fix_tables_layout(); diff --git a/libs/litehtml/src/document_container.cpp b/libs/litehtml/src/document_container.cpp index 8c3aea61bd..95f45c62cb 100644 --- a/libs/litehtml/src/document_container.cpp +++ b/libs/litehtml/src/document_container.cpp @@ -1,4 +1,4 @@ -#include "html.h" +#include "utf8_strings.h" #include "document_container.h" void litehtml::document_container::split_text(const char* text, const std::function<void(const char*)>& on_word, const std::function<void(const char*)>& on_space) diff --git a/libs/litehtml/src/el_anchor.cpp b/libs/litehtml/src/el_anchor.cpp index 372e4afb50..2491c60033 100644 --- a/libs/litehtml/src/el_anchor.cpp +++ b/libs/litehtml/src/el_anchor.cpp @@ -1,6 +1,6 @@ -#include "html.h" #include "el_anchor.h" #include "document.h" +#include "document_container.h" litehtml::el_anchor::el_anchor(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc) { diff --git a/libs/litehtml/src/el_base.cpp b/libs/litehtml/src/el_base.cpp index baf0256539..b2db13e09f 100644 --- a/libs/litehtml/src/el_base.cpp +++ b/libs/litehtml/src/el_base.cpp @@ -1,10 +1,10 @@ -#include "html.h" #include "el_base.h" #include "document.h" +#include "document_container.h" litehtml::el_base::el_base(const std::shared_ptr<document>& doc) : html_tag(doc) { - + } void litehtml::el_base::parse_attributes() diff --git a/libs/litehtml/src/el_body.cpp b/libs/litehtml/src/el_body.cpp index 3d35f8f758..899f27f041 100644 --- a/libs/litehtml/src/el_body.cpp +++ b/libs/litehtml/src/el_body.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_body.h" #include "document.h" diff --git a/libs/litehtml/src/el_break.cpp b/libs/litehtml/src/el_break.cpp index f13b2e3cf8..f190d06c1b 100644 --- a/libs/litehtml/src/el_break.cpp +++ b/libs/litehtml/src/el_break.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_break.h" litehtml::el_break::el_break(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc) diff --git a/libs/litehtml/src/el_cdata.cpp b/libs/litehtml/src/el_cdata.cpp index e5948bff13..c3b431b3f7 100644 --- a/libs/litehtml/src/el_cdata.cpp +++ b/libs/litehtml/src/el_cdata.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_cdata.h" litehtml::el_cdata::el_cdata(const std::shared_ptr<document>& doc) : element(doc) diff --git a/libs/litehtml/src/el_comment.cpp b/libs/litehtml/src/el_comment.cpp index 1ec934d046..1a29a51662 100644 --- a/libs/litehtml/src/el_comment.cpp +++ b/libs/litehtml/src/el_comment.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_comment.h" litehtml::el_comment::el_comment(const std::shared_ptr<document>& doc) : element(doc) diff --git a/libs/litehtml/src/el_div.cpp b/libs/litehtml/src/el_div.cpp index 983d45ab2a..a23681cd1d 100644 --- a/libs/litehtml/src/el_div.cpp +++ b/libs/litehtml/src/el_div.cpp @@ -1,5 +1,5 @@ -#include "html.h" #include "el_div.h" +#include "document.h" litehtml::el_div::el_div(const document::ptr& doc) : html_tag(doc) diff --git a/libs/litehtml/src/el_font.cpp b/libs/litehtml/src/el_font.cpp index 3d5f6d9f73..e8e1f7e231 100644 --- a/libs/litehtml/src/el_font.cpp +++ b/libs/litehtml/src/el_font.cpp @@ -1,5 +1,5 @@ -#include "html.h" #include "el_font.h" +#include "document.h" litehtml::el_font::el_font(const std::shared_ptr<document>& doc) : html_tag(doc) diff --git a/libs/litehtml/src/el_image.cpp b/libs/litehtml/src/el_image.cpp index 0dee84e011..7ac81193bb 100644 --- a/libs/litehtml/src/el_image.cpp +++ b/libs/litehtml/src/el_image.cpp @@ -1,6 +1,6 @@ -#include "html.h" #include "el_image.h" #include "render_image.h" +#include "document_container.h" litehtml::el_image::el_image(const document::ptr& doc) : html_tag(doc) { @@ -82,4 +82,4 @@ std::shared_ptr<litehtml::render_item> litehtml::el_image::create_render_item(co auto ret = std::make_shared<render_item_image>(shared_from_this()); ret->parent(parent_ri); return ret; -} +}
\ No newline at end of file diff --git a/libs/litehtml/src/el_link.cpp b/libs/litehtml/src/el_link.cpp index aa3bc76597..2783feafca 100644 --- a/libs/litehtml/src/el_link.cpp +++ b/libs/litehtml/src/el_link.cpp @@ -1,7 +1,7 @@ -#include "html.h" #include "el_link.h" #include "document.h" - +#include "document_container.h" +#include <cstring> litehtml::el_link::el_link(const std::shared_ptr<document>& doc) : litehtml::html_tag(doc) { diff --git a/libs/litehtml/src/el_para.cpp b/libs/litehtml/src/el_para.cpp index 5d79151351..0362be9dfd 100644 --- a/libs/litehtml/src/el_para.cpp +++ b/libs/litehtml/src/el_para.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_para.h" #include "document.h" diff --git a/libs/litehtml/src/el_script.cpp b/libs/litehtml/src/el_script.cpp index 4b598a137e..857e47fc5f 100644 --- a/libs/litehtml/src/el_script.cpp +++ b/libs/litehtml/src/el_script.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_script.h" #include "document.h" diff --git a/libs/litehtml/src/el_style.cpp b/libs/litehtml/src/el_style.cpp index cc2f0bab6d..f0fbc66fa2 100644 --- a/libs/litehtml/src/el_style.cpp +++ b/libs/litehtml/src/el_style.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "el_style.h" #include "document.h" @@ -21,8 +20,17 @@ void litehtml::el_style::parse_attributes() bool litehtml::el_style::appendChild(const ptr &el) { - m_children.push_back(el); - return true; + if(el && el->is_text()) + { + m_children.push_back(el); + return true; + } + return false; +} + +void litehtml::el_style::compute_styles(bool /* recursive */) +{ + css_w().set_display(display_none); } litehtml::string_id litehtml::el_style::tag() const diff --git a/libs/litehtml/src/el_table.cpp b/libs/litehtml/src/el_table.cpp index 82b02c6921..c3ce2a9ffc 100644 --- a/libs/litehtml/src/el_table.cpp +++ b/libs/litehtml/src/el_table.cpp @@ -1,58 +1,47 @@ -#include "html.h" #include "el_table.h" #include "document.h" -#include "iterators.h" namespace litehtml { -el_table::el_table(const shared_ptr<document>& doc) : html_tag(doc) -{ -} - -bool el_table::appendChild(const element::ptr& el) -{ - if(!el) return false; - if( el->tag() == _tbody_ || - el->tag() == _thead_ || - el->tag() == _tfoot_ || - el->tag() == _caption_) + el_table::el_table(const shared_ptr<document>& doc) : + html_tag(doc) { - return html_tag::appendChild(el); } - return false; -} -void el_table::parse_attributes() -{ - // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-width - const char* str = get_attr("width"); - if (str) - map_to_dimension_property_ignoring_zero(_width_, str); - - // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-height - str = get_attr("height"); - if (str) - map_to_dimension_property(_height_, str); - - // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-cellspacing - str = get_attr("cellspacing"); - if (str) - map_to_pixel_length_property(_border_spacing_, str); - - // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-border - str = get_attr("border"); - if (str) - map_to_pixel_length_property_with_default_value(_border_width_, str, 1); - - // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-background - str = get_attr("bgcolor"); - if (str) + bool el_table::appendChild(const element::ptr& el) { - m_style.add_property(_background_color_, str, "", false, get_document()->container()); + if(!el) return false; + if(el->tag() == _tbody_ || el->tag() == _thead_ || el->tag() == _tfoot_ || el->tag() == _caption_) + { + return html_tag::appendChild(el); + } + return false; } - html_tag::parse_attributes(); -} + void el_table::parse_attributes() + { + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-width + const char* str = get_attr("width"); + if(str) map_to_dimension_property_ignoring_zero(_width_, str); + + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-height + str = get_attr("height"); + if(str) map_to_dimension_property(_height_, str); + + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-cellspacing + str = get_attr("cellspacing"); + if(str) map_to_pixel_length_property(_border_spacing_, str); + + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-table-border + str = get_attr("border"); + if(str) map_to_pixel_length_property_with_default_value(_border_width_, str, 1); + + // https://html.spec.whatwg.org/multipage/rendering.html#tables-2:attr-background + str = get_attr("bgcolor"); + if(str) { m_style.add_property(_background_color_, str, "", false, get_document()->container()); } + + html_tag::parse_attributes(); + } -} // namespace litehtml
\ No newline at end of file +} // namespace litehtml diff --git a/libs/litehtml/src/el_td.cpp b/libs/litehtml/src/el_td.cpp index 659bfb1bc7..f665c7c095 100644 --- a/libs/litehtml/src/el_td.cpp +++ b/libs/litehtml/src/el_td.cpp @@ -1,5 +1,5 @@ -#include "html.h" #include "el_td.h" +#include "document.h" namespace litehtml { diff --git a/libs/litehtml/src/el_text.cpp b/libs/litehtml/src/el_text.cpp index 70ed82e6af..042da32651 100644 --- a/libs/litehtml/src/el_text.cpp +++ b/libs/litehtml/src/el_text.cpp @@ -1,6 +1,7 @@ #include "html.h" #include "el_text.h" #include "render_item.h" +#include "document_container.h" litehtml::el_text::el_text(const char* text, const document::ptr& doc) : element(doc) { @@ -28,7 +29,7 @@ void litehtml::el_text::compute_styles(bool /*recursive*/) element::ptr el_parent = parent(); if (el_parent) { - css_w().set_line_height(el_parent->css().get_line_height()); + css_w().line_height_w() = el_parent->css().line_height(); css_w().set_font(el_parent->css().get_font()); css_w().set_font_metrics(el_parent->css().get_font_metrics()); css_w().set_white_space(el_parent->css().get_white_space()); diff --git a/libs/litehtml/src/el_title.cpp b/libs/litehtml/src/el_title.cpp index f0e42311b4..7752d49a82 100644 --- a/libs/litehtml/src/el_title.cpp +++ b/libs/litehtml/src/el_title.cpp @@ -1,6 +1,6 @@ -#include "html.h" #include "el_title.h" #include "document.h" +#include "document_container.h" litehtml::el_title::el_title(const std::shared_ptr<document>& doc) : html_tag(doc) { diff --git a/libs/litehtml/src/el_tr.cpp b/libs/litehtml/src/el_tr.cpp index 5b80cc1221..78c53f4e80 100644 --- a/libs/litehtml/src/el_tr.cpp +++ b/libs/litehtml/src/el_tr.cpp @@ -1,5 +1,5 @@ -#include "html.h" #include "el_tr.h" +#include "document.h" litehtml::el_tr::el_tr(const std::shared_ptr<document>& doc) : html_tag(doc) diff --git a/libs/litehtml/src/element.cpp b/libs/litehtml/src/element.cpp index fb4c2c2948..8672b9de7c 100644 --- a/libs/litehtml/src/element.cpp +++ b/libs/litehtml/src/element.cpp @@ -317,7 +317,7 @@ string litehtml::element::get_counters_value(const string_vector& parameters) litehtml::trim(delims, "\"'"); string_vector values; - + element::ptr current = shared_from_this(); while (current != nullptr) { @@ -362,7 +362,7 @@ bool litehtml::element::find_counter(const string_id& counter_name_id, std::map< } current = current->parent(); } - + return false; } @@ -451,7 +451,7 @@ bool element::is_text() const LITEHTML_RETURN_FUNC(false) bool element::on_mouse_over() LITEHTML_RETURN_FUNC(false) bool element::on_mouse_leave() LITEHTML_RETURN_FUNC(false) bool element::on_lbutton_down() LITEHTML_RETURN_FUNC(false) -bool element::on_lbutton_up() LITEHTML_RETURN_FUNC(false) +bool element::on_lbutton_up(const bool /*is_click*/) LITEHTML_RETURN_FUNC(false) bool element::set_pseudo_class( string_id /*cls*/, bool /*add*/ ) LITEHTML_RETURN_FUNC(false) bool element::set_class( const char* /*pclass*/, bool /*add*/ ) LITEHTML_RETURN_FUNC(false) bool element::is_replaced() const LITEHTML_RETURN_FUNC(false) diff --git a/libs/litehtml/src/encodings.cpp b/libs/litehtml/src/encodings.cpp index 9cb64d821b..f56c0f10fe 100644 --- a/libs/litehtml/src/encodings.cpp +++ b/libs/litehtml/src/encodings.cpp @@ -1,4 +1,6 @@ #include "html.h" +#include "os_types.h" +#include "utf8_strings.h" #include "encodings.h" #include <cassert> @@ -1888,7 +1890,7 @@ loop: // 1. index = (int)str.find_first_of(" \t\r\n\f>", index); if (index == -1 || end_condition(index)) throw 0; // abort prescan - + // 2. string tmp; while (prescan_get_attribute(str, index, tmp, tmp)) {} diff --git a/libs/litehtml/src/flex_item.cpp b/libs/litehtml/src/flex_item.cpp index b117c22415..687c7374e6 100644 --- a/libs/litehtml/src/flex_item.cpp +++ b/libs/litehtml/src/flex_item.cpp @@ -1,8 +1,6 @@ -#include "html.h" +#include <cmath> #include "flex_item.h" -#include "render_item.h" #include "flex_line.h" -#include <cmath> void litehtml::flex_item::init(const litehtml::containing_block_context &self_size, litehtml::formatting_context *fmt_ctx, flex_align_items align_items) diff --git a/libs/litehtml/src/flex_line.cpp b/libs/litehtml/src/flex_line.cpp index ce45a06335..4e22d0aca8 100644 --- a/libs/litehtml/src/flex_line.cpp +++ b/libs/litehtml/src/flex_line.cpp @@ -1,7 +1,5 @@ -#include "html.h" #include "flex_line.h" #include "flex_item.h" -#include "render_item.h" void litehtml::flex_line::distribute_free_space(int container_main_size) { diff --git a/libs/litehtml/src/formatting_context.cpp b/libs/litehtml/src/formatting_context.cpp index e85e990c9c..ab5e65a006 100644 --- a/libs/litehtml/src/formatting_context.cpp +++ b/libs/litehtml/src/formatting_context.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "render_item.h" #include "formatting_context.h" diff --git a/libs/litehtml/src/gumbo/CMakeLists.txt b/libs/litehtml/src/gumbo/CMakeLists.txt index 7282604893..9c0dc5b072 100644 --- a/libs/litehtml/src/gumbo/CMakeLists.txt +++ b/libs/litehtml/src/gumbo/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.11) project(gumbo C) diff --git a/libs/litehtml/src/gumbo/char_ref.c b/libs/litehtml/src/gumbo/char_ref.c index a1d74fd5df..406afad032 100644 --- a/libs/litehtml/src/gumbo/char_ref.c +++ b/libs/litehtml/src/gumbo/char_ref.c @@ -136,7 +136,7 @@ static bool consume_numeric_ref( return false; } - int codepoint = 0; + unsigned int codepoint = 0; bool status = true; do { codepoint = (codepoint * (is_hex ? 16 : 10)) + digit; diff --git a/libs/litehtml/src/gumbo/char_ref.rl b/libs/litehtml/src/gumbo/char_ref.rl index 139a4bbd33..464e1690ba 100644 --- a/libs/litehtml/src/gumbo/char_ref.rl +++ b/libs/litehtml/src/gumbo/char_ref.rl @@ -162,7 +162,7 @@ static bool consume_numeric_ref( return false; } - int codepoint = 0; + unsigned int codepoint = 0; bool status = true; do { codepoint = (codepoint * (is_hex ? 16 : 10)) + digit; diff --git a/libs/litehtml/src/gumbo/include/gumbo.h b/libs/litehtml/src/gumbo/include/gumbo.h index f8137cf061..83cd22d5df 100644 --- a/libs/litehtml/src/gumbo/include/gumbo.h +++ b/libs/litehtml/src/gumbo/include/gumbo.h @@ -389,7 +389,10 @@ typedef enum { */ GUMBO_INSERTION_CONVERTED_FROM_END_TAG = 1 << 4, - /** A flag for nodes that are converted from the parse of an <isindex> tag. */ + /** + * Deprecated! Do not use! + * It's not used anymore since special handling for <isindex> is obsolete. + */ GUMBO_INSERTION_FROM_ISINDEX = 1 << 5, /** A flag for <image> tags that are rewritten as <img>. */ diff --git a/libs/litehtml/src/gumbo/include/gumbo/tag_enum.h b/libs/litehtml/src/gumbo/include/gumbo/tag_enum.h index 7a33d1e114..4237b1dec4 100644 --- a/libs/litehtml/src/gumbo/include/gumbo/tag_enum.h +++ b/libs/litehtml/src/gumbo/include/gumbo/tag_enum.h @@ -151,5 +151,6 @@ GUMBO_TAG_MULTICOL, GUMBO_TAG_NOBR, GUMBO_TAG_SPACER, GUMBO_TAG_DIALOG, +GUMBO_TAG_SEARCH, GUMBO_TAG_TT, GUMBO_TAG_RTC, diff --git a/libs/litehtml/src/gumbo/include/gumbo/tag_gperf.h b/libs/litehtml/src/gumbo/include/gumbo/tag_gperf.h index 525453946f..10691e473d 100644 --- a/libs/litehtml/src/gumbo/include/gumbo/tag_gperf.h +++ b/libs/litehtml/src/gumbo/include/gumbo/tag_gperf.h @@ -2,32 +2,32 @@ static unsigned int tag_hash(register const char *str, register size_t len) { static unsigned short asso_values[] = { - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 30, - 27, 27, 9, 6, 3, 6, 6, 3, 274, 274, - 274, 274, 274, 274, 274, 78, 3, 171, 12, 30, - 39, 129, 12, 105, 24, 156, 9, 51, 60, 87, - 12, 96, 3, 6, 18, 75, 99, 96, 36, 123, - 274, 274, 274, 274, 274, 274, 274, 78, 3, 171, - 12, 30, 39, 129, 12, 105, 24, 156, 9, 51, - 60, 87, 12, 96, 3, 6, 18, 75, 99, 96, - 36, 123, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, - 274, 274, 274, 274, 274, 274, 274, 274, 274 + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 9, + 5, 4, 2, 2, 1, 2, 1, 1, 284, 284, + 284, 284, 284, 284, 284, 56, 62, 156, 5, 14, + 47, 102, 3, 78, 32, 136, 10, 28, 36, 61, + 22, 108, 1, 2, 7, 55, 80, 123, 115, 76, + 284, 284, 284, 284, 284, 284, 284, 56, 62, 156, + 5, 14, 47, 102, 3, 78, 32, 136, 10, 28, + 36, 61, 22, 108, 1, 2, 7, 55, 80, 123, + 115, 76, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284 }; register unsigned int hval = len; @@ -49,239 +49,244 @@ static const unsigned char kGumboTagMap[] = { GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_B, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, GUMBO_TAG_S, GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, GUMBO_TAG_H6, - GUMBO_TAG_SPACER, - GUMBO_TAG_LAST, - GUMBO_TAG_RP, - GUMBO_TAG_LAST, - GUMBO_TAG_P, GUMBO_TAG_H5, - GUMBO_TAG_DIR, - GUMBO_TAG_LAST, GUMBO_TAG_H4, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, - GUMBO_TAG_SMALL, + GUMBO_TAG_H3, + GUMBO_TAG_SPACER, + GUMBO_TAG_H2, GUMBO_TAG_HEADER, - GUMBO_TAG_SAMP, - GUMBO_TAG_LABEL, - GUMBO_TAG_DEL, - GUMBO_TAG_DETAILS, - GUMBO_TAG_RB, - GUMBO_TAG_LEGEND, + GUMBO_TAG_SEARCH, GUMBO_TAG_HEAD, - GUMBO_TAG_BASEFONT, + GUMBO_TAG_H1, + GUMBO_TAG_DETAILS, GUMBO_TAG_SELECT, + GUMBO_TAG_DIR, + GUMBO_TAG_LAST, + GUMBO_TAG_DEL, GUMBO_TAG_LAST, - GUMBO_TAG_H3, GUMBO_TAG_SOURCE, - GUMBO_TAG_BGSOUND, - GUMBO_TAG_H2, - GUMBO_TAG_SUB, - GUMBO_TAG_BASE, + GUMBO_TAG_LEGEND, GUMBO_TAG_DATALIST, - GUMBO_TAG_FOOTER, GUMBO_TAG_LAST, - GUMBO_TAG_H1, - GUMBO_TAG_HGROUP, + GUMBO_TAG_RP, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_SUP, - GUMBO_TAG_PICTURE, - GUMBO_TAG_EMBED, + GUMBO_TAG_LABEL, + GUMBO_TAG_TABLE, + GUMBO_TAG_TEMPLATE, + GUMBO_TAG_SAMP, GUMBO_TAG_LAST, GUMBO_TAG_TIME, GUMBO_TAG_TITLE, - GUMBO_TAG_XMP, - GUMBO_TAG_FONT, - GUMBO_TAG_TABLE, + GUMBO_TAG_METER, GUMBO_TAG_LAST, + GUMBO_TAG_SMALL, + GUMBO_TAG_MATH, GUMBO_TAG_LAST, - GUMBO_TAG_TEMPLATE, - GUMBO_TAG_SCRIPT, GUMBO_TAG_NOBR, - GUMBO_TAG_METER, - GUMBO_TAG_LAST, - GUMBO_TAG_FOREIGNOBJECT, - GUMBO_TAG_FIELDSET, GUMBO_TAG_LAST, GUMBO_TAG_SPAN, + GUMBO_TAG_P, + GUMBO_TAG_EMBED, GUMBO_TAG_NOFRAMES, - GUMBO_TAG_MAP, - GUMBO_TAG_MATH, - GUMBO_TAG_PARAM, - GUMBO_TAG_LAST, - GUMBO_TAG_NOEMBED, - GUMBO_TAG_BR, - GUMBO_TAG_FIGURE, GUMBO_TAG_SECTION, - GUMBO_TAG_LAST, - GUMBO_TAG_LAST, + GUMBO_TAG_NOEMBED, + GUMBO_TAG_NEXTID, GUMBO_TAG_LAST, GUMBO_TAG_NOSCRIPT, - GUMBO_TAG_NEXTID, + GUMBO_TAG_PICTURE, + GUMBO_TAG_MARQUEE, + GUMBO_TAG_FOOTER, + GUMBO_TAG_LAST, GUMBO_TAG_LAST, + GUMBO_TAG_MAP, + GUMBO_TAG_FONT, + GUMBO_TAG_PARAM, GUMBO_TAG_HR, - GUMBO_TAG_MGLYPH, + GUMBO_TAG_SCRIPT, + GUMBO_TAG_HGROUP, GUMBO_TAG_LAST, + GUMBO_TAG_TR, GUMBO_TAG_EM, + GUMBO_TAG_MENUITEM, + GUMBO_TAG_FOREIGNOBJECT, + GUMBO_TAG_MGLYPH, + GUMBO_TAG_DATA, + GUMBO_TAG_APPLET, + GUMBO_TAG_FIELDSET, + GUMBO_TAG_MAIN, + GUMBO_TAG_TEXTAREA, + GUMBO_TAG_ABBR, GUMBO_TAG_LAST, + GUMBO_TAG_FIGURE, + GUMBO_TAG_DL, + GUMBO_TAG_RB, GUMBO_TAG_FORM, - GUMBO_TAG_TR, GUMBO_TAG_LAST, - GUMBO_TAG_MARQUEE, + GUMBO_TAG_BASEFONT, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_BASE, + GUMBO_TAG_LAST, GUMBO_TAG_PROGRESS, + GUMBO_TAG_OBJECT, + GUMBO_TAG_VAR, + GUMBO_TAG_MENU, + GUMBO_TAG_META, + GUMBO_TAG_MO, + GUMBO_TAG_OPTGROUP, + GUMBO_TAG_PRE, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_MULTICOL, - GUMBO_TAG_BUTTON, - GUMBO_TAG_DATA, + GUMBO_TAG_TFOOT, + GUMBO_TAG_DIV, + GUMBO_TAG_PLAINTEXT, + GUMBO_TAG_LI, GUMBO_TAG_LAST, - GUMBO_TAG_APPLET, + GUMBO_TAG_TBODY, + GUMBO_TAG_FIGCAPTION, GUMBO_TAG_LAST, - GUMBO_TAG_DL, + GUMBO_TAG_OPTION, + GUMBO_TAG_BGSOUND, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_OPTGROUP, GUMBO_TAG_LAST, - GUMBO_TAG_ABBR, - GUMBO_TAG_TEXTAREA, - GUMBO_TAG_VAR, - GUMBO_TAG_FIGCAPTION, + GUMBO_TAG_LAST, + GUMBO_TAG_U, + GUMBO_TAG_MS, + GUMBO_TAG_A, + GUMBO_TAG_DD, + GUMBO_TAG_LAST, + GUMBO_TAG_TD, + GUMBO_TAG_FRAMESET, + GUMBO_TAG_MI, + GUMBO_TAG_IMAGE, + GUMBO_TAG_BR, + GUMBO_TAG_FRAME, + GUMBO_TAG_DFN, + GUMBO_TAG_DIALOG, + GUMBO_TAG_NAV, + GUMBO_TAG_B, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_UL, + GUMBO_TAG_LISTING, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_ARTICLE, GUMBO_TAG_RT, - GUMBO_TAG_PRE, - GUMBO_TAG_HTML, - GUMBO_TAG_MENUITEM, - GUMBO_TAG_DIV, + GUMBO_TAG_OL, + GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_LI, - GUMBO_TAG_PLAINTEXT, - GUMBO_TAG_MAIN, GUMBO_TAG_DT, + GUMBO_TAG_ACRONYM, + GUMBO_TAG_TT, + GUMBO_TAG_HTML, + GUMBO_TAG_WBR, + GUMBO_TAG_SUP, + GUMBO_TAG_BODY, + GUMBO_TAG_STYLE, + GUMBO_TAG_STRIKE, GUMBO_TAG_LAST, GUMBO_TAG_BLOCKQUOTE, + GUMBO_TAG_TH, GUMBO_TAG_LAST, - GUMBO_TAG_WBR, - GUMBO_TAG_BODY, - GUMBO_TAG_TT, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_STYLE, - GUMBO_TAG_STRIKE, GUMBO_TAG_LAST, - GUMBO_TAG_FRAMESET, - GUMBO_TAG_OBJECT, - GUMBO_TAG_MENU, - GUMBO_TAG_MO, + GUMBO_TAG_THEAD, + GUMBO_TAG_LAST, + GUMBO_TAG_ASIDE, + GUMBO_TAG_VIDEO, + GUMBO_TAG_I, + GUMBO_TAG_KBD, + GUMBO_TAG_LAST, + GUMBO_TAG_LINK, + GUMBO_TAG_MULTICOL, + GUMBO_TAG_XMP, + GUMBO_TAG_MTEXT, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_CENTER, + GUMBO_TAG_ADDRESS, + GUMBO_TAG_DESC, + GUMBO_TAG_CANVAS, + GUMBO_TAG_COL, + GUMBO_TAG_AREA, + GUMBO_TAG_LAST, + GUMBO_TAG_MARK, + GUMBO_TAG_MN, + GUMBO_TAG_CODE, + GUMBO_TAG_IFRAME, GUMBO_TAG_BIG, - GUMBO_TAG_META, - GUMBO_TAG_TFOOT, - GUMBO_TAG_OUTPUT, GUMBO_TAG_LAST, - GUMBO_TAG_FRAME, + GUMBO_TAG_MALIGNMARK, GUMBO_TAG_LAST, - GUMBO_TAG_U, - GUMBO_TAG_IMAGE, + GUMBO_TAG_KEYGEN, + GUMBO_TAG_SUB, + GUMBO_TAG_SVG, + GUMBO_TAG_CITE, GUMBO_TAG_LAST, - GUMBO_TAG_LISTING, - GUMBO_TAG_DD, - GUMBO_TAG_DIALOG, - GUMBO_TAG_A, - GUMBO_TAG_MS, - GUMBO_TAG_OPTION, GUMBO_TAG_LAST, - GUMBO_TAG_TD, + GUMBO_TAG_COLGROUP, + GUMBO_TAG_ANNOTATION_XML, + GUMBO_TAG_OUTPUT, GUMBO_TAG_LAST, + GUMBO_TAG_INS, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_RUBY, - GUMBO_TAG_MI, GUMBO_TAG_LAST, + GUMBO_TAG_RUBY, GUMBO_TAG_LAST, - GUMBO_TAG_MTEXT, + GUMBO_TAG_INPUT, GUMBO_TAG_LAST, GUMBO_TAG_SUMMARY, - GUMBO_TAG_UL, - GUMBO_TAG_NAV, - GUMBO_TAG_ACRONYM, - GUMBO_TAG_TBODY, GUMBO_TAG_LAST, - GUMBO_TAG_LINK, GUMBO_TAG_LAST, - GUMBO_TAG_DFN, + GUMBO_TAG_TRACK, + GUMBO_TAG_CAPTION, + GUMBO_TAG_IMG, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_OL, - GUMBO_TAG_COL, GUMBO_TAG_LAST, - GUMBO_TAG_TH, GUMBO_TAG_LAST, - GUMBO_TAG_ARTICLE, - GUMBO_TAG_THEAD, - GUMBO_TAG_CENTER, - GUMBO_TAG_Q, - GUMBO_TAG_COLGROUP, - GUMBO_TAG_CANVAS, GUMBO_TAG_LAST, - GUMBO_TAG_ANNOTATION_XML, GUMBO_TAG_LAST, - GUMBO_TAG_DESC, - GUMBO_TAG_VIDEO, - GUMBO_TAG_KBD, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, + GUMBO_TAG_Q, GUMBO_TAG_LAST, - GUMBO_TAG_AUDIO, + GUMBO_TAG_BUTTON, GUMBO_TAG_LAST, - GUMBO_TAG_CODE, - GUMBO_TAG_MN, - GUMBO_TAG_INS, - GUMBO_TAG_I, - GUMBO_TAG_ASIDE, GUMBO_TAG_LAST, - GUMBO_TAG_CITE, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_ADDRESS, GUMBO_TAG_LAST, GUMBO_TAG_BDO, - GUMBO_TAG_MARK, - GUMBO_TAG_INPUT, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_MALIGNMARK, + GUMBO_TAG_STRONG, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_AUDIO, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_KEYGEN, - GUMBO_TAG_AREA, GUMBO_TAG_LAST, - GUMBO_TAG_STRONG, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_BDI, @@ -290,22 +295,23 @@ static const unsigned char kGumboTagMap[] = { GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_IFRAME, - GUMBO_TAG_ISINDEX, GUMBO_TAG_LAST, - GUMBO_TAG_IMG, - GUMBO_TAG_CAPTION, - GUMBO_TAG_BLINK, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_TRACK, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, - GUMBO_TAG_SVG, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_BLINK, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, @@ -317,5 +323,9 @@ static const unsigned char kGumboTagMap[] = { GUMBO_TAG_LAST, GUMBO_TAG_LAST, GUMBO_TAG_LAST, + GUMBO_TAG_LAST, + GUMBO_TAG_ISINDEX, + GUMBO_TAG_LAST, + GUMBO_TAG_LAST, GUMBO_TAG_RTC }; diff --git a/libs/litehtml/src/gumbo/include/gumbo/tag_sizes.h b/libs/litehtml/src/gumbo/include/gumbo/tag_sizes.h index 5b93c22fa2..9dc9529995 100644 --- a/libs/litehtml/src/gumbo/include/gumbo/tag_sizes.h +++ b/libs/litehtml/src/gumbo/include/gumbo/tag_sizes.h @@ -1,4 +1,4 @@ // Generated via `gentags.py src/tag.in`. // Do not edit; edit src/tag.in instead. // clang-format off -4, 4, 5, 4, 4, 4, 5, 6, 8, 8, 4, 7, 7, 3, 5, 2, 2, 2, 2, 2, 2, 6, 6, 6, 7, 1, 2, 3, 10, 2, 2, 2, 2, 2, 2, 6, 10, 4, 3, 1, 2, 6, 5, 1, 4, 1, 3, 4, 4, 4, 4, 3, 4, 3, 3, 3, 1, 1, 1, 4, 4, 2, 2, 3, 3, 4, 2, 3, 3, 3, 5, 3, 7, 6, 5, 6, 5, 5, 5, 6, 5, 6, 3, 4, 4, 2, 2, 2, 2, 5, 6, 10, 14, 3, 13, 4, 5, 7, 8, 3, 5, 5, 5, 2, 2, 2, 4, 8, 6, 5, 5, 6, 6, 8, 8, 6, 8, 6, 6, 8, 5, 7, 7, 4, 8, 6, 7, 7, 3, 5, 8, 8, 7, 7, 3, 6, 7, 9, 2, 6, 8, 3, 5, 6, 4, 7, 8, 4, 6, 6, 2, 3,
\ No newline at end of file +4, 4, 5, 4, 4, 4, 5, 6, 8, 8, 4, 7, 7, 3, 5, 2, 2, 2, 2, 2, 2, 6, 6, 6, 7, 1, 2, 3, 10, 2, 2, 2, 2, 2, 2, 6, 10, 4, 3, 1, 2, 6, 5, 1, 4, 1, 3, 4, 4, 4, 4, 3, 4, 3, 3, 3, 1, 1, 1, 4, 4, 2, 2, 3, 3, 4, 2, 3, 3, 3, 5, 3, 7, 6, 5, 6, 5, 5, 5, 6, 5, 6, 3, 4, 4, 2, 2, 2, 2, 5, 6, 10, 14, 3, 13, 4, 5, 7, 8, 3, 5, 5, 5, 2, 2, 2, 4, 8, 6, 5, 5, 6, 6, 8, 8, 6, 8, 6, 6, 8, 5, 7, 7, 4, 8, 6, 7, 7, 3, 5, 8, 8, 7, 7, 3, 6, 7, 9, 2, 6, 8, 3, 5, 6, 4, 7, 8, 4, 6, 6, 6, 2, 3,
\ No newline at end of file diff --git a/libs/litehtml/src/gumbo/include/gumbo/tag_strings.h b/libs/litehtml/src/gumbo/include/gumbo/tag_strings.h index 03d793c05d..188bcda00b 100644 --- a/libs/litehtml/src/gumbo/include/gumbo/tag_strings.h +++ b/libs/litehtml/src/gumbo/include/gumbo/tag_strings.h @@ -151,5 +151,6 @@ "nobr", "spacer", "dialog", +"search", "tt", "rtc", diff --git a/libs/litehtml/src/gumbo/parser.c b/libs/litehtml/src/gumbo/parser.c index 968fcc0f41..0ab3f92084 100644 --- a/libs/litehtml/src/gumbo/parser.c +++ b/libs/litehtml/src/gumbo/parser.c @@ -291,17 +291,16 @@ typedef struct _NamespacedAttributeReplacement { static const NamespacedAttributeReplacement kForeignAttributeReplacements[] = { {"xlink:actuate", "actuate", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:actuate", "actuate", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:href", "href", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:role", "role", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:show", "show", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:title", "title", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xlink:type", "type", GUMBO_ATTR_NAMESPACE_XLINK}, - {"xml:base", "base", GUMBO_ATTR_NAMESPACE_XML}, - {"xml:lang", "lang", GUMBO_ATTR_NAMESPACE_XML}, - {"xml:space", "space", GUMBO_ATTR_NAMESPACE_XML}, - {"xmlns", "xmlns", GUMBO_ATTR_NAMESPACE_XMLNS}, - {"xmlns:xlink", "xlink", GUMBO_ATTR_NAMESPACE_XMLNS}, + {"xlink:arcrole", "arcrole", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xlink:href", "href", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xlink:role", "role", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xlink:show", "show", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xlink:title", "title", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xlink:type", "type", GUMBO_ATTR_NAMESPACE_XLINK}, + {"xml:lang", "lang", GUMBO_ATTR_NAMESPACE_XML}, + {"xml:space", "space", GUMBO_ATTR_NAMESPACE_XML}, + {"xmlns", "xmlns", GUMBO_ATTR_NAMESPACE_XMLNS}, + {"xmlns:xlink", "xlink", GUMBO_ATTR_NAMESPACE_XMLNS}, }; // The "scope marker" for the list of active formatting elements. We use a @@ -1564,12 +1563,12 @@ static bool is_special_node(const GumboNode* node) { (gumbo_tagset){TAG(ADDRESS), TAG(APPLET), TAG(AREA), TAG(ARTICLE), TAG(ASIDE), TAG(BASE), TAG(BASEFONT), TAG(BGSOUND), TAG(BLOCKQUOTE), TAG(BODY), TAG(BR), TAG(BUTTON), TAG(CAPTION), TAG(CENTER), TAG(COL), - TAG(COLGROUP), TAG(MENUITEM), TAG(DD), TAG(DETAILS), TAG(DIR), + TAG(COLGROUP), TAG(DD), TAG(DETAILS), TAG(DIR), TAG(DIV), TAG(DL), TAG(DT), TAG(EMBED), TAG(FIELDSET), TAG(FIGCAPTION), TAG(FIGURE), TAG(FOOTER), TAG(FORM), TAG(FRAME), TAG(FRAMESET), TAG(H1), TAG(H2), TAG(H3), TAG(H4), TAG(H5), TAG(H6), TAG(HEAD), TAG(HEADER), TAG(HGROUP), TAG(HR), TAG(HTML), TAG(IFRAME), - TAG(IMG), TAG(INPUT), TAG(ISINDEX), TAG(LI), TAG(LINK), TAG(LISTING), + TAG(IMG), TAG(INPUT), TAG(LI), TAG(LINK), TAG(LISTING), TAG(MARQUEE), TAG(MENU), TAG(META), TAG(NAV), TAG(NOEMBED), TAG(NOFRAMES), TAG(NOSCRIPT), TAG(OBJECT), TAG(OL), TAG(P), TAG(PARAM), TAG(PLAINTEXT), TAG(PRE), TAG(SCRIPT), TAG(SECTION), @@ -2179,7 +2178,7 @@ static bool handle_in_head(GumboParser* parser, GumboToken* token) { return handle_in_body(parser, token); } else if (tag_in(token, kStartTag, (gumbo_tagset){TAG(BASE), TAG(BASEFONT), TAG(BGSOUND), - TAG(MENUITEM), TAG(LINK)})) { + TAG(LINK)})) { insert_element_from_token(parser, token); pop_current_node(parser); acknowledge_self_closing_tag(parser); @@ -2419,7 +2418,7 @@ static bool handle_in_body(GumboParser* parser, GumboToken* token) { return false; } else if (tag_in(token, kStartTag, (gumbo_tagset){TAG(BASE), TAG(BASEFONT), TAG(BGSOUND), - TAG(MENUITEM), TAG(LINK), TAG(META), TAG(NOFRAMES), + TAG(LINK), TAG(META), TAG(NOFRAMES), TAG(SCRIPT), TAG(STYLE), TAG(TEMPLATE), TAG(TITLE)}) || tag_is(token, kEndTag, GUMBO_TAG_TEMPLATE)) { return handle_in_head(parser, token); @@ -2514,13 +2513,13 @@ static bool handle_in_body(GumboParser* parser, GumboToken* token) { record_end_of_element(state->_current_token, &body->v.element); } return success; - } else if (tag_in(token, kStartTag, - (gumbo_tagset){TAG(ADDRESS), TAG(ARTICLE), TAG(ASIDE), - TAG(BLOCKQUOTE), TAG(CENTER), TAG(DETAILS), TAG(DIALOG), - TAG(DIR), TAG(DIV), TAG(DL), TAG(FIELDSET), TAG(FIGCAPTION), - TAG(FIGURE), TAG(FOOTER), TAG(HEADER), TAG(HGROUP), - TAG(MENU), TAG(MAIN), TAG(NAV), TAG(OL), TAG(P), - TAG(SECTION), TAG(SUMMARY), TAG(UL)})) { + } else if (tag_in(token, kStartTag, (gumbo_tagset){ + TAG(ADDRESS), TAG(ARTICLE), TAG(ASIDE), TAG(BLOCKQUOTE), TAG(CENTER), + TAG(DETAILS), TAG(DIALOG), TAG(DIR), TAG(DIV), TAG(DL), TAG(FIELDSET), + TAG(FIGCAPTION), TAG(FIGURE), TAG(FOOTER), TAG(HEADER), TAG(HGROUP), + TAG(MENU), TAG(MAIN), TAG(NAV), TAG(OL), TAG(P), TAG(SECTION), + TAG(SUMMARY), TAG(UL), TAG(SEARCH)})) + { bool result = maybe_implicitly_close_p_tag(parser, token); insert_element_from_token(parser, token); return result; @@ -2583,13 +2582,13 @@ static bool handle_in_body(GumboParser* parser, GumboToken* token) { insert_element_from_token(parser, token); state->_frameset_ok = false; return true; - } else if (tag_in(token, kEndTag, - (gumbo_tagset){TAG(ADDRESS), TAG(ARTICLE), TAG(ASIDE), - TAG(BLOCKQUOTE), TAG(BUTTON), TAG(CENTER), TAG(DETAILS), - TAG(DIALOG), TAG(DIR), TAG(DIV), TAG(DL), TAG(FIELDSET), - TAG(FIGCAPTION), TAG(FIGURE), TAG(FOOTER), TAG(HEADER), - TAG(HGROUP), TAG(LISTING), TAG(MAIN), TAG(MENU), TAG(NAV), - TAG(OL), TAG(PRE), TAG(SECTION), TAG(SUMMARY), TAG(UL)})) { + } else if (tag_in(token, kEndTag, (gumbo_tagset){ + TAG(ADDRESS), TAG(ARTICLE), TAG(ASIDE), TAG(BLOCKQUOTE), TAG(BUTTON), + TAG(CENTER), TAG(DETAILS), TAG(DIALOG), TAG(DIR), TAG(DIV), TAG(DL), + TAG(FIELDSET), TAG(FIGCAPTION), TAG(FIGURE), TAG(FOOTER), TAG(HEADER), + TAG(HGROUP), TAG(LISTING), TAG(MAIN), TAG(MENU), TAG(NAV), TAG(OL), + TAG(PRE), TAG(SECTION), TAG(SUMMARY), TAG(UL), TAG(SEARCH)})) + { GumboTag tag = token->v.end_tag; if (!has_an_element_in_scope(parser, tag)) { parser_add_parse_error(parser, token); @@ -2820,100 +2819,13 @@ static bool handle_in_body(GumboParser* parser, GumboToken* token) { set_frameset_not_ok(parser); return result; } else if (tag_is(token, kStartTag, GUMBO_TAG_ISINDEX)) { - parser_add_parse_error(parser, token); - if (parser->_parser_state->_form_element != NULL && - !has_open_element(parser, GUMBO_TAG_TEMPLATE)) { - ignore_token(parser); - return false; - } - acknowledge_self_closing_tag(parser); - maybe_implicitly_close_p_tag(parser, token); - set_frameset_not_ok(parser); - - GumboVector* token_attrs = &token->v.start_tag.attributes; - GumboAttribute* prompt_attr = gumbo_get_attribute(token_attrs, "prompt"); - GumboAttribute* action_attr = gumbo_get_attribute(token_attrs, "action"); - GumboAttribute* name_attr = gumbo_get_attribute(token_attrs, "name"); - - GumboNode* form = insert_element_of_tag_type( - parser, GUMBO_TAG_FORM, GUMBO_INSERTION_FROM_ISINDEX); - if (!has_open_element(parser, GUMBO_TAG_TEMPLATE)) { - parser->_parser_state->_form_element = form; - } - if (action_attr) { - gumbo_vector_add(parser, action_attr, &form->v.element.attributes); - } - insert_element_of_tag_type( - parser, GUMBO_TAG_HR, GUMBO_INSERTION_FROM_ISINDEX); - pop_current_node(parser); // <hr> - - insert_element_of_tag_type( - parser, GUMBO_TAG_LABEL, GUMBO_INSERTION_FROM_ISINDEX); - TextNodeBufferState* text_state = &parser->_parser_state->_text_node; - text_state->_start_original_text = token->original_text.data; - text_state->_start_position = token->position; - text_state->_type = GUMBO_NODE_TEXT; - if (prompt_attr) { - int prompt_attr_length = strlen(prompt_attr->value); - gumbo_string_buffer_destroy(parser, &text_state->_buffer); - text_state->_buffer.data = gumbo_copy_stringz(parser, prompt_attr->value); - text_state->_buffer.length = prompt_attr_length; - text_state->_buffer.capacity = prompt_attr_length + 1; - gumbo_destroy_attribute(parser, prompt_attr); - } else { - GumboStringPiece prompt_text = - GUMBO_STRING("This is a searchable index. Enter search keywords: "); - gumbo_string_buffer_append_string( - parser, &prompt_text, &text_state->_buffer); - } - - GumboNode* input = insert_element_of_tag_type( - parser, GUMBO_TAG_INPUT, GUMBO_INSERTION_FROM_ISINDEX); - for (unsigned int i = 0; i < token_attrs->length; ++i) { - GumboAttribute* attr = token_attrs->data[i]; - if (attr != prompt_attr && attr != action_attr && attr != name_attr) { - gumbo_vector_add(parser, attr, &input->v.element.attributes); - } - token_attrs->data[i] = NULL; - } - - // All attributes have been successfully transferred and nulled out at this - // point, so the call to ignore_token will free the memory for it without - // touching the attributes. - ignore_token(parser); - - // The name attribute, if present, should be destroyed since it's ignored - // when copying over. The action attribute should be kept since it's moved - // to the form. - if (name_attr) { - gumbo_destroy_attribute(parser, name_attr); - } - - GumboAttribute* name = - gumbo_parser_allocate(parser, sizeof(GumboAttribute)); - GumboStringPiece name_str = GUMBO_STRING("name"); - GumboStringPiece isindex_str = GUMBO_STRING("isindex"); - name->attr_namespace = GUMBO_ATTR_NAMESPACE_NONE; - name->name = gumbo_copy_stringz(parser, "name"); - name->value = gumbo_copy_stringz(parser, "isindex"); - name->original_name = name_str; - name->original_value = isindex_str; - name->name_start = kGumboEmptySourcePosition; - name->name_end = kGumboEmptySourcePosition; - name->value_start = kGumboEmptySourcePosition; - name->value_end = kGumboEmptySourcePosition; - gumbo_vector_add(parser, name, &input->v.element.attributes); - - pop_current_node(parser); // <input> - pop_current_node(parser); // <label> - insert_element_of_tag_type( - parser, GUMBO_TAG_HR, GUMBO_INSERTION_FROM_ISINDEX); - pop_current_node(parser); // <hr> - pop_current_node(parser); // <form> - if (!has_open_element(parser, GUMBO_TAG_TEMPLATE)) { - parser->_parser_state->_form_element = NULL; + reconstruct_active_formatting_elements(parser); + insert_element_from_token(parser, token); + if (token->v.start_tag.is_self_closing) { + pop_current_node(parser); + acknowledge_self_closing_tag(parser); } - return false; + return true; } else if (tag_is(token, kStartTag, GUMBO_TAG_TEXTAREA)) { run_generic_parsing_algorithm(parser, token, GUMBO_LEX_RCDATA); parser->_parser_state->_ignore_next_linefeed = true; @@ -3491,6 +3403,17 @@ static bool handle_in_select(GumboParser* parser, GumboToken* token) { } insert_element_from_token(parser, token); return true; + } else if (tag_is(token, kStartTag, GUMBO_TAG_HR)) { + if (node_html_tag_is(get_current_node(parser), GUMBO_TAG_OPTION)) { + pop_current_node(parser); + } + if (node_html_tag_is(get_current_node(parser), GUMBO_TAG_OPTGROUP)) { + pop_current_node(parser); + } + insert_element_from_token(parser, token); + pop_current_node(parser); + acknowledge_self_closing_tag(parser); + return true; } else if (tag_is(token, kEndTag, GUMBO_TAG_OPTGROUP)) { GumboVector* open_elements = &parser->_parser_state->_open_elements; if (node_html_tag_is(get_current_node(parser), GUMBO_TAG_OPTION) && @@ -3854,40 +3777,33 @@ static bool handle_in_foreign_content(GumboParser* parser, GumboToken* token) { // Fall through to the if-statements below. break; } - // Order matters for these clauses. - if (tag_in(token, kStartTag, - (gumbo_tagset){TAG(B), TAG(BIG), TAG(BLOCKQUOTE), TAG(BODY), TAG(BR), - TAG(CENTER), TAG(CODE), TAG(DD), TAG(DIV), TAG(DL), TAG(DT), - TAG(EM), TAG(EMBED), TAG(H1), TAG(H2), TAG(H3), TAG(H4), TAG(H5), - TAG(H6), TAG(HEAD), TAG(HR), TAG(I), TAG(IMG), TAG(LI), - TAG(LISTING), TAG(MENU), TAG(META), TAG(NOBR), TAG(OL), TAG(P), - TAG(PRE), TAG(RUBY), TAG(S), TAG(SMALL), TAG(SPAN), TAG(STRONG), - TAG(STRIKE), TAG(SUB), TAG(SUP), TAG(TABLE), TAG(TT), TAG(U), - TAG(UL), TAG(VAR)}) || - (tag_is(token, kStartTag, GUMBO_TAG_FONT) && - (token_has_attribute(token, "color") || - token_has_attribute(token, "face") || - token_has_attribute(token, "size")))) { + + if (tag_in(token, kStartTag, (gumbo_tagset){ + TAG(B), TAG(BIG), TAG(BLOCKQUOTE), TAG(BODY), TAG(BR), TAG(CENTER), + TAG(CODE), TAG(DD), TAG(DIV), TAG(DL), TAG(DT), TAG(EM), TAG(EMBED), + TAG(H1), TAG(H2), TAG(H3), TAG(H4), TAG(H5), TAG(H6), TAG(HEAD), + TAG(HR), TAG(I), TAG(IMG), TAG(LI), TAG(LISTING), TAG(MENU), TAG(META), + TAG(NOBR), TAG(OL), TAG(P), TAG(PRE), TAG(RUBY), TAG(S), TAG(SMALL), + TAG(SPAN), TAG(STRONG), TAG(STRIKE), TAG(SUB), TAG(SUP), TAG(TABLE), + TAG(TT), TAG(U), TAG(UL), TAG(VAR)}) + || tag_in(token, kEndTag, (gumbo_tagset){TAG(BR), TAG(P)}) + || (tag_is(token, kStartTag, GUMBO_TAG_FONT) + && (token_has_attribute(token, "color") + || token_has_attribute(token, "face") + || token_has_attribute(token, "size")))) + { /* Parse error */ parser_add_parse_error(parser, token); - /* - * Fragment case: If the parser was originally created for the HTML - * fragment parsing algorithm, then act as described in the "any other - * start tag" entry below. - */ - if (!is_fragment_parser(parser)) { - do { - pop_current_node(parser); - } while (!(is_mathml_integration_point(get_current_node(parser)) || - is_html_integration_point(get_current_node(parser)) || - get_current_node(parser)->v.element.tag_namespace == - GUMBO_NAMESPACE_HTML)); - parser->_parser_state->_reprocess_current_token = true; - return false; + while (!is_mathml_integration_point(get_current_node(parser)) + && !is_html_integration_point(get_current_node(parser)) + && get_current_node(parser)->v.element.tag_namespace != GUMBO_NAMESPACE_HTML) + { + pop_current_node(parser); } - assert(token->type == GUMBO_TOKEN_START_TAG); + handle_html_content(parser, token); + return false; } if (token->type == GUMBO_TOKEN_START_TAG) { diff --git a/libs/litehtml/src/html_microsyntaxes.cpp b/libs/litehtml/src/html_microsyntaxes.cpp index f16bd622e0..d8ce01471f 100644 --- a/libs/litehtml/src/html_microsyntaxes.cpp +++ b/libs/litehtml/src/html_microsyntaxes.cpp @@ -1,3 +1,4 @@ +#include "html_microsyntaxes.h" #include "html.h" namespace litehtml diff --git a/libs/litehtml/src/html_tag.cpp b/libs/litehtml/src/html_tag.cpp index 54a8dd404a..08f289df9d 100644 --- a/libs/litehtml/src/html_tag.cpp +++ b/libs/litehtml/src/html_tag.cpp @@ -3,6 +3,7 @@ #include "html.h" #include "html_tag.h" #include "document.h" +#include "html_microsyntaxes.h" #include "iterators.h" #include "stylesheet.h" #include "table.h" @@ -10,6 +11,7 @@ #include "line_box.h" #include "render_item.h" #include "internal.h" +#include "document_container.h" namespace litehtml { @@ -126,7 +128,7 @@ litehtml::elements_list litehtml::html_tag::select_all(const string& selector ) { css_selector sel; sel.parse(selector, get_document()->mode()); - + return select_all(sel); } @@ -143,7 +145,7 @@ void litehtml::html_tag::select_all(const css_selector& selector, elements_list& { res.push_back(shared_from_this()); } - + for(auto& el : m_children) { el->select_all(selector, res); @@ -295,7 +297,7 @@ void litehtml::html_tag::draw(uint_ptr hdc, int x, int y, const position *clip, draw_background(hdc, x, y, clip, ri); - if(m_css.get_display() == display_list_item && + if(m_css.get_display() == display_list_item && (m_css.get_list_style_type() != list_style_type_none || m_css.get_list_style_image() != "")) { if(m_css.get_overflow() > overflow_visible) @@ -816,7 +818,7 @@ bool litehtml::html_tag::on_lbutton_down() return ret; } -bool litehtml::html_tag::on_lbutton_up() +bool litehtml::html_tag::on_lbutton_up(bool is_click) { bool ret = false; @@ -830,7 +832,7 @@ bool litehtml::html_tag::on_lbutton_up() el = el->parent(); } - on_click(); + if (is_click) on_click(); return ret; } @@ -839,10 +841,13 @@ void litehtml::html_tag::on_click() { if (!is_root()) { - element::ptr el_parent = parent(); - if (el_parent) + if(!get_document()->container()->on_element_click(shared_from_this())) { - el_parent->on_click(); + element::ptr el_parent = parent(); + if (el_parent) + { + el_parent->on_click(); + } } } } @@ -935,7 +940,7 @@ void litehtml::html_tag::draw_background(uint_ptr hdc, int x, int y, const posit bdr.radius.top_right_y = m_css.get_borders().radius.top_right_y; } - + bdr.top = m_css.get_borders().top; bdr.bottom = m_css.get_borders().bottom; if(box == boxes.begin()) @@ -954,7 +959,7 @@ void litehtml::html_tag::draw_background(uint_ptr hdc, int x, int y, const posit { background_layer layer; if(!bg->get_layer(i, content_box, this, ri, layer)) continue; - layer.border_radius = bdr.radius.calc_percents(layer.border_box.width, layer.border_box.width); + layer.border_radius = bdr.radius.calc_percents(box->width, box->height); bg->draw_layer(hdc, i, layer, get_document()->container()); } } @@ -1057,7 +1062,7 @@ void litehtml::html_tag::draw_list_marker( uint_ptr hdc, const position& pos ) lm.baseurl = nullptr; } - int ln_height = css().get_line_height(); + int ln_height = css().line_height().computed_value; int sz_font = css().get_font_size(); lm.pos.x = pos.x; lm.pos.width = sz_font - sz_font * 2 / 3; @@ -1192,7 +1197,7 @@ bool html_tag::is_nth_child(const element::ptr& el, int num, int off, bool of_ty { if(child->css().get_display() != display_inline_text) { - if( (!of_type && selector_list.empty()) || + if( (!of_type && selector_list.empty()) || (of_type && child->tag() == el->tag()) || child->select(selector_list) ) { if(el == child) @@ -1502,7 +1507,7 @@ const litehtml::background* litehtml::html_tag::get_background(bool own_only) } return nullptr; } - + if(is_body()) { element::ptr el_parent = parent(); @@ -1578,7 +1583,7 @@ void html_tag::map_to_dimension_property_ignoring_zero(string_id prop_name, stri tok = {DIMENSION, x, css_number_number, "px"}; else tok = {PERCENTAGE, x, css_number_number}; - + m_style.add_property(prop_name, {tok}); } diff --git a/libs/litehtml/src/iterators.cpp b/libs/litehtml/src/iterators.cpp index f0a87555c2..3d48e463dd 100644 --- a/libs/litehtml/src/iterators.cpp +++ b/libs/litehtml/src/iterators.cpp @@ -1,8 +1,5 @@ -#include "html.h" #include "iterators.h" -#include "html_tag.h" #include "render_item.h" -#include <iterator> litehtml::elements_iterator::elements_iterator(bool return_parents, iterator_selector* go_inside, iterator_selector* select) : m_go_inside(go_inside), diff --git a/libs/litehtml/src/line_box.cpp b/libs/litehtml/src/line_box.cpp index fed0aa404d..20aed39fb3 100644 --- a/libs/litehtml/src/line_box.cpp +++ b/libs/litehtml/src/line_box.cpp @@ -45,6 +45,11 @@ int litehtml::line_box_item::left() const return m_element->left(); } +int litehtml::line_box_item::height() const +{ + return m_element->height(); +} + ////////////////////////////////////////////////////////////////////////////////////////// litehtml::lbi_start::lbi_start(const std::shared_ptr<render_item>& element) : line_box_item(element) @@ -86,6 +91,11 @@ int litehtml::lbi_start::left() const return m_pos.x - m_element->content_offset_left(); } +int litehtml::lbi_start::height() const +{ + return m_pos.height; +} + ////////////////////////////////////////////////////////////////////////////////////////// litehtml::lbi_end::lbi_end(const std::shared_ptr<render_item>& element) : lbi_start(element) @@ -180,9 +190,9 @@ int litehtml::line_box::calc_va_baseline(const va_context& current, vertical_ali switch(va) { case va_super: - return current.baseline - current.fm.height / 3; + return current.baseline - current.fm.super_shift; case va_sub: - return current.baseline + current.fm.height / 3; + return current.baseline + current.fm.sub_shift; case va_middle: return current.baseline - current.fm.x_height / 2; case va_text_top: @@ -190,10 +200,10 @@ int litehtml::line_box::calc_va_baseline(const va_context& current, vertical_ali new_font.height - new_font.base_line(); case va_text_bottom: return current.baseline + current.fm.base_line() - new_font.base_line(); + case va_bottom: + return bottom - new_font.base_line(); case va_top: return top + new_font.height - new_font.base_line(); - case va_bottom: - return bottom - new_font.height + new_font.base_line(); default: return current.baseline; } @@ -275,130 +285,236 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish if( is_empty() || (!is_empty() && last_box && is_break_only()) ) { - m_height = m_default_line_height; + m_height = m_default_line_height.computed_value; m_baseline = m_font_metrics.base_line(); return ret_items; } - int spc_x = 0; + int spacing_x = 0; // Number of pixels to distribute between elements + int shift_x = 0; // Shift elements by X to apply the text-align - int add_x = 0; switch(m_text_align) { case text_align_right: if(m_width < (m_right - m_left)) { - add_x = (m_right - m_left) - m_width; + shift_x = (m_right - m_left) - m_width; } break; case text_align_center: if(m_width < (m_right - m_left)) { - add_x = ((m_right - m_left) - m_width) / 2; + shift_x = ((m_right - m_left) - m_width) / 2; } break; case text_align_justify: if (m_width < (m_right - m_left)) { - add_x = 0; - spc_x = (m_right - m_left) - m_width; - if (spc_x > m_width/4) - spc_x = 0; + shift_x = 0; + spacing_x = (m_right - m_left) - m_width; + // don't justify for small lines + if (spacing_x > m_width / 4) + spacing_x = 0; } break; default: - add_x = 0; + shift_x = 0; } int counter = 0; - float offj = float(spc_x) / std::max(1.f, float(m_items.size())-1.f); + float offj = float(spacing_x) / std::max(1.f, float(m_items.size()) - 1.f); float cixx = 0.0f; - int line_top = 0; - int line_bottom = 0; + std::optional<int> line_height; + + if(!m_default_line_height.css_value.is_predefined()) + { + line_height = m_default_line_height.computed_value; + } va_context current_context; std::list<va_context> contexts; current_context.baseline = 0; current_context.fm = m_font_metrics; + current_context.start_lbi = nullptr; + current_context.line_height = m_default_line_height.computed_value; m_min_width = 0; + struct items_dimensions + { + int top = 0; + int bottom = 0; + int count = 0; + int max_height = 0; + + void add_item(const line_box_item* item) + { + top = std::min(top, item->top()); + bottom = std::max(bottom, item->bottom()); + max_height = std::max(max_height, item->height()); + count++; + } + int height() const { return bottom - top; } + }; + + items_dimensions line_max_height; + items_dimensions top_aligned_max_height; + items_dimensions bottom_aligned_max_height; + items_dimensions inline_boxes_dims; + + // First pass + // 1. Apply text-align-justify + // 1. Align all items by baseline + // 2. top/button aligned items are aligned by baseline + // 3. Calculate top and button of the linebox separately for items in baseline + // and for top and bottom aligned items for (const auto& lbi : m_items) - { + { + // Apply text-align-justify m_min_width += lbi->get_rendered_min_width(); - { // start text_align_justify - if (spc_x && counter) + if (spacing_x && counter) + { + cixx += offj; + if ((counter + 1) == int(m_items.size())) + cixx += 0.99f; + lbi->pos().x += int(cixx); + } + counter++; + if ((m_text_align == text_align_right || spacing_x) && counter == int(m_items.size())) + { + // Forcible justify the last element to the right side for text align right and justify; + lbi->pos().x = m_right - lbi->pos().width; + } else if (shift_x) + { + lbi->pos().x += shift_x; + } + + // Calculate new baseline for inline start/continue + // Inline start/continue elements are inline containers like <span> + if (lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue) + { + contexts.push_back(current_context); + if(is_one_of(lbi->get_el()->css().get_vertical_align(), va_top, va_bottom)) { - cixx += offj; - if ((counter + 1) == int(m_items.size())) - cixx += 0.99f; - lbi->pos().x += int(cixx); - } - counter++; - if ((m_text_align == text_align_right || spc_x) && counter == int(m_items.size())) + // top/bottom aligned inline boxes are aligned by baseline == 0 + current_context.baseline = 0; + current_context.start_lbi = lbi.get(); + current_context.start_lbi->reset_items_height(); + } else if(current_context.start_lbi) { - // Forcible justify the last element to the right side for text align right and justify; - lbi->pos().x = m_right - lbi->pos().width; - } else if (add_x) + current_context.baseline = calc_va_baseline(current_context, + lbi->get_el()->css().get_vertical_align(), + lbi->get_el()->css().get_font_metrics(), + current_context.start_lbi->top(), current_context.start_lbi->bottom()); + } else { - lbi->pos().x += add_x; + current_context.start_lbi = nullptr; + current_context.baseline = calc_va_baseline(current_context, + lbi->get_el()->css().get_vertical_align(), + lbi->get_el()->css().get_font_metrics(), + line_max_height.top, line_max_height.bottom); } - } // end text_align_justify + current_context.fm = lbi->get_el()->css().get_font_metrics(); + current_context.line_height = lbi->get_el()->css().line_height().computed_value; + } - if (lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue) + int bl = current_context.baseline; + int content_offset = 0; + bool is_top_bottom_box = false; + bool ignore = false; + + // Align element by baseline + if(!is_one_of(lbi->get_el()->src_el()->css().get_display(), display_inline_text, display_inline)) { - contexts.push_back(current_context); - current_context.baseline = calc_va_baseline(current_context, - lbi->get_el()->css().get_vertical_align(), - lbi->get_el()->css().get_font_metrics(), - line_top, line_bottom); - current_context.fm = lbi->get_el()->css().get_font_metrics(); + // Apply margins, paddings and border for inline boxes + content_offset = lbi->get_el()->content_offset_top(); + switch (lbi->get_el()->css().get_vertical_align()) + { + case va_bottom: + case va_top: + // Align by base line 0 all inline boxes with top and bottom vertical aling + bl = 0; + is_top_bottom_box = true; + break; + + case va_text_bottom: + lbi->pos().y = bl + current_context.fm.base_line() - lbi->get_el()->height() + content_offset; + ignore = true; + break; + + case va_text_top: + lbi->pos().y = bl - current_context.fm.ascent + content_offset; + ignore = true; + break; + + case va_middle: + lbi->pos().y = bl - current_context.fm.x_height / 2 - lbi->get_el()->height() / 2 + content_offset; + ignore = true; + break; + + default: + bl = calc_va_baseline(current_context, + lbi->get_el()->css().get_vertical_align(), + lbi->get_el()->css().get_font_metrics(), + line_max_height.top, line_max_height.bottom); + break; + } + } + if(!ignore) + { + lbi->pos().y = bl - lbi->get_el()->get_last_baseline() + content_offset; } - // Align elements vertically by baseline. - if(lbi->get_el()->src_el()->css().get_display() == display_inline_text || lbi->get_el()->src_el()->css().get_display() == display_inline) - { - // inline elements and text are aligned by baseline only - // at this point the baseline for text is properly aligned already - lbi->pos().y = current_context.baseline - lbi->get_el()->css().get_font_metrics().height + lbi->get_el()->css().get_font_metrics().base_line(); - } else - { - switch(lbi->get_el()->css().get_vertical_align()) - { - case va_sub: - case va_super: - { - int bl = calc_va_baseline(current_context, lbi->get_el()->css().get_vertical_align(), current_context.fm, line_top, line_bottom); - lbi->pos().y = bl - lbi->get_el()->get_last_baseline() + - lbi->get_el()->content_offset_top(); - } + if(is_top_bottom_box) + { + switch (lbi->get_el()->css().get_vertical_align()) + { + case va_top: + top_aligned_max_height.add_item(lbi.get()); break; case va_bottom: - lbi->pos().y = line_bottom - lbi->get_el()->height() + lbi->get_el()->content_offset_top(); + bottom_aligned_max_height.add_item(lbi.get()); break; + default: + break; + } + } else if(current_context.start_lbi) + { + current_context.start_lbi->add_item_height(lbi->top(), lbi->bottom()); + switch (current_context.start_lbi->get_el()->css().get_vertical_align()) + { case va_top: - lbi->pos().y = line_top + lbi->get_el()->content_offset_top(); + top_aligned_max_height.add_item(lbi.get()); break; - case va_baseline: - lbi->pos().y = current_context.baseline - lbi->get_el()->get_last_baseline() + - lbi->get_el()->content_offset_top(); - break; - case va_text_top: - lbi->pos().y = current_context.baseline - current_context.fm.height + current_context.fm.base_line() + - lbi->get_el()->content_offset_top(); - break; - case va_text_bottom: - lbi->pos().y = current_context.baseline + current_context.fm.base_line() - lbi->get_el()->height() + - lbi->get_el()->content_offset_top(); + case va_bottom: + bottom_aligned_max_height.add_item(lbi.get()); break; - case va_middle: - lbi->pos().y = current_context.baseline - current_context.fm.x_height / 2 - lbi->get_el()->height() / 2 + - lbi->get_el()->content_offset_top(); - break; - } - } + default: + break; + } + } else + { + if(!lbi->get_el()->src_el()->is_inline_box()) + { + line_max_height.add_item(lbi.get()); + } else + { + inline_boxes_dims.add_item(lbi.get()); + } + } + + if(!lbi->get_el()->src_el()->is_inline_box() && !lbi->get_el()->css().line_height().css_value.is_predefined()) + { + if(line_height.has_value()) + { + line_height = std::max(line_height.value(), lbi->get_el()->css().line_height().computed_value); + } else + { + line_height = lbi->get_el()->css().line_height().computed_value; + } + } if (lbi->get_type() == line_box_item::type_inline_end) { @@ -408,25 +524,68 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish contexts.pop_back(); } } + } - // calculate line height - line_top = std::min(line_top, lbi->top()); - line_bottom = std::max(line_bottom, lbi->bottom()); - - if(lbi->get_el()->src_el()->css().get_display() == display_inline_text) + int top_shift = 0; + if(line_height.has_value()) + { + m_height = line_height.value(); + if(line_max_height.count != 0) + { + // We have inline items + top_shift = std::abs(line_max_height.top); + const int top_shift_correction = (line_height.value() - line_max_height.height()) / 2; + m_baseline = line_max_height.bottom + top_shift_correction; + top_shift += top_shift_correction; + if(inline_boxes_dims.count) + { + const int diff2 = std::abs(inline_boxes_dims.top) - std::abs(top_shift); + if(diff2 > 0) + { + m_height += diff2; + top_shift += diff2; + m_baseline += diff2; + } + const int diff1 = inline_boxes_dims.bottom - (line_max_height.bottom + top_shift_correction); + if(diff1 > 0) + { + m_height += diff1; + } + } + } else if(inline_boxes_dims.count != 0) + { + // We have inline boxes only + m_height = inline_boxes_dims.height(); + top_shift = std::abs(inline_boxes_dims.top); + m_baseline = inline_boxes_dims.bottom; + } else { - m_line_height = std::max(m_line_height, lbi->get_el()->css().get_line_height()); + // We don't have inline items and inline boxes + top_shift = 0; } - } - m_height = line_bottom - line_top; - int top_shift = line_top; - if(m_height < m_line_height) + + const int top_down_height = std::max(top_aligned_max_height.max_height, bottom_aligned_max_height.max_height); + if(top_down_height > m_height) + { + if(bottom_aligned_max_height.count) + { + top_shift += bottom_aligned_max_height.height() - m_height; + } + m_height = top_down_height; + } + } else { - top_shift -= (m_line_height - m_height) / 2; - m_height = m_line_height; + // Add inline boxes dimentions + line_max_height.top = std::min(line_max_height.top, inline_boxes_dims.top); + line_max_height.bottom = std::max(line_max_height.bottom, inline_boxes_dims.bottom); + + // Height is maximum from inline elements height and top/bottom aligned elements height + m_height = std::max({line_max_height.height(), top_aligned_max_height.height(), bottom_aligned_max_height.height()}); + + top_shift = -std::min(line_max_height.top, line_max_height.bottom - bottom_aligned_max_height.height()); + m_baseline = line_max_height.bottom; } - m_baseline = line_bottom; struct inline_item_box { @@ -443,37 +602,30 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish current_context.baseline = 0; current_context.fm = m_font_metrics; - bool va_top_bottom = false; + current_context.start_lbi = nullptr; + //int va_top_bottom = 0; + // Second pass: + // 1. Vertical align top/bottom + // 2. Apply relative shift + // 3. Calculate inline boxes for (const auto& lbi : m_items) { - // Calculate baseline. Now we calculate baseline for vertical alignment top and bottom - if (lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue) + if(is_one_of(lbi->get_type(), line_box_item::type_inline_start, line_box_item::type_inline_continue)) { contexts.push_back(current_context); - va_top_bottom = lbi->get_el()->css().get_vertical_align() == va_bottom || lbi->get_el()->css().get_vertical_align() == va_top; - current_context.baseline = calc_va_baseline(current_context, - lbi->get_el()->css().get_vertical_align(), - lbi->get_el()->css().get_font_metrics(), - top_shift, top_shift + m_height); current_context.fm = lbi->get_el()->css().get_font_metrics(); - } - // Align inlines and text by baseline if current vertical alignment is top or bottom - if(va_top_bottom) - { - if (lbi->get_el()->src_el()->css().get_display() == display_inline_text || - lbi->get_el()->src_el()->css().get_display() == display_inline) + if(lbi->get_el()->css().get_vertical_align() == va_top) { - // inline elements and text are aligned by baseline only - // at this point the baseline for text is properly aligned already - lbi->pos().y = current_context.baseline - lbi->get_el()->css().get_font_metrics().height + - lbi->get_el()->css().get_font_metrics().base_line(); + current_context.baseline = m_top - lbi->get_items_top(); + current_context.start_lbi = lbi.get(); + } else if(lbi->get_el()->css().get_vertical_align() == va_bottom) + { + current_context.baseline = m_top + m_height - lbi->get_items_bottom(); + current_context.start_lbi = lbi.get(); } - } - - // Pop the prev context - if (lbi->get_type() == line_box_item::type_inline_end) + } else if(lbi->get_type() == line_box_item::type_inline_end) { if(!contexts.empty()) { @@ -482,20 +634,25 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish } } - // move element to the correct position - lbi->pos().y += m_top - top_shift; - - // Perform vertical align top and bottom for inline boxes - if(lbi->get_el()->css().get_display() != display_inline_text && lbi->get_el()->css().get_display() != display_inline) - { - if(lbi->get_el()->css().get_vertical_align() == va_top) + if(current_context.start_lbi) + { + lbi->pos().y = current_context.baseline - lbi->get_el()->get_last_baseline() + + lbi->get_el()->content_offset_top(); + } else if(is_one_of(lbi->get_el()->css().get_vertical_align(), va_top, va_bottom) && lbi->get_type() == line_box_item::type_text_part) + { + if(lbi->get_el()->css().get_vertical_align() == va_top) { lbi->pos().y = m_top + lbi->get_el()->content_offset_top(); - } else if(lbi->get_el()->css().get_vertical_align() == va_bottom) + } else { - lbi->pos().y = m_top + m_height - lbi->get_el()->height() + lbi->get_el()->content_offset_top(); + lbi->pos().y = m_top + m_height - (lbi->bottom() - lbi->top()) + lbi->get_el()->content_offset_bottom(); } - } + } else + { + // move element to the correct position + lbi->pos().y += m_top + top_shift; + } + lbi->get_el()->apply_relative_shift(containing_block_size); // Calculate and push inline box into the render item element @@ -703,11 +860,9 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::new_wi { remove_begin = i; break; - } else - { - (*i)->pos().x += add; - m_width += (*i)->get_el()->width(); } + (*i)->pos().x += add; + m_width += (*i)->get_el()->width(); } i++; } @@ -722,4 +877,3 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::new_wi } return ret_items; } - diff --git a/libs/litehtml/src/media_query.cpp b/libs/litehtml/src/media_query.cpp index 8593f89f11..e2e17eb8a4 100644 --- a/libs/litehtml/src/media_query.cpp +++ b/libs/litehtml/src/media_query.cpp @@ -2,6 +2,8 @@ #include "media_query.h" #include "css_parser.h" #include <cassert> +#include "document.h" +#include "document_container.h" #define UNE 8800 // u'≠' #define ULE 10877 // u'⩽' @@ -53,7 +55,7 @@ bool media_feature::check(const media_features& feat) const return compare(feat.height >= feat.width ? _portrait_ : _landscape_); case _aspect_ratio_: // The standard calls 1/0 "a degenerate ratio" https://drafts.csswg.org/css-values-4/#ratio-value, - // but it doesn't specify exactly how it behaves in this context: https://drafts.csswg.org/mediaqueries-5/#aspect-ratio. + // but it doesn't specify exactly how it behaves in this context: https://drafts.csswg.org/mediaqueries-5/#aspect-ratio. // Chrome/Firefox work as expected with 1/0, for example when both width and height are nonzero // (aspect-ratio < 1/0) evaluates to true. But they behave the same for 0/0, which is unexpected // (0/0 is NaN, so any comparisons should evaluate to false). @@ -79,12 +81,12 @@ trilean media_condition::check(const media_features& features) const { if (op == _not_) return !m_conditions[0].check(features); - + if (op == _and_) { // https://drafts.csswg.org/mediaqueries/#evaluating - // The result is true if the <media-in-parens> child term and all of the <media-in-parens> - // children of the <media-and> child terms are true, false if at least one of these + // The result is true if the <media-in-parens> child term and all of the <media-in-parens> + // children of the <media-and> child terms are true, false if at least one of these // <media-in-parens> terms are false, and unknown otherwise. trilean result = True; for (const auto& condition : m_conditions) @@ -96,8 +98,8 @@ trilean media_condition::check(const media_features& features) const } if (op == _or_) { - // The result is false if the <media-in-parens> child term and all of the <media-in-parens> - // children of the <media-or> child terms are false, true if at least one of these + // The result is false if the <media-in-parens> child term and all of the <media-in-parens> + // children of the <media-or> child terms are false, true if at least one of these // <media-in-parens> terms are true, and unknown otherwise. trilean result = False; for (const auto& condition : m_conditions) @@ -129,7 +131,7 @@ trilean media_query::check(const media_features& features) const result = False; else if (m_media_type == media_type_all) result = True; - else + else result = (trilean)(m_media_type == features.type); if (result == True) @@ -237,7 +239,7 @@ bool parse_media_query(const css_token_vector& tokens, media_query& mquery, docu bool _not = false; if (ident == "not") index++, _not = true; else if (ident == "only") index++; // ignored https://drafts.csswg.org/mediaqueries-5/#mq-only - + // <media-type> = <ident> except only, not, and, or, and layer ident = at(tokens, index).ident(); if (is_one_of(ident, "", "only", "not", "and", "or", "layer")) @@ -310,7 +312,7 @@ bool parse_media_in_parens(const css_token& token, media_in_parens& media_in_par media_in_parens = unknown(); return true; } - + if (token.type != ROUND_BLOCK) return false; const css_token_vector& tokens = token.value; @@ -344,7 +346,7 @@ struct mf_info string_id type = empty_id; // range, discrete string_id value_type = empty_id; // length, ratio, resolution, integer, keyword vector<string_id> keywords = {}; // default value is specified here to get rid of gcc warning "missing initializer for member" - + operator bool() { return type != empty_id; } }; @@ -407,7 +409,7 @@ bool convert_units(mf_info mfi, css_token val[2], document::ptr doc) case _integer_: // nothing to convert, just verify return val[0].type == NUMBER && val[0].n.number_type == css_number_integer && val[1].type == 0; - + case _length_: { if (val[1].type != 0) return false; @@ -419,7 +421,7 @@ bool convert_units(mf_info mfi, css_token val[2], document::ptr doc) val[0].n.number = length.val(); return true; } - + case _resolution_: // https://drafts.csswg.org/css-values-4/#resolution if (val[1].type != 0) return false; if (val[0].type == DIMENSION) @@ -444,7 +446,7 @@ bool convert_units(mf_info mfi, css_token val[2], document::ptr doc) } // Note: <resolution> doesn't allow unitless zero return false; - + case _ratio_: // https://drafts.csswg.org/css-values-4/#ratio <ratio> = <number [0,∞]> [ / <number [0,∞]> ]? if (val[0].type == NUMBER && val[0].n.number >= 0 && ((val[1].type == NUMBER && val[1].n.number >= 0) || val[1].type == 0)) @@ -463,7 +465,7 @@ bool convert_units(mf_info mfi, css_token val[2], document::ptr doc) val[0] = css_token(NUMBER, (float)ident); return true; } - + default: return false; } @@ -549,7 +551,7 @@ bool parse_media_feature(const css_token& token, media_feature& result, document int index = 2; if (!parse_mf_value(tokens, index, val) || index != (int)tokens.size()) return false; - + media_feature mf = {tokens[0].ident()}; if (!mf.verify_and_convert_units(_plain_, val, nullptr, doc)) return false; result = mf; @@ -566,9 +568,9 @@ bool parse_mf_value(const css_token_vector& tokens, int& index, css_token val[2] const css_token& a = at(tokens, index); const css_token& b = at(tokens, index + 1); const css_token& c = at(tokens, index + 2); - + if (!is_one_of(a.type, NUMBER, DIMENSION, IDENT)) return false; - + if (a.type == NUMBER && a.n.number >= 0 && b.ch == '/' && c.type == NUMBER && c.n.number >= 0) { diff --git a/libs/litehtml/src/render_block.cpp b/libs/litehtml/src/render_block.cpp index 7e2867f35e..6fba641b03 100644 --- a/libs/litehtml/src/render_block.cpp +++ b/libs/litehtml/src/render_block.cpp @@ -1,8 +1,9 @@ -#include "html.h" #include "render_block.h" #include "render_inline_context.h" #include "render_block_context.h" #include "document.h" +#include "document_container.h" +#include "html_tag.h" int litehtml::render_item_block::place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx) { @@ -199,7 +200,7 @@ int litehtml::render_item_block::_render(int x, int y, const containing_block_co { if(m_pos.height == 0) { - m_pos.height = css().get_line_height(); + m_pos.height = css().line_height().computed_value; } } diff --git a/libs/litehtml/src/render_block_context.cpp b/libs/litehtml/src/render_block_context.cpp index 205485d478..d039985003 100644 --- a/libs/litehtml/src/render_block_context.cpp +++ b/libs/litehtml/src/render_block_context.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "render_block_context.h" #include "document.h" diff --git a/libs/litehtml/src/render_flex.cpp b/libs/litehtml/src/render_flex.cpp index 7b497cf312..ad8ff3a2fc 100644 --- a/libs/litehtml/src/render_flex.cpp +++ b/libs/litehtml/src/render_flex.cpp @@ -1,6 +1,6 @@ -#include "html.h" #include "types.h" #include "render_flex.h" +#include "html_tag.h" int litehtml::render_item_flex::_render_content(int x, int y, bool /*second_pass*/, const containing_block_context &self_size, formatting_context* fmt_ctx) { diff --git a/libs/litehtml/src/render_image.cpp b/libs/litehtml/src/render_image.cpp index 23b059bd90..0f13216079 100644 --- a/libs/litehtml/src/render_image.cpp +++ b/libs/litehtml/src/render_image.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "render_image.h" #include "document.h" @@ -19,7 +18,7 @@ int litehtml::render_item_image::_render(int x, int y, const containing_block_co m_pos.width = sz.width; m_pos.height = sz.height; - src_el()->css_w().set_line_height(height()); + src_el()->css_w().line_height_w().computed_value = height(); if(src_el()->css().get_height().is_predefined() && src_el()->css().get_width().is_predefined()) { diff --git a/libs/litehtml/src/render_inline_context.cpp b/libs/litehtml/src/render_inline_context.cpp index fcf23bf733..4c4d974800 100644 --- a/libs/litehtml/src/render_inline_context.cpp +++ b/libs/litehtml/src/render_inline_context.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "render_inline_context.h" #include "document.h" #include "iterators.h" @@ -150,7 +149,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt, { line_left += src_el()->css().get_text_indent().calc_percent(self_size.width); } - + } auto items = m_line_boxes.back()->new_width(line_left, line_right); @@ -227,7 +226,7 @@ int litehtml::render_item_inline_context::new_box(const std::unique_ptr<line_box m_line_boxes.emplace_back(std::make_unique<line_box>( line_ctx.top, line_ctx.left + first_line_margin + text_indent, line_ctx.right, - css().get_line_height(), + css().line_height(), css().get_font_metrics(), css().get_text_align())); @@ -403,7 +402,7 @@ int litehtml::render_item_inline_context::get_last_baseline() bl = line->bottom() - line->baseline() + content_offset_top(); } else { - bl = height() - margin_bottom(); + bl = height(); } return bl; } diff --git a/libs/litehtml/src/render_item.cpp b/libs/litehtml/src/render_item.cpp index 5ec65ab049..3794807a4f 100644 --- a/libs/litehtml/src/render_item.cpp +++ b/libs/litehtml/src/render_item.cpp @@ -1,8 +1,8 @@ -#include "html.h" #include "render_item.h" #include "document.h" #include <typeinfo> -#include <utf8_strings.h> +#include "document_container.h" +#include "types.h" litehtml::render_item::render_item(std::shared_ptr<element> _src_el) : m_element(std::move(_src_el)), @@ -46,7 +46,6 @@ int litehtml::render_item::render(int x, int y, const containing_block_context& if(src_el()->is_block_formatting_context() || ! fmt_ctx) { formatting_context fmt; - fmt.push_position(content_left, content_top); ret = _render(x, y, containing_block_size, &fmt, second_pass); fmt.apply_relative_shift(containing_block_size); } else @@ -243,8 +242,8 @@ bool litehtml::render_item::fetch_positioned() void litehtml::render_item::render_positioned(render_type rt) { - position wnd_position; - src_el()->get_document()->container()->get_client_rect(wnd_position); + position view_port; + src_el()->get_document()->container()->get_viewport(view_port); element_position el_position; bool process; @@ -275,8 +274,8 @@ void litehtml::render_item::render_positioned(render_type rt) containing_block_context containing_block_size; if(el_position == element_position_fixed || (is_root() && !src_el()->is_positioned())) { - containing_block_size.height = wnd_position.height; - containing_block_size.width = wnd_position.width; + containing_block_size.height = view_port.height; + containing_block_size.width = view_port.width; } else { containing_block_size.height = m_pos.height + m_padding.height(); @@ -648,8 +647,8 @@ void litehtml::render_item::render_positioned(render_type rt) if(el_position == element_position_fixed) { - position fixed_pos; - el->get_redraw_box(fixed_pos); + position fixed_pos = el->pos(); + el->get_redraw_box(fixed_pos); src_el()->get_document()->add_fixed_box(fixed_pos); } } @@ -832,12 +831,10 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi if (el->src_el()->is_positioned() && el->src_el()->css().get_z_index() == zindex) { if (el->src_el()->css().get_position() == element_position_fixed) - { - position browser_wnd; - doc->container()->get_client_rect(browser_wnd); - - el->src_el()->draw(hdc, browser_wnd.x, browser_wnd.y, clip, el); - el->draw_stacking_context(hdc, browser_wnd.x, browser_wnd.y, clip, true); + { + // Fixed elements position is always relative to the (0,0) + el->src_el()->draw(hdc, 0, 0, clip, el); + el->draw_stacking_context(hdc, 0, 0, clip, true); } else { @@ -1129,17 +1126,39 @@ void litehtml::render_item::get_rendering_boxes( position::vector& redraw_boxes) if(src_el()->css().get_position() != element_position_fixed) { - auto cur_el = parent(); + auto cur_el = parent(); + int add_x = 0; + int add_y = 0; + while(cur_el) - { - for(auto& box : redraw_boxes) - { - box.x += cur_el->m_pos.x; - box.y += cur_el->m_pos.y; - } + { + if(cur_el->css().get_position() == element_position_fixed) + { + position view_port; + src_el()->get_document()->container()->get_viewport(view_port); + add_x += cur_el->m_pos.x + view_port.left(); + add_y += cur_el->m_pos.y + view_port.top(); + break; + } + add_x += cur_el->m_pos.x; + add_y += cur_el->m_pos.y; cur_el = cur_el->parent(); } - } + for(auto& box : redraw_boxes) + { + box.x += add_x; + box.y += add_y; + } + } else + { + position view_port; + src_el()->get_document()->container()->get_viewport(view_port); + for(auto& box : redraw_boxes) + { + box.x += view_port.left(); + box.y += view_port.top(); + } + } } void litehtml::render_item::dump(litehtml::dumper& cout) diff --git a/libs/litehtml/src/render_table.cpp b/libs/litehtml/src/render_table.cpp index 16a143eb43..4792f14972 100644 --- a/libs/litehtml/src/render_table.cpp +++ b/libs/litehtml/src/render_table.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "render_table.h" #include "document.h" #include "iterators.h" diff --git a/libs/litehtml/src/string_id.cpp b/libs/litehtml/src/string_id.cpp index d197d24469..ac131962b7 100644 --- a/libs/litehtml/src/string_id.cpp +++ b/libs/litehtml/src/string_id.cpp @@ -2,10 +2,12 @@ #include "string_id.h" #include <cassert> +#include <Windows.h> +#include <m_system.h> + #ifndef LITEHTML_NO_THREADS - #include <mutex> - static std::mutex mutex; - #define lock_guard std::lock_guard<std::mutex> lock(mutex) + static mir_cs mutex; + #define lock_guard mir_cslock lock(mutex) #else #define lock_guard #endif diff --git a/libs/litehtml/src/style.cpp b/libs/litehtml/src/style.cpp index 10768700a6..2707dd8bed 100644 --- a/libs/litehtml/src/style.cpp +++ b/libs/litehtml/src/style.cpp @@ -2,6 +2,9 @@ #include "style.h" #include "css_parser.h" #include "internal.h" +#include <set> +#include "html_tag.h" +#include "document.h" // All functions here assume that whitespace have been removed. @@ -28,6 +31,7 @@ std::map<string_id, string> style::m_valid_values = { _float_, element_float_strings }, { _clear_, element_clear_strings }, { _overflow_, overflow_strings }, + { _appearance_, appearance_strings }, { _box_sizing_, box_sizing_strings }, { _text_align_, text_align_strings }, @@ -62,6 +66,9 @@ std::map<string_id, string> style::m_valid_values = { _align_self_, flex_align_items_strings }, { _caption_side_, caption_side_strings }, + + { _text_decoration_style_, style_text_decoration_style_strings }, + { _text_emphasis_position_, style_text_emphasis_position_strings }, }; std::map<string_id, vector<string_id>> shorthands = @@ -101,6 +108,9 @@ std::map<string_id, vector<string_id>> shorthands = { _flex_, {_flex_grow_, _flex_shrink_, _flex_basis_}}, { _flex_flow_, {_flex_direction_, _flex_wrap_}}, + + { _text_decoration_, {_text_decoration_color_, _text_decoration_line_, _text_decoration_style_, _text_decoration_thickness_}}, + { _text_emphasis_, {_text_emphasis_style_, _text_emphasis_color_}}, }; void style::add(const string& txt, const string& baseurl, document_container* container) @@ -167,10 +177,10 @@ void style::add_property(string_id name, const css_token_vector& value, const st // Note: empty value is a valid value for a custom property. if (value.empty() && _s(name).substr(0, 2) != "--") return; - + if (has_var(value)) return add_parsed_property(name, property_value(value, important, true)); - + // valid only if value contains a single token css_token val = value.size() == 1 ? value[0] : css_token(); // nonempty if value is a single identifier @@ -193,6 +203,7 @@ void style::add_property(string_id name, const css_token_vector& value, const st case _position_: case _float_: case _clear_: + case _appearance_: case _box_sizing_: case _overflow_: @@ -203,6 +214,7 @@ void style::add_property(string_id name, const css_token_vector& value, const st case _font_style_: case _font_variant_: + case _text_decoration_style_: case _list_style_type_: case _list_style_position_: @@ -233,7 +245,7 @@ void style::add_property(string_id name, const css_token_vector& value, const st // <length-percentage> https://developer.mozilla.org/en-US/docs/Web/CSS/text-indent#formal_syntax case _text_indent_: return add_length_property(name, val, "", f_length_percentage, important); - + // <length-percentage [0,∞]> https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left case _padding_left_: case _padding_right_: @@ -251,7 +263,7 @@ void style::add_property(string_id name, const css_token_vector& value, const st case _margin_top_: case _margin_bottom_: return add_length_property(name, val, "auto", f_length_percentage, important); - + // auto | min-content | max-content | fit-content | <length-percentage [0,∞]> https://developer.mozilla.org/en-US/docs/Web/CSS/width#formal_syntax case _width_: case _height_: @@ -281,7 +293,7 @@ void style::add_property(string_id name, const css_token_vector& value, const st if (int n = parse_1234_lengths(value, len, f_length_percentage | f_positive)) add_four_properties(_padding_top_, len, n, important); break; - + // ============================= COLOR ============================= case _color_: @@ -370,8 +382,8 @@ void style::add_property(string_id name, const css_token_vector& value, const st case _border_radius_x_: case _border_radius_y_: { - string_id top_left = name == _border_radius_x_ ? - _border_top_left_radius_x_ : + string_id top_left = name == _border_radius_x_ ? + _border_top_left_radius_x_ : _border_top_left_radius_y_; if (int n = parse_1234_lengths(value, len, f_length_percentage | f_positive)) @@ -424,10 +436,38 @@ void style::add_property(string_id name, const css_token_vector& value, const st break; case _text_decoration_: + parse_text_decoration(value, important, container); + break; + + case _text_decoration_thickness_: + add_length_property(name, val, style_text_decoration_thickness_strings, f_length_percentage|f_positive, important); + break; + + case _text_decoration_color_: + parse_text_decoration_color(val, important, container); + break; + + case _text_decoration_line_: + parse_text_decoration_line(value, important); + break; + + case _text_emphasis_: + parse_text_emphasis(value, important, container); + break; + + case _text_emphasis_style_: str = get_repr(value, 0, -1, true); add_parsed_property(name, property_value(str, important)); break; + case _text_emphasis_color_: + parse_text_emphasis_color(val, important, container); + break; + + case _text_emphasis_position_: + parse_text_emphasis_position(value, important); + break; + // ============================= FLEX ============================= case _flex_: @@ -484,10 +524,10 @@ void style::add_property(string_id name, const css_token_vector& value, const st break; // ============================= CUSTOM PROPERTY ============================= - + // https://drafts.csswg.org/css-variables-2/#defining-variables default: - if (_s(name).substr(0, 2) == "--" && _s(name).size() >= 3 && + if (_s(name).substr(0, 2) == "--" && _s(name).size() >= 3 && (value.empty() || is_declaration_value(value))) add_parsed_property(name, property_value(value, important)); } @@ -527,7 +567,7 @@ void style::parse_list_style(const css_token_vector& tokens, string baseurl, boo for (const auto& token : tokens) { - // "...none is a valid value for both list-style-image and list-style-type. To resolve this ambiguity, + // "...none is a valid value for both list-style-image and list-style-type. To resolve this ambiguity, // a value of none ... must be applied to whichever of the two properties aren’t otherwise set by the shorthand." if (token.ident() == "none") { none_count++; @@ -566,12 +606,12 @@ void style::parse_list_style(const css_token_vector& tokens, string baseurl, boo } // https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius -// border-radius = <length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]? +// border-radius = <length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]? void style::parse_border_radius(const css_token_vector& tokens, bool important) { int i; for (i = 0; i < (int)tokens.size() && tokens[i].ch != '/'; i++) {} - + if (i == (int)tokens.size()) // no '/' { css_length len[4]; @@ -585,11 +625,11 @@ void style::parse_border_radius(const css_token_vector& tokens, bool important) { auto raduis_x = slice(tokens, 0, i); auto raduis_y = slice(tokens, i + 1); - + css_length rx[4], ry[4]; int n = parse_1234_lengths(raduis_x, rx, f_length_percentage | f_positive); int m = parse_1234_lengths(raduis_y, ry, f_length_percentage | f_positive); - + if (n && m) { add_four_properties(_border_top_left_radius_x_, rx, n, important); @@ -603,10 +643,10 @@ bool parse_border_width(const css_token& token, css_length& w) css_length width; if (!width.from_token(token, f_length | f_positive, border_width_strings)) return false; - + if (width.is_predefined()) width.set_value(border_width_values[width.predef()], css_units_px); - + w = width; return true; } @@ -650,7 +690,7 @@ void style::parse_border(const css_token_vector& tokens, bool important, documen css_length width; border_style style; web_color color; - + if (!parse_border_helper(tokens, container, width, style, color)) return; @@ -724,7 +764,7 @@ int parse_1234_lengths(const css_token_vector& tokens, css_length len[4], int op // This function implements the logic of the kind "if two values are specified, the first one applies to // top and bottom, the second one to left and right". Works in conjunction with parse_1234_values. -template<class T> +template<class T> void style::add_four_properties(string_id top_name, T val[4], int n, bool important) { // These always go in trbl order, see comment for "CSS property names" in string_id. @@ -751,7 +791,7 @@ void style::parse_background(const css_token_vector& tokens, const string& baseu if (layers.empty()) return; web_color color; - std::vector<image> images; + std::vector<image> images; length_vector x_positions, y_positions; size_vector sizes; int_vector repeats, attachments, origins, clips; @@ -761,7 +801,7 @@ void style::parse_background(const css_token_vector& tokens, const string& baseu background bg; if (!parse_bg_layer(layers[i], container, bg, i == layers.size() - 1)) return; - + color = bg.m_color; images.push_back(bg.m_image[0]); x_positions.push_back(bg.m_position_x[0]); @@ -821,7 +861,7 @@ bool style::parse_bg_layer(const css_token_vector& tokens, document_container* c repeat_found = true; else if (!attachment_found && parse_keyword(tokens[i], bg.m_attachment[0], background_attachment_strings)) attachment_found = true; - // If one <visual-box> value is present then it sets both background-origin and background-clip to that value. + // If one <visual-box> value is present then it sets both background-origin and background-clip to that value. // If two values are present, then the first sets background-origin and the second background-clip. else if (!origin_found && parse_keyword(tokens[i], bg.m_origin[0], background_box_strings)) origin_found = true, bg.m_clip[0] = bg.m_origin[0]; @@ -841,7 +881,7 @@ bool parse_bg_position_size(const css_token_vector& tokens, int& index, css_leng if (at(tokens, index).ch != '/') return true; // no [ / <bg-size> ] - + if (!parse_bg_size(tokens, ++index, size)) { index--; // restore index to point to '/' @@ -859,7 +899,7 @@ bool parse_bg_size(const css_token_vector& tokens, int& index, css_size& size) if (!a.from_token(at(tokens, index), f_length_percentage | f_positive, background_size_strings)) return false; - + // cover | contain if (a.is_predefined() && a.predef() != background_size_auto) { @@ -900,7 +940,7 @@ bool parse_bg_position(const css_token_vector& tokens, int& index, css_length& x bottom = background_position_bottom, center = background_position_center }; - + css_length a, b; if (!a.from_token(at(tokens, index), f_length_percentage, background_position_strings)) @@ -924,7 +964,7 @@ bool parse_bg_position(const css_token_vector& tokens, int& index, css_length& x if ((is_one_of_predef(a, top, bottom) && b.is_predefined()) || (a.is_predefined() && is_one_of_predef(b, left, right))) swap(a, b); - + // check for wrong order if (is_one_of_predef(a, top, bottom) || is_one_of_predef(b, left, right)) return false; @@ -939,7 +979,7 @@ bool parse_bg_position(const css_token_vector& tokens, int& index, css_length& x if (b.is_predefined()) b.set_value(background_position_percentages[b.predef()], css_units_percentage); } - + x = a; y = b; return true; @@ -949,7 +989,7 @@ void style::parse_background_image(const css_token_vector& tokens, const string& { auto layers = parse_comma_separated_list(tokens); if (layers.empty()) return; - + std::vector<image> images; for (const auto& layer : layers) @@ -1009,7 +1049,7 @@ bool parse_url(const css_token& tok, string& url) url = trim(tok.value[0].str); return true; } - + return false; } @@ -1231,6 +1271,121 @@ void style::parse_font(css_token_vector tokens, bool important) add_parsed_property(_font_family_, property_value(font_family, important)); } +void style::parse_text_decoration(const css_token_vector& tokens, bool important, document_container* container) +{ + css_length len; + css_token_vector line_tokens; + for(const auto& token : tokens) + { + if(parse_text_decoration_color(token, important, container)) continue; + + if(parse_length(token, len, f_length_percentage|f_positive, style_text_decoration_thickness_strings)) + { + add_parsed_property(_text_decoration_thickness_, property_value(len, important)); + } else + { + if(token.type == IDENT) + { + int style = value_index(token.ident(), style_text_decoration_style_strings); + if(style >= 0) + { + add_parsed_property(_text_decoration_style_, property_value(style, important)); + } else + { + line_tokens.push_back(token); + } + } else + { + line_tokens.push_back(token); + } + } + } + if(!line_tokens.empty()) + { + parse_text_decoration_line(line_tokens, important); + } +} + +bool style::parse_text_decoration_color(const css_token& token, bool important, document_container* container) +{ + web_color _color; + if(parse_color(token, _color, container)) + { + add_parsed_property(_text_decoration_color_, property_value(_color, important)); + return true; + } + if(token.type == IDENT && value_in_list(token.ident(), "auto;currentcolor")) + { + add_parsed_property(_text_decoration_color_, property_value(web_color::current_color, important)); + return true; + } + return false; +} + +void style::parse_text_decoration_line(const css_token_vector& tokens, bool important) +{ + int val = 0; + for(const auto& token : tokens) + { + if(token.type == IDENT) + { + int idx = value_index(token.ident(), style_text_decoration_line_strings); + if(idx >= 0) + { + val |= 1 << (idx - 1); + } + } + } + add_parsed_property(_text_decoration_line_, property_value(val, important)); +} + +void style::parse_text_emphasis(const css_token_vector& tokens, bool important, document_container *container) { + string style; + for(const auto& token : std::vector(tokens.rbegin(), tokens.rend())) + { + if(parse_text_emphasis_color(token, important, container)) continue; + style.insert(0, token.str + " "); + } + style = trim(style); + if (!style.empty()) + { + add_parsed_property(_text_emphasis_style_, property_value(style, important)); + } +} + +bool style::parse_text_emphasis_color(const css_token &token, bool important, document_container *container) +{ + web_color _color; + if(parse_color(token, _color, container)) + { + add_parsed_property(_text_emphasis_color_, property_value(_color, important)); + return true; + } + if(token.type == IDENT && value_in_list(token.ident(), "auto;currentcolor")) + { + add_parsed_property(_text_emphasis_color_, property_value(web_color::current_color, important)); + return true; + } + return false; +} + +void style::parse_text_emphasis_position(const css_token_vector &tokens, bool important) +{ + int val = 0; + for(const auto& token : tokens) + { + if(token.type == IDENT) + { + int idx = value_index(token.ident(), style_text_emphasis_position_strings); + if(idx >= 0) + { + val |= 1 << (idx - 1); + } + } + } + add_parsed_property(_text_emphasis_position_, property_value(val, important)); +} + // https://developer.mozilla.org/en-US/docs/Web/CSS/flex // https://drafts.csswg.org/css-flexbox/#flex-property // flex = none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] @@ -1355,9 +1510,9 @@ void style::parse_align_self(string_id name, const css_token_vector& tokens, boo return; if (tokens[0].type != IDENT || (n == 2 && tokens[1].type != IDENT)) return; - + string a = tokens[0].ident(); - + if (name == _align_items_ && a == "auto") return; @@ -1441,11 +1596,11 @@ const property_value& style::get_property(string_id name) const bool check_var_syntax(const css_token_vector& args) { if (args.empty()) return false; - + string name = args[0].ident(); if (name.substr(0, 2) != "--" || name.size() <= 2) return false; - + if (args.size() > 1 && args[1].ch != ',') return false; if (args.size() > 2 && !is_declaration_value(args, 2)) @@ -1467,11 +1622,11 @@ bool subst_var(css_token_vector& tokens, const html_tag* el, std::set<string_id> { auto args = tok.value; // copy is intentional if (!check_var_syntax(args)) return false; - + auto name = _id(args[0].name); if (name in used_vars) return false; // dependency cycle https://drafts.csswg.org/css-variables/#cycles used_vars.insert(name); - + css_token_vector value; if (el->get_custom_property(name, value)) { diff --git a/libs/litehtml/src/stylesheet.cpp b/libs/litehtml/src/stylesheet.cpp index bb428b1328..d6ddca5e8f 100644 --- a/libs/litehtml/src/stylesheet.cpp +++ b/libs/litehtml/src/stylesheet.cpp @@ -1,6 +1,8 @@ #include "html.h" #include "stylesheet.h" #include "css_parser.h" +#include "document.h" +#include "document_container.h" namespace litehtml { @@ -12,12 +14,12 @@ void css::parse_css_stylesheet(const Input& input, string baseurl, document::ptr if (doc && media) doc->add_media_list(media); - // To parse a CSS stylesheet, first parse a stylesheet. + // To parse a CSS stylesheet, first parse a stylesheet. auto rules = css_parser::parse_stylesheet(input, top_level); bool import_allowed = top_level; // Interpret all of the resulting top-level qualified rules as style rules, defined below. - // If any style rule is invalid, or any at-rule is not recognized or is invalid according + // If any style rule is invalid, or any at-rule is not recognized or is invalid according // to its grammar or context, it's a parse error. Discard that rule. for (auto rule : rules) { @@ -40,7 +42,7 @@ void css::parse_css_stylesheet(const Input& input, string baseurl, document::ptr else css_parse_error("incorrect placement of @import rule"); break; - + // https://www.w3.org/TR/css-conditional-3/#at-media // @media <media-query-list> { <stylesheet> } case _media_: @@ -58,7 +60,7 @@ void css::parse_css_stylesheet(const Input& input, string baseurl, document::ptr import_allowed = false; break; } - + default: css_parse_error("unrecognized rule @" + rule->name); } @@ -115,7 +117,7 @@ bool css::parse_style_rule(raw_rule::ptr rule, string baseurl, document::ptr doc } style::ptr style = make_shared<litehtml::style>(); // style block - // The content of the qualified rule's block is parsed as a style block's contents. + // The content of the qualified rule's block is parsed as a style block's contents. style->add(rule->block.value, baseurl, doc->container()); for (auto sel : list) diff --git a/libs/litehtml/src/url.cpp b/libs/litehtml/src/url.cpp index caa8fbb9d3..dbae382ace 100644 --- a/libs/litehtml/src/url.cpp +++ b/libs/litehtml/src/url.cpp @@ -29,7 +29,6 @@ #include "url.h" -#include <iostream> #include <sstream> #include <algorithm> diff --git a/libs/litehtml/src/utf8_strings.cpp b/libs/litehtml/src/utf8_strings.cpp index f720f6d26c..6a578e1b9e 100644 --- a/libs/litehtml/src/utf8_strings.cpp +++ b/libs/litehtml/src/utf8_strings.cpp @@ -1,4 +1,3 @@ -#include "html.h" #include "utf8_strings.h" namespace litehtml @@ -13,7 +12,7 @@ char32_t read_utf8_char(const string& str, int& index) if (!str[index]) return 0; return str[index++]; }; - + byte b1 = getb(); // Determine whether we are dealing diff --git a/libs/litehtml/src/web_color.cpp b/libs/litehtml/src/web_color.cpp index 51c6e762f1..c9472432d7 100644 --- a/libs/litehtml/src/web_color.cpp +++ b/libs/litehtml/src/web_color.cpp @@ -1,6 +1,8 @@ #include "html.h" #include "web_color.h" #include "css_parser.h" +#include "os_types.h" +#include "document_container.h" namespace litehtml { @@ -18,7 +20,7 @@ struct def_color const char* rgb; }; -def_color g_def_colors[] = +def_color g_def_colors[] = { {"transparent","rgba(0, 0, 0, 0)"}, {"AliceBlue","#F0F8FF"}, @@ -268,7 +270,7 @@ bool parse_rgb_func(const css_token& tok, web_color& color) int n = (int)list.size(); if (!is_one_of(n, 1, 3, 4)) return false; - + css_length r, g, b, a(1, css_units_none); // legacy syntax: <percentage>#{3} , <alpha-value>? | <number>#{3} , <alpha-value>? if (n != 1) @@ -354,18 +356,18 @@ bool parse_hsl_func(const css_token& tok, web_color& color) float lit = l.val(); // For historical reasons, if the saturation is less than 0% it is clamped to 0% at parsed-value time, before being converted to an sRGB color. if (sat < 0) sat = 0; - + // Note: Chrome and Firefox treat invalid hsl values differently. - // - // Note: at this point, sat is not clamped at 100, and lit is not clamped at all. The standard + // + // Note: at this point, sat is not clamped at 100, and lit is not clamped at all. The standard // mentions only clamping sat at 0. As a result, returning rgb values may not be inside [0,1]. float r, g, b; hsl_to_rgb(hue, sat, lit, r, g, b); - + r = clamp(r, 0, 1); g = clamp(g, 0, 1); b = clamp(b, 0, 1); - + color = web_color( (byte)round(r * 255), (byte)round(g * 255), @@ -411,9 +413,9 @@ bool parse_name_color(const css_token& tok, web_color& color, document_container // https://drafts.csswg.org/css-color-5/#typedef-color bool parse_color(const css_token& tok, web_color& color, document_container* container) { - return - parse_hash_color(tok, color) || - parse_func_color(tok, color) || + return + parse_hash_color(tok, color) || + parse_func_color(tok, color) || parse_name_color(tok, color, container); } |