嵌入式 SDL显示文字

原创 2013年12月02日 14:55:13
前面教程里,我们只显示图片,没提到如何显示文字, SDL本身没有显示文字功能,它需要用扩展库SDL_ttf来显示文字。ttf是True Type Font的缩写,ttf是Windows下的缺省字体,它有美观,放大缩小不变形的优点,因此广泛应用很多场合。

  使用ttf库的第一件事要从Windows的字库下拷贝出一个字库出来,最好是中文字体,这样可以同时支持英文和中文显示。它一般在c:\windows\fonts 目录下面。比如simhei.ttf 就是仿黑体的字库,将这个文件拷贝到你的源文件目录下。

  要使用SDL_ttf库首先要下载该扩展库:http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf.html

  下载完成后按以前方式安装(SDL安装教程里有讲),然后在你的源文件里加载头文件"SDL_ttf.h”。要显示文字需要按以下步骤进行:

  一.初始TTF库

  初始化TTF库要调用TTF_Init(),成功返回-1,不成功返回0。

  二.打开一个TTF_Font字体.

   使用 TTF_Font *TTF_OpenFont(const char *file, int ptsize);函数打开字体
  其中file是指字体文件的路径,可以为相对路径或绝对路径, ptsize是指字号,即字体大小。它是基于720DPI的,有一个简单办法来估算字体大小,在Word中    选择相应的字号即可看出效果来,不成功返回NULL。以下是打开一个黑体代码,字号20,字体文件跟原文件在同一个目录下。  

复制代码
 //打开simfang.ttf 字库,设字体为20号 font = TTF_OpenFont("simhei.ttf",20); if(font == NULL) { fprintf(stderr,"font open failure %s\n",SDL_GetError()); exit(-1); }  
复制代码

三.将文字转换成表面

  要想显示文字,首先要将文字渲染成一副图像,将文字渲染成一个图像表面,有三种渲染方式:

  Solid 渲染的最快,但效果最差,文字不平滑,是单色文字,不带边框。

  Shaded 比Solid渲染的慢,但显示效果好于Solid,带阴影。

  Blend 渲染最慢,但显示效果最好。

  四.把文字SDL_Surface 输出到屏幕显示,如果不需它,必须释放它

   文字表面和其他表面一样,可以传输到显示表面显示。
五.关闭TTF_Font字体

  使用 void TTF_CloseFont(TTF_Font *font) ;关闭字体
六.释放TTF库

  如果不需要再显示文字,可以释放TTF库,使用 void TTF_Quit() ;
  下面以一个例子展示一下如何显示文字,程序运行效果:  

  在这个例子里我们要掌握如何显示西文、中文,以及如何给程序设置标题、图标。程序主要代码如下:  

复制代码
 1 #include 2 #include 3 #include <<SPAN style="COLOR: rgb(0,0,255)">string.h> 4 #include "font.h" 5 6 int main(int argc,char * argv[]) 7 { 8 char a[] = "Hello World!"; 9 int quit = 0; 10 wchar_t * p ; 11 char tmp[]="世界,你好!"; 12 wchar_t msg[] =L"圣 旨"; 13 14 if(!init("文字","icon.bmp")) 15 { 16 exit(0); 17 } 18 19 //打开simfang.ttf 字库,设字体为20号 20 font = TTF_OpenFont("simhei.ttf",20); 21 if(font == NULL) 22 { 23 fprintf(stderr,"font open failure %s\n",SDL_GetError()); 24 exit(-1); 25 } 26 27 gpBackground = loadImage("background.jpg"); 28 applySurface(0,0,gpBackground,gpScreen); 29 30 //TTF_SetFontStyle(font,TTF_STYLE_BOLD | TTF_STYLE_ITALIC); 31 32 //显示西文 33 gpMessage[0] = TTF_RenderText_Solid(font,a,RGB_Black); 34 gpMessage[1] = TTF_RenderText_Shaded(font,a,RGB_Black,RGB_White); 35 gpMessage[2] = TTF_RenderText_Blended(font,a,RGB_Black); 36 applySurface(80,120,gpMessage[0],gpScreen); 37 applySurface(80,150,gpMessage[1],gpScreen); 38 applySurface(80,180,gpMessage[2],gpScreen); 39 SDL_Flip(gpScreen); 40 41 42 //显示中文 43 p = cstringToUnicode(tmp); 44 gpChinese = TTF_RenderUNICODE_Solid( font, p, RGB_Black); 45 applySurface(340,120,gpChinese,gpScreen); 46 SDL_FreeSurface(gpChinese); 47 gpChinese = TTF_RenderUNICODE_Shaded( font, p, RGB_Black,RGB_White); 48 applySurface(340,150,gpChinese,gpScreen); 49 SDL_FreeSurface(gpChinese); 50 gpChinese = TTF_RenderUNICODE_Blended( font, p, RGB_Black); 51 applySurface(340,180,gpChinese,gpScreen); 52 SDL_FreeSurface(gpChinese); 53 SDL_Flip(gpScreen); 54 free(p); 55 p = NULL; 56 57 TTF_CloseFont(font); 58 59 //重新打开simfang.ttf 字库,设字体为40 60 font = TTF_OpenFont("simhei.ttf",40); 61 if(font == NULL) 62 { 63 fprintf(stderr,"font open failure %s\n",SDL_GetError()); 64 exit(-1); 65 } 66 gpChinese = TTF_RenderUNICODE_Solid( font, msg, RGB_Yellow); 67 applySurface(260,50,gpChinese,gpScreen); 68 SDL_Flip(gpScreen); 69 SDL_FreeSurface(gpChinese); 70 71 gpChinese = TTF_RenderUNICODE_Solid( font, L"C语言始终被模仿,从未被超越!", RGB_Red); 72 applySurface(100,240,gpChinese,gpScreen); 73 SDL_FreeSurface(gpChinese); 74 75 gpChinese = TTF_RenderUNICODE_Solid( font, L"不懂C语言不要说自己是程序员!", RGB_Red); 76 applySurface(100,300,gpChinese,gpScreen); 77 SDL_FreeSurface(gpChinese); 78 SDL_Flip(gpScreen); 79 80 // 事件处理 81 while(!quit) 82 { 83 if (SDL_PollEvent(&myEvent)) 84 { 85 if (myEvent.type==SDL_QUIT) 86 { 87 quit = 1; 88 } 89 } 90 } 91 return 0; 92 }
复制代码

  其中font.h是自己定义的头文件,声明了常用的变量、常量、函数,其代码如下:  

复制代码
#ifndef FONT_H_2012_05_31 #define FONT_H_2012_05_31 #include "SDL.h" #include "SDL_image.h" #include "SDL_ttf.h" #include  //定义布尔类型 typedef int BOOL; #define TRUE 1 #define FALSE 0 //屏幕分辩率 #define SCREEN_WIDTH 718 #define SCREEN_HEIGHT 419 #define SCREEN_BPP 32 //表面声明 extern SDL_Surface *gpBackground; //背景表面 extern SDL_Surface *gpScreen; //显示表面 extern SDL_Surface *gpMessage[3]; //西文文字表面 extern SDL_Surface *gpChinese;//中文文字表面 //事件声明 extern SDL_Event myEvent; // 字体声明 extern TTF_Font *font;  extern const SDL_Color RGB_Black; extern const SDL_Color RGB_Red; extern const SDL_Color RGB_Green; extern const SDL_Color RGB_Blue; extern const SDL_Color RGB_Cyan; extern const SDL_Color RGB_Magenta; extern const SDL_Color RGB_Yellow; extern const SDL_Color RGB_White; extern const SDL_Color RGB_Gray; extern const SDL_Color RGB_Grey; extern const SDL_Color RGB_Maroon ; extern const SDL_Color RGB_Darkgreen; extern const SDL_Color RGB_Navy; extern const SDL_Color RGB_Teal; extern const SDL_Color RGB_Purple; extern const SDL_Color RGB_Olive; extern const SDL_Color RGB_Noname;  BOOL init(char* aCaption,char * aIcon); SDL_Surface *loadImage( char * filename ); void applySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination ); void cleanup(); char *localeToUTF8(char *src); wchar_t* cstringToUnicode(char * aSrc); #endif 
复制代码

  其中引用了windows.h,因为要做C语言字符串和宽字节字符的转换要用到其中函数。C语言本身没有BOOl类型,所以用typedef定义了自己的布尔类型,并且声明了布尔常量TRUE和FALSE。

  下面我们从主函数说起,在第10行和12行我们看到了一种新的数据类型wcha_t,其实这是C99新加的一种宽字符类型,C语言char类型用一个字节表示一个ANSI字符,但汉字、日文等文字无法表示,所以引入了wchar_t,wchar_t用两个字节表示一个字符,所以它可以表示绝大多数字符,无论是那种语言,unicode字符是wchar_t一种实现,在C语言中,unicode字符串一般来说都是wchar_t类型。TTF库中提供了unicode字符串显示和UTF8字符串显示,要显示中文必须是这两种串才能显示。

  第14行init函数完成系统初始化,包括初始化SDL、建立主窗口、初始化TTF库,设置程序标题、图标。其代码如下:

复制代码
 BOOL init(char* aCaption,char * aIcon) { //初始化 SDL if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) { return FALSE; } //载入程序图标 SDL_WM_SetIcon(SDL_LoadBMP(aIcon), NULL); //初始化窗口 gpScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE||SDL_HWSURFACE ); if( gpScreen == NULL )//检测是否初始化成功 { return FALSE; } atexit(cleanup); //初始化字体库 if( TTF_Init() == -1 ) return FALSE; //设置窗口名字和图标 SDL_WM_SetCaption(localeToUTF8(aCaption), NULL ); return TRUE; } 
复制代码

  注意要设置程序图标,必须在建立主窗口前调用SDL_WM_SetIcon(SDL_LoadBMP(aIcon), NULL);来设置图标,图标必须是32*32的bmp图片,因为TTF库不是SDL自己的,所以必须调用TTF_Init()单独初始化;最后设置程序标题,注意标题如果设英文可以直接显示,但如果像我们这个程序这样显示中文,则必须将字符串转换成UTF8的才能显示,所以我们调用了自定义的函数localeToUTF8(aCaption)完成将c语言的字符串转换成UTF8格式的字符串,这个函数定义如下:

复制代码
 char *localeToUTF8(char *src) { static char *buf = NULL; wchar_t *unicode_buf; int nRetLen; if(buf){ free(buf); buf = NULL; } nRetLen = MultiByteToWideChar(CP_ACP,0,src,-1,NULL,0); unicode_buf = (wchar_t*)malloc((nRetLen+1)*sizeof(wchar_t)); MultiByteToWideChar(CP_ACP,0,src,-1,unicode_buf,nRetLen); nRetLen = WideCharToMultiByte(CP_UTF8,0,unicode_buf,-1,NULL,0,NULL,NULL); buf = (char*)malloc(nRetLen+1); WideCharToMultiByte(CP_UTF8,0,unicode_buf,-1,buf,nRetLen,NULL,NULL); free(unicode_buf); return buf; } 
复制代码

  这个函数完成将C语言字符串转换成UTF8格式的字符串。 这样我们就可以设置中文程序标题了。

  在主函数的第20行我们打开了一个字体库,并设置字号为20,关于字号的大小你可以打开word看一下字号的大小。接下来,在33行我们调用TTF_RenderText_Solid将文字渲染成一幅图片,返回图片表面的指针,这个函数只能显示西文,不能显示中文。其原型:

  SDL_Surface *TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg);

  参数:font,打开的字体;text要显示的字符串,C语言格式的字符串(以\0做结束符);fg是文字的颜色,前面我们介绍过SDL_Color结构,这里不再多说。

  除了这种渲染,还有:

  SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg);

  其中font、text和fg与TTF_RenderText_Solid中的一样,bg是文字背景色。

  SDL_Surface *TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg)和TTF_RenderText_Solid参数一样,关于这三种渲染的差别前面已经提过,运行结果页显示了blend效果最好,solid最差,shade可以设置文字背景。

  然后我们把这些表面和显示图片一样显示就可以了,36至40我们调用了自定义函数显示文字:

  void applySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination );

  x、y是文字显示到屏幕上的位置,source是文字表面,destination是目标表面,一般是显示表面。

  显示西文比较简单。显示中文稍微麻烦点,如果你把char tmp[]="世界,你好!";显示到屏幕,调用TTF_RenderText_Solid只会显示一堆乱码,因为这个函数只能显示西文,如果要显示中文要调用:  

显示UTF8字符串 SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font, const char *text, SDL_Color fg);
SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg);
SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font, const char *text, SDL_Color fg);
显示unicode字符串 SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text, SDL_Color fg) ;
SDL_Surface *TTF_RenderUNICODE_Shaded(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg) ;
SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text, SDL_Color fg) ;

   UTF8编码请查:http://baike.baidu.com/view/25412.htm;UNICODE编码请查:http://baike.baidu.com/view/40801.htm

  这些函数的参数和前面差不多,唯一不同是要求text必须是UTF8或unicode格式的。那么如何将C语言字符串转换成UTF8字符串或unicode字符串呢,前面我们使用自定义的函数char *localeToUTF8(char *src)将c字符串转换为UTF8字符串返回,将c字符串转换成unicode字符串,我们自定义了函数:

复制代码
 wchar_t* cstringToUnicode(char * aSrc) { int size; wchar_t *unicodestr = NULL; if(!aSrc) { return NULL; } size=MultiByteToWideChar(CP_ACP,0,aSrc,-1,NULL,0); unicodestr= malloc((size+1)*sizeof(wchar_t)); MultiByteToWideChar(CP_ACP,0,aSrc,-1,unicodestr,size); return unicodestr; } 
复制代码

  这个函数完成将c语言字符串转换成unicode字符串返回,使用这两个函数要注意,在函数中我们动态分配了内存来保存UTF8或unicode

SDL2.0--绘制文字

使用SDL2_ttf绘制文字- 先下载sdl2_ttf的库,关于如何使用这个库的很多,我只是在说绘制的流程,及那一点的小思想 - 绘制过程:渲染视频------------>渲染文字 - 注意:SDL...
  • scylhy
  • scylhy
  • 2016年07月08日 11:01
  • 1486

SDL显示图像和文字

这两天在做一个视频分析软件需要用到SDL显示图像及文字,将阶段成果做一下总结: SDL本身并没有实际文字的功能,需要用到其扩展库SDL_ttf,下载地址: http://www.libsdl....
  • skywalker_leo
  • skywalker_leo
  • 2015年01月16日 14:20
  • 5488

在SDL工程中让SDL_ttf渲染汉字

有时候在关于SDL的博文中看到一些评论,说SDL对中文的支持不佳,因为当程序涉及中文时总是输出乱码。 照我个人观点,这里面很多都是误解。下面就根据我在windows下使用SDL的情况,说说我的观点。 ...
  • mao0514
  • mao0514
  • 2014年12月29日 17:48
  • 1275

移植SDL到JZ2440显示BMP图片

写这类教程的目的是, 熟悉Linux基本操作和嵌入式开发流程, 希望对你有所帮助.   前面我们讲过系统起来后开机LOGO的制作, 韦老师第3期讲了如何显示jpeg图片, 那么怎么显示bm...
  • thisway_diy
  • thisway_diy
  • 2017年06月29日 11:07
  • 474

SDL游戏之路(十八)--文本输入框

 文本输入框 为了方便游戏界面绘制,可以使用一些配置文件来初始化组件的展示。 配置文件定义如下: 按钮: 1 ...
  • ycg01
  • ycg01
  • 2014年01月22日 00:19
  • 1608

SDL显示图像和文字

转自 : http://blog.csdn.net/skywalker_leo/article/details/42776377 这两天在做一个视频分析软件需要用到SDL显示图像及文...
  • xiaoxianerqq
  • xiaoxianerqq
  • 2015年08月19日 19:19
  • 309

SDL移植到ARM-linux下

 SDL移植到ARM-linux上   参考自:bluedrum笔《SDL及扩展库在ARM-Linux 完整移植》 我用的编译环境是ubuntu10.10                ...
  • u012075739
  • u012075739
  • 2014年05月02日 15:48
  • 644

SDL使用SDL_ttf显示文字

搞了一天终于成功显示了,网上找了好多资料都不能正常显示,出现各种异常,最后终于用这种方式搞定了 先看显示效果 备注一下: 两个库的版本分别为SDL1.3.0.0   SDL_ttf-2.0.1...
  • rankun1
  • rankun1
  • 2016年05月13日 11:22
  • 1667

SDL2.0 绘制图像

如何建立SDL风格的Hello World程序。 既然你已经配置好了SDL, 是时候来建立一个能加载并显示一张图片的基本图形程序了。 //将SDL函数和数据类型包含进来#include "SDL/S...
  • sz76211822
  • sz76211822
  • 2017年06月22日 10:20
  • 294

用SDL显示不同的风格文字

v1.0.0   备注:以下代码是在c4droid运行。   #include #include SDL_Window*window=NULL; SDL_Renderer*renderer=NU...
  • qq_38124598
  • qq_38124598
  • 2017年06月22日 20:38
  • 152
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 SDL显示文字
举报原因:
原因补充:

(最多只允许输入30个字)