NGUI所见即所得之UIFont , UIFontMaker

本文深入解析NGUI中的UIFont组件及其生成工具UIFontMaker的工作原理。详细介绍了UIFontMaker如何生成动态字体和位图字体,并探讨了UIFont如何支持表情输入等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

         NGUI所见即所得之UIFont , UIFontMaker

        在上一篇博客介绍了UIAtlas的结构和UIAtlasMaker生成Atlas的原理(NGUI所见即所得之UIAtlasMaker , UIAtlas),按照介绍UIAtlas的行为脉络,应该先对UIFont进行介绍,但是发现UIFont这个脚本特别长有点被吓到了,这主要是因为之前都没有怎么用过UIFontMaker,只是创建Dynamic字体很简单,然后又一个改进是不用再对不同字体大小生成不同的预设,现在只需要TTF和设置字体大小就可以了,方便直观多了,看下图:
FontMaker界面     

       既然从代码理出点头绪出来比较困难,UIFont的成员变量太多了,只有先玩下FontMaker,因为Dynamic字体已经不用创建了,只需要改下Font Type为Dynamic就可以了,所以只要看下Bitmap的形式就差不多了:

      Font Data其实每个字在指定Texture的偏移已经大小等信息(Font Data可以由BM Font等软件生成),看下Output栏。选择UIFont就是把新生成的字体加入选择的UIFont中去,至于Atlas选项很重要(因为看到DrawCall),就是把Texture的图片放进选择的Atlas中去,减少DrawCall。

      进过上面的操作,对UIFont一堆的成员变量就不会莫名其妙了,这也是因为UIFont糅合了比较多的东西,所以会复杂些。

UIFontMaker

      下面还是先看下UIFontMaker,人的思维都习惯从易到难,所以会学习一定是最注重循序渐进的,好了不废话了,切入正题。先看下MakeAsChanged():

void MarkAsChanged ()
	{
		if (NGUISettings.font != null)
		{
			List<UILabel> labels = NGUIEditorTools.FindAll<UILabel>();

			foreach (UILabel lbl in labels)
			{
				if (lbl.bitmapFont == NGUISettings.font)
				{
					lbl.bitmapFont = null;
					lbl.bitmapFont = NGUISettings.font;
				}
			}
		}
	}

       做为开胃菜,这个函数很简单,就是替换UILabel的UIFont,也就说当前对NGUISettings.font进行修改,而上面UIFontMaker的见面只有一个Select是对UIFont进行更改的(加入新生成的字体),所以很自然可以猜到MakeAsChange这个函数只有在Select选择了UIFont的情况下才会被调用执行。

       

static void CreateFont (UIFont font, int create, Material mat)
	{
		if (create == 1)
		{
			// New dynamic font
			font.atlas = null;
			font.dynamicFont = NGUISettings.dynamicFont;
			font.dynamicFontStyle = NGUISettings.dynamicFontStyle;
		}
		else
		{
			// New bitmap font
			font.dynamicFont = null;
			BMFontReader.Load(font.bmFont, NGUITools.GetHierarchy(font.gameObject), NGUISettings.fontData.bytes);

			if (create == 2)
			{
				font.atlas = null;
				font.material = mat;
			}
			else if (create == 3)
			{
				font.spriteName = NGUISettings.fontTexture.name;
				font.atlas = NGUISettings.atlas;
			}
		}
	}

       最主要的是BMFontReader.Load,然后可以进一步看下BMFontReader,BMFont,BMGlphy这三个脚本,其实看到这三个脚本的注释可以发现,其实NGUI就是把BMFont移植过来:

                    BMFont reader. C# implementation of http://www.angelcode.com/products/bmfont/

由于篇幅和主题,这里就不做介绍了,但是至少可以认识了字体制作方法,下次可以自己写一个美术字体的制作程序。

    剩下的OnGUI就没有什么必要介绍的,只是一个条件的跳转和细节的判断。

 

UIFont

    看到UIFontMaker的界面操作(选择项比较多),就知道UIFont的成员变量或属性会多出一些,其中mMat,mReplacement mSprite在UIAtlas中也有,就不做解释了。  

 

        [HideInInspector][SerializeField] Material mMat;
	[HideInInspector][SerializeField] Rect mUVRect = new Rect(0f, 0f, 1f, 1f);
	[HideInInspector][SerializeField] BMFont mFont = new BMFont();
	[HideInInspector][SerializeField] int mSpacingX = 0;
	[HideInInspector][SerializeField] int mSpacingY = 0;
	[HideInInspector][SerializeField] UIAtlas mAtlas;
	[HideInInspector][SerializeField] UIFont mReplacement;
	[HideInInspector][SerializeField] float mPixelSize = 1f;

	// List of symbols, such as emoticons like ":)", ":(", etc
	[HideInInspector][SerializeField] List<BMSymbol> mSymbols = new List<BMSymbol>();

	// Used for dynamic fonts
	[HideInInspector][SerializeField] Font mDynamicFont;
	[HideInInspector][SerializeField] int mDynamicFontSize = 16;
	[HideInInspector][SerializeField] FontStyle mDynamicFontStyle = FontStyle.Normal;

	// Cached value
	UISpriteData mSprite = null;
	int mPMA = -1;
	bool mSpriteSet = false;

	// I'd use a Stack here, but then Flash export wouldn't work as it doesn't support it
	static BetterList<Color> mColors = new BetterList<Color>();

     下面对部分变量做下注释性的介绍:

mUVRect

public Rect uvRect
	{
		get
		{
			if (mReplacement != null) return mReplacement.uvRect;

			if (mAtlas != null && (mSprite == null && sprite != null))
			{
				Texture tex = mAtlas.texture;

				if (tex != null)
				{
					mUVRect = new Rect(
						mSprite.x - mSprite.paddingLeft,
						mSprite.y - mSprite.paddingTop,
						mSprite.width + mSprite.paddingLeft + mSprite.paddingRight,
						mSprite.height + mSprite.paddingTop + mSprite.paddingBottom);

					mUVRect = NGUIMath.ConvertToTexCoords(mUVRect, tex.width, tex.height);
#if UNITY_EDITOR
					// The font should always use the original texture size
					if (mFont != null)
					{
						float tw = (float)mFont.texWidth / tex.width;
						float th = (float)mFont.texHeight / tex.height;

						if (tw != mUVRect.width || th != mUVRect.height)
						{
							//Debug.LogWarning("Font sprite size doesn't match the expected font texture size.\n" +
							//	"Did you use the 'inner padding' setting on the Texture Packer? It must remain at '0'.", this);
							mUVRect.width = tw;
							mUVRect.height = th;
						}
					}
#endif
					// Trimmed sprite? Trim the glyphs
					if (mSprite.hasPadding) Trim();
				}
			}
			return mUVRect;
		}
		set
		{
			if (mReplacement != null)
			{
				mReplacement.uvRect = value;
			}
			else if (sprite == null && mUVRect != value)
			{
				mUVRect = value;
				MarkAsDirty();
			}
		}
	}

 很长一段代码,mUVRect表示的文字集的图片在图集的偏移和长宽。

     针对UILabel提供三种显示类型,UIFont提供了三种计算字符串Dimension(像素)的下面三个方法,这三个方法也占用了UIFont相当大的篇幅:

                public Vector2 CalculatePrintedSize (string text, int size, bool encoding, SymbolStyle symbolStyle)

                public string GetEndOfLineThatFits (string text, int size, int lineWidth, bool encoding, SymbolStyle symbolStyle)

                public int CalculateOffsetToFit (string text, int size, int lineWidth, bool encoding, SymbolStyle symbolStyle)

 

BMSymbol

        很早就看到说NGUI支持表情输入,虽然之前项目中,看到同事做聊天框用的是NGUIHtml这个插件来实现的,但是这样的话,不是让NGUI不得极其用,有点小浪费,其实原理就是根据符号的字符串找到图片。

 

 

小结:

        今天晚上,一开始看到UIFont这么行代码就有点畏难,后面看了点视频,觉得还是接着写吧,虽然BMFont和BMSymbol的部分几乎没有介绍,原因有两个:1)如果实际项目中不是自己动手写NGUI插件没有太多必要,2)现在已经凌晨2:10了时间有点晚,以前在学校都没觉得什么,现在工作了,觉得码农都是一个高危职业,身体是自己的,所以自己一再强调要早点休息(虽然还是到了这个时候,原谅我吧),说真的现在头还真有点晕。

        刚突然听到Beyond的《不再犹豫》无聊望见了犹豫,达到理想不太易,即使有信心,斗志却抑止”很深刻的刻画了我一直以来的状态,所以才坚持写完的,加油,努力!

        如果您对D.S.Qiu有任何建议或意见可以在文章后面评论,或者发邮件(gd.s.qiu@gmail.com)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。

        转载请在文首注明出处:http://dsqiu.iteye.com/blog/1968002

更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)

     

     晚安,明天早起跑步去!

 

 

 

 

 

 


 

v1.13 (10/19/2012) + 增加 (BDF) 字体合并功能。 + 增加自动校准基线功能。 + 增加对BDF V2.2 的支持。 * 完善越南文unicode编码字库(增加扩展码和附加码) v1.12 (09/17/2012) + 增加自动升级功能(由于增加了网络下载功能,可能会被杀毒软件拦截,但请放心,绝对安全)。 + 增加usbkey注册。 + 增加字体加粗功能。 * 修改字体文件,以及输出文件路径不能保持的bug。 * 修改scanmode为Horb0~b7的bug。 * 完善多语言文本提示。 v1.11 (08/14/2012) + 增加注册年限选择。 * 修改获取机器码失败的bug。 v1.10 (06/26/2012) * 精简字库检索表。 + 增加 GBK 字库输出。 + 增加一种点阵数据存储格式(只存有效像素数据--not fixed, 不支持MBCS编码格式的中日韩), 对泰文,缅甸文等特殊语种显示非常便捷。 v1.09 (06/15/2012) + 增加输出 C 语言(数组) 字体格式。 V1.08 (05/17/2012) + 增加了两个版本(免费和试用版) 免费版 只对 16点阵有效。 试用版 对所有点阵有效,但是会缺部分字符。 + 增加热键功能。 * 修改了多国语言生成.h文件时,start 与 end 不匹配的bug。 * 完善文档《GuiTool 使用说明》, 增加更多图解说明。 文档下载地址: http://ishare.iask.sina.com.cn/f/24472766.html v1.07 (05/02/2012) * 修改注册方式(改为文件)。 + 增加bdf格式编码过滤功能,主要是为了支持 MTK 手机点阵字库。 + 增加xp控件属性。 + 增加扫描模式图解。 * 修改了 bdf 2 bin 的一个bug。(选择输出位图时,会输出n个位图文件) * 修改了 BDF 文件中当字符显示宽度为0,存位图(所有字符存一张图片)失败的错误。 v1.06 (04/10/2012) + 增加系统字体支持,操作更简便,快捷。 枚举所有已安装系统字体,直接选择即可。 v1.05 (03/24/2012) Fontmaker(点阵字库) * 修正了字符对齐问题。 + 增加了单个字符或多个字符输出成位图文件设定。 * 完善了阿拉伯文字库(unicode 字库有效)。 + 增加自定义字符功能(unicode 字库有效)。 Multi-language(多国语言) + 增加输出编码格式 (mbcs, utf16-lb, utf8)设置 + 增加数组格式输出。 Image Manager(图像管理) + 该页为新增功能,支持图片图像的数据转换。主要应用在做产品logo图片方面。 V1.04 (07/16/2011) + 增加了一个字符串mbcs2unicode(内码转统一码)的功能。 (支持转:U16-LE, U16-BE, UTF8) V1.03 (07/05/2011) * 修改了 Example 中点阵字库解析源码,更加便于移植。(基本做到只需修改font_file.c 即可) * 修改了内码(MBCS)字库点阵信息读取的一个错误。 + 增加了多语言支持(简中,英文),还有待完善。。。 V1.02 (07/01/2011) 1. FontMaker V2.03 + 增加字符宽高比调节(HorR & VerR) + 增加对*.ttc 字库的支持。 + 增加bdf(*.bdf)文件格式转Simple Unicode编码格式的bin文件。 V1.01 (06/29/2011) 1. FontMaker V2.02 + 增加了 Simple Unicode功能。(适合小字库) + 增加了 “扫描方向及反显”设置。 2. Multi-Language V1.01 * 修改了除 office 2000 外,其它不能支持的问题。 V1.00: (2007-2011) * 继承 FontMaker V2.01 的所有功能。 + 增加了一个 Multi-Languge V1.00 的打包转换功能。 FontMaker 基本功能: 1.支持所有 windows 字符集:CP932(日文Shift-JIS)CP936(简体中文GBK)CP949(韩文)CP950(繁体中文 Big5),CP874(泰文),CP1250(中欧)CP1251(西里尔文),CP1252(西欧--"拉丁文I"),CP1253(希腊文), CP1254(土耳其文),CP1255(希伯来文),CP1256(阿拉伯文),CP1257(波罗的海文),CP1258(越南) 2.支持非等宽字库。 3.支持BIN,TXT,BMP,BDF 文件输出。 4.支持unicode字库输出,即可以做到在一个窗口中同时显示多国语言(文字) 5.支持单个字符编辑,预览(所见即所得)。 6.支持字库文件和输出路径记忆功能. 7. 支持从bdf格式转换自定义字库(bin文件)格式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值