mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 10:23:51 +00:00
358 lines
8.2 KiB
C++
358 lines
8.2 KiB
C++
/*!
|
||
@file
|
||
@author Albert Semenov
|
||
@date 09/2009
|
||
@module
|
||
*/
|
||
#ifndef __MYGUI_TEXT_VIEW_H__
|
||
#define __MYGUI_TEXT_VIEW_H__
|
||
|
||
#include "MyGUI_Prerequest.h"
|
||
#include "MyGUI_TextureUtility.h"
|
||
|
||
namespace MyGUI
|
||
{
|
||
|
||
class CharInfo
|
||
{
|
||
public:
|
||
CharInfo() : width(0) { }
|
||
CharInfo(const FloatRect& _rect, int _width) : rect(_rect), width(_width) { }
|
||
CharInfo(uint32 _colour) : rect(-1, 0, 0, 0), width((int)_colour) { }
|
||
|
||
bool isColour() const { return rect.left == -1; }
|
||
int getWidth() const { return width; }
|
||
const FloatRect& getUVRect() const { return rect; }
|
||
uint32 getColour() const { return (uint32)width; }
|
||
|
||
private:
|
||
FloatRect rect;
|
||
int width;
|
||
};
|
||
|
||
typedef std::vector<CharInfo> VectorCharInfo;
|
||
|
||
struct LineInfo
|
||
{
|
||
LineInfo() : width(0), offset(0), count(0) { }
|
||
void clear() { width = 0; count = 0; simbols.clear(); offset = 0; }
|
||
int width;
|
||
int offset;
|
||
size_t count;
|
||
VectorCharInfo simbols;
|
||
};
|
||
|
||
typedef std::vector<LineInfo> VectorLineInfo;
|
||
|
||
class RollBackPoint
|
||
{
|
||
public:
|
||
RollBackPoint() :
|
||
position(0),
|
||
count(0),
|
||
lenght(0),
|
||
rollback(false)
|
||
{ }
|
||
|
||
void set(
|
||
size_t _position,
|
||
UString::const_iterator& _space_point,
|
||
size_t _count,
|
||
int _length
|
||
)
|
||
{
|
||
position = _position;
|
||
space_point = _space_point;
|
||
count = _count;
|
||
lenght = _length;
|
||
rollback = true;
|
||
}
|
||
|
||
void clear() { rollback = false; }
|
||
bool empty() const { return !rollback; }
|
||
int getLenght() const { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return lenght; }
|
||
size_t getCount() const { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return count; }
|
||
size_t getPosition() const { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return position; }
|
||
UString::const_iterator getTextIter() { MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid"); return space_point; }
|
||
|
||
private:
|
||
size_t position;
|
||
UString::const_iterator space_point;
|
||
size_t count;
|
||
int lenght;
|
||
bool rollback;
|
||
};
|
||
|
||
class TextView
|
||
{
|
||
public:
|
||
TextView() :
|
||
mLength(0),
|
||
mFontHeight(0)
|
||
{
|
||
}
|
||
|
||
void update(const UString& _text, IFont* _font, int _height, Align _align, VertexColourType _format, int _maxheight = -1)
|
||
{
|
||
mFontHeight = _height;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
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
|
||
};
|
||
|
||
mViewSize.clear();
|
||
|
||
RollBackPoint roll_back;
|
||
IntSize result;
|
||
int width = 0;
|
||
size_t count = 0;
|
||
mLength = 0;
|
||
mLineInfo.clear();
|
||
LineInfo line_info;
|
||
int font_height = _font->getDefaultHeight();
|
||
|
||
UString::const_iterator end = _text.end();
|
||
UString::const_iterator index = _text.begin();
|
||
|
||
/*if (index == end)
|
||
return;*/
|
||
|
||
result.height += _height;
|
||
|
||
for (; index!=end; ++index)
|
||
{
|
||
Char character = *index;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (character == FontCodeType::CR
|
||
|| character == FontCodeType::NEL
|
||
|| character == FontCodeType::LF)
|
||
{
|
||
if (character == FontCodeType::CR)
|
||
{
|
||
UString::const_iterator peeki = index;
|
||
peeki ++;
|
||
if ((peeki != end) && (*peeki == FontCodeType::LF))
|
||
index = peeki; // skip both as one newline
|
||
}
|
||
|
||
line_info.width = width;
|
||
line_info.count = count;
|
||
mLength += line_info.count + 1;
|
||
|
||
result.height += _height;
|
||
if (result.width < width)
|
||
result.width = width;
|
||
width = 0;
|
||
count = 0;
|
||
|
||
mLineInfo.push_back(line_info);
|
||
line_info.clear();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
roll_back.clear();
|
||
|
||
continue;
|
||
}
|
||
// <20><><EFBFBD>
|
||
else if (character == L'#')
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
++ index;
|
||
if (index == end) { --index; continue; } // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
character = *index;
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if (character != L'#')
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
uint32 colour = convert_colour[(character-48) & 0x3F];
|
||
|
||
// <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
for (char i=0; i<5; i++)
|
||
{
|
||
++ index;
|
||
if (index == end) { --index; continue; } // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
colour <<= 4;
|
||
colour += convert_colour[ ((*index) - 48) & 0x3F ];
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
texture_utility::convertColour(colour, _format);
|
||
|
||
line_info.simbols.push_back( CharInfo(colour) );
|
||
|
||
continue;
|
||
}
|
||
}
|
||
|
||
GlyphInfo* info = _font->getGlyphInfo(character);
|
||
if (FontCodeType::Space == character)
|
||
{
|
||
roll_back.set(line_info.simbols.size(), index, count, width);
|
||
}
|
||
else if (FontCodeType::Tab == character)
|
||
{
|
||
roll_back.set(line_info.simbols.size(), index, count, width);
|
||
}
|
||
|
||
int char_width = info->width;
|
||
if (font_height != _height)
|
||
{
|
||
char_width = char_width * _height / font_height;
|
||
if (!char_width) char_width = 1;
|
||
}
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
||
if (_maxheight != -1
|
||
&& (width + char_width) > _maxheight
|
||
&& !roll_back.empty())
|
||
{
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
width = roll_back.getLenght();
|
||
count = roll_back.getCount();
|
||
index = roll_back.getTextIter();
|
||
line_info.simbols.erase(line_info.simbols.begin() + roll_back.getPosition(), line_info.simbols.end());
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
line_info.width = width;
|
||
line_info.count = count;
|
||
mLength += line_info.count + 1;
|
||
|
||
result.height += _height;
|
||
if (result.width < width)
|
||
result.width = width;
|
||
width = 0;
|
||
count = 0;
|
||
|
||
mLineInfo.push_back(line_info);
|
||
line_info.clear();
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||
roll_back.clear();
|
||
|
||
continue;
|
||
}
|
||
|
||
line_info.simbols.push_back(CharInfo(info->uvRect, char_width));
|
||
width += char_width;
|
||
count ++;
|
||
}
|
||
|
||
line_info.width = width;
|
||
line_info.count = count;
|
||
mLength += line_info.count;
|
||
|
||
mLineInfo.push_back(line_info);
|
||
|
||
if (result.width < width)
|
||
result.width = width;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
for (VectorLineInfo::iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
|
||
{
|
||
if (_align.isRight())
|
||
line->offset = result.width - line->width;
|
||
else if (_align.isHCenter())
|
||
line->offset = (result.width - line->width) / 2;
|
||
}
|
||
|
||
mViewSize = result;
|
||
}
|
||
|
||
size_t getCursorPosition(const IntPoint& _value)
|
||
{
|
||
const int height = mFontHeight;
|
||
size_t result = 0;
|
||
int top = 0;
|
||
|
||
for (VectorLineInfo::const_iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
|
||
{
|
||
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
bool lastline = !(line + 1 != mLineInfo.end());
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
if (top + height > _value.top || lastline)
|
||
{
|
||
top += height;
|
||
int left = line->offset;
|
||
int count = 0;
|
||
|
||
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
for (VectorCharInfo::const_iterator sim=line->simbols.begin(); sim!=line->simbols.end(); ++sim)
|
||
{
|
||
if (sim->isColour())
|
||
continue;
|
||
|
||
if ((left + (sim->getWidth() / 2)) > _value.left)
|
||
{
|
||
break;
|
||
}
|
||
left += sim->getWidth();
|
||
count ++;
|
||
}
|
||
|
||
result += count;
|
||
break;
|
||
}
|
||
|
||
if (!lastline)
|
||
{
|
||
top += height;
|
||
result += line->count + 1;
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
IntPoint getCursorPoint(size_t _position)
|
||
{
|
||
if (_position >= mLength + 1) _position = mLength;
|
||
|
||
size_t position = 0;
|
||
int top = 0;
|
||
int left = 0;
|
||
for (VectorLineInfo::const_iterator line=mLineInfo.begin(); line!=mLineInfo.end(); ++line)
|
||
{
|
||
left = line->offset;
|
||
if (position + line->count >= _position)
|
||
{
|
||
for (VectorCharInfo::const_iterator sim=line->simbols.begin(); sim!=line->simbols.end(); ++sim)
|
||
{
|
||
if (sim->isColour())
|
||
continue;
|
||
|
||
if (position == _position)
|
||
break;
|
||
|
||
position ++;
|
||
left += sim->getWidth();
|
||
}
|
||
break;
|
||
}
|
||
position += line->count + 1;
|
||
top += mFontHeight;
|
||
}
|
||
|
||
return IntPoint(left, top);
|
||
}
|
||
|
||
const IntSize& getViewSize() const { return mViewSize; }
|
||
size_t getTextLength() const { return mLength; }
|
||
const VectorLineInfo& getData() { return mLineInfo; }
|
||
|
||
private:
|
||
IntSize mViewSize;
|
||
size_t mLength;
|
||
VectorLineInfo mLineInfo;
|
||
int mFontHeight;
|
||
};
|
||
|
||
|
||
} // namespace MyGUI
|
||
|
||
#endif // __MYGUI_TEXT_VIEW_H__
|