aboutsummaryrefslogtreecommitdiffstats
path: root/include/litehtml/line_box.h
blob: 43f5d439e9f9cd39da7da5bf6706057b07d19799 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#ifndef LH_LINE_BOX_H
#define LH_LINE_BOX_H

#include <vector>
#include <memory>
#include "os_types.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;
        }
    };

	class line_box_item
	{
	public:
		enum element_type
		{
			type_text_part,
			type_inline_start,
			type_inline_continue,
			type_inline_end
		};
	protected:
		std::shared_ptr<render_item> m_element;
		int m_rendered_min_width;
	public:
		explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element), m_rendered_min_width(0) {}
		line_box_item() = default;
		line_box_item(const line_box_item& el) = default;
		line_box_item(line_box_item&&) = default;

		int height() const { return right() - left(); }
		const std::shared_ptr<render_item>& 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; }
	};

	class lbi_start : public line_box_item
	{
	protected:
		position m_pos;
	public:
		explicit lbi_start(const std::shared_ptr<render_item>& element);

		void place_to(int x, int y) 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<render_item>& element);

		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<render_item>& element);

		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 			baseline;
			font_metrics 	fm;

			va_context() : baseline(0) {}
		};

        int		                m_top;
        int		                m_left;
        int		                m_right;
        int						m_height;
        int						m_width;
		int						m_line_height;
		int						m_default_line_height;
        font_metrics			m_font_metrics;
        int						m_baseline;
        text_align				m_text_align;
		int 					m_min_width;
		std::list< std::unique_ptr<line_box_item> > m_items;
    public:
        line_box(int top, int left, int right, int line_height, const font_metrics& fm, text_align align) :
				m_top(top),
				m_left(left),
				m_right(right),
				m_height(0),
				m_width(0),
				m_font_metrics(fm),
				m_default_line_height(line_height),
				m_baseline(0),
				m_line_height(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<line_box_item> item);
        bool				can_hold(const std::unique_ptr<line_box_item>& 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<line_box_item> >	finish(bool last_box, const containing_block_context &containing_block_size);
		std::list< std::unique_ptr<line_box_item> > new_width(int left, int right);
		std::shared_ptr<render_item> 		get_last_text_part() const;
		std::shared_ptr<render_item> 		get_first_text_part() const;
		std::list< std::unique_ptr<line_box_item> >& 	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