PSP上的阅读软件我所知道的有bookr和XReader(没用过)等,我比较喜欢bookr,不过bookr在阅读很多pdf时,中文会显示成乱码,阅读txt时,根本就无法显示中文,
这确实很让人不爽。
过年前闲着没事,顺便解决了bookr中文问题,本文记录了那段时间的工作:如何从官方版bookr修改,解决pdf中文乱码问题,支持txt中文、中文目录显示的问题,抛砖引玉和大家分享下整个的思路
和问题的解决方式,解决过程比较丑陋,希望高手多多指点。
貌似这里不能贴超过2M的附件,这里就不贴出修改后的bookr的发布文件了,在PSP2000测试通过,最近也一直在用,需要的同学可以email问我要。
注:已经上传到csdn:http://download.csdn.net/source/2578241
内置了少量字体,大家可以自行扩展字体。
准备工作
1、搭建PSP开发环境。sourceforge上集成的安装包,下载下来直接安装即可,这里不多说了。
2、下载bookr源码,我下载的是0.7.1版本。可以用SVN下载最新的,也可以在sourceForge下载打包的源码包。
解决PDF中文问题
bookr的代码结果很清晰,由于是用c++开发的,所以代码很好理解,BKLayer 是基础的显示类,BKDocument是基础的文档处理类。
bookr支持pdf、txt、html和 PalmDoc(我没用过这种),分别由从BKDocument的派生类来处理。
pdf是由BKPDF来处理的。解决pdf中文问题的关键就在BKPDF类了。
1、如何调试
PSP开发首先遇到的问题是调试,PSP并不能实时调试,这确实是个问题。好在Bookr源码级支持了跨平台,在windows下,使用Makefile.cygwin
就可以编译一个windows版本
的Bookr了。一般来说,在windows下bookr运行正常,大致在PSP上的版本也是正常的,当然,在细节上其实是有差别的。另外,还可以通过日志来实现跟踪。
2、解决字体问题
实际上,有些中文pdf用bookr打开时是正常的,比如Programming_In_Lua.pdf,但是在打开经常温习的金庸全集的时候,就出现乱码了。
注意到Bookr的pdf显示其实是主要是mudpf来实现的。那么bookr中文显示问题到底是bookr自身的还是mupdf的呢?
为了确认这个问题,先从sourceforge下载mupdf,建立一个vs2005的项目,编译,OK,可以运行了,打开金庸全集一看,还是乱码,这下基本可以确认,这个
问题是从mupdf就存在了。要定位中文显示乱码的问题,自然需要了解pdf的内部格式,从adobe的官网下载了最新的pdf手册,打开一看,一共700多页。。。
好在我们不需要从头开始阅读,只要挑关键的地方看就可以了,中文问题一般是因为字体引起的。
所以我们可以直接挑Text的字体相关部分看。
mupdf的字体加载在pdf_loadfont里,从pdf手册可知,pdf支持了若干种字体,反正我是没什么耐心看下去,直接打开金庸全集单步调试了下,
发现问题在TrueType字体的加载里,TrueType字体的加载是loadsimplefont来处理的,通过跟踪可知,在获取字体的FontDescriptor的时候失败了,然后就是用内置的默认字体来处理了。
默认字体都不支持中文,所以自然就显示成乱码了。
最简单的办法就是只要是TrueType字体,不管具体是什么字体,都强制从硬盘加载一种指定字体(例如黑体),当然,这样会导致我们看到的pdf和实际应该显示的样子有差别,只有一种字体了。
让我们先这样试试吧:在发现pdf_loadfontdescriptor
加载失败后,强制用loadCustomFont
加载硬盘指定字体"font/simhei.ttf",这样字体加载的问题貌似解决了。
编译,运行,发现还是有问题,这次的问题在文字编码了。
3、编码问题
一般显示不正常的中文pdf都是GBK编码的,mupdf的显示是通过如下两个步骤来做的:
首先解码,将文字内容全部转化成cid,然后将要显示的cid全部push到一个队列,然后遍历cid,将cid转化成gid(对trueType就是转成unicode),接着显示。
mupdf本身有一个比较优雅的办法来解码,通过pdf_lookupcmap来得到unicode,我用了比较笨的办法:自己暴力做GBK到unicode的转换。
一般在windows和linux下都有库或者API来完成编码转换问题。不过在PSP下却没有这样的API,只好自己做一个编码转换了,
在http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT
找到了转换表,复制粘贴到txt文本,用lua脚本处理下,生成一个.c文件,分别将GBK和unicode值存储到2个数组里,
现在你一定知道怎么转换了:二分查找到指定GBK值在GBK数组的下标,然后直接在unicode数组用这个下标,可以得到对应的unicode值。
编译测试,OK了,终于能正常显示中文了。
不过到现在为止,整个页面只有一种字体,要解决这个问题,我们可以根据名字匹配来找到指定的字体,名字匹配不到的,使用默认的字体(我是用的simsun.ttf)。
txt中文问题
相对来说txt的中文问题比较好解决了,基本都是些常规开发,从FzFont.cpp代码可知,txt显示不了中文主要是字体加载的时候,只加载了前面的256个字形。那么我们只要做2件事情就可以显示中文了:
1、文字解码,现在大部分的txt电子书都是gbk编码的,这样比较省空间,解码算法前面已经提过了。
2、中文文字纹理管理和效率问题。一般在PC游戏中,中文字体一般都是将多个连续的汉字按照存储到一张64X64的纹理中,这样可以节省显存,降低渲染批次(3D菜鸟的简单推测)。
不过如果在psp也这样做,会发现显示页面是在太慢,最后发现,最简单的办法居然是每个汉字一个纹理,当然要实际用到的时候才生成该汉字纹理。
3、显示页分割。bookr阅读txt的时候,会自己将电子书分割成若干页面,并且支持书签功能,因此,不可避免的涉及到页面分割问题,引入中文显示后,这里稍微有点不同,要注意不能拆分一个汉字,
当然,还有其他细节需要处理,这里不多说了。
目录中文问题
必须承认,这是我遇到的最痛苦的问题了,原因是从API上就有问题了,读取出来的目录名居然是Shift-jis编码的,谁让PSP是索尼产的呢,我尝试过将PSP的语言设置、时间等本地化设置改成中文、中国等。
发现读取到的目录名还是shift-jis编码。我先将目录名从shift-jis转回gb2312,然后显示,结果发现很多汉字丢失,因为从gb2312转到shift-jis的时候已经失真了,转回来显示很多字体就显示不了了。
看上去这个问题无法解决了,其实不然,PSP的API提供了打开记忆卡设备的功能,这样,我们自己做一个FAT32驱动(叫驱动不合适,其实就是自己读取FAT32文件系统管理文件)就可以了,FAT32的文档
到处都是,linux下也有vfat文件系统的实现,不过我偷懒了,我直接从PMP Player的代码里拷贝了FAT32相关文件,直接移植过来,修改了FzScreenPsp.cpp文件里目录相关的目录读取函数,
然后修改目录相关显示代码后,编码显示,一切终于解决了。。。
posted on 2010-07-26 21:41
feixuwu 阅读(6973)
评论(5) 编辑 收藏 引用 所属分类:
PSP开发