1 /* NetHack may be freely redistributed under the Nethack General Public License
2 * See nethack/dat/license for details */
3
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <SDL.h>
8 #include "SDL_ttf.h"
9
10 #include "vulture_txt.h"
11
12 #define VULTURE_MAX_FONTS 2
13
14 /* the rest of vulture gets these defines indirectly from nethack code.
15 * but I'd prefer not to pull all that in here */
16 #define TRUE 1
17 #define FALSE 0
18
19 static struct vulture_font {
20 TTF_Font *fontptr;
21 char lineheight;
22 } *vulture_fonts = NULL;
23
24
25 /* load a font from a ttf file with the given fontindex and pointsize as font font_id */
vulture_load_font(int font_id,const char * ttf_filename,int fontindex,int pointsize)26 int vulture_load_font (int font_id, const char * ttf_filename, int fontindex, int pointsize)
27 {
28 TTF_Font *newfont;
29 if(!TTF_WasInit()) {
30 if(TTF_Init()==-1)
31 return FALSE;
32
33 if (!vulture_fonts)
34 vulture_fonts = (struct vulture_font *)calloc(VULTURE_MAX_FONTS, sizeof(struct vulture_font));
35 }
36
37 /* font_id should always be passed as a #define, which is always < VULTURE_MAX_FONTS */
38 if (font_id >= VULTURE_MAX_FONTS)
39 return FALSE;
40
41 newfont = TTF_OpenFontIndex(ttf_filename, pointsize, fontindex);
42
43 if (!newfont)
44 return FALSE;
45
46 if (vulture_fonts[font_id].fontptr)
47 TTF_CloseFont(vulture_fonts[font_id].fontptr);
48
49 vulture_fonts[font_id].fontptr = newfont;
50 vulture_fonts[font_id].lineheight = TTF_FontAscent(newfont) + 2;
51
52 return TRUE;
53 }
54
55
vulture_put_text(int font_id,std::string str,SDL_Surface * dest,int x,int y,Uint32 color)56 int vulture_put_text (int font_id, std::string str, SDL_Surface *dest, int x, int y, Uint32 color)
57 {
58 SDL_Surface *textsurface;
59 SDL_Color fontcolor;
60 SDL_Rect dstrect;
61 std::string cleaned_str;
62 unsigned int i;
63
64 if (font_id >= VULTURE_MAX_FONTS || (!vulture_fonts[font_id].fontptr) || str.empty())
65 return FALSE;
66
67 /* sanitize the input string of unprintable characters */
68 cleaned_str = str;
69 for (i = 0; i < cleaned_str.length(); i++)
70 if (!isprint(cleaned_str[i]))
71 cleaned_str[i] = ' ';
72
73
74 /* extract components from the 32-bit color value */
75 fontcolor.r = (color & dest->format->Rmask) >> dest->format->Rshift;
76 fontcolor.g = (color & dest->format->Gmask) >> dest->format->Gshift;
77 fontcolor.b = (color & dest->format->Bmask) >> dest->format->Bshift;
78 fontcolor.unused = 0;
79
80 textsurface = TTF_RenderText_Blended(vulture_fonts[font_id].fontptr,
81 cleaned_str.c_str(), fontcolor);
82 if (!textsurface)
83 return FALSE;
84
85 dstrect.x = x;
86 dstrect.y = y - 1;
87 dstrect.w = textsurface->w;
88 dstrect.h = textsurface->h;
89
90 SDL_BlitSurface(textsurface, NULL, dest, &dstrect);
91 SDL_FreeSurface(textsurface);
92
93 return TRUE;
94 }
95
96
97
vulture_put_text_shadow(int font_id,std::string str,SDL_Surface * dest,int x,int y,Uint32 textcolor,Uint32 shadowcolor)98 int vulture_put_text_shadow (int font_id, std::string str, SDL_Surface *dest,
99 int x, int y, Uint32 textcolor, Uint32 shadowcolor)
100 {
101 /* draw the shadow first */
102 vulture_put_text(font_id, str, dest, x+1, y+1, shadowcolor);
103 /* we only truly care that the actual text got drawn, so only retrun that status */
104 return vulture_put_text(font_id, str, dest, x, y, textcolor);
105 }
106
107
108 /* draw text over multiple lines if its length exceeds maxlen */
vulture_put_text_multiline(int font_id,std::string str,SDL_Surface * dest,int x,int y,Uint32 color,Uint32 shadowcolor,int maxlen)109 void vulture_put_text_multiline(int font_id, std::string str, SDL_Surface *dest,
110 int x, int y, Uint32 color, Uint32 shadowcolor, int maxlen)
111 {
112 std::string str_copy;
113 int lastfit, txtlen, lineno, text_height;
114 size_t endpos, startpos;
115
116 lineno = 0;
117 lastfit = 0;
118 startpos = endpos = 0;
119 text_height = vulture_text_height(font_id, str);
120
121 /* lastfit is true when the last segment has been fit onto the surface (drawn) */
122 while (!lastfit) {
123 lastfit = 1;
124
125 startpos = startpos + endpos;
126 str_copy = str.substr(startpos, std::string::npos);
127 endpos = str_copy.length() - 1;
128
129 txtlen = vulture_text_length(font_id, str_copy);
130
131 /* split word off the end of the string until it is short enough to fit */
132 while (txtlen > maxlen) {
133 /* a piece will be split off the end, so this is not the last piece */
134 lastfit = 0;
135
136 /* find a suitable place to split */
137 endpos = str_copy.find_last_of(" \t\n");
138
139 /* prevent infinite loops if a long word doesn't fit */
140 if (endpos == std::string::npos) {
141 endpos = str_copy.length() - 1;
142 lastfit = 1;
143 break;
144 }
145
146 /* truncate the text */
147 str_copy.erase(endpos++);
148 txtlen = vulture_text_length(font_id, str_copy);
149 }
150 vulture_put_text_shadow(font_id, str_copy, dest, x, y + lineno * text_height, color, shadowcolor);
151
152 lineno++;
153 }
154 }
155
156
157
vulture_text_length(int font_id,std::string str)158 int vulture_text_length (int font_id, std::string str)
159 {
160 int width = 0;
161
162 if (!vulture_fonts[font_id].fontptr || str.empty())
163 return 0;
164
165 TTF_SizeText(vulture_fonts[font_id].fontptr, str.c_str(), &width, NULL);
166
167 return width;
168 }
169
170
171
vulture_text_height(int font_id,std::string str)172 int vulture_text_height (int font_id, std::string str)
173 {
174 int height = 0;
175
176 if (!vulture_fonts[font_id].fontptr || str.empty())
177 return 0;
178
179 TTF_SizeText(vulture_fonts[font_id].fontptr, str.c_str(), NULL, &height);
180
181 return height;
182 }
183
184
185
vulture_get_lineheight(int font_id)186 int vulture_get_lineheight(int font_id)
187 {
188 if (font_id < VULTURE_MAX_FONTS && vulture_fonts[font_id].fontptr)
189 return vulture_fonts[font_id].lineheight;
190 return 0;
191 }
192
193
194
vulture_free_fonts()195 void vulture_free_fonts()
196 {
197 int font_id;
198
199 for (font_id = 0; font_id < VULTURE_MAX_FONTS; font_id++)
200 {
201 if (vulture_fonts[font_id].fontptr)
202 TTF_CloseFont(vulture_fonts[font_id].fontptr);
203 vulture_fonts[font_id].fontptr = NULL;
204 }
205
206 free(vulture_fonts);
207 vulture_fonts = NULL;
208
209 TTF_Quit();
210 }
211