Mygui中文换行问题

3 篇文章 0 订阅

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值