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