SDL使用16x16字模HZK16畫漢字

好多年前寫的東西了,翻出來玩玩,當時是爲了在ARM板的觸摸屏上顯示漢字,用到了16x16的字模HZK16,它裏面包含了很多漢字的字模,符合GB2312標準。

HZK16可以到這裏下載http://download.csdn.net/detail/chenxupro/6349685

字模的使用以及原理可以參考這裏http://www.chinaunix.net/old_jh/4/1064637.html

這裏與其說顯示漢字倒不如說“畫”比較合適,其實就是按照字模在SDL_Surface上畫點,組成漢字

下面的代碼可以這樣編譯

gcc -o SDLDrawChinese SDLDrawChinese.c -I./SDL-1.2.15/include -lmingw32 -L./SDL-1.2.15/lib -lSDLmain -lSDL

代碼如下

#include "SDL/SDL.h"
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void quit(int rc);
Uint32 getpixel(SDL_Surface *surface, int x, int y);
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel);

void DrawOnePoint(SDL_Surface *screen,int x,int y);
void DrawChineseCharacter(SDL_Surface *screen,int ShowX,int ShowY,unsigned char InCode0,unsigned char InCode1);

int main(int argc, char *argv[])
{
	SDL_Surface *screen;

    /* Initialize the SDL library */
    if( SDL_Init(SDL_INIT_VIDEO) < 0 ) 
    {
        fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
        exit(1);
    }

    /*
    * Initialize the display in a 240x320 8-bit palettized mode,
    * requesting a software surface
    */
    screen = SDL_SetVideoMode(240, 320, 8, SDL_SWSURFACE);
    if ( screen == NULL ) 
    {
        fprintf(stderr, "Couldn't set 320x240x8 video mode: %s\n",SDL_GetError());
        exit(1);
    }

	DrawChineseCharacter(screen,30, 50, 0xD1, 0xAF);

    SDL_Delay(4*1000);
    SDL_Quit();
	
	return 0;
}


/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void quit(int rc)
{
	SDL_Quit();
	exit(rc);
}

/*
* Return the pixel value at (x, y)
* NOTE: The surface must be locked before calling this!
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to retrieve */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
    switch(bpp) 
    {
    case 1:
        return *p;
    case 2:
        return *(Uint16 *)p;
    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
            return p[0] << 16 | p[1] << 8 | p[2];
        else
            return p[0] | p[1] << 8 | p[2] << 16;
    case 4:
        return *(Uint32 *)p;
    default:
        return 0; /* shouldn't happen, but avoids warnings */
    }
}

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch(bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        } else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;
    }
}

void DrawChineseCharacter(SDL_Surface *screen,int ShowX,int ShowY,unsigned char InCode0,unsigned char InCode1)
{
   int x=ShowX;
   int y=ShowY; // 顯示位置設置
   int i,j,k;   
   unsigned char incode[3]={0};    // 要讀出的漢字
   incode[0]=InCode0;
   incode[1]=InCode1; // GBK內碼
   unsigned char qh,wh;   
   unsigned long offset;   
         
   FILE *HZK;   
   char mat[32]; 

   // 佔兩個字節,取其區位號   
   qh=incode[0]-0xa0;    
   wh=incode[1]-0xa0;                
   offset=(94*(qh-1)+(wh-1))*32;  
   
   if((HZK=fopen("HZK16","rb"))==NULL)   
   {   
	   printf("Can't Open hzk16\n");   
	   exit(0);   
   }   
   fseek(HZK,offset,SEEK_SET);   
   fread(mat,32,1,HZK);
   for(j=0;j<16;j++)
   {
        for(i=0;i<2;i++)
		{
            for(k=0;k<8;k++)
			{
				if(((mat[j*2+i]>>(7-k))&0x1)!=0)
				{
					DrawOnePoint(screen,x+8*i+k,y+j);
				}
			}
		}
   }
   x+=30; 	
   fclose(HZK);
}

void DrawOnePoint(SDL_Surface *screen,int x,int y)
{
    Uint32 yellow;
    /* Map the color yellow to this display (R=0xff, G=ff, B=0x00)
       Note:  If the display is palettized, you must set the palette first.
    */
    yellow = SDL_MapRGB(screen->format, 0xff, 0xff, 0x00);
    /* Lock the screen for direct access to the pixels */
    if ( SDL_MUSTLOCK(screen) ) {
        if ( SDL_LockSurface(screen) < 0 ) {
            fprintf(stderr, "Can't lock screen: %s\n", SDL_GetError());
            return;
        }
    }
    putpixel(screen, x, y, yellow);
    if ( SDL_MUSTLOCK(screen) ) {
        SDL_UnlockSurface(screen);
    }
    /* Update just the part of the display that we've changed */
    SDL_UpdateRect(screen, x, y, 1, 1);
    return;
}

效果如下


發佈了51 篇原創文章 · 獲贊 7 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章