需要做的是实现对这个系统的汉字全角支持,在

1. 30天操作系统帮衬汉语。

 

汉字的字样其实是汉字字形的图形化。对于16点阵字模,就是把汉字写在三个16×16的网格内,汉字的笔画能过某网格时该网格就对应1,否则该网格对应0,那样每一网格均对应1或0,把对应1的网格连起来看,就是那几个汉字。汉字便是那般经过字节表示点阵存款和储蓄在字库中的。

04 80 0E A0 78 90 08 90 08 84 FF FE 08 80 08 90

0A 90 0C 60 18 40 68 A0 09 20 0A 14 28 14 10 0C

注意事项

  1. 将HZK16字库放到assets文件夹中

3、最终乘以32是因为汉字库文应从该岗位起的32字节音信记录该字的字样消息(前边提到八个中国字要有三15个字节显示)

 

值得注意的是,基于单片机的方块字显示无法在字符LCD上完成。使用图形LCD有大多独到之处,不只好展现汉字,并且能够兑现汉字动态移动和前后滚屏,落成汉字与图片的混合展现,同期功耗低。

【转自 自个儿学习用 侵删】

有关的定义

  1. 点阵字库与矢量字库
    点阵字库正是每三个汉字用矩形点阵来表示,然后用每一个点的虚实来代表汉字的概貌,常用来作为展现字库使用,那类点阵字库汉字最大的毛病是不可能松手,一旦松开后就能够发掘文字边缘的锯齿,常用的点阵矩阵有HZK12、HZK16和HZK24,笔者上边例子中的用到的字库是HZK16。
    矢量字库保存的是对每贰在那之中华夏族民共和国字的叙说消息,举个例子四个笔画的早先、终止坐标,半径、弧度等等。在展示、打字与印刷这一类字库时,要通过一名目多数的数学生运动算工夫出口结果,可是这一类字库保存的方块字理论上能够被Infiniti地推广,笔划轮廓还是能保持狡猾,打字与印刷时使用的字库均为此类字库.

  2. 点阵字库结构
    在汉字的点阵字库中,各样字节的各类位都意味一个中中原人民共和国字的四个点,各种汉字都以由一个矩形点阵组成,0代表未有,1意味有一点点,将0和1分级用不相同颜色画出,就产生了三个汉字。字库依照字节所表示的点是单排照旧一列将字库的存放形式分为横向和纵向,近年来比相当多的字库都以横向的囤积格局(用得最多的应有是开始时期UCDOS字库),纵向一般是因为有点液晶是行使纵向扫描显示法,为了坚实突显速度,于是便把字库矩阵做成纵向,省得在体现时还要做矩阵调换。大家接下去所描述的HZK16正是一种纵向字库。对于16*16字库来讲,它所需求的位数共是16*16=2五16个位,种种字节为8位,因而,每种汉字都亟需用256/8=叁十七个字节来代表。即每多个字节代表一行的十两个点,共需求16行,展现汉字时,只需二回性读取三十二个字节,并将每三个字节为一行打字与印刷出来,就能够形成叁个汉字.

  3. 汉字的区位码
    汉字通过GB2312编码即每一个汉字用三个byte来代表,第叁个byte表示这些汉字在字库文件中的区码,第贰个byte表示那一个汉字在字库文件中的位码,通过那四个值能够总括到那几个汉字在字库文件中的相对地点,遵照这一个地点读取接下来的29个byte(对于16*16字库),就对应着那一个汉字对应的字样消息,字模信息实际正是多个byte数组。
    HZK16字库是相符GB2312标准的16×16点阵字库,HZK16的GB2312-80援救的汉字有6765个,符号6八十几个。在这之中一流汉字有37伍10个,按声序排列,二级汉字有3008个,按偏旁部首排列。

  4. 经过机内码获取文字对应字模消息的苗子地方
    在PC机的文件文件中,汉字是以机内码的花样积累的,种种汉字占用三个字节:第二个字节为区码,为了与ASCII码差异,范围从十六进制的0A1H起来(小于80H的为ASCII码字符),对应区位码中区码的率先区;第一个字节为位码,范围也是从0A1H最初,对应某区中的第3个位码。那样,将汉字机内码减去0A0A0H就得该汉字的区位码。
    举例汉字“房”的机内码为十六进制的“B7BF”,其中“B7”表示区码,“BF”表示位码。所以“房”的区位码为0B7BFH-0A0A0H=171FH。将区码和位码分别转变为十进制得汉字“房”的区位码为“2331”,即“房”的字样新闻位于第23区的第三19个字的岗位,由于多个区包涵91个汉字,所以第32×[(23-1) ×94+(31-1)]=67136Bit过后的叁十一个字节为“房”的字样新闻。

代码如下:

 

而是,在单片机上展现汉字也设有多少个难点。首先,单片机能源有限,大家不可能为了彰显汉字占用太多的能源;其次,汉字存款和储蓄读取比较麻烦,使用不方便人民群众;第三,汉字是透过点阵展现出来的,往往与LCD写入措施不相同,这就得举行改换和调度。

fprintf(stderr, "error hzk16n");

参照文书档案

  1. Android点阵屏效果的控件
  2. 汉字库(HZK16)的使用

那边别的的地点相比弄,第5步将大小修改一下,笔者的是nihongo = (unsigned char *) memman_alloc_4k(memman, 55*94*32);

 

位码=内码第二字节-160

for(k=0; k<16; k++){

代码完成分析

要落到实处地方的轮转字幕的作用,能够分成如下几步:

  1. 获得文字字符串的字样新闻,並且将字模消息转化为Boolean类型的二维数组(字模音信的每一bit中0代表未有,1意味有一点,将0调换来false,将1转移为true)
    /**
     * 获取汉字字符串的点阵矩阵
     * @param text
     * @return
     */
    public boolean[][] getWordsMatrix(Context context, String text) {
        return getWordsMatrix(context, text, null);
    }

    public boolean[][] getWordsMatrix(Context context, String text, DotMatrixFontType dotMatrixFontType) {
        if (null == dotMatrixFontType) {
            this.mDotMatrixFontType = DotMatrixFontType.SIXTEEN_TYPE;
            this.mWordByteByDots = DotMatrixFontType.SIXTEEN_TYPE.getValue() * DotMatrixFontType.SIXTEEN_TYPE.getValue() / 8;
        } else {
            this.mDotMatrixFontType = dotMatrixFontType;
            this.mWordByteByDots = dotMatrixFontType.getValue() * dotMatrixFontType.getValue() / 8;
        }

        byte[] bytes = null;
        try {
            // 获取汉字文本的字节编码
            bytes = text.getBytes(ENCODE);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        // 获取每个字节对应正数编码,即得到汉字对应的区码和位码
        int[] code = new int[bytes.length];
        for (int i = 0; i < bytes.length; i++) {
            code[i] = bytes[i] < 0 ? 256 + bytes[i] : bytes[i];
        }

        int wordNumber = code.length / 2;
        boolean[][] wordsMatrix = new boolean[mDotMatrixFontType.getValue()][mDotMatrixFontType.getValue() * wordNumber];
        for (int i = 0; i < wordNumber; i++) {
            // 通过区码和位码获取字库中对应的字模信息
            byte[] temp = read(context, code[2 * i], code[2 * i + 1]);
            for (int j = 0; j < mWordByteByDots; j++) {
                for (int k = 0; k < 8; k++) {
                    // 将字模信息转化为Boolean类型的二维数组并且进行纵向填充数组
                    int row = (j * 8 + k) / 16 + i * mDotMatrixFontType.getValue();
                    int col = (j * 8 + k) % 16;
                    if (((temp[j] >> (7 - k)) & 1) == 1) {
                        wordsMatrix[col][row] = true;
                    } else {
                        wordsMatrix[col][row] = false;
                    }
                }
            }
        }

        return wordsMatrix;
    }

    /**
     * 从字库中获取指定区码和位码汉字的字模信息
     * @param areaCode 区码,对应编码的第一个字节
     * @param posCode  位码,对应编码的第二个字节
     * @return
     */
    private byte[] read(Context context, int areaCode, int posCode) {
        byte[] data = null;
        try {
            int area = areaCode - 0xa0;
            int pos = posCode - 0xa0;
            InputStream in = context.getAssets().open(DOT_MATRIX_FONT);
            int offset = ((area - 1) * 94 + pos -1) * mWordByteByDots;
            in.skip(offset);
            data = new byte[mWordByteByDots];
            in.read(data, 0, mWordByteByDots);
            in.close();
        } catch (IOException e) {
            Log.d(TAG, "IOException e = " + e.getMessage());
        }
        return data;
    }
  1. 基于Boolean类型的二维数组绘制点阵,当Boolean值为false,表示要绘制空心圆,反之绘制实心圆。
    @Override
    protected void onDraw(Canvas canvas) {
        //super.onDraw(canvas);
        for (int row = 0; row < mDotMatrixFontType.getValue(); row++) {
            for (int col = 0; col < mDotMatrixFontType.getValue() * this.mWordNumber; col++) {
                if (mWordsMatrix[row][col]) {
                    canvas.drawCircle(col * (mPointSpace + mPaintRadius * 2) + mPointSpace + mPaintRadius,
                            row * (mPointSpace + mPaintRadius * 2) + mPointSpace + mPaintRadius,
                            mPaintRadius, mFillPaint);
                } else {
                    canvas.drawCircle(col * (mPointSpace + mPaintRadius * 2) + mPointSpace + mPaintRadius,
                            row * (mPointSpace + mPaintRadius * 2) + mPointSpace + mPaintRadius,
                            mPaintRadius, mHollowPaint);
                }
            }
        }
        Message message = new Message();
        message.obj = this.mScrollDirection;
        mHandler.sendMessageDelayed(message, mScrollSpeed.getValue());
    }
  1. 通过Handler机制实现按期刷新分界面,即落到实处滚动作效果应。在下边包车型客车代码最终,正是在绘制后向Handler发送一个延迟音讯,进而步向到滚动循环,上边是在Handler中通过调用invalidate方法实现定期刷新,即落到实处滚动的效用:
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch ((Direction)msg.obj) {
                case LEFT:
                    matrixMoveToLeft();
                    invalidate();
                    break;
                case RIGHT:
                    matrixMoveToRight();
                    invalidate();
                    break;
            }
        }
    };

    private void matrixMoveToRight() {
        for (int row = 0; row < mDotMatrixFontType.getValue(); row++) {
            boolean temp = mWordsMatrix[row][mDotMatrixFontType.getValue() * mWordNumber - 1];
            System.arraycopy(mWordsMatrix[row], 0, mWordsMatrix[row], 1, mDotMatrixFontType.getValue() * mWordNumber - 1);
            mWordsMatrix[row][0] = temp;
        }
    }

    private void matrixMoveToLeft() {
        for (int row = 0; row < mDotMatrixFontType.getValue(); row++) {
            boolean temp = mWordsMatrix[row][0];
            System.arraycopy(mWordsMatrix[row], 1, mWordsMatrix[row], 0, mDotMatrixFontType.getValue() * mWordNumber - 1);
            mWordsMatrix[row][mDotMatrixFontType.getValue() * mWordNumber - 1] = temp;
        }
    }

hzk16的介绍以及简单的应用情势

申明:1、区码减1是因为数组是以0为早先而区号位号是以1为起首的

一点高级单片机,如魅族的M68300体系30人单片机,寻址范围可达8M,液晶显示常用的16×16汉字库二进制数据文件为两百多k,将汉字字仓库储存入大容积的E2PROM,通过地方线可寻址到汉字库中的每贰在这之中夏族民共和国字。

unsigned char key[8] = {

概述

看过歌唱会的同学应该都看出过客官举着LED点阵荧屏的品牌来支撑自个儿内心中的男神恐怕美人,认为这种点阵荧屏的意义挺风趣的,于是花了点时间用Android完结了弹指间,完结效果与利益如下:

图片 1

落到实处际效果益

HZK16字库是相符GB2312标准的16×16点阵字库,HZK16的GB2312-80支撑的方块字有6761个,符号6八十五个。个中超级汉字有3751个,按声序排列,二级汉字有3008个,按偏旁部首排列。大家在有的用参与合根本用不到如此多汉字字模,所以在采用时就足以只领到部分字体作为己用。

仅须求用asii码值乘以16就足以固定到方今字符的点阵地方

    }

printf("n");

void putfont32(char *vram, int xsize, int x, int y, char c, char *font1, char *font2)
{
    int i,k,j,f;
    char *p, d ;
    j=0;
    p=vram+(y+j)*xsize+x;
    j++;
    //上半部分
    for(i=0;i<16;i++)
    {
        for(k=0;k<8;k++)
        {
            if(font1[i]&(0x80>>k))
            {
                p[k+(i%2)*8]=c;
            }
        }
        if(i%2==0){
            for(k=0;k<4;k++){
                f=p[k];
                p[k]=p[7-k];
                p[7-k]=f;
            }
        }else{
            for(k=0;k<4;k++){
                f=p[k+8];
                p[k+8]=p[15-k];
                p[15-k]=f;
            }
        }
       /* for(k=0;k<8/2;k++)
        {
            f=p[k+(i%2)*8];
            p[k+(i%2)*8]=p[8-1-k+(i%2)*8];
            p[8-1-k+(i%2)*8]=f;
        }*/
        if(i%2)
        {
            p=vram+(y+j)*xsize+x;
            j++;
        }
    }
    //下半部分
    for(i=0;i<16;i++)
    {
        for(k=0;k<8;k++)
        {
            if(font2[i]&(0x80>>k))
            {
                p[k+(i%2)*8]=c;
            }
        }
        if(i%2==0){
            for(k=0;k<4;k++){
                f=p[k];
                p[k]=p[7-k];
                p[7-k]=f;
            }
        }else{
            for(k=0;k<4;k++){
                f=p[k+8];
                p[k+8]=p[15-k];
                p[15-k]=f;
            }
        }
        /*for(k=0;k<8/2;k++)
        {
            f=p[k+(i%2)*8];
            p[k+(i%2)*8]=p[8-1-k+(i%2)*8];
            p[8-1-k+(i%2)*8]=f;
        }*/
        if(i%2)
        {
            p=vram+(y+j)*xsize+x;
            j++;
        }
    }
    return;
}

unsigned char* fb_mem;

                            printf("%s",'#');

unsigned char buffer[32];

offset=(94*(区码-1)+(位码-1))*32

   3、最终乘以32是因为汉字库文应从该地点起的32字节音讯记录该字的字样消息(前边提到贰个中华人民共和国字要有三十二个字节展现)

在依附单片机的智能体系中,汉字展现模块是很首要的贰个组成都部队分,它应用遍布、操作轻便、调节和测量检验简便。

FILE* fphzk = NULL;

参谋资料:

这么我们就能够获得汉字在HZK16中的相对偏移地点:

概念如下:
unsigned char str[]="我"
在运营时str被最早化为2个字节长度,内容为“作者”的GBK码,为:0xCE(区码),0xD2(位码)。
运用如下换算公式得到“笔者”在HZK16文书中的地址,从该地方上马的各样32字节为“小编”的字样。
    ADD=【(区码-0xa1)×0x5e + (位码-0xa1)】×0x20
根据上边的总括办法,“作者”的字样地址:0x216E0 。他的C语言字模为:0x04,0x80,0x0E,0xA0,0x78,0x90,0x08,
0x90,0x08,0x84,0xFF,0xFE,0x08,0x80,
0x08,0x90,0x0A,0x90,0x0C,0x60,0x18,
0x40,0x68,0xA0,0x09,0x20,0x0A,0x14,
0x28,0x14,0x10,0x0C

0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01

区码:区号(汉字的首先个字节)-0xa0 (因为汉字编码是从0xa0区始发的,所以文件最前头正是从0xa0区开头,要算出相对区码)

二个字节8位来代表一行的8个像素是或不是被入选点亮

抑制篇幅,这里唯有给出流程图(假定事先将所需汉字写到了四个文本文件),如图1所示。

int i, j, k, offset;

笔者们领略贰个GB2312汉字是由三个字节编码的,范围为A1A1~FEFE。A1-A9为符号区,B0到F7为汉字区。每一个区有九十四个字符(注意:那只是编码的批准限制,不自然都有字型对应,例如符号区就有众多编码空白区域)。上边以汉字“作者”为例,介绍怎么样在HZK16文书中找到它对应的三十多个字节的字样数据。

显示器输出‘a’,“中”

      hz_buffer[i]=read_data(addr+i); //读取一字节的数额

版本2

运转结果,大家在euc.txt中步入一些中夏族民共和国字。

offset=(94*(区码-1)+(位码-1))*32

在微型Computer中对汉字的辨识是透过机内码来兑现的,汉字标准机内码为两字节代码。汉字在汉字库中是比照区位来排列的,每一区中有95个汉字,各种汉字都对应独一的区号和在本区的位号,汉字输入法中就有区位码方法,实际上,汉字机内码和区位码有标准的呼应关系,有些汉字在字库中的区号加上0xa0等于其机内码的高字节,位号加上0xa0等于其机内码的低字节,由此很轻易通进度序计算出要显示的汉字在汉字库中的区位号,即获取了其在汉字库中的偏移地址。

};

要求:原操作系统代码里只是支撑了希伯来语显示,要求做的是兑现对那么些种类的方块字全角辅助。

memset (fb_mem, 0, 1024*768); //这么些命令应该唯有在root能够实行

函数void read_hz(int16 hz)的参数hz为两字节的机内码,调用方法:read_hz(‘汉’);

flag = buffer[k*2+j]&key[i];

 

 

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

}

HZK16字Curry的16×16汉字一共要求2伍十六个点来呈现,也正是说须求叁拾二个字节本领达到规定的标准彰显四个一般性汉字的目标。

 

*/

就如下边那样:

位码:位号(汉字的第三个字节)-0xa0

    lcd_put_ascii(var.xres / 2, var.yres / 2, 'a');
    printf("中: chinese code: %02x %02xn", str[0], str[1]);
    lcd_put_chinese(var.xres / 2 + 32, var.yres / 2, str);

}

图片 2

字符点阵展现

if(pos<64*1024)   //在首先片27512微芯片

0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01

兑现思路:

各样字符由17个字节表示

int8 hz_buffer[32];//定义32字节数组,用于存款和储蓄点阵字模,该字模为横排字模。

这样大家就足以博得汉字在HZK16中的相对偏移地点:

  1. 理解HZK编码,明白一下相符GB2312标准的粤语点阵字库文件HZK16;
  2. 下载汉语GB2312的二进制点阵文件;
  3. 将HZK16.fnt文书放入nihongo文件夹中;
  4. 修改主makefile文件和app_make.txt文件,将原先装载nihongo.fnt的话语替换到装载HZK16.fnt就可以;
  5. 修改bootpack.c文件,将以前分配的装载俄文字体的内部存款和储蓄器扩展,载入字库的文件名;
  6. 在haribote/graphic.c中加上协助汉字的代码,扩张一个函数用于体现汉字;
  7. 修改putfonts8_asc函数里if (task->langmode == 3)语句块;
  8. 测验程序。
  9. 留意:马耳他语的编码是分为左半部分和右半部分,而笔者辈运用的HZK16是分为上半部分和下半部分的。

HZK16字Curry的16×16汉字一共须求257个点来突显,也正是说须求35个字节手艺达到规定的标准显示三个常见汉字的目的。

else if((pos>=128*1024)&&(pos<192*1024)) //在第三片27512晶片

printf("uchar code key[32] = {");

2、(94*(区号-1)+位号-1)是三个汉字字模占用的字节数

能够用命令: #dd if=/dev/zero of=/dev/fb 清空显示屏. 假设展现方式是 1024x768-8 位色,

汉字相似是以点阵式存款和储蓄的,如16×16,24×24点阵(即汉字的字样),每种汉字由32字节(16点阵)或72字节(24点阵)描述。根据汉字的分化字体,也可分为黑体字模、宋体字模、石籀文字模等等。

fgets((char*)word, 3, stdin);

注解:1、区码减1是因为数组是以0为发端而区号位号是以1为发端的

 

       addr=(int16)pos;

printf("%02X ", buffer[k]);

第6步,要静心,HZK16是前后两部分,差异于拉脱维亚语的左右两部分的构造。

framebuffer的道具文件一般是 /dev/fb0、/dev/fb1 等等。

pos=32*((int32)((area_h-1)*94)+area_l-1); //总计在二个整机的字库中的地方(256K)

fseek(fphzk, offset, SEEK_SET);

 有了摇头地址就能够从HZK16中读取汉字编码了

fb = open ("/dev/fb0", O_RDWR);

2依照单片机的汉字展现原理

fphzk = NULL;

本文由必威发布于必威-操作系统,转载请注明出处:需要做的是实现对这个系统的汉字全角支持,在

相关阅读