diff --git a/CMakeLists.txt b/CMakeLists.txt index 34d6b1538..014089023 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ set(SOURCE_LITEHTML src/render_table.cpp src/render_flex.cpp src/render_image.cpp + src/formatting_context.cpp ) set(HEADER_LITEHTML @@ -124,6 +125,7 @@ set(HEADER_LITEHTML include/litehtml/render_item.h include/litehtml/master_css.h include/litehtml/string_id.h + include/litehtml/formatting_context.h ) set(TEST_LITEHTML diff --git a/include/litehtml/document.h b/include/litehtml/document.h index a4a080204..e2623b222 100644 --- a/include/litehtml/document.h +++ b/include/litehtml/document.h @@ -110,7 +110,7 @@ namespace litehtml private: uint_ptr add_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm); - void create_node(void* gnode, elements_vector& elements, bool parseTextNode); + void create_node(void* gnode, elements_list& elements, bool parseTextNode); bool update_media_lists(const media_features& features); void fix_tables_layout(); void fix_table_children(const std::shared_ptr& el_ptr, style_display disp, const char* disp_str); diff --git a/include/litehtml/el_before_after.h b/include/litehtml/el_before_after.h index ac966f395..eed5f3dad 100644 --- a/include/litehtml/el_before_after.h +++ b/include/litehtml/el_before_after.h @@ -11,7 +11,6 @@ namespace litehtml el_before_after_base(const std::shared_ptr& doc, bool before); void add_style(const style& style) override; - void apply_stylesheet(const litehtml::css& stylesheet) override; private: void add_text(const string& txt); void add_function(const string& fnc, const string& params); diff --git a/include/litehtml/el_style.h b/include/litehtml/el_style.h index b6258932d..62f154625 100644 --- a/include/litehtml/el_style.h +++ b/include/litehtml/el_style.h @@ -7,7 +7,7 @@ namespace litehtml { class el_style : public element { - elements_vector m_children; + elements_list m_children; public: explicit el_style(const std::shared_ptr& doc); diff --git a/include/litehtml/element.h b/include/litehtml/element.h index 2fa160c2c..e330b5c01 100644 --- a/include/litehtml/element.h +++ b/include/litehtml/element.h @@ -28,12 +28,12 @@ namespace litehtml protected: std::weak_ptr m_parent; std::weak_ptr m_doc; - elements_vector m_children; + elements_list m_children; css_properties m_css; std::list> m_renders; used_selector::vector m_used_styles; - virtual void select_all(const css_selector& selector, elements_vector& res); + virtual void select_all(const css_selector& selector, elements_list& res); element::ptr _add_before_after(int type, const style& style); public: explicit element(const std::shared_ptr& doc); @@ -43,13 +43,14 @@ namespace litehtml css_properties& css_w(); bool in_normal_flow() const; - bool is_inline_box() const; + bool is_inline() const; // returns true if element is inline + bool is_inline_box() const; // returns true if element is inline box (inline-table, inline-box, inline-flex) bool is_block_box() const; position get_placement() const; bool is_positioned() const; bool is_float() const; + bool is_block_formatting_context() const; - bool have_parent() const; bool is_root() const; element::ptr parent() const; void parent(const element::ptr& par); @@ -57,9 +58,10 @@ namespace litehtml bool is_table_skip() const; std::shared_ptr get_document() const; + const std::list>& children() const; - virtual elements_vector select_all(const string& selector); - virtual elements_vector select_all(const css_selector& selector); + virtual elements_list select_all(const string& selector); + virtual elements_list select_all(const css_selector& selector); virtual element::ptr select_one(const string& selector); virtual element::ptr select_one(const css_selector& selector); @@ -73,8 +75,6 @@ namespace litehtml virtual const char* get_tagName() const; virtual void set_tagName(const char* tag); virtual void set_data(const char* data); - virtual size_t get_children_count() const; - virtual element::ptr get_child(int idx) const; virtual void set_attr(const char* name, const char* val); virtual const char* get_attr(const char* name, const char* def = nullptr) const; @@ -119,8 +119,6 @@ namespace litehtml virtual element::ptr find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr); virtual element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr); virtual void get_content_size(size& sz, int max_width); - virtual bool is_floats_holder() const; - virtual void update_floats(int dy, const ptr &parent); virtual bool is_nth_child(const element::ptr& el, int num, int off, bool of_type) const; virtual bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const; virtual bool is_only_child(const element::ptr& el, bool of_type) const; @@ -211,6 +209,11 @@ namespace litehtml } return false; } + + inline const std::list>& element::children() const + { + return m_children; + } } #endif // LH_ELEMENT_H diff --git a/include/litehtml/formatting_context.h b/include/litehtml/formatting_context.h new file mode 100644 index 000000000..eee481dc4 --- /dev/null +++ b/include/litehtml/formatting_context.h @@ -0,0 +1,54 @@ +#ifndef LITEHTML_FLOATS_HOLDER_H +#define LITEHTML_FLOATS_HOLDER_H + +#include +#include "types.h" + +namespace litehtml +{ + class formatting_context + { + private: + std::list m_floats_left; + std::list m_floats_right; + int_int_cache m_cache_line_left; + int_int_cache m_cache_line_right; + int m_current_top; + int m_current_left; + + public: + formatting_context() : m_current_top(0), m_current_left(0) {} + + void push_position(int x, int y) + { + m_current_left += x; + m_current_top += y; + } + void pop_position(int x, int y) + { + m_current_left -= x; + m_current_top -= y; + } + + void add_float(const std::shared_ptr &el, int min_width, int context); + void clear_floats(int context); + int find_next_line_top( int top, int width, int def_right ); + int get_floats_height(element_float el_float = float_none) const; + int get_left_floats_height() const; + int get_right_floats_height() const; + int get_line_left( int y ); + void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) + { + ln_left = get_line_left(y); + ln_right = get_line_right(y, def_right); + } + int get_line_right( int y, int def_right ); + int get_cleared_top(const std::shared_ptr &el, int line_top) const; + void update_floats(int dy, const std::shared_ptr &parent); + void apply_relative_shift(const containing_block_context &containing_block_size); + int find_min_left(int y, int context_idx); + int find_min_right(int y, int right, int context_idx); + }; +} + +#endif //LITEHTML_FLOATS_HOLDER_H diff --git a/include/litehtml/html_tag.h b/include/litehtml/html_tag.h index 71b9cb345..9148031b2 100644 --- a/include/litehtml/html_tag.h +++ b/include/litehtml/html_tag.h @@ -31,7 +31,7 @@ namespace litehtml string_map m_attrs; std::vector m_pseudo_classes; - void select_all(const css_selector& selector, elements_vector& res) override; + void select_all(const css_selector& selector, elements_list& res) override; public: explicit html_tag(const std::shared_ptr& doc); @@ -46,8 +46,6 @@ namespace litehtml const char* get_tagName() const override; void set_tagName(const char* tag) override; void set_data(const char* data) override; - size_t get_children_count() const override; - element::ptr get_child(int idx) const override; void set_attr(const char* name, const char* val) override; const char* get_attr(const char* name, const char* def = nullptr) const override; @@ -84,7 +82,7 @@ namespace litehtml size_vector get_size_vector_property (string_id name, bool inherited, const size_vector& default_value, uint_ptr css_properties_member_offset) const override; string get_custom_property(string_id name, const string& default_value) const override; - elements_vector& children(); + elements_list& children(); int select(const string& selector) override; int select(const css_selector& selector, bool apply_pseudo = true) override; @@ -92,8 +90,8 @@ namespace litehtml int select_pseudoclass(const css_attribute_selector& sel); int select_attribute(const css_attribute_selector& sel); - elements_vector select_all(const string& selector) override; - elements_vector select_all(const css_selector& selector) override; + elements_list select_all(const string& selector) override; + elements_list select_all(const css_selector& selector) override; element::ptr select_one(const string& selector) override; element::ptr select_one(const css_selector& selector) override; @@ -105,7 +103,6 @@ namespace litehtml void parse_attributes() override; void get_content_size(size& sz, int max_width) override; - bool is_floats_holder() const override; void add_style(const style& style) override; bool is_nth_child(const element::ptr& el, int num, int off, bool of_type) const override; @@ -128,7 +125,7 @@ namespace litehtml /* Inline Functions */ /************************************************************************/ - inline elements_vector& litehtml::html_tag::children() + inline elements_list& litehtml::html_tag::children() { return m_children; } diff --git a/include/litehtml/master_css.h b/include/litehtml/master_css.h index b5c7f3f03..c8b7f3352 100644 --- a/include/litehtml/master_css.h +++ b/include/litehtml/master_css.h @@ -224,6 +224,19 @@ table[border|=0] td, table[border|=0] th { border-style:none; } +table[align=left] { + float: left; +} + +table[align=right] { + float: right; +} + +table[align=center] { + margin-left: auto; + margin-right: auto; +} + caption { display: table-caption; } diff --git a/include/litehtml/render_item.h b/include/litehtml/render_item.h index f3575778f..db2cf1255 100644 --- a/include/litehtml/render_item.h +++ b/include/litehtml/render_item.h @@ -8,6 +8,7 @@ #include "types.h" #include "line_box.h" #include "table.h" +#include "formatting_context.h" namespace litehtml { @@ -28,6 +29,10 @@ namespace litehtml containing_block_context calculate_containing_block_context(const containing_block_context& cb_context); void calc_cb_length(const css_length& len, int percent_base, containing_block_context::typed_int& out_value) const; + virtual int _render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false) + { + return 0; + } public: explicit render_item(std::shared_ptr src_el); @@ -268,10 +273,7 @@ namespace litehtml ri->parent(shared_from_this()); } - virtual int render(int x, int y, const containing_block_context& containing_block_size, bool second_pass = false) - { - return 0; - } + int render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false); bool is_root() const { @@ -345,27 +347,11 @@ namespace litehtml * @return */ void get_rendering_boxes( position::vector& redraw_boxes); - - virtual void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) {} - virtual int get_line_left( int y ) { return 0; } - virtual int get_line_right( int y, int def_right ) { return 0; } - virtual int get_left_floats_height() const { return 0; } - virtual int get_right_floats_height() const { return 0; } - virtual int get_floats_height(element_float el_float = float_none) const { return 0; } - virtual int find_next_line_top( int top, int width, int def_right ) { return 0; } - virtual void add_float(const std::shared_ptr &el, int x, int y, int context) {} - virtual void clear_floats(int context) {} - virtual void update_floats(int dy, const std::shared_ptr &_parent) {} }; class render_item_block : public render_item { protected: - std::list m_floats_left; - std::list m_floats_right; - int_int_cache m_cache_line_left; - int_int_cache m_cache_line_right; - /** * Render block content. * @@ -376,24 +362,13 @@ namespace litehtml * @param self_size - defines calculated size of block * @return return value is the minimal width of the content in block. Must be greater or equal to ret_width parameter */ - virtual int _render_content(int x, int y, bool second_pass, int ret_width, const containing_block_context &self_size) {return ret_width;} - int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override; - - int place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size); - int get_floats_height(element_float el_float = float_none) const override; - int get_left_floats_height() const override; - int get_right_floats_height() const override; - int get_line_left( int y ) override; - int get_line_right( int y, int def_right ) override; - void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) override; - void add_float(const std::shared_ptr &el, int x, int y, int context) override; - void clear_floats(int context) override; - int get_cleared_top(const std::shared_ptr &el, int line_top) const; - int find_next_line_top( int top, int width, int def_right ) override; - virtual void fix_line_width(element_float flt, - const containing_block_context &containing_block_size) + virtual int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) {return 0;} + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + int place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx); + virtual void fix_line_width(element_float flt, + const containing_block_context &containing_block_size, formatting_context* fmt_ctx) {} - void update_floats(int dy, const std::shared_ptr &_parent) override; + public: explicit render_item_block(std::shared_ptr src_el) : render_item(std::move(src_el)) {} @@ -413,8 +388,7 @@ namespace litehtml class render_item_block_context : public render_item_block { protected: - int _render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) override; + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; public: explicit render_item_block_context(std::shared_ptr src_el) : render_item_block(std::move(src_el)) @@ -452,14 +426,13 @@ namespace litehtml std::vector > m_line_boxes; int m_max_line_width; - int _render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) override; + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; void fix_line_width(element_float flt, - const containing_block_context &self_size) override; + const containing_block_context &self_size, formatting_context* fmt_ctx) override; std::list > finish_last_box(bool end_of_render, const containing_block_context &self_size); - void place_inline(std::unique_ptr item, const containing_block_context &self_size); - int new_box(const std::unique_ptr& el, line_context& line_ctx, const containing_block_context &self_size); + void place_inline(std::unique_ptr item, const containing_block_context &self_size, formatting_context* fmt_ctx); + int new_box(const std::unique_ptr& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx); void apply_vertical_align() override; public: explicit render_item_inline_context(std::shared_ptr src_el) : render_item_block(std::move(src_el)), m_max_line_width(0) @@ -481,6 +454,8 @@ namespace litehtml int m_border_spacing_x; int m_border_spacing_y; + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + public: explicit render_item_table(std::shared_ptr src_el); @@ -488,7 +463,6 @@ namespace litehtml { return std::make_shared(src_el()); } - int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override; void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override; int get_draw_vertical_offset() override; std::shared_ptr init() override; @@ -544,12 +518,12 @@ namespace litehtml { protected: int calc_max_height(int image_height, int containing_block_height); + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; public: explicit render_item_image(std::shared_ptr src_el) : render_item(std::move(src_el)) {} - int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override; std::shared_ptr clone() override { return std::make_shared(src_el()); @@ -579,8 +553,7 @@ namespace litehtml protected: std::list> m_flex_items; - int _render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) override; + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; public: explicit render_item_flex(std::shared_ptr src_el) : render_item_block(std::move(src_el)) diff --git a/include/litehtml/types.h b/include/litehtml/types.h index 7946a3f08..20cb3d471 100644 --- a/include/litehtml/types.h +++ b/include/litehtml/types.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace litehtml { @@ -12,7 +13,7 @@ namespace litehtml class element; typedef std::map string_map; - typedef std::vector< std::shared_ptr > elements_vector; + typedef std::list< std::shared_ptr > elements_list; typedef std::vector int_vector; typedef std::vector string_vector; @@ -598,6 +599,7 @@ namespace litehtml element_clear clear_floats; std::shared_ptr el; int context; + int min_width; floated_box() = default; floated_box(const floated_box& val) @@ -607,6 +609,7 @@ namespace litehtml clear_floats = val.clear_floats; el = val.el; context = val.context; + min_width = val.min_width; } floated_box& operator=(const floated_box& val) { @@ -615,6 +618,7 @@ namespace litehtml clear_floats = val.clear_floats; el = val.el; context = val.context; + min_width = val.min_width; return *this; } floated_box(floated_box&& val) @@ -624,6 +628,7 @@ namespace litehtml clear_floats = val.clear_floats; el = std::move(val.el); context = val.context; + min_width = val.min_width; } void operator=(floated_box&& val) { @@ -632,6 +637,7 @@ namespace litehtml clear_floats = val.clear_floats; el = std::move(val.el); context = val.context; + min_width = val.min_width; } }; diff --git a/src/document.cpp b/src/document.cpp index 8623bff41..4ba36b4ea 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -54,7 +54,7 @@ litehtml::document::ptr litehtml::document::createFromString( const char* str, d document::ptr doc = std::make_shared(objPainter); // Create litehtml::elements. - elements_vector root_elements; + elements_list root_elements; doc->create_node(output->root, root_elements, true); if (!root_elements.empty()) { @@ -304,7 +304,7 @@ int litehtml::document::render( int max_width, render_type rt ) m_root_render->render_positioned(rt); } else { - ret = m_root_render->render(0, 0, cb_context); + ret = m_root_render->render(0, 0, cb_context, nullptr); if(m_root_render->fetch_positioned()) { m_fixed_boxes.clear(); @@ -718,7 +718,7 @@ void litehtml::document::add_media_list( const media_query_list::ptr& list ) } } -void litehtml::document::create_node(void* gnode, elements_vector& elements, bool parseTextNode) +void litehtml::document::create_node(void* gnode, elements_list& elements, bool parseTextNode) { auto* node = (GumboNode*)gnode; switch (node->type) @@ -756,7 +756,7 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo } if (ret) { - elements_vector child; + elements_list child; for (unsigned int i = 0; i < node->v.element.children.length; i++) { child.clear(); @@ -1018,7 +1018,7 @@ void litehtml::document::append_children_from_string(element& parent, const char GumboOutput* output = gumbo_parse(str); // Create litehtml::elements. - elements_vector child_elements; + elements_list child_elements; create_node(output->root, child_elements, true); // Destroy GumboOutput diff --git a/src/el_before_after.cpp b/src/el_before_after.cpp index 4455642e8..8c24eec98 100644 --- a/src/el_before_after.cpp +++ b/src/el_before_after.cpp @@ -109,7 +109,7 @@ void litehtml::el_before_after_base::add_text( const string& txt ) word.clear(); } word += chr; - element::ptr el = std::make_shared(word.c_str(), get_document()); + element::ptr el = std::make_shared(word.c_str(), get_document()); appendChild(el); word.clear(); } else @@ -197,8 +197,3 @@ litehtml::string litehtml::el_before_after_base::convert_escape( const char* txt u_str[1] = 0; return litehtml::string(litehtml_from_wchar(u_str)); } - -void litehtml::el_before_after_base::apply_stylesheet( const litehtml::css& stylesheet ) -{ - -} diff --git a/src/el_table.cpp b/src/el_table.cpp index d0c711c4d..0bb864843 100644 --- a/src/el_table.cpp +++ b/src/el_table.cpp @@ -30,23 +30,6 @@ void litehtml::el_table::parse_attributes() m_style.add_property(_width_, str); } - str = get_attr("align"); - if(str) - { - int align = value_index(str, "left;center;right"); - switch(align) - { - case 1: - m_style.add_property(_margin_left_, "auto"); - m_style.add_property(_margin_right_, "auto"); - break; - case 2: - m_style.add_property(_margin_left_, "auto"); - m_style.add_property(_margin_right_, "0"); - break; - } - } - str = get_attr("cellspacing"); if(str) { diff --git a/src/element.cpp b/src/element.cpp index 2438b1325..234e95975 100644 --- a/src/element.cpp +++ b/src/element.cpp @@ -44,7 +44,7 @@ position element::get_placement() const return pos; } -bool element::is_inline_box() const +bool element::is_inline() const { if( css().get_display() == display_inline || css().get_display() == display_inline_table || @@ -57,6 +57,17 @@ bool element::is_inline_box() const return false; } +bool element::is_inline_box() const +{ + if( css().get_display() == display_inline_table || + css().get_display() == display_inline_block || + css().get_display() == display_inline_flex) + { + return true; + } + return false; +} + bool element::is_ancestor(const ptr &el) const { element::ptr el_parent = parent(); @@ -244,30 +255,41 @@ bool element::find_styles_changes( position::vector& redraw_boxes) element::ptr element::_add_before_after(int type, const style& style) { - if(style.get_property(_content_).m_type != prop_type_invalid) + element::ptr el; + if(type == 0) { - element::ptr el; - if(type == 0) - { - el = std::make_shared(get_document()); - m_children.insert(m_children.begin(), el); - } else - { - el = std::make_shared(get_document()); - m_children.insert(m_children.end(), el); - } - el->parent(shared_from_this()); - return el; + el = std::make_shared(get_document()); + m_children.insert(m_children.begin(), el); + } else + { + el = std::make_shared(get_document()); + m_children.insert(m_children.end(), el); } - return nullptr; + el->parent(shared_from_this()); + return el; } +bool element::is_block_formatting_context() const +{ + if( m_css.get_display() == display_inline_block || + m_css.get_display() == display_table_cell || + m_css.get_display() == display_table_caption || + is_root() || + m_css.get_float() != float_none || + m_css.get_position() == element_position_absolute || + m_css.get_position() == element_position_fixed || + m_css.get_overflow() > overflow_visible) + { + return true; + } + return false; +} const background* element::get_background(bool own_only) LITEHTML_RETURN_FUNC(nullptr) void element::add_style( const style& style) LITEHTML_EMPTY_FUNC -void element::select_all(const css_selector& selector, elements_vector& res) LITEHTML_EMPTY_FUNC -elements_vector element::select_all(const css_selector& selector) LITEHTML_RETURN_FUNC(elements_vector()) -elements_vector element::select_all(const string& selector) LITEHTML_RETURN_FUNC(elements_vector()) +void element::select_all(const css_selector& selector, elements_list& res) LITEHTML_EMPTY_FUNC +elements_list element::select_all(const css_selector& selector) LITEHTML_RETURN_FUNC(elements_list()) +elements_list element::select_all(const string& selector) LITEHTML_RETURN_FUNC(elements_list()) element::ptr element::select_one( const css_selector& selector ) LITEHTML_RETURN_FUNC(nullptr) element::ptr element::select_one( const string& selector ) LITEHTML_RETURN_FUNC(nullptr) element::ptr element::find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/) LITEHTML_RETURN_FUNC(nullptr) @@ -275,10 +297,6 @@ element::ptr element::find_sibling(const element::ptr& el, const css_selector& s bool element::is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const LITEHTML_RETURN_FUNC(false) bool element::is_nth_child(const element::ptr&, int num, int off, bool of_type) const LITEHTML_RETURN_FUNC(false) bool element::is_only_child(const element::ptr& el, bool of_type) const LITEHTML_RETURN_FUNC(false) -element::ptr element::get_child( int idx ) const LITEHTML_RETURN_FUNC(nullptr) -size_t element::get_children_count() const LITEHTML_RETURN_FUNC(0) -void element::update_floats(int dy, const ptr &parent) LITEHTML_EMPTY_FUNC -bool element::is_floats_holder() const LITEHTML_RETURN_FUNC(false) void element::get_content_size( size& sz, int max_width ) LITEHTML_EMPTY_FUNC bool element::appendChild(const ptr &el) LITEHTML_RETURN_FUNC(false) bool element::removeChild(const ptr &el) LITEHTML_RETURN_FUNC(false) diff --git a/src/formatting_context.cpp b/src/formatting_context.cpp new file mode 100644 index 000000000..4e41c7b5f --- /dev/null +++ b/src/formatting_context.cpp @@ -0,0 +1,441 @@ +#include "html.h" +#include "render_item.h" +#include "formatting_context.h" + +void litehtml::formatting_context::add_float(const std::shared_ptr &el, int min_width, int context) +{ + floated_box fb; + fb.pos.x = el->left() + m_current_left; + fb.pos.y = el->top() + m_current_top; + fb.pos.width = el->width(); + fb.pos.height = el->height(); + fb.float_side = el->src_el()->css().get_float(); + fb.clear_floats = el->src_el()->css().get_clear(); + fb.el = el; + fb.context = context; + fb.min_width = min_width; + + if(fb.float_side == float_left) + { + if(m_floats_left.empty()) + { + m_floats_left.push_back(fb); + } else + { + bool inserted = false; + for(auto i = m_floats_left.begin(); i != m_floats_left.end(); i++) + { + if(fb.pos.right() > i->pos.right()) + { + m_floats_left.insert(i, std::move(fb)); + inserted = true; + break; + } + } + if(!inserted) + { + m_floats_left.push_back(std::move(fb)); + } + } + m_cache_line_left.invalidate(); + } else if(fb.float_side == float_right) + { + if(m_floats_right.empty()) + { + m_floats_right.push_back(std::move(fb)); + } else + { + bool inserted = false; + for(auto i = m_floats_right.begin(); i != m_floats_right.end(); i++) + { + if(fb.pos.left() < i->pos.left()) + { + m_floats_right.insert(i, std::move(fb)); + inserted = true; + break; + } + } + if(!inserted) + { + m_floats_right.push_back(fb); + } + } + m_cache_line_right.invalidate(); + } +} + +int litehtml::formatting_context::get_floats_height(element_float el_float) const +{ + int h = 0; + + for(const auto& fb : m_floats_left) + { + bool process = false; + switch(el_float) + { + case float_none: + process = true; + break; + case float_left: + if (fb.clear_floats == clear_left || fb.clear_floats == clear_both) + { + process = true; + } + break; + case float_right: + if (fb.clear_floats == clear_right || fb.clear_floats == clear_both) + { + process = true; + } + break; + } + if(process) + { + if(el_float == float_none) + { + h = std::max(h, fb.pos.bottom()); + } else + { + h = std::max(h, fb.pos.top()); + } + } + } + + + for(const auto& fb : m_floats_right) + { + int process = false; + switch(el_float) + { + case float_none: + process = true; + break; + case float_left: + if (fb.clear_floats == clear_left || fb.clear_floats == clear_both) + { + process = true; + } + break; + case float_right: + if (fb.clear_floats == clear_right || fb.clear_floats == clear_both) + { + process = true; + } + break; + } + if(process) + { + if(el_float == float_none) + { + h = std::max(h, fb.pos.bottom()); + } else + { + h = std::max(h, fb.pos.top()); + } + } + } + + return h - m_current_top; +} + +int litehtml::formatting_context::get_left_floats_height() const +{ + int h = 0; + if(!m_floats_left.empty()) + { + for (const auto& fb : m_floats_left) + { + h = std::max(h, fb.pos.bottom()); + } + } + return h - m_current_top; +} + +int litehtml::formatting_context::get_right_floats_height() const +{ + int h = 0; + if(!m_floats_right.empty()) + { + for(const auto& fb : m_floats_right) + { + h = std::max(h, fb.pos.bottom()); + } + } + return h - m_current_top; +} + +int litehtml::formatting_context::get_line_left(int y ) +{ + y += m_current_top; + + if(m_cache_line_left.is_valid && m_cache_line_left.hash == y) + { + if(m_cache_line_left.val - m_current_left < 0) + { + return 0; + } + return m_cache_line_left.val - m_current_left; + } + + int w = 0; + for(const auto& fb : m_floats_left) + { + if (y >= fb.pos.top() && y < fb.pos.bottom()) + { + w = std::max(w, fb.pos.right()); + if (w < fb.pos.right()) + { + break; + } + } + } + m_cache_line_left.set_value(y, w); + w -= m_current_left; + if(w < 0) return 0; + return w; +} + +int litehtml::formatting_context::get_line_right(int y, int def_right ) +{ + y += m_current_top; + def_right += m_current_left; + if(m_cache_line_right.is_valid && m_cache_line_right.hash == y) + { + if(m_cache_line_right.is_default) + { + return def_right - m_current_left; + } else + { + int w = std::min(m_cache_line_right.val, def_right) - m_current_left; + if(w < 0) return 0; + return w; + } + } + + int w = def_right; + m_cache_line_right.is_default = true; + for(const auto& fb : m_floats_right) + { + if(y >= fb.pos.top() && y < fb.pos.bottom()) + { + w = std::min(w, fb.pos.left()); + m_cache_line_right.is_default = false; + if(w > fb.pos.left()) + { + break; + } + } + } + m_cache_line_right.set_value(y, w); + w -= m_current_left; + if(w < 0) return 0; + return w; +} + + +void litehtml::formatting_context::clear_floats(int context) +{ + auto iter = m_floats_left.begin(); + while(iter != m_floats_left.end()) + { + if(iter->context >= context) + { + iter = m_floats_left.erase(iter); + m_cache_line_left.invalidate(); + } else + { + iter++; + } + } + + iter = m_floats_right.begin(); + while(iter != m_floats_right.end()) + { + if(iter->context >= context) + { + iter = m_floats_right.erase(iter); + m_cache_line_right.invalidate(); + } else + { + iter++; + } + } +} + +int litehtml::formatting_context::get_cleared_top(const std::shared_ptr &el, int line_top) const +{ + switch(el->src_el()->css().get_clear()) + { + case clear_left: + { + int fh = get_left_floats_height(); + if(fh && fh > line_top) + { + line_top = fh; + } + } + break; + case clear_right: + { + int fh = get_right_floats_height(); + if(fh && fh > line_top) + { + line_top = fh; + } + } + break; + case clear_both: + { + int fh = get_floats_height(float_none); + if(fh && fh > line_top) + { + line_top = fh; + } + } + break; + default: + if(el->src_el()->css().get_float() != float_none) + { + int fh = get_floats_height(el->src_el()->css().get_float()); + if(fh && fh > line_top) + { + line_top = fh; + } + } + break; + } + return line_top; +} + +int litehtml::formatting_context::find_next_line_top(int top, int width, int def_right ) +{ + top += m_current_top; + def_right += m_current_left; + + int new_top = top; + int_vector points; + + for(const auto& fb : m_floats_left) + { + if(fb.pos.top() >= top) + { + if(find(points.begin(), points.end(), fb.pos.top()) == points.end()) + { + points.push_back(fb.pos.top()); + } + } + if (fb.pos.bottom() >= top) + { + if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end()) + { + points.push_back(fb.pos.bottom()); + } + } + } + + for (const auto& fb : m_floats_right) + { + if (fb.pos.top() >= top) + { + if (find(points.begin(), points.end(), fb.pos.top()) == points.end()) + { + points.push_back(fb.pos.top()); + } + } + if (fb.pos.bottom() >= top) + { + if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end()) + { + points.push_back(fb.pos.bottom()); + } + } + } + + if(!points.empty()) + { + sort(points.begin(), points.end(), std::less( )); + new_top = points.back(); + + for(auto pt : points) + { + int pos_left = 0; + int pos_right = def_right; + get_line_left_right(pt - m_current_top, def_right - m_current_left, pos_left, pos_right); + + if(pos_right - pos_left >= width) + { + new_top = pt; + break; + } + } + } + return new_top - m_current_top; +} + +void litehtml::formatting_context::update_floats(int dy, const std::shared_ptr &parent) +{ + bool reset_cache = false; + for(auto fb = m_floats_left.rbegin(); fb != m_floats_left.rend(); fb++) + { + if(fb->el->src_el()->is_ancestor(parent->src_el())) + { + reset_cache = true; + fb->pos.y += dy; + } + } + if(reset_cache) + { + m_cache_line_left.invalidate(); + } + reset_cache = false; + for(auto fb = m_floats_right.rbegin(); fb != m_floats_right.rend(); fb++) + { + if(fb->el->src_el()->is_ancestor(parent->src_el())) + { + reset_cache = true; + fb->pos.y += dy; + } + } + if(reset_cache) + { + m_cache_line_right.invalidate(); + } +} + +void litehtml::formatting_context::apply_relative_shift(const containing_block_context &containing_block_size) +{ + for (const auto& fb : m_floats_left) + { + fb.el->apply_relative_shift(containing_block_size); + } +} + +int litehtml::formatting_context::find_min_left(int y, int context_idx) +{ + y += m_current_top; + int min_left = m_current_left; + for(const auto& fb : m_floats_left) + { + if (y >= fb.pos.top() && y < fb.pos.bottom() && fb.context == context_idx) + { + min_left += fb.min_width; + } + } + if(min_left < m_current_left) return 0; + return min_left - m_current_left; +} + +int litehtml::formatting_context::find_min_right(int y, int right, int context_idx) +{ + y += m_current_top; + int min_right = right + m_current_left; + for(const auto& fb : m_floats_right) + { + if (y >= fb.pos.top() && y < fb.pos.bottom() && fb.context == context_idx) + { + min_right -= fb.min_width; + } + } + if(min_right < m_current_left) return 0; + return min_right - m_current_left; +} diff --git a/src/html_tag.cpp b/src/html_tag.cpp index d1e7302e4..1015a4ee0 100644 --- a/src/html_tag.cpp +++ b/src/html_tag.cpp @@ -121,7 +121,7 @@ const char* litehtml::html_tag::get_attr( const char* name, const char* def ) co return def; } -litehtml::elements_vector litehtml::html_tag::select_all( const string& selector ) +litehtml::elements_list litehtml::html_tag::select_all(const string& selector ) { css_selector sel; sel.parse(selector); @@ -129,14 +129,14 @@ litehtml::elements_vector litehtml::html_tag::select_all( const string& selector return select_all(sel); } -litehtml::elements_vector litehtml::html_tag::select_all( const css_selector& selector ) +litehtml::elements_list litehtml::html_tag::select_all(const css_selector& selector ) { - litehtml::elements_vector res; + litehtml::elements_list res; select_all(selector, res); return res; } -void litehtml::html_tag::select_all(const css_selector& selector, elements_vector& res) +void litehtml::html_tag::select_all(const css_selector& selector, elements_list& res) { if(select(selector)) { @@ -203,45 +203,62 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet ) if(sel->is_media_valid()) { - if(apply & select_match_pseudo_class) - { - if(select(*sel, true)) + auto apply_before_after = [&]() { + const auto& content_property = sel->m_style->get_property(_content_); + bool content_none = content_property.m_type == prop_type_string && content_property.m_string == "none"; + bool create = !content_none && (sel->m_right.m_attrs.size() > 1 || sel->m_right.m_tag != star_id); + + element::ptr el; if(apply & select_match_with_after) { - element::ptr el = get_element_after(*sel->m_style, true); - if(el) + el = get_element_after(*sel->m_style, create); + } else if(apply & select_match_with_before) + { + el = get_element_before(*sel->m_style, create); + } else + { + return; + } + if(el) + { + if(!content_none) { el->add_style(*sel->m_style); + } else + { + el->parent()->removeChild(el); } - } else if(apply & select_match_with_before) + } else { - element::ptr el = get_element_before(*sel->m_style, true); - if(el) + if(!content_none) { - el->add_style(*sel->m_style); + add_style(*sel->m_style); + } else + { + parent()->removeChild(shared_from_this()); } } - else + us->m_used = true; + }; + + + if(apply & select_match_pseudo_class) + { + if(select(*sel, true)) + { + if((apply & (select_match_with_after | select_match_with_before))) + { + apply_before_after(); + } else { add_style(*sel->m_style); us->m_used = true; } } - } else if(apply & select_match_with_after) + } else if((apply & (select_match_with_after | select_match_with_before))) { - element::ptr el = get_element_after(*sel->m_style, true); - if(el) - { - el->add_style(*sel->m_style); - } - } else if(apply & select_match_with_before) - { - element::ptr el = get_element_before(*sel->m_style, true); - if(el) - { - el->add_style(*sel->m_style); - } + apply_before_after(); } else { add_style(*sel->m_style); @@ -537,9 +554,17 @@ int litehtml::html_tag::select(const css_element_selector& selector, bool apply_ case select_pseudo_element: if(attr.name == _after_) { + if(selector.m_attrs.size() == 1 && selector.m_tag == star_id && m_tag != __tag_after_) + { + return select_no_match; + } res |= select_match_with_after; } else if(attr.name == _before_) { + if(selector.m_attrs.size() == 1 && selector.m_tag == star_id && m_tag != __tag_before_) + { + return select_no_match; + } res |= select_match_with_before; } else { @@ -1063,32 +1088,6 @@ bool litehtml::html_tag::is_replaced() const return false; } -bool litehtml::html_tag::is_floats_holder() const -{ - if( m_css.get_display() == display_inline_block || - m_css.get_display() == display_table_cell || - is_root() || - m_css.get_float() != float_none || - m_css.get_position() == element_position_absolute || - m_css.get_position() == element_position_fixed || - m_css.get_overflow() > overflow_visible) - { - return true; - } - return false; -} - -size_t litehtml::html_tag::get_children_count() const -{ - return m_children.size(); -} - -litehtml::element::ptr litehtml::html_tag::get_child( int idx ) const -{ - return m_children[idx]; -} - - void litehtml::html_tag::init_background_paint(position pos, std::vector& bg_paint, const background* bg, const std::shared_ptr& ri) { bg_paint = { background_paint() }; diff --git a/src/line_box.cpp b/src/line_box.cpp index 269dd4672..1ca9c85d7 100644 --- a/src/line_box.cpp +++ b/src/line_box.cpp @@ -551,7 +551,7 @@ std::shared_ptr litehtml::line_box::get_last_text_part() bool litehtml::line_box::can_hold(const std::unique_ptr& item, white_space ws) const { - if(!item->get_el()->src_el()->is_inline_box()) return false; + if(!item->get_el()->src_el()->is_inline()) return false; if(item->get_type() == line_box_item::type_text_part) { diff --git a/src/render_block.cpp b/src/render_block.cpp index 8e1d107b4..a9568d11e 100644 --- a/src/render_block.cpp +++ b/src/render_block.cpp @@ -2,556 +2,52 @@ #include "render_item.h" #include "document.h" -int litehtml::render_item_block::place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size) +int litehtml::render_item_block::place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx) { - int line_top = get_cleared_top(el, top); + int line_top = fmt_ctx->get_cleared_top(el, top); int line_left = 0; int line_right = self_size.render_width; - get_line_left_right(line_top, self_size.render_width, line_left, line_right); + fmt_ctx->get_line_left_right(line_top, self_size.render_width, line_left, line_right); int ret_width = 0; + int min_rendered_width = el->render(line_left, line_top, self_size.new_width(line_right), fmt_ctx); + if(min_rendered_width < el->width() && el->src_el()->css().get_width().is_predefined()) + { + el->render(line_left, line_top, self_size.new_width(min_rendered_width), fmt_ctx); + } + if (el->src_el()->css().get_float() == float_left) { - el->render(line_left, line_top, self_size.new_width(line_right)); if(el->right() > line_right) { - int new_top = find_next_line_top(el->top(), el->width(), self_size.render_width); - el->pos().x = get_line_left(new_top) + el->content_offset_left(); - el->pos().y = new_top + el->content_offset_top(); + line_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width); + el->pos().x = fmt_ctx->get_line_left(line_top) + el->content_offset_left(); + el->pos().y = line_top + el->content_offset_top(); } - add_float(el, 0, 0, self_size.context_idx); - fix_line_width(float_left, self_size); - ret_width = el->right(); + fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx); + fix_line_width(float_left, self_size, fmt_ctx); + + ret_width = fmt_ctx->find_min_left(line_top, self_size.context_idx); } else if (el->src_el()->css().get_float() == float_right) { - el->render(0, line_top, self_size.new_width(line_right)); - if(line_left + el->width() > line_right) { - int new_top = find_next_line_top(el->top(), el->width(), self_size.render_width); - el->pos().x = get_line_right(new_top, self_size.render_width) - el->width() + el->content_offset_left(); + int new_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width); + el->pos().x = fmt_ctx->get_line_right(new_top, self_size.render_width) - el->width() + el->content_offset_left(); el->pos().y = new_top + el->content_offset_top(); } else { el->pos().x = line_right - el->width() + el->content_offset_left(); } - add_float(el, 0, 0, self_size.context_idx); - fix_line_width(float_right, self_size); - line_left = 0; - line_right = self_size.render_width; - get_line_left_right(line_top, self_size.render_width, line_left, line_right); - - ret_width = ret_width + (self_size.render_width - line_right); + fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx); + fix_line_width(float_right, self_size, fmt_ctx); + line_right = fmt_ctx->find_min_right(line_top, self_size.render_width, self_size.context_idx); + ret_width = self_size.render_width - line_right; } return ret_width; } -int litehtml::render_item_block::get_floats_height(element_float el_float) const -{ - if(src_el()->is_floats_holder()) - { - int h = 0; - - for(const auto& fb : m_floats_left) - { - bool process = false; - switch(el_float) - { - case float_none: - process = true; - break; - case float_left: - if (fb.clear_floats == clear_left || fb.clear_floats == clear_both) - { - process = true; - } - break; - case float_right: - if (fb.clear_floats == clear_right || fb.clear_floats == clear_both) - { - process = true; - } - break; - } - if(process) - { - if(el_float == float_none) - { - h = std::max(h, fb.pos.bottom()); - } else - { - h = std::max(h, fb.pos.top()); - } - } - } - - - for(const auto& fb : m_floats_right) - { - int process = false; - switch(el_float) - { - case float_none: - process = true; - break; - case float_left: - if (fb.clear_floats == clear_left || fb.clear_floats == clear_both) - { - process = true; - } - break; - case float_right: - if (fb.clear_floats == clear_right || fb.clear_floats == clear_both) - { - process = true; - } - break; - } - if(process) - { - if(el_float == float_none) - { - h = std::max(h, fb.pos.bottom()); - } else - { - h = std::max(h, fb.pos.top()); - } - } - } - - return h; - } - auto el_parent = parent(); - if (el_parent) - { - int h = el_parent->get_floats_height(el_float); - return h - m_pos.y; - } - return 0; -} - -int litehtml::render_item_block::get_left_floats_height() const -{ - if(src_el()->is_floats_holder()) - { - int h = 0; - if(!m_floats_left.empty()) - { - for (const auto& fb : m_floats_left) - { - h = std::max(h, fb.pos.bottom()); - } - } - return h; - } - auto el_parent = parent(); - if (el_parent) - { - int h = el_parent->get_left_floats_height(); - return h - m_pos.y; - } - return 0; -} - -int litehtml::render_item_block::get_right_floats_height() const -{ - if(src_el()->is_floats_holder()) - { - int h = 0; - if(!m_floats_right.empty()) - { - for(const auto& fb : m_floats_right) - { - h = std::max(h, fb.pos.bottom()); - } - } - return h; - } - auto el_parent = parent(); - if (el_parent) - { - int h = el_parent->get_right_floats_height(); - return h - m_pos.y; - } - return 0; -} - -int litehtml::render_item_block::get_line_left( int y ) -{ - if(src_el()->is_floats_holder()) - { - if(m_cache_line_left.is_valid && m_cache_line_left.hash == y) - { - return m_cache_line_left.val; - } - - int w = 0; - for(const auto& fb : m_floats_left) - { - if (y >= fb.pos.top() && y < fb.pos.bottom()) - { - w = std::max(w, fb.pos.right()); - if (w < fb.pos.right()) - { - break; - } - } - } - m_cache_line_left.set_value(y, w); - return w; - } - auto el_parent = parent(); - if (el_parent) - { - int w = el_parent->get_line_left(y + m_pos.y); - if (w < 0) - { - w = 0; - } - return w - (w ? m_pos.x : 0); - } - return 0; -} - -int litehtml::render_item_block::get_line_right( int y, int def_right ) -{ - if(src_el()->is_floats_holder()) - { - if(m_cache_line_right.is_valid && m_cache_line_right.hash == y) - { - if(m_cache_line_right.is_default) - { - return def_right; - } else - { - return std::min(m_cache_line_right.val, def_right); - } - } - - int w = def_right; - m_cache_line_right.is_default = true; - for(const auto& fb : m_floats_right) - { - if(y >= fb.pos.top() && y < fb.pos.bottom()) - { - w = std::min(w, fb.pos.left()); - m_cache_line_right.is_default = false; - if(w > fb.pos.left()) - { - break; - } - } - } - m_cache_line_right.set_value(y, w); - return w; - } - auto el_parent = parent(); - if (el_parent) - { - int w = el_parent->get_line_right(y + m_pos.y, def_right + m_pos.x); - return w - m_pos.x; - } - return 0; -} - - -void litehtml::render_item_block::get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) -{ - if(src_el()->is_floats_holder()) - { - ln_left = get_line_left(y); - ln_right = get_line_right(y, def_right); - } else - { - auto el_parent = parent(); - if (el_parent) - { - el_parent->get_line_left_right(y + m_pos.y, def_right + m_pos.x, ln_left, ln_right); - } - ln_right -= m_pos.x; - - if(ln_left < 0) - { - ln_left = 0; - } else if (ln_left > 0) - { - ln_left -= m_pos.x; - if (ln_left < 0) - { - ln_left = 0; - } - } - } -} - -void litehtml::render_item_block::clear_floats(int context) -{ - if(src_el()->is_floats_holder()) - { - auto iter = m_floats_left.begin(); - while(iter != m_floats_left.end()) - { - if(iter->context >= context) - { - iter = m_floats_left.erase(iter); - m_cache_line_left.invalidate(); - } else - { - iter++; - } - } - - iter = m_floats_right.begin(); - while(iter != m_floats_right.end()) - { - if(iter->context >= context) - { - iter = m_floats_right.erase(iter); - m_cache_line_right.invalidate(); - } else - { - iter++; - } - } - } else - { - auto el_parent = parent(); - if (el_parent) - { - el_parent->clear_floats(context); - } - } -} - -void litehtml::render_item_block::add_float(const std::shared_ptr &el, int x, int y, int context) -{ - if(src_el()->is_floats_holder()) - { - floated_box fb; - fb.pos.x = el->left() + x; - fb.pos.y = el->top() + y; - fb.pos.width = el->width(); - fb.pos.height = el->height(); - fb.float_side = el->src_el()->css().get_float(); - fb.clear_floats = el->src_el()->css().get_clear(); - fb.el = el; - fb.context = context; - - if(fb.float_side == float_left) - { - if(m_floats_left.empty()) - { - m_floats_left.push_back(fb); - } else - { - bool inserted = false; - for(auto i = m_floats_left.begin(); i != m_floats_left.end(); i++) - { - if(fb.pos.right() > i->pos.right()) - { - m_floats_left.insert(i, std::move(fb)); - inserted = true; - break; - } - } - if(!inserted) - { - m_floats_left.push_back(std::move(fb)); - } - } - m_cache_line_left.invalidate(); - } else if(fb.float_side == float_right) - { - if(m_floats_right.empty()) - { - m_floats_right.push_back(std::move(fb)); - } else - { - bool inserted = false; - for(auto i = m_floats_right.begin(); i != m_floats_right.end(); i++) - { - if(fb.pos.left() < i->pos.left()) - { - m_floats_right.insert(i, std::move(fb)); - inserted = true; - break; - } - } - if(!inserted) - { - m_floats_right.push_back(fb); - } - } - m_cache_line_right.invalidate(); - } - } else - { - auto el_parent = parent(); - if (el_parent) - { - el_parent->add_float(el, x + m_pos.x, y + m_pos.y, context); - } - } -} - -int litehtml::render_item_block::get_cleared_top(const std::shared_ptr &el, int line_top) const -{ - switch(el->src_el()->css().get_clear()) - { - case clear_left: - { - int fh = get_left_floats_height(); - if(fh && fh > line_top) - { - line_top = fh; - } - } - break; - case clear_right: - { - int fh = get_right_floats_height(); - if(fh && fh > line_top) - { - line_top = fh; - } - } - break; - case clear_both: - { - int fh = get_floats_height(float_none); - if(fh && fh > line_top) - { - line_top = fh; - } - } - break; - default: - if(el->src_el()->css().get_float() != float_none) - { - int fh = get_floats_height(el->src_el()->css().get_float()); - if(fh && fh > line_top) - { - line_top = fh; - } - } - break; - } - return line_top; -} - -int litehtml::render_item_block::find_next_line_top( int top, int width, int def_right ) -{ - if(src_el()->is_floats_holder()) - { - int new_top = top; - int_vector points; - - for(const auto& fb : m_floats_left) - { - if(fb.pos.top() >= top) - { - if(find(points.begin(), points.end(), fb.pos.top()) == points.end()) - { - points.push_back(fb.pos.top()); - } - } - if (fb.pos.bottom() >= top) - { - if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end()) - { - points.push_back(fb.pos.bottom()); - } - } - } - - for (const auto& fb : m_floats_right) - { - if (fb.pos.top() >= top) - { - if (find(points.begin(), points.end(), fb.pos.top()) == points.end()) - { - points.push_back(fb.pos.top()); - } - } - if (fb.pos.bottom() >= top) - { - if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end()) - { - points.push_back(fb.pos.bottom()); - } - } - } - - if(!points.empty()) - { - sort(points.begin(), points.end(), std::less( )); - new_top = points.back(); - - for(auto pt : points) - { - int pos_left = 0; - int pos_right = def_right; - get_line_left_right(pt, def_right, pos_left, pos_right); - - if(pos_right - pos_left >= width) - { - new_top = pt; - break; - } - } - } - return new_top; - } - auto el_parent = parent(); - if (el_parent) - { - int new_top = el_parent->find_next_line_top(top + m_pos.y, width, def_right + m_pos.x); - return new_top - m_pos.y; - } - return 0; -} - -void litehtml::render_item_block::update_floats(int dy, const std::shared_ptr &_parent) -{ - if(src_el()->is_floats_holder()) - { - bool reset_cache = false; - for(auto fb = m_floats_left.rbegin(); fb != m_floats_left.rend(); fb++) - { - if(fb->el->src_el()->is_ancestor(_parent->src_el())) - { - reset_cache = true; - fb->pos.y += dy; - } - } - if(reset_cache) - { - m_cache_line_left.invalidate(); - } - reset_cache = false; - for(auto fb = m_floats_right.rbegin(); fb != m_floats_right.rend(); fb++) - { - if(fb->el->src_el()->is_ancestor(_parent->src_el())) - { - reset_cache = true; - fb->pos.y += dy; - } - } - if(reset_cache) - { - m_cache_line_right.invalidate(); - } - } else - { - auto el_parent = parent(); - if (el_parent) - { - el_parent->update_floats(dy, _parent); - } - } -} - std::shared_ptr litehtml::render_item_block::init() { { @@ -571,9 +67,8 @@ std::shared_ptr litehtml::render_item_block::init() if (auto p = src_el()->parent()) { int val = atoi(p->get_attr("start", "1")); - for (int i = 0; i < (int)p->get_children_count(); i++) + for(const auto &child : p->children()) { - auto child = p->get_child(i); if (child == src_el()) { src_el()->set_attr("list_index", std::to_string(val).c_str()); @@ -618,7 +113,7 @@ std::shared_ptr litehtml::render_item_block::init() if (el->src_el()->is_block_box()) { has_block_level = true; - } else if (el->src_el()->is_inline_box()) + } else if (el->src_el()->is_inline()) { has_inlines = true; } @@ -637,7 +132,7 @@ std::shared_ptr litehtml::render_item_block::init() bool not_ws_added = false; for (const auto& el : m_children) { - if(el->src_el()->is_inline_box()) + if(el->src_el()->is_inline()) { inlines.push_back(el); if(!el->src_el()->is_white_space()) @@ -698,28 +193,14 @@ std::shared_ptr litehtml::render_item_block::init() return ret; } -int litehtml::render_item_block::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) +int litehtml::render_item_block::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) { - int ret_width = 0; - calc_outlines(containing_block_size.width); - - m_pos.clear(); - m_pos.move_to(x, y); - - m_pos.x += content_offset_left(); - m_pos.y += content_offset_top(); - - m_floats_left.clear(); - m_floats_right.clear(); - m_cache_line_left.invalidate(); - m_cache_line_right.invalidate(); - containing_block_context self_size = calculate_containing_block_context(containing_block_size); //***************************************** // Render content //***************************************** - ret_width = _render_content(x, y, second_pass, ret_width, self_size); + int ret_width = _render_content(x, y, second_pass, self_size, fmt_ctx); //***************************************** bool requires_rerender = false; // when true, the second pass for content rendering is required @@ -733,22 +214,7 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con m_pos.width = self_size.render_width; } else { - if(src_el()->is_inline_box() || - src_el()->css().get_float() != float_none || - src_el()->css().get_display() == display_table_cell || - src_el()->css().get_display() == display_table_caption || - src_el()->css().get_position() > element_position_relative) - { - m_pos.width = ret_width; - if(ret_width < self_size.render_width && !second_pass) - { - // We have to render content again with new max_width - requires_rerender = true; - } - } else - { - m_pos.width = self_size.render_width; - } + m_pos.width = self_size.render_width; } // Fix width with min-width attribute @@ -774,32 +240,32 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con // re-render content with new width if required if (requires_rerender && !second_pass && !is_root()) { - if(src_el()->is_floats_holder()) + if(src_el()->is_block_formatting_context()) { - m_floats_left.clear(); - m_floats_right.clear(); + fmt_ctx->clear_floats(-1); } else { - clear_floats(self_size.context_idx); + fmt_ctx->clear_floats(self_size.context_idx); } - m_cache_line_left.invalidate(); - m_cache_line_right.invalidate(); - _render_content(x, y, true, ret_width, self_size.new_width(m_pos.width)); + _render_content(x, y, true, self_size.new_width(m_pos.width), fmt_ctx); } // Set block height if (self_size.height.type != containing_block_context::cbc_value_type_auto) { - m_pos.height = self_size.height; + if(self_size.height > 0) + { + m_pos.height = self_size.height; + } if(src_el()->css().get_box_sizing() == box_sizing_border_box) { m_pos.height -= box_sizing_height(); } - } else if (src_el()->is_floats_holder()) + } else if (src_el()->is_block_formatting_context()) { // add the floats' height to the block height - int floats_height = get_floats_height(); + int floats_height = fmt_ctx->get_floats_height(); if (floats_height > m_pos.height) { m_pos.height = floats_height; @@ -845,12 +311,5 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con } - if (src_el()->is_floats_holder() && !second_pass) - { - for (const auto& fb : m_floats_left) - { - fb.el->apply_relative_shift(containing_block_size); - } - } return ret_width + content_offset_width(); } diff --git a/src/render_block_context.cpp b/src/render_block_context.cpp index b0aa444d7..0d16ab58f 100644 --- a/src/render_block_context.cpp +++ b/src/render_block_context.cpp @@ -2,11 +2,11 @@ #include "render_item.h" #include "document.h" -int litehtml::render_item_block_context::_render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) +int litehtml::render_item_block_context::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) { element_position el_position; + int ret_width = 0; int child_top = 0; int last_margin = 0; std::shared_ptr last_margin_el; @@ -22,7 +22,7 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco if(el->src_el()->css().get_float() != float_none) { - int rw = place_float(el, child_top, self_size); + int rw = place_float(el, child_top, self_size, fmt_ctx); if (rw > ret_width) { ret_width = rw; @@ -31,10 +31,14 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco { if(el->src_el()->css().get_position() == element_position_absolute || el->src_el()->css().get_position() == element_position_fixed) { - el->render(0, child_top, self_size); + int min_rendered_width = el->render(0, child_top, self_size, fmt_ctx); + if(min_rendered_width < el->width() && el->src_el()->css().get_width().is_predefined()) + { + el->render(0, child_top, self_size.new_width(min_rendered_width), fmt_ctx); + } } else { - child_top = get_cleared_top(el, child_top); + child_top = fmt_ctx->get_cleared_top(el, child_top); int child_x = 0; int child_width = self_size.render_width; @@ -59,11 +63,11 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco } } - if(el->src_el()->is_replaced() || el->src_el()->is_floats_holder() || el->src_el()->css().get_display() == display_table) + if(el->src_el()->is_replaced() || el->src_el()->is_block_formatting_context() || el->src_el()->css().get_display() == display_table) { int ln_left = 0; int ln_right = child_width; - get_line_left_right(child_top, child_width, ln_left, ln_right); + fmt_ctx->get_line_left_right(child_top, child_width, ln_left, ln_right); child_x = ln_left; child_width = ln_right - ln_left; @@ -72,11 +76,11 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco el->pos().height = el->src_el()->css().get_height().calc_percent(el_parent ? el_parent->pos().height : 0); } - int rw = el->render(child_x, child_top, self_size.new_width(child_width)); + int rw = el->render(child_x, child_top, self_size.new_width(child_width), fmt_ctx); // Render table with "width: auto" into returned width if(el->src_el()->css().get_display() == display_table && rw < child_width && el->src_el()->css().get_width().is_predefined()) { - el->render(child_x, child_top, self_size.new_width(rw)); + el->render(child_x, child_top, self_size.new_width(rw), fmt_ctx); } int auto_margin = el->calc_auto_margins(child_width); if(auto_margin) diff --git a/src/render_flex.cpp b/src/render_flex.cpp index c9cf8e538..983f61812 100644 --- a/src/render_flex.cpp +++ b/src/render_flex.cpp @@ -2,8 +2,7 @@ #include "render_item.h" #include "types.h" -int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) +int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) { return 0; } diff --git a/src/render_image.cpp b/src/render_image.cpp index 38f576bc1..37105278e 100644 --- a/src/render_image.cpp +++ b/src/render_image.cpp @@ -2,8 +2,7 @@ #include "render_item.h" #include "document.h" -int -litehtml::render_item_image::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) +int litehtml::render_item_image::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) { int parent_width = containing_block_size.width; diff --git a/src/render_inline_context.cpp b/src/render_inline_context.cpp index b348a8cf7..72cd1fe3d 100644 --- a/src/render_inline_context.cpp +++ b/src/render_inline_context.cpp @@ -3,8 +3,7 @@ #include "document.h" #include "iterators.h" -int litehtml::render_item_inline_context::_render_content(int x, int y, bool second_pass, int ret_width, - const containing_block_context &self_size) +int litehtml::render_item_inline_context::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) { m_line_boxes.clear(); m_max_line_width = 0; @@ -50,20 +49,20 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec } } // place element into rendering flow - place_inline(std::unique_ptr(new line_box_item(el)), self_size); + place_inline(std::unique_ptr(new line_box_item(el)), self_size, fmt_ctx); } break; case iterator_item_type_start_parent: { el->clear_inline_boxes(); - place_inline(std::unique_ptr(new lbi_start(el)), self_size); + place_inline(std::unique_ptr(new lbi_start(el)), self_size, fmt_ctx); } break; case iterator_item_type_end_parent: { - place_inline(std::unique_ptr(new lbi_end(el)), self_size); + place_inline(std::unique_ptr(new lbi_end(el)), self_size, fmt_ctx); } break; } @@ -79,7 +78,7 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec m_margins.top = std::max(m_line_boxes.front()->top_margin(), m_margins.top); if (m_margins.top != old_top) { - update_floats(m_margins.top - old_top, shared_from_this()); + fmt_ctx->update_floats(m_margins.top - old_top, shared_from_this()); } } if (collapse_bottom_margin()) @@ -93,13 +92,13 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec } } - return std::max(ret_width, m_max_line_width); + return m_max_line_width; } void litehtml::render_item_inline_context::fix_line_width(element_float flt, - const containing_block_context &self_size) + const containing_block_context &self_size, + formatting_context* fmt_ctx) { - int ret_width = 0; if(!m_line_boxes.empty()) { auto el_front = m_line_boxes.back()->get_first_text_part(); @@ -128,7 +127,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt, for(auto& item : items) { - place_inline(std::move(item), self_size); + place_inline(std::move(item), self_size, fmt_ctx); } } else { @@ -137,7 +136,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt, int line_left = 0; int line_right = self_size.render_width; - get_line_left_right(line_top, self_size.render_width, line_left, line_right); + fmt_ctx->get_line_left_right(line_top, self_size.render_width, line_left, line_right); if(m_line_boxes.size() == 1) { @@ -157,7 +156,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt, auto items = m_line_boxes.back()->new_width(line_left, line_right); for(auto& item : items) { - place_inline(std::move(item), self_size); + place_inline(std::move(item), self_size, fmt_ctx); } } } @@ -183,7 +182,7 @@ std::list > litehtml::render_item_inlin return ret; } -int litehtml::render_item_inline_context::new_box(const std::unique_ptr& el, line_context& line_ctx, const containing_block_context &self_size) +int litehtml::render_item_inline_context::new_box(const std::unique_ptr& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx) { auto items = finish_last_box(false, self_size); int line_top = 0; @@ -191,22 +190,22 @@ int litehtml::render_item_inline_context::new_box(const std::unique_ptrbottom(); } - line_ctx.top = get_cleared_top(el->get_el(), line_top); + line_ctx.top = fmt_ctx->get_cleared_top(el->get_el(), line_top); line_ctx.left = 0; line_ctx.right = self_size.render_width; line_ctx.fix_top(); - get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); + fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); - if(el->get_el()->src_el()->is_inline_box() || el->get_el()->src_el()->is_floats_holder()) + if(el->get_el()->src_el()->is_inline() || el->get_el()->src_el()->is_block_formatting_context()) { if (el->get_el()->width() > line_ctx.right - line_ctx.left) { - line_ctx.top = find_next_line_top(line_ctx.top, el->get_el()->width(), self_size.render_width); + line_ctx.top = fmt_ctx->find_next_line_top(line_ctx.top, el->get_el()->width(), self_size.render_width); line_ctx.left = 0; line_ctx.right = self_size.render_width; line_ctx.fix_top(); - get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); + fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); } } @@ -241,7 +240,7 @@ int litehtml::render_item_inline_context::new_box(const std::unique_ptr item, const containing_block_context &self_size) +void litehtml::render_item_inline_context::place_inline(std::unique_ptr item, const containing_block_context &self_size, formatting_context* fmt_ctx) { if(item->get_el()->src_el()->css().get_display() == display_none) return; @@ -252,7 +251,7 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptrtop(); } - int ret = place_float(item->get_el(), line_top, self_size); + int ret = place_float(item->get_el(), line_top, self_size, fmt_ctx); if(ret > m_max_line_width) { m_max_line_width = ret; @@ -269,24 +268,24 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptrget_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); if(item->get_type() == line_box_item::type_text_part) { - switch (item->get_el()->src_el()->css().get_display()) + if(item->get_el()->src_el()->is_inline_box()) { - case display_inline_block: - case display_inline_table: - item->set_rendered_min_width(item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(line_ctx.right))); - break; - case display_inline_text: + int min_rendered_width = item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(line_ctx.right), fmt_ctx); + if(min_rendered_width < item->get_el()->width() && item->get_el()->src_el()->css().get_width().is_predefined()) { - litehtml::size sz; - item->get_el()->src_el()->get_content_size(sz, line_ctx.right); - item->get_el()->pos() = sz; - item->set_rendered_min_width(sz.width); + item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(min_rendered_width), fmt_ctx); } - break; + item->set_rendered_min_width(min_rendered_width); + } else if(item->get_el()->src_el()->css().get_display() == display_inline_text) + { + litehtml::size sz; + item->get_el()->src_el()->get_content_size(sz, line_ctx.right); + item->get_el()->pos() = sz; + item->set_rendered_min_width(sz.width); } } @@ -300,7 +299,7 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptrtop(); @@ -311,10 +310,10 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptrget_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right); } - if(!item->get_el()->src_el()->is_inline_box()) + if(!item->get_el()->src_el()->is_inline()) { if(m_line_boxes.size() == 1) { diff --git a/src/render_item.cpp b/src/render_item.cpp index 2fc8e99c7..808ffaf3f 100644 --- a/src/render_item.cpp +++ b/src/render_item.cpp @@ -27,6 +27,36 @@ litehtml::render_item::render_item(std::shared_ptr _src_el) : m_borders.bottom = doc->to_pixels(src_el()->css().get_borders().bottom.width, fnt_size); } +int litehtml::render_item::render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass) +{ + int ret; + + calc_outlines(containing_block_size.width); + + m_pos.clear(); + m_pos.move_to(x, y); + + int content_left = content_offset_left(); + int content_top = content_offset_top(); + + m_pos.x += content_left; + m_pos.y += content_top; + + + 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 + { + fmt_ctx->push_position(x + content_left, y + content_top); + ret = _render(x, y, containing_block_size, fmt_ctx, second_pass); + fmt_ctx->pop_position(x + content_left, y + content_top); + } + return ret; +} void litehtml::render_item::calc_outlines( int parent_width ) { @@ -119,10 +149,10 @@ bool litehtml::render_item::get_predefined_height(int& p_height, int containing_ if(h.units() == css_units_percentage) { p_height = h.calc_percent(containing_block_height); - return containing_block_height != 0; + return containing_block_height > 0; } p_height = src_el()->get_document()->to_pixels(h, src_el()->css().get_font_size()); - return true; + return p_height > 0; } int litehtml::render_item::calc_width(int defVal, int containing_block_width) const @@ -438,7 +468,7 @@ void litehtml::render_item::render_positioned(render_type rt) if(need_render) { position pos = el->m_pos; - el->render(el->left(), el->top(), containing_block_size.new_width(el->width()), true); + el->render(el->left(), el->top(), containing_block_size.new_width(el->width()), nullptr, true); el->m_pos = pos; } @@ -632,7 +662,7 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi } break; case draw_block: - if (!el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) + if (!el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) { el->src_el()->draw(hdc, pos.x, pos.y, clip, el); } @@ -646,7 +676,7 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi } break; case draw_inlines: - if (el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) + if (el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) { el->src_el()->draw(hdc, pos.x, pos.y, clip, el); if (el->src_el()->css().get_display() == display_inline_block) @@ -734,7 +764,7 @@ std::shared_ptr litehtml::render_item::get_child_by_point(in } break; case draw_block: - if(!el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) + if(!el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) { if(el->is_point_inside(el_pos.x, el_pos.y)) { @@ -755,7 +785,7 @@ std::shared_ptr litehtml::render_item::get_child_by_point(in } break; case draw_inlines: - if(el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) + if(el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned()) { if(el->src_el()->css().get_display() == display_inline_block || el->src_el()->css().get_display() == display_inline_table || diff --git a/src/render_table.cpp b/src/render_table.cpp index 2ec048a98..c6756304e 100644 --- a/src/render_table.cpp +++ b/src/render_table.cpp @@ -11,30 +11,12 @@ litehtml::render_item_table::render_item_table(std::shared_ptr _src_el) { } -int litehtml::render_item_table::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) +int litehtml::render_item_table::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) { if (!m_grid) return 0; - calc_outlines(containing_block_size.width); - - m_pos.clear(); - m_pos.move_to(x, y); - - m_pos.x += content_offset_left(); - m_pos.y += content_offset_top(); - containing_block_context self_size = calculate_containing_block_context(containing_block_size); -/* if(cb_size.width_type == containing_block_context::cbc_value_type_auto) - { - max_width -= content_offset_left() + content_offset_right(); - } else - { - max_width -= m_padding.width() + m_borders.width(); - } - if(max_width < 0) max_width = 0; - max_width = std::min(max_width, cb_size.width); -*/ // Calculate table spacing int table_width_spacing = 0; if (src_el()->css().get_border_collapse() == border_collapse_separate) @@ -71,7 +53,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con table_cell* cell = m_grid->cell(0, row); if (cell && cell->el) { - cell->min_width = cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing)); + cell->min_width = cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing), fmt_ctx); cell->el->pos().width = cell->min_width - cell->el->content_offset_left() - cell->el->content_offset_right(); } @@ -89,7 +71,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con if (!m_grid->column(col).css_width.is_predefined() && m_grid->column(col).css_width.units() != css_units_percentage) { int css_w = m_grid->column(col).css_width.calc_percent(self_size.width); - int el_w = cell->el->render(0, 0, self_size.new_width(css_w)); + int el_w = cell->el->render(0, 0, self_size.new_width(css_w),fmt_ctx); cell->min_width = cell->max_width = std::max(css_w, el_w); cell->el->pos().width = cell->min_width - cell->el->content_offset_left() - cell->el->content_offset_right(); @@ -97,9 +79,9 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con else { // calculate minimum content width - cell->min_width = cell->el->render(0, 0, self_size.new_width(cell->el->content_offset_width())); + cell->min_width = cell->el->render(0, 0, self_size.new_width(cell->el->content_offset_width()), fmt_ctx); // calculate maximum content width - cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing)); + cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing), fmt_ctx); } } } @@ -201,7 +183,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con //if (cell->el->pos().width != cell_width - cell->el->content_offset_left() - // cell->el->content_offset_right()) { - cell->el->render(m_grid->column(col).left, 0, self_size.new_width(cell_width), true); + cell->el->render(m_grid->column(col).left, 0, self_size.new_width(cell_width), fmt_ctx, true); cell->el->pos().width = cell_width - cell->el->content_offset_left() - cell->el->content_offset_right(); } @@ -343,7 +325,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con for (auto& caption : m_grid->captions()) { - caption->render(-border_left(), captions_height, self_size.new_width(table_width + border_left() + border_right())); + caption->render(-border_left(), captions_height, self_size.new_width(table_width + border_left() + border_right()), fmt_ctx); captions_height += caption->height(); } diff --git a/test/render/test33.htm b/test/render/test33.htm new file mode 100644 index 000000000..d47eb2365 --- /dev/null +++ b/test/render/test33.htm @@ -0,0 +1,5 @@ + + + + +
Lorem ipsum dolor
diff --git a/test/render/test33.htm.png b/test/render/test33.htm.png new file mode 100644 index 000000000..d1bee94be Binary files /dev/null and b/test/render/test33.htm.png differ diff --git a/test/render/test34.htm b/test/render/test34.htm new file mode 100644 index 000000000..34586732b --- /dev/null +++ b/test/render/test34.htm @@ -0,0 +1,14 @@ + + + + + +
Should be on right side
+
+ + + + +
Should be on left side
diff --git a/test/render/test34.htm.png b/test/render/test34.htm.png new file mode 100644 index 000000000..fd4dbab0a Binary files /dev/null and b/test/render/test34.htm.png differ diff --git a/test/render/test35.htm b/test/render/test35.htm new file mode 100644 index 000000000..aeffaec46 --- /dev/null +++ b/test/render/test35.htm @@ -0,0 +1,28 @@ + + + diff --git a/test/render/test35.htm.png b/test/render/test35.htm.png new file mode 100644 index 000000000..9ab5b44d8 Binary files /dev/null and b/test/render/test35.htm.png differ diff --git a/test/render/test36.htm b/test/render/test36.htm new file mode 100644 index 000000000..62afa347f --- /dev/null +++ b/test/render/test36.htm @@ -0,0 +1,68 @@ + + +
+
+ + + +
+
diff --git a/test/render/test36.htm.png b/test/render/test36.htm.png new file mode 100644 index 000000000..ef7f915aa Binary files /dev/null and b/test/render/test36.htm.png differ diff --git a/test/render/test37.htm b/test/render/test37.htm new file mode 100644 index 000000000..a6f722111 --- /dev/null +++ b/test/render/test37.htm @@ -0,0 +1,46 @@ + + +
+
a
+
s
+
+
+
d
+
f
+
diff --git a/test/render/test37.htm.png b/test/render/test37.htm.png new file mode 100644 index 000000000..75b2b7c4d Binary files /dev/null and b/test/render/test37.htm.png differ diff --git a/test/render/test38.htm b/test/render/test38.htm new file mode 100644 index 000000000..a2eb9c325 --- /dev/null +++ b/test/render/test38.htm @@ -0,0 +1,33 @@ + + +
    +
  • item1
  • +
  • item2
  • +
  • item3
  • +
\ No newline at end of file diff --git a/test/render/test38.htm.png b/test/render/test38.htm.png new file mode 100644 index 000000000..0abfc11b5 Binary files /dev/null and b/test/render/test38.htm.png differ