qte-从ttf字库中提取指定汉字生成qpf字库的笨办法 ttf字体库下载
这篇文档大家可以随意转载.我本人只保留所有权.转载请注明作者和出处.
我记得qte下中文显示为乱码是因为字体编解码错误,而显示为方块是字体指定错误。
QString内部是用unicode16编码的,但是可以在我们的main函数中先指定它的编码方式:
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
像上面三行是网上的经典解决方案。再者,可以这样使用我们已经放到font目录下的simhei字体:
QFont font;
font.setPointSize(20);
font.setFamily(("simhei"));
app.setFont(font);
这样两步基本上能解决字体问题了。可以一试。
解决思路: 获取汉字的unicode编码,使用unicode编码来获取ttf字库中的汉字来生成qpf字库.
首先对我所用的linux环境作以下说明:
Linux系统:
Redhat Linux 9
QT:
qt-embedded-free-3.3.3.tar.bz2
下面正式开始了:
1. 在根目录下新建一个目录
mkdir qte
2. 把qt-embedded-free-3.3.3.tar.bz2移到qte目录
mv qt-embedded-free-3.3.3.tar.bz2 /qte
3. 解压qt-embedded-free-3.3.3.tar.bz2
tar -jxvf qt-embedded-free-3.3.3.tar.bz2
4. 重命名qt-embedded-free-3.3.3.tar.bz2文件夹
mv qt-embedded-free-3.3.3 qte
5. 在根目录的qte目录下写如下shell脚本并保存成buildqte
#!/bin/sh
cd qte
export QTDIR=$PWD
export PATH=$QTDIR/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
./configure -qt-gfx-transformed -qvfb
make -C src #这样只是编译src目录下的源码 如果你没有 moc uic 工具就全部编译 你可以直接make而不要后面的 -C src
cd ..
6. 执行buildqte脚本编译x86版本的qte库.
./buildqte
7. 检查/qte/qte/bin目录是否有以下工具 qmake moc
如果有就行了,没有就请仔细看第5步,或许你的机器已经安装了qt3 x11版本,可以把uic她拷贝到/qte/qte/bin下使用.
8. 修改/qte/qte/src/kernel/qmemorymamager_qws.cpp文件。(修改的代码很少,这也是最关键的部分。)
说明:为什么要改这个文件
请进入如下目录 /qte/qte/tools/makeqpf/ 打开main.cpp文件(这是makeqpf工具的源码)
请关注下面的代码
129 class MakeQPF : public QMainWindow
130 {
131 Q_OBJECT
132 QListView* view;
133 public:
134 MakeQPF()
135 {
136 view = new QListView(this);
137 view->addColumn("Family");
138 view->addColumn("Size");
139 view->addColumn("Weight");
140 view->addColumn("Style");
141 setCentralWidget(view);
142 QString fontdir = qws_topdir() + "/lib/fonts";
143 readFontDir(fontdir);
144
145 connect(view,SIGNAL(selectionChanged(QListViewItem*)),this,SLOT(renderAndSave(QListViewItem*)));
146 }
重点关注145行,在这里调用了renderAndSave(QListViewItem*)槽
234
235 private slots:
236 void renderAndSave(QListViewItem* i)
237 {
238 ((FontViewItem*)i)->renderAndSave();
239 }
重点关注238行
54 void renderAndSave()
55 {
56 font = QFont(family,pointSize,weight,italic);
57 #ifdef Q_WS_QWS
58 memorymanager->savePrerenderedFont((QMemoryManager::FontID)font.handle());
59 #endif
60 setHeight(QFontMetrics(font).lineSpacing());
61 repaint();
62 }
重点关注58行
33 #ifdef Q_WS_QWS
34 #include <qmemorymanager_qws.h>
35 #endif
重点关注34行
58行中的memorymanager是在头文件qmemorymanager_qws.h中定义的。
打开/qte/qte/include/qmemorymanager_qws.h文件
77 #ifndef QT_NO_QWS_SAVEFONTS
78 void savePrerenderedFont(const QFontDef&, bool all=TRUE);
79 void savePrerenderedFont(FontID id, bool all=TRUE);
80 #endif
81 bool fontSmooth(FontID id) const;
82 int fontAscent(FontID id) const;
83 int fontDescent(FontID id) const;
84 int fontMinLeftBearing(FontID id) const;
85 int fontMinRightBearing(FontID id) const;
86 int fontLeading(FontID id) const;
87 int fontMaxWidth(FontID id) const;
88 int fontUnderlinePos(FontID id) const;
89 int fontLineWidth(FontID id) const;
90 int fontLineSpacing(FontID id) const;
91
92 private:
93 QMap<PixmapID,QMemoryManagerPixmap> pixmap_map;
94 int next_pixmap_id;
95 QMap<QString,FontID> font_map;
96 int next_font_id;
97 };
98
99 extern QMemoryManager* memorymanager;
重点关注79行和99行
79行的成员函数实现在/qte/qte/src/kernel/qmemorymanager_qws.cpp
打开上面的文件看到下面的代码( 生成qpf字库的工作就在下面做了, 下面是没有改动过的代码 )
991 #ifndef QT_NO_QWS_SAVEFONTS
992 void QMemoryManager::savePrerenderedFont(const QFontDef& f, bool all)
993 {
994 QMemoryManagerFont* mmf = (QMemoryManagerFont*)refFont(f);
995 savePrerenderedFont((FontID)mmf,all);
996 }
997
998 void QMemoryManager::savePrerenderedFont(FontID id, bool all)
999 {
1000 QMemoryManagerFont* mmf = (QMemoryManagerFont*)id;
1001
1002 if ( !mmf->renderer ) {
1003 qWarning("Already a ROM font");
1004 } else {
1005 if ( !mmf->tree )
1006 mmf->tree = new QGlyphTree(32,32,mmf->renderer); // 32 = " " - likely to be in the font
1007 if ( all ) {
1008 int j=0;
1009 //qDebug("Rendering %s",fontFilename(mmf->def).ascii());
1010 for (int i=0; i<=mmf->renderer->maxchar; i++) {
1011 if ( mmf->renderer->inFont( i ) ) {
1012 mmf->tree->get( i, mmf->renderer );
1013 if ( !(j++ & 0x3f) ) {
1014 // XXX keep it from becoming degenerate - should be in QGlyphTree
1015 mmf->tree->compress();
1016 QGlyphTree::balance(mmf->tree);
1017 }
1018 }
1019 }
1020 }
1021 mmf->tree->compress();
1022 QGlyphTree::balance(mmf->tree);
1023 //qDebug("DUMP..."); mmf->tree->dump();
1024 QFile f(fontFilename(mmf->def));
1025 f.open(IO_WriteOnly);
1026 f.writeBlock((char*)&mmf->fm,sizeof(mmf->fm));
1027 mmf->tree->write(f);
1028 }
1029 }
1030 #endif
重点关注1010行到1019行
里面中的for循环的i变量就是unicode编码对应。
如果你只是要大小写字母,你可以将for循环改成下面这样
for (int i=0x21; i<=0x7e; i++) //大小写字母和英文标点符号uincode编码是从0x21 到 0x7e
{
if ( mmf->renderer->inFont( i ) )
{
mmf->tree->get( i, mmf->renderer );
if ( !(j++ & 0x3f) )
{
// XXX keep it from becoming degenerate - should be in QGlyphTree
mmf->tree->compress();
QGlyphTree::balance(mmf->tree);
}
}
}
上面的循环就是生成只包含大小写字母和英文标点符号的qpf字库了。
现在我们的目标是生成指定汉字的qpf字库.
现在就以我修改的代码为例进行说明。
把qmemorymanager_qws.cpp中998-1029行中 void QMemoryManager::savePrerenderedFont(FontID id, bool all)
实现代码修改成如下代码:
void QMemoryManager::savePrerenderedFont(FontID id, bool all)
{
QMemoryManagerFont* mmf = (QMemoryManagerFont*)id;
if ( !mmf->renderer )
{
qWarning("Already a ROM font");
}
else
{
if ( !mmf->tree )
mmf->tree = new QGlyphTree(32,32,mmf->renderer); // 32 = " " - likely to be in the font
if ( all )
{
int j=0;
qDebug("Rendering %s",fontFilename(mmf->def).ascii());
//for (int i=0; i<=mmf->renderer->maxchar; i++) {
printf("mmf->renderer->maxchar=%un", mmf->renderer->maxchar);
for (int i=0x21; i<=0x7e; i++)//大小写字母和英文标点符号uincode编码是从0x21 到 0x7e(这是一般字库都要有的)
{
if ( mmf->renderer->inFont( i ) )
{
mmf->tree->get( i, mmf->renderer );
if ( !(j++ & 0x3f) )
{
// XXX keep it from becoming degenerate - should be in QGlyphTree
mmf->tree->compress();
QGlyphTree::balance(mmf->tree);
}
}
}
//把你需要的汉字加入到 tmp 中去,这样一来就可以实现从ttf中提取指定汉字的qpf字库了.
//本人的方法笨就笨在这里,每次添加了汉字就要重新编译qte库和makeqpf
QString tmp("开始停止登录退出参数设置户代码用户密码提示信息你输设置图像摄像图片预览图片浏览摄像状态信息设备状态通道检测");
//注意现在只能处理utf-8的汉字编码, 我是由汉字的utf-8编码来获取汉字unicode编码 关于utf-8, 参考utf-8的相关信息
unsigned int len = tmp.length();
const char *ch = tmp.latin1();
unsigned int n;
unsigned int count = 0;
printf( "len=%un",len );
for( n=0; n<len ; )
{
if( ( (unsigned char)ch[n] ) >> 4 == 0xE)//0xE开始是汉字 汉字3字节
{
unsigned int sp1=0;
unsigned int sp2=0;
unsigned int sp3=0;
//以下是utf-8 转换成 unicode编码的过程
//分别获取三个字节,分别转换,然后三个相加就是所需的汉字unicode编码
sp1 =(unsigned int)( (unsigned char)ch[n] - 0xe0 );
sp2 =(unsigned int)( (unsigned char)ch[n+1] - 0x80 );
sp3 =(unsigned int)( (unsigned char)ch[n+2] - 0x80 );
//printf( "0x%x 0x%x 0x%x n", sp1, sp2, sp3 );
sp1 = sp1 << 12;
sp2 = sp2 << 6;
sp3 = sp1 + sp2 + sp3;
//printf( "0x%xnn", sp3 );
if ( mmf->renderer->inFont( sp3 ) )
{
mmf->tree->get( sp3, mmf->renderer );
if ( !(j++ & 0x3f) )
{
// XXX keep it from becoming degenerate - should be in QGlyphTree
mmf->tree->compress();
QGlyphTree::balance(mmf->tree);
}
}
n += 3;
count++;
}
else if ( ( (unsigned char)ch[n] ) >> 7 == 0x0 )//单字节
{
n ++;
}
else if( ( (unsigned char)ch[n]) >> 5 == 0x6 )//双字节
{
n += 2;
}
}
}
mmf->tree->compress();
QGlyphTree::balance(mmf->tree);
//qDebug("DUMP..."); mmf->tree->dump();
QFile f(fontFilename(mmf->def));
f.open(IO_WriteOnly);
f.writeBlock((char*)&mmf->fm,sizeof(mmf->fm));
mmf->tree->write(f);
}
}
以上就是修改代码的过程
9.修改buildqte shell脚本.
把buildqte脚本中的下面一行注释掉
./configure -qt-gfx-transformed -qvfb
./buildqte 重新编译qte库
10.编译makeqpf工具(qte用这个工具来生成qpf字库).
注意:makeqpf一定要编译成qte的版本,不能编译成x11版本
cd /qte/qte/tools/makeqpf
../../bin/qmake -project
../../bin/qmake
make
(请按上面的命令执行)
11. 修该fontdir文件
fontdir文件一般默认在/usr/lib/qt-3.1/lib/fonts/目录下
具体修改,应该大家都清楚怎么做了.
下面是我的fontdir文件的内容
unifont unifont_160_50.qpf QPF n 50 160 su
#simfang simfang.bdf BDF n 50 140 su
#simfang simfang.ttf FT n 50 140 su
#simfnag simfang.pcf PCF n 50 140 su
#simfang simfang_140_50.qpf QPF n 50 140 su
#simfang simfang.ttf FT n 50 120 su
#simfang simhei_120_50.qpf QPF n 50 120 su
#simhei simhei.ttf FT n 50 140 su
#simhei simhei_140_50.qpf QPF n 50 140 su
#simkai simkai.ttf FT n 50 130 su
#simkai simkai_130_50.qpf QPF n 50 130 su
#
zysong zysong.ttf FT n 50 120 su
zysong zysong_120_50.qpf QPF n 50 120 su
12. 最后就是运行makeqpf生成qpf字库
makeqpf可以在framebuffer中运行,也可以在qvfb中运行.
运行后你可以去看看自己的成果了,字库是不是小了.
后记:
字库提取的问题困扰了很久,我只用几百个汉字,但是每次生成的字库很大,对嵌入式来说存储空间是很不划算的.
现在我的办法有点笨,但是总算能解决这个问题了,所以第一时间给大家共享出来,希望也能帮上你的忙.
也希望大家提出建议和指出错误,如果有有心人,还希望能够在完善这个过程.(因为本人的办法确实还是比较麻烦.)
这篇文档大家可以随意转载.我本人只保留所有权.转载请注明作者和出处.
2007/04/22
刘志文
lzwwiner@163.com
更多阅读
如何从QQ朋友网中提取QQ号 从朋友网提取qq号码
如何从QQ朋友网中提取QQ号——简介很多人,在使用QQ朋友网时,通过朋友网中的二度人脉,找到失散多年的同学,好朋友,又或者曾经暗恋的对象。很兴奋的去Ta朋友主页看了看,但很想得知Ta的QQ,但归于,腾讯朋友网是QQ旗下的一个真实社交平台,所以很
五类美女从酒局中开始沦陷(图) 白宫沦陷类似电影
有些美女在酒局中,肚子不是喝坏了,而是喝大了支持原创,网络转载署名!五类美女从酒局中开始沦陷■易孑草 第一种:渴望从酒局渗透进权力层的女人年轻女人想进步快,往往在按部就班的职场,不得其门而入。酒局为她们敞开了一道“旁门”。
怎么将某章节从DVD中提取出来 dvd按章节提取
怎么将花絮从DVD中提取出来??这个问题超级简单啦...用DVDShrink就可以做到了详细提取花絮步骤:1:将碟片放进光驱(或将镜像载入虚拟光驱),这个人人都懂了吧?(晕~第一句就是废话)2:启动DVDShrink,然后打开要提取花絮的碟片,界面显示"A
著名书法家字体字库下载 cad2007字体库下载
著名书法家字体字库下载1本人精心搜集整理一批著名书法家字库字体,并经过本人安装使用正常,字体示范均为同一字体,方便挑选,为广大书法爱好者提供免费下载,其中包括:王羲之字体,黄庭坚字体,毛泽东字体,启功字体,舒同字体,全真颜真卿字体,孙过庭
从毛发中提取胱氨酸 同型半胱氨酸偏高
从毛发中提取胱氨酸胱氨酸是由两个β-巯基-a-氨基丙酸组织的含硫氨基酸,学名为双巯丙氨酸,白色六角形板状晶体或结晶粉末,不溶于乙醇、乙醚,难溶于水。易溶于酸、碱溶液,但在热碱溶液中可被分解。胱氨酸存在于人发、猪毛、羊毛、马毛、