MyGUI 3.0.1

MyGUI_TextView.h

Go to the documentation of this file.
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             /*if (index == end)
00121                 return;*/
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; // skip both as one newline
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 } // namespace MyGUI
00357 
00358 #endif // __MYGUI_TEXT_VIEW_H__
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines