【项目1_电子书】第2.3.3课、在LCD上显示一个矢量字体

时间:2022-01-10 16:12:30

主 机:VMWare--Ubuntu-16.04.2-x64-100ask
开发板:Mini2440--256M NandFlash,   2M NorFlash,   64M SDRAM,   LCD-TD35;
    bootlorder:u-boot1.16,      Kernel:4.3.2;
编译器:arm-linux-gcc-4.3.2


 

1、查看原来mini2440开发板的数据
SMDK2410 # print
baudrate=115200
bootargs=console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.1.105:/work/nfs_root/fs_mini_mdev_new ip=192.168.1.44:192.168.1.105:192.168.1.1:255.255.255.0::eth0:off
bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0
bootdelay=10
ethact=dm9000
ethaddr=08:00:3e:26:0a:5b
fileaddr=30000000
filesize=791340
ipaddr=192.168.1.44
machid=7cf
mtddevname=u-boot
mtddevnum=0
mtdids=nand0=jz2440-0
mtdparts=mtdparts=jz2440-0:256k(u-boot),128k(params),2m(kernel),-(rootfs)
netmask=255.255.255.0
partition=nand0,0
serverip=192.168.1.105
stderr=serial
stdin=serial
stdout=serial

Environment size: 631/131068 bytes
SMDK2410 # set bootargs noinitrd console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.0.106:/work/nfs_root/fs_mini_mdev_new ip=192.168.0.44:192.168.0.106:192.168.0.1:255.255.255.0::eth0:off
SMDK2410 # save
SMDK2410 # set serverip 192.168.0.106
SMDK2410 # save


set bootargs noinitrd console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.0.101:/work/nfs_root/fs_mini_mdev_new ip=192.168.0.44:192.168.0.101:192.168.0.1:255.255.255.0::eth0:off
nfs 32000000 192.168.0.101:/work/nfs_root/uImage_lcd_3th; bootm 32000000

set bootargs noinitrd console=ttySAC0,115200 root=/dev/nfs nfsroot=192.168.0.106:/work/nfs_root/fs_mini_mdev_new ip=192.168.0.44:192.168.0.106:192.168.0.1:255.255.255.0::eth0:off
nfs 32000000 192.168.0.106:/work/nfs_root/uImage_lcd_3th; bootm 32000000

 

2.操作笔记

2. Configuration
2.1. Building and target system
To configure for cross-build, the options `--host=<system>' and
`--build=<system>' must be passed to configure. For example, if
your building system is FreeBSD/i386 and the target system is
Linux/MIPS, say

./configure \
--build=i386-unknown-freebsd \
--host=mips-ip22-linuxelf \
[other options]

2.2. The prefix to install FreeType2
Setting `--prefix=<prefix>' properly is important. The prefix
to install FreeType2 is written into the freetype-config script
and freetype2.pc configuration file.

If the built FreeType 2 library is used as a part of the
cross-building system, the prefix is expected to be different
from the self-building system. For example, configuration with
`--prefix=/usr/local' installs binaries into the system wide
`/usr/local' directory which then can't be executed.
翻译:
安装FreeType2的前缀正确设置'——prefix=<prefix>'非常重要。安装FreeType2的前缀被写入
到freetype-config脚本和FreeType2.pc配置文件中。

如果构建的FreeType 2库用作交叉构建系统的一部分,那么前缀应该与自构建系统不同。例如,
带有“--prefix=/usr/local”的配置将二进制文件安装到系统范围的“/usr/local”目录中,然后
无法执行该目录。这将导致使用FreeType2的所有应用程序的配置混乱。相反,使用前缀将交叉构建安
装到单独的系统树中,例如,'——prefix=/usr/local/mips-ip22-linux/'。

另一方面,如果构建的FreeType2用作目标系统的一部分,则安装的前缀应该反映目标系统的文件系统结构。

4. Installation
Saying
make install

In such cases, the make variable `DESTDIR' is useful to change the root
directory in the installation. For example, after
make DESTDIR=/mnt/target_system_root/ install

2.1配置时的参数项设置
解释:
.configure --host=arm-linux //表示编译出来的程序是在arm开发板的linux系统下使用,;
--build=... //build表示PC机,一般不用管;
--prefix= //若无此项,默认安装在根目录/的/usr/local目录(供PC机使用)下,若想按照到交叉编译工具链(供arm开发板使用),则:
需要前缀安装到该目录?
编译出来的头文件应该放入:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
编译出来的库文件应该放入:
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
一般来说,lib和include的目录应该是一样的,即都是/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/ usr/或armv4t/,则只需要添加:
--prefix=/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/ usr/或armv4t/
即可。
但我们的编译工具链里面头文件和库文件的目录不一样,因此我们只能自己复制,如此就无需再前缀--prefix=。先把它们编译出来,然后再分
别copy到这些目录里面去。安装的时候,先安装到一个临时目录。
示例:
./configure --host=arm-linux
make
make DESTDIR=$PWD/tmp install //$PWD为当前的.../freetype-2.4.10目录; tmp为临时创建的目录;

2.2安装
把tmp/usr/local/lib/* 复制到 /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
sudo cp * /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib -d -rf
cp *so* /work/nfs_root/fs_mini_mdev_new/lib -d

把tmp/usr/local/include/* 复制到 /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
cp * /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include -rf
cd /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
mv freetype2/freetype .

如此,便已交叉编译了我们的freetype-2.4.10并安装(freetype-2.4.10的头文件和库文件)到交叉编译工具链里面去了。

 

arm-linux-gcc -finput-charset=GBK -o example1 example1.c -lfreetype -lm //前缀-finput-charset=GBK 必须在-o前面;
arm-linux-gcc -finput-charset=GBK -o show_font show_font.c -lfreetype -lm
注意:-finput-charset=GBK必须添加,否则'韦'字将打印成'T'字符;


3、上机操作
--------------------------------
一、在arm终端显示汉字字体
book@www.100ask.org:/usr/local/arm/4.3.2/bin$ echo $PATH
/home/book/bin:/home/book/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/arm/4.3.2/bin:/snap/bin
book@www.100ask.org:/usr/local/arm/4.3.2/bin$ cd /usr/local/arm/4.3.2/
book@www.100ask.org:/usr/local/arm/4.3.2$ ls
arm-none-linux-gnueabi bin lib libexec share
book@www.100ask.org:/usr/local/arm/4.3.2$ find -name include
./arm-none-linux-gnueabi/include
./arm-none-linux-gnueabi/libc/usr/include
./lib/gcc/arm-none-linux-gnueabi/4.3.2/include
./lib/gcc/arm-none-linux-gnueabi/4.3.2/install-tools/include
book@www.100ask.org:/usr/local/arm/4.3.2$ find -name stdio.h
./arm-none-linux-gnueabi/include/c++/4.3.2/tr1/stdio.h
./arm-none-linux-gnueabi/libc/usr/include/stdio.h
./arm-none-linux-gnueabi/libc/usr/include/bits/stdio.h
book@www.100ask.org:/usr/local/arm/4.3.2$ cd ./arm-none-linux-gnueabi/libc/usr/include/
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ pwd
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include

book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ find -name lib
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ cd /usr/local/arm/
book@www.100ask.org:/usr/local/arm$ find -name lib
./4.3.2/arm-none-linux-gnueabi/lib
./4.3.2/arm-none-linux-gnueabi/libc/thumb2/usr/lib
./4.3.2/arm-none-linux-gnueabi/libc/thumb2/lib
./4.3.2/arm-none-linux-gnueabi/libc/usr/lib
./4.3.2/arm-none-linux-gnueabi/libc/armv4t/usr/lib
./4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
./4.3.2/arm-none-linux-gnueabi/libc/lib
./4.3.2/lib
book@www.100ask.org:/usr/local/arm$ cd ./4.3.2/arm-none-linux-gnueabi/libc/armv4t/
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t$ ls
etc lib sbin usr
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t$ pwd
/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype$ cd freetype-2.4.10
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10$ ./configure --host=arm-linux
...省略打印信息...
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10$ make
...省略打印信息...

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10$ pwd
/home/book/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10$ ls -l tmp
ls: cannot access 'tmp': No such file or directory
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10$ make DESTDIR=$PWD/tmp install
...省略打印信息...

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10/tmp/usr/local$ ls
bin include lib share
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10/tmp/usr/local$ sudo cp lib/* /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib -d -rf
[sudo] password for book:
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10/tmp/usr/local$ sudo cp include/* /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include -rf
如此,便已交叉编译了我们的freetype-2.4.10并安装(freetype-2.4.10的头文件和库文件)到交叉编译工具链里面去了。然后,
编译一下我们的测试程序example1.c,看是否可以编译成功。

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ arm-linux-gcc -o example1 example1.c
In file included from example1.c:12:
/usr/local/arm/4.3.2/bin/../arm-none-linux-gnueabi/libc/usr/include/ft2build.h:56:38: error: freetype/config/ftheader.h: No such file or directory

解决:
ft2build.h文件要用的文件ftheader.h(freetype/config/ftheader.h)的实际位置是:
freetype2/freetype/config/ftheader.h
方法1:
指定目录
gcc -o example1 example1.c -I /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include/freetype2 -lfreetype -lm
方法2:直接移动/freetype到/include下:
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ mv freetype2/freetype .
mv: cannot move 'freetype2/freetype' to './freetype': Permission denied
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ sudo mv freetype2/freetype .
[sudo] password for book:
book@www.100ask.org:/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include$ find -name ftheader.h
./freetype/config/ftheader.h

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ arm-linux-gcc -o example1 example1.c
/tmp/ccKxTYqr.o: In function `main':
example1.c:(.text+0x384): undefined reference to `FT_Init_FreeType'
example1.c:(.text+0x3b4): undefined reference to `FT_New_Face'
...问题:函数未定义
example1.c:(.text+0x3e8): undefined reference to `cos'
example1.c:(.text+0x438): undefined reference to `sin'
...数学函数未定义
函数未定义,加上动态库即可 -lfreetype;
数学函数未定义,加上数学库即可 -lm;
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ arm-linux-gcc -o example1 example1.c -lfreetype
/tmp/ccMKLujp.o: In function `main':
example1.c:(.text+0x3e8): undefined reference to `cos'
...
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ arm-linux-gcc -o example1 example1.c -lfreetype -lm

 

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype$ sudo cp simsun.ttc /work/nfs_root/fs_mini_mdev_new/driver_test3/2.3freetype/
[sudo] password for book:
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype$ ls
01th_pc 02th_arm freetype-2.4.10 freetype-2.4.10_pc freetype-2.4.10.tar.bz2 simsun.ttc
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype$ sudo cp 02th_arm/ /work/nfs_root/fs_mini_mdev_new/driver_test3/2.3freetype/ -rf

开发板:/driver_test3/2.3freetype/02th_arm/01th # ./example1
./example1: error while loading shared libraries: libfreetype.so.6: cannot open shared object file: No such file or directory
主机:book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/freetype-2.4.10/tmp/usr/local/lib$ sudo cp *so* /work/nfs_root/fs_mini_mdev_new/lib/ -d
[sudo] password for book:

开发板:/driver_test3/2.3freetype/02th_arm/01th # ./example1 ../../simsun.ttc
...Tgif

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ arm-linux-gcc -finput-charset=GBK -o example1 example1.c -lfreetype -lm
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ ls
example1 example1.c
book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/01th$ sudo cp example1 /work/nfs_root/fs_mini_mdev_new/driver_test3/2.3freetype/02th_arm/01th
[sudo] password for book:
开发板:/driver_test3/2.3freetype/02th_arm/01th # ./example1 ../../simsun.ttc
...韦gif
如此,即实现同样一个应用程序,可以在PC机上执行,交叉编译之后可以在开发板上运行。
但是不想只在控制台(开发板终端)上输出,想在开发板LCD上输出,怎么做?
在原来2.2字符点阵显示程序show_font.c的基础上修改:


--------------------------------
二、在arm开发板显示矢量字体
1.face 可否翻译为: 字形?或者字型?
2.对于fb_put_pixel(i, j, bitmap->buffer[(j - y)*bitmap->width + (i - x)]);中,buffer的数据类型是unsigned char *类型,
因此,为单字节,其代表的颜色为蓝色;

3.arm-linux-gcc -finput-charset=GBK -fexec-charset=GBK -o show_font show_font.c -lfreetype -lm
用SourcInsight工具,是ASCII编码方式(基本都是,可以用'记事本'工具打开查看编码方式),对于源码中的汉字,在简体中文PC机,汉字用的都是国标码GBK。
-finput-charset=GBK:编译时指定汉字的编码方式为国标码; 即输入是国标码。
-fexec-charset=GBK:输出是国标码。
是为了让str[]里面存的是国标码,因为源码下面部分printf("chinese code: %02x %02x\n", str[0], str[1]);
是用国标码来找到汉字的点阵的。

unsigned char str[] = "我";
输入是国标码,输出也是国标码是指存储 “ unsigned char str[] = "我"; ” 的时候,
输入文件里面是国标码,当编译出来的应用程序在str[]的数组内存里面也是存的国标码。

wchar_t chinese_str[] = L"繁";
输入是国标码,但是在字符串chinese_str[]的数组内存里面存储的是宽字符的类型,
宽字符的类型里面即Unicode码。


4、编译及错误解决:
$ arm-linux-gcc -o show_font_1 show_font_1.c -lfreetype -lm
show_font_1.c:4769:26: error: converting to execution character set: Invalid or incomplete multibyte or wide character
【注:】4769: wchar_t chinese_str[] = L"繁";
$ arm-linux-gcc -finput-charset=GBK -o show_font_1 show_font_1.c -lfreetype -lm
cc1: error: failure to convert GBK to UTF-8
$ arm-linux-gcc -finput-charset=GBK -fexec-charset=GBK -o show_font_1 show_font_1.c -lfreetype -lm
$man gcc
/charset
【...
charset can be any encoding supported by the system's "iconv" library routine.

$ iconv --help

Usage: iconv [OPTION...] [FILE...]
Convert encoding of given files from one encoding to another.
Input/Output format specification:
-f, --from-code=NAME encoding of original text
-t, --to-code=NAME encoding for output

Information:
-l, --list list all known coded character sets

Output control:
-c omit invalid characters from output
-o, --output=FILE output file
-s, --silent suppress warnings
--verbose print progress information

-?, --help Give this help list
--usage Give a short usage message
-V, --version Print program version
Mandatory or optional arguments to long options are also mandatory or optional
for any corresponding short options.

book@www.100ask.org:~/workbook/mini2440/3th_project/2.3freetype/02th_arm/02th_lcd$ iconv -f GBK -t UTF-8 show_font_1.c
...源码...
/* 128 0x80 'iconv: illegal input sequence at position 48126
修改:/* 128 0x80 '€' */ 去掉: '€'
/* 255 0xff 'iconv: illegal input sequence at position 95371
修改:/* 255 0xff '' */ 去掉:''
<结束>
$ arm-linux-gcc -finput-charset=GBK -fexec-charset=GBK -o show_font_1 show_font_1.c -lfreetype -lm
$ ls
show_font show_font_1 show_font_1.c show_font.c
$ sudo cp show_font_1 /work/nfs_root/fs_mini_mdev_new/driver_test3/2.3freetype/02th_arm/

--------------------------------------
三、在arm开发板显示旋转的矢量字体
源码修改:
FT_Matrix matrix; /* 变换矩阵 */
double angle;

angle = ( 1.0*strtoul(argv[2], NULL, 0)/360 ) * 3.14159 * 2; /* use 25 degrees */
/* 设置矩阵 */
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
FT_Set_Transform( face, &matrix, &pen ); /* 设置转换参数: 旋转0度 */
操作:
$ arm-linux-gcc -finput-charset=GBK -fexec-charset=GBK -o show_font_5 show_font_5.c -lfreetype -lm
$ sudo cp show_font_5 /work/nfs_root/fs_mini_mdev_new/driver_test3/2.3freetype/02th_arm/03th_lcd_angle
# ./show_font_5 ../../simsun.ttc 90 //矢量字体“龘”旋转90度;
chinese code: ce d2
|打印:A我龘

函数定义:
unsigned long strtoul(const char *nptr,char **endptr,int base);
函数说明:
strtoul()会将参数nptr字符串根据参数base来转换成无符号的长整型数。参数base范围从2至36,或0。参数base代表采用的进制方式,
如base值为10则采用10进制,若base值为16则采用16进制数等。当base值为0时会根据情况选择用哪种进制:如果第一个字符是'0',就
判断第二字符如果是‘x’则用16进制,否则用8进制;第一个字符不是‘0’,则用10进制。一开始strtoul()会扫描参数nptr字符串,跳过
前面的空格字符串,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时('')结束转换,并将结果返回。若参数endptr
不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。

 


 源码show_font.c

  1 /* 
  2  * 2019-07-26
  3  * 目的: 1.显示字符、汉字的应用程序;  2.显示矢量字体(汉字);
  4  */
  5 #include <stdio.h>
  6 #include <sys/mman.h>
  7 #include <sys/types.h>
  8 #include <sys/stat.h>
  9 #include <unistd.h>
 10 #include <linux/fb.h>
 11 #include <string.h>
 12 #include <fcntl.h>
 13 
 14 #include <math.h>
 15 #include <wchar.h>
 16 #include <ft2build.h>
 17 #include <stdlib.h>
 18 #include FT_FREETYPE_H
 19 #include FT_GLYPH_H
 20 
 21 #define FONTDATAMAX 4096
 22 
 23 static const unsigned char fontdata_8x16[FONTDATAMAX] = {...省略...};
 24 
 25 int fd_fb;
 26 int fd_hzk16;
 27 static unsigned char *fbmem;            /* fb的起始地址 */
 28 static unsigned char *hzkmem;
 29 static struct fb_var_screeninfo var;
 30 static struct fb_fix_screeninfo fix;
 31 static struct stat hzk_stat;
 32 
 33 /*
 34  * color: 0x00RRGGBB
 35  */
 36 static unsigned short convert32to16(int color)
 37 {
 38     int red, green, blue;
 39     red = (color>>16) & 0xff;
 40     green = (color>>8) & 0xff;
 41     blue = (color>>0) & 0xff;
 42     return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);        //color: 565
 43 }
 44 
 45 /* 画点
 46  * color: 32bit, 0x00RRGGBB
 47  * 归根结底,是在帧缓冲器中填写数据,然后扫描显示到LCD屏幕;
 48  */
 49 static void fb_put_pixel(int x, int y, unsigned int color)
 50 {
 51     unsigned char * pen_8;
 52     unsigned short *pen_16;
 53     unsigned int *pen_32;
 54     unsigned char *pixel_base = fbmem + (var.xres*y + x)*var.bits_per_pixel/8;
 55 
 56     switch(var.bits_per_pixel)
 57     {
 58         case 8:
 59             pen_8 = (unsigned char *)pixel_base;
 60             *pen_8 = color;
 61             break;
 62         case 16:
 63             pen_16 = (unsigned short *)pixel_base;
 64             *pen_16 = convert32to16(color);
 65             break;
 66         case 32:
 67             pen_32 = (unsigned int *)pixel_base;
 68             *pen_32 = color;
 69             break;
 70         default:
 71             printf("can't surpport %dbpp\n", var.bits_per_pixel);
 72             break;
 73     }
 74 }
 75 
 76 /* 画ASCII码字符: 8x16 */
 77 static void fb_print_char(int x, int y, unsigned char c, int color)
 78 {
 79     int bit, j;
 80     unsigned char data;
 81     /* 1.从fontdata_8x16[]数组取得字符c的数据 */
 82     unsigned char *dots = (unsigned char *)&fontdata_8x16[c*16];
 83 
 84     /* 2.根据数据,在帧缓冲器fb中填写数据 */
 85     for(j = 0; j < 16; j++)
 86     {
 87         data = *dots++;
 88         for(bit = 7; bit >= 0; bit--)
 89         {
 90             if(data & (1<<bit))        /* show */
 91             {
 92                 fb_put_pixel(x + 7 - bit, y + j, 0xffffff);        /* 白色 */     
 93             }
 94             else                    /* hide */
 95                 fb_put_pixel(x + 7 - bit, y + j, 0);            /* 黑色 */
 96         }
 97     }
 98 }
 99 
100 /* 画GB2312中文字
101  * HZK16: 16x16
102  */
103 static void fb_print_chinese(int x, int y, unsigned char * str, unsigned int color)
104 {
105     unsigned char area_code = str[0] - 0XA1;    /* 区码 */
106     unsigned char byte_code = str[1] - 0XA1;    /* 位码 */
107     
108     
109     /* 1.从HZK16取得字*str的数据 */
110     unsigned char *dots = hzkmem + (area_code*94 + byte_code)*32;
111     /* 2.根据数据,在帧缓冲器fb中填写数据 */
112     int i, j, bit;
113     unsigned char data;
114 
115     for(j = 0; j < 16; j++)
116     {
117         for(i = 0; i < 2; i++)
118         {
119             data = dots[j*2 + i];
120             for(bit = 7; bit >= 0; bit--)
121             {
122                 if(data & (1<<bit))        /* show */
123                 {
124                     fb_put_pixel(x + i*8 + (7 - bit), y + j, 0xffffff);        /* 白色 */
125                 }
126                 else                    /* hide */
127                     fb_put_pixel(x + i*8 + (7 - bit), y + j, 0);            /* 黑色 */
128             }
129         }
130     }
131 }
132 
133 /* 绘制字符位图 */
134 void draw_bitmap(FT_Bitmap * bitmap, FT_Int x, FT_Int y)
135 {
136     FT_Int i, j;
137 
138     for(j = y; j < y + bitmap->rows; j++)
139         for(i = x; i < x + bitmap->width; i++)
140         {
141             if(i < 0 || j < 0 || i >= var.xres || j >= var.yres)
142                 continue;
143             //image[j][i] |= bitmap->buffer[(j - y)*bitmap->width + (i - x)];
144             fb_put_pixel(i, j, bitmap->buffer[(j - y)*bitmap->width + (i - x)]);
145         }
146 }
147 
148 
149 int main(int argc, char **argv)
150 {
151     FT_Library    library;
152     FT_Face       face;
153 
154     FT_GlyphSlot  slot;
155     FT_Vector     pen;                    /* 未转换的起始点 */
156     FT_Matrix     matrix;                 /* 转换矩阵 */
157 
158     double        angle;
159     int error;
160     
161     unsigned char str[] = "";
162     wchar_t chinese_str[] = L"";
163 
164     if(argc != 3)
165     {
166         printf("Usage: %s <font_file> <angle>\n", argv[0]);
167         return -1;
168     }
169     
170     /* 一、显示固定尺寸的汉字/字符 */
171     /* 1、LCD初始化 */
172     fd_fb = open("/dev/fb0", O_RDWR);
173     if(fd_fb < 0)
174     {
175         printf("can't open /dev/fb0\n");
176         return -1;
177     }
178     if(ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))        //可变参数,成功,返回0; 出错,返回-1;
179     {
180         printf("can't get var\n");
181         return -1;
182     }
183     if(ioctl(fd_fb, FBIOGET_FSCREENINFO, &fix))        //固定参数,成功,返回0; 出错,返回-1;
184     {
185         printf("can't get fix\n");
186         return -1;
187     }
188 
189     fbmem = (unsigned char *)mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
190     if(fbmem == (unsigned char *)-1)
191     {
192         printf("can't mmap fbmem\n");
193         return -1;
194     }
195     
196     /* 2、HZK16初始化 */
197     fd_hzk16 = open("HZK16", O_RDONLY);
198     if(fd_hzk16 < 0)
199     {
200         printf("can't open HZK16\n");
201         return -1;
202     }
203     if(fstat(fd_hzk16, &hzk_stat))        //成功,返回0; 失败,返回-1;
204     {
205         printf("can't get fd_hzk16 fstat\n");
206         return -1;
207     }
208     hzkmem = (unsigned char *)mmap(NULL, hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
209     if(fbmem == (unsigned char *)-1)
210     {
211         printf("can't mmap hzkmem\n");
212         return -1;
213     }
214     
215     /* 3、清屏,然后在LCD屏*打印字符'A'和汉字"我" */
216     memset(fbmem, 0, fix.smem_len);
217     fb_print_char(var.xres/2, var.yres/2, 'A', 0xffffff);
218     fb_print_chinese(var.xres/2 + 8, var.yres/2, str, 0xffffff);
219     printf("chinese code: %02x %02x\n", str[0], str[1]);
220 
221 
222     /* 二、显示矢量字体 */
223     error = FT_Init_FreeType( &library );              /* 初始化 Freetype 库 */
224     if(error)
225     {
226         printf("FT_Init_FreeType error.\n");
227         return -1;
228     }
229       error = FT_New_Face( library, argv[1], 0, &face );     /* 打开一个字体文件 */
230       if(error)
231     {
232         printf("FT_New_Face error.\n");
233         return -1;
234     }
235     slot = face->glyph;
236     FT_Set_Pixel_Sizes(face, 24, 0);
237     /* 确定起始点坐标:
238      * 位置: 紧挨着'我'字排列;
239      * lcd_x = var.xres/2 + 8 + 16;
240      * lcd_y = var.yres/2 + 16;
241      * 笛卡尔坐标系:
242      * x = lcd_x = var.xres/2 + 8 + 16;
243      * y = var.yres - lcd_y = var.yres/2 - 16;
244      */
245     pen.x = (var.xres/2 + 8 + 16)*64;
246       pen.y = (var.yres/2 - 16)*64;
247 
248     angle = ( 1.0 * strtoul(argv[2], NULL, 0) / 360 ) * 3.14159 * 2;                  /* use 25 degrees */
249     /* set up matrix */
250     matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
251     matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
252     matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
253     matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
254     FT_Set_Transform( face, &matrix, &pen );            /* 设置转换参数: 旋转0度 */
255 
256     /* 根据编码值加载glyph到slot */
257     error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );
258     if(error)
259     {
260         printf("FT_Load_Char error.\n");
261         return -1;
262     }
263     draw_bitmap( &slot->bitmap,
264                  slot->bitmap_left,
265                  var.yres - slot->bitmap_top );
266 
267     return 0;
268 }