Mygui中文换行问题解决方案
Mygui中文换行问题解决方案
发布时间:2016-12-28 来源:查字典编辑
摘要:相信大家解决了中文输入后一定会遇到如何解决中文输入的问题,中文输入换行问题是很多gui框架都存在的一个问题,这里不废话了,大家打开mygui...

相信大家解决了中文输入后一定会遇到如何解决中文输入的问题,中文输入换行问题是很多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的中文自动换行问题。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新C语言学习
热门C语言学习
编程开发子分类