MyGUI: MyGUI_TextView.cpp Source File

MyGUI 3.2.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
10 namespace 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, UString::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::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::const_iterator space_point;
89 size_t count;
90 float width;
91 bool rollback;
92 };
93
94 TextView::TextView() :
95 mLength(0),
96 mFontHeight(0)
97 {
98 }
99
100 void TextView::update(const UString& _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::const_iterator end = _text.end();
125 UString::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::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)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.simbols.push_back( CharInfo(colour) );
201
202 continue;
203 }
204 }
205
206 GlyphInfo* info = _font->getGlyphInfo(character);
207
208 if (info == nullptr)
209 continue;
210
211 if (FontCodeType::Space == character)
212 {
213 roll_back.set(line_info.simbols.size(), index, count, width);
214 }
215 else if (FontCodeType::Tab == character)
216 {
217 roll_back.set(line_info.simbols.size(), index, count, width);
218 }
219
220 float char_width = info->width;
221 float char_height = info->height;
222 float char_advance = info->advance;
223 float char_bearingX = info->bearingX;
224 float char_bearingY = info->bearingY;
225
226 if (_height != font_height)
227 {
228 float scale = (float)_height / font_height;
229
230 char_width *= scale;
231 char_height *= scale;
232 char_advance *= scale;
233 char_bearingX *= scale;
234 char_bearingY *= scale;
235 }
236
237 float char_fullAdvance = char_bearingX + char_advance;
238
239 // перенос слов
240 if (_maxWidth != -1
241 && (width + char_fullAdvance) > _maxWidth
242 && !roll_back.empty())
243 {
244 // откатываем до последнего пробела
245 width = roll_back.getWidth();
246 count = roll_back.getCount();
247 index = roll_back.getTextIter();
248 line_info.simbols.erase(line_info.simbols.begin() + roll_back.getPosition(), line_info.simbols.end());
249
250 // запоминаем место отката, как полную строку
251 line_info.width = (int)ceil(width);
252 line_info.count = count;
253 mLength += line_info.count + 1;
254
255 result.height += _height;
256 setMax(result.width, line_info.width);
257 width = 0;
258 count = 0;
259
260 mLineInfo.push_back(line_info);
261 line_info.clear();
262
263 // отменяем откат
264 roll_back.clear();
265
266 continue;
267 }
268
269 line_info.simbols.push_back(CharInfo(info->uvRect, char_width, char_height, char_advance, char_bearingX, char_bearingY));
270 width += char_fullAdvance;
271 count ++;
272 }
273
274 line_info.width = (int)ceil(width);
275 line_info.count = count;
276 mLength += line_info.count;
277
278 mLineInfo.push_back(line_info);
279
280 setMax(result.width, line_info.width);
281
282 // теперь выравниванием строки
283 for (VectorLineInfo::iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
284 {
285 if (_align.isRight())
286 line->offset = result.width - line->width;
287 else if (_align.isHCenter())
288 line->offset = (result.width - line->width) / 2;
289 }
290
291 mViewSize = result;
292 }
293
294 size_t TextView::getCursorPosition(const IntPoint& _value)
295 {
296 const int height = mFontHeight;
297 size_t result = 0;
298 int top = 0;
299
300 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
301 {
302 // это последняя строка
303 bool lastline = !(line + 1 != mLineInfo.end());
304
305 // наша строчка
306 if (top + height > _value.top || lastline)
307 {
308 top += height;
309 float left = (float)line->offset;
310 int count = 0;
311
312 // ищем символ
313 for (VectorCharInfo::const_iterator sim = line->simbols.begin(); sim != line->simbols.end(); ++sim)
314 {
315 if (sim->isColour())
316 continue;
317
318 float fullAdvance = sim->getAdvance() + sim->getBearingX();
319 if (left + fullAdvance / 2.0f > _value.left)
320 {
321 break;
322 }
323 left += fullAdvance;
324 count ++;
325 }
326
327 result += count;
328 break;
329 }
330
331 if (!lastline)
332 {
333 top += height;
334 result += line->count + 1;
335 }
336 }
337
338 return result;
339 }
340
341 IntPoint TextView::getCursorPoint(size_t _position)
342 {
343 setMin(_position, mLength);
344
345 size_t position = 0;
346 int top = 0;
347 float left = 0.0f;
348 for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
349 {
350 left = (float)line->offset;
351 if (position + line->count >= _position)
352 {
353 for (VectorCharInfo::const_iterator sim = line->simbols.begin(); sim != line->simbols.end(); ++sim)
354 {
355 if (sim->isColour())
356 continue;
357
358 if (position == _position)
359 break;
360
361 position ++;
362 left += sim->getBearingX() + sim->getAdvance();
363 }
364 break;
365 }
366 position += line->count + 1;
367 top += mFontHeight;
368 }
369
370 return IntPoint((int)left, top);
371 }
372
373 const IntSize& TextView::getViewSize() const
374 {
375 return mViewSize;
376 }
377
378 size_t TextView::getTextLength() const
379 {
380 return mLength;
381 }
382
383 const VectorLineInfo& TextView::getData() const
384 {
385 return mLineInfo;
386 }
387
388 } // namespace MyGUI
MyGUI::TextView::getViewSize
const IntSize & getViewSize() const
Definition: MyGUI_TextView.cpp:373
MyGUI::GlyphInfo::advance
float advance
Definition: MyGUI_FontData.h:61
MyGUI::Align::isHCenter
bool isHCenter() const
Definition: MyGUI_Align.h:44
MyGUI::types::TSize::height
T height
Definition: MyGUI_TSize.h:21
MyGUI::TextView::update
void update(const UString &_text, IFont *_font, int _height, Align _align, VertexColourType _format, int _maxWidth=-1)
Definition: MyGUI_TextView.cpp:100
MyGUI::LineInfo::width
int width
Definition: MyGUI_TextViewData.h:131
MyGUI::GlyphInfo::bearingX
float bearingX
Definition: MyGUI_FontData.h:62
MyGUI::IFont::getGlyphInfo
virtual GlyphInfo * getGlyphInfo(Char _id)=0
MyGUI::types::TPoint::top
T top
Definition: MyGUI_TPoint.h:21
MyGUI::FontCodeType::Tab
Definition: MyGUI_FontData.h:20
MyGUI::types::TPoint< int >
MyGUI::UString::begin
iterator begin()
returns an iterator to the first element of the string
Definition: MyGUI_UString.cpp:787
MyGUI::LineInfo::simbols
VectorCharInfo simbols
Definition: MyGUI_TextViewData.h:134
MyGUI::types::TSize::width
T width
Definition: MyGUI_TSize.h:20
MyGUI::LineInfo::clear
void clear()
Definition: MyGUI_TextViewData.h:123
MyGUI::Align
Definition: MyGUI_Align.h:19
MyGUI::UString::const_iterator
_const_fwd_iterator const_iterator
const iterator
Definition: MyGUI_UString.h:434
MyGUI::TextView::getData
const VectorLineInfo & getData() const
Definition: MyGUI_TextView.cpp:383
MyGUI::TextView::TextView
TextView()
Definition: MyGUI_TextView.cpp:94
MyGUI::LineInfo::count
size_t count
Definition: MyGUI_TextViewData.h:133
MyGUI::uint32
unsigned int uint32
Definition: MyGUI_Types.h:48
MyGUI::FontCodeType::CR
Definition: MyGUI_FontData.h:22
MyGUI::GlyphInfo::uvRect
FloatRect uvRect
Definition: MyGUI_FontData.h:64
MyGUI::UString
A UTF-16 string with implicit conversion to/from std::string and std::wstring.
Definition: MyGUI_UString.h:168
MyGUI_Precompiled.h
MyGUI::GlyphInfo
Definition: MyGUI_FontData.h:38
MyGUI::UString::_const_fwd_iterator
const forward iterator for UString
Definition: MyGUI_UString.h:289
MyGUI::IntPoint
types::TPoint< int > IntPoint
Definition: MyGUI_Types.h:26
MyGUI::types::TPoint::left
T left
Definition: MyGUI_TPoint.h:20
MyGUI::IFont
Definition: MyGUI_IFont.h:20
MyGUI::FontCodeType::Space
Definition: MyGUI_FontData.h:23
MyGUI::types::TSize::clear
void clear()
Definition: MyGUI_TSize.h:90
MyGUI::texture_utility::convertColour
__inline void convertColour(uint32 &_colour, VertexColourType _format)
Definition: MyGUI_TextureUtility.h:23
MyGUI::VertexColourType
Definition: MyGUI_RenderFormat.h:15
MyGUI::types::TSize< int >
MyGUI::TextView::getCursorPosition
size_t getCursorPosition(const IntPoint &_value)
Definition: MyGUI_TextView.cpp:294
MyGUI::IFont::getDefaultHeight
virtual int getDefaultHeight()=0
MyGUI::Align::isRight
bool isRight() const
Definition: MyGUI_Align.h:64
MyGUI::TextView::getCursorPoint
IntPoint getCursorPoint(size_t _position)
Definition: MyGUI_TextView.cpp:341
MyGUI::Char
unsigned int Char
Definition: MyGUI_Types.h:51
MyGUI::GlyphInfo::height
float height
Definition: MyGUI_FontData.h:60
MyGUI::VectorLineInfo
std::vector< LineInfo > VectorLineInfo
Definition: MyGUI_TextViewData.h:137
MyGUI::GlyphInfo::bearingY
float bearingY
Definition: MyGUI_FontData.h:63
MyGUI::GlyphInfo::width
float width
Definition: MyGUI_FontData.h:59
MyGUI
Definition: MyGUI_ActionController.h:14
MyGUI::UString::end
iterator end()
returns an iterator just past the end of the string
Definition: MyGUI_UString.cpp:803
MYGUI_DEBUG_ASSERT
#define MYGUI_DEBUG_ASSERT(exp, dest)
Definition: MyGUI_Diagnostic.h:67
MyGUI::CharInfo
Definition: MyGUI_TextViewData.h:15
MyGUI::FontCodeType::NEL
Definition: MyGUI_FontData.h:24
MyGUI::LineInfo
Definition: MyGUI_TextViewData.h:114
MyGUI::TextView::getTextLength
size_t getTextLength() const
Definition: MyGUI_TextView.cpp:378
MyGUI::FontCodeType::LF
Definition: MyGUI_FontData.h:21
MyGUI_TextView.h