diff --git a/CMakeLists.txt b/CMakeLists.txt index 014089023..58a598881 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,6 @@ set(SOURCE_LITEHTML src/render_block_context.cpp src/render_block.cpp src/render_inline_context.cpp - src/render_inline.cpp src/render_table.cpp src/render_flex.cpp src/render_image.cpp @@ -123,6 +122,13 @@ set(HEADER_LITEHTML include/litehtml/css_properties.h include/litehtml/line_box.h include/litehtml/render_item.h + include/litehtml/render_flex.h + include/litehtml/render_image.h + include/litehtml/render_inline.h + include/litehtml/render_table.h + include/litehtml/render_inline_context.h + include/litehtml/render_block_context.h + include/litehtml/render_block.h include/litehtml/master_css.h include/litehtml/string_id.h include/litehtml/formatting_context.h diff --git a/include/litehtml/render_block.h b/include/litehtml/render_block.h new file mode 100644 index 000000000..eb058c618 --- /dev/null +++ b/include/litehtml/render_block.h @@ -0,0 +1,40 @@ +#ifndef LITEHTML_RENDER_BLOCK_H +#define LITEHTML_RENDER_BLOCK_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_block : public render_item + { + protected: + /** + * Render block content. + * + * @param x - horizontal position of the content + * @param y - vertical position of the content + * @param second_pass - true is this is the second pass. + * @param ret_width - input minimal width. + * @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, 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) + {} + + public: + explicit render_item_block(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + std::shared_ptr init() override; + }; +} + +#endif //LITEHTML_RENDER_BLOCK_H diff --git a/include/litehtml/render_block_context.h b/include/litehtml/render_block_context.h new file mode 100644 index 000000000..3b5192261 --- /dev/null +++ b/include/litehtml/render_block_context.h @@ -0,0 +1,29 @@ +#ifndef LITEHTML_RENDER_BLOCK_CONTEXT_H +#define LITEHTML_RENDER_BLOCK_CONTEXT_H + +#include "render_block.h" + +namespace litehtml +{ + /** + * In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a + * containing block. + * https://www.w3.org/TR/CSS22/visuren.html#block-formatting + */ + class render_item_block_context : public render_item_block + { + protected: + 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)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_BLOCK_CONTEXT_H diff --git a/include/litehtml/render_flex.h b/include/litehtml/render_flex.h new file mode 100644 index 000000000..5d31bc9bf --- /dev/null +++ b/include/litehtml/render_flex.h @@ -0,0 +1,46 @@ +#ifndef LITEHTML_RENDER_FLEX_H +#define LITEHTML_RENDER_FLEX_H + +#include "render_block.h" + +namespace litehtml +{ + class render_item_flex : public render_item_block + { + struct flex_item + { + std::shared_ptr el; + int base_size; + int main_size; + int min_width; + int max_width; + int line; + + explicit flex_item(std::shared_ptr _el) : + el(std::move(_el)), + min_width(0), + max_width(0), + line(0), + base_size(0), + main_size(0) + {} + }; + protected: + std::list> m_flex_items; + + 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)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override; + std::shared_ptr init() override; + }; +} + +#endif //LITEHTML_RENDER_FLEX_H diff --git a/include/litehtml/render_image.h b/include/litehtml/render_image.h new file mode 100644 index 000000000..e85f487ca --- /dev/null +++ b/include/litehtml/render_image.h @@ -0,0 +1,25 @@ +#ifndef LITEHTML_RENDER_IMAGE_H +#define LITEHTML_RENDER_IMAGE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_image : public render_item + { + 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)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_IMAGE_H diff --git a/include/litehtml/render_inline.h b/include/litehtml/render_inline.h new file mode 100644 index 000000000..476011563 --- /dev/null +++ b/include/litehtml/render_inline.h @@ -0,0 +1,30 @@ +#ifndef LITEHTML_RENDER_INLINE_H +#define LITEHTML_RENDER_INLINE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_inline : public render_item + { + protected: + position::vector m_boxes; + + public: + explicit render_item_inline(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + void get_inline_boxes( position::vector& boxes ) const override { boxes = m_boxes; } + void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; } + void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); }; + void clear_inline_boxes() override { m_boxes.clear(); } + int get_base_line() override { return src_el()->css().get_font_metrics().base_line(); } + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_INLINE_H diff --git a/include/litehtml/render_inline_context.h b/include/litehtml/render_inline_context.h new file mode 100644 index 000000000..894cfe989 --- /dev/null +++ b/include/litehtml/render_inline_context.h @@ -0,0 +1,55 @@ +#ifndef LITEHTML_RENDER_INLINE_CONTEXT_H +#define LITEHTML_RENDER_INLINE_CONTEXT_H + +#include "render_block.h" + +namespace litehtml +{ + /** + * An inline formatting context is established by a block container box that contains no block-level boxes. + * https://www.w3.org/TR/CSS22/visuren.html#inline-formatting + */ + class render_item_inline_context : public render_item_block + { + /** + * Structure contains elements with display: inline + * members: + * - element: render_item with display: inline + * - boxes: rectangles represented inline element content. There are can be many boxes if content + * is split into some lines + * - start_box: the start position of currently calculated box + */ + struct inlines_item + { + std::shared_ptr element; + position::vector boxes; + position start_box; + + explicit inlines_item(const std::shared_ptr& el) : element(el) {} + }; + protected: + std::vector > m_line_boxes; + int m_max_line_width; + + 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, 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, 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) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + + int get_base_line() override; + }; +} + +#endif //LITEHTML_RENDER_INLINE_CONTEXT_H diff --git a/include/litehtml/render_item.h b/include/litehtml/render_item.h index db2cf1255..9d4561e5a 100644 --- a/include/litehtml/render_item.h +++ b/include/litehtml/render_item.h @@ -273,8 +273,6 @@ namespace litehtml ri->parent(shared_from_this()); } - 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 { return m_parent.expired(); @@ -305,6 +303,7 @@ namespace litehtml return !(m_skip || src_el()->css().get_display() == display_none || src_el()->css().get_visibility() != visibility_visible); } + int render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false); int calc_width(int defVal, int containing_block_width) const; bool get_predefined_height(int& p_height, int containing_block_height) const; void apply_relative_shift(const containing_block_context &containing_block_size); @@ -348,225 +347,6 @@ namespace litehtml */ void get_rendering_boxes( position::vector& redraw_boxes); }; - - class render_item_block : public render_item - { - protected: - /** - * Render block content. - * - * @param x - horizontal position of the content - * @param y - vertical position of the content - * @param second_pass - true is this is the second pass. - * @param ret_width - input minimal width. - * @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, 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) - {} - - public: - explicit render_item_block(std::shared_ptr src_el) : render_item(std::move(src_el)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - std::shared_ptr init() override; - }; - - /** - * In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a - * containing block. - * https://www.w3.org/TR/CSS22/visuren.html#block-formatting - */ - class render_item_block_context : public render_item_block - { - protected: - 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)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - }; - - /** - * An inline formatting context is established by a block container box that contains no block-level boxes. - * https://www.w3.org/TR/CSS22/visuren.html#inline-formatting - */ - class render_item_inline_context : public render_item_block - { - /** - * Structure contains elements with display: inline - * members: - * - element: render_item with display: inline - * - boxes: rectangles represented inline element content. There are can be many boxes if content - * is split into some lines - * - start_box: the start position of currently calculated box - */ - struct inlines_item - { - std::shared_ptr element; - position::vector boxes; - position start_box; - - explicit inlines_item(const std::shared_ptr& el) : element(el) {} - }; - protected: - std::vector > m_line_boxes; - int m_max_line_width; - - 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, 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, 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) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - - int get_base_line() override; - }; - - class render_item_table : public render_item - { - protected: - // data for table rendering - std::unique_ptr m_grid; - 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); - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - 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; - }; - - class render_item_table_part : public render_item - { - public: - explicit render_item_table_part(std::shared_ptr src_el) : render_item(std::move(src_el)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - }; - - class render_item_table_row : public render_item - { - public: - explicit render_item_table_row(std::shared_ptr src_el) : render_item(std::move(src_el)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - void get_inline_boxes( position::vector& boxes ) const override; - }; - - class render_item_inline : public render_item - { - protected: - position::vector m_boxes; - - public: - explicit render_item_inline(std::shared_ptr src_el) : render_item(std::move(src_el)) - {} - - void get_inline_boxes( position::vector& boxes ) const override { boxes = m_boxes; } - void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; } - void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); }; - void clear_inline_boxes() override { m_boxes.clear(); } - int get_base_line() override { return src_el()->css().get_font_metrics().base_line(); } - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - }; - - class render_item_image : public render_item - { - 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)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - }; - - class render_item_flex : public render_item_block - { - struct flex_item - { - std::shared_ptr el; - int base_size; - int main_size; - int min_width; - int max_width; - int line; - - explicit flex_item(std::shared_ptr _el) : - el(std::move(_el)), - min_width(0), - max_width(0), - line(0), - base_size(0), - main_size(0) - {} - }; - protected: - std::list> m_flex_items; - - 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)) - {} - - std::shared_ptr clone() override - { - return std::make_shared(src_el()); - } - void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override; - std::shared_ptr init() override; - }; - } #endif //LH_RENDER_ITEM_H diff --git a/include/litehtml/render_table.h b/include/litehtml/render_table.h new file mode 100644 index 000000000..57fe435df --- /dev/null +++ b/include/litehtml/render_table.h @@ -0,0 +1,56 @@ +#ifndef LITEHTML_RENDER_TABLE_H +#define LITEHTML_RENDER_TABLE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_table : public render_item + { + protected: + // data for table rendering + std::unique_ptr m_grid; + 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); + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + 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; + }; + + class render_item_table_part : public render_item + { + public: + explicit render_item_table_part(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; + + class render_item_table_row : public render_item + { + public: + explicit render_item_table_row(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + void get_inline_boxes( position::vector& boxes ) const override; + }; +} + +#endif //LITEHTML_RENDER_TABLE_H diff --git a/src/document.cpp b/src/document.cpp index 4ba36b4ea..ec336613d 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -27,6 +27,8 @@ #include "gumbo.h" #include "utf8_strings.h" #include "render_item.h" +#include "render_table.h" +#include "render_block.h" litehtml::document::document(document_container* objContainer) { diff --git a/src/el_image.cpp b/src/el_image.cpp index 34b8a7aef..9cf8146b4 100644 --- a/src/el_image.cpp +++ b/src/el_image.cpp @@ -1,6 +1,6 @@ #include "html.h" #include "el_image.h" -#include "render_item.h" +#include "render_image.h" litehtml::el_image::el_image(const document::ptr& doc) : html_tag(doc) { diff --git a/src/element.cpp b/src/element.cpp index 234e95975..1d0a509b1 100644 --- a/src/element.cpp +++ b/src/element.cpp @@ -2,6 +2,9 @@ #include "element.h" #include "document.h" #include "render_item.h" +#include "render_flex.h" +#include "render_inline.h" +#include "render_table.h" #include "el_before_after.h" namespace litehtml diff --git a/src/render_block.cpp b/src/render_block.cpp index a9568d11e..d653f3114 100644 --- a/src/render_block.cpp +++ b/src/render_block.cpp @@ -1,5 +1,7 @@ #include "html.h" -#include "render_item.h" +#include "render_block.h" +#include "render_inline_context.h" +#include "render_block_context.h" #include "document.h" int litehtml::render_item_block::place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx) diff --git a/src/render_block_context.cpp b/src/render_block_context.cpp index 0d16ab58f..7591378c2 100644 --- a/src/render_block_context.cpp +++ b/src/render_block_context.cpp @@ -1,5 +1,5 @@ #include "html.h" -#include "render_item.h" +#include "render_block_context.h" #include "document.h" 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) diff --git a/src/render_flex.cpp b/src/render_flex.cpp index 983f61812..2cab59e04 100644 --- a/src/render_flex.cpp +++ b/src/render_flex.cpp @@ -1,6 +1,6 @@ #include "html.h" -#include "render_item.h" #include "types.h" +#include "render_flex.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/src/render_image.cpp b/src/render_image.cpp index 37105278e..63e622d7b 100644 --- a/src/render_image.cpp +++ b/src/render_image.cpp @@ -1,5 +1,5 @@ #include "html.h" -#include "render_item.h" +#include "render_image.h" #include "document.h" int litehtml::render_item_image::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) diff --git a/src/render_inline.cpp b/src/render_inline.cpp deleted file mode 100644 index 0ea24b17d..000000000 --- a/src/render_inline.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "html.h" -#include "render_item.h" - diff --git a/src/render_inline_context.cpp b/src/render_inline_context.cpp index 72cd1fe3d..2d8f2e173 100644 --- a/src/render_inline_context.cpp +++ b/src/render_inline_context.cpp @@ -1,5 +1,5 @@ #include "html.h" -#include "render_item.h" +#include "render_inline_context.h" #include "document.h" #include "iterators.h" diff --git a/src/render_item.cpp b/src/render_item.cpp index 808ffaf3f..4eb25757d 100644 --- a/src/render_item.cpp +++ b/src/render_item.cpp @@ -1086,21 +1086,3 @@ litehtml::containing_block_context litehtml::render_item::calculate_containing_b } return ret; } - -void litehtml::render_item_table_row::get_inline_boxes( position::vector& boxes ) const -{ - position pos; - for(auto& el : m_children) - { - if(el->src_el()->css().get_display() == display_table_cell) - { - pos.x = el->left() + el->margin_left(); - pos.y = el->top() - m_padding.top - m_borders.top; - - pos.width = el->right() - pos.x - el->margin_right() - el->margin_left(); - pos.height = el->height() + m_padding.top + m_padding.bottom + m_borders.top + m_borders.bottom; - - boxes.push_back(pos); - } - } -} diff --git a/src/render_table.cpp b/src/render_table.cpp index c6756304e..3720bfcd0 100644 --- a/src/render_table.cpp +++ b/src/render_table.cpp @@ -1,5 +1,5 @@ #include "html.h" -#include "render_item.h" +#include "render_table.h" #include "document.h" #include "iterators.h" @@ -462,3 +462,21 @@ int litehtml::render_item_table::get_draw_vertical_offset() } return 0; } + +void litehtml::render_item_table_row::get_inline_boxes( position::vector& boxes ) const +{ + position pos; + for(auto& el : m_children) + { + if(el->src_el()->css().get_display() == display_table_cell) + { + pos.x = el->left() + el->margin_left(); + pos.y = el->top() - m_padding.top - m_borders.top; + + pos.width = el->right() - pos.x - el->margin_right() - el->margin_left(); + pos.height = el->height() + m_padding.top + m_padding.bottom + m_borders.top + m_borders.bottom; + + boxes.push_back(pos); + } + } +}