• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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 
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             /*if (index == end)
00122                 return;*/
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; // skip both as one newline
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 } // namespace MyGUI
00358 
00359 #endif // __MYGUI_TEXT_VIEW_H__

Generated on Sun Jan 30 2011 for MyGUI by  doxygen 1.7.1