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