1 /*
2  *******************************************************************************************
3  * Dgame (a D game framework) - Copyright (c) Randy Schütt
4  * 
5  * This software is provided 'as-is', without any express or implied warranty.
6  * In no event will the authors be held liable for any damages arising from
7  * the use of this software.
8  * 
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  * 
13  * 1. The origin of this software must not be misrepresented; you must not claim
14  *    that you wrote the original software. If you use this software in a product,
15  *    an acknowledgment in the product documentation would be appreciated but is
16  *    not required.
17  * 
18  * 2. Altered source versions must be plainly marked as such, and must not be
19  *    misrepresented as being the original software.
20  * 
21  * 3. This notice may not be removed or altered from any source distribution.
22  *******************************************************************************************
23  */
24 module Dgame.System.Font;
25 
26 private:
27 
28 import derelict.sdl2.types;
29 import derelict.sdl2.ttf;
30 
31 import Dgame.Graphic.Color;
32 import Dgame.Graphic.Surface;
33 
34 import Dgame.Internal.Error;
35 import Dgame.Internal.d2c;
36 
37 enum ubyte MinDepth = 24;
38 
39 public:
40 
41 /**
42  * Font is the low-level class for loading and manipulating character fonts.
43  * This class is meant to be used by Dgame.Graphic.Text.
44  *
45  * Author: Randy Schuett (rswhite4@googlemail.com)
46  */
47 struct Font {
48 private:
49     TTF_Font* _ttf;
50     ubyte _fontSize;
51 
52 public:
53     /**
54      * The default size of every Font is 10
55      */
56     enum ubyte DefaultSize = 10;
57 
58     /**
59      * Available Font styles
60      */
61     enum Style {
62         Normal = TTF_STYLE_NORMAL, /// Used to indicate regular, normal, plain rendering style.
63         Bold = TTF_STYLE_BOLD, /// Used to indicate bold rendering style.This is used in a bitmask along with other styles.
64         Italic = TTF_STYLE_ITALIC, /// Used to indicate italicized rendering style.This is used in a bitmask along with other styles.
65         Underline = TTF_STYLE_UNDERLINE, /// Used to indicate underlined rendering style.This is used in a bitmask along with other styles.
66         StrikeThrough = TTF_STYLE_STRIKETHROUGH /// Used to indicate strikethrough rendering style.This is used in a bitmask along with other styles.
67     }
68 
69     /**
70      * Available Font modes
71      */
72     enum Mode : ubyte {
73         Solid, /// Solid
74         Shaded, /// Shaded
75         Blended /// Blended
76     }
77 
78     /**
79      * CTor
80      */
81     @nogc
82     this(string filename, ubyte fontSize) nothrow {
83         this.loadFromFile(filename, fontSize);
84     }
85     
86     /**
87      * Postblit is disabled
88      */
89     @disable
90     this(this);
91 
92     /**
93      * DTor
94      */
95     @nogc
96     ~this() nothrow {
97         TTF_CloseFont(_ttf);
98     }
99 
100     /**
101      * Load the font from a file.
102      * Returns if the loading was successful.
103      * If not, an error message is shown, which describes the problem.
104      * If the second parameter isn't 0, the current font size will be replaced with that.
105      * If the current size is also 0, the DefaultSize (10) will be used.
106      *
107      * See: DefaultSize
108      */
109     @nogc
110     bool loadFromFile(string filename, ubyte fontSize) nothrow {
111         _fontSize = fontSize == 0 ? DefaultSize : fontSize;
112         _ttf = TTF_OpenFont(toStringz(filename), _fontSize);
113         if (!_ttf) {
114             print_fmt("Error by loading TTF_Font %s: %s\n", toStringz(filename), TTF_GetError());
115             return false;
116         }
117 
118         return true;
119     }
120 
121     /**
122      * Set the Font style.
123      *
124      * See: Font.Style enum
125      */
126     @nogc
127     void setStyle(Style style) nothrow {
128         if (_ttf)
129             TTF_SetFontStyle(_ttf, style);
130     }
131 
132     /**
133      * Returns the current Font style.
134      *
135      * See: Font.Style enum
136      */
137     @nogc
138     Style getStyle() const nothrow {
139         if (_ttf)
140             return cast(Style) TTF_GetFontStyle(_ttf);
141         return Style.Normal;
142     }
143 
144     /**
145      * Draws the text on a Surface by using this Font and the given Mode (default is Mode.Solid)
146      * The text (and the Surface) is colorized by fg / bg Color.
147      *
148      * Note: The background color is ignored if your mode is not Font.Mode.Shaded
149      *
150      * Returns a Surface with the text or throws an Error
151      */
152     @nogc
153     Surface render(string text, const Color4b fg, const Color4b bg, Mode mode = Mode.Solid) nothrow {
154         assert(_ttf, "Font is invalid");
155 
156         SDL_Color a = void;
157         SDL_Color b = void;
158 
159         _transfer(fg, a);
160         _transfer(bg, b);
161 
162         SDL_Surface* sdl_srfc;
163         final switch (mode) {
164             case Mode.Solid:
165                 sdl_srfc = TTF_RenderUTF8_Solid(_ttf, toStringz(text), a);
166                 break;
167             case Mode.Shaded:
168                 sdl_srfc = TTF_RenderUTF8_Shaded(_ttf, toStringz(text), a, b);
169                 break;
170             case Mode.Blended:
171                 sdl_srfc = TTF_RenderUTF8_Blended(_ttf, toStringz(text), a);
172                 break;
173         }
174 
175         assert_fmt(sdl_srfc, "Error by rendering text: %s", TTF_GetError());
176 
177         Surface srfc = Surface(sdl_srfc);
178         if (srfc.bits < MinDepth)
179             srfc.adaptTo(MinDepth);
180 
181         return srfc;
182     }
183 }