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