#ifndef LH_LINE_BOX_H #define LH_LINE_BOX_H #include #include "css_properties.h" #include "types.h" namespace litehtml { class render_item; struct line_context { int calculatedTop; int top; int left; int right; int width() const { return right - left; } void fix_top() { calculatedTop = top; } line_context() : calculatedTop(0), top(0), left(0), right(0) {} }; class line_box_item { public: enum element_type { type_text_part, type_inline_start, type_inline_continue, type_inline_end }; protected: std::shared_ptr m_element; int m_rendered_min_width = 0; int m_items_top = 0; int m_items_bottom = 0; public: explicit line_box_item(const std::shared_ptr& element) : m_element(element) {} line_box_item(const line_box_item& el) = default; line_box_item(line_box_item&&) = default; virtual ~line_box_item(); virtual int height() const; const std::shared_ptr& get_el() const { return m_element; } virtual position& pos(); virtual void place_to(int x, int y); virtual int width() const; virtual int top() const; virtual int bottom() const; virtual int right() const; virtual int left() const; virtual element_type get_type() const { return type_text_part; } virtual int get_rendered_min_width() const { return m_rendered_min_width; } virtual void set_rendered_min_width(int min_width) { m_rendered_min_width = min_width; } void reset_items_height() { m_items_top = m_items_bottom = 0; } void add_item_height(int item_top, int item_bottom) { m_items_top = std::min(m_items_top, item_top); m_items_bottom = std::max(m_items_bottom, item_bottom); } int get_items_top() const { return m_items_top; } int get_items_bottom() const { return m_items_bottom; } }; class lbi_start : public line_box_item { protected: position m_pos; public: explicit lbi_start(const std::shared_ptr& element); ~lbi_start() override; void place_to(int x, int y) override; int height() const override; int width() const override; position& pos() override { return m_pos; } int top() const override; int bottom() const override; int right() const override; int left() const override; element_type get_type() const override { return type_inline_start; } int get_rendered_min_width() const override { return width(); } }; class lbi_end : public lbi_start { public: explicit lbi_end(const std::shared_ptr& element); virtual ~lbi_end() override; void place_to(int x, int y) override; int right() const override; int left() const override; element_type get_type() const override { return type_inline_end; } }; class lbi_continue : public lbi_start { public: explicit lbi_continue(const std::shared_ptr& element); virtual ~lbi_continue() override; void place_to(int x, int y) override; int right() const override; int left() const override; int width() const override; element_type get_type() const override { return type_inline_continue; } }; class line_box { struct va_context { int line_height = 0; int baseline = 0; font_metrics fm; line_box_item* start_lbi = nullptr; }; int m_top; int m_left; int m_right; int m_height; int m_width; css_line_height_t m_default_line_height; font_metrics m_font_metrics; int m_baseline; text_align m_text_align; int m_min_width; std::list< std::unique_ptr > m_items; public: line_box(int top, int left, int right, const css_line_height_t& line_height, const font_metrics& fm, text_align align) : m_top(top), m_left(left), m_right(right), m_height(0), m_width(0), m_default_line_height(line_height), m_font_metrics(fm), m_baseline(0), m_text_align(align), m_min_width(0) { } int bottom() const { return m_top + height(); } int top() const { return m_top; } int right() const { return m_left + width(); } int left() const { return m_left; } int height() const { return m_height; } int width() const { return m_width; } int line_right() const { return m_right; } int min_width() const { return m_min_width; } void add_item(std::unique_ptr item); bool can_hold(const std::unique_ptr& item, white_space ws) const; bool is_empty() const; int baseline() const; int top_margin() const; int bottom_margin() const; void y_shift(int shift); std::list< std::unique_ptr > finish(bool last_box, const containing_block_context &containing_block_size); std::list< std::unique_ptr > new_width(int left, int right); std::shared_ptr get_last_text_part() const; std::shared_ptr get_first_text_part() const; std::list< std::unique_ptr >& items() { return m_items; } private: bool have_last_space() const; bool is_break_only() const; static int calc_va_baseline(const va_context& current, vertical_align va, const font_metrics& new_font, int top, int bottom); }; } #endif //LH_LINE_BOX_H