1 /+
2 +            Copyright 2022 – 2024 Aya Partridge
3 +          Copyright 2018 - 2022 Michael D. Parker
4 + Distributed under the Boost Software License, Version 1.0.
5 +     (See accompanying file LICENSE_1_0.txt or copy at
6 +           http://www.boost.org/LICENSE_1_0.txt)
7 +/
8 module sdl_ttf;
9 
10 import bindbc.sdl.config;
11 static if(bindSDLTTF):
12 import bindbc.sdl.codegen;
13 
14 import sdl.error: SDL_GetError, SDL_SetError;
15 import sdl.pixels: SDL_Color;
16 import sdl.rwops: SDL_RWops;
17 import sdl.surface: SDL_Surface;
18 import sdl.stdinc: SDL_bool;
19 
20 enum SDLTTFSupport: SDL_version{
21 	noLibrary   = SDL_version(0,0,0),
22 	badLibrary  = SDL_version(0,0,255),
23 	v2_0_12     = SDL_version(2,0,12),
24 	v2_0_13     = SDL_version(2,0,13),
25 	v2_0_14     = SDL_version(2,0,14),
26 	v2_0_15     = SDL_version(2,0,15),
27 	v2_0_18     = SDL_version(2,0,18),
28 	v2_20       = SDL_version(2,20,0),
29 	v2_22       = SDL_version(2,22,0),
30 	
31 	deprecated("Please use `v2_0_12` instead") sdlTTF2012 = SDL_version(2,0,12),
32 	deprecated("Please use `v2_0_13` instead") sdlTTF2013 = SDL_version(2,0,13),
33 	deprecated("Please use `v2_0_14` instead") sdlTTF2014 = SDL_version(2,0,14),
34 	deprecated("Please use `v2_0_15` instead") sdlTTF2015 = SDL_version(2,0,15),
35 	deprecated("Please use `v2_0_18` instead") sdlTTF2018 = SDL_version(2,0,18),
36 }
37 
38 enum sdlTTFSupport = (){
39 	version(SDL_TTF_2_22)      return SDLTTFSupport.v2_22;
40 	else version(SDL_TTF_2_20) return SDLTTFSupport.v2_20;
41 	else version(SDL_TTF_2018) return SDLTTFSupport.v2_0_18;
42 	else version(SDL_TTF_2015) return SDLTTFSupport.v2_0_15;
43 	else version(SDL_TTF_2014) return SDLTTFSupport.v2_0_14;
44 	else version(SDL_TTF_2013) return SDLTTFSupport.v2_0_13;
45 	else                       return SDLTTFSupport.v2_0_12;
46 }();
47 
48 enum SDL_TTF_MAJOR_VERSION = sdlTTFSupport.major;
49 enum SDL_TTF_MINOR_VERSION = sdlTTFSupport.minor;
50 enum SDL_TTF_PATCHLEVEL    = sdlTTFSupport.patch;
51 
52 pragma(inline, true) void SDL_TTF_VERSION(SDL_version* x) nothrow @nogc pure @safe{
53 	x.major = SDL_TTF_MAJOR_VERSION;
54 	x.minor = SDL_TTF_MINOR_VERSION;
55 	x.patch = SDL_TTF_PATCHLEVEL;
56 }
57 
58 deprecated("Please use `SDL_TTF_MAJOR_VERSION` instead") alias TTF_MAJOR_VERSION = SDL_TTF_MAJOR_VERSION;
59 deprecated("Please use `SDL_TTF_MINOR_VERSION` instead") alias TTF_MINOR_VERSION = SDL_TTF_MINOR_VERSION;
60 deprecated("Please use `SDL_TTF_PATCHLEVEL` instead")    alias TTF_PATCHLEVEL    = SDL_TTF_PATCHLEVEL;
61 deprecated("Please use `SDL_TTF_VERSION` instead")       alias TTF_VERSION       = SDL_TTF_VERSION;
62 
63 bool SDL_TTF_VERSION_ATLEAST(ubyte x, ubyte y, ubyte z){ return SDL_version(SDL_TTF_MAJOR_VERSION, SDL_TTF_MINOR_VERSION, SDL_TTF_PATCHLEVEL) >= SDL_version(x, y, z); }
64 
65 enum{
66 	UNICODE_BOM_NATIVE   = 0xFEFF,
67 	UNICODE_BOM_SWAPPED  = 0xFFFE,
68 }
69 
70 struct TTF_Font;
71 
72 enum{
73 	TTF_STYLE_NORMAL         = 0x00,
74 	TTF_STYLE_BOLD           = 0x01,
75 	TTF_STYLE_ITALIC         = 0x02,
76 	TTF_STYLE_UNDERLINE      = 0x04,
77 	TTF_STYLE_STRIKETHROUGH  = 0x08,
78 }
79 
80 enum{
81 	TTF_HINTING_NORMAL          = 0,
82 	TTF_HINTING_LIGHT           = 1,
83 	TTF_HINTING_MONO            = 2,
84 	TTF_HINTING_NONE            = 3,
85 }
86 static if(sdlTTFSupport >= SDLTTFSupport.v2_0_18)
87 enum{
88 	TTF_HINTING_LIGHT_SUBPIXEL  = 4,
89 }
90 
91 static if(sdlTTFSupport >= SDLTTFSupport.v2_20){
92 	enum{
93 		TTF_WRAPPED_ALIGN_LEFT    = 0,
94 		TTF_WRAPPED_ALIGN_CENTER  = 1,
95 		TTF_WRAPPED_ALIGN_RIGHT   = 2,
96 	}
97 }
98 
99 alias TTF_SetError = SDL_SetError;
100 
101 alias TTF_GetError = SDL_GetError;
102 
103 alias TTF_Direction = int;
104 enum: TTF_Direction{
105 	TTF_DIRECTION_LTR  = 0, /* Left to Right */
106 	TTF_DIRECTION_RTL  = 1, /* Right to Left */
107 	TTF_DIRECTION_TTB  = 2, /* Top to Bottom */
108 	TTF_DIRECTION_BTT  = 3, /* Bottom to Top */
109 };
110 
111 mixin(joinFnBinds((){
112 	FnBind[] ret = [
113 		{q{SDL_version*}, q{TTF_Linked_Version}, q{}},
114 		{q{void}, q{TTF_ByteSwappedUNICODE}, q{int swapped}},
115 		{q{int}, q{TTF_Init}, q{}},
116 		{q{TTF_Font*}, q{TTF_OpenFont}, q{const(char)* file, int ptSize}},
117 		{q{TTF_Font*}, q{TTF_OpenFontIndex}, q{const(char)* file, int ptSize, c_long index}},
118 		{q{TTF_Font*}, q{TTF_OpenFontRW}, q{SDL_RWops* src, int freeSrc, int ptSize}},
119 		{q{TTF_Font*}, q{TTF_OpenFontIndexRW}, q{SDL_RWops* src, int freeSrc, int ptSize, c_long index}},
120 		{q{int}, q{TTF_GetFontStyle}, q{const(TTF_Font)* font}},
121 		{q{void}, q{TTF_SetFontStyle}, q{const(TTF_Font)* font, int style}},
122 		{q{int}, q{TTF_GetFontOutline}, q{const(TTF_Font)* font}},
123 		{q{void}, q{TTF_SetFontOutline}, q{TTF_Font* font, int outline}},
124 		{q{int}, q{TTF_GetFontHinting}, q{const(TTF_Font)* font}},
125 		{q{void}, q{TTF_SetFontHinting}, q{TTF_Font* font, int hinting}},
126 		{q{int}, q{TTF_FontHeight}, q{const(TTF_Font)* font}},
127 		{q{int}, q{TTF_FontAscent}, q{const(TTF_Font)* font}},
128 		{q{int}, q{TTF_FontDescent}, q{const(TTF_Font)* font}},
129 		{q{int}, q{TTF_FontLineSkip}, q{const(TTF_Font)* font}},
130 		{q{int}, q{TTF_GetFontKerning}, q{const(TTF_Font)* font}},
131 		{q{void}, q{TTF_SetFontKerning}, q{TTF_Font* font, int allowed}},
132 		{q{int}, q{TTF_FontFaces}, q{const(TTF_Font)* font}},
133 		{q{int}, q{TTF_FontFaceIsFixedWidth}, q{const(TTF_Font)* font}},
134 		{q{char*}, q{TTF_FontFaceFamilyName}, q{const(TTF_Font)* font}},
135 		{q{char*}, q{TTF_FontFaceStyleName}, q{const(TTF_Font)* font}},
136 		{q{int}, q{TTF_GlyphIsProvided}, q{const(TTF_Font)* font, ushort ch}},
137 		{q{int}, q{TTF_GlyphMetrics}, q{TTF_Font* font, ushort ch, int* minX, int* maxX, int* minY, int* maxY, int* advance}},
138 		{q{int}, q{TTF_SizeText}, q{TTF_Font* font, const(char)* text, int* w, int* h}},
139 		{q{int}, q{TTF_SizeUTF8}, q{TTF_Font* font, const(char)* text, int* w, int* h}},
140 		{q{int}, q{TTF_SizeUNICODE}, q{TTF_Font* font, const(ushort)* text, int* w, int* h}},
141 		{q{SDL_Surface*}, q{TTF_RenderText_Solid}, q{TTF_Font* font, const(char)* text, SDL_Color fg}},
142 		{q{SDL_Surface*}, q{TTF_RenderUTF8_Solid}, q{TTF_Font* font, const(char)* text, SDL_Color fg}},
143 		{q{SDL_Surface*}, q{TTF_RenderUNICODE_Solid}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg}},
144 		{q{SDL_Surface*}, q{TTF_RenderGlyph_Solid}, q{TTF_Font* font, ushort ch, SDL_Color fg}},
145 		{q{SDL_Surface*}, q{TTF_RenderText_Shaded}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}},
146 		{q{SDL_Surface*}, q{TTF_RenderUTF8_Shaded}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}},
147 		{q{SDL_Surface*}, q{TTF_RenderUNICODE_Shaded}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg}},
148 		{q{SDL_Surface*}, q{TTF_RenderGlyph_Shaded}, q{TTF_Font* font, ushort ch, SDL_Color fg,SDL_Color bg}},
149 		{q{SDL_Surface*}, q{TTF_RenderText_Blended}, q{TTF_Font* font, const(char)* text, SDL_Color fg}},
150 		{q{SDL_Surface*}, q{TTF_RenderUTF8_Blended}, q{TTF_Font* font, const(char)* text, SDL_Color fg}},
151 		{q{SDL_Surface*}, q{TTF_RenderUNICODE_Blended}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg}},
152 		{q{SDL_Surface*}, q{TTF_RenderText_Blended_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}},
153 		{q{SDL_Surface*}, q{TTF_RenderUTF8_Blended_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}},
154 		{q{SDL_Surface*}, q{TTF_RenderUNICODE_Blended_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, uint wrapLength}},
155 		{q{SDL_Surface*}, q{TTF_RenderGlyph_Blended}, q{TTF_Font* font, ushort ch, SDL_Color fg}},
156 		{q{void}, q{TTF_CloseFont}, q{TTF_Font* font}},
157 		{q{void}, q{TTF_Quit}, q{}},
158 		{q{int}, q{TTF_WasInit}, q{}},
159 		{q{int}, q{TTF_GetFontKerningSize}, q{TTF_Font* font, int prevIndex, int index}}, //NOTE: deprecated
160 	];
161 	if(sdlTTFSupport >= SDLTTFSupport.v2_0_14){
162 		FnBind[] add = [
163 			{q{int}, q{TTF_GetFontKerningSizeGlyphs}, q{TTF_Font* font, ushort previousCh, ushort ch}},
164 		];
165 		ret ~= add;
166 	}
167 	if(sdlTTFSupport >= SDLTTFSupport.v2_0_18){
168 		FnBind[] add = [
169 			{q{void}, q{TTF_GetFreeTypeVersion}, q{int* major, int* minor, int* patch}},
170 			{q{void}, q{TTF_GetHarfBuzzVersion}, q{int* major, int* minor, int* patch}},
171 			{q{int}, q{TTF_SetFontSDF}, q{TTF_Font* font, SDL_bool on_off}},
172 			{q{SDL_bool}, q{TTF_GetFontSDF}, q{const(TTF_Font)* font}},
173 			{q{TTF_Font*}, q{TTF_OpenFontDPI}, q{const(char)* file, int ptSize, uint hdpi, uint vdpi}},
174 			{q{TTF_Font*}, q{TTF_OpenFontIndexDPI}, q{const(char)*file, int ptSize, long index, uint hdpi, uint vdpi}},
175 			{q{TTF_Font*}, q{TTF_OpenFontDPIRW}, q{SDL_RWops* src, int freeSrc, int ptsize, uint hdpi, uint vdpi}},
176 			{q{TTF_Font*}, q{TTF_OpenFontIndexDPIRW}, q{SDL_RWops* src, int freeSrc, int ptSize, long index, uint hdpi, uint vdpi}},
177 			{q{int}, q{TTF_SetFontSizeDPI}, q{TTF_Font* font, int ptsize, uint hdpi, uint vdpi}},
178 			{q{int}, q{TTF_GlyphIsProvided32}, q{TTF_Font* font, uint ch}},
179 			{q{int}, q{TTF_GlyphMetrics32}, q{TTF_Font* font, uint ch, int* minx, int* maxx, int* miny, int* maxy, int* advance}},
180 			{q{SDL_Surface*}, q{TTF_RenderGlyph32_Solid}, q{TTF_Font* font, uint ch, SDL_Color fg}},
181 			{q{SDL_Surface*}, q{TTF_RenderGlyph32_Shaded}, q{TTF_Font* font, uint ch, SDL_Color fg, SDL_Color bg}},
182 			{q{SDL_Surface*}, q{TTF_RenderGlyph32_Blended}, q{TTF_Font* font, uint ch, SDL_Color fg}},
183 			{q{int}, q{TTF_GetFontKerningSizeGlyphs32}, q{TTF_Font* font, uint previousCh, uint ch}},
184 			{q{int}, q{TTF_SetDirection}, q{int direction}}, //NOTE: deprecated
185 			{q{int}, q{TTF_SetScript}, q{int script}}, //NOTE: deprecated
186 			{q{int}, q{TTF_MeasureText}, q{TTF_Font* font, const(char)* text, int measureWidth, int* extent, int* count}},
187 			{q{int}, q{TTF_MeasureUTF8}, q{TTF_Font* font, const(char)* text, int measureWidth, int* extent, int* count}},
188 			{q{int}, q{TTF_MeasureUNICODE}, q{TTF_Font* font, const(ushort)* text, int measureWidth, int* extent, int* count}},
189 			{q{int}, q{TTF_SetFontSize}, q{TTF_Font* font, int ptsize}},
190 			{q{SDL_Surface*}, q{TTF_RenderText_Solid_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}},
191 			{q{SDL_Surface*}, q{TTF_RenderUTF8_Solid_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}},
192 			{q{SDL_Surface*}, q{TTF_RenderUNICODE_Solid_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, uint wrapLength}},
193 			{q{SDL_Surface*}, q{TTF_RenderText_Shaded_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
194 			{q{SDL_Surface*}, q{TTF_RenderUTF8_Shaded_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
195 			{q{SDL_Surface*}, q{TTF_RenderUNICODE_Shaded_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
196 		];
197 		ret ~= add;
198 	}
199 	if(sdlTTFSupport >= SDLTTFSupport.v2_20){
200 		FnBind[] add = [
201 			{q{int}, q{TTF_GetFontWrappedAlign}, q{const(TTF_Font)* font}},
202 			{q{void}, q{TTF_SetFontWrappedAlign}, q{TTF_Font* font, int align_}},
203 			{q{SDL_Surface*}, q{TTF_RenderText_LCD}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}},
204 			{q{SDL_Surface*}, q{TTF_RenderUTF8_LCD}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}},
205 			{q{SDL_Surface*}, q{TTF_RenderUNICODE_LCD}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg}},
206 			{q{SDL_Surface*}, q{TTF_RenderText_LCD_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
207 			{q{SDL_Surface*}, q{TTF_RenderUTF8_LCD_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
208 			{q{SDL_Surface*}, q{TTF_RenderUNICODE_LCD_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}},
209 			{q{SDL_Surface*}, q{TTF_RenderGlyph_LCD}, q{TTF_Font* font, ushort ch, SDL_Color fg, SDL_Color bg}},
210 			{q{SDL_Surface*}, q{TTF_RenderGlyph32_LCD}, q{TTF_Font* font, uint ch, SDL_Color fg, SDL_Color bg}},
211 			{q{int}, q{TTF_SetFontDirection}, q{TTF_Font* font, TTF_Direction direction}},
212 			{q{int}, q{TTF_SetFontScriptName}, q{TTF_Font* font, const(char)* script}},
213 		];
214 		ret ~= add;
215 	}
216 	return ret;
217 }()));
218 
219 static if(!staticBinding):
220 import bindbc.loader;
221 
222 private{
223 	SharedLib lib;
224 	SDLTTFSupport loadedVersion;
225 	enum libNamesCT = (){
226 		version(Windows){
227 			return [
228 				`SDL2_ttf.dll`,
229 			];
230 		}else version(OSX){
231 			return [
232 				`libSDL2_ttf.dylib`,
233 				`/opt/homebrew/lib/libSDL2_ttf.dylib`,
234 				`SDL2_ttf`,
235 				`/Library/Frameworks/SDL2_ttf.framework/SDL2_ttf`,
236 				`/System/Library/Frameworks/SDL2_ttf.framework/SDL2_ttf`,
237 			];
238 		}else version(Posix){
239 			return [
240 				`libSDL2_ttf.so`,
241 				`libSDL2-2.0_ttf.so`,
242 				`libSDL2-2.0_ttf.so.0`,
243 			];
244 		}else static assert(0, "BindBC-SDL_ttf does not have library search paths set up for this platform");
245 	}();
246 }
247 
248 nothrow @nogc:
249 deprecated("Please use `TTF_Linked_Version` instead")
250 	SDLTTFSupport loadedSDLTTFVersion(){ return loadedVersion; }
251 
252 mixin(bindbc.sdl.codegen.makeDynloadFns("TTF", [__MODULE__]));