MyGUI 3.4.2
MyGUI_TextView.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
8#include "MyGUI_TextView.h"
9
10namespace MyGUI
11{
12
13 namespace
14 {
15
16 template<typename T>
17 void setMin(T& _var, const T& _newValue)
18 {
19 if (_newValue < _var)
20 _var = _newValue;
21 }
22
23 template<typename T>
24 void setMax(T& _var, const T& _newValue)
25 {
26 if (_var < _newValue)
27 _var = _newValue;
28 }
29
30 }
31
32 class RollBackPoint
33 {
34 public:
35 RollBackPoint() :
36 position(0),
37 count(0),
38 width(0),
39 rollback(false)
40 {
41 }
42
43 void set(size_t _position, const UString::utf32string::const_iterator& _space_point, size_t _count, float _width)
44 {
45 position = _position;
46 space_point = _space_point;
47 count = _count;
48 width = _width;
49 rollback = true;
50 }
51
52 void clear()
53 {
54 rollback = false;
55 }
56
57 bool empty() const
58 {
59 return !rollback;
60 }
61
62 float getWidth() const
63 {
64 MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
65 return width;
66 }
67
68 size_t getCount() const
69 {
70 MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
71 return count;
72 }
73
74 size_t getPosition() const
75 {
76 MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
77 return position;
78 }
79
80 UString::utf32string::const_iterator getTextIter() const
81 {
82 MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
83 return space_point;
84 }
85
86 private:
87 size_t position;
88 UString::utf32string::const_iterator space_point;
89 size_t count;
90 float width;
91 bool rollback;
92 };
93
95 mLength(0),
96 mFontHeight(0)
97 {
98 }
99
101 {
102 mFontHeight = _height;
103
104 // массив для быстрой конвертации цветов
105 static const char convert_colour[64] =
106 {
107 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
108 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0
111 };
112
113 mViewSize.clear();
114
115 RollBackPoint roll_back;
117 float width = 0.0f;
118 size_t count = 0;
119 mLength = 0;
120 mLineInfo.clear();
122 int font_height = _font->getDefaultHeight();
123
124 UString::utf32string::const_iterator end = _text.end();
125 UString::utf32string::const_iterator index = _text.begin();
126
127 /*if (index == end)
128 return;*/
129
130 result.height += _height;
131
132 for (; index != end; ++index)
133 {
134 Char character = *index;
135
136 // new line
140 {
142 {
143 UString::utf32string::const_iterator peeki = index;
144 ++peeki;
145 if ((peeki != end) && (*peeki == FontCodeType::LF))
146 index = peeki; // skip both as one newline
147 }
148
149 line_info.width = (int)std::ceil(width);
150 line_info.count = count;
151 mLength += line_info.count + 1;
152
153 result.height += _height;
154 setMax(result.width, line_info.width);
155 width = 0;
156 count = 0;
157
158 mLineInfo.push_back(line_info);
159 line_info.clear();
160
161 roll_back.clear();
162
163 continue;
164 }
165 // tag
166 else if (character == L'#')
167 {
168 // check next character
169 ++index;
170 if (index == end)
171 {
172 --index;
173 continue;
174 }
175
176 character = *index;
177 // "##" converted to visible '#', change colour otherwise
178 if (character != L'#')
179 {
180 // read first character
181 uint32 colour = convert_colour[(character - 48) & 0x3F];
182
183 // and 5 more after '#'
184 for (char i = 0; i < 5; i++)
185 {
186 ++ index;
187 if (index == end)
188 {
189 --index;
190 continue;
191 }
192 colour <<= 4;
193 colour += convert_colour[ ((*index) - 48) & 0x3F ];
194 }
195
196 // convert to ABGR if we use that colour format
198
199 line_info.symbols.push_back( CharInfo(colour) );
200
201 continue;
202 }
203 }
204
205 const GlyphInfo* info = _font->getGlyphInfo(character);
206
207 if (info == nullptr)
208 continue;
209
211 {
212 roll_back.set(line_info.symbols.size(), index, count, width);
213 }
214
215 float char_width = info->width;
216 float char_height = info->height;
217 float char_advance = info->advance;
218 float char_bearingX = info->bearingX;
219 float char_bearingY = info->bearingY;
220
221 if (_height != font_height)
222 {
223 float scale = (float)_height / font_height;
224
225 char_width *= scale;
230 }
231
233
234 // перенос слов
235 if (_maxWidth != -1
236 && (width + char_fullAdvance) > _maxWidth
237 && !roll_back.empty())
238 {
239 // откатываем до последнего пробела
240 width = roll_back.getWidth();
241 count = roll_back.getCount();
242 index = roll_back.getTextIter();
243 line_info.symbols.erase(line_info.symbols.begin() + roll_back.getPosition(), line_info.symbols.end());
244
245 // запоминаем место отката, как полную строку
246 line_info.width = (int)std::ceil(width);
247 line_info.count = count;
248 mLength += line_info.count + 1;
249
250 result.height += _height;
251 setMax(result.width, line_info.width);
252 width = 0;
253 count = 0;
254
255 mLineInfo.push_back(line_info);
256 line_info.clear();
257
258 // отменяем откат
259 roll_back.clear();
260
261 continue;
262 }
263
265 width += char_fullAdvance;
266 count ++;
267 }
268
269 line_info.width = (int)std::ceil(width);
270 line_info.count = count;
271 mLength += line_info.count;
272
273 mLineInfo.push_back(line_info);
274
275 setMax(result.width, line_info.width);
276
277 // теперь выравниванием строки
278 for (VectorLineInfo::iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
279 {
280 if (_align.isRight())
281 line->offset = result.width - line->width;
282 else if (_align.isHCenter())
283 line->offset = (result.width - line->width) / 2;
284 }
285
286 mViewSize = result;
287 }
288
290 {
291 size_t result = 0;
292 int top = 0;
293
294 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
295 {
296 bool lastline = line + 1 == mLineInfo.end();
297
298 // наша строчка
299 if (top + mFontHeight <= _value.top && !lastline)
300 {
301 top += mFontHeight;
302 result += line->count + 1;
303 }
304 else
305 {
306 float left = (float)line->offset;
307 int count = 0;
308
309 // ищем символ
310 for (const auto& sim : line->symbols)
311 {
312 if (sim.isColour())
313 continue;
314
315 float fullAdvance = sim.getAdvance() + sim.getBearingX();
316 if (left + fullAdvance / 2.0f > _value.left)
317 {
318 break;
319 }
320 left += fullAdvance;
321 count ++;
322 }
323
324 result += count;
325 break;
326 }
327 }
328
329 return result;
330 }
331
333 {
334 setMin(_position, mLength);
335
336 size_t position = 0;
337 int top = 0;
338 float left = 0.0f;
339 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
340 {
341 left = (float)line->offset;
342 if (position + line->count >= _position)
343 {
344 for (VectorCharInfo::const_iterator sim = line->symbols.begin(); sim != line->symbols.end(); ++sim)
345 {
346 if (sim->isColour())
347 continue;
348
349 if (position == _position)
350 break;
351
352 position ++;
353 left += sim->getBearingX() + sim->getAdvance();
354 }
355 break;
356 }
357 position += line->count + 1;
358 top += mFontHeight;
359 }
360
361 return IntPoint((int)left, top);
362 }
363
365 {
366 return mViewSize;
367 }
368
370 {
371 return mLength;
372 }
373
375 {
376 return mLineInfo;
377 }
378
379} // namespace MyGUI
#define MYGUI_DEBUG_ASSERT(exp, dest)
size_t getCursorPosition(const IntPoint &_value) const
IntPoint getCursorPoint(size_t _position) const
size_t getTextLength() const
void update(const UString::utf32string &_text, IFont *_font, int _height, Align _align, VertexColourType _format, int _maxWidth=-1)
const VectorLineInfo & getData() const
const IntSize & getViewSize() const
std::basic_string< unicode_char > utf32string
string type used for returning UTF-32 formatted data
void convertColour(uint32 &_colour, VertexColourType _format)
Convert from 32-bit ARGB to native colour (ABGR or ARGB)
std::vector< LineInfo > VectorLineInfo
types::TPoint< int > IntPoint
Definition MyGUI_Types.h:27