使用FreeType和SDL2渲染文本会生成白色方块而不是字符

时间:2018-05-03 01:37:25

标签: c++ sdl freetype

我试图获得一个基本项目来渲染SDL2和FreeType的文本,但它的所有渲染都是白色方块而不是每个角色。我渲染每个glygh并将像素数据转换为SDL_Surface SDL_CreateRGBSurfaceFrom()。我试着搞乱rgb组件的位掩码,像素的深度,甚至是表面的混合模式,但到目前为止还没有这个工作。

以下是相关的代码位。字体在文件的前面正确加载,我在加载字体后设置字体的大小。什么可能导致字符显示为空白方块?

#include <sdl.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H
#include FT_OUTLINE_H

#include <iostream>

/// Forward declaration
void Init();
void DeInit();
void Input();
void Update();
void Draw();

/// Memory
SDL_Window* window;
SDL_Surface* target;
FT_Library ftLib;
FT_Bitmap ftTarget;
FT_Face ftFace;

bool running = true;
int x = 0;
int y = 32;

/// Functions
void DrawBitmap(FT_Bitmap bm, int x, int y);

int main(int argc, char* argv[]) {
    Init();
    while (running) {
        Input();
        Update();
        Draw();
    }
    DeInit();

    return 0;
}

void Init() {
    // Init
    SDL_Init(SDL_INIT_EVERYTHING);
    window = SDL_CreateWindow("FreeType Test", 1920/2-600/2, 1080/2-400/2, 600, 400, 0);
    FT_Init_FreeType(&ftLib);
    FT_New_Face(ftLib, "C:\\Windows\\Fonts\\Arial.ttf", 0, &ftFace);
    FT_Set_Char_Size(ftFace, 12 << 6, 12 << 6, 72, 72);

    // Setup
    target = SDL_GetWindowSurface(window);
}

void DeInit() {
    // DeInit
    FT_Done_Face(ftFace);
    FT_Done_FreeType(ftLib);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

void Input() {
    SDL_Event e;
    while (SDL_PollEvent(&e)) {
        switch (e.type) {
        case SDL_QUIT:
            running = false;
            break;
        }
    }
}

void Update() {
    // nothing for now
}

void Draw() {
    SDL_FillRect(target, nullptr, SDL_MapRGBA(target->format, 128, 128, 0, 255));

    // Draw text
    constexpr char text[] = "This is cool B)";
    for (int n = 0; n < sizeof(text); n++)
    {
        FT_Load_Char(ftFace, text[n], FT_LOAD_RENDER);

        DrawBitmap(ftFace->glyph->bitmap, x + ftFace->glyph->bitmap_left, y - ftFace->glyph->bitmap_top);

        x += ftFace->glyph->advance.x >> 6;
        y += ftFace->glyph->advance.y >> 6;
    }

    x = 0;
    y = 32;

    SDL_UpdateWindowSurface(window);
    SDL_Delay(10);
}

void DrawBitmap(FT_Bitmap bm, int x, int y) {
    SDL_Surface* glyph = SDL_CreateRGBSurfaceFrom(bm.buffer, bm.width, bm.rows, 8, bm.pitch, 0, 0, 0, 0xFF);
    SDL_SetSurfaceBlendMode(glyph, SDL_BlendMode::SDL_BLENDMODE_NONE);
    SDL_Rect dest = { x, y, 0, 0 };
    SDL_BlitSurface(glyph, nullptr, target, &dest);
    SDL_FreeSurface(glyph);
}

1 个答案:

答案 0 :(得分:1)

您可以设置调色板:

void DrawBitmap(FT_Bitmap bm, int x, int y)
{
    if( bm.width == 0 || bm.rows == 0 )
    {
        return;
    }

    std::vector< unsigned char > rgba( bm.width * bm.rows * 4 );
    for( unsigned int y = 0; y < bm.rows; ++y )
    {
        for( unsigned int x = 0; x < bm.width; ++x )
        {
            unsigned char val = bm.buffer[ ( bm.pitch * y ) + x ];
            size_t base = ( ( bm.width * y ) + x ) * 4;
            rgba[ base + 0 ] = 0xFF;
            rgba[ base + 1 ] = 0xFF;
            rgba[ base + 2 ] = 0xFF;
            rgba[ base + 3 ] = val;
        }
    }

    SDL_Surface* glyph = SDL_CreateRGBSurfaceFrom
        (
        &rgba[0],
        bm.width,
        bm.rows,
        32,
        bm.width*4,
        0x000000ff,
        0x0000ff00,
        0x00ff0000,
        0xff000000
        );

    SDL_SetSurfaceBlendMode(glyph, SDL_BlendMode::SDL_BLENDMODE_BLEND);
    SDL_Rect dest = { x, y, 0, 0 };
    SDL_BlitSurface(glyph, nullptr, target, &dest);
    SDL_FreeSurface(glyph);
}

或者自己进行RGBA转换:

public IConfiguration Configuration { get; }