现在的位置: 首页 > 综合 > 正文

MTK字库相关

2019年08月28日 ⁄ 综合 ⁄ 共 17627字 ⁄ 字号 评论关闭

点阵字库的显示原理

  • 所有的汉字或者英文都是下面的原理,

    由左至右,每8个点占用一个字节,最后不足8个字节的占用一个字节,而且从最高位向最低位排列。

    生成的字库说明:(以12×12例子)

    一个汉字占用字节数:12÷8=1····4也就是占用了2×12=24个字节。

    编码排序A0A0→A0FE A1A0→A2FE依次排列。

    以12×12字库的“我”为例:“我”的编码为CED2,所以在汉字排在CEH-AOH=2EH区的D2H-A0H=32H个。所以在12×12字库的起始位置就是[{FE-A0}*2EH+32H]*24=104976开始的24个字节就是我的点阵模。

    其他的类推即可。

    英文点阵也是如此推理。

点阵字库与字符字模

  • 在dos终端模式下是不可以显示中文汉字的,只能显示英文。

    汉字与英文的区别是:

    1. 汉字字库中,任何字符均用2个字节编码,即区码和位码,在英文字库中,所有字符均用单字节编码。

    2.16点阵汉字字库(16*16)用32个字节存储一个字符的字模,16点阵英文字库(8*16)用16个字节存储单个字符的字模。

    在DOS终端模式下用的是16点阵英文字库,如果要让DOS终端中显示中文,可以改写终端模式下的16点阵英文字库,使其显示的不是原有的英文字符,而是汉字字符,当然也可以加入自造点阵图形图像。原理为:

    我们输入AB,正常显示的是AB,但如果改变AB的字模,用汉字的字模代替,这样输入AB字符,并不显示AB,而是显示一个汉字。将一个汉字从中间劈为两半,左面部分顶替A的字模,右面部分顶替B的字模。

    dos所用字库,文件头结构很简单,如默认的8*16英文字库,文件头长度为4,跳过这四个字节就是字模数据;也有没有文件头的,从第一个字节开始就是字模数据。

点阵字库结构

  • 1、点阵字库存储

    在汉字的点阵字库中,每个字节的每个位都代表一个汉字的一个点,每个汉字都是由一个矩形的点阵组成,0代表没有,1代表有点,将0和1分别用不同颜色画出,就形成了一个汉字,常用的点阵矩阵有12*12, 14*14, 16*16三种字库。

    字库根据字节所表示点的不同有分为横向矩阵和纵向矩阵,目前多数的字库都是横向矩阵的存储方式(用得最多的应该是早期UCDOS字库),纵向矩阵一般是因为有某些液晶是采用纵向扫描显示法,为了提高显示速度,于是便把字库矩阵做成纵向,省得在显示时还要做矩阵转换。我们接下去所描述的都是指横向矩阵字库。

    2、16*16点阵字库

    对于16*16的矩阵来说,它所需要的位数共是16*16=256个位,每个字节为8位,因此,每个汉字都需要用256/8=32个字节来表示。

    即每两个字节代表一行的16个点,共需要16行,显示汉字时,只需一次性读取32个字节,并将每两个字节为一行打印出来,即可形成一个汉字。

    点阵结构如下图所示:

    第一字节 第二字节

    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    3、14*14与12*12点阵字库

    对于14*14和12*12的字库,理论上计算,它们所需要的点阵分别为(14*14/8)=25, (12*12/8)=18个字节,但是,如果按这种方式来存储,那么取点阵和显示时,由于它们每一行都不是8的整位数,因此,就会涉到点阵的计算处理问题,会增加程序的复杂度,降低程序的效率。

    为了解决这个问题,有些点阵字库会将14*14和12*12的字库按16*14和16*12来存储,即,每行还是按两个字节来存储,但是14*14的字库,每两个字节的最后两位是没有使用,12*12的字节,每两字节的最后4位是没有使用,这个根据不同的字库会有不同的处理方式,所以在使用字库时要注意这个问题,特别是14*14的字库。

汉字点阵获取

  • 1、利用区位码获取汉字

    汉字点阵字库是根据区位码的顺序进行存储的,因此,我们可以根据区位来获取一个字库的点阵,它的计算公式如下:

    点阵起始位置 = ((区码- 1)*94 + (位码 – 1)) * 汉字点阵字节数

    获取点阵起始位置后,我们就可以从这个位置开始,读取出一个汉字的点阵。

    2、利用汉字机内码获取汉字

    前面我们己经讲过,汉字的区位码和机内码的关系如下:

    机内码高位字节 = 区码 + 20H + 80H(或区码 + A0H)

    机内码低位字节 = 位码 + 20H + 80H(或位码 + AOH)

    反过来说,我们也可以根据机内码来获得区位码:

    区码 = 机内码高位字节 - A0H

    位码 = 机内码低位字节 - AOH

    将这个公式与获取汉字点阵的公式进行合并计就可以得到汉字的点阵位置。

在DOS程序中使用点阵字库的方法

  • 首先需要理解的是点阵字库是一个数据文件,在这个数据文件里面保存了所有文字的点阵数据.至于什么是点阵,我想我不讲大家都知道 的,使用过"文曲星"之类的电子辞典吧,那个的液晶显示器上面显示的汉子就能够明显的看出"点阵"的痕迹.在 PC 机上也是如此,文字也是由点阵来组成了,不同的是,PC机显示器的显示分辨率更高,高到了我们肉眼无法区分的地步,因此"点阵"的痕迹也就不那么明显了。

    点阵、矩阵、位图这三个概念在本质上是有联系的,从某种程度上来讲,这三个就是同义词.点阵从本质上讲就是单色位图,他使用一个比特来表示一个点,如果这 个比特为0,表示某个位置没有点,如果为1表示某个位置有点.矩阵和位图有着密不可分的联系,矩阵其实是位图的数学抽象,是一个二维的阵列.位图就是这种 二维的阵列,这个阵列中的 (x,y) 位置上的数据代表的就是对原始图形进行采样量化后的颜色值.但是,另一方面,我们要面对的问题是,计算机中数据的存放都是一维的,线性的.因此,我们需要
    将二维的数据线性化到一维里面去.通常的做法就是将二维数据按行顺序的存放,这样就线性化到了一维。

    那么点阵字的数据存放细节到底是怎么样的呢.其实也十分的简单,举个例子最能说明问题.比如说 16*16 的点阵,也就是说每一行有16个点,由于一个点使用一个比特来表示,如果这个比特的值为1,则表示这个位置有点,如果这个比特的值为0,则表示这个位置没 有点,那么一行也就需要16个比特,而8个比特就是一个字节,也就是说,这个点阵中,一行的数据需要两个字节来存放.第一行的前八个点的数据存放在点阵数 据的第一个字节里面,第一行的后面八个点的数据存放在点阵数据的第二个字节里面,第二行的前八个点的数据存放在点阵数据的第三个字节里面,…,然后后
    面的就以此类推了.这样我们可以计算出存放一个点阵总共需要32个字节.看看下面这个图形化的例子:

    | |1| | | | | | | | | | |1| | | |

    | | |1|1| |1|1|1|1|1|1|1|1|1| | |

    | | | |1| | | | | | | | |1| | | |

    |1| | | | | |1| | | | | |1| | | |

    | |1|1| | | |1| | | | | |1| | | |

    | | |1| | | |1| | | | |1| | | | |

    | | | | |1| | |1| | | |1| | | | |

    | | | |1| | | |1| | |1| | | | | |

    | | |1| | | | | |1| |1| | | | | |

    |1|1|1| | | | | | |1| | | | | | |

    | | |1| | | | | |1| |1| | | | | |

    | | |1| | | | |1| | | |1| | | | |

    | | |1| | | |1| | | | | |1| | | |

    | | |1| | |1| | | | | | |1|1|1| |

    | | | | |1| | | | | | | | |1| | |

    | | | | | | | | | | | | | | | | |

    可以看出这是一个"汉"字的点阵,当然文本的方式效果不是很好.根据上面的原则,我们可以写出这个点阵的点阵数 据:0x40,0x08,0x37,0xfc,0x10,0x08,…, 当然写这个确实很麻烦所以我不再继续下去.我这样做,也只是为了向你说明,在点阵字库中,每一个点阵的数据就是按照这种方式存放的.

    当然也存在着不规则的点阵,这里说的不规则,指的是点阵的宽度不是8的倍数,比如 12*12 的点阵,那么这样的点阵数据又是如何存放的呢?其实也很简单,每一行的前面8个点存放在一个字节里面,每一行的剩下的4点就使用一个字节来存放,也就是说 剩下的4个点将占用一个字节的高4位,而这个字节的低4位没有使用,全部都默认的为零.这样做当然显得有点浪费,不过却能够便于我们进行存放和寻址.对于 其他不规则的点阵,也是按照这个原则进行处理的.这样我们可以得出一个
    m*n 的点阵所占用的字节数为 (m+7)/8*n.

    在明白了以上所讲的以后,我们可以写出一个显示一个任意大小的点阵字模的函数,这个函数的功能是输出一个宽度为w,高度为h的字模到屏幕的 (x,y) 坐标出,文字的颜色为 color,文字的点阵数据为 pdata 所指:

    /*输出字模的函数*/

    void _draw_model(char *pdata, int w, int h, int x, int y, int color)

    {

    int     i;    /* 控制行 */

    int     j;    /* 控制一行中的8个点 */

    int     k;    /* 一行中的第几个"8个点"了 */

    int     nc;   /* 到点阵数据的第几个字节了 */

    int     cols; /* 控制列 */

    BYTE    static mask[8]={128, 64, 32, 16, 8, 4, 2, 1}; /* 位屏蔽字 */

    w = (w + 7) / 8 * 8; /* 重新计算w */

    nc = 0;

    for (i=0; i<h; i++)

    {

    cols = 0;

    for (k=0; k<w/8; k++)

    {

    for (j=0; j<8; j++)

    {

    if (pdata[nc]&amp;mask[j])

    putpixel(x+cols, y+i, color);

    cols++;

    }

    nc++;

    }

    }

    }

    代码很简单,不用怎么讲解就能看懂,代码可能不是最优化的,但是应该是最易读懂的.其中的 putpixel 函数,使用的是TC提供的 Graphics 中的画点函数.使用这个函数就可以完成点阵任意大小的点阵字模的输出.

    接下来的问题就是如何在汉子库中寻址某个汉子的点阵数据了.要解决这个问题,首先需要了解汉字在计算机中是如何表示的.在计算机中英文可以使用 ASCII 码来表示,而汉字使用的是扩展 ASCII 码,并且使用两个扩展 ASCII 码来表示一个汉字.一个 ASCII 码使用一个字节表示,所谓扩展 ASCII 码,也就是 ASCII 码的最高位是1的 ASCII 码,简单的说就是码值大于等于 128 的 ASCII 码.一个汉字由两个扩展 ASCII
    码组成,第一个扩展 ASCII 码用来存放区码,第二个扩展 ASCII 码用来存放位码.在 GB2312-80 标准中,将所有的汉字分为94个区,每个区有94个位可以存放94个汉字,形成了人们常说的区位码,这样总共就有 94*94=8836 个汉字.在点阵字库中,汉字点阵数据就是按照这个区位的顺序来存放的,也就是最先存放的是第一个区的汉字点阵数据,在每一个区中有是按照位的顺序来存放 的.在汉字的内码中,汉字区位码的存放实在扩展 ASCII 基础上存放的,并且将区码和位码都加上了32,然后存放在两个扩展 ASCII
    码中.具体的说就是:

    第一个扩展ASCII码 = 128+32 + 汉字区码

    第二个扩展ASCII吗 = 128+32 + 汉字位码

    如果用char hz[2]来表示一个汉字,那么我可以计算出这个汉字的区位码为:

    区码 = hz[0] - 128 - 32 = hz[0] - 160

    位码 = hz[1] - 128 - 32 = hz[1] - 160.

    这样,我们可以根据区位码在文件中进行殉职了,寻址公式如下:

    汉字点阵数据在字库文件中的偏移 = ((区码-1) * 94 + 位码) * 一个点阵字模占用的字节数

    在寻址以后,即可读取汉字的点阵数据到缓冲区进行显示了.以下是实现代码:

    /* 输出一个汉字的函数 */

    void _draw_hz(char hz[2], FILE *fp, int x, int y, int w, int h, int color)

    {

    char ftbuf[128];   /* 足够大的缓冲区,也可以动态分配 */

    int ch0 = (BYTE)hz[0]-0xA0; /* 区码 */

    int ch1 = (BYTE)hz[1]-0xA0; /* 位码 */

    /* 计算偏移 */

    long offset = (long)pf->_hz_buf_size * ((ch0 - 1) * 94 + ch1 - 1);

    fseek(fp, offset, SEEK_SET);              /* 进行寻址 */

    fread(fontbuf, 1, (w + 7) / 8 * h, fp);   /* 读入点阵数据 */

    _draw_model(fontbuf, w, h, x, y, color); /* 绘制字模 */

    }

    以上介绍完了中文点阵字库的原理,当然还有英文点阵字库了.英文点阵字库中单个点阵字模数据的存放方式与中文是一模一样的,也就是对我们所写的 _draw_model 函数同样可以使用到英文字库中.唯一不同的是对点阵字库的寻址上.英文使用的就是 ASCII 码,其码值是0到127,寻址公式为:

    英文点阵数据在英文点阵字库中的偏移 = 英文的ASCII码 * 一个英文字模占用的字节数可以看到,区分中英文的关键就是,一个字符是 ASCII 码还是扩展 ASCII 码,如果是 ASCII 码,其范围是0到127,这样是使用的英文字库,如果是扩展 ASCII 码,则与其后的另一个扩展 ASCII 码组成汉字内码,使用中文字库进行显示.只要正确区分 ASCII 码的类型并进行分别的处理,也就能实现中英文字符串的混合输出了。

点阵字库和矢量字库的差别

  • 我们都只知道,各种字符在电脑屏幕上都是以一些点来表示的,因此也叫点阵。最早的字库就是直接把这些点存储起来,就是点阵字库。常见的汉字点阵字库有 16x16, 24x24等。点阵字库也有很多种,主要区别在于其中存储编码的方式不同。点阵字库的最大缺点就是它是固定分辨率的,也就是每种字库都有固定的大小尺寸,在原始尺寸下使用,效果很好,但如果将其放大或缩小使用,效果就很糟糕了,就会出现我们通常说的锯齿现象。因为需要的字体大小组合有无数种,我们也不可能为每种大小都定义一个点阵字库。于是就出现了矢量字库。

    矢量字库

    矢量字库是把每个字符的笔划分解成各种直线和曲线,然后记下这些直线和曲线的参数,在显示的时候,再根据具体的尺寸大小,画出这些线条,就还原了原来的字符。它的好处就是可以随意放大缩小而不失真。而且所需存储量和字符大小无关。矢量字库有很多种,区别在于他们采用的不同数学模型来描述组成字符的线条。常见的矢量字库有 Type1字库和Truetype字库。

    在点阵字库中,每个字符由一个位图表示,并把它用一个称为字符掩膜的矩阵来表示,其中的每个元素都是一位二进制数,如果该位为1表示字符的笔画经过此位,该像素置为字符颜色;如果该位为0,表示字符的笔画不经过此位,该像素置为背景颜色。点阵字符的显示分为两步:首先从字库中将它的位图检索出来,然后将检索到的位图写到帧缓冲器中。

    在实际应用中,同一个字符有多种字体(如宋体、楷体等),每种字体又有多种大小型号,因此字库的存储空间十分庞大。为了减少存储空间,一般采用压缩技术。

    矢量字符记录字符的笔画信息而不是整个位图,具有存储空间小,美观、变换方便等优点。例如:在AutoCAD中使用图形实体-形(Shape)-来定义矢量字符,其中,采用了直线和圆弧作为基本的笔画来对矢量字符进行描述。 对于字符的旋转、放大、缩小等几何变换,点阵字符需要对其位图中的每个象素进行变换,而矢量字符则只需要对其几何图素进行变换就可以了,例如:对直线笔画的两个端点进行变换,对圆弧的起点、终点、半径和圆心进行变换等等。

    矢量字符的显示也分为两步。首先从字库中将它的字符信息。然后取出端点坐标,对其进行适当的几何变换,再根据各端点的标志显示出字符。

    轮廓字形法是当今国际上最流行的一种字符表示方法,其压缩比大,且能保证字符质量。轮廓字形法采用直线、B样条/Bezier曲线的集合来描述一个字符的轮廓线。轮廓线构成一个或若干个封闭的平面区域。轮廓线定义加上一些指示横宽、竖宽、基点、基线等等控制信息就构成了字符的压缩数据。

如何使用Windows的系统字库生成点阵字库

  • 程序现在只能预览一个汉字的不同字体的点阵表达.

    界面很简单:   一个输出点阵大小的选择列表(8x8,16x16,24x24等),一个系统中已有的字体名称列表,一个预览按钮,一块画图显示区域.

    得到字体列表的方法:(作者称这一段是用来取回系统的字体,然后添加到下拉框中)

    //取字体名称列表的回调函数,使用前要声明一下该方法

    int   CALLBACK   MyEnumFONtProc(ENUMLOGFONTEX*   lpelf,NEWTEXTMETRICEX*   lpntm,DWORD   nFontType,long   lParam)

    {

    CFontPeekerDlg*   pWnd=(CFontPeekerDlg*)   lParam;

    if(pWnd)

    {

    if(   pWnd->m_combo_sfont.FindSTring(0,   lpelf->elfLogFont.lfFaceName)   <0   )

    pWnd->m_combo_sfont.AddString(lpelf->elfLogFont.lfFaceName);

    return   1;

    }

    return   0;

    }

    //说明:CFontPeekerDlg   是我的dialog的类名,   m_combo_sfont是列表名称下拉combobox关联的control变量

    //调用的地方     (******问题1:下面那个&lf怎么得到呢……)

    {

    ::EnumFontFamiliesEx((HDC)   dc,&lf,   (FONTENUMPROC)MyEnumFontProc,(LPARAM)   this,0);

    m_combo_sfont.SetCurSel(0);

    }

    字体预览:

    如果点阵大小选择16,显示的时候就画出16x16个方格.自定义一个类CMyStatic继承自CStatic,用来画图.在CMyStatic的OnPaint()函数中计算并显示.

    取得字体:

    常用的方法:用CreateFont创建字体,把字TextOut再用GetPixel()取点存入数组.   缺点:必须把字TextOut出来,能在屏幕上看见,不爽.

    我的方法,用这个函数:GetGlyphOutline(),可以得到一个字的轮廓矢量或者位图.可以不用textout到屏幕,直接取得字模信息

    函数原型如下:

    DWORD   GetGlyphOutline(

    HDC   hdc,                     //画图设备句柄

    UINT   uChar,                 //将要读取的字符/汉字

    UINT   uFormat,             //返回数据的格式(字的外形轮廓还是字的位图)

    LPGLYPHMETRICS   lpgm,     //   GLYPHMETRICS结构地址,输出参数

    DWORD   cbBuffer,       //输出数据缓冲区的大小

    LPVOID   lpvBuffer,     //输出数据缓冲区的地址

    CONST   MAT2   *lpmat2   //转置矩阵的地址

    );

    说明:

    uChar字符需要判断是否是汉字还是英文字符.中文占2个字节长度.

    lpgm是输出函数,调用GetGlyphOutline()是无须给lpgm   赋值.

    lpmat2如果不需要转置,将   eM11.value=1;   eM22.value=1;   即可.

    cbBuffer缓冲区的大小,可以先通过调用GetGlyphOutline(……lpgm,   0,   NULL,   mat);   来取得,然后动态分配lpvBuffer,再一次调用GetGlyphOutline,将信息存到lpvBuffer.   使用完毕后再释放lpvBuffer.

    程序示例:(***问题2:用这段程序,我获取的字符点阵总都是一样的,不管什么字……)

    ……前面部分省略……

    GLYPHMETRICS   glyph;

    MAT2   m2;

    memset(&m2,   0,   sizeof(MAT2));

    m2.eM11.value   =   1;

    m2.eM22.value   =   1;

    //取得buffer的大小

    DWORD   cbBuf   =   dc.GetGlyphOutline(   nChar,   GGO_BITMAP,   &glyph,   0L,   NULL,   &m2);

    BYTE*   pBuf=NULL;

    //返回GDI_ERROR表示失败.

    if(   cbBuf   !=   GDI_ERROR   )

    {

    pBuf   =   new   BYTE[cbBuf];

    //输出位图GGO_BITMAP   的信息.输出信息4字节(DWORD)对齐

    dc.GetGlyphOutline(   nChar,   GGO_BITMAP,   &glyph,   cbBuf,   pBuf,   &m2);

    }

    else

    {

    if(m_pFont!=NULL)

    delete   m_pFont;

    return;

    }

    编程中遇到问题:

    一开始,GetGlyphOutline总是返回-1,getLastError显示是"无法完成的功能",后来发现是因为调用之前没有给hdc设置Font.

    后来能取得pBuf信息后,又开始郁闷,因为不太明白bitmap的结果是按什么排列的.后来跟踪汉字"一"来调试(这个字简单),注意到了glyph.gmBlackBoxX   其实就是输出位图的宽度,glyph.gmBlackBoxY就是高度.如果gmBlackBoxX=15,glyph.gmBlackBoxY=2,表示输出的pBuf中有这些信息:位图有2行信息,每一行使用15   bit来存储信息.

    例如:我读取"一":glyph.gmBlackBoxX   =   0x0e,glyph.gmBlackBoxY=0x2;     pBuf长度cbBuf=8   字节

    pBuf信息:       00   08   00   00   ff   fc   00   00

    字符宽度   0x0e=14     则   第一行信息为:           0000   0000   0000   100       (只取到前14位)

    第二行根据4字节对齐的规则,从0xff开始         1111   1111   1111   110

    看出"一"字了吗?呵呵

    直到他的存储之后就可以动手解析输出的信息了.

    我定义了一个宏#define   BIT(n)     (1<<(n))     用来比较每一个位信息时使用

    后来又遇到了一个问题,就是小头和大头的问题了.在我的机器上是little   endian的形式,如果我用

    unsigned   long   *lptr   =   (unsigned   long*)pBuf;

    //j   from   0   to   15

    if(   *lptr   &   BIT(j)   )

    {

    //这时候如果想用j来表示写1的位数,就错了

    }

    因为从字节数组中转化成unsigned   long型的时候,数值已经经过转化了,像上例中,实际上是0x0800   在同BIT(j)比较.

    不多说了,比较之前转化一下就可以了if(   htonl(*lptr)   &   BIT(j)   )

标准点阵字库芯片

  • 标准点阵字库的特点:

    1.内涵全国信标委授权的标准点阵字型数据;

    2.支持国标字符集GB2312(6,763汉字),GB18030(27,484汉字);

    3.支持多种点阵字型,包括11×12点,15×16点,24×24点,32×32点;

    4.免除了字库烧录和测试工序,并节省了2%以上的烧录损耗;

    5.价格相当于空白FLASH价格;

 

 

 

 

FONTEDITOR V1.3版本出来了

字库格式转换:ttf2bdf,bdf2fnt,bdf2fnb,fnt2bdf,fnb2bdf,fnt2fnb,fnb2fnt

FontEditor 为一款功能强大的字体编辑和字体格式转换工具,支持制作32*32的全字库。能将TTF,OTF矢量字库转换为BDF字库,可以很方便的将Windows 已经安装到系统的矢量字库转换为BDF字库,并能将TTF,OTF文件直接转换成BDF格式,并支持BDF,FNT,FNB文件格式的互转换,随心所欲将 windows字体应用于各种嵌入式系统中。并支持将GB2312,BIG5,GBK转换为UCS2,UTF8,以及UCS2,UTF8编码的互转换

本软件现已应用于多个嵌入式平台,如MTK,QUALCOMM,TI,展讯等。

本软件主要功能:
1.字体点阵编辑,支持制作32*32点阵的全字库
2.支持BDF,FNT,FNB格式的互转换,BDF<-->FNT, BDF<-->FNB,FNT<-->FNB
3.直接将TTF,OTF文件转换为BDF,FNT,FNB格式
4.将Windows系统安装的TTF,OTF导入为BDF,FNT,FNB格式
5.将字符点阵导出为Bitmap文件,并提供字符点阵宽度索引
6.支持将GB2312,BIG5,GBK转换为UCS2,UTF8,并支持UCS2,UTF8编码的互转换

运行环境:Win2003, WinXP, Win2000, NT, WinME
版本发布说明:
V1.2
(1)BDF,FNT,FNB字体格式的互转换
(2)将Windows已经安装TTF转换为BDF格式
(3)将TTF文件导入转为BDF,FNT,FNB格式
(4)汉字查码

V1.25
(1)Windows已经安装TTF字体导入为BDF时,剔除无效字符
(2)将BDF,FNT,FNB导出为bitmap文件和字符宽度索引
(3)GB2312,BIG5,GBK转换为UCS2,UTF8,以及UCS2,UTF8互转换

V1.25.03
(1)将单个字符导出为Bitmap文件
(2)解决导出字库bitmap时,字符少于256个导出文件不正确的问题
(3)解决导出选择中字符实际上是导出所有字符的问题

V1.26
(1)增加修正字符点阵的功能,可对所有字符或者当前页字符的点阵大小和位移进行调整
(2)修正V1.25.03中导出位图文件选择取消无法退出程序的问题

V1.3
(1)增加导出全字库bitmap方式,同时支持二进制导出和ASCII码导出
(2)增强读取BDF文件的兼容性
(3)增加手动剔除无效字符功能

欢迎所需了解相关使用情况的人员与我联系,可以提供3天的体验版本。

==================================================================================

TTF转换成BDF
2008-09-12 21:47

 

由于TTF格式的字库可以转换成任意大小的BDF字库,而可以找到的BDF字库都是固定大小的,因此在实际制作BDF字体文件时,还是需要TTF格式的字库。把TTF转换成BDF的方法如下:
./ttf2bdf source.ttf -p yourSize -o destination.bdf
    即利用软件ttf2bdf可以把源文件source.ttf转换成大小为yourSize的BDF格式的文件destination.bdf。那在程序内部是如何实现将TTF转成BDF的呢?由2.2.1和2.2.2的介绍,并且查阅参考文献[3],可以知道TTF的内部存储结构。其中最核心的部分是 TTF文件格式中的12个字节的文件表:表目录按tag以升序排列。

 

Type Name Description
ULONG tag 4字节的标识
ULONG checkSum 表中的CheckSum
ULONG offset TrueType font文件的起始偏移量Offset
ULONG length 表长

    还有一个有关Offset表的信息,包括版本号,表的数量,查找范围。入口选择,转换范围。
    通过操作文件表,将描述表中的数据取出来,按照BDF字体所定义的格式写入,就可以生成对应的字体。比如,可以给出一小段c语言程序,此程序用于计算当前CheckSum的位置。
ULONG
CalcTableChecksum(ULONG *Table,ULONG Length)
{
ULONG Sum = 0L;
ULONG *Endptr=Table+((Length+3)& ~3)/sizeof(ULONG);
while(Table<EndPtr)
Sum += *Table++;
return Sum;
}
    利用此程序可以将每个字体的信息分开,并将每个字体信息从文件中取出来,对每个字体进行操作。在从TTF转到BDF过程中,仅通过使用WINDOW的函数是很不方便的,最方便的办法是使用c语言对字体进行操作。我在此列出转换过程中最重要的几个值:PIXEL_SIZE,POINT_SIZE,RESOLUTION_X,RESOLUTION_Y,FONT_DESCENT,FONT_ASCENT,SWIDTH,DWIDTH,BBX。这些值决定着最后生成的BDF字体与TTF字体的失真度,因为TTF是可缩放的,而BDF是固定大小的,所以在转换过程中一定会出现失真的情况。

 

========================================================================================

MTK的语言问题,希望大家看完后顶帖

1。MMI_featuresPLUTO.h (plutommi\customer\custresource\pluto_mmi)

      #define __MMI_LANG_SM_CHINESE__ //定义宏开关

 

2。FontRes.c (plutommi\customer\lcdresource\mainlcd240x320)

      <1>

      #ifdef __MMI_16X16_CHINESE_FONT__

      #include "L_Pluto_16x16_ch.h"                  //引入字库头文件

      #else

 

     <2>

      const RangeData XXX_RangeData[a]={。。。}

 

      <3>

      const U16 mtk_gMaxDeployedLangs = 1;

 

      <4>

       #if defined(__MMI_LANG_SM_CHINESE__)

      sFontFamily pluto_ch_standardFamily = {6,{&Pluto_ch, &Pluto_ch, &Pluto_ch, &Pluto_ch, &Pluto_ch,&gVirtualKeyboardFont}};

      #endif

 

       <5>

      #if defined(__MMI_LANG_SM_CHINESE__)

      {

      {(char)0x80,(char)0x7B,(char)0x53,(char)0x4F,(char)0x2D,(char)0x4E,(char)0x87,(char)0x65,(char)0x00,(char)0x00},//Language Name

        "*#0086#",//SSC string name

        0,

        { &pluto_ch_standardFamily },

        "zh"

      },

      #endif

 

附注:<2> 中对应字体的长,宽,高,偏离值等,

      <3> 对应添加的语言的种类数,

      <4> 定义了界面中具体模块的字体,如gVirtualKeyboardFont对应与虚拟键盘中字体的显示问题

       <5> (mtk_gLanguageArray)中对应要添加的语言以及其在手机语言列表中的显示顺序(注意各种语言的顺序)

   我们通常遇到的问题是在真机中有些地方的字体显示有问题(如虚拟键盘,日历等,还未探索清楚),每个语言都有相对应的语系(如pluto_en_standardFamily pluto_ch_standardFamily),当(虚拟键盘)有问题时,首先定位到有问题的语言(),寻找其中利用的语系中的相应模块(virtual_keyboard_latin),对其进行修改(可参考其他显示正确的相近工程中的相应模块拷贝修改(virtual_keyboard_latin),缺少相应字库时添加字库并在fontres.c中添加)

 

MTK多国语言相关经验总结

一、        移植多国语言

移植多国语言主要牵涉到对mmi_features.h(整个工程的宏控定义文件)、fontres.c(字体资源文件)的修改,并添加相应的字库文件。

1、        语言宏控的修改

在mmi_features.h文件中,用于控制各种语言的开关是类似于__MMI_LANG_ENGLISH__的宏,打开该宏,那么工程就支持该种语言。有时侯,需要同时打开与该语言相关的一些宏,比如阿拉伯语的编码模式、汉语的编码模式。(当然这个编码模式一般都是设置好了的,但也有些许例外,自己看着办)

2、        字库文件的添加

在mtk中,字库主要是两个文件,一个是*.h文件,还有一个是对应的fontres.c文件。

①字库的获取

有两个方式:1)直接去网上找对应语言的字库文件。2)自己利用mtk公司所提供的MCT 6.0工具来制作字库。不过mct6.0制作字库需要.bdf的点阵字库源文件,而网上能找的基本上都是.ttf的矢量字库文件,这就存在一个需要将ttf文件转换成bdf文件的第三方软件,并且转换的好坏将直接影响到最终用mct6.0生成的字库文件(目前我们用的是otf2bdf3,免费的,因此效果不是很好)。

        ②字库的使用。首先我们查看下mtk版本中自带的英文字库L_1_Pluto_Large.h是存放在什么位置的,然后将我们的*.h也放入相同的文件夹下;接下来我们需要将我们的fontres.c文件与mtk中原有的fontres.c文件合并为一个fontres.c文件:合并的方法就参考原有的fontres.c文件中英文字库的代码分布方式,将我们的fontres.c文件里面的代码利用语言宏控拷入mtk原有的fontres.c文件中。

        3、修改默认显示语言

        这个只需要修改C:\NEOTEL26_06B_W07.20.MP.V21_MMI\custom\app\NEOTEL26_

06B_BB这个目录下面的nvram_cust_pack.c文件(不同的版本,该文件所处位置不一样,这里是6225的版本)。在该文件里面有如下一处:

    0x00,        

这个0x00值指的就是设置语言界面某种语言所处的位置。如果我们想修改默认显示语言为简体中文,而设置语言界面中文在第6的位置,那么我们将0x00这个值改为0x05即可。

 

 

MTK点阵字库介绍:

每个字符都是由点阵组成,每个字符的每个像素由黑或者白两种点填上,假设该字符是14*14,那么

该字符由14*14=196个像素组成,其中黑色部分就型成了A这个字,比如图一所示。

 

 

UE打开该BDF文件可以看到如下内容:

STARTFONT 2.1

COMMENT Used in M3

COMMENT Author: Wangbo(Longcheertel software department)

FONT -Longcheertel-WB medium-r-normal--14-140-75-75-c-140-GB2312-13X14

SIZE 14 75 75

FONTBOUNDINGBOX 14 14 0 -3 

STARTPROPERTIES 14

FONT_ASCENT 11

FONT_DESCENT 3

DEFAULT_CHAR 12288

COPYRIGHT "Shanghai Longcheer Telecommunication Co, Ltd."

POINT_SIZE 140

WEIGHT 10

RESOLUTION 103

RESOLUTION_X 75

RESOLUTION_Y 75

X_HEIGHT 4294967295

QUAD_WIDTH 14

ENDPROPERTIES

CHARS 7104

STARTCHAR 601

ENCODING 913

SWIDTH 560 0

DWIDTH 14 0

BBX 14 14 0 -3

BITMAP

0000

0200

0500

0500

0880

0880

1040

1FC0

2020

2020

4010

E038

0000

0000

ENDCHAR

其中

0000

0200

0500

0500

0880

0880

1040

1FC0

2020

2020

4010

E038

0000

0000

这段数据的意思是表示黑白像素的,共14行,第一行0000表示第一行全为白点无黑占,第二0200表示在七位有一个黑点,其他都为白点

 

 

 

MTK字库是由BDF文件通过MCT工具转化而来。

转化后生成一个.H和一个.C文件,其中.h文件里面有四个数组:

L_MTK_Latin_16_Width[]代表每个字符的宽度是多少,数组大小代表字符数目

L_MTK_Latin_16_Offset[]代表每个字符数据在L_MTK_Latin_16_Data里的位置,比如0x0000,0x000A,就是说该字符数据在L_MTK_Latin_16_Data第0位至第10位之间(0x000A转化成十进制后为10),

L_MTK_Latin_16_RangOffse[]

L_MTK_Latin_16_Data[]代表每个字符的实际数据内容

 

比如:字符A这个BDF文件转化成代码以后如下:

const U8 GB3212_13X14_Width[1]= {

0xE/*字符宽度为14*/

}

const U32 GB3212_13X14_Offset[7105]= {

0x0000,0x0019/*字符数据范围为0-25*/

}

const U32 GB3212_13X14_RangeOffset[3563]= {

0,

}

const U8  GB3212_13X14_Data[1]= {

0x0,0x0,0x10,0x0,0xA,0x80,0x2,0x10,0x1,0x44,0x80,0x20,0xE0,0xF,0x4,0x4,

0x1,0x21,0x80,0x1C,0x70,0x0,0x0,0x0,0x0/*字符A的位图结构*/

}

 

我们取GB3212_13X14_Data[1]的前四位数据分析一下是怎么表示字符A的

0x0,0x0,0x10,0x0展开成二进制就是:

0000 0000

0000 0000

0001 0000

0000 0000

 

高低位字节颠倒后就为:

0000 0000

0000 0000

0000 1000

0000 0000 

这里的0代表白格,1代表黑格,在第21位有一个1即有一个黑格,与图一正好吻合。

其他数据以此类推。

 

 

1.如果要更改字体宽度,可手工修改BDF文件,具体方法为先记录各个BMP中字体所需宽度,然后手工修改BDF文件的如下红色部分:
     ENCODING 1569

SWIDTH 520 0

DWIDTH 17 0

BBX 16 16 0 -3,经过实践,16×16的字体宽度最小能修改为9

2.打开MCT工具的Font Customizer Tool,在选择Language的时候有“Alphabetic”(字母文字)及“Ideographic”(象形文字)可选;如果是等宽的BDF则选择alphabetic,如果是非等宽的则选择Ideographic,同时Width Property选择Variable即可生成有宽度属性的字体.h文件。

一个典型的字体文件的定义为:

#if defined(__MMI_LANG_THAI__)

//泰文字体,使用EmbedTools能够直观看到

//泰文在Unicode中的分布为两块

const RangeData Thai14_RangeData[2]={

{3585,3642},//0x0E01~0x0E3A: 58个字母
{3647,3675},//0x0E3F~0x0E5B: 29个字母,共87个字母

};

const RangeDetails Thai14_RangeInfo={

2,

Thai14_RangeData

};

sCustFontData pluto_thai = {

//5个参数分别表示字体宽、高、是否等宽(0非等宽、1等宽)、每个字在data中的长度及最大字符个数,如果是非等宽的情况,好像第四个参数无用

14, 14, 0, 25, 500,

(U8*)L_Thai_Medium_W, (U32*)L_Thai_Medium_O, (U8*)L_Thai_Medium_D, (U32*)RangeOffset_14_Thai_Medium,

{

{FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH,FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH},

{FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH,FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH},

{FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH,FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH},

{FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH,FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH},

{FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH,FONTATTRIB_NORMAL|FONTATTRIB_BOLD|FONTATTRIB_ITALIC|FONTATTRIB_OBLIQUE|FONTATTRIB_UNDERLINE|FONTATTRIB_STRIKETHROUGH}, },

&Thai14_RangeInfo};

#endif

 

 

抱歉!评论已关闭.