前面教程里,我们只显示图片,没提到如何显示文字, 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,字体文件跟原文件在同一个目录下。  

  1. //打开simfang.ttf 字库,设字体为20号
  2. font = TTF_OpenFont("simhei.ttf",20);
  3. if(font == NULL)
  4. {
  5. fprintf(stderr,"font open failure %s\n",SDL_GetError());
  6. exit(-1);
  7. }

三.将文字转换成表面

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

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

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

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

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

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

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

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

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

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

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

  1. #ifndef FONT_H_2012_05_31
  2. #define FONT_H_2012_05_31
  3. #include "SDL.h"
  4. #include "SDL_image.h"
  5. #include "SDL_ttf.h"
  6. #include <Windows.h>
  7.  
  8. //定义布尔类型
  9. typedef int BOOL;
  10. #define TRUE 1
  11. #define FALSE 0
  12.  
  13. //屏幕分辩率
  14. #define SCREEN_WIDTH 718
  15. #define SCREEN_HEIGHT 419
  16. #define SCREEN_BPP 32
  17.  
  18. //表面声明
  19. extern SDL_Surface *gpBackground; //背景表面
  20. extern SDL_Surface *gpScreen; //显示表面
  21. extern SDL_Surface *gpMessage[3]; //西文文字表面
  22. extern SDL_Surface *gpChinese;//中文文字表面
  23.  
  24. //事件声明
  25. extern SDL_Event myEvent;
  26.  
  27. // 字体声明
  28. extern TTF_Font *font;
  29.  
  30. /*****************************声明常见颜色*****************************************/
  31. extern const SDL_Color RGB_Black;
  32. extern const SDL_Color RGB_Red;
  33. extern const SDL_Color RGB_Green;
  34. extern const SDL_Color RGB_Blue;
  35. extern const SDL_Color RGB_Cyan;
  36. extern const SDL_Color RGB_Magenta;
  37. extern const SDL_Color RGB_Yellow;
  38. extern const SDL_Color RGB_White;
  39. extern const SDL_Color RGB_Gray;
  40. extern const SDL_Color RGB_Grey;
  41. extern const SDL_Color RGB_Maroon ;
  42. extern const SDL_Color RGB_Darkgreen;
  43. extern const SDL_Color RGB_Navy;
  44. extern const SDL_Color RGB_Teal;
  45. extern const SDL_Color RGB_Purple;
  46. extern const SDL_Color RGB_Olive;
  47. extern const SDL_Color RGB_Noname;
  48.  
  49. /*****************************函数声明*****************************************/
  50. BOOL init(char* aCaption,char * aIcon);
  51. SDL_Surface *loadImage( char * filename );
  52. void applySurface( int x, int y, SDL_Surface* source, SDL_Surface* destination );
  53. void cleanup();
  54. char *localeToUTF8(char *src);
  55. wchar_t* cstringToUnicode(char * aSrc);
  56.  
  57. #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库,设置程序标题、图标。其代码如下:

  1. /*
  2. 函数名:init
  3. 函数功能:完成系统初始化工作
  4. 函数参数:aCaption程序标题栏显示名称,c语言字符串
  5. aIcon 程序图标,必须为32*32bmp图片
  6. 函数返回值:无
  7. */
  8. BOOL init(char* aCaption,char * aIcon)
  9. {
  10. //初始化 SDL
  11. if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
  12. {
  13. return FALSE;
  14. }
  15.  
  16. //载入程序图标
  17. SDL_WM_SetIcon(SDL_LoadBMP(aIcon), NULL);
  18.  
  19. //初始化窗口
  20. gpScreen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE||SDL_HWSURFACE );
  21. if( gpScreen == NULL )//检测是否初始化成功
  22. {
  23. return FALSE;
  24. }
  25. atexit(cleanup);
  26.  
  27. //初始化字体库
  28. if( TTF_Init() == -1 )
  29. return FALSE;
  30.  
  31. //设置窗口名字和图标
  32. SDL_WM_SetCaption(localeToUTF8(aCaption), NULL );
  33. return TRUE;
  34. }

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

  1. /*--------------------------------------------------------------------
  2. 函数名: localeToUTF8
  3. 参 数: char *src C语言字符串
  4. 返回值: char * UTF8字符串
  5. 功 能: 将C语言字符串转换成UTF8字符串
  6. 备 注:
  7. ----------------------------------------------------------------------*/
  8. char *localeToUTF8(char *src)
  9. {
  10. static char *buf = NULL;
  11. wchar_t *unicode_buf;
  12. int nRetLen;
  13.  
  14. if(buf){
  15. free(buf);
  16. buf = NULL;
  17. }
  18. nRetLen = MultiByteToWideChar(CP_ACP,0,src,-1,NULL,0);
  19. unicode_buf = (wchar_t*)malloc((nRetLen+1)*sizeof(wchar_t));
  20. MultiByteToWideChar(CP_ACP,0,src,-1,unicode_buf,nRetLen);
  21. nRetLen = WideCharToMultiByte(CP_UTF8,0,unicode_buf,-1,NULL,0,NULL,NULL);
  22. buf = (char*)malloc(nRetLen+1);
  23. WideCharToMultiByte(CP_UTF8,0,unicode_buf,-1,buf,nRetLen,NULL,NULL);
  24. free(unicode_buf);
  25. return buf;
  26. }

  这个函数完成将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字符串,我们自定义了函数:

  1. /*--------------------------------------------------------------------
  2. 函数名: cstringToUnicode
  3. 参 数: char *src C语言字符串
  4. 返回值: wchar_t * Unicode字符串
  5. 功 能: 将c语言字符串转换成unicode字符串
  6. 备 注:
  7. ----------------------------------------------------------------------*/
  8. wchar_t* cstringToUnicode(char * aSrc)
  9. {
  10. int size;
  11. wchar_t *unicodestr = NULL;
  12. if(!aSrc)
  13. {
  14. return NULL;
  15. }
  16. size=MultiByteToWideChar(CP_ACP,0,aSrc,-1,NULL,0);
  17. unicodestr= malloc((size+1)*sizeof(wchar_t));
  18. MultiByteToWideChar(CP_ACP,0,aSrc,-1,unicodestr,size);
  19. return unicodestr;
  20. }

  这个函数完成将c语言字符串转换成unicode字符串返回,使用这两个函数要注意,在函数中我们动态分配了内存来保存UTF8或unicode字符串,然后将其返回,所以我们在调用函数中显示完后必须释放这些字符串所占空间。主函数第43行我们将tmp串转换成unicode串返回给p,然后显示,在54行释放了p。

  在第57行我们关闭了前面打开的字体,因为下面我们将用大一点字体显示,如果要显示中文,其实最简单的办法是在程序里直接定义wchar_t类型数组保存unicode字符串,然后可以直接显示这个字符串,在第12行我们定义了wchar_t msg[] =L"圣    旨";unicode的字符串,注意unicode字符串必须以L开头,否则就是C语言的字符串了。在第66-69行我们直接将其显示到屏幕了。你也可以显示unicode常量串,第71-78行我们分别显示了两个unicode常量串。

  在这里我们只讨论了windows平台下中文显示问题,如果在linux下会有所不同,具体的你可以查询linux平台相关资料。如果你想要例子的源代码,请点击这儿。代码中的字体文件太大,删除了,你可以从windows下的fonts目录下copy一个中文ttf文件到源文件目录就可以了。

SDL显示文字的更多相关文章

  1. SDL 显示汉字

    #include "stdafx.h" #pragma comment(lib,"SDL.lib") #pragma comment(lib,"SDL ...

  2. (原)多线程sdl_ttf显示文字

    最近在使用sdl做视频显示,因为需要显示文字,所以就找了sdl的拓展库,sdl_ttf来做文字显示. 这里说明一下:sdl_ttf不支持多线程,官方上面有说明,它不是多线程安全的. 所以当我最初使用s ...

  3. 实现password框中显示文字提示的方式

    其实实际上实现中并不能让password中显示文字提示,但是我们在工作中有这样的需求,当没输入东西的时候,框内有提示输入密码,但是当输入东西的时候又显示的是*号,那么是如何实现的呢?其实原理很简单,就 ...

  4. Android 使用Font Awesome 显示文字图标

    Android 使用Font Awesome 显示文字图标 简单几步就可以完成 简单的效果图: 1. 创建 assets 文件夹 在Android Studio 上的创建步骤为: 在 src/main ...

  5. 根据html容器大小和显示文字多少调节字体大小

    在做html相关的东西的时候经常会遇到这样的问题,容器大小(长x宽)固定,容器包含内容(特指文字)多少不固定,这个时候就让人很苦恼了,将字体大小设置成多少才合适呢?下面看看我的解决思路: 首先要知道网 ...

  6. Qt中在图片上叠加显示文字

    Qt中在图片上叠加显示文字   QCustLabel::QCustLabel(QWidget *parent):QLabel(parent){ setPixmap(QPixmap(QString::f ...

  7. 动态更新Toolbar Menu以及Menu中同时显示文字和图标

    动态更新Toolbar Menu以及Menu中同时显示文字和图标 我们经常会有这样的需求,在切换Fragment或者点击某个按钮后动态更新Toolbar上Menu项.但是onCreateOptions ...

  8. 解决TextView在显示文字的时候,一行还没显示满就跳到下一行

    转载请注明:转自 http://blog.csdn.NET/u011176685/article/details/48295185 一.问题描述: Android的TextView在显示文字的时候,如 ...

  9. ActionBar只显示图标不显示文字

    问题:ActionBar菜单项android:showAsAction设置为android:showAsAction="always|withText"或者android:show ...

随机推荐

  1. 1.C和C++区别,以及const分析

    从本章起开始从0学习C++,本章主要内容: 1)C和C++的基本区别 2)C和C++的const区别 1.C++和C区别 1.1 C++更强调语言的实用性,所有变量都可以在需要时再定义 比如: ;i& ...

  2. 给你的jQuery项目赋予Router技能吧

    现在你不会React/Vue都不好意思说自己是前端,不过我相信很多前端项目还是基于jquery类库的传统模式的,假如你有追求的态度使用过requireJs这个库,你一定思考过一个问题,或者说一种组件化 ...

  3. BZOJ 4276: [ONTAK2015]Bajtman i Okrągły Robin [线段树优化建边]

    4276: [ONTAK2015]Bajtman i Okrągły Robin 题意:\(n \le 5000\)个区间\(l,r\le 5000\),每个区间可以选一个点得到val[i]的价值,每 ...

  4. vuex学习笔记

    一.vuex的目的 把组件的共享状态抽取出来,以一个全局单例模式管理.在这种模式下,组件树构成了一个巨大的视图,不管在树的哪个位置,任何组件都能获取状态或触发行为. 二.vuex集中式管理数据 安装 ...

  5. Markdown 安装图解(破解汉化教程)

    http://blog.csdn.net/taokai_110/article/details/72934818 终于解决了问题

  6. 运行自己的 DaemonSet - 每天5分钟玩转 Docker 容器技术(131)

    本节以 Prometheus Node Exporter 为例演示如何运行自己的 DaemonSet. Prometheus 是流行的系统监控方案,Node Exporter 是 Prometheus ...

  7. 通过SVG与CSS3实现向上图标

    需求 H5活动页需要用的图标很少,暂时没有使用iconfont的必要性,而通过图片的话额外增加UI的工作量以及增加请求数,前端也有很多实现简单图标的方法,所以就尝试自己去解决,写一个"返回顶 ...

  8. 浅学vue

    因之前项目接触了vue,从此我被迷住,简洁而不失优雅,小巧而不乏大匠. 首先我们要了解vue,什么是vue,正如官网所说:Vue.js 是一套构建用户界面的渐进式框架,Vue 的核心库只关注视图层.V ...

  9. MAC下secretCRT使用技巧(转)

    1.打开secureCRT,按alt+b,可以调出快速启动栏,我相信secureCRT的忠实用户,都会保存一堆的sessions.2.按ctrl,可以同时选中多个session,再点击连接,可快速连接 ...

  10. ps调整文字平滑

    1. 选中文字 2. 调整字体样式,选择"平滑"