Mercurial > hg > dmlib
view tools/fontconv.c @ 1272:acae5f8ebc67
Fix build process.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 19 May 2016 12:08:16 +0300 |
parents | 5b8245e5f785 |
children | 370c40e0847f |
line wrap: on
line source
/* * fontconv - Convert bitmap fonts * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2012-2015 Tecnic Software productions (TNSP) * * Please read file 'COPYING' for information on license and distribution. */ #include <stdio.h> #include "dmlib.h" #include "dmargs.h" #include "dmfile.h" #include "dmimage.h" #include "dmtext.h" #include "dmresw.h" char *optInFilename = NULL, *optOutFilename = NULL; int optSplitWidth = 8, optSplitHeight = 8; SDL_Color optColor = { 255, 255, 255, 100 }; static const DMOptArg optList[] = { { 0, '?', "help", "Show this help", OPT_NONE }, { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, { 2, 'o', "output", "Set output filename", OPT_ARGREQ }, { 3, 's', "size", "Set glyph dimensions (-s W:H) for image->font conversion", OPT_ARGREQ }, #ifdef DM_GFX_TTF_TEXT { 4, 'c', "color", "TTF font rendering color (def: 0xFFFFFF)", OPT_ARGREQ }, #endif }; const int optListN = sizeof(optList) / sizeof(optList[0]); BOOL argHandleOpt(const int optN, char *optArg, char *currArg) { switch (optN) { case 0: dmPrintBanner(stdout, dmProgName, "[options] <sourcefile.(ttf|fnt|dmf|png)> <outputfile.dmf>"); dmArgsPrintHelp(stdout, optList, optListN, 0); printf( "\n" "This utility can be used to convert TSFONT files to bitmap DMFONT (DMF)\n" "files, render TrueType TTF to DMFONT at desired glyph resolution, or\n" "cut a PNG (or JPEG) image to glyphs of desired size.\n"); exit(0); break; case 1: dmVerbosity++; break; case 2: optOutFilename = optArg; break; case 3: { int w, h; if (sscanf(optArg, "%d:%d", &w, &h) != 2) { dmErrorMsg("Invalid argument for -s option, '%s'.\n", optArg); return FALSE; } if (w < DMFONT_MIN_WIDTH || w > DMFONT_MAX_WIDTH || h < DMFONT_MIN_HEIGHT || h > DMFONT_MAX_HEIGHT) { dmErrorMsg("Invalid dimensions, must be %d < W %d, %d < H < %d.\n", DMFONT_MIN_WIDTH , DMFONT_MAX_WIDTH, DMFONT_MIN_HEIGHT , DMFONT_MAX_HEIGHT); return FALSE; } optSplitWidth = w; optSplitHeight = h; } break; case 4: { unsigned int colR, colG, colB, colA = 100; if (optArg[0] == '#' || optArg[0] == '$') optArg++; else if (optArg[0] == '0' && optArg[1] == 'x') optArg += 2; if (sscanf(optArg, "%02x%02x%02x", &colR, &colG, &colB) != 3 && sscanf(optArg, "%02x%02x%02x%02x", &colR, &colG, &colB, &colA) != 4) { dmErrorMsg("Invalid RGB hex representation '%s'.\n", optArg); return FALSE; } optColor.r = colR; optColor.g = colG; optColor.b = colB; optColor.unused = colA; } break; default: dmErrorMsg("Unknown argument '%s'.\n", currArg); return FALSE; } return TRUE; } BOOL argHandleFile(char *currArg) { if (!optInFilename) optInFilename = currArg; else if (!optOutFilename) optOutFilename = currArg; else { dmErrorMsg("Too many filename arguments, '%s'\n", currArg); return FALSE; } return TRUE; } int dmCreateBitmapFontFromImage(SDL_Surface *image, int width, int height, DMBitmapFont **pfont) { int nglyph, xc, yc, xglyphs, yglyphs; DMBitmapFont *font; if (image->w < width || width < 2 || image->h < height || height < 2) return DMERR_INVALID_ARGS; xglyphs = image->w / width; yglyphs = image->h / height; if ((font = dmNewBitmapFont(xglyphs * yglyphs, width, height)) == NULL) return DMERR_MALLOC; dmMsg(1, "%d x %d split as %d x %d blocks => %d x %d = %d glyphs.\n", image->w, image->h, width, height, xglyphs, yglyphs, xglyphs * yglyphs); nglyph = 0; for (yc = 0; yc < yglyphs; yc++) for (xc = 0; xc < xglyphs; xc++) { SDL_Surface *glyph = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, image->format->BitsPerPixel, image->format->Rmask, image->format->Gmask, image->format->Bmask, image->format->Amask); if (glyph == NULL) { dmFreeBitmapFont(font); return DMERR_MALLOC; } SDL_Rect r; r.x = xc * width; r.y = yc * height; r.w = width; r.h = height; SDL_BlitSurface(image, &r, glyph, NULL); font->glyphs[nglyph++] = glyph; } *pfont = font; return DMERR_OK; } int dmSaveBitmapFont(DMResource *res, DMBitmapFont *font) { SDL_Surface *glyph; int maxglyph, nglyphs, n; if (font == NULL) return DMERR_NULLPTR; if (font->nglyphs > DMFONT_MAX_GLYPHS || font->width > DMFONT_MAX_WIDTH || font->height > DMFONT_MAX_HEIGHT || font->width < DMFONT_MIN_WIDTH || font->height < DMFONT_MIN_HEIGHT) return DMERR_INVALID_DATA; // Count number of actually existing glyphs for (maxglyph = nglyphs = n = 0; n < font->nglyphs; n++) { SDL_Surface *glyph = font->glyphs[n]; if (glyph != NULL) { maxglyph = n; if (glyph->w < DMFONT_MIN_WIDTH || glyph->h < DMFONT_MIN_HEIGHT || glyph->w > DMFONT_MAX_WIDTH || glyph->h > DMFONT_MAX_HEIGHT) continue; nglyphs++; } } if (nglyphs == 0) return DMERR_INVALID_DATA; // Write the DMFONT header if (!dmf_write_str(res, (Uint8 *) DMFONT_MAGIC, 6)) return DMERR_FWRITE; dmf_write_le16(res, DMFONT_VERSION); dmf_write_le16(res, nglyphs); dmf_write_le16(res, maxglyph + 1); dmfputc(font->width, res); dmfputc(font->height, res); // Store glyph format data glyph = font->glyphs[maxglyph]; dmfputc(glyph->format->BitsPerPixel, res); dmf_write_le32(res, glyph->format->Rmask); dmf_write_le32(res, glyph->format->Gmask); dmf_write_le32(res, glyph->format->Bmask); dmf_write_le32(res, glyph->format->Amask); for (n = 0; n < font->nglyphs; n++) { glyph = font->glyphs[n]; if (glyph != NULL) { int y; Uint8 *pixels = glyph->pixels; if (glyph->w < DMFONT_MIN_WIDTH || glyph->h < DMFONT_MIN_HEIGHT || glyph->w > DMFONT_MAX_WIDTH || glyph->h > DMFONT_MAX_HEIGHT) continue; // Each glyph has its table index and w/h stored dmf_write_le16(res, n); dmfputc(glyph->w, res); dmfputc(glyph->h, res); // Write the pixel data for (y = 0; y < glyph->h; y++) { if (dmfwrite(pixels, glyph->format->BytesPerPixel, glyph->w, res) != (size_t) glyph->w) return DMERR_FWRITE; pixels += glyph->pitch; } } } return DMERR_OK; } int main(int argc, char *argv[]) { DMResource *inFile = NULL, *outFile = NULL; DMBitmapFont *font = NULL; SDL_Surface *fontbmap = NULL; int res; #ifdef DM_GFX_TTF_TEXT BOOL initTTF = FALSE; TTF_Font *ttf = NULL; #endif dmInitProg("fontconv", "Bitmap font converter", "0.3", NULL, NULL); dmVerbosity = 1; // Parse arguments if (!dmArgsProcess(argc, argv, optList, optListN, argHandleOpt, argHandleFile, OPTH_BAILOUT)) exit(1); // Check arguments if (!optInFilename || !optOutFilename) { dmErrorMsg("Input or output file not specified!\n"); return 1; } #ifdef DM_GFX_TTF_TEXT if (TTF_Init() < 0) { dmErrorMsg("Could not initialize FreeType/TTF: %s\n", SDL_GetError()); goto error_exit; } initTTF = TRUE; #endif // Open the source file if ((res = dmf_create_stdio(optInFilename, "rb", &inFile)) != DMERR_OK) { dmErrorMsg("Error opening input file '%s', %d: %s\n", optInFilename, res, dmErrorStr(res)); return 1; } if ((res = dmLoadBitmapFont(inFile, &font)) == DMERR_OK) { dmMsg(1, "Input is a TSFONT/DMFONT font file.\n"); } #ifdef DM_GFX_TTF_TEXT else if ((ttf = TTF_OpenFont(optInFilename, optSplitWidth)) != NULL) { int i; dmMsg(1, "Input is a TTF TrueType font, rendering at %d x %d.\n", optSplitWidth, optSplitHeight); TTF_SetFontStyle(ttf, TTF_STYLE_NORMAL); if ((font = dmNewBitmapFont(256, optSplitWidth - 1, optSplitHeight+4)) == NULL) { goto error_exit; } for (i = 0; i < 255; i++) { char str[2]; str[0] = i; str[1] = 0; font->glyphs[i] = TTF_RenderText_Blended(ttf, str, optColor); } } #endif else { dmfreset(inFile); if ((fontbmap = dmLoadImage(inFile)) == NULL) { dmErrorMsg("Could not load image file '%s'.\n", optInFilename); goto error_exit; } dmMsg(1, "Input is a bitmap image (%d x %d, %d bpp), splitting to %d x %d.\n", fontbmap->w, fontbmap->h, fontbmap->format->BitsPerPixel, optSplitWidth, optSplitHeight); if ((res = dmCreateBitmapFontFromImage(fontbmap, optSplitWidth, optSplitHeight, &font)) != DMERR_OK) { dmErrorMsg("Could not create a font from image, %d: %s\n", res, dmErrorStr(res)); goto error_exit; } } if (font == NULL) { dmErrorMsg("No font loaded.\n"); goto error_exit; } dmMsg(1, "Outputting a DMFONT format bitmap font.\n"); if ((res = dmf_create_stdio(optOutFilename, "wb", &outFile)) != DMERR_OK) { dmErrorMsg("Error creating file '%s', %d: %s\n", optInFilename, res, dmErrorStr(res)); goto error_exit; } res = dmSaveBitmapFont(outFile, font); dmf_close(outFile); if (res != DMERR_OK) { dmErrorMsg("Error saving font, %d: %s\n", res, dmErrorStr(res)); } error_exit: #ifdef DM_GFX_TTF_TEXT if (initTTF) TTF_Quit(); #endif dmf_close(inFile); dmFreeBitmapFont(font); SDL_FreeSurface(fontbmap); return 0; }