xref: /haiku/src/apps/haikudepot/textview/ParagraphLayout.h (revision a5061ecec55353a5f394759473f1fd6df04890da)
1 /*
2  * Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
3  * Copyright 2021, Andrew Lindesay <apl@lindesay.co.nz>.
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 #ifndef PARAGRAPH_LAYOUT_H
7 #define PARAGRAPH_LAYOUT_H
8 
9 #include <vector>
10 
11 #include <Font.h>
12 #include <Referenceable.h>
13 #include <String.h>
14 
15 #include "CharacterStyle.h"
16 #include "List.h"
17 #include "Paragraph.h"
18 
19 
20 class BView;
21 
22 
23 class GlyphInfo {
24 public:
25 	GlyphInfo()
26 		:
27 		charCode(0),
28 		x(0.0f),
29 		width(0.0f),
30 		lineIndex(0)
31 	{
32 	}
33 
34 	GlyphInfo(uint32 charCode, float x, float width, int32 lineIndex)
35 		:
36 		charCode(charCode),
37 		x(x),
38 		width(width),
39 		lineIndex(lineIndex)
40 	{
41 	}
42 
43 	GlyphInfo(const GlyphInfo& other)
44 		:
45 		charCode(other.charCode),
46 		x(other.x),
47 		width(other.width),
48 		lineIndex(other.lineIndex)
49 	{
50 	}
51 
52 	GlyphInfo& operator=(const GlyphInfo& other)
53 	{
54 		charCode = other.charCode;
55 		x = other.x;
56 		width = other.width;
57 		lineIndex = other.lineIndex;
58 		return *this;
59 	}
60 
61 	bool operator==(const GlyphInfo& other) const
62 	{
63 		return charCode == other.charCode
64 			&& x == other.x
65 			&& width == other.width
66 			&& lineIndex == other.lineIndex;
67 	}
68 
69 	bool operator!=(const GlyphInfo& other) const
70 	{
71 		return !(*this == other);
72 	}
73 
74 public:
75 	uint32					charCode;
76 
77 	float					x;
78 	float					width;
79 
80 	int32					lineIndex;
81 };
82 
83 
84 class LineInfo {
85 public:
86 	LineInfo()
87 		:
88 		textOffset(0),
89 		y(0.0f),
90 		height(0.0f),
91 		maxAscent(0.0f),
92 		maxDescent(0.0f),
93 		extraGlyphSpacing(0.0f),
94 		extraWhiteSpacing(0.0f),
95 		layoutedSpans()
96 	{
97 	}
98 
99 	LineInfo(int32 textOffset, float y, float height, float maxAscent,
100 		float maxDescent)
101 		:
102 		textOffset(textOffset),
103 		y(y),
104 		height(height),
105 		maxAscent(maxAscent),
106 		maxDescent(maxDescent),
107 		extraGlyphSpacing(0.0f),
108 		extraWhiteSpacing(0.0f),
109 		layoutedSpans()
110 	{
111 	}
112 
113 	LineInfo(const LineInfo& other)
114 		:
115 		textOffset(other.textOffset),
116 		y(other.y),
117 		height(other.height),
118 		maxAscent(other.maxAscent),
119 		maxDescent(other.maxDescent),
120 		extraGlyphSpacing(other.extraGlyphSpacing),
121 		extraWhiteSpacing(other.extraWhiteSpacing),
122 		layoutedSpans(other.layoutedSpans)
123 	{
124 	}
125 
126 	LineInfo& operator=(const LineInfo& other)
127 	{
128 		textOffset = other.textOffset;
129 		y = other.y;
130 		height = other.height;
131 		maxAscent = other.maxAscent;
132 		maxDescent = other.maxDescent;
133 		extraGlyphSpacing = other.extraGlyphSpacing;
134 		extraWhiteSpacing = other.extraWhiteSpacing;
135 		layoutedSpans = other.layoutedSpans;
136 		return *this;
137 	}
138 
139 	bool operator==(const LineInfo& other) const
140 	{
141 		return textOffset == other.textOffset
142 			&& y == other.y
143 			&& height == other.height
144 			&& maxAscent == other.maxAscent
145 			&& maxDescent == other.maxDescent
146 			&& extraGlyphSpacing == other.extraGlyphSpacing
147 			&& extraWhiteSpacing == other.extraWhiteSpacing
148 			&& layoutedSpans == other.layoutedSpans;
149 	}
150 
151 	bool operator!=(const LineInfo& other) const
152 	{
153 		return !(*this == other);
154 	}
155 
156 public:
157 	int32			textOffset;
158 
159 	float			y;
160 	float			height;
161 
162 	float			maxAscent;
163 	float			maxDescent;
164 
165 	float			extraGlyphSpacing;
166 	float			extraWhiteSpacing;
167 
168 	std::vector<TextSpan>
169 					layoutedSpans;
170 };
171 
172 
173 class ParagraphLayout : public BReferenceable {
174 public:
175 								ParagraphLayout();
176 								ParagraphLayout(const Paragraph& paragraph);
177 								ParagraphLayout(const ParagraphLayout& other);
178 	virtual						~ParagraphLayout();
179 
180 			void				SetParagraph(const Paragraph& paragraph);
181 			const ParagraphStyle& Style() const
182 									{ return fParagraphStyle; }
183 
184 			void				SetWidth(float width);
185 			float				Width() const
186 									{ return fWidth; }
187 
188 			float				Height();
189 			void				Draw(BView* view, const BPoint& offset);
190 
191 			int32				CountGlyphs() const;
192 			int32				CountLines();
193 
194 			int32				LineIndexForOffset(int32 textOffset);
195 			int32				FirstOffsetOnLine(int32 lineIndex);
196 			int32				LastOffsetOnLine(int32 lineIndex);
197 
198 			void				GetLineBounds(int32 lineIndex,
199 									float& x1, float& y1,
200 									float& x2, float& y2);
201 
202 			void				GetTextBounds(int32 textOffset,
203 									float& x1, float& y1,
204 									float& x2, float& y2);
205 
206 			int32				TextOffsetAt(float x, float y,
207 									bool& rightOfCenter);
208 
209 private:
210 			void				_Init();
211 
212 			void				_ValidateLayout();
213 			void				_Layout();
214 			void				_ApplyAlignment();
215 
216 			bool				_AppendGlyphInfos(const TextSpan& span);
217 			bool				_AppendGlyphInfo(uint32 charCode,
218 									float advanceX,
219 									const CharacterStyle& style);
220 
221 			bool				_FinalizeLine(int lineStart, int lineEnd,
222 									int lineIndex, float y, float& lineHeight);
223 
224 			void				_IncludeStyleInLine(LineInfo& line,
225 									const CharacterStyle& style);
226 
227 			void				_DrawLine(BView* view, const BPoint& offset,
228 									const LineInfo& line) const;
229 			void				_DrawSpan(BView* view, BPoint offset,
230 									const TextSpan& span,
231 									int32 textOffset) const;
232 
233 			void				_GetEmptyLayoutBounds(float& x1, float& y1,
234 									float& x2, float& y2) const;
235 
236 			void				_AppendTextSpans(const Paragraph& paragraph);
237 
238 private:
239 			std::vector<TextSpan>
240 								fTextSpans;
241 			ParagraphStyle		fParagraphStyle;
242 
243 			float				fWidth;
244 			bool				fLayoutValid;
245 
246 			std::vector<GlyphInfo>
247 								fGlyphInfos;
248 			std::vector<LineInfo>
249 								fLineInfos;
250 };
251 
252 
253 typedef BReference<ParagraphLayout> ParagraphLayoutRef;
254 
255 
256 #endif // PARAGRAPH_LAYOUT_H
257