Mercurial > hg > dmlib
view src/dmtext_bm.c @ 2091:3b3acb6b4ba0
Cleanups.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 28 Feb 2019 12:18:27 +0200 |
parents | 934cc71c97eb |
children | 92b93a12c014 |
line wrap: on
line source
/* * DMLib * -- Bitmap and TTF text & font support * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2012 Tecnic Software productions (TNSP) */ #include "dmtext.h" void dmDrawBMTextConst(SDL_Surface *screen, const DMBitmapFont *font, const BOOL condensed, const int mode, int xc, int yc, const char *fmt) { const char *ptr = fmt; DMUnscaledBlitFunc blit = dmGetUnscaledBlitFunc(font->glyphs->format, screen->format, mode); SDL_Surface surf; Uint8 *orig = font->glyphs->pixels; memcpy(&surf, font->glyphs, sizeof(SDL_Surface)); while (*ptr) { unsigned char ch = *ptr++; if (ch < font->maxglyph) { DMBitmapGlyph *glyph = &font->glyphMap[ch]; if (glyph->index >= 0) { surf.pixels = orig + glyph->index * font->gsize; surf.w = glyph->width; surf.h = glyph->height; blit(&surf, xc, yc, screen); xc += condensed ? glyph->width : font->width; } else xc += font->width; } else xc += font->width; } } void dmDrawBMTextVA(SDL_Surface *screen, const DMBitmapFont *font, const BOOL condensed, const int mode, const int xc, const int yc, const char *fmt, va_list ap) { char tmp[512]; vsnprintf(tmp, sizeof(tmp), fmt, ap); dmDrawBMTextConst(screen, font, condensed, mode, xc, yc, tmp); dmFree(tmp); } void dmDrawBMText(SDL_Surface *screen, const DMBitmapFont *font, const BOOL condensed, const int mode, const int xc, const int yc, const char *fmt, ...) { va_list ap; va_start(ap, fmt); dmDrawBMTextVA(screen, font, condensed, mode, xc, yc, fmt, ap); va_end(ap); } DMBitmapFont *dmNewBitmapFont(const int nglyphs, const int maxglyph, const int width, const int height, const int bpp) { DMBitmapFont *font = dmMalloc0(sizeof(DMBitmapFont)); if (font == NULL || (bpp != 8 && bpp != 32)) return NULL; font->width = width; font->height = height; font->nglyphs = nglyphs; font->maxglyph = maxglyph; if ((font->glyphMap = dmCalloc(font->maxglyph, sizeof(DMBitmapGlyph))) == NULL) goto error; if ((font->glyphs = SDL_CreateRGBSurfaceWithFormat( 0, width, height * (nglyphs + 1), bpp, bpp == 8 ? SDL_PIXELFORMAT_INDEX8 : SDL_PIXELFORMAT_RGBA32)) == NULL) goto error; font->gsize = font->height * font->glyphs->pitch; for (int i = 0; i < font->maxglyph; i++) { DMBitmapGlyph *glyph = &font->glyphMap[i]; glyph->width = width; glyph->height = height; glyph->index = -1; // means that this index is empty/unused } return font; error: dmFreeBitmapFont(font); return NULL; } int dmFreeBitmapFont(DMBitmapFont *font) { if (font == NULL) return DMERR_NULLPTR; if (font->glyphs != NULL) SDL_FreeSurface(font->glyphs); dmFree(font->glyphMap); dmFree(font); return DMERR_OK; } /* Set the palette for each glyph. While the function allows you to * specify 'start' and 'end' indices and palette array freely, you should * typically use DMFONT_NPALETTE size palette starting at index 0. */ int dmSetBitmapFontPalette(DMBitmapFont *font, const SDL_Color *pal, const int start, const int size) { if (font == NULL) return DMERR_NULLPTR; if (start < 0 || size < 1) return DMERR_INVALID_ARGS; SDL_SetPaletteColors(font->glyphs->format->palette, pal, start, size); return DMERR_OK; } //#define FN_DEBUG int dmLoadBitmapFont(DMResource *fp, DMBitmapFont **pfont) { DMBitmapFont *font; char magic[8]; Uint16 version, nglyphs, maxglyph; Uint8 width, height, bpp; BOOL tsfont = FALSE; // Check magic and version if (!dmf_read_str(fp, (Uint8 *) &magic, 6) || !dmf_read_le16(fp, &version)) return DMERR_FREAD; // Check if it is a legacy TSFONT file if (memcmp(magic, TSFONT_MAGIC, 6) == 0) { // Yep, we handle these a bit differently int encoding = dmfgetc(fp); tsfont = TRUE; #ifdef FN_DEBUG fprintf(stderr, "TSFONT v%d.%d (0x%04x), encoding=%d\n", version >> 8, version & 0xff, version, encoding); #endif if (version > TSFONT_VERSION || version < 0x0200) return DMERR_VERSION; // There were only two encodings, 0 = none and 1 = RLE // of which RLE was never actually used ... derp. if (encoding != 0) return DMERR_NOT_SUPPORTED; } else if (memcmp(magic, DMFONT_MAGIC, 6) == 0) { #ifdef FN_DEBUG fprintf(stderr, "DMFONT v%d.%d (0x%04x)\n", version >> 8, version & 0xff, version); #endif if (version > DMFONT_VERSION) return DMERR_VERSION; } else return DMERR_INVALID; // Read other header data if (tsfont) { // TSFONT has number of glyphs and dimensions Uint8 tmp, unused; if (!dmf_read_byte(fp, &tmp) || !dmf_read_byte(fp, &width) || !dmf_read_byte(fp, &height) || !dmf_read_byte(fp, &unused)) return DMERR_FREAD; nglyphs = tmp; maxglyph = 256; bpp = 8; // Very old TSFONTs have some extra data that is not used // .. can't actually even remember what it was for. if (version == 0x0200) { for (int i = 0; i < 32; i++) { if (!dmf_read_byte(fp, &unused)) return DMERR_FREAD; } } } else { // DMFONT has Uint16 values for nglyphs and maxglyph, plus BPP if (!dmf_read_le16(fp, &nglyphs) || !dmf_read_le16(fp, &maxglyph) || !dmf_read_byte(fp, &width) || !dmf_read_byte(fp, &height) || !dmf_read_byte(fp, &bpp)) return DMERR_FREAD; } #ifdef FN_DEBUG fprintf(stderr, "nglyphs=%d, maxglyph=%d, width=%d, height=%d, bpp=%d\n", nglyphs, maxglyph, width, height, bpp); #endif if (width < DMFONT_MIN_WIDTH || height < DMFONT_MIN_HEIGHT || width > DMFONT_MAX_WIDTH || height > DMFONT_MAX_HEIGHT || nglyphs > DMFONT_MAX_GLYPHS || nglyphs > maxglyph || maxglyph > DMFONT_MAX_GLYPHS || maxglyph < 1) return DMERR_INVALID_DATA; if (bpp != 8 && bpp != 32) return DMERR_NOT_SUPPORTED; // Allocate font if ((*pfont = font = dmNewBitmapFont(nglyphs, maxglyph, width, height, bpp)) == NULL) return DMERR_MALLOC; // Setup palette for 8bpp fonts if (bpp == 8) { SDL_Color pal[DMFONT_NPALETTE]; for (int n = 0; n < DMFONT_NPALETTE; n++) { pal[n].r = pal[n].g = pal[n].b = n > 0 ? 255 : 0; pal[n].a = n > 0 ? 255 : 0; } dmSetBitmapFontPalette(font, pal, 0, DMFONT_NPALETTE); } // Read glyph data, if any for (int i = 0; i < nglyphs; i++) { DMBitmapGlyph *glyph; Uint8 gwidth, gheight; Uint16 gindex; Uint8 *pixels; // TSFONT format has only byte sized index if (tsfont) gindex = dmfgetc(fp); else dmf_read_le16(fp, &gindex); // Read dimensions if (!dmf_read_byte(fp, &gwidth) || !dmf_read_byte(fp, &gheight)) return DMERR_FREAD; #ifdef FN_DEBUG fprintf(stderr, "#%d @ %d - %d x %d\n", i, gindex, gwidth, gheight); #endif // Check the glyph data if (gwidth < DMFONT_MIN_WIDTH || gheight < DMFONT_MIN_HEIGHT || gwidth > DMFONT_MAX_WIDTH || gheight > DMFONT_MAX_HEIGHT || gwidth > width || gheight > height || gindex >= maxglyph) return DMERR_INVALID_DATA; // Set glyph data glyph = &font->glyphMap[gindex]; glyph->width = gwidth; glyph->height = gheight; glyph->index = i; // Read pixel data pixels = font->glyphs->pixels + (i * font->gsize); for (int y = 0; y < glyph->height; y++) { if (dmfread(pixels, font->glyphs->format->BytesPerPixel, glyph->width, fp) != (size_t) glyph->width) return DMERR_FREAD; pixels += font->glyphs->pitch; } } return DMERR_OK; }