Mercurial > hg > dmlib
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; |