在SDL中显示GBK点阵汉字

大家注意到没有,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 〈time.h>
#include 〈stdio.h>
#include 〈stdlib.h>
#include 〈string.h>
#include "SDL.h"
#include "SDL_image.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 HZK16[766080];
bool HZ_Init();
bool HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, const 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;

int main()
{
char TimeString[256];
time_t timer;
struct tm *tblock;

HZ_Init();

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.jpg" );

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;

return 1;
}

void DrawFrame( )
{
char tmp[256];
int step = 4;

//
sprintf( tmp, "TotalFrame=%u", frames );

TileBlt( bg, 0, 0 );



if ( rand( ) % 400 < 2 )
{
jx = rand( ) % ( Width - 10 );
jy = rand( ) % ( Height - 10 );
}

sprintf( tmp, "FPS=%d", fps );

HZ_TextOut( screen, 10, 300, 12, 0, "正面面板");
HZ_TextOut( screen, 10, 318, 12, 0, "电子对抗显示" );
HZ_TextOut( screen, 10, 334, 12, 0, "陈青山" );
HZ_TextOut( screen , 10, 380, 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 */
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");
#else
newfp = 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");
#else
newfp = 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;
int num=0;
if((file = fopen( "./HZK16", "rb" ))==NULL)
{
printf("open HZK16 error! ");
return false;
}

num=fread( HZK16, 32, 0x5d84, file );
printf("num ---> %d ", num);
fclose( file );

file = fopen( "./HZK12", "rb" );
fread( HZK12, 24, 0x5d84, file );
fclose( file );

return true;
}
//---------------------------------------------------------------------------

bool HZ_TextOut( SDL_Surface * image, int x, int y, int width, int space, const 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 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;
}
//---------------------------------------------------------------------------
_____________________________________________________________________________
Makefile内容如下

DD = -I/usr/include/SDL -L/usr/local/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_mixer -lpthread
FF = -D__FOR_LINUX__
WW = -lpthread -pthread -lfml -lfml32 -lengine -lpthread
RM = rm -f
RMDIR =rm -rf
CXX = g++

.SUFFIXES: .cpp

.cpp.o:
$(CXX) -c $(DD) -o $@ $<

OBJS_cqs= cqs.o
all: cqs

cqs: $(OBJS_cqs)
$(RM) $@
$(CXX) -o $@ $(OBJS_cqs) $(DD) $(FF)

clean:
$(RM) cqs *.o

come from: http://blog.itpub.net/10797429/viewspace-101687/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值