zoukankan      html  css  js  c++  java
  • SDL显示文字

      前面教程里,我们只显示图片,没提到如何显示文字, 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 <stdio.h>
     2 #include <stdlib.h>
     3 #include <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 <Windows.h>
    
    //定义布尔类型
    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库,设置程序标题、图标。其代码如下:

    /*
     函数名:init
     函数功能:完成系统初始化工作
     函数参数:aCaption程序标题栏显示名称,c语言字符串
               aIcon 程序图标,必须为32*32bmp图片
     函数返回值:无
    */
    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格式的字符串,这个函数定义如下:

    /*--------------------------------------------------------------------
        函数名:    localeToUTF8
        参  数:    char *src  C语言字符串
        返回值: char * UTF8字符串
        功  能:    将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字符串,我们自定义了函数:

    /*--------------------------------------------------------------------
        函数名:    cstringToUnicode
        参  数:    char *src  C语言字符串
        返回值: wchar_t * Unicode字符串
        功  能:    将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字符串,然后将其返回,所以我们在调用函数中显示完后必须释放这些字符串所占空间。主函数第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文件到源文件目录就可以了。

  • 相关阅读:
    Universal-image-loader Mason 修复版(ImageLoader Image can't be decoded)
    118、通过solid来定义不同边框的颜色,可以只定义一个边框的颜色
    Freeline的快速集成(转载)
    SQL存储过程解密
    Bootstrap
    PHP5.6.15连接Sql Server 2008配置方案
    php使用saop简单例子和注意事项
    php使用mysql和mysqli连接查询数据
    MYSQL中UNIX时间戳与日期的转换
    xp和win7安装telnet服务
  • 原文地址:https://www.cnblogs.com/landmark/p/2526140.html
Copyright © 2011-2022 走看看