Mercurial > hg > dmlib
diff fontconv.c @ 160:67d2cba58a87
Add fontconv tool.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 06 Oct 2012 07:29:26 +0300 |
parents | |
children | 63ff0fb944cd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fontconv.c Sat Oct 06 07:29:26 2012 +0300 @@ -0,0 +1,251 @@ +/* + * fontconv - Convert bitmap fonts + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#include <stdio.h> +#include <errno.h> +#include "dmlib.h" +#include "dmargs.h" +#include "dmfile.h" +#include "dmimage.h" +#include "dmtext.h" + +enum +{ + OFMT_DMFONT, +}; + +enum +{ + IFMT_IMAGE, + IFMT_FONT, +}; + +char *optInFilename = NULL, *optOutFilename = NULL; +int optOutFormat = OFMT_DMFONT, + optSplitWidth = 8, + optSplitHeight = 8; + + +DMOptArg optList[] = +{ + { 0, '?', "help", "Show this help", OPT_NONE }, + { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, + { 2, 'o', "output", "Output file (default stdout)", OPT_ARGREQ }, + { 3, 's', "size", "Set glyph dimensions (-s WxH) for image->font conversion", OPT_ARGREQ }, +}; + +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]"); + + dmArgsPrintHelp(stdout, optList, optListN); + exit(0); + break; + + case 1: + dmVerbosity++; + break; + + case 2: + optOutFilename = optArg; + break; + + case 3: + { + int w, h; + if (sscanf(optArg, "%dx%d", &w, &h) != 2) + { + dmError("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) + { + dmError("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; + + default: + dmError("Unknown argument '%s'.\n", currArg); + return FALSE; + } + + return TRUE; +} + + +BOOL argHandleFile(char *currArg) +{ + if (!optInFilename) + optInFilename = currArg; + else + { + dmError("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 < 4 || image->h < height || height < 4) + return DMERR_INVALID_ARGS; + + xglyphs = image->w / width; + yglyphs = image->h / height; + + if ((font = dmNewBitmapFont(xglyphs * yglyphs, width, height)) == NULL) + return DMERR_MALLOC; + +/* + fprintf(stderr, "%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 main(int argc, char *argv[]) +{ + DMResource *inFile = NULL; + DMBitmapFont *font = NULL; + int res; + + dmInitProg("fontconv", "Bitmap font converter", "0.2", NULL, NULL); + dmVerbosity = 1; + + // Parse arguments + if (!dmArgsProcess(argc, argv, optList, optListN, + argHandleOpt, argHandleFile, TRUE)) + exit(1); + + // Check arguments + if (!optInFilename) + { + dmError("Input or output file not specified!\n"); + return 1; + } + + // Open the source file + if ((inFile = dmf_create_stdio(optInFilename, "rb")) == NULL) + { + dmError("Error opening input file '%s', %d: %s\n", + optInFilename, errno, strerror(errno)); + return 1; + } + + if ((res = dmLoadBitmapFont(inFile, &font)) != DMERR_OK) + { + SDL_Surface *fontbmap; + + dmfseek(inFile, 0L, SEEK_SET); + + if ((fontbmap = dmLoadImage(inFile)) == NULL) + { + dmError("Could not load image file '%s'.\n", optInFilename); + goto error_exit; + } + + if ((res = dmCreateBitmapFontFromImage(fontbmap, optSplitWidth, optSplitHeight, &font)) != DMERR_OK) + { + dmError("Could not create a font from image, %d: %s\n", + res, dmErrorStr(res)); + goto error_exit; + } + SDL_FreeSurface(fontbmap); + } + + if (font == NULL) + { + dmError("No font loaded.\n"); + goto error_exit; + } + + if (optOutFormat == OFMT_DMFONT) + { + DMResource *file; + + if (optOutFilename == NULL) + file = dmf_create_stdio_stream(stdout); + else + file = dmf_create_stdio(optOutFilename, "wb"); + + if (file == NULL) + { + dmError("Error creating file '%s', %d: %s\n", + optInFilename, errno, strerror(errno)); + goto error_exit; + } + + res = dmSaveBitmapFont(file, font); + dmf_close(file); + } + + if (res != DMERR_OK) + { + dmError("Error saving font, %d: %s\n", + res, dmErrorStr(res)); + } + +error_exit: + + dmf_close(inFile); + dmFreeBitmapFont(font); + + return 0; +}