我用JS又撸了一个Minecraft高清字体生成器

时间:2022-01-01 来源:未知网络 作者:996建站网

(专栏终于通过申请了,这两篇姊妹文章作为开头好了,希望能一直写下去)

继上一篇我用C++撸了一个MineCraft高清字体材质生成器后我又重新撸了一个网页版本的——不要问我为啥要和MC字体过不去,C++版本能用的人太少,没办法,虽然写这个程序并不是为了给别人用,但是我还是希望能让更多的人能用上,对吧~

这次的版本,去除了好多不必要的复杂度,比如编译,命令行,构建,准备freetype支持的字体文件等等一堆东西,加上直接以网页形式呈现,理论上应该可以让更多有这个方面需求的人用的上,这回,要好好介绍技术细节了。。编写的顺序以问题为索引,基本描述了我解决问题的思路和方法。

文件输入输出

首先我遇到了一个问题,如何让网页能操作本地的文件——很明显,网页浏览器是不可能提供对用户本地文件系统的直接访问的,因为这样存在安全问题。网页可以提供上传下载的功能,但是这又涉及到后台。然后我思考了一下需求问题,发现其实只有文件输出的需求。输入方面,字体完全可以直接用canvas的函数,没必要读取用户提供的字体文件;输出方面,才是需要考虑的问题,因为我们要生成的是实际的图像文件,有一种比较简单,容易想到的方案就是将canvas直接存为datauri,然后让用户手动右键下载。

但是有256个图片呐。。。虽然我们是开源软件,可以不用照顾用户体验(划去),但是这样真的没法用了好吧!

仔细想想通常我们是怎么解决多文件传输的呢?压缩是一个好方法!JS可以完成压缩文件这个任务吗?可以!我直接用"JS ZIP"作为关键词,在谷歌上搜索,第一个结果是zip.js,第二个结果是JSZip,简单一看首页,我默默选择第二个(原因自己猜)。

JSZip还顺带帮我解决了文件输出问题——就是用示例代码里用过的FileSaver.js直接让浏览器出现下载文件页面,而非给个链接让用户手动点击。

而且有了zip压缩,我还可以考虑直接生成立即可用的资源包,进一步方便小白的操作。

PNG输出

很明显,Minecraft对材质包格式的要求是PNG格式,然后canvas可以输出任意支持格式的datauri,恰好JSZip也支持base64,那么只要把datauri前面部分裁剪了就可以用了。

还记得C++版本我是怎么做得吗?我直接引入了一个PNG++的库,然后才可以操作,和网页相比,不要难太多——不过这样也有好处——我可以自由控制生成png的参数,比如设定像素格式,我用grayalpha的格式存储,理论上应该能减少存储的空间(当然用索引模式更好)不过实际测试表明,区别真不是很大。。。。毕竟png也是有压缩算法的。。。

Canvas输出文字

关于Canvas输出文字,我是直接照着这篇MDN上的教程来做的。

有一点被坑了一下,就是输出文字的位置,比如如果fill('a', 0, 0);的话,是啥都看不到的——我还检查了各种设置,最后继续看文档就知道了:是字体基线的锅。其默认输出文字的位置是按照字母基线来计算的,好在之前研究FreeType2的过程中也是身经百战了,这个那副图一会就看懂了,我直接设置为top之后,一切都正常了。

还有一个注意点,绘图-导出-压缩这种高耗时操作,最好通过setTimeout来进行递归,循环的话可能会导致主线程阻塞,以至于用户无法中断操作。

测量文字属性

除了输出材质图片之外,文字宽度的测量也是很重要的,否则某些字体会在Minecraft里显示异常,其实主要的问题就在于宽度不一致,毕竟有半角字符全角字符,还有一些神奇的特长字符(这部分不处理了。。。。)

具体测量就是文字的横向范围,由于渲染方式与C++版本不太一样,这个版本里所有的文字都是从单元格的最左端开始的,所以高位肯定是F,低位就是宽度/单元格宽度*16了(然后让特长字符截断),最后保存到文件里面,这方面JS版本写的非常简单,因为不涉及多进程操作,直接写入就可以了。。。。

一些小问题

主要就是文字错位的问题,即纵向方面有几px的偏移,也不知道有什么好的解决方法,因为和字体名字/字体大小/浏览器版本均有关系,所以只能让用户手动输入了。剩下就是防止上一行的文字溢出到下一行来——那就在写入之前先刷空那片区域——不过还是无法避免下一行字偏移到上一行去的情况,还好只有一小部分特殊字符会出问题,所以也就没准备解决。

后记

上面就是全部的技术难点了,后期编码部分基本不是什么难事,毕竟有先前的C++版本,大的问题都在那里解决掉了。。。。

附上源码仓库的地址(欢迎star/issue/p):codehz/minecraft-unicode-font-texture-generator-online

DEMO:codehz/minecraft-unicode-font-texture-generator-online

关于代码格式,写在一起是为了方便,这并不是一个值得用工程来解决的问题,那就不要复杂化实现。

我用JS又撸了一个Minecraft高清字体生成器插图

微信扫一扫 关注公众号

微信扫一扫 使用小程序

百度扫一扫 使用小程序