1 /*
2  * OpenTyrian: A modern cross-platform port of Tyrian
3  * Copyright (C) 2007-2009  The OpenTyrian Development Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  */
19 #include "font.h"
20 #include "fonthand.h"
21 #include "sprite.h"
22 
23 /**
24  * \file font.c
25  * \brief Text drawing routines.
26  */
27 
28 /**
29  * \brief Draws text in a color specified by hue and value and with a drop
30  *        shadow.
31  *
32  * A '~' in the text is not drawn but instead toggles highlighting which
33  * increases \c value by 4.
34  *
35  * \li like JE_dString()                    if (black == false && shadow_dist == 2 && hue == 15)
36  * \li like JE_textShade() with PART_SHADE  if (black == true && shadow_dist == 1)
37  * \li like JE_outTextAndDarken()           if (black == false && shadow_dist == 1)
38  * \li like JE_outTextAdjust() with shadow  if (black == false && shadow_dist == 2)
39  *
40  * @param surface destination surface
41  * @param x initial x-position in pixels; which direction(s) the text is drawn
42  *        from this position depends on the alignment
43  * @param y initial upper y-position in pixels
44  * @param text text to be drawn
45  * @param font style/size of text
46  * @param alignment left_aligned, centered, or right_aligned
47  * @param hue hue component of text color
48  * @param value value component of text color
49  * @param black if true the shadow is drawn as solid black, if false the shadow
50  *        is drawn by darkening the pixels of the destination surface
51  * @param shadow_dist distance in pixels that the shadow will be drawn away from
52  *        the text. (This is added to both the x and y positions, so a value of
53  *        1 causes the shadow to be drawn 1 pixel right and 1 pixel lower than
54  *        the text.)
55  */
draw_font_hv_shadow(SDL_Surface * surface,int x,int y,const char * text,Font font,FontAlignment alignment,Uint8 hue,Sint8 value,bool black,int shadow_dist)56 void draw_font_hv_shadow( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value, bool black, int shadow_dist )
57 {
58 	draw_font_dark(surface, x + shadow_dist, y + shadow_dist, text, font, alignment, black);
59 
60 	draw_font_hv(surface, x, y, text, font, alignment, hue, value);
61 }
62 
63 /**
64  * \brief Draws text in a color specified by hue and value and with a
65  *        surrounding shadow.
66  *
67  * A '~' in the text is not drawn but instead toggles highlighting which
68  * increases \c value by 4.
69  *
70  * \li like JE_textShade() with FULL_SHADE  if (black == true && shadow_dist == 1)
71  *
72  * @param surface destination surface
73  * @param x initial x-position in pixels; which direction(s) the text is drawn
74  *        from this position depends on the alignment
75  * @param y initial upper y-position in pixels
76  * @param text text to be drawn
77  * @param font style/size of text
78  * @param alignment left_aligned, centered, or right_aligned
79  * @param hue hue component of text color
80  * @param value value component of text color
81  * @param black if true the shadow is drawn as solid black, if false the shadow
82  *        is drawn by darkening the pixels of the destination surface
83  * @param shadow_dist distance in pixels that the shadows will be drawn away
84  *        from the text. (This distance is separately added to and subtracted
85  *        from the x position and y position, resulting in four shadows -- one
86  *        in each cardinal direction.  If this shadow distance is small enough,
87  *        this produces a shadow that outlines the text.)
88  */
draw_font_hv_full_shadow(SDL_Surface * surface,int x,int y,const char * text,Font font,FontAlignment alignment,Uint8 hue,Sint8 value,bool black,int shadow_dist)89 void draw_font_hv_full_shadow( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value, bool black, int shadow_dist )
90 {
91 	draw_font_dark(surface, x,               y - shadow_dist, text, font, alignment, black);
92 	draw_font_dark(surface, x + shadow_dist, y,               text, font, alignment, black);
93 	draw_font_dark(surface, x,               y + shadow_dist, text, font, alignment, black);
94 	draw_font_dark(surface, x - shadow_dist, y,               text, font, alignment, black);
95 
96 	draw_font_hv(surface, x, y, text, font, alignment, hue, value);
97 }
98 
99 /**
100  * \brief Draws text in a color specified by hue and value.
101  *
102  * A '~' in the text is not drawn but instead toggles highlighting which
103  * increases \c value by 4.
104  *
105  * \li like JE_outText() with (brightness >= 0)
106  * \li like JE_outTextAdjust() without shadow
107  *
108  * @param surface destination surface
109  * @param x initial x-position in pixels; which direction(s) the text is drawn
110  *        from this position depends on the alignment
111  * @param y initial upper y-position in pixels
112  * @param text text to be drawn
113  * @param font style/size of text
114  * @param alignment left_aligned, centered, or right_aligned
115  * @param hue hue component of text color
116  * @param value value component of text color
117  */
draw_font_hv(SDL_Surface * surface,int x,int y,const char * text,Font font,FontAlignment alignment,Uint8 hue,Sint8 value)118 void draw_font_hv( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value )
119 {
120 	switch (alignment)
121 	{
122 	case left_aligned:
123 		break;
124 	case centered:
125 		x -= JE_textWidth(text, font) / 2;
126 		break;
127 	case right_aligned:
128 		x -= JE_textWidth(text, font);
129 		break;
130 	}
131 
132 	bool highlight = false;
133 
134 	for (; *text != '\0'; ++text)
135 	{
136 		int sprite_id = font_ascii[(unsigned char)*text];
137 
138 		switch (*text)
139 		{
140 		case ' ':
141 			x += 6;
142 			break;
143 
144 		case '~':
145 			highlight = !highlight;
146 			if (highlight)
147 				value += 4;
148 			else
149 				value -= 4;
150 			break;
151 
152 		default:
153 			if (sprite_id != -1 && sprite_exists(font, sprite_id))
154 			{
155 				blit_sprite_hv(surface, x, y, font, sprite_id, hue, value);
156 
157 				x += sprite(font, sprite_id)->width + 1;
158 			}
159 			break;
160 		}
161 	}
162 }
163 
164 /**
165  * \brief Draws blended text in a color specified by hue and value.
166  *
167  * Corresponds to blit_sprite_hv_blend()
168  *
169  * \li like JE_outTextModify()
170  *
171  * @param surface destination surface
172  * @param x initial x-position in pixels; which direction(s) the text is drawn
173  *        from this position depends on the alignment
174  * @param y initial upper y-position in pixels
175  * @param text text to be drawn
176  * @param font style/size of text
177  * @param alignment left_aligned, centered, or right_aligned
178  * @param hue hue component of text color
179  * @param value value component of text color
180  */
draw_font_hv_blend(SDL_Surface * surface,int x,int y,const char * text,Font font,FontAlignment alignment,Uint8 hue,Sint8 value)181 void draw_font_hv_blend( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, Uint8 hue, Sint8 value )
182 {
183 	switch (alignment)
184 	{
185 	case left_aligned:
186 		break;
187 	case centered:
188 		x -= JE_textWidth(text, font) / 2;
189 		break;
190 	case right_aligned:
191 		x -= JE_textWidth(text, font);
192 		break;
193 	}
194 
195 	for (; *text != '\0'; ++text)
196 	{
197 		int sprite_id = font_ascii[(unsigned char)*text];
198 
199 		switch (*text)
200 		{
201 		case ' ':
202 			x += 6;
203 			break;
204 
205 		case '~':
206 			break;
207 
208 		default:
209 			if (sprite_id != -1 && sprite_exists(font, sprite_id))
210 			{
211 				blit_sprite_hv_blend(surface, x, y, font, sprite_id, hue, value);
212 
213 				x += sprite(font, sprite_id)->width + 1;
214 			}
215 			break;
216 		}
217 	}
218 }
219 
220 /**
221  * \brief Draws darkened text.
222  *
223  * Corresponds to blit_sprite_dark()
224  *
225  * \li like JE_outText() with (brightness < 0)  if (black == true)
226  *
227  * @param surface destination surface
228  * @param x initial x-position in pixels; which direction(s) the text is drawn
229  *        from this position depends on the alignment
230  * @param y initial upper y-position in pixels
231  * @param text text to be drawn
232  * @param font style/size of text
233  * @param alignment left_aligned, centered, or right_aligned
234  * @param black if true text is drawn as solid black, if false text is drawn by
235  *        darkening the pixels of the destination surface
236  */
draw_font_dark(SDL_Surface * surface,int x,int y,const char * text,Font font,FontAlignment alignment,bool black)237 void draw_font_dark( SDL_Surface *surface, int x, int y, const char *text, Font font, FontAlignment alignment, bool black )
238 {
239 	switch (alignment)
240 	{
241 	case left_aligned:
242 		break;
243 	case centered:
244 		x -= JE_textWidth(text, font) / 2;
245 		break;
246 	case right_aligned:
247 		x -= JE_textWidth(text, font);
248 		break;
249 	}
250 
251 	for (; *text != '\0'; ++text)
252 	{
253 		int sprite_id = font_ascii[(unsigned char)*text];
254 
255 		switch (*text)
256 		{
257 		case ' ':
258 			x += 6;
259 			break;
260 
261 		case '~':
262 			break;
263 
264 		default:
265 			if (sprite_id != -1 && sprite_exists(font, sprite_id))
266 			{
267 				blit_sprite_dark(surface, x, y, font, sprite_id, black);
268 
269 				x += sprite(font, sprite_id)->width + 1;
270 			}
271 			break;
272 		}
273 	}
274 }
275