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