在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 <windows.h>
#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\\n", 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\\nFPS=%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;
else
ScreenMode = 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\\n", 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\\n", 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");
#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;
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;
}
http://www.rosoo.net/a/201003/8785.html
在SDL中显示GBK点阵汉字的更多相关文章
- GBK点阵显示字库的制作和使用
转自:http://blog.csdn.net/exbob/article/details/6539643 GBK编码共收录汉字21003个.符号883个,并提供1894个造字码位,简.繁体字融于一库 ...
- 在SDL工程中让SDL_ttf渲染汉字
有时候在关于SDL的博文中看到一些评论,说SDL对中文的支持不佳,因为当程序涉及中文时总是输出乱码. 照我个人观点,这里面很多都是误解.下面就根据我在windows下使用SDL的情况,说说我的观点. ...
- (转)在SDL工程中让SDL_ttf渲染汉字
有时候在关于SDL的博文中看到一些评论,说SDL对中文的支持不佳,因为当程序涉及中文时总是输出乱码. 照我个人观点,这里面很多都是误解.下面就根据我在windows下使用SDL的情况,说说我的观点. ...
- 将汉字取模软件中的汉字放到keil5中显示
最近因为要使用STM32做毕业设计,需要用LCD显示中文,STM32开发板用的是原子的战舰STM32开发板,给的LCD显示例程里貌似没有中文显示,那么需要自己去编写中文显示程序. 软件编写对我来说并不 ...
- Kivy中显示汉字的问题
1. kivy中显示中文乱码和提示错误的原因: 编码问题 字体问题 2. 字体问题的解决 可以下载支持中文的字体文件ttf,我这里使用了微软雅黑中文简体msyh.ttf.我们在编写布局时可以直接在相关 ...
- dedecms为什么文档标题最大长度只能显示二十个汉字呢?
今天遇到文章标题无论怎么修改,超出二十个汉字不能全部保存,系统只截取前二十个汉字的内容进行保存. 在后台查看系统设置: 系统——其它选项——文档标题最大长度,的值是60,对应的数据库表字段char的长 ...
- centos7安装vim以及在vim中显示中文
1.centos7安装vim yum -y install vim(简单粗暴安装方法) 2.在vim中显示中文不出现乱码 (1).vim ~/.vimrc (~/.vimrc为vim配置文件) (2) ...
- MathType中输入不了汉字如何处理
MathType作为一款常见的数学公式编辑器在编辑数学公式时,不仅可以输入英文字符,对中文也有很好的兼容性.但是有些用户在使用MathType编辑公式时,发现一些汉字是输入不进去的,这个时候我们就需要 ...
- 【转载】在Windows终端中显示UTF-8字符
一直苦恼于如何在Windows终端中显示UTF-8字符的问题.比如,在MySQL命令行下,如果数据库的编码是UTF-8,那么,在查询数据库的时候,里面的中文都会变成乱码.今天半无意的搜索了一下,结果发 ...
随机推荐
- Ribbon负载均衡(四)
一.Ribbon定义 spring cloud Ribbon是基于Netflix Ribbon实现的一套客户端,负载均衡工具 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端 ...
- Codeforces 246E - Blood Cousins Return (树上启发式合并)
246E - Blood Cousins Return 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor,每个节点有名字,名字不唯一.多次查询,给出 u k ...
- Requirement Analysis
BRD:Business Requirements Document,商业需求文档.这是产品声明周期中最早的问的文档,再早就应该是脑中的构思了,其内容涉及市场分析,销售策略,盈利预测等,通常是和老大们 ...
- bzoj 3864: Hero meet devil
bzoj3864次元联通们 第一次写dp of dp (:з」∠) 不能再颓废啦 考虑最长匹配序列匹配书转移 由于dp[i][j]的转移可由上一行dp[i-1][j-1],dp[i-1][j],dp[ ...
- 【NOI2016】优秀的拆分
题目描述 如果一个字符串可以被拆分为 $AABB$ 的形式,其中 $A$ 和 $B$ 是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aabaabaa,如果令 $A = \m ...
- Extjs Ext.grid.column.Column 隐藏显示列
1.根据字段名字 grid.down("gridcolumn[dataIndex=PLAN_QTY]").show();//hide() 2.根据列号 grid.columns[1 ...
- 记录在Spring-Boot中使用Fegin调用RESTfull的PATCH方法设置
使用了ZooKeeper,设置 spring.cloud.zookeeper.dependency.headers.enabled=false 参考: https://github.com/sprin ...
- 虚拟机拷贝之后,发现系统内的开机自启动的nginx,不能自启动了
因业务需要,同事以某个虚拟机为模板,复制出其他的CentOS虚拟机时,发现原系统内的开机自启动的nginx,不能再自启动了. 好吧,那就重新注册一下 nginx 的开机自启动: # 先删除原来的注册: ...
- JAVA之抽象类与抽象方法
抽象方法:在类中没有方法体的方法,就是抽象方法.抽象类:含有抽象方法的类就叫抽象类.|||||||||抽象类不能被实例化(new)为什么要使用抽象方法?(以下是个人观点)因 为在面向对象的编程的思想中 ...
- log4j教程 8、日志格式化
Apache log4j 提供了各种布局对象,每一个对象都可以根据各种布局格式记录数据.另外,也可以创建一个布局对象格式化测井数据中的特定应用的方法. 所有的布局对象 - Appender对象收到 L ...