Skip to content

Commit 7279a01

Browse files
authored
Adds SDL3_ttf port (#24601)
1 parent a21d6d9 commit 7279a01

10 files changed

Lines changed: 218 additions & 12 deletions

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ See docs/process.md for more on how version tagging works.
3535
- SDL2 port updated to include stub functions for `SDL_hid_init()` and related
3636
functions. (#26297)
3737
- libpng port updated from 1.6.39 to 1.6.55. (#26388)
38+
- Added sdl3_ttf port. (#24601)
3839

3940
5.0.2 - 02/25/26
4041
----------------

test/browser/test_sdl3_ttf.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2025 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <stdio.h>
9+
#include <SDL3/SDL.h>
10+
#include <SDL3/SDL_main.h>
11+
#include <SDL3_ttf/SDL_ttf.h>
12+
13+
SDL_Window *window;
14+
SDL_Renderer *renderer;
15+
TTF_Font *font;
16+
17+
#define WIDTH 640
18+
#define HEIGHT 480
19+
20+
void render() {
21+
SDL_Color colorA = { 0xff, 0x99, 0x00, 0xff };
22+
SDL_Color colorB = { 0x11, 0xff, 0xff, 0xff };
23+
SDL_FRect upperRect = {0, 0, WIDTH, HEIGHT / 2};
24+
SDL_FRect lowerRect = {0, HEIGHT / 2, WIDTH, HEIGHT / 2};
25+
26+
SDL_Surface *helloSurface = TTF_RenderText_Shaded(font, "hello", 0, colorA, colorB);
27+
SDL_Surface *worldSurface = TTF_RenderText_Shaded(font, "world", 0, colorB, colorA);
28+
SDL_Texture *helloTexture = SDL_CreateTextureFromSurface(renderer, helloSurface);
29+
SDL_Texture *worldTexture = SDL_CreateTextureFromSurface(renderer, worldSurface);
30+
31+
SDL_SetRenderDrawColor(renderer, 0xcc, 0xcc, 0xcc, 0xff);
32+
SDL_RenderClear(renderer);
33+
SDL_RenderTexture(renderer, helloTexture, NULL, &upperRect);
34+
SDL_RenderTexture(renderer, worldTexture, NULL, &lowerRect);
35+
SDL_RenderPresent(renderer);
36+
37+
SDL_DestroySurface(helloSurface);
38+
SDL_DestroySurface(worldSurface);
39+
SDL_DestroyTexture(helloTexture);
40+
SDL_DestroyTexture(worldTexture);
41+
}
42+
43+
int main(int argc, char *argv[]) {
44+
SDL_Init(SDL_INIT_VIDEO);
45+
TTF_Init();
46+
47+
if (!SDL_CreateWindowAndRenderer("SDL3 TTF", WIDTH, HEIGHT, 0, &window, &renderer)) {
48+
printf("SDL_CreateWindowAndRenderer: %s\n", SDL_GetError());
49+
return 1;
50+
}
51+
font = TTF_OpenFont("LiberationSansBold.ttf", 40);
52+
if (!font) {
53+
printf("TTF_OpenFont: %s\n", SDL_GetError());
54+
return 1;
55+
}
56+
render();
57+
58+
return 0;
59+
}

test/browser/test_sdl3_ttf.png

79.4 KB
Loading
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2025 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <stdio.h>
9+
#include <SDL3/SDL.h>
10+
#include <SDL3/SDL_main.h>
11+
#include <SDL3_ttf/SDL_ttf.h>
12+
13+
int main(int argc, char *argv[]) {
14+
int width = 320;
15+
int height = 48;
16+
17+
SDL_Init(SDL_INIT_VIDEO);
18+
SDL_Window *window = SDL_CreateWindow("SDL3 TTF Render Text Solid", width, height, 0);
19+
SDL_Surface *screen = SDL_GetWindowSurface(window);
20+
21+
TTF_Init();
22+
TTF_Font *font = TTF_OpenFont("LiberationSansBold.ttf", 32);
23+
if (!font) {
24+
printf("TTF_OpenFont: %s\n", SDL_GetError());
25+
return 1;
26+
}
27+
28+
SDL_Color color = { 0xff, 0x99, 0x00, 0xff };
29+
SDL_Surface *text = TTF_RenderText_Solid(font, "Play", 0, color);
30+
31+
SDL_FillSurfaceRect(screen, NULL, SDL_MapRGB(SDL_GetPixelFormatDetails(screen->format), NULL, 255, 0, 0));
32+
SDL_BlitSurface(text, NULL, screen, NULL);
33+
SDL_UpdateWindowSurface(window);
34+
35+
return 0;
36+
}
570 Bytes
Loading

test/browser/test_sdl_ttf_render_text_solid.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@
1111

1212
int main()
1313
{
14-
SDL_Init(SDL_INIT_VIDEO);
15-
SDL_Surface *screen = SDL_SetVideoMode(320, 32, 32, SDL_HWSURFACE);
16-
17-
TTF_Init();
18-
TTF_Font *font = TTF_OpenFont("Arial", 32);
19-
20-
SDL_Color color = { 0xff, 0x99, 0x00, 0xff };
21-
SDL_Surface *text = TTF_RenderText_Solid(font, "Play", color);
22-
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 0, 0));
23-
SDL_BlitSurface(text, NULL, screen, NULL);
24-
return 0;
14+
SDL_Init(SDL_INIT_VIDEO);
15+
SDL_Surface *screen = SDL_SetVideoMode(320, 32, 32, SDL_HWSURFACE);
16+
17+
TTF_Init();
18+
TTF_Font *font = TTF_OpenFont("Arial", 32);
19+
20+
SDL_Color color = { 0xff, 0x99, 0x00, 0xff };
21+
SDL_Surface *text = TTF_RenderText_Solid(font, "Play", color);
22+
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 0, 0));
23+
SDL_BlitSurface(text, NULL, screen, NULL);
24+
25+
return 0;
2526
}
26-

test/test_browser.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,14 @@ def test_sdl_canvas_palette_2(self):
21592159
def test_sdl_ttf_render_text_solid(self):
21602160
self.reftest('test_sdl_ttf_render_text_solid.c', cflags=['-O2', '-lSDL', '-lGL'])
21612161

2162+
def test_sdl3_ttf_render_text_solid(self):
2163+
self.cflags.append('-Wno-experimental')
2164+
shutil.copy2(test_file('freetype/LiberationSansBold.ttf'), self.get_dir())
2165+
self.reftest('test_sdl3_ttf_render_text_solid.c', 'test_sdl3_ttf_render_text_solid.png',
2166+
cflags=[
2167+
'-O2', '-sUSE_SDL=3', '-sUSE_SDL_TTF=3', '-lGL',
2168+
'--embed-file', 'LiberationSansBold.ttf'])
2169+
21622170
def test_sdl_alloctext(self):
21632171
self.btest_exit('test_sdl_alloctext.c', cflags=['-lSDL', '-lGL'])
21642172

@@ -3125,6 +3133,12 @@ def test_sdl2_ttf(self):
31253133
copy_asset('freetype/LiberationSansBold.ttf')
31263134
self.reftest('test_sdl2_ttf.c', cflags=['-O2', '-sUSE_SDL=2', '-sUSE_SDL_TTF=2', '--embed-file', 'LiberationSansBold.ttf'])
31273135

3136+
@requires_graphics_hardware
3137+
def test_sdl3_ttf(self):
3138+
shutil.copy2(test_file('freetype/LiberationSansBold.ttf'), self.get_dir())
3139+
self.reftest('test_sdl3_ttf.c', 'test_sdl3_ttf.png',
3140+
cflags=['-O2', '-sUSE_SDL=3', '-sUSE_SDL_TTF=3', '--embed-file', 'LiberationSansBold.ttf'])
3141+
31283142
@requires_graphics_hardware
31293143
def test_sdl2_ttf_rtl(self):
31303144
copy_asset('third_party/notofont/NotoNaskhArabic-Regular.ttf')

test/test_other.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,6 +2691,12 @@ def test_sdl2_ttf(self):
26912691
self.emcc('browser/test_sdl2_ttf.c', args=['-sUSE_SDL=2', '-sUSE_SDL_TTF=2', '-o', 'a.out.js'])
26922692
self.emcc('browser/test_sdl2_ttf.c', args=['--use-port=sdl2', '--use-port=sdl2_ttf', '-o', 'a.out.js'])
26932693

2694+
@requires_network
2695+
def test_sdl3_ttf(self):
2696+
# A compile-only test that checks if sdl3-ttf, and dependencies freetype and harfbuzz, are buildable.
2697+
self.emcc(test_file('browser/test_sdl3_ttf.c'), args=['-sUSE_SDL=3', '-sUSE_SDL_TTF=3'])
2698+
self.emcc(test_file('browser/test_sdl3_ttf.c'), args=['--use-port=sdl3', '--use-port=sdl3_ttf'])
2699+
26942700
@requires_network
26952701
def test_contrib_ports(self):
26962702
# Verify that contrib ports can be used (using the only contrib port available ATM, but can be replaced

test/test_sdl3_ttf.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2025 The Emscripten Authors. All rights reserved.
3+
* Emscripten is available under two separate licenses, the MIT license and the
4+
* University of Illinois/NCSA Open Source License. Both these licenses can be
5+
* found in the LICENSE file.
6+
*/
7+
8+
#include <stdio.h>
9+
#include <SDL3/SDL.h>
10+
#include <SDL3_ttf/SDL_ttf.h>
11+
#include <assert.h>
12+
#include <emscripten.h>
13+
#include <unistd.h>
14+
15+
int main() {
16+
SDL_Init(SDL_INIT_VIDEO);
17+
18+
if (!TTF_Init()) {
19+
printf("TTF_Init: %s\n", SDL_GetError());
20+
return 1;
21+
}
22+
23+
TTF_Quit();
24+
SDL_Quit();
25+
26+
return 0;
27+
}

tools/ports/sdl3_ttf.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Copyright 2025 The Emscripten Authors. All rights reserved.
2+
# Emscripten is available under two separate licenses, the MIT license and the
3+
# University of Illinois/NCSA Open Source License. Both these licenses can be
4+
# found in the LICENSE file.
5+
6+
import os
7+
8+
TAG = 'release-3.2.2'
9+
HASH = 'c5f34d1b79492e0341c91687cde9ec315f5d6544c7ebaa7ef5d092e77ccfc363a0e702ba9c43bfa0926c54420843ccfb98b81362985fd7b4a67d09a7852b90ba'
10+
11+
deps = ['freetype', 'sdl3', 'harfbuzz']
12+
13+
variants = {'sdl3_ttf-mt': {'PTHREADS': 1}}
14+
15+
16+
def needed(settings):
17+
return settings.USE_SDL_TTF == 3
18+
19+
20+
def get_lib_name(settings):
21+
return 'libSDL3_ttf' + ('-mt' if settings.PTHREADS else '') + '.a'
22+
23+
24+
def get(ports, settings, shared):
25+
ports.fetch_project('sdl3_ttf', f'https://github.com/libsdl-org/SDL_ttf/archive/{TAG}.zip', sha512hash=HASH)
26+
27+
def create(final):
28+
src_root = ports.get_dir('sdl3_ttf', 'SDL_ttf-' + TAG)
29+
ports.install_header_dir(os.path.join(src_root, 'include'), target='.')
30+
flags = ['-DTTF_USE_HARFBUZZ=1', '-sUSE_SDL=3', '-sUSE_FREETYPE', '-sUSE_HARFBUZZ']
31+
if settings.PTHREADS:
32+
flags += ['-pthread']
33+
34+
srcs = [
35+
'src/SDL_gpu_textengine.c',
36+
'src/SDL_hashtable.c',
37+
'src/SDL_hashtable_ttf.c',
38+
'src/SDL_renderer_textengine.c',
39+
'src/SDL_surface_textengine.c',
40+
'src/SDL_ttf.c',
41+
]
42+
43+
ports.build_port(src_root, final, 'sdl3_ttf', flags=flags, srcs=srcs)
44+
45+
return [shared.cache.get_lib(get_lib_name(settings), create, what='port')]
46+
47+
48+
def clear(ports, settings, shared):
49+
shared.cache.erase_lib(get_lib_name(settings))
50+
51+
52+
def process_dependencies(settings):
53+
settings.USE_SDL = 3
54+
settings.USE_FREETYPE = 1
55+
settings.USE_HARFBUZZ = 1
56+
57+
58+
def process_args(ports):
59+
return ['-DTTF_USE_HARFBUZZ=1']
60+
61+
62+
def show():
63+
return 'sdl3_ttf (-sUSE_SDL_TTF=3 or --use-port=sdl3_ttf; zlib license)'

0 commit comments

Comments
 (0)