Mygui中文换行问题解决方案

时间:2021-09-02 05:45:06

相信大家解决了中文输入后一定会遇到如何解决中文输入的问题,中文输入换行问题是很多gui框架都存在的一个问题,这里不废话了,大家打开mygui的引擎层中的widget的textview 的头文件和源文件将其替换为:

复制代码 代码如下:


/*!
@file
@author Albert Semenov
@date 09/2009
*/
#ifndef __MYGUI_TEXT_VIEW_DATA_H__
#define __MYGUI_TEXT_VIEW_DATA_H__
#include "MyGUI_Prerequest.h"
namespace MyGUI
{
class CharInfo
{
public:
CharInfo() :
mIsColour(false)
{
mMetrics.mWidth = 0.0f;
mMetrics.mHeight = 0.0f;
mMetrics.mAdvance = 0.0f;
mMetrics.mBearingX = 0.0f;
mMetrics.mBearingY = 0.0f;
}
CharInfo(
const FloatRect& _rect,
float _width,
float _height,
float _advance,
float _bearingX,
float _bearingY) :
mIsColour(false),
mUVRect(_rect)
{
mMetrics.mWidth = _width;
mMetrics.mHeight = _height;
mMetrics.mAdvance = _advance;
mMetrics.mBearingX = _bearingX;
mMetrics.mBearingY = _bearingY;
}
CharInfo(uint32 _colour) :
mIsColour(true),
mColour(_colour)
{ }
bool isColour() const
{
return mIsColour;
}
float getWidth() const
{
return mMetrics.mWidth;
}
float getHeight() const
{
return mMetrics.mHeight;
}
float getAdvance() const
{
return mMetrics.mAdvance;
}
float getBearingX() const
{
return mMetrics.mBearingX;
}
float getBearingY() const
{
return mMetrics.mBearingY;
}
const FloatRect& getUVRect() const
{
return mUVRect;
}
uint32 getColour() const
{
return mColour;
}
private:
bool mIsColour;
FloatRect mUVRect;
struct Metrics
{
float mWidth;
float mHeight;
float mAdvance;
float mBearingX;
float mBearingY;
};
union
{
Metrics mMetrics;
uint32 mColour;
};
};
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;
//};
struct LineInfo
{
LineInfo() :
width(0),
offset(0),
count(0),
offcount(0)
{
}
void clear()
{
offcount = 0;
width = 0;
count = 0;
simbols.clear();
offset = 0;
}
int offcount;
int width;
int offset;
size_t count;
VectorCharInfo simbols;
};
typedef std::vector<LineInfo> VectorLineInfo;
} // namespace MyGUI
#endif // __MYGUI_TEXT_VIEW_DATA_H__


上面是头文件,下面是源文件:

复制代码 代码如下:


/*!
@file
@author Albert Semenov
@date 09/2010
*/
/*
This file is part of MyGUI.
MyGUI is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
MyGUI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
*/
#include "MyGUI_Precompiled.h"
#include "MyGUI_TextView.h"
namespace MyGUI
{
namespace
{
template<typename T>
void setMin(T& _var, const T& _newValue)
{
if (_newValue < _var)
_var = _newValue;
}
template<typename T>
void setMax(T& _var, const T& _newValue)
{
if (_var < _newValue)
_var = _newValue;
}
}
class RollBackPoint
{
public:
RollBackPoint() :
position(0),
count(0),
width(0),
rollback(false)
{
}
void set(size_t _position, UString::const_iterator& _space_point, size_t _count, float _width)
{
position = _position;
space_point = _space_point;
count = _count;
width = _width;
rollback = true;
}
void clear()
{
rollback = false;
}
bool empty() const
{
return !rollback;
}
float getWidth() const
{
MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
return width;
}
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() const
{
MYGUI_DEBUG_ASSERT(rollback, "rollback point not valid");
return space_point;
}
private:
size_t position;
UString::const_iterator space_point;
size_t count;
float width;
bool rollback;
};
TextView::TextView() :
mLength(0),
mFontHeight(0)
{
}
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;
mLength += line_info.offcount;
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;
}
// тег
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;
// перенос слов
if (_maxWidth != -1
&& (width + char_fullAdvance) > _maxWidth
/*&& !roll_back.empty()*/)
{
--index;
// откатываем до последнего пробела
/*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();*/
// запоминаем место отката, как полную строку
line_info.width = (int)ceil(width);
line_info.count = count;
line_info.offcount = 0;
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;
}
size_t TextView::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)
{
// это последняя строка
bool lastline = !(line + 1 != mLineInfo.end());
// наша строчка
if (top + height > _value.top || lastline)
{
top += height;
float left = (float)line->offset;
int count = 0;
// ищем символ
for (VectorCharInfo::const_iterator sim = line->simbols.begin(); sim != line->simbols.end(); ++sim)
{
if (sim->isColour())
continue;
float fullAdvance = sim->getAdvance() + sim->getBearingX();
if (left + fullAdvance / 2.0f > _value.left)
{
break;
}
left += fullAdvance;
count ++;
}
result += count;
break;
}
if (!lastline)
{
top += height;
result += line->count + line->offcount;

}
}
return result;
}
IntPoint TextView::getCursorPoint(size_t _position)
{
setMin(_position, mLength);
size_t position = 0;
int top = 0;
float left = 0.0f;
for (VectorLineInfo::const_iterator line = mLineInfo.begin(); line != mLineInfo.end(); ++line)
{
left = (float)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->getBearingX() + sim->getAdvance();
}
break;
}
position += line->count + line->offcount;

top += mFontHeight;
}
return IntPoint((int)left, top);
}
const IntSize& TextView::getViewSize() const
{
return mViewSize;
}
size_t TextView::getTextLength() const
{
return mLength;
}
const VectorLineInfo& TextView::getData() const
{
return mLineInfo;
}
} // namespace MyGUI


修改了这两个以后,然后将edit控件改为多行支持和自动换行,这样就实现了mygui的中文自动换行问题。