Before trying to display th texts you need to build SDL3 and SDL3_tff for that you can check the previous tutorial
You can download the latest version of the library here:
You can download the font here: KosugiMaru-Regular.ttf
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)
#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;
}
You can download the full project (for macos): SDL3_DisplayTexts.7z