1 module gfm.sdl2.sdlttf; 2 3 import std.string; 4 5 import derelict.sdl2.sdl, 6 derelict.sdl2.ttf, 7 derelict.util.exception; 8 9 import std.experimental.logger; 10 11 import gfm.sdl2.sdl, 12 gfm.sdl2.surface; 13 14 /// SDL_ttf library wrapper. 15 final class SDLTTF 16 { 17 public 18 { 19 /// Loads the SDL_ttf library. 20 /// Throws: $(D SDL2Exception) on error. 21 this(SDL2 sdl2) 22 { 23 _sdl2 = sdl2; // force loading of SDL first 24 _logger = sdl2._logger; 25 _SDLTTFInitialized = false; 26 27 try 28 { 29 DerelictSDL2ttf.load(); 30 } 31 catch(DerelictException e) 32 { 33 throw new SDL2Exception(e.msg); 34 } 35 36 int res = TTF_Init(); 37 if (res != 0) 38 throwSDL2TTFException("TTF_Init"); 39 40 _SDLTTFInitialized = true; 41 } 42 43 /// Releases the SDL_ttf library. 44 void close() 45 { 46 if (_SDLTTFInitialized) 47 { 48 _SDLTTFInitialized = false; 49 TTF_Quit(); 50 } 51 52 DerelictSDL2ttf.unload(); 53 } 54 55 ~this() 56 { 57 close(); 58 } 59 } 60 61 private 62 { 63 Logger _logger; 64 SDL2 _sdl2; 65 bool _SDLTTFInitialized; 66 67 void throwSDL2TTFException(string callThatFailed) 68 { 69 string message = format("%s failed: %s", callThatFailed, getErrorString()); 70 throw new SDL2Exception(message); 71 } 72 73 const(char)[] getErrorString() 74 { 75 return fromStringz(TTF_GetError()); 76 } 77 } 78 } 79 80 /// SDL_ttf loaded font wrapper. 81 final class SDLFont 82 { 83 public 84 { 85 /// Loads a font from a file. 86 /// Params: 87 /// ptSize = font size in 72 dpi ("This basically translates to pixel height" says the doc). 88 /// Throws: $(D SDL2Exception) on error. 89 this(SDLTTF sdlttf, string filename, int ptSize) 90 { 91 _sdlttf = sdlttf; 92 _font = TTF_OpenFont(toStringz(filename), ptSize); 93 if (_font is null) 94 _sdlttf.throwSDL2TTFException("TTF_OpenFont"); 95 } 96 97 ~this() 98 { 99 close(); 100 } 101 102 /// Releases the SDL resource. 103 void close() 104 { 105 if (_font !is null) 106 { 107 TTF_CloseFont(_font); 108 _font = null; 109 } 110 } 111 112 /// Returns: Font style. 113 int style() 114 { 115 return TTF_GetFontStyle(_font); 116 } 117 118 /// Set font style. 119 int setStyle(int newStyle) 120 { 121 if (newStyle != TTF_GetFontStyle(_font)) 122 TTF_SetFontStyle(_font, newStyle); 123 return newStyle; 124 } 125 126 /// Returns: Font hinting. 127 int hinting() 128 { 129 return TTF_GetFontHinting(_font); 130 } 131 132 /// Set font hinting. 133 int setHinting(int newHinting) 134 { 135 if (newHinting != TTF_GetFontHinting(_font)) 136 TTF_SetFontHinting(_font, newHinting); 137 return newHinting; 138 } 139 140 /// Returns: Font outline. 141 int outline() 142 { 143 return TTF_GetFontOutline(_font); 144 } 145 146 /// Set font outline. 147 int setOutline(int newOutline) 148 { 149 if (newOutline != TTF_GetFontOutline(_font)) 150 TTF_SetFontOutline(_font, newOutline); 151 return newOutline; 152 } 153 154 /// Returns: true if kerning is enabled. 155 bool getKerning() 156 { 157 return TTF_GetFontKerning(_font) != 0; 158 } 159 160 /// Enables/Disables font kerning. 161 bool setKerning(bool enabled) 162 { 163 TTF_SetFontKerning(_font, enabled ? 1 : 0); 164 return enabled; 165 } 166 167 /// Returns: Maximum height of a glyph in pixels. 168 int height() 169 { 170 return TTF_FontAscent(_font); 171 } 172 173 /// Returns: Height above baseline in pixels. 174 int ascent() 175 { 176 return TTF_FontAscent(_font); 177 } 178 179 /// Returns: Height below baseline. 180 int descent() 181 { 182 return TTF_FontDescent(_font); 183 } 184 185 /// Returns: Line skip, the recommended pixel interval between two lines. 186 int lineSkip() 187 { 188 return TTF_FontLineSkip(_font); 189 } 190 191 /// Returns: Size of text in pixels if rendered with this font. 192 SDL_Point measureText(string text) 193 { 194 int w, h; 195 TTF_SizeUTF8(_font, toStringz(text), &w, &h); 196 return SDL_Point(w, h); 197 } 198 199 /// Create a 32-bit ARGB surface and render the given character at high quality, 200 /// using alpha blending to dither the font with the given color. 201 /// Throws: $(D SDL2Exception) on error. 202 SDL2Surface renderGlyphBlended(dchar ch, SDL_Color color) 203 { 204 return checkedSurface(TTF_RenderGlyph_Blended(_font, cast(ushort)ch, color)); 205 } 206 207 /// Create a 32-bit ARGB surface and render the given text at high quality, 208 /// using alpha blending to dither the font with the given color. 209 /// Throws: $(D SDL2Exception) on error. 210 SDL2Surface renderTextBlended(string text, SDL_Color color) 211 { 212 return checkedSurface(TTF_RenderUTF8_Blended(_font, toStringz(text), color)); 213 } 214 215 /// Create an 8-bit palettized surface and render the given text at fast 216 /// quality with the given font and color. 217 /// Throws: $(D SDL2Exception) on error. 218 SDL2Surface renderTextSolid(string text, SDL_Color color) 219 { 220 return checkedSurface(TTF_RenderUTF8_Solid(_font, toStringz(text), color)); 221 } 222 223 /// Create an 8-bit palettized surface and render the given text at high 224 /// quality with the given font and colors. 225 /// Throws: $(D SDL2Exception) on error. 226 SDL2Surface renderTextShaded(string text, SDL_Color fg, SDL_Color bg) 227 { 228 return checkedSurface(TTF_RenderUTF8_Shaded(_font, toStringz(text), fg, bg)); 229 } 230 231 /// Create a 32-bit ARGB surface and render the given text at high quality, 232 /// using alpha blending to dither the font with the given color. 233 /// Uses multi-line text wrapping. 234 /// Throws: $(D SDL2Exception) on error. 235 SDL2Surface renderTextBlendedWrapped(string text, SDL_Color color, uint wrapLength) 236 { 237 return checkedSurface(TTF_RenderUTF8_Blended_Wrapped(_font, toStringz(text), color, wrapLength)); 238 } 239 } 240 241 private 242 { 243 SDLTTF _sdlttf; 244 TTF_Font *_font; 245 246 SDL2Surface checkedSurface(SDL_Surface* s) 247 { 248 if (s is null) 249 _sdlttf.throwSDL2TTFException("TTF_Render"); 250 return new SDL2Surface(_sdlttf._sdl2, s, SDL2Surface.Owned.YES); 251 } 252 } 253 }