首先谢谢这位兄台给了一个思路。
http://blog.youkuaiyun.com/cparent/article/details/8230304?reload#cpp
但是这个有点问题,选中的区域有问题。
我这里是直接使用他的类似:
[code=C/C++]
<pre class="cpp" name="code"> if (FontCodeType::Space == character)
{
roll_back.set(line_info.simbols.size(), index, count, width);
}
[/code]
的方法来达到换行目的。在
[code=C/C++]
if(_maxWidth != -1
&& (width + char_fullAdvance) > _maxWidth)
[/code]
这里加上换行标示,就可以了。但是由于这时候长度已经大于了,所以这个标示应该加在当前字符的前面。
找到前一个地点加换行。
现在逻辑是对的,但是选中的索引还有问题。
在MyGUI_EditText.cpp里
void EditText::doRender()
原来每行都会把索引++。这里注释掉去掉。
MyGUI_TextView.cpp
里把回车加上一个虚的符号。
[code=C/C++]
line_info.simbols.push_back(CharInfo());
[/code]
如下:
[code=C/C++]
void TextView::update(const UString& _text, IFont* _font, int _height, Align _align, VertexColourType _format, int _maxWidth)
{
mFontHeight = _height;
// массив для быстрой конвертации цветов
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;
float width = 0.0f;
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;
// новая строка
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 = (int)ceil(width);
line_info.count = count;
mLength += line_info.count + 1;
result.height += _height;
setMax(result.width, line_info.width);
width = 0;
count = 0;
<span style="color:#ff0000;">line_info.simbols.push_back(CharInfo());
</span> mLineInfo.push_back(line_info);
line_info.clear();
// отменяем откат
roll_back.clear();
continue;
}
// тег
else if (character == L'#')
{
// берем следующий символ
++ index;
if (index == end)
{
--index; // это защита
continue;
}
character = *index;
// если два подряд, то рисуем один шарп, если нет то меняем цвет
if (character != L'#')
{
// парсим первый символ
uint32 colour = convert_colour[(character - 48) & 0x3F];
// и еще пять символов после шарпа
for (char i = 0; i < 5; i++)
{
++ index;
if (index == end)
{
--index; // это защита
continue;
}
colour <<= 4;
colour += convert_colour[ ((*index) - 48) & 0x3F ];
}
// если нужно, то меняем красный и синий компоненты
texture_utility::convertColour(colour, _format);
line_info.simbols.push_back( CharInfo(colour) );
continue;
}
}
GlyphInfo* info = _font->getGlyphInfo(character);
if (info == nullptr)
continue;
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);
}
float char_width = info->width;
float char_height = info->height;
float char_advance = info->advance;
float char_bearingX = info->bearingX;
float char_bearingY = info->bearingY;
if (_height != font_height)
{
float scale = (float)_height / font_height;
char_width *= scale;
char_height *= scale;
char_advance *= scale;
char_bearingX *= scale;
char_bearingY *= scale;
}
float char_fullAdvance = char_bearingX + char_advance;
<span style="color:#ff0000;"> if( (_maxWidth != -1) &&
((width + char_fullAdvance) > _maxWidth) &&
(_maxWidth>char_fullAdvance))
{
UString::const_iterator peeki_front = index;
if (peeki_front!=_text.begin())
{
--peeki_front;
GlyphInfo* info_front = _font->getGlyphInfo(*peeki_front);
if (info_front)
{
float char_advance_front = info_front->advance;
float char_bearingX_front = info_front->bearingX;
if (_height != font_height)
{
float scale = (float)_height / font_height;
char_advance_front *= scale;
char_bearingX_front *= scale;
}
float char_fullAdvance_front = char_bearingX_front + char_advance_front;
line_info.simbols.push_back(CharInfo(info->uvRect, char_width, char_height, char_advance, char_bearingX, char_bearingY));
roll_back.set(line_info.simbols.size()-1, peeki_front, count-1, width-char_fullAdvance_front);
width += char_fullAdvance;
}
}
}
</span>
// перенос слов
if (_maxWidth != -1
&& (width + char_fullAdvance) > _maxWidth
&& !roll_back.empty())
{
// откатываем до последнего пробела
width = roll_back.getWidth();
count = roll_back.getCount();
index = roll_back.getTextIter();
line_info.simbols.erase(line_info.simbols.begin() + roll_back.getPosition(), line_info.simbols.end());
// запоминаем место отката, как полную строку
line_info.width = (int)ceil(width);
line_info.count = count;
mLength += line_info.count + 1;
result.height += _height;
setMax(result.width, line_info.width);
width = 0;
count = 0;
mLineInfo.push_back(line_info);
line_info.clear();
// отменяем откат
roll_back.clear();
continue;
}
line_info.simbols.push_back(CharInfo(info->uvRect, char_width, char_height, char_advance, char_bearingX, char_bearingY));
width += char_fullAdvance;
count ++;
}
line_info.width = (int)ceil(width);
line_info.count = count;
mLength += line_info.count;
mLineInfo.push_back(line_info);
setMax(result.width, line_info.width);
// теперь выравниванием строки
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;
}
[/code]
[code=C/C++]
void EditText::doRender()
{
if (nullptr == mFont || !mVisible || mEmptyView)
return;
if (mRenderItem->getCurrentUpdate() || mTextOutDate)
updateRawData();
Vertex* vertex = mRenderItem->getCurrentVertexBuffer();
const RenderTargetInfo& renderTargetInfo = mRenderItem->getRenderTarget()->getInfo();
// колличество отрисованных вершин
size_t vertexCount = 0;
// текущие цвета
uint32 colour = mCurrentColourNative;
uint32 inverseColour = mInverseColourNative;
uint32 selectedColour = mInvertSelect ? inverseColour : colour | 0x00FFFFFF;
const VectorLineInfo& textViewData = mTextView.getData();
float top = (float)(-mViewOffset.top + mCoord.top);
FloatRect vertexRect;
const FloatRect& selectedUVRect = mFont->getGlyphInfo(mBackgroundNormal ? FontCodeType::Selected : FontCodeType::SelectedBack)->uvRect;
size_t index = 0;
for (VectorLineInfo::const_iterator line = textViewData.begin(); line != textViewData.end(); ++line)
{
float left = (float)(line->offset - mViewOffset.left + mCoord.left);
for (VectorCharInfo::const_iterator sim = line->simbols.begin(); sim != line->simbols.end(); ++sim)
{
if (sim->isColour())
{
colour = sim->getColour() | (colour & 0xFF000000);
inverseColour = colour ^ 0x00FFFFFF;
selectedColour = mInvertSelect ? inverseColour : colour | 0x00FFFFFF;
continue;
}
// смещение текстуры для фона
bool select = index >= mStartSelect && index < mEndSelect;
float fullAdvance = sim->getBearingX() + sim->getAdvance();
// Render the selection, if any, first.
if (select)
{
vertexRect.set(left, top, left + fullAdvance, top + (float)mFontHeight);
drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, selectedUVRect, selectedColour);
}
// Render the glyph shadow, if any.
if (mShadow)
{
vertexRect.left = left + sim->getBearingX() + 1.0f;
vertexRect.top = top + sim->getBearingY() + 1.0f;
vertexRect.right = vertexRect.left + sim->getWidth();
vertexRect.bottom = vertexRect.top + sim->getHeight();
drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, sim->getUVRect(), mShadowColourNative);
}
// Render the glyph itself.
vertexRect.left = left + sim->getBearingX();
vertexRect.top = top + sim->getBearingY();
vertexRect.right = vertexRect.left + sim->getWidth();
vertexRect.bottom = vertexRect.top + sim->getHeight();
drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, sim->getUVRect(), (!select || !mInvertSelect) ? colour : inverseColour);
left += fullAdvance;
++index;
}
top += mFontHeight;
<span style="color:#cc0000;">//++index;</span>
}
// Render the cursor, if any, last.
if (mVisibleCursor)
{
IntPoint point = mTextView.getCursorPoint(mCursorPosition) - mViewOffset + mCoord.point();
GlyphInfo* cursorGlyph = mFont->getGlyphInfo(static_cast<Char>(FontCodeType::Cursor));
vertexRect.set((float)point.left, (float)point.top, (float)point.left + cursorGlyph->width, (float)(point.top + mFontHeight));
drawGlyph(renderTargetInfo, vertex, vertexCount, vertexRect, cursorGlyph->uvRect, mCurrentColourNative | 0x00FFFFFF);
}
// колличество реально отрисованных вершин
mRenderItem->setLastVertexCount(vertexCount);
}
[/code]
MyGUI_TextViewData.h不要动