00001
00007 #ifndef __MYGUI_TEXT_VIEW_H__
00008 #define __MYGUI_TEXT_VIEW_H__
00009
00010 #include "MyGUI_Prerequest.h"
00011
00012 namespace MyGUI
00013 {
00014
00015 class CharInfo
00016 {
00017 public:
00018 CharInfo() : width(0) { }
00019 CharInfo(const FloatRect& _rect, int _width) : rect(_rect), width(_width) { }
00020 CharInfo(uint32 _colour) : rect(-1, 0, 0, 0), width((int)_colour) { }
00021
00022 bool isColour() const { return rect.left == -1; }
00023 int getWidth() const { return width; }
00024 const FloatRect& getUVRect() const { return rect; }
00025 uint32 getColour() const { return (uint32)width; }
00026
00027 private:
00028 FloatRect rect;
00029 int width;
00030 };
00031
00032 typedef std::vector<CharInfo> VectorCharInfo;
00033
00034 struct LineInfo
00035 {
00036 LineInfo() : width(0), offset(0), count(0) { }
00037 void clear() { width = 0; count = 0; simbols.clear(); offset = 0; }
00038 int width;
00039 int offset;
00040 size_t count;
00041 VectorCharInfo simbols;
00042 };
00043
00044 typedef std::vector<LineInfo> VectorLineInfo;
00045
00046 class RollBackPoint
00047 {
00048 public:
00049 RollBackPoint() :
00050 position(0),
00051 count(0),
00052 lenght(0),
00053 rollback(false)
00054 { }
00055
00056 void set(
00057 size_t _position,
00058 UString::const_iterator& _space_point,
00059 size_t _count,
00060 int _length
00061 )
00062 {
00063 position = _position;
00064 space_point = _space_point;
00065 count = _count;
00066 lenght = _length;
00067 rollback = true;
00068 }
00069
00070 void clear() { rollback = false; }
00071 bool empty() { return !rollback; }
00072 int getLenght() { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return lenght; }
00073 size_t getCount() { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return count; }
00074 size_t getPosition() { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return position; }
00075 UString::const_iterator getTextIter() { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return space_point; }
00076
00077 private:
00078 size_t position;
00079 UString::const_iterator space_point;
00080 size_t count;
00081 int lenght;
00082 bool rollback;
00083 };
00084
00085 MYGUI_FORCEINLINE void ConvertColour(uint32& _colour, VertexColourType _format)
00086 {
00087 if (_format == VertexColourType::ColourABGR)
00088 _colour = ((_colour & 0x00FF0000) >> 16) | ((_colour & 0x000000FF) << 16) | (_colour & 0xFF00FF00);
00089 }
00090
00091 class TextView
00092 {
00093 public:
00094 TextView() :
00095 mLength(0),
00096 mFontHeight(0)
00097 {
00098 }
00099
00100 void update(const UString& _text, IFont* _font, int _height, Align _align, VertexColourType _format, int _maxheight = -1)
00101 {
00102 mFontHeight = _height;
00103
00104
00105 static const char convert_colour[64] = { 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0 };
00106
00107 mViewSize.clear();
00108
00109 RollBackPoint roll_back;
00110 IntSize result;
00111 int width = 0;
00112 size_t count = 0;
00113 mLength = 0;
00114 mLineInfo.clear();
00115 LineInfo line_info;
00116 int font_height = _font->getDefaultHeight();
00117
00118 UString::const_iterator end = _text.end();
00119 UString::const_iterator index = _text.begin();
00120
00121
00122
00123
00124 result.height += _height;
00125
00126 for (; index!=end; ++index)
00127 {
00128 Char character = *index;
00129
00130
00131 if (character == FontCodeType::CR
00132 || character == FontCodeType::NEL
00133 || character == FontCodeType::LF)
00134 {
00135 if (character == FontCodeType::CR)
00136 {
00137 UString::const_iterator peeki = index;
00138 peeki ++;
00139 if ((peeki != end) && (*peeki == FontCodeType::LF))
00140 index = peeki;
00141 }
00142
00143 line_info.width = width;
00144 line_info.count = count;
00145 mLength += line_info.count + 1;
00146
00147 result.height += _height;
00148 if (result.width < width)
00149 result.width = width;
00150 width = 0;
00151 count = 0;
00152
00153 mLineInfo.push_back(line_info);
00154 line_info.clear();
00155
00156
00157 roll_back.clear();
00158
00159 continue;
00160 }
00161
00162 else if (character == L'#')
00163 {
00164
00165 ++ index;
00166 if (index == end) { --index ;continue; }
00167
00168 character = *index;
00169
00170 if (character != L'#')
00171 {
00172
00173 uint32 colour = convert_colour[(character-48) & 0x3F];
00174
00175
00176 for (char i=0; i<5; i++)
00177 {
00178 ++ index;
00179 if (index == end) { --index ;continue; }
00180 colour <<= 4;
00181 colour += convert_colour[ ((*index) - 48) & 0x3F ];
00182 }
00183
00184
00185 ConvertColour(colour, _format);
00186
00187 line_info.simbols.push_back( CharInfo(colour) );
00188
00189 continue;
00190 }
00191 }
00192
00193 GlyphInfo* info = _font->getGlyphInfo(character);
00194 if (FontCodeType::Space == character)
00195 {
00196 roll_back.set(line_info.simbols.size(), index, count, width);
00197 }
00198 else if (FontCodeType::Tab == character)
00199 {
00200 roll_back.set(line_info.simbols.size(), index, count, width);
00201 }
00202
00203 int char_width = info->width;
00204 if (font_height != _height)
00205 {
00206 char_width = char_width * _height / font_height;
00207 if (!char_width) char_width = 1;
00208 }
00209
00210
00211 if (_maxheight != -1
00212 && (width + char_width) > _maxheight
00213 && !roll_back.empty())
00214 {
00215
00216 width = roll_back.getLenght();
00217 count = roll_back.getCount();
00218 index = roll_back.getTextIter();
00219 line_info.simbols.erase(line_info.simbols.begin() + roll_back.getPosition(), line_info.simbols.end());
00220
00221
00222 line_info.width = width;
00223 line_info.count = count;
00224 mLength += line_info.count + 1;
00225
00226 result.height += _height;
00227 if (result.width < width)
00228 result.width = width;
00229 width = 0;
00230 count = 0;
00231
00232 mLineInfo.push_back(line_info);
00233 line_info.clear();
00234
00235
00236 roll_back.clear();
00237
00238 continue;
00239 }
00240
00241 line_info.simbols.push_back(CharInfo(info->uvRect, char_width));
00242 width += char_width;
00243 count ++;
00244 }
00245
00246 line_info.width = width;
00247 line_info.count = count;
00248 mLength += line_info.count;
00249
00250 mLineInfo.push_back(line_info);
00251
00252 if (result.width < width)
00253 result.width = width;
00254
00255
00256 for (VectorLineInfo::iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
00257 {
00258 if (_align.isRight())
00259 line->offset = result.width - line->width;
00260 else if (_align.isHCenter())
00261 line->offset = (result.width - line->width) / 2;
00262 }
00263
00264 mViewSize = result;
00265 }
00266
00267 size_t getCursorPosition(const IntPoint& _value)
00268 {
00269 const int height = mFontHeight;
00270 size_t result = 0;
00271 int top = 0;
00272
00273 for (VectorLineInfo::const_iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
00274 {
00275
00276 bool lastline = !(line + 1 != mLineInfo.end());
00277
00278
00279 if (top + height > _value.top || lastline)
00280 {
00281 top += height;
00282 int left = line->offset;
00283 int count = 0;
00284
00285
00286 for (VectorCharInfo::const_iterator sim=line->simbols.begin(); sim!=line->simbols.end(); ++sim)
00287 {
00288 if (sim->isColour())
00289 continue;
00290
00291 if ((left + (sim->getWidth() / 2)) > _value.left)
00292 {
00293 break;
00294 }
00295 left += sim->getWidth();
00296 count ++;
00297 }
00298
00299 result += count;
00300 break;
00301 }
00302
00303 if (!lastline)
00304 {
00305 top += height;
00306 result += line->count + 1;
00307 }
00308 }
00309
00310 return result;
00311 }
00312
00313 IntPoint getCursorPoint(size_t _position)
00314 {
00315 if (_position >= mLength + 1) _position = mLength;
00316
00317 size_t position = 0;
00318 int top = 0;
00319 int left = 0;
00320 for (VectorLineInfo::const_iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
00321 {
00322 left = line->offset;
00323 if (position + line->count >= _position)
00324 {
00325 for (VectorCharInfo::const_iterator sim=line->simbols.begin(); sim!=line->simbols.end(); ++sim)
00326 {
00327 if (sim->isColour())
00328 continue;
00329
00330 if (position == _position)
00331 break;
00332
00333 position ++;
00334 left += sim->getWidth();
00335 }
00336 break;
00337 }
00338 position += line->count + 1;
00339 top += mFontHeight;
00340 }
00341
00342 return IntPoint(left, top);
00343 }
00344
00345 const IntSize& getViewSize() { return mViewSize; }
00346 size_t getTextLength() { return mLength; }
00347 const VectorLineInfo& getData() { return mLineInfo; }
00348
00349 private:
00350 IntSize mViewSize;
00351 size_t mLength;
00352 VectorLineInfo mLineInfo;
00353 int mFontHeight;
00354 };
00355
00356
00357 }
00358
00359 #endif // __MYGUI_TEXT_VIEW_H__