MyGUI 3.4.1
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
100 void TextView::update(const UString::utf32string& _text, IFont* _font, int _height, Align _align, VertexColourType _format, int _maxWidth)
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;
116 IntSize result;
117 float width = 0.0f;
118 size_t count = 0;
119 mLength = 0;
120 mLineInfo.clear();
121 LineInfo line_info;
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 // новая строка
137 if (character == FontCodeType::CR
138 || character == FontCodeType::NEL
139 || character == FontCodeType::LF)
140 {
141 if (character == FontCodeType::CR)
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 // отменяем откат
162 roll_back.clear();
163
164 continue;
165 }
166 // тег
167 else if (character == L'#')
168 {
169 // берем следующий символ
170 ++ index;
171 if (index == end)
172 {
173 --index; // это защита
174 continue;
175 }
176
177 character = *index;
178 // если два подряд, то рисуем один шарп, если нет то меняем цвет
179 if (character != L'#')
180 {
181 // парсим первый символ
182 uint32 colour = convert_colour[(character - 48) & 0x3F];
183
184 // и еще пять символов после шарпа
185 for (char i = 0; i < 5; i++)
186 {
187 ++ index;
188 if (index == end)
189 {
190 --index; // это защита
191 continue;
192 }
193 colour <<= 4;
194 colour += convert_colour[ ((*index) - 48) & 0x3F ];
195 }
196
197 // если нужно, то меняем красный и синий компоненты
198 texture_utility::convertColour(colour, _format);
199
200 line_info.symbols.push_back( CharInfo(colour) );
201
202 continue;
203 }
204 }
205
206 const GlyphInfo* info = _font->getGlyphInfo(character);
207
208 if (info == nullptr)
209 continue;
210
211 if (FontCodeType::Space == character || FontCodeType::Tab == character)
212 {
213 roll_back.set(line_info.symbols.size(), index, count, width);
214 }
215
216 float char_width = info->width;
217 float char_height = info->height;
218 float char_advance = info->advance;
219 float char_bearingX = info->bearingX;
220 float char_bearingY = info->bearingY;
221
222 if (_height != font_height)
223 {
224 float scale = (float)_height / font_height;
225
226 char_width *= scale;
227 char_height *= scale;
228 char_advance *= scale;
229 char_bearingX *= scale;
230 char_bearingY *= scale;
231 }
232
233 float char_fullAdvance = char_bearingX + char_advance;
234
235 // перенос слов
236 if (_maxWidth != -1
237 && (width + char_fullAdvance) > _maxWidth
238 && !roll_back.empty())
239 {
240 // откатываем до последнего пробела
241 width = roll_back.getWidth();
242 count = roll_back.getCount();
243 index = roll_back.getTextIter();
244 line_info.symbols.erase(line_info.symbols.begin() + roll_back.getPosition(), line_info.symbols.end());
245
246 // запоминаем место отката, как полную строку
247 line_info.width = (int)std::ceil(width);
248 line_info.count = count;
249 mLength += line_info.count + 1;
250
251 result.height += _height;
252 setMax(result.width, line_info.width);
253 width = 0;
254 count = 0;
255
256 mLineInfo.push_back(line_info);
257 line_info.clear();
258
259 // отменяем откат
260 roll_back.clear();
261
262 continue;
263 }
264
265 line_info.symbols.push_back(CharInfo(info->uvRect, char_width, char_height, char_advance, char_bearingX, char_bearingY));
266 width += char_fullAdvance;
267 count ++;
268 }
269
270 line_info.width = (int)std::ceil(width);
271 line_info.count = count;
272 mLength += line_info.count;
273
274 mLineInfo.push_back(line_info);
275
276 setMax(result.width, line_info.width);
277
278 // теперь выравниванием строки
279 for (VectorLineInfo::iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
280 {
281 if (_align.isRight())
282 line->offset = result.width - line->width;
283 else if (_align.isHCenter())
284 line->offset = (result.width - line->width) / 2;
285 }
286
287 mViewSize = result;
288 }
289
290 size_t TextView::getCursorPosition(const IntPoint& _value) const
291 {
292 size_t result = 0;
293 int top = 0;
294
295 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
296 {
297 bool lastline = line + 1 == mLineInfo.end();
298
299 // наша строчка
300 if (top + mFontHeight <= _value.top && !lastline)
301 {
302 top += mFontHeight;
303 result += line->count + 1;
304 }
305 else
306 {
307 float left = (float)line->offset;
308 int count = 0;
309
310 // ищем символ
311 for (const auto& sim : line->symbols)
312 {
313 if (sim.isColour())
314 continue;
315
316 float fullAdvance = sim.getAdvance() + sim.getBearingX();
317 if (left + fullAdvance / 2.0f > _value.left)
318 {
319 break;
320 }
321 left += fullAdvance;
322 count ++;
323 }
324
325 result += count;
326 break;
327 }
328 }
329
330 return result;
331 }
332
333 IntPoint TextView::getCursorPoint(size_t _position) const
334 {
335 setMin(_position, mLength);
336
337 size_t position = 0;
338 int top = 0;
339 float left = 0.0f;
340 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
341 {
342 left = (float)line->offset;
343 if (position + line->count >= _position)
344 {
345 for (VectorCharInfo::const_iterator sim = line->symbols.begin(); sim != line->symbols.end(); ++sim)
346 {
347 if (sim->isColour())
348 continue;
349
350 if (position == _position)
351 break;
352
353 position ++;
354 left += sim->getBearingX() + sim->getAdvance();
355 }
356 break;
357 }
358 position += line->count + 1;
359 top += mFontHeight;
360 }
361
362 return IntPoint((int)left, top);
363 }
364
366 {
367 return mViewSize;
368 }
369
371 {
372 return mLength;
373 }
374
376 {
377 return mLineInfo;
378 }
379
380} // namespace MyGUI
#define MYGUI_DEBUG_ASSERT(exp, dest)
virtual int getDefaultHeight() const =0
virtual const GlyphInfo * getGlyphInfo(Char _id) const =0
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)
std::vector< LineInfo > VectorLineInfo
types::TPoint< int > IntPoint
Definition: MyGUI_Types.h:26
unsigned int Char
Definition: MyGUI_Types.h:49
uint32_t uint32
Definition: MyGUI_Types.h:47
bool isRight() const
Definition: MyGUI_Align.h:64
bool isHCenter() const
Definition: MyGUI_Align.h:44
VectorCharInfo symbols