Mercurial > hg > dmlib
view src/dmtext_bm.c @ 1531:260bf529a8f2
Implement current len/offs push/pop for growbuf.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 12 May 2018 03:23:32 +0300 |
parents | e06abfde6c39 |
children | 5e5f75b45f8d |
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, DMBitmapFont *font, BOOL condensed, int mode, int xc, int yc, const char *fmt) { const char *ptr = fmt; DMUnscaledBlitFunc blit = NULL; while (*ptr) { int ch = *ptr++; SDL_Surface *glyph; if (ch >= 0 && ch < font->nglyphs && (glyph = font->glyphs[ch]) != NULL) { if (blit == NULL) blit = dmGetUnscaledBlitFunc(glyph->format, screen->format, mode); if (blit != NULL) { blit(glyph, xc, yc, screen); xc += condensed ? glyph->w : font->width; } } else xc += font->width; } } void dmDrawBMTextVA(SDL_Surface *screen, DMBitmapFont *font, BOOL condensed, int mode, int xc, 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, DMBitmapFont *font, BOOL condensed, int mode, int xc, 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(int nglyphs, int width, int height) { DMBitmapFont *font = dmMalloc0(sizeof(DMBitmapFont)); if (font == NULL) return NULL; font->width = width; font->height = height; font->nglyphs = nglyphs; font->glyphs = dmCalloc(nglyphs, sizeof(SDL_Surface *)); if (font->glyphs == NULL) { dmFree(font); return NULL; } return font; } int dmFreeBitmapFont(DMBitmapFont *font) { int i; if (font == NULL) return DMERR_NULLPTR; for (i = 0; i < font->nglyphs; i++) { if (font->glyphs[i] != NULL) { SDL_FreeSurface(font->glyphs[i]); font->glyphs[i] = NULL; } } 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, SDL_Color *pal, int start, int size) { int i; if (font == NULL) return DMERR_NULLPTR; if (start < 0 || size < 1) return DMERR_INVALID_ARGS; for (i = 0; i < font->nglyphs; i++) { SDL_Surface *glyph = font->glyphs[i]; if (glyph != NULL) { SDL_SetColors(glyph, pal, start, size); } } return DMERR_OK; } //#define FN_DEBUG int dmLoadBitmapFont(DMResource *res, DMBitmapFont **pfont) { DMBitmapFont *font; char magic[8]; Uint16 version, nglyphs, maxglyph; int width, height; BOOL tsfont = FALSE; // Check magic and version dmf_read_str(res, (Uint8 *) &magic, 6); dmf_read_le16(res, &version); // 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(res); tsfont = TRUE; if (version > TSFONT_VERSION) return DMERR_VERSION; #ifdef FN_DEBUG fprintf(stderr, "TSFONT v%d.%d (0x%04x), encoding=%d\n", version >> 8, version & 0xff, version, encoding); #endif // 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) return DMERR_INVALID; if (version > DMFONT_VERSION) return DMERR_VERSION; } // Read other header data if (tsfont) { // TSFONT only has number of glyphs stored in the file nglyphs = dmfgetc(res); // Maximum glyph number maxglyph = 256; } else { dmf_read_le16(res, &nglyphs); dmf_read_le16(res, &maxglyph); } width = dmfgetc(res); height = dmfgetc(res); #ifdef FN_DEBUG fprintf(stderr, "nglyphs=%d (0x%02x), maxglyph=%d (0x%02x) width=%d, height=%d\n", nglyphs, nglyphs, maxglyph, maxglyph, width, height); #endif if (tsfont) { // TSFONT color assignments (boolean) .. we discard this. dmfgetc(res); // Very old TSFONTs have some extra data that is not used // .. can't actually even remember what it was for. if (version == 0x0200) { int i; for (i = 0; i < 32; i++) dmfgetc(res); } } if (width < DMFONT_MIN_WIDTH || height < DMFONT_MIN_HEIGHT || width > DMFONT_MAX_WIDTH || height > DMFONT_MAX_HEIGHT || nglyphs > DMFONT_MAX_GLYPHS || maxglyph > DMFONT_MAX_GLYPHS || maxglyph < 1) return DMERR_INVALID_DATA; // Allocate font if ((*pfont = font = dmNewBitmapFont(maxglyph, width, height)) == NULL) return DMERR_MALLOC; // Read glyph data, if any if (nglyphs > 0) { int n, i; Uint32 BitsPerPixel, Rmask, Gmask, Bmask, Amask; SDL_Color pal[DMFONT_NPALETTE]; // Setup palette for 8bpp fonts for (n = 0; n < DMFONT_NPALETTE; n++) { pal[n].r = pal[n].g = pal[n].b = 0; pal[n].unused = n > 0 ? 255 : 0; } if (tsfont) { BitsPerPixel = 8; Rmask = Gmask = Bmask = Amask = 0; } else { BitsPerPixel = dmfgetc(res); dmf_read_le32(res, &Rmask); dmf_read_le32(res, &Gmask); dmf_read_le32(res, &Bmask); dmf_read_le32(res, &Amask); } for (i = 0; i < nglyphs; i++) { int y; Uint16 index; Uint8 *pixels; SDL_Surface *glyph; // TSFONT format has only byte sized index if (tsfont) index = dmfgetc(res); else dmf_read_le16(res, &index); // Read dimensions width = dmfgetc(res); height = dmfgetc(res); #ifdef FN_DEBUG fprintf(stderr, "#%d @ %d - w=%d, h=%d\n", i, index, width, height); #endif if (width < DMFONT_MIN_WIDTH || height < DMFONT_MIN_HEIGHT || width > DMFONT_MAX_WIDTH || height > DMFONT_MAX_HEIGHT || index >= maxglyph) return DMERR_INVALID_DATA; // Allocate bitmap font->glyphs[index] = glyph = SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, BitsPerPixel, Rmask, Gmask, Bmask, Amask); if (glyph == NULL) return DMERR_MALLOC; if (BitsPerPixel == 8) SDL_SetColors(glyph, pal, 0, DMFONT_NPALETTE); // Read pixel data pixels = glyph->pixels; for (y = 0; y < glyph->h; y++) { if (dmfread(pixels, glyph->format->BytesPerPixel, glyph->w, res) != (size_t) glyph->w) return DMERR_FREAD; pixels += glyph->pitch; } } } return DMERR_OK; }