Glusoft

Display an unicode texts with SDL3

Display unicode texts with SDL3_ttf

Before trying to display th texts you need to build SDL3 and SDL3_tff for that you can check the previous tutorial

Compile SDL3_tff

You can download the latest version of the library here:

Download the font KosugiMaru

You can download the font here: KosugiMaru-Regular.ttf

The CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(SDL3_TextRendering)

# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Find SDL3 and SDL3_ttf
find_package(SDL3 REQUIRED)
find_package(SDL3_ttf REQUIRED)

# Add executable
add_executable(SDL3_TextRendering main.cpp)

# Link SDL3 and SDL3_ttf
target_link_libraries(SDL3_TextRendering PRIVATE SDL3::SDL3 SDL3_ttf::SDL3_ttf)

The main function

#include "SDL3/SDL.h"
#include "SDL3_ttf/SDL_ttf.h"
#include <iostream>

int main(int argc, char* argv[]) {
    // Initialize SDL3
    SDL_Init(SDL_INIT_VIDEO);
    TTF_Init();

    // Create SDL Window
    SDL_Window* window = SDL_CreateWindow("SDL3 Unicode Text", 420, 300, SDL_WINDOW_RESIZABLE);
    if (!window) {
        std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
        return -1;
    }

    // Create Renderer
    SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
    if (!renderer) {
        std::cerr << "Failed to create renderer: " << SDL_GetError() << std::endl;
        SDL_DestroyWindow(window);
        return -1;
    }

    // Load Font
    TTF_Font* font = TTF_OpenFont("KosugiMaru-Regular.ttf", 16);
    if (!font) {
        std::cerr << "Failed to load font: " << SDL_GetError() << std::endl;
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        return -1;
    }

    // Unicode text to render
    std::wstring text = L"申し訳ございませんがたくさんあります。";
    
    // Vector of surfaces
    std::vector<SDL_Surface*> surfaces;
    surfaces.reserve(text.size());

    // Render each character as a surface
    for (size_t i = 0; i < text.size(); i++) {
        SDL_Surface* textSurface = TTF_RenderGlyph_LCD(font, text[i], SDL_Color{255, 255, 255, 255}, SDL_Color{0, 0, 0, 255});
        if (!textSurface) {
            std::cerr << "Failed to create text surface: " << SDL_GetError() << std::endl;
            continue; // Skip if surface creation fails
        }
        surfaces.push_back(textSurface);
    }

    // Calculate total width and max height for the combined surface
    int totalWidth = 0;
    int maxHeight = 0;
    for (auto& surf : surfaces) {
        totalWidth += surf->w + 5; // Add spacing between glyphs
        if (surf->h > maxHeight) {
            maxHeight = surf->h;
        }
    }
    
    SDL_FRect rect{5, 50, static_cast<float>(totalWidth), static_cast<float>(maxHeight)};

    // Create the final combined surface
    SDL_Surface* combinedSurface = SDL_CreateSurface(totalWidth, maxHeight, SDL_PIXELFORMAT_RGBA32);
    if (!combinedSurface) {
        std::cerr << "Failed to create combined surface: " << SDL_GetError() << std::endl;
        return -1;
    }

    // Blit each glyph onto the combined surface
    int xOffset = 0;
    for (auto& surf : surfaces) {
        SDL_Rect destRect = {xOffset, 0, surf->w, surf->h};
        SDL_BlitSurface(surf, NULL, combinedSurface, &destRect);
        xOffset += surf->w + 5; // Move to the next position with spacing
        SDL_DestroySurface(surf); // Free individual surfaces after blitting
    }

    surfaces.clear(); // Clear the vector since we don't need it anymore

    // Convert the combined surface to a texture
    SDL_Texture* combinedTexture = SDL_CreateTextureFromSurface(renderer, combinedSurface);
    SDL_DestroySurface(combinedSurface); // Free the surface after conversion

    // Event loop
    bool running = true;
    SDL_Event event;
    while (running) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_EVENT_QUIT || 
                (event.type == SDL_EVENT_KEY_DOWN && event.key.scancode == SDL_SCANCODE_ESCAPE)) {
                running = false;
            }
        }

        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);

        // Render the combined text texture
        SDL_RenderTexture(renderer, combinedTexture, NULL, &rect);

        SDL_RenderPresent(renderer);
    }

    // Cleanup
    SDL_DestroyTexture(combinedTexture);
    TTF_CloseFont(font);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);

    // Shutdown SDL3 and TTF
    TTF_Quit();
    SDL_Quit();

    return 0;
}

Download the full project

You can download the full project (for macos): SDL3_DisplayTexts.7z