Skip to content

Commit 0e6c291

Browse files
committed
Initial work on the SDL_ttf functions
1 parent 251a245 commit 0e6c291

File tree

12 files changed

+655
-8
lines changed

12 files changed

+655
-8
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ include erlang.mk
2828

2929
CFLAGS += $(shell sdl2-config --cflags)
3030
# @todo -undefined dynamic_lookup on OSX?
31-
LDLIBS += $(SDL2_LIBS) -lSDL2_image
31+
LDLIBS += $(SDL2_LIBS) -lSDL2_image -lSDL2_ttf
3232

3333
check:: cppcheck scan-build
3434

README.asciidoc

+59-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22

33
SDL2 Erlang NIF.
44

5-
The following sections list the state of the implementation
6-
as of SDL 2.0.7. The implementation is cut into sections
7-
corresponding to the public headers.
5+
This project tries to implement SDL2 and some of its
6+
extensions in one convenient NIF. The supported versions
7+
and features are listed below.
8+
9+
* SDL 2.0.7
10+
* SDL_ttf 2.0.14
11+
12+
The implementation is cut into sections corresponding
13+
to the public headers.
814

915
== Fully implemented
1016

@@ -80,6 +86,53 @@ corresponding to the public headers.
8086
** `SDL_RenderReadPixels` (renderer)
8187
* 'SDL_stdinc.h': Erlang does not come with the functions `copysign` and `scalbn`.
8288
* 'SDL_surface.h': Only surface creation (via `IMG_Load`) and destruction is implemented. Might be better to move IMG_* functions in their own space.
89+
** Everything in this header can be implemented as simple functions (as opposed to cast/call).
90+
** We'll need to add functions to retrieve the pixel format and possibly pitch (though format+dimensions is enough to get it).
91+
** We'll need to add extra functions for direct access to the pixels.
92+
* 'SDL_ttf.h':
93+
** A function to obtain the SDL_ttf version could be useful
94+
** `TTF_Linked_Version` (if it makes sense, depends on how the library is loaded)
95+
** `TTF_ByteSwappedUNICODE`
96+
** `TTF_OpenFontIndex`
97+
** `TTF_OpenFontRW`
98+
** `TTF_OpenFontIndexRW`
99+
** `TTF_GetFontStyle`
100+
** `TTF_SetFontStyle`
101+
** `TTF_GetFontOutline`
102+
** `TTF_SetFontOutline`
103+
** `TTF_GetFontHinting`
104+
** `TTF_SetFontHinting`
105+
** `TTF_FontHeight`
106+
** `TTF_FontAscent`
107+
** `TTF_FontDescent`
108+
** `TTF_FontLineSkip`
109+
** `TTF_GetFontKerning`
110+
** `TTF_SetFontKerning`
111+
** `TTF_FontFaces`
112+
** `TTF_FontFaceIsFixedWidth`
113+
** `TTF_FontFaceFamilyName`
114+
** `TTF_FontFaceStyleName`
115+
** `TTF_GlyphIsProvided`
116+
** `TTF_GlyphMetrics`
117+
** `TTF_SizeText`
118+
** `TTF_SizeUTF8`
119+
** `TTF_SizeUNICODE`
120+
** `TTF_RenderText_Solid`
121+
** `TTF_RenderUNICODE_Solid`
122+
** `TTF_RenderGlyph_Solid`
123+
** `TTF_RenderText_Shaded`
124+
** `TTF_RenderUTF8_Shaded`
125+
** `TTF_RenderUNICODE_Shaded`
126+
** `TTF_RenderGlyph_Shaded`
127+
** `TTF_RenderText_Blended`
128+
** `TTF_RenderUTF8_Blended`
129+
** `TTF_RenderUNICODE_Blended`
130+
** `TTF_RenderText_Blended_Wrapped`
131+
** `TTF_RenderUTF8_Blended_Wrapped`
132+
** `TTF_RenderUNICODE_Blended_Wrapped`
133+
** `TTF_RenderGlyph_Blended`
134+
** `TTF_CloseFont`
135+
** `TTF_GetFontKerningSizeGlyphs`
83136
* 'SDL_version.h': `SDL_GetRevisionNumber` must be implemented. The macros may also be useful.
84137
* 'SDL_video.h': The following elements are missing:
85138
** `SDL_WINDOWPOS_*` values for different displays
@@ -103,9 +156,9 @@ corresponding to the public headers.
103156
* 'SDL_timer.h' (unclear if we need it)
104157
* 'SDL_touch.h'
105158

106-
SDL extensions also need to be investigated and implemented.
107-
We definitely want at least some of SDL_image, SDL_mixer
108-
and SDL_ttf. We probably do not need SDL_net or SDL_rtf.
159+
Other SDL extensions need to be investigated and implemented.
160+
We definitely want at least some of SDL_image and SDL_mixer.
161+
We probably do not need SDL_net or SDL_rtf.
109162

110163
== OpenGL and Vulkan
111164

c_src/esdl2.h

+16
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
#define __ESDL2_H__
1717

1818
#include "SDL.h"
19+
#include "SDL_ttf.h"
1920

2021
// List of atoms used by this NIF.
2122

2223
#define NIF_ATOMS(A) \
24+
A(a) \
2325
A(abgr1555) \
2426
A(abgr32) \
2527
A(abgr4444) \
@@ -43,6 +45,7 @@
4345
A(audio) \
4446
A(audio_device_added) \
4547
A(audio_device_removed) \
48+
A(b) \
4649
A(bgr24) \
4750
A(bgr555) \
4851
A(bgr565) \
@@ -105,6 +108,7 @@
105108
A(format) \
106109
A(fullscreen) \
107110
A(fullscreen_desktop) \
111+
A(g) \
108112
A(game_controller) \
109113
A(get) \
110114
A(h) \
@@ -179,6 +183,7 @@
179183
A(present_vsync) \
180184
A(pressed) \
181185
A(quit) \
186+
A(r) \
182187
A(refresh_rate) \
183188
A(released) \
184189
A(render_device_reset) \
@@ -263,9 +268,12 @@
263268

264269
// List of resources used by this NIF.
265270

271+
#define SDL_Font TTF_Font
272+
266273
#define NIF_RES_TYPE(r) SDL_ ## r
267274
#define NIF_RESOURCES(R) \
268275
R(Cursor) \
276+
R(Font) \
269277
R(GLContext) \
270278
R(Renderer) \
271279
R(Surface) \
@@ -405,6 +413,7 @@
405413
/* sdl_stdinc */ \
406414
F(get_num_allocations, 0) \
407415
/* sdl_surface */ \
416+
F(get_surface_dimensions, 1) \
408417
F(img_load, 1) \
409418
/* sdl_texture */ \
410419
F(create_texture_from_surface, 2) \
@@ -414,6 +423,12 @@
414423
F(set_texture_alpha_mod, 2) \
415424
F(set_texture_blend_mode, 2) \
416425
F(set_texture_color_mod, 4) \
426+
/* sdl_ttf */ \
427+
F(ttf_init, 0) \
428+
F(ttf_open_font, 2) \
429+
F(ttf_quit, 0) \
430+
F(ttf_render_utf8_solid, 3) \
431+
F(ttf_was_init, 0) \
417432
/* sdl_version */ \
418433
F(get_version, 0) \
419434
F(get_revision, 0) \
@@ -504,6 +519,7 @@ NIF_ENUM_TO_ATOM_FUNCTION_DECL(window_event_to_atom, Uint8)
504519
NIF_LIST_TO_FLAGS_FUNCTION_DECL(keymod_list_to_flags, Uint16)
505520
NIF_FLAGS_TO_LIST_FUNCTION_DECL(keymod_flags_to_list, Uint16)
506521

522+
int map_to_color(ErlNifEnv*, ERL_NIF_TERM, SDL_Color*);
507523
int map_to_point(ErlNifEnv*, ERL_NIF_TERM, SDL_Point*);
508524
ERL_NIF_TERM point_to_map(ErlNifEnv*, const SDL_Point*);
509525
int map_to_rect(ErlNifEnv*, ERL_NIF_TERM, SDL_Rect*);

c_src/sdl_pixels.c

+31
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,34 @@
6060

6161
NIF_ENUM_TO_ATOM_FUNCTION(pixel_format_to_atom, Uint32, PIXEL_FORMAT_ENUM)
6262
NIF_ATOM_TO_ENUM_FUNCTION(atom_to_pixel_format, Uint32, PIXEL_FORMAT_ENUM)
63+
64+
int map_to_color(ErlNifEnv* env, ERL_NIF_TERM map, SDL_Color* color)
65+
{
66+
ERL_NIF_TERM r, g, b, a;
67+
unsigned int ri, gi, bi, ai;
68+
69+
if (!enif_get_map_value(env, map, atom_r, &r))
70+
return 0;
71+
if (!enif_get_map_value(env, map, atom_g, &g))
72+
return 0;
73+
if (!enif_get_map_value(env, map, atom_b, &b))
74+
return 0;
75+
if (!enif_get_map_value(env, map, atom_a, &a))
76+
return 0;
77+
78+
if (!enif_get_uint(env, r, &ri))
79+
return 0;
80+
if (!enif_get_uint(env, g, &gi))
81+
return 0;
82+
if (!enif_get_uint(env, b, &bi))
83+
return 0;
84+
if (!enif_get_uint(env, a, &ai))
85+
return 0;
86+
87+
color->r = ri;
88+
color->g = gi;
89+
color->b = bi;
90+
color->a = ai;
91+
92+
return 1;
93+
}

c_src/sdl_surface.c

+19
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,26 @@ void dtor_Surface(ErlNifEnv* env, void* obj)
2020
SDL_FreeSurface(NIF_RES_GET(Surface, obj));
2121
}
2222

23+
// get_surface_dimensions
24+
25+
NIF_FUNCTION(get_surface_dimensions)
26+
{
27+
void* surface_res;
28+
SDL_Surface* surface;
29+
30+
BADARG_IF(!enif_get_resource(env, argv[0], res_Surface, &surface_res));
31+
surface = NIF_RES_GET(Surface, surface_res);
32+
33+
return enif_make_tuple2(env,
34+
enif_make_int(env, surface->w),
35+
enif_make_int(env, surface->h)
36+
);
37+
}
38+
2339
// img_load
40+
// @todo We should accept file:filename_all() and convert to binary
41+
// before passing it to the NIF. Then we can support UTF-8 paths.
42+
// @todo This function probably doesn't need to be a call.
2443

2544
NIF_CALL_HANDLER(thread_img_load)
2645
{

c_src/sdl_ttf.c

+158
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright (c) 2018, Loïc Hoguin <[email protected]>
2+
//
3+
// Permission to use, copy, modify, and/or distribute this software for any
4+
// purpose with or without fee is hereby granted, provided that the above
5+
// copyright notice and this permission notice appear in all copies.
6+
//
7+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8+
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9+
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10+
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11+
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12+
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13+
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14+
15+
#include "esdl2.h"
16+
17+
// @todo These operations should probably occur in the thread.
18+
void dtor_Font(ErlNifEnv* env, void* obj)
19+
{
20+
TTF_Font* font = NIF_RES_GET(Font, obj);
21+
22+
TTF_CloseFont(font);
23+
}
24+
25+
// ttf_init
26+
27+
NIF_CALL_HANDLER(thread_ttf_init)
28+
{
29+
if (TTF_Init())
30+
return sdl_error_tuple(env);
31+
32+
return atom_ok;
33+
}
34+
35+
NIF_FUNCTION(ttf_init)
36+
{
37+
return nif_thread_call(env, thread_ttf_init, 0);
38+
}
39+
40+
// ttf_openfont
41+
42+
NIF_CALL_HANDLER(thread_ttf_open_font)
43+
{
44+
TTF_Font* font;
45+
obj_Font* res;
46+
ERL_NIF_TERM term;
47+
48+
font = TTF_OpenFont(args[0], (long)args[1]);
49+
50+
enif_free(args[0]);
51+
52+
if (!font)
53+
return sdl_error_tuple(env);
54+
55+
NIF_RES_TO_PTR_AND_TERM(Font, font, res, term);
56+
57+
return enif_make_tuple2(env,
58+
atom_ok,
59+
term
60+
);
61+
}
62+
63+
NIF_FUNCTION(ttf_open_font)
64+
{
65+
ErlNifBinary bin;
66+
char* filename;
67+
int ptsize;
68+
69+
BADARG_IF(!enif_get_int(env, argv[1], &ptsize));
70+
71+
// Getting the filename last to simplify the code due to memory allocation.
72+
73+
BADARG_IF(!enif_inspect_binary(env, argv[0], &bin));
74+
75+
filename = enif_alloc(bin.size + 1);
76+
memcpy(filename, bin.data, bin.size);
77+
filename[bin.size] = '\0';
78+
79+
return nif_thread_call(env, thread_ttf_open_font, 2,
80+
filename, ptsize);
81+
}
82+
83+
// ttf_quit
84+
85+
NIF_CAST_HANDLER(thread_ttf_quit)
86+
{
87+
TTF_Quit();
88+
}
89+
90+
NIF_FUNCTION(ttf_quit)
91+
{
92+
return nif_thread_cast(env, thread_ttf_quit, 0);
93+
}
94+
95+
// ttf_render_utf8_solid
96+
97+
NIF_CALL_HANDLER(thread_ttf_render_utf8_solid)
98+
{
99+
SDL_Surface* surface;
100+
obj_Surface* res;
101+
ERL_NIF_TERM term;
102+
103+
surface = TTF_RenderUTF8_Solid(args[0], args[1], *(SDL_Color*)args[2]);
104+
105+
enif_free(args[1]);
106+
enif_free(args[2]);
107+
108+
if (!surface)
109+
return sdl_error_tuple(env);
110+
111+
NIF_RES_TO_PTR_AND_TERM(Surface, surface, res, term);
112+
113+
return enif_make_tuple2(env,
114+
atom_ok,
115+
term
116+
);
117+
}
118+
119+
NIF_FUNCTION(ttf_render_utf8_solid)
120+
{
121+
void* font_res;
122+
ErlNifBinary bin;
123+
char* text;
124+
SDL_Color* color;
125+
126+
BADARG_IF(!enif_get_resource(env, argv[0], res_Font, &font_res));
127+
BADARG_IF(!enif_inspect_binary(env, argv[1], &bin));
128+
129+
text = enif_alloc(bin.size + 1);
130+
memcpy(text, bin.data, bin.size);
131+
text[bin.size] = '\0';
132+
133+
color = enif_alloc(sizeof(SDL_Color));
134+
if (!map_to_color(env, argv[2], color)) {
135+
enif_free(text);
136+
enif_free(color);
137+
138+
return enif_make_badarg(env);
139+
}
140+
141+
return nif_thread_call(env, thread_ttf_render_utf8_solid, 3,
142+
NIF_RES_GET(Font, font_res), text, color);
143+
}
144+
145+
// ttf_was_init
146+
147+
NIF_CALL_HANDLER(thread_ttf_was_init)
148+
{
149+
if (TTF_WasInit())
150+
return atom_true;
151+
152+
return atom_false;
153+
}
154+
155+
NIF_FUNCTION(ttf_was_init)
156+
{
157+
return nif_thread_call(env, thread_ttf_was_init, 0);
158+
}

0 commit comments

Comments
 (0)