Chinaunix首页 | 论坛 | 博客
  • 博客访问: 72270
  • 博文数量: 14
  • 博客积分: 1410
  • 博客等级: 上尉
  • 技术积分: 165
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-06 23:59
文章分类

全部博文(14)

文章存档

2009年(14)

我的朋友

分类: C/C++

2009-06-22 21:16:26

一、什么是点阵?

我们先看两个字的点阵图:

A字母的点阵是这样的:8×16



汉字“你”的点阵是这样的:16×16


以上的两个文字的字模信息,应该让我们很清楚的明白了文字的显示原理。但是又是如何获取这些字模信息的呢?

我们知道英文字母数量比较少,我们只要用一个字节(8位)就足以表达。但是汉字非常多。要怎么表达呢?
前人采用的一个方法就是把ASCII码的高128位作为汉字的内码,低128位仍然作为英文字母的内码,然后用两个字节来表示一个汉字。通过这个内码,我们可以获取汉字的字模信息。然后再根据这些字模的信息,把相应的汉字显示出来。

二、什么是汉字字库?如何寻址?

点阵字库其实就是按照汉字内码的顺序,把汉字的字模信息存起来。16×16的点阵字库有94区,每个区有94个汉字的字模。这样总的有94×94个汉字。
我们之前说了,一个汉字由两个ASCII扩展码构成。第一个ASCII扩展码用来存放汉字的区码,第二个ASCII扩展码用来存放汉字的位码。具体是这样的:
第一个扩展ASCII码 = 128  + 汉字的区码
第二个扩展ASCII码 = 128 + 汉字的位码
这样,如果我们用char HZ[2]来表示一个汉字。则:
区码 = HZ[0] - 128
位码 = HZ[1] - 128
这样,算出区位码之后,我们就可以用它在汉字库里面寻址找字模了。具体的方式是:
该汉字的偏移地址 = (区码-1)×94×一个字占用的字节数 + 位码×一个字占用的字节数

这样我们就很容易的写出显示汉字字模的函数:

INT8U *HZK = (INT8U *)0x801c0000;   /* 汉字字库的存储地址 */
INT8U *ASCII = (INT8U *)0x801fba00; /* ASCII码字库的存储地址 */

INT8U const cmp_w[8]={128,64,32,16,8,4,2,1};

/*
*********************************************************************************************************
* Function   : DisplayHZ()                                         
*
* Description: 该函数用于在FDGK/GUI上显示一个汉字。汉字为:16*16点阵
*
* Arguments  : x     预显示的位置的横坐标
*              y     预显示的位置的纵坐标
*              FontModule 预显示的汉字模指针
*              color 该点的颜色值:16位,闪烁位(1位)+ RGB555(15位)
*
* Returns    : none
*********************************************************************************************************
*/
static void DisplayHZ(INT16U x, INT16U y, INT8U *FontModule, INT16U color)
    INT16U row,c;
    for( row=0;row<16;row++)                       /* 十六行点阵 */
    { 
        for( c=0;c<8;c++)
            if((FontModule[row*2]&cmp_w[c])!=0)    /* 前八位显示 */
                LCD_DrawPixel(c+x,row+y,color); 
        for(c=0;c<8;c++)
            if((FontModule[row*2+1]&cmp_w[c])!=0)  /* 后八位显示 */
                LCD_DrawPixel(c+8+x,row+y,color); 
    }
}

/*
*********************************************************************************************************
* Function   : GUI_WriteHZ()                                         
*
* Description: 该函数用于在FDGK/GUI上显示一个或多个汉字。
*
* Arguments  : x     预显示的位置的横坐标
*              y     预显示的位置的纵坐标
*              HZ    预显示的汉字串指针
*              color 该点的颜色值:16位,闪烁位(1位)+ RGB555(15位)
*
* Returns    : none
* Note       : 汉字串里面不能带有ASC字符,因为它们使用的字库不一样,会导致无法正常显示。
*********************************************************************************************************
*/
void GUI_WriteHZ(INT16U x,INT16U y,INT8U *HZ, INT16U color)
{
    INT32U i,j,k;
    INT8U *str;    
k = 0;
while(1)
{
   if(*HZ=='\0') break;               /* 显示所有,直到结束 */
   
   /* 取得字在字库里面的索引地址 */
   i = *HZ++ - 0xa0;
   j = *HZ++ - 0xa0;    
   str = HZK+((i-6-1)*94+(j-1))*32;   /* -6 操作是因为本终端对字库做了处理,汉字是由16区开始,而不是从11区开始*/
    
        DisplayHZ(x+k*16,y,str,color);     /* 在相应的地方写上汉字 */
        k++;
    }
}


这样就可以显示一大串的汉字了。但是还有一个问题,就是如果要显示的文字里面夹带英文字母,就无法显示。于是,对函数进行改进。

void GUI_PutString(INT16U x,INT16U y,INT8U *font, INT16U color)
{
    INT8U i,j;
    INT8U *str;    
    INT16U x0,y0;
    x0 = x;
    y0 = y;
    while(1)
    {
        if(*font == '\0') break;
        
        i = *font;
        if( (i & 0x80) == 0)                      /* 判断是否是扩展ASCII码 */
        {
            i = *font++;
            str = ASCII + (i-0x20)*16;
            DisplayASCII(x0,y0,str,color);     /* 在相应的地方写上ASC码 */
            x0 += 8;           
        }
        else {
            i = *font++ - 0xa0;
            j = *font++ - 0xa0;    
       str = HZK+((i-6-1)*94+(j-1))*32;   /* -6 操作是因为本终端对字库做了处理,汉字是由16区开始,而不是从11区开始*/
    
            DisplayHZ(x0,y0,str,color);     /* 在相应的地方写上汉字 */
            x0 += 16;           
        }
    }
}

这样,无论是汉字,还是英文单词,都可以很好的显示了。
阅读(3501) | 评论(1) | 转发(0) |
0

上一篇:openSUSE的liveCD的硬盘安装

下一篇:没有了

给主人留下些什么吧!~~

chinaunix网友2009-07-22 11:22:14

讲的非常好, 学习了,谢谢!