comparison dmtext_bm.c @ 89:b10884934aca

Various improvements in bitmapped font support, and addition of legacy TSFONT loading support (untested as of now).
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 02 Oct 2012 15:52:44 +0300
parents 7d201aed1fd9
children e1e308167991
comparison
equal deleted inserted replaced
88:aa9fbdbcea70 89:b10884934aca
67 dmDrawBMTextVA(screen, font, mode, xc, yc, fmt, ap); 67 dmDrawBMTextVA(screen, font, mode, xc, yc, fmt, ap);
68 va_end(ap); 68 va_end(ap);
69 } 69 }
70 70
71 71
72 DMBitmapFont *dmNewBitmapFont(int nglyphs) 72 DMBitmapFont *dmNewBitmapFont(int nglyphs, int width, int height)
73 { 73 {
74 DMBitmapFont *font = dmMalloc0(sizeof(DMBitmapFont)); 74 DMBitmapFont *font = dmMalloc0(sizeof(DMBitmapFont));
75 if (font == NULL) 75 if (font == NULL)
76 return NULL; 76 return NULL;
77 77
78 font->width = width;
79 font->height = height;
78 font->nglyphs = nglyphs; 80 font->nglyphs = nglyphs;
79 font->glyphs = dmCalloc(nglyphs, sizeof(SDL_Surface *)); 81 font->glyphs = dmCalloc(nglyphs, sizeof(SDL_Surface *));
80 82 if (font->glyphs == NULL)
83 {
84 dmFree(font);
85 return NULL;
86 }
87
81 return font; 88 return font;
82 } 89 }
83 90
84 91
85 int dmFreeBitmapFont(DMBitmapFont *font) 92 int dmFreeBitmapFont(DMBitmapFont *font)
112 return DMERR_INVALID_ARGS; 119 return DMERR_INVALID_ARGS;
113 120
114 xglyphs = image->w / width; 121 xglyphs = image->w / width;
115 yglyphs = image->h / height; 122 yglyphs = image->h / height;
116 123
117 if ((font = dmNewBitmapFont(xglyphs * yglyphs)) == NULL) 124 if ((font = dmNewBitmapFont(xglyphs * yglyphs, width, height)) == NULL)
118 return DMERR_MALLOC; 125 return DMERR_MALLOC;
119
120 font->width = width;
121 font->height = height;
122 126
123 /* 127 /*
124 fprintf(stderr, "%d x %d split as %d x %d blocks => %d x %d = %d glyphs\n", 128 fprintf(stderr, "%d x %d split as %d x %d blocks => %d x %d = %d glyphs\n",
125 image->w, image->h, 129 image->w, image->h,
126 width, height, 130 width, height,
162 166
163 int dmLoadBitmapFont(DMResource *res, DMBitmapFont **pfont) 167 int dmLoadBitmapFont(DMResource *res, DMBitmapFont **pfont)
164 { 168 {
165 DMBitmapFont *font; 169 DMBitmapFont *font;
166 char magic[8]; 170 char magic[8];
167 Uint16 version; 171 Uint16 version, nglyphs, maxglyph;
168 Uint32 width, height, nglyphs; 172 int width, height;
173 BOOL tsfont = FALSE;
169 174
170 // Check magic and version 175 // Check magic and version
171 dmf_read_str(res, (Uint8 *) &magic, 6); 176 dmf_read_str(res, (Uint8 *) &magic, 6);
172 dmf_read_le16(res, &version); 177 dmf_read_le16(res, &version);
173 178
174 if (memcmp(magic, DMFONT_MAGIC, 6) != 0) 179 // Check if it is a legacy TSFONT file
175 return DMERR_INVALID; 180 if (memcmp(magic, TSFONT_MAGIC, 6) == 0)
176 181 {
177 if (version != DMFONT_VERSION) 182 // Yep, we handle these a bit differently
178 return DMERR_VERSION; 183 int encoding = dmfgetc(res);
184 tsfont = TRUE;
185
186 if (version > TSFONT_VERSION)
187 return DMERR_VERSION;
188
189 // There were only two encodings, 0 = none and 1 = RLE
190 // of which RLE was never actually used ... derp.
191 if (encoding != 0)
192 return DMERR_NOT_SUPPORTED;
193 }
194 else
195 {
196 if (memcmp(magic, DMFONT_MAGIC, 6) != 0)
197 return DMERR_INVALID;
198
199 if (version > DMFONT_VERSION)
200 return DMERR_VERSION;
201 }
179 202
180 // Check other data 203 // Check other data
181 dmf_read_le32(res, &width); 204 if (tsfont)
182 dmf_read_le32(res, &height); 205 {
183 dmf_read_le32(res, &nglyphs); 206 nglyphs = dmfgetc(res);
184 207 maxglyph = 256;
185 if (width > 128 || height > 128 || nglyphs > 1024) 208 }
209 else
210 {
211 dmf_read_le16(res, &nglyphs);
212 dmf_read_le16(res, &maxglyph);
213 }
214
215 width = dmfgetc(res);
216 height = dmfgetc(res);
217
218 if (tsfont)
219 {
220 // TSFONT color assigns (boolean) .. we discard this.
221 dmfgetc(res);
222 }
223
224 if (width < DMFONT_MIN_WIDTH ||
225 height < DMFONT_MIN_HEIGHT ||
226 width > DMFONT_MAX_WIDTH ||
227 height > DMFONT_MAX_HEIGHT ||
228 nglyphs > DMFONT_MAX_GLYPHS ||
229 maxglyph > DMFONT_MAX_GLYPHS ||
230 maxglyph < 1)
186 return DMERR_INVALID_DATA; 231 return DMERR_INVALID_DATA;
187 232
188 // Allocate font 233 // Allocate font
189 if ((*pfont = font = dmNewBitmapFont(nglyphs)) == NULL) 234 if ((*pfont = font = dmNewBitmapFont(maxglyph, width, height)) == NULL)
190 return DMERR_MALLOC; 235 return DMERR_MALLOC;
191
192 font->width = width;
193 font->height = height;
194 font->nglyphs = nglyphs;
195 236
196 // Read glyph data, if any 237 // Read glyph data, if any
197 if (nglyphs > 0) 238 if (nglyphs > 0)
198 { 239 {
199 Uint32 i, BitsPerPixel, Rmask, Gmask, Bmask, Amask, pitch; 240 Uint32 i, BitsPerPixel, Rmask, Gmask, Bmask, Amask;
200 241
201 BitsPerPixel = dmfgetc(res); 242 if (tsfont)
202 dmf_read_le32(res, &Rmask); 243 {
203 dmf_read_le32(res, &Gmask); 244 BitsPerPixel = 8;
204 dmf_read_le32(res, &Bmask); 245 Rmask = Gmask = Bmask = Amask = 0;
205 dmf_read_le32(res, &Amask); 246 }
247 else
248 {
249 BitsPerPixel = dmfgetc(res);
250 dmf_read_le32(res, &Rmask);
251 dmf_read_le32(res, &Gmask);
252 dmf_read_le32(res, &Bmask);
253 dmf_read_le32(res, &Amask);
254 }
206 255
207 for (i = 0; i < nglyphs; i++) 256 for (i = 0; i < nglyphs; i++)
208 { 257 {
209 int y; 258 int y;
259 Uint16 index;
210 Uint8 *pixels; 260 Uint8 *pixels;
211 SDL_Surface *glyph; 261 SDL_Surface *glyph;
212 dmf_read_le32(res, &width); 262
213 dmf_read_le32(res, &height); 263 if (tsfont)
214 dmf_read_le32(res, &pitch); 264 index = dmfgetc(res);
265 else
266 dmf_read_le16(res, &index);
267
268 width = dmfgetc(res);
269 height = dmfgetc(res);
215 270
216 font->glyphs[i] = glyph = SDL_CreateRGBSurface( 271 if (width < DMFONT_MIN_WIDTH ||
272 height < DMFONT_MIN_HEIGHT ||
273 width > DMFONT_MAX_WIDTH ||
274 height > DMFONT_MAX_HEIGHT ||
275 index > DMFONT_MAX_GLYPHS)
276 return DMERR_INVALID_DATA;
277
278 font->glyphs[index] = glyph = SDL_CreateRGBSurface(
217 SDL_SWSURFACE, width, height, 279 SDL_SWSURFACE, width, height,
218 BitsPerPixel, Rmask, Gmask, 280 BitsPerPixel, Rmask, Gmask,
219 Bmask, 281 Bmask,
220 Amask); 282 Amask);
221 283
223 return DMERR_MALLOC; 285 return DMERR_MALLOC;
224 286
225 pixels = glyph->pixels; 287 pixels = glyph->pixels;
226 for (y = 0; y < glyph->h; y++) 288 for (y = 0; y < glyph->h; y++)
227 { 289 {
228 if (dmfread(pixels, glyph->format->BytesPerPixel, glyph->w, res) != glyph->w) 290 if (dmfread(pixels, glyph->format->BytesPerPixel, glyph->w, res) != (size_t) glyph->w)
229 return DMERR_FREAD; 291 return DMERR_FREAD;
230 pixels += glyph->pitch; 292 pixels += glyph->pitch;
231 } 293 }
232 } 294 }
233 } 295 }
236 } 298 }
237 299
238 300
239 int dmSaveBitmapFont(DMResource *res, DMBitmapFont *font) 301 int dmSaveBitmapFont(DMResource *res, DMBitmapFont *font)
240 { 302 {
303 int count, n;
241 if (font == NULL) 304 if (font == NULL)
242 return DMERR_NULLPTR; 305 return DMERR_NULLPTR;
243 306
307 if (font->nglyphs > DMFONT_MAX_GLYPHS ||
308 font->width > DMFONT_MAX_WIDTH ||
309 font->height > DMFONT_MAX_HEIGHT ||
310 font->width < DMFONT_MIN_WIDTH ||
311 font->height < DMFONT_MIN_HEIGHT)
312 return DMERR_INVALID_DATA;
313
314 // Count number of actually existing glyphs
315 for (count = n = 0; n < font->nglyphs; n++)
316 if (font->glyphs[n] != NULL) count++;
317
318 // Write the DMFONT header
244 if (!dmf_write_str(res, (Uint8 *) DMFONT_MAGIC, 6)) 319 if (!dmf_write_str(res, (Uint8 *) DMFONT_MAGIC, 6))
245 return DMERR_FWRITE; 320 return DMERR_FWRITE;
246 321
247 dmf_write_le16(res, DMFONT_VERSION); 322 dmf_write_le16(res, DMFONT_VERSION);
248 dmf_write_le32(res, font->width); 323 dmf_write_le16(res, count); // # of glyphs actually
249 dmf_write_le32(res, font->height); 324 dmf_write_le16(res, font->nglyphs); // Max glyph #
250 dmf_write_le32(res, font->nglyphs); 325 dmfputc(font->width, res);
326 dmfputc(font->height, res);
251 327
252 if (font->nglyphs > 0) 328 if (font->nglyphs > 0)
253 { 329 {
254 int i; 330 int i;
255 SDL_Surface *glyph = font->glyphs[0]; 331 SDL_Surface *glyph = font->glyphs[0];
256 332
333 // If there are actual glyphs stored, save thi
257 dmfputc(glyph->format->BitsPerPixel, res); 334 dmfputc(glyph->format->BitsPerPixel, res);
258 dmf_write_le32(res, glyph->format->Rmask); 335 dmf_write_le32(res, glyph->format->Rmask);
259 dmf_write_le32(res, glyph->format->Gmask); 336 dmf_write_le32(res, glyph->format->Gmask);
260 dmf_write_le32(res, glyph->format->Bmask); 337 dmf_write_le32(res, glyph->format->Bmask);
261 dmf_write_le32(res, glyph->format->Amask); 338 dmf_write_le32(res, glyph->format->Amask);
262 339
263 for (i = 0; i < font->nglyphs; i++) 340 for (i = 0; i < font->nglyphs; i++)
264 { 341 {
265 int y;
266 glyph = font->glyphs[i]; 342 glyph = font->glyphs[i];
267 Uint8 *pixels = glyph->pixels; 343 if (glyph != NULL)
268
269 dmf_write_le32(res, glyph->w);
270 dmf_write_le32(res, glyph->h);
271
272 for (y = 0; y < glyph->h; y++)
273 { 344 {
274 if (dmfwrite(pixels, glyph->format->BytesPerPixel, glyph->w, res) != glyph->w) 345 int y;
275 return DMERR_FWRITE; 346 Uint8 *pixels = glyph->pixels;
276 pixels += glyph->pitch; 347
348 if (glyph->w < DMFONT_MIN_WIDTH ||
349 glyph->h < DMFONT_MIN_HEIGHT ||
350 glyph->w > DMFONT_MAX_WIDTH ||
351 glyph->h > DMFONT_MAX_HEIGHT)
352 return DMERR_INVALID_DATA;
353
354 // Each glyph has its table index and w/h stored
355 dmf_write_le16(res, i);
356 dmf_write_le16(res, glyph->w);
357 dmf_write_le16(res, glyph->h);
358
359 // Write the pixel data
360 for (y = 0; y < glyph->h; y++)
361 {
362 if (dmfwrite(pixels, glyph->format->BytesPerPixel, glyph->w, res) != (size_t) glyph->w)
363 return DMERR_FWRITE;
364 pixels += glyph->pitch;
365 }
277 } 366 }
278 } 367 }
279 } 368 }
280 369
281 return DMERR_OK; 370 return DMERR_OK;