ASCII

ascii是“American Standard Code for Information Interchange”的缩写, 美国信息交换标准代码。

电脑毕竟是西方人发明的,他们常用字母就 26 个,区分大小写、加上标点符号也没超过 127 个,每个字符用一个字节来表示就足够了。一个字节的 7 位就可以表示 128 个数值,在 ASCII 码中最高位永远是 0。

linux-4.18.16/lib/fonts这个目录下就有对应文件。在这里我挑选font_8x16.c

 

 

ANSI

ASNI 是 ASCII 的扩展,向下包含 ASCII。对于 ASCII 字符仍以一个字节来表示.

对于非 ASCII 字符则使用 2 字节来表示。并没有固定的 ASNI 编码.

比如在中国大陆地区, ANSI 的默认编码是 GB2312;

在港澳台地区默认编码是 BIG5。以数值“ 0xd0d6”为例,对于 GB2312 编码它表示“中”;对于 BIG5 编码它表示“ 笢”。

用ANSI编码字符’aa中’的16进制数据

 

UNICODE

在 ANSI 标准中,很多种文字都有自己的编码标准,汉字简体字有 GB2312、繁体字有 BIG5,这难免同一个数值对应不同字符。比如数值“ 0xd0d6”,对于GB2312 编码它表示“中”;对于 BIG5 编码它表示“ 笢”。这造成了使用 ANSI 编码保存的文件,不适合跨地区交流。

UNICODE 编码就是解决这类问题:对于地球上任意一个字符,都给它一个唯一的数值。

  1. ASCII 编码中使用一个字节来表示一个字符,只用到其中的 7 位,最高位恒为 0;
  2. ANSI 编码中,对于 ASCII 字符仍使用一个字节来表示(BIT7 是 0),对于非ASCII 字符一般使用 2 个字节来表示,非 ASCII 字符的数值 BIT7 都是 1

UTF-16 LE

每个 UNICODE 值用 3 字节来表示有点浪费,那只用 2 字节呢?它可以表示2^16=65536 个字符,全世界常用的字符都可以表示了。Little endian 表示小字节序,数值中权重低的字节放在前面,比如字符“ A 中”在 TXT 文件中的数值如下,其中的“ A”使用“0x41 0x00”两字节表示;“中”使用“ 0x2d 0x4e”两字节表示。文件开头的“ 0xff 0xfe”表示“UTF-16 LE”。

 

UTF-16 BE

Big endian 表示大字节序,数值中权重低的字节放在后面,比如字符“ ab中”在 TXT 文件中的数值如下,其中的“ A”使用“ 0x00 0x41”两字节表示;“中”使用“ 0x4e 0x2d”两字节表示。文件开头的“ 0xfe 0xff”表示“UTF-16 BE”

 

UTF8

UTF8 是一种变长的编码方法,有 2 种 UTF8格式的文件:带有头部、不带头部。

 

对于 ASCII 字符用UTF-16有空间浪费、而且文件中有某个字节丢失,这会使得后面所有字符都因为错位而无法显示。UTF8则不会有这样的问题。0x41表示大写字母’A’,只用了一个字节。上图中的 3 个字节“ 0xe4 0xb8 0xad”表示的数值是 0x4e2d,对应“中”的 UNICODE 码.

 

上图中, 0xe4 的二进制是“ 11100100”,高位有 3 个 1,表示从当前字节起有 3 字节参与表示 UNICODE;

0xb8 的二进制是“10111000”,高位有 1 个 1,表示从当前字节起有 1 字节参与表示 UNICODE;

0xad 的二进制是“10101101”,高位有 1 个 1,表示从当前字节起有 1 字节参与表示 UNICODE;

除去高位的“ 1110”、“ 10”、“ 10”后,剩下的二进制数组合起来得到“ 01001110001101”,它就是 0x4e2d,即“中”的 UNICODE 值。

使用 UTF8 编码时,即使 TXT 文件中丢失了某些数据,也只会影响到当前字符的显示,后面的字符不受影响。

中文字库移植

-finput-charset -fexec-charset编译选项

我们编写 C 程序时,可以使用 ANSI 编码,或是 UTF-8 编码;在编译程序时,可以使用以下的选项告诉编译器用什么方式编码:

-finput-charset=GB2312

-finput-charset=UTF-8

如果不指定“ -finput-charset”, GCC 就会默认 C 程序的编码方式为 UTF8。

1.用ANSI格式编写编码,vim浏览显示会乱码,用notepad++采用ANSI编码格式浏览.

 

由于编译器默认用utf8编码,所以看到最终打印是乱码的。可以看到“中”的ANSI码是d6 d0。

2.用utf8编写代码

 

 

最终打印是OK的。可以看到“中”的utf8码是e4 b8 ad.

GB2312 转为 UTF-8

 

从上面的输出信息可以看出来, GB2312 的”0xd6 0xd0″可以转换为 UTF-8的“ 0xe4 0xb8 0xad”。而如果把原本就是 UTF-8 格式的 test_charset_utf8.c当作 GB2312 格式,会引起错误

UTF-8 转为 GB2312

 

从 上 面 的 输 出 信 息 可 以 看 出 来 , 如 果 把 原 本 就 是 GB2312 格 式 test_charset_ansi.c 当成UTF-8 格式,会引起错误。而 UTF-8 格式的“中”编码值为“ 0xe4 0xb8 0xad”,可以转换为 GB2312 的“0xd6 0xd0”

HZK16中文字库

HZK16字库里的16×16汉字一共需要256个点来显示,也就是说需要32个字节才能达到显示一个普通汉字的目的。符合GB2312标准。

一个GB2312汉字是由两个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有94个字符。

HZK16 中是以 GB2312 编码值来查找点阵的,以“中”字为例,它的编码值是“ 0xd6 0xd0”,其中的 0xd6 表示“区码”,表示在哪一个区;其中的 0xd0 表示“位码”,表示它是这个区里的哪一个字符。每一个区有 94 个汉字。区位码从 0xa1 而不是从 0 开始,是为了兼容 ASCII码。

要显示“中”字, 它的 GB2312 编码是 d6d0,它是 HZK16 里第“ (0xd6-0xa1)*94+(0xd0-0xa1)”个字符。(0xd6-0xa1)表示是哪个区,(0xd0-0xa1)表示是哪个位。

 

如何获取和显示汉字”中“?

fd_hzk16 = open("HZK16", O_RDONLY);
if (fd_hzk16 < 0){
        printf("can't open HZK16\n");
        return -1;
}
if(fstat(fd_hzk16, &hzk_stat)){
        printf("can't get fstat\n");
        return -1;
}
hzkmem = (unsigned char *)mmap(NULL , hzk_stat.st_size, PROT_READ, MAP_SHARED, fd_hzk16, 0);
if (hzkmem == (unsigned char *)-1){
        printf("can't mmap for hzk16\n");
        return -1;
}

下载HZK16字库,读取并且mmap字库。

 

 

 

 

 该函数在 LCD 的(x,y)位置处显示汉字字符 str, str[0]中保存区码、 str[1]中保存位码。

第 4734 行确定该汉字属于哪个区;第 4735 行确实它是该区中哪一个汉字。

第 4736 行确实它的字库地址(第多少个字节):每个区中有 94 个汉字,每个汉字在字库中占据 32 字节。

根据下图来理解字库中每个像素点是如何显示的。

 

总共有十六行,因此需要一个循环 16次的大循环(第 4740 行)。

考虑到一行有两个字节, 在大循环中加入一个 2 次的循环用于区分是哪个字节(第 4741 行)。

最后使用第 3 个循环来处理一个字节中的 8 位(第 4744 行)。对于每一位,它等于 1 时对应的像素被设置为白色,它等于 0 时对应的像素被设置为黑色。需要注意的是根据 x、 y、 i、 j、 b 来计算像素坐标。

测试:

 

注意:使用上述命令时 show_chinese.c 的编码格式必须是 ANSI(GB2312),因为HZK16字库是按照GB2312编码的,否则编译时需要指定“ -fexec-charset=GB2312”。

freetype移植

FreeType库是一个完全免费(开源)的、高质量的且可移植的字体引擎。

Freetype 是开源的字体引擎库, 它提供统一的接口来访问多种字体格式文件,从而实现矢量字体显示。我们只需要移植这个字体引擎,调用对应的 API 接口,提供字体文件,就可以让 freetype 库帮我们取出关键点、实现闭合曲线, 填充

颜色, 达到显示矢量字体的目的。

这里仅移植freetype库,freetype的使用不做具体展开。可以从 https://www.freetype.org/ 可 以 下 载 到 “ freetype-doc-2.10.2.tar.xz”。

什么是矢量字体

使用点阵字库显示英文字母、汉字时, 大小固定, 如果放大缩小则会模糊甚

至有锯齿出现,为了解决这个问题,引用矢量字体。

第1步 确定关键点,

第2步 使用数学曲线( 贝塞尔曲线) 连接头键点,

第3步 填充闭合区线内部空间。

什么是关键点?以字母“ A”为例

 

再用数学曲线(比如贝塞尔曲线)将关键点都连接起来, 得到一系列的封闭的曲线

 

 

 最后把封闭空间填满颜色,就显示出一个 A 字母

 

 

 如果需要放大或者缩小字体,关键点的相对位置是不变的, 只要数学曲线平滑,字体就不会变形。

下载freetype: https://freetype.org/download.html

https://download.savannah.gnu.org/releases/freetype/

freetype 依赖于 libpng, libpng 又依赖于 zlib,所以我们应该:先编译安装 zlib,再编译安装 libpng,最后编译安装 freetype。 但是,有些工具链里有 zlib, 那就不用编译安装 zlib.

下载安装libpng: https://www.linuxfromscratch.org/blfs/view/svn/general/libpng.html

下载安装zlib: https://www.zlib.net/fossils/

1.根据自己的工具链设置环境:

export ARCH=arm

export CROSS_COMPILE=arm-buildroot-linux-gnueabihf

export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin

echo ‘main(){}’| arm-buildroot-linux-gnueabihf-gcc -E -v –

头文件的系统目录为:

 /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include

 /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include-fixed

 /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/include

 /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include

库文件的系统目录为:

COMPILER_PATH=/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../libexec/gcc/arm-buildroot-linux-gnueabihf/7.5.0/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../libexec/gcc/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/bin/

 

LIBRARY_PATH=/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/lib/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/lib/:/media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib/

 

2.编译zlib

 

编译zlib库时,./configure不允许传入–host参数;不支持的话需要export CC设置为你的arm工具链

export CC=arm-buildroot-linux-gnueabihf-gcc

./configure –prefix=$PWD/tmp

Make;make install

cd tmp/lib;ls

 

将lib和头文件拷贝到工具链目录(或者不拷贝,到时候编译用-L, -I指定即可,运行时指定LIBRARY_PATH)

cp include/* -rf /home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/include

cp lib/* -rfd /home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/../lib/gcc/arm-buildroot-linux-gnueabihf/7.5.0/../../../../arm-buildroot-linux-gnueabihf/lib

 

3.编译libpng

./configure –host= arm-buildroot-linux-gnueabihf –prefix=$PWD/tmp

make

make install

cd tmp/lib;ls

 

将lib和头文件拷贝到工具链目录

 

4.编译freetype

./configure –host= arm-buildroot-linux-gnueabihf –prefix=$PWD/tmp

Make

Make  install

注意:如果你的工具链路径不是 /home/book/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot,那么make时会出现类似如下错误。

 

修改自己工具链下的$(TOOLCHAIN)/arm-buildroot-linux-gnueabihf/sysroot/usr/lib目录下编辑libfreetype.la, 替换dependency_libs和libdir的路径。

来自 < http://bbs.100ask.net/question/15908>

 

libfreetype库如下:

 

将lib和头文件拷贝到工具链目录。

 

5.测试

gcc freetype_show_font.c -I /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/include/freetype2/ -L /media/cvitek/robin.lee/my_test/study/weidongshan/100ask_imx6ull-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/arm-buildroot-linux-gnueabihf/sysroot/usr/lib -lfreetype

#include <sys/mman.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <linux/fb.h>

#include <fcntl.h>

#include <stdio.h>

#include <string.h>

#include <math.h>

#include <wchar.h>

#include <sys/ioctl.h>

#include <ft2build.h>

#include FT_FREETYPE_H

#include FT_GLYPH_H

 

int fd_fb;

struct fb_var_screeninfo var;        /* Current var */

int screen_size;

unsigned char *fbmem;

unsigned int line_width;

unsigned int pixel_width;

 

/**********************************************************************

 * 函数名称: lcd_put_pixel

 * 功能描述: 在LCD指定位置上输出指定颜色(描点)

 * 输入参数: x坐标,y坐标,颜色

 * 输出参数: 无

 * 返 回 值: 会

 ***********************************************************************/

void lcd_put_pixel(int x, int y, unsigned int color)

{

        unsigned char *pen_8 = fbmem+y*line_width+x*pixel_width;

        unsigned short *pen_16;        

        unsigned int *pen_32;        

        unsigned int red, green, blue;        

 

        pen_16 = (unsigned short *)pen_8;

        pen_32 = (unsigned int *)pen_8;

 

        switch (var.bits_per_pixel)

        {

                case 8:

                {

                        *pen_8 = color;

                        break;

                }

                case 16:

                {

                        /* 565 */

                        red   = (color >> 16) & 0xff;

                        green = (color >> 8) & 0xff;

                        blue  = (color >> 0) & 0xff;

                        color = ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3);

                        *pen_16 = color;

                        break;

                }

                case 32:

                {

                        *pen_32 = color;

                        break;

                }

                default:

                {

                        printf(“can’t surport %dbpp\n”, var.bits_per_pixel);

                        break;

                }

        }

}

 

/**********************************************************************

 * 函数名称: draw_bitmap

 * 功能描述: 根据bitmap位图,在LCD指定位置显示汉字

 * 输入参数: x坐标,y坐标,位图指针

 * 输出参数: 无

 * 返 回 值: 无

 ***********************************************************************/

void

draw_bitmap( FT_Bitmap*  bitmap,

             FT_Int      x,

             FT_Int      y)

{

        FT_Int  i, j, p, q;

        FT_Int  x_max = x + bitmap->width;

        FT_Int  y_max = y + bitmap->rows;

 

        //printf(“x = %d, y = %d\n”, x, y);

 

        for ( j = y, q = 0; j < y_max; j++, q++ )

        {

                for ( i = x, p = 0; i < x_max; i++, p++ )

                {

                        if ( i < 0      || j < 0       ||

                                i >= var.xres || j >= var.yres )

                        continue;

 

        //image[j][i] |= bitmap->buffer[q * bitmap->width + p];

        lcd_put_pixel(i, j, bitmap->buffer[q * bitmap->width + p]);

        }

        }

}

 

int main(int argc, char **argv)

{

        wchar_t *chinese_str = L”繁”;

        FT_Library          library;

        FT_Face           face;

        int error;

    FT_Vector     pen;

        FT_GlyphSlot  slot;

        int font_size = 24;

 

        if (argc < 2)

        {

                printf(“Usage : %s <font_file> [font_size]\n”, argv[0]);

                return -1;

        }

 

        if (argc == 3)

                font_size = strtoul(argv[2], NULL, 0);

                

        fd_fb = open(“/dev/fb0”, O_RDWR);

        if (fd_fb < 0)

        {

                printf(“can’t open /dev/fb0\n”);

                return -1;

        }

 

        if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))

        {

                printf(“can’t get var\n”);

                return -1;

        }

 

        line_width  = var.xres * var.bits_per_pixel / 8;

        pixel_width = var.bits_per_pixel / 8;

        screen_size = var.xres * var.yres * var.bits_per_pixel / 8;

        fbmem = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);

        if (fbmem == (unsigned char *)-1)

        {

                printf(“can’t mmap\n”);

                return -1;

        }

 

        /* 清屏: 全部设为黑色 */

        memset(fbmem, 0, screen_size);

 

        /* 显示矢量字体 */

        error = FT_Init_FreeType( &library );                           /* initialize library */

        /* error handling omitted */

        

        error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */

        /* error handling omitted */        

        slot = face->glyph;

 

        FT_Set_Pixel_Sizes(face, font_size, 0);

 

        /* 确定座标:

         */

        //pen.x = 0;

        //pen.y = 0;

 

    /* set transformation */

    //FT_Set_Transform( face, 0, &pen);

 

    /* load glyph image into the slot (erase previous one) */

    error = FT_Load_Char( face, chinese_str[0], FT_LOAD_RENDER );

        if (error)

        {

                printf(“FT_Load_Char error\n”);

                return -1;

        }

        

    draw_bitmap( &slot->bitmap,

                 var.xres/2,

                 var.yres/2);

 

        return 0;        

}

原文地址:http://www.cnblogs.com/fuzidage/p/16828292.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性