前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(译)SDL编程入门(16)TrueType字体

(译)SDL编程入门(16)TrueType字体

作者头像
arcticfox
发布2020-10-29 10:13:48
9030
发布2020-10-29 10:13:48
举报

TrueType字体

使用SDL渲染文本的一种方法是使用扩展库SDL_ttf。SDL_ttf允许你从TrueType字体中创建图像,我们将在这里使用它从字体文本中创建纹理。

代码语言:javascript
复制
// 使用SDL、SDL_image、SDL_ttf、标准IO、math和string
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <stdio.h>
#include <string>
#include <cmath>

要使用 SDL_ttf,你必须设置 SDL_ttf 扩展库[1],就像你 设置 SDL_image一样。就像之前一样,只是把头文件、库文件和二进制文件放在正确的位置,并把编译器配置成使用它们。

代码语言:javascript
复制
//Texture wrapper class
class LTexture
{
    public:
        //Initializes variables
        LTexture();

        //Deallocates memory
        ~LTexture();

        //Loads image at specified path
        bool loadFromFile( std::string path );
        
        //Creates image from font string
        bool loadFromRenderedText( std::string textureText, SDL_Color textColor );

        //Deallocates texture
        void free();

        //Set color modulation
        void setColor( Uint8 red, Uint8 green, Uint8 blue );

        //Set blending
        void setBlendMode( SDL_BlendMode blending );

        //Set alpha modulation
        void setAlpha( Uint8 alpha );
        
        //Renders texture at given point
        void render( int x, int y, SDL_Rect* clip = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );

        //Gets image dimensions
        int getWidth();
        int getHeight();

    private:
        //The actual hardware texture
        SDL_Texture* mTexture;

        //Image dimensions
        int mWidth;
        int mHeight;
};

在这里,我们在texture class中添加了另一个函数,叫做loadFromRenderedText。SDL_ttf的工作方式是从字体和颜色中创建一个新的图像。对于我们的纹理类来说,这意味着我们将从SDL_ttf渲染文本而不是从文件中加载图像。

代码语言:javascript
复制
//我们要渲染的窗口
SDL_Window* gWindow = NULL;

//窗口渲染器
SDL_Renderer* gRenderer = NULL;

//全局通用的字体
TTF_Font *gFont = NULL;

//渲染纹理
LTexture gTextTexture;

在本教程和未来的教程中,我们将使用全局字体进行文本渲染。在SDL_ttf中,字体的数据类型是TTF_Font。

我们还有一个纹理,它将由字体生成。

代码语言:javascript
复制
bool LTexture::loadFromRenderedText( std::string textureText, SDL_Color textColor ){
    //释放已有的纹理
    free();

    //渲染文本表面
    SDL_Surface* textSurface = TTF_RenderText_Solid( gFont, textureText.c_str(), textColor );
    if( textSurface == NULL ){
        printf( "Unable to render text surface! SDL_ttf Error: %s\n", TTF_GetError() );
    }else{
        //从表面像素创建纹理
        mTexture = SDL_CreateTextureFromSurface( gRenderer, textSurface );
        if( mTexture == NULL ){
            printf( "Unable to create texture from rendered text! SDL Error: %s\n", SDL_GetError() );
        }else{
            //Get image dimensions
            mWidth = textSurface->w;
            mHeight = textSurface->h;
        }

        //释放旧表面
        SDL_FreeSurface( textSurface );
    }
    
    //Return success
    return mTexture != NULL;
}

这里是我们实际创建文本纹理的地方,我们将从字体中渲染。这个函数接收我们想要渲染的文本字符串和我们想要用来渲染它的颜色。之后,这个函数的工作原理和从文件中加载文字的工作原理差不多,只是这次我们使用的是SDL_ttf创建的SDL_Surface而不是文件。

在释放任何预存在的纹理后,我们使用 TTF_RenderText_Solid[2] 加载一个表面。这将从给定的字体、文本和颜色中创建一个纯色表面。如果表面创建成功,我们将从中创建一个纹理,就像之前从文件中加载表面时一样。在创建纹理后,我们可以像其他纹理一样用它进行渲染。

还有其他方法可以渲染出更平滑或混合的文本。实验一下SDL_ttf文档[3]中概述的不同类型的渲染。Shaded/Blended 渲染可能对不同大小的文本效果更好。

代码语言:javascript
复制
//初始化PNG加载
int imgFlags = IMG_INIT_PNG;
if( !( IMG_Init( imgFlags ) & imgFlags ) ){
    printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
    success = false;
}

//初始化 SDL_ttf
if( TTF_Init() == -1 ){
    printf( "SDL_ttf could not initialize! SDL_ttf Error: %s\n", TTF_GetError() );
    success = false;
}

就像SDL_image一样,我们必须对它进行初始化,否则字体加载和渲染功能将无法正常工作。我们使用TTF_init[4]来启动SDL_ttf。我们可以使用TTF_GetError()来检查错误。

代码语言:javascript
复制
bool loadMedia(){
    //Loading success flag
    bool success = true;

    //Open the font
    gFont = TTF_OpenFont( "16_true_type_fonts/lazy.ttf", 28 );
    if( gFont == NULL ){
        printf( "Failed to load lazy font! SDL_ttf Error: %s\n", TTF_GetError() );
        success = false;
    }else{
        //Render text
        SDL_Color textColor = { 0, 0, 0 };
        if( !gTextTexture.loadFromRenderedText( "The quick brown fox jumps over the lazy dog", textColor ) ){
            printf( "Failed to render text texture!\n" );
            success = false;
        }
    }

    return success;
}

在我们的加载函数中,使用TTF_OpenFont[5]加载字体。这需要字体文件的路径和我们想要渲染的点大小。

如果字体加载成功,我们要使用加载方法加载一个文本纹理。作为一般规则,你要尽量减少渲染文本的次数。只有在需要的时候才重新渲染,由于我们在整个程序中使用的是同一个文本表面,所以我们只想渲染一次。

代码语言:javascript
复制
void close(){
    //Free loaded images
    gTextTexture.free();

    //Free global font
    TTF_CloseFont( gFont );
    gFont = NULL;

    //Destroy window
    SDL_DestroyRenderer( gRenderer );
    SDL_DestroyWindow( gWindow );
    gWindow = NULL;
    gRenderer = NULL;

    //Quit SDL subsystems
    TTF_Quit();
    IMG_Quit();
    SDL_Quit();
}

在我们的清理函数中,希望使用TTF_CloseFont[6]来释放字体。我们还想使用TTF_Quit[7]来退出SDL_ttf库,以完成清理工作。

代码语言:javascript
复制
//While application is running
while( !quit ){
    //Handle events on queue
    while( SDL_PollEvent( &e ) != 0 ){
        //User requests quit
        if( e.type == SDL_QUIT ){
            quit = true;
        }
    }

    //Clear screen
    SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF );
    SDL_RenderClear( gRenderer );

    //Render current frame
    gTextTexture.render( ( SCREEN_WIDTH - gTextTexture.getWidth() ) / 2, ( SCREEN_HEIGHT - gTextTexture.getHeight() ) / 2 );

    //Update screen
    SDL_RenderPresent( gRenderer );
}

正如你所看到的,在我们渲染了文本纹理之后,我们可以像其他纹理一样渲染它。

这里[8]下载本教程的媒体和源代码。

原文链接[9]

参考资料

[1]

SDL_ttf 扩展库: http://www.libsdl.org/projects/SDL_ttf/

[2]

TTF_RenderText_Solid: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_43.html

[3]

SDL_ttf文档: http://www.libsdl.org/projects/docs/SDL_ttf/SDL_ttf_35.html

[4]

TTF_init: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_8.html

[5]

TTF_OpenFont: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_14.html

[6]

TTF_CloseFont: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_18.html

[7]

TTF_Quit: http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_10.html

[8]

这里: http://www.lazyfoo.net/tutorials/SDL/16_true_type_fonts/16_true_type_fonts.zip

[9]

原文链接: http://www.lazyfoo.net/tutorials/SDL/16_true_type_fonts/index.php

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程之路从0到1 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TrueType字体
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档