在SDL中显示GBK点阵汉字(转)[@more@]
大家注意到没有,RA2的中文版本使用的是GBK点阵字库,这样做有一个好处:不管玩家是用的简体还是繁体都能识别显示的文字。
GBK的意思大概是“国家标准汉字扩展字符集”吧,记不清了。但它的确是个好东东,比GB2312、BIG5什么的强多了。因为它包括GB2312、GBK的所有字符而且还补充了很多字,另外,还包括日文、朝鲜文以及大量的符号字符。
我在UCDOS for win版本里面找到了GBK的点阵字库(HZK12.GBK、HZK14.GBK、HZK16.GBK)。分析了一下,知道了结构。这里是我写的一个演示程序,程序编译需要有sdl库。遵循“惯例”,按F4切换全屏/窗口状态,Esc退出。程序把标准输出和标准错误重定向到"stdout.txt"和 "stderr.txt"中。
#include
#include #include #include #include "sdl.h"#include "SDL_image.h"#include "sfont.h"//---------------------------------------------------------------------------#define STDOUT_FILE "stdout.txt"#define STDERR_FILE "stderr.txt"SDL_Surface *screen;Uint32 fps;Uint32 AppStartTime = 0;Uint32 frame_count = 0;static Uint32 frames;SDL_Event event;SDL_Surface * SetMode( int Width, int Height, int BPP, int Flags );SDL_Surface * LoadBMP( char * filename );void MainLoops( int ( * EventFunc)( ), void ( * DrawFunc )( ), int DelayTime );void Blt( SDL_Surface * image, int x, int y );void TileBlt( SDL_Surface * image, int x, int y );void SetTransparentColor( SDL_Surface * sprite, int R, int G, int B );void IoRedirect( );void cleanup_output( );void initfps();//---------------------------------------------------------------------------Uint8 HZK12[574560];Uint8 HZK14[670320];Uint8 HZK16[766080];BOOL HZ_Init();BOOL HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, unsigned char * str );//---------------------------------------------------------------------------int ProcessEvent( );void DrawFrame( );SDL_Surface * bg, * font;int ix, iy, jx, jy;int Width = 640;int Height = 480;int bpp = 16;int ScreenMode = 0;WINAPI WinMain(HINSTANCE hInstPre, HINSTANCE hInstance, LPSTR cmd, int xxx ){char TimeString[256];time_t timer;struct tm *tblock;HZ_Init();IoRedirect( );frames = 0;timer = time(NULL);tblock = localtime(&timer);strftime( TimeString, 256, "Time=%Z: %Y-%m-%d %a %H:%M:%S", tblock );printf( "%s
", TimeString );SetMode( Width, Height, bpp, SDL_SWSURFACE|ScreenMode );SDL_ShowCursor(0);SDL_WM_SetCaption( "demo", "demo" );bg = IMG_Load( ".\2k_bg.gif" );font = IMG_Load( ".\small.gif" );InitFont(font);SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 127 );ix=iy=0;jx=jy= Height>>1;srand( (Uint32)timer );MainLoops( ProcessEvent, DrawFrame, 0 );printf( "ScreenMode=%d*%d*%d
FPS=%u", Width, Height, bpp, fps );return 0;}int ProcessEvent( ){Uint8 *keystate;keystate = SDL_GetKeyState( NULL );if ( ( keystate[SDLK_ESCAPE] ) || ( keystate[SDLK_q] ) )return 0;if ( keystate[SDLK_F4] ){if ( ScreenMode )ScreenMode = 0;elseScreenMode = SDL_FULLSCREEN;SetMode( Width, Height, bpp, SDL_SWSURFACE|ScreenMode );initfps( );}return 1;}void DrawFrame( ){char tmp[256];int step = 4;//sprintf( tmp, "TotalFrame=%u", frames );TileBlt( bg, 0, 0 );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 4 );PutString( screen, ix % Width - 6, iy % Height - 6, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 8 );PutString( screen, ix % Width - 5, iy % Height - 5, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 16 );PutString( screen, ix % Width - 4, iy % Height - 4, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 32 );PutString( screen, ix % Width - 3, iy % Height - 3, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 64 );PutString( screen, ix % Width - 2, iy % Height - 2, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 128 );PutString( screen, ix % Width - 1, iy % Height - 1, tmp );SDL_SetAlpha( font, SDL_SRCALPHA|SDL_RLEACCEL, 192 );PutString( screen, ix % Width, iy % Height, tmp );PutString( screen, ix % Width, iy % Height + 40, tmp );if ( rand( ) % 400 < 2 ){jx = rand( ) % ( Width - 10 );jy = rand( ) % ( Height - 10 );}sprintf( tmp, "FPS=%d", fps );PutString( screen, 7, 7, tmp );//聞波,2000 HZ_TextOut( screen, 10, 300, 16, 0, "十步殺一人,千里不留行");HZ_TextOut( screen, 10, 318, 14, 0, "十步殺一人,千里不留行" );HZ_TextOut( screen, 10, 334, 12, 0, "十步殺一人,千里不留行" );ix += step;iy += step;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------SDL_Surface * SetMode( int Width, int Height, int BPP, int Flags ){/* Initialize the SDL library */if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ){fprintf(stderr, "Couldn't initialize SDL: %s
", SDL_GetError( ) );return NULL;}/* Clean up on exit */atexit(SDL_Quit);/* Initialize the display in a 640x480 8-bit palettized mode */screen = SDL_SetVideoMode( Width, Height, BPP, Flags );if ( screen == NULL ){fprintf( stderr, "Couldn't set %dx%dx%d video mode: %s
", Width, Height, BPP, SDL_GetError( ) );}return screen;}//---------------------------------------------------------------------------void initfps( ){AppStartTime = SDL_GetTicks();frame_count = 0;}//---------------------------------------------------------------------------void MainLoops( int ( * EventFunc)( ), void ( * DrawFunc)( ), int DelayTime ){if ( EventFunc&&DrawFunc ){memset( &event, 0, sizeof( SDL_Event ) );initfps( );while( EventFunc( ) ){SDL_PollEvent(&event);if ( event.type == SDL_ACTIVEEVENT ){if ( ( ( event.active.state & SDL_APPACTIVE ) == FALSE ) ||( event.active.gain == FALSE ) )initfps( );}SDL_PumpEvents();DrawFunc( );SDL_UpdateRect(screen,0, 0, 0, 0);frame_count ++;frames ++;fps = frame_count * 1000 / ( SDL_GetTicks( ) - AppStartTime );if ( DelayTime ) SDL_Delay( DelayTime );}}}//---------------------------------------------------------------------------SDL_Surface * LoadBMP( char * filename ){SDL_Surface * imagebmp, * image;imagebmp = SDL_LoadBMP( filename );if ( imagebmp == NULL )return NULL;if ( imagebmp->format->palette != NULL ){SDL_SetColors( screen, imagebmp->format->palette->colors, 0, imagebmp->format->palette->ncolors );}/* Convert the image to the video format (maps colors) */image = SDL_DisplayFormat( imagebmp );SDL_FreeSurface( imagebmp );return image;}//---------------------------------------------------------------------------void Blt( SDL_Surface * image, int x, int y ){int Row, Col, r, c, shiftx, shifty;SDL_Rect dest, src;/* out of screen */if ( ( x > screen->w ) || ( y > screen->h ) ||( x + image->w < 1 ) || ( y + image->h < 1 ) )return;src.x = 0;src.y = 0;src.w = image->w;src.h = image->h;dest.x = x;dest.y = y;dest.w = src.w;if ( y < 0 ){src.y = 0 - y;src.h = image->h + src.y;dest.y = 0;}dest.h = src.h;SDL_BlitSurface( image, &src, screen, &dest );}//---------------------------------------------------------------------------void TileBlt( SDL_Surface * image, int x, int y ){int Row, Col, r, c, shiftx, shifty;SDL_Rect dest, src;shiftx = x % image->w;shifty = y % image->h;if ( shiftx >0 ) shiftx -= image->w;if ( shifty >0 ) shifty -= image->h;Row = screen->h / image->h + 2;Col = screen->w / image->w + 2;dest.x = 0;dest.y = 0;dest.w = image->w;dest.h = image->h;src.x = 0;src.y = 0;src.w = image->w;src.h = image->h;for ( r = 0; r < Row; r ++ ){if ( r ){src.y = 0;src.h = image->h;dest.h = image->h;dest.y = image->h * r + shifty;}else{ /* first line ? */src.y = 0 - shifty;src.h = image->h;dest.h = image->h + shifty;dest.y = 0;}for ( c = 0; c < Col; c ++ ){dest.x = image->w * c + shiftx;SDL_BlitSurface( image, &src, screen, &dest );}}}//---------------------------------------------------------------------------void SetTransparentColor( SDL_Surface * sprite, int R, int G, int B ){SDL_SetColorKey( sprite, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB( sprite->format, R, G, B ) );}//---------------------------------------------------------------------------/* Remove the output files if there was no output written */static void cleanup_output( ){FILE *file;int empty;/* Flush the output in case anything is queued */fclose(stdout);fclose(stderr);/* See if the files have any output in them */file = fopen(STDOUT_FILE, "rb");if ( file ){empty = (fgetc(file) == EOF) ? 1 : 0;fclose(file);if ( empty )remove(STDOUT_FILE);}file = fopen(STDERR_FILE, "rb");if ( file ){empty = (fgetc(file) == EOF) ? 1 : 0;fclose(file);if ( empty )remove(STDERR_FILE);}}//---------------------------------------------------------------------------void IoRedirect( ){FILE *newfp;/* Redirect standard standard output */newfp = freopen(STDOUT_FILE, "w", stdout);if ( newfp == NULL ){ /* This happens on NT */#if !defined(stdout)stdout = fopen(STDOUT_FILE, "w");#elsenewfp = fopen(STDOUT_FILE, "w");if ( newfp ) *stdout = *newfp;#endif}/* Redirect standard standard error */newfp = freopen(STDERR_FILE, "w", stderr);if ( newfp == NULL ){ /* This happens on NT */#if !defined(stderr)stderr = fopen(STDERR_FILE, "w");#elsenewfp = fopen(STDERR_FILE, "w");if ( newfp ) *stderr = *newfp;#endif}setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */setbuf(stderr, NULL); /* No buffering */atexit(cleanup_output);}//---------------------------------------------------------------------------BOOL HZ_Init(){FILE * file;file = fopen( ".\HZK16.GBK", "rb" );fread( HZK16, 32, 0x5d84, file );fclose( file );file = fopen( ".\HZK14.GBK", "rb" );fread( HZK14, 28, 0x5d84, file );fclose( file );file = fopen( ".\HZK12.GBK", "rb" );fread( HZK12, 24, 0x5d84, file );fclose( file );return TRUE;}//---------------------------------------------------------------------------BOOL HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, unsigned char * str ){Uint8 * bufptr;Uint8 * HZK;Uint16 Bits[16];int i,j,k, m, offset = 0;unsigned char q;unsigned char w;switch ( width ){case 12:HZK = HZK12;break;case 14:HZK = HZK14;break;case 16:HZK = HZK16;break;default:return FALSE;}bufptr = (unsigned char*)image->pixels;m = strlen( str );for ( k = 0; k < m; k +=2 ){Uint32 X, Y, Z, M;q = str[k];w = str[k+1];if ( w > 0xa0 ){M = 0x5e;Y = w - 0xa1;if ( q > 0xa0 ){X = q - 0xa1;Z = 0;}else{X = q - 0x81;Z = 0x2284;}}else{M = 0x60;if ( w > 0x7f ) Y = w - 0x41;else Y = w - 0x40;if ( q > 0xa0 ){X = q - 0xa1;Z = 0x3a44;}else{X = q - 0x81;Z = 0x2e44;}}memcpy( Bits, HZK + ( X * M + Y + Z ) * width * 2, width * 2 );for ( i = 0; i < width; i ++ ) // row{Uint16 line;line = Bits[ i ];line = ( line >> 8 ) + ( line << 8 );for ( j = 0; j < 16 ; j ++ ) //col{int index;int mask = 1;index = offset + x + 16 - j - 1 + ( y + i ) * image->pitch / image->format->BytesPerPixel;mask <<= j;if ( mask & line ){bufptr[ index * 2 ] = 0xff;bufptr[ index * 2 + 1 ] = 0xff;}}}offset += width + space;}return TRUE;
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/8225414/viewspace-944777/
,如需转载,请注明出处,否则将追究法律责任。