Deepin Linux 下 SDL2.0 如何显示汉字
**
前言:
**
SDL2跨平台、开源、优异的性能,能开发各种游戏、工业软件,但貌似中文支持不尿性。网上有各种SDL显示汉字的方案,十分繁杂,还不易成功,还有的是windows下的经验。好在SDL2.0对Utf8格式支持很好,能显示多国语言,但也容易失败,原因是SDL2需要安装扩展包,还依赖free type,还要自己加载字体。踩坑后总结如下。支持国产,全在Deepin Linux 15.8下测试成功。
一、安装SDL2
源码下载 https://www.libsdl.org/download-2.0.php
SDL2官方教程 http://lazyfoo.net/tutorials/SDL/index.php
SDL2 函数参考 https://wiki.libsdl.org/CategoryAPI
安装
apt-get 虽然好用,但源码安装的最新最全,下载SDL2-2.0.16.tar.gz源码包后, 用tar命令解压,然后用cmake 生成makefile, 最后make 和 安装。
tar -xzvf SDL2-2.0.16.tar.gz
cd SDL2-2.0.16
mkdir mybuild
cd mybuild
cmake ..
make
sudo make install
二、安装字体包freetype
freetype源码下载 https://sourceforge.net/projects/freetype/
freetype-2.11.0.tar.gz, 虽然可以用cmake 安装,但有点问题,所以改用configure安装:
tar -xzvf freetype-2.11.0.tar.gz
cd freetype-2.11.0
./configure
make
sudo make install
三、安装SDL2扩展字体包TTF
字体扩展ttf源码下载 https://www.libsdl.org/projects/SDL_ttf/
源码包SDL2_ttf-2.0.15.tar.gz,cmake 安装如下
tar SDL2_ttf-2.0.15
cd SDL2_ttf-2.0.15
./configure
make
sudo make install
如果要处理多种格式的图像,顺便把 image 扩展包也安装了
https://github.com/libsdl-org/SDL_image/releases
SDL2_image-2.0.5.tar.gz,现在又得用configure安装
tar -xzvf SDL2_image-2.0.5.tar.gz
cd SDL2_image-2.0.5
./configure
make
sudo make install
四、编码测试
为了一例多测,我把png图像载入和显示、键盘和鼠标控制也加入例子,导致代码较多,但参考意义大。为了简单,用纯c语言完成,适合怕c++语法复杂的人。另外使用了禁忌goto语句,为了方便发生错误时,能及时释放内存。
#include <stdlib.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
// gcc `sdl2-config --cflags --libs` font.c -lSDL2_image -lSDL2_ttf
SDL_Surface * g_TextSurface, * g_Surface, * g_PNGSurface;
SDL_Window * g_Window = NULL;
TTF_Font * g_Font =NULL;
//======================================================================
SDL_Surface * OpenPng( const char * fileName )
{
SDL_Surface* optimizedSurface = NULL;//The final optimized image
SDL_Surface* loadedSurface = IMG_Load( fileName);
if( loadedSurface == NULL )
{
printf( "Unable to load image %s! SDL_image Error: %s\n", fileName, IMG_GetError() );
}
else
{
optimizedSurface = SDL_ConvertSurface( loadedSurface, g_Surface->format, 0 );
if( optimizedSurface == NULL )
{
printf( "Unable to optimize image %s! SDL Error: %s\n", fileName, SDL_GetError() );
}
SDL_FreeSurface( loadedSurface );
}
return optimizedSurface;
}
//======================================================================
int InitFont()
{
if(TTF_Init()==-1)
{
printf("TTF_Init: %s\n", TTF_GetError());
return 0;
}
g_Font = TTF_OpenFont("./simhei.ttf", 30); // 此处更换你想的字体
if (g_Font == NULL)
{
fprintf(stderr, "font open failure %s\n", SDL_GetError());
return 0;
}
return 1;
}
//======================================================================
int Init()
{
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
return (0);
}
// Register SDL_Quit to be called at exit; makes sure things are
// cleaned up when we quit.
atexit(SDL_Quit);
// Attempt to create a 640x480 window with 32bit pixels.
g_Window = SDL_CreateWindow( "汉字和png图像测试", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN );
if ( !g_Window )
{
fprintf(stderr, "error create window: %s\n", SDL_GetError());
return 0;
}
g_Surface = SDL_GetWindowSurface( g_Window );
if ( !g_Surface )
{
fprintf(stderr, "Unable to set up video: %s\n", SDL_GetError());
return 0;
}
g_PNGSurface = OpenPng( "./logo.png" ); // 可替换为你的png图片
if( g_PNGSurface == NULL )
{
printf( "Failed to load PNG image!\n" );
}
return InitFont();
}
//======================================================================
int Print(int x, int y, char *text)
{
SDL_Color color = {0xFF, 0x22, 0};
SDL_Rect offset = {x,y,x,y};
if(!(g_TextSurface=TTF_RenderUTF8_Solid(g_Font,text, color) ))
{
fprintf(stderr, "font open failure %s\n", SDL_GetError());
return 0;
}
else
{
SDL_BlitSurface(g_TextSurface, NULL, g_Surface, &offset);
}
return 1;
}
//======================================================================
void DrawImg(int x, int y, int w, int h)
{
SDL_Rect r;
r.x = x;
r.y = y;
r.w = w;
r.h = h;
if (g_PNGSurface)
{
SDL_BlitSurface( g_PNGSurface, NULL, g_Surface, &r ); // SDL_BlitSurface
}
else
SDL_FillRect(g_Surface, &r, 0xFF0000); // red to warning no img
}
//======================================================================
int render()
{ int r = Print(20, 30, "全球linux系统排名: 国产Deepin排名第10");
DrawImg(220, 180, 0, 0);
SDL_UpdateWindowSurface( g_Window );
SDL_Delay(20); // don't take all the cpu time
return r;
}
//======================================================================
int main(int argc, char *argv[])
{
if ( ! Init())
goto end;
SDL_Rect r = {0,0,640,480};
while (1) // Main loop: loop forever.
{
if (! render())
goto end;
SDL_Event event; // SDL_Event is a union
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
goto end;
case SDL_KEYUP:
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
goto end;
}
break;
case SDL_MOUSEBUTTONUP:
SDL_FillRect(g_Surface, &r, rand() | 0x77);
if (! Print(event.motion.x, event.motion.y, "中文 Linux"))
goto end;
break;
}
}
}
end:
TTF_CloseFont(g_Font);
SDL_FreeSurface(g_TextSurface);
SDL_FreeSurface(g_Surface);
TTF_Quit();
return 0;
}
编译指令如下:
gcc `sdl2-config --cflags --libs` font.c -lSDL2_image -lSDL2_ttf
运行效果如下,用鼠标点击,就不断冒出"中文 Linux"文字。
大家可能感觉到SDL显示文字和图片比其他工具都困难,但高效的底层开发就是这样,因为一切细节都在你的掌控之中。