关于SDL混合显示中英文标准字体的方式以及SDL显示可能带来的内存泄露

首先,我们从WIN10系统以下路径中找到字体库:simsun.ttc,他的路径一般为:

C:\Windows\Fonts

文件夹中的宋体,常规即是我们要的内容

 将其拷贝出来,即可作为我们显示时所用的字体库。

SDL显示字体的一般流程为:

首先使用SDL_CreateWindow;以及SDL_CreateRenderer函数分别创建SDL窗口以及窗口对应的渲染器。

1. 使用TTF_OpenFont()函数打开字体库,同时设置字体大小;

2. 根据打开的字体库,要显示的内容以及字体颜色创建文本表面Surface,根据你采用的编码不同使用的函数为:(本文推荐采用UNICODE编码,这意味着字符需要采用16位来表示,这样可以同时显示中英文内容)

TTF_RenderText_Blended(TTF_Font *font,
                const char *text, SDL_Color fg);
TTF_RenderUTF8_Blended(TTF_Font *font,
                const char *text, SDL_Color fg);
TTF_RenderUNICODE_Blended(TTF_Font *font,
                const Uint16 *text, SDL_Color fg);;

3. 根据得到的Surface使用SDL_CreateTextureFromSurface()函数创建纹理Texture;

4. 使用SDL_RenderCopy()函数将文本纹理复制到窗口渲染器,以及使用SDL_RenderPresent(pWndRenderer);   将渲染器内容显示出来;

5. 使用    SDL_DestroyTexture(pTextTexture);  SDL_FreeSurface(pTextSurface);函数释放Surface以及Texture。通常这2个函数的错误使用往往会照成多次显示内容后,内存疯狂泄露,解决办法是:每使用一次TTF_RenderUNICODE_Blended()、SDL_CreateTextureFromSurface()函数,就执行一次对应的释放函数,注意是每一次。

假如你在某个调用函数中多次执行这2个函数,而只在该函数退出前执行了一次对应的内存释放,恭喜你,你的操作将会造成大量的内存泄露,不信你放在while循环里泡个几百遍看看

记住是每使用一次TTF_RenderUNICODE_Blended()、SDL_CreateTextureFromSurface()函数,在退出前就执行一次对应的释放函数,注意是每一次,而不是退出时仅执行一次。

6. 注意事项:如果你要显示出来的字体无失真,不要自己指定显示内容所需要的区域大小,而是指定显示起始位置,使用TTF_SizeUNICODE()函数计算所需要的显示区域,如果需要调整字体大小,请使用TTF_OpenFont()函数更改。这样你的字体才能保证不失真变形。

以下是代码部分:

首先是主函数:

int main()
{


    SDL_Window* pSDLWindow = NULL;  //sdl窗口
    SDL_Renderer* pWndRenderer = NULL;//窗口渲染器

    wchar_t display_word[] = L"H***************你好啊,jackiewmt!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*";

    //初始化SDL  
    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) return -1;

    //创建窗口  
    pSDLWindow = SDL_CreateWindow("SDLWind", 200, 200, 1600, 800, SDL_WINDOW_RESIZABLE);
    if (NULL == pSDLWindow) return -1;

    //创建窗口渲染器
    pWndRenderer = SDL_CreateRenderer(pSDLWindow, -1, 0);
    
    sdl_OutWord(pSDLWindow, pWndRenderer,display_word);


    SDL_Event sdl_event;
    bool bQuit = false;
    while (!bQuit)
    {
        
        if (SDL_PollEvent(&sdl_event))
        {
            switch (sdl_event.type)
            {
            case SDL_QUIT:
                bQuit = true;
                break;
            case SDL_WINDOWEVENT:
            {
                if (sdl_event.window.event == SDL_WINDOWEVENT_RESIZED)
                {    
                    SDL_DestroyRenderer(pWndRenderer);
                    pWndRenderer = SDL_CreateRenderer(pSDLWindow, -1, 0);
                    //创建窗口渲染器
                    sdl_OutWord(pSDLWindow, pWndRenderer, display_word);

                    printf("一次  ");
                    break;
                }
                else
                    break;
            }
            default:
                break;
            }
        }
    }
    SDL_DestroyRenderer(pWndRenderer);
    SDL_DestroyWindow(pSDLWindow);

}

然后是调用函数部分:

void sdl_OutWord(SDL_Window* pSDLWindow, SDL_Renderer* pWndRenderer, wchar_t* display_word)
{
    
    
    SDL_Surface * pTextSurface = NULL;//文本表面
    SDL_Texture* pTextTexture = NULL;//文本纹理

    int Font_size = 32;

    //文本显示区域
    SDL_Rect rcText;
    rcText.x = 0;
    rcText.y = 0;
    rcText.w = 0;
    rcText.h = 0;

    //设置窗口背景色
    SDL_SetRenderDrawColor(pWndRenderer, 120, 120, 120, 255);
    //用设置的颜色清屏窗口渲染器
    SDL_RenderClear(pWndRenderer);


    //初始化字体库
    if (TTF_Init() == -1)
        return;
    //打开字体
    TTF_Font *font;
    font = TTF_OpenFont("data/simsun.ttc", Font_size);
    if (!font)
    {
        printf("TTF_OpenFont: Open simsun.ttf %s\n", TTF_GetError());
        return;
    }
    
    TTF_SizeUNICODE(font, (const Uint16 *)display_word, &rcText.w, &rcText.h);//计算所需要的显示区域大小

    //创建文本表面
    SDL_Color color2 = { 255,255,255 };
    pTextSurface = TTF_RenderUNICODE_Blended(font, (Uint16*)display_word, color2);   

    //创建文本纹理
    pTextTexture = SDL_CreateTextureFromSurface(pWndRenderer, pTextSurface);

    //将文本纹理复制到窗口渲染器
    SDL_RenderCopy(pWndRenderer, pTextTexture, NULL, &rcText);  // NULL means that use all texture( and renderer)  
    
    //刷新窗口渲染器的显示
    SDL_RenderPresent(pWndRenderer);


    //清理  
    TTF_CloseFont(font);
    TTF_Quit();
    SDL_RenderClear(pWndRenderer);
    SDL_DestroyTexture(pTextTexture);
    SDL_FreeSurface(pTextSurface);
    return ;
    }
显示效果如下:

当然,这个函数也有弊端,那就是当你缩小显示区域的时候,会发现显示部分超出了显示框,像下面这样:

 所以也可以稍作更改,将显示内容做到自动换行,具体效果如下:

至于具体实现,下次有空了再发吧。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Ubuntu上使用SDL显示图片,你需要进行以下步骤: 1. 安装SDL库:首先,确保你已经安装了SDL库。可以使用以下命令在Ubuntu上安装: ``` sudo apt-get install libsdl2-dev ``` 2. 初始化SDL:在你的代码中,首先需要初始化SDL。你可以在程序的开始处调用`SDL_Init`函数来初始化SDL。例如: ```c if (SDL_Init(SDL_INIT_VIDEO) != 0) { printf("SDL initialization failed: %s\n", SDL_GetError()); return 1; } ``` 3. 创建窗口和渲染器:在初始化SDL后,你需要创建一个窗口和一个渲染器来显示图片。你可以使用`SDL_CreateWindow`函数创建一个窗口,并使用`SDL_CreateRenderer`函数创建一个渲染器。例如: ```c SDL_Window* window = SDL_CreateWindow("Image Display", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 800, 600, SDL_WINDOW_SHOWN); if (window == NULL) { printf("Window creation failed: %s\n", SDL_GetError()); return 1; } SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); if (renderer == NULL) { printf("Renderer creation failed: %s\n", SDL_GetError()); return 1; } ``` 4. 加载图片并创建纹理:使用SDL_image库加载图片,并将其转换为纹理以供渲染。你需要安装SDL_image库,并在代码中包含相应的头文件。例如,加载一张名为"image.png"的图片并创建纹理: ```c #include <SDL2/SDL_image.h> SDL_Surface* surface = IMG_Load("image.png"); if (surface == NULL) { printf("Image loading failed: %s\n", IMG_GetError()); return 1; } SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_FreeSurface(surface); if (texture == NULL) { printf("Texture creation failed: %s\n", SDL_GetError()); return 1; } ``` 5. 渲染纹理:最后,你可以在主循环中使用`SDL_RenderCopy`函数将纹理渲染到窗口上。例如,将纹理渲染到整个窗口: ```c SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); ``` 6. 释放资源:在程序结束时,记得释放已分配的资源。例如,释放纹理、渲染器和窗口: ```c SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); ``` 这就是在Ubuntu上使用SDL显示图片的基本步骤。你可以根据自己的需求进行更多的操作和调整。如果你有其他问题,请提供更多的细节,我将尽力帮助你解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值