1 /+
2 +            Copyright 2022 – 2023 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.version_: SDL_version;
19 import sdl.stdinc: SDL_bool;
20 
21 enum SDLTTFSupport: SDL_version{
22 	noLibrary   = SDL_version(0,0,0),
23 	badLibrary  = SDL_version(0,0,255),
24 	v2_0_12     = SDL_version(2,0,12),
25 	v2_0_13     = SDL_version(2,0,13),
26 	v2_0_14     = SDL_version(2,0,14),
27 	v2_0_15     = SDL_version(2,0,15),
28 	v2_0_18     = SDL_version(2,0,18),
29 	v2_20       = SDL_version(2,20,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_20)      return SDLTTFSupport.v2_20;
40 	else version(SDL_TTF_2018) return SDLTTFSupport.v2_0_18;
41 	else version(SDL_TTF_2015) return SDLTTFSupport.v2_0_15;
42 	else version(SDL_TTF_2014) return SDLTTFSupport.v2_0_14;
43 	else version(SDL_TTF_2013) return SDLTTFSupport.v2_0_13;
44 	else                       return SDLTTFSupport.v2_0_12;
45 }();
46 
47 enum SDL_TTF_MAJOR_VERSION = sdlTTFSupport.major;
48 enum SDL_TTF_MINOR_VERSION = sdlTTFSupport.minor;
49 enum SDL_TTF_PATCHLEVEL    = sdlTTFSupport.patch;
50 
51 pragma(inline, true) void SDL_TTF_VERSION(SDL_version* X) @nogc nothrow pure @safe{
52 	X.major = SDL_TTF_MAJOR_VERSION;
53 	X.minor = SDL_TTF_MINOR_VERSION;
54 	X.patch = SDL_TTF_PATCHLEVEL;
55 }
56 
57 deprecated("Please use `SDL_TTF_MAJOR_VERSION` instead") alias TTF_MAJOR_VERSION = SDL_TTF_MAJOR_VERSION;
58 deprecated("Please use `SDL_TTF_MINOR_VERSION` instead") alias TTF_MINOR_VERSION = SDL_TTF_MINOR_VERSION;
59 deprecated("Please use `SDL_TTF_PATCHLEVEL` instead")    alias TTF_PATCHLEVEL    = SDL_TTF_PATCHLEVEL;
60 deprecated("Please use `SDL_TTF_VERSION` instead")       alias TTF_VERSION       = SDL_TTF_VERSION;
61 
62 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); }
63 
64 enum{
65 	UNICODE_BOM_NATIVE   = 0xFEFF,
66 	UNICODE_BOM_SWAPPED  = 0xFFFE,
67 }
68 
69 struct TTF_Font;
70 
71 enum{
72 	TTF_STYLE_NORMAL         = 0x00,
73 	TTF_STYLE_BOLD           = 0x01,
74 	TTF_STYLE_ITALIC         = 0x02,
75 	TTF_STYLE_UNDERLINE      = 0x04,
76 	TTF_STYLE_STRIKETHROUGH  = 0x08,
77 }
78 
79 enum{
80 	TTF_HINTING_NORMAL          = 0,
81 	TTF_HINTING_LIGHT           = 1,
82 	TTF_HINTING_MONO            = 2,
83 	TTF_HINTING_NONE            = 3,
84 }
85 static if(sdlTTFSupport >= SDLTTFSupport.v2_0_18)
86 enum{
87 	TTF_HINTING_LIGHT_SUBPIXEL  = 4,
88 }
89 
90 static if(sdlTTFSupport >= SDLTTFSupport.v2_20){
91 	enum{
92 		TTF_WRAPPED_ALIGN_LEFT    = 0,
93 		TTF_WRAPPED_ALIGN_CENTER  = 1,
94 		TTF_WRAPPED_ALIGN_RIGHT   = 2,
95 	}
96 }
97 
98 alias TTF_SetError = SDL_SetError;
99 
100 alias TTF_GetError = SDL_GetError;
101 
102 alias TTF_Direction = int;
103 enum: TTF_Direction{
104 	TTF_DIRECTION_LTR  = 0, /* Left to Right */
105 	TTF_DIRECTION_RTL  = 1, /* Right to Left */
106 	TTF_DIRECTION_TTB  = 2, /* Top to Bottom */
107 	TTF_DIRECTION_BTT  = 3, /* Bottom to Top */
108 };
109 
110 mixin(joinFnBinds((){
111 	string[][] ret;
112 	ret ~= makeFnBinds([
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 prev_index, int index}], //NOTE: deprecated
160 	]);
161 	static if(sdlTTFSupport >= SDLTTFSupport.v2_0_14){
162 		ret ~= makeFnBinds([
163 			[q{int}, q{TTF_GetFontKerningSizeGlyph}, q{TTF_Font* font, ushort previous_ch, ushort ch}],
164 		]);
165 	}
166 	static if(sdlTTFSupport >= SDLTTFSupport.v2_0_18){
167 		ret ~= makeFnBinds([
168 			[q{void}, q{TTF_GetFreeTypeVersion}, q{int* major, int* minor, int* patch}],
169 			[q{void}, q{TTF_GetHarfBuzzVersion}, q{int* major, int* minor, int* patch}],
170 			[q{int}, q{TTF_SetFontSDF}, q{TTF_Font* font, SDL_bool on_off}],
171 			[q{SDL_bool}, q{TTF_GetFontSDF}, q{const(TTF_Font)* font}],
172 			[q{TTF_Font*}, q{TTF_OpenFontDPI}, q{const(char)* file, int ptsize, uint hdpi, uint vdpi}],
173 			[q{TTF_Font*}, q{TTF_OpenFontIndexDPI}, q{const(char)*file, int ptsize, long index, uint hdpi, uint vdpi}],
174 			[q{TTF_Font*}, q{TTF_OpenFontDPIRW}, q{SDL_RWops* src, int freesrc, int ptsize, uint hdpi, uint vdpi}],
175 			[q{TTF_Font*}, q{TTF_OpenFontIndexDPIRW}, q{SDL_RWops* src, int freesrc, int ptsize, long index, uint hdpi, uint vdpi}],
176 			[q{int}, q{TTF_SetFontSizeDPI}, q{TTF_Font* font, int ptsize, uint hdpi, uint vdpi}],
177 			[q{int}, q{TTF_GlyphIsProvided32}, q{TTF_Font* font, uint ch}],
178 			[q{int}, q{TTF_GlyphMetrics32}, q{TTF_Font* font, uint ch, int* minx, int* maxx, int* miny, int* maxy, int* advance}],
179 			[q{SDL_Surface*}, q{TTF_RenderGlyph32_Solid}, q{TTF_Font* font, uint ch, SDL_Color fg}],
180 			[q{SDL_Surface*}, q{TTF_RenderGlyph32_Shaded}, q{TTF_Font* font, uint ch, SDL_Color fg, SDL_Color bg}],
181 			[q{SDL_Surface*}, q{TTF_RenderGlyph32_Blended}, q{TTF_Font* font, uint ch, SDL_Color fg}],
182 			[q{int}, q{TTF_GetFontKerningSizeGlyphs32}, q{TTF_Font* font, uint previous_ch, uint ch}],
183 			[q{int}, q{TTF_SetDirection}, q{int direction}], //NOTE: deprecated
184 			[q{int}, q{TTF_SetScript}, q{int script}], //NOTE: deprecated
185 			[q{int}, q{TTF_MeasureText}, q{TTF_Font* font, const(char)* text, int measure_width, int* extent, int* count}],
186 			[q{int}, q{TTF_MeasureUTF8}, q{TTF_Font* font, const(char)* text, int measure_width, int* extent, int* count}],
187 			[q{int}, q{TTF_MeasureUNICODE}, q{TTF_Font* font, const(ushort)* text, int measure_width, int* extent, int* count}],
188 			[q{int}, q{TTF_SetFontSize}, q{TTF_Font* font, int ptsize}],
189 			[q{SDL_Surface*}, q{TTF_RenderText_Solid_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}],
190 			[q{SDL_Surface*}, q{TTF_RenderUTF8_Solid_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, uint wrapLength}],
191 			[q{SDL_Surface*}, q{TTF_RenderUNICODE_Solid_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, uint wrapLength}],
192 			[q{SDL_Surface*}, q{TTF_RenderText_Shaded_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
193 			[q{SDL_Surface*}, q{TTF_RenderUTF8_Shaded_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
194 			[q{SDL_Surface*}, q{TTF_RenderUNICODE_Shaded_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
195 		]);
196 	}
197 	static if(sdlTTFSupport >= SDLTTFSupport.v2_20){
198 		ret ~= makeFnBinds([
199 			[q{int}, q{TTF_GetFontWrappedAlign}, q{const(TTF_Font)* font}],
200 			[q{void}, q{TTF_SetFontWrappedAlign}, q{TTF_Font* font, int align_}],
201 			[q{SDL_Surface*}, q{TTF_RenderText_LCD}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}],
202 			[q{SDL_Surface*}, q{TTF_RenderUTF8_LCD}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg}],
203 			[q{SDL_Surface*}, q{TTF_RenderUNICODE_LCD}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg}],
204 			[q{SDL_Surface*}, q{TTF_RenderText_LCD_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
205 			[q{SDL_Surface*}, q{TTF_RenderUTF8_LCD_Wrapped}, q{TTF_Font* font, const(char)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
206 			[q{SDL_Surface*}, q{TTF_RenderUNICODE_LCD_Wrapped}, q{TTF_Font* font, const(ushort)* text, SDL_Color fg, SDL_Color bg, uint wrapLength}],
207 			[q{SDL_Surface*}, q{TTF_RenderGlyph_LCD}, q{TTF_Font* font, ushort ch, SDL_Color fg, SDL_Color bg}],
208 			[q{SDL_Surface*}, q{TTF_RenderGlyph32_LCD}, q{TTF_Font* font, uint ch, SDL_Color fg, SDL_Color bg}],
209 			[q{int}, q{TTF_SetFontDirection}, q{TTF_Font* font, TTF_Direction direction}],
210 			[q{int}, q{TTF_SetFontScriptName}, q{TTF_Font* font, const(char)* script}],
211 		]);
212 	}
213 	return ret;
214 }()));
215 
216 static if(!staticBinding):
217 import bindbc.loader;
218 
219 private{
220 	SharedLib lib;
221 	SDLTTFSupport loadedVersion;
222 	enum libNamesCT = (){
223 		version(Windows){
224 			return [
225 				`SDL2_ttf.dll`,
226 			];
227 		}else version(OSX){
228 			return [
229 				`libSDL2_ttf.dylib`,
230 				`/opt/homebrew/lib/libSDL2_ttf.dylib`,
231 				`SDL2_ttf`,
232 				`/Library/Frameworks/SDL2_ttf.framework/SDL2_ttf`,
233 				`/System/Library/Frameworks/SDL2_ttf.framework/SDL2_ttf`,
234 			];
235 		}else version(Posix){
236 			return [
237 				`libSDL2_ttf.so`,
238 				`libSDL2-2.0_ttf.so`,
239 				`libSDL2-2.0_ttf.so.0`,
240 			];
241 		}else static assert(0, "BindBC-SDL_ttf does not have library search paths set up for this platform");
242 	}();
243 }
244 
245 @nogc nothrow:
246 deprecated("Please use `TTF_Linked_Version` instead")
247 	SDLTTFSupport loadedSDLTTFVersion(){ return loadedVersion; }
248 
249 mixin(bindbc.sdl.codegen.makeDynloadFns("TTF", [__MODULE__]));