#include /* perror */ #include /* EXIT_FAILURE, EXIT_SUCCESS */ #include /* strlen, strrchr */ #include /* bool, true, false */ #include /* uint8_t */ #include /* basename */ #include /* pow */ #include /* isalnum */ #include "trace.h" /* TRACE_MSG */ #define MAX_LINE_SIZE 128 #define PIXEL_WIDTH 7 void chomp(char *s) { size_t len, i; len = strlen(s); for (i = len; i > 0; ) if (s[--i] == '\r' || s[i] == '\n') s[i] = '\0'; } void reverse(char *s) { size_t len, i, j; char c; len = strlen(s); for (i = 0, j = len; i < j && j > 1; ++i) { --j; c = s[i]; s[i] = s[j]; s[j] = c; } } int convertReverseBinaryStringToInt(char *s) { size_t i, len; int value = 0; len = strlen(s); for (i = 0; i < len; ++i) if (s[i] == '1') value += pow(2, i); else if (s[i] != '0') break; return value; } char *makeIdentName(char *s) { size_t i, len; len = strlen(s); for (i = 0; i < len; i++) if (! isalnum(s[i]) && s[i] != '_') s[i] = '_'; return s; } char *removeExtension(char *fileName) { char *ext; ext = strrchr(fileName, '.'); if (ext != NULL) *ext = '\0'; return fileName; } char *readLine(FILE *f, char *name) { static char line[MAX_LINE_SIZE]; char *linePtr; if ((linePtr = fgets(line, MAX_LINE_SIZE, f)) != NULL) chomp(linePtr); else if (ferror(f)) perror(name); return linePtr; } char *replaceWithOnesAndZeros(char *line, size_t len) { size_t i; for (i = 0; i < len; ++i) { switch (line[i]) { case '#': line[i] = '1'; break; case '.': line[i] = '0'; break; } } return line; } bool makeGlyph(FILE *f, char *name, uint16_t *lineNum, uint8_t pixelHeight) { char *line; uint8_t i; bool ok = true; size_t len; printf("\t{\n"); for (i = 0; i < pixelHeight; ++i) if ((line = readLine(f, name)) != NULL) { (*lineNum)++; if ((len = strlen(line)) == PIXEL_WIDTH) { replaceWithOnesAndZeros(line, len); printf("\t0x%x,\n", convertReverseBinaryStringToInt(line)); } else { fprintf(stderr, "Line %d, containing '%s', is wrong length: %d\n", *lineNum, line, len); ok = false; break; } } else break; printf(" },\n"); return ok; } bool makeFontFromStream(FILE *f, char *name) { uint8_t pixelHeight, asciiCode, i, prevAsciiCode = 0; char *line, *arrayName; bool ok = true; uint16_t lineNum = 0; size_t len; if ((line = readLine(f, name)) != NULL) { lineNum++; pixelHeight = atoi(line); arrayName = makeIdentName(removeExtension(basename(name))); printf("uint8_t %s[128][%d] = {\n", arrayName, pixelHeight); printf(" /* ASCII code 0x0 */ {0},\n"); while ((line = readLine(f, name)) != NULL) { lineNum++; if ((len = strlen(line)) != 1) { fprintf(stderr, "Line %d, containing '%s', is wrong length: %d\n", lineNum, line, len); ok = false; break; } asciiCode = (uint8_t) line[0]; for (i = prevAsciiCode + 1; i < asciiCode; ++i) printf(" /* ASCII code 0x%x */ {0},\n", i); printf(" /* Char '%c', ASCII code 0x%x */\n", asciiCode, asciiCode); if (makeGlyph(f, name, &lineNum, pixelHeight)) prevAsciiCode = asciiCode; else { ok = false; break; } } printf("};\n\n"); } return ok; } bool makeFontFromFile(char *fileName) { FILE *f; bool ok = false; if ((f = fopen(fileName, "r")) != NULL) { if (makeFontFromStream(f, fileName)) ok = true; fclose(f); } else perror(fileName); return ok; } int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; ++i) if (! makeFontFromFile(argv[i])) return EXIT_FAILURE; return EXIT_SUCCESS; }