#include #include #include #include #include #include int main(int argc, char** argv) { if (argc != 6) { fprintf(stderr, "Usage: %s \n", argv[0]); return 1; } const char* inFilename = argv[1]; const char* layoutFilename = argv[2]; const char* outFilename = argv[3]; const int glyphWidth = atoi(argv[4]); const int glyphHeight = atoi(argv[5]); int imageWidth; int imageHeight; uint8_t* imageBuffer; { FILE* inFile = fopen(inFilename, "rb"); assert(inFile); #pragma pack(push,1) struct BmpHeader { char magic[2]; uint32_t totalSize; uint32_t reserved; uint32_t offset; uint32_t headerSize; int32_t width; int32_t height; uint16_t planes; uint16_t depth; uint32_t compression; uint32_t imageSize; int32_t horizontalResolution; int32_t verticalResolution; uint32_t paletteColorCount; uint32_t importantColorcount; } bmpHeader; #pragma pack(pop) // Read the BMP header so we know where the image data is located fread(&bmpHeader, 1, sizeof(bmpHeader), inFile); assert(bmpHeader.magic[0] == 'B' && bmpHeader.magic[1] == 'M'); assert(bmpHeader.depth == 8); assert(bmpHeader.headerSize == 40); // Go to location in file of image data fseek(inFile, bmpHeader.offset, SEEK_SET); // Read in the image data imageBuffer = malloc(bmpHeader.imageSize); assert(imageBuffer); fread(imageBuffer, 1, bmpHeader.imageSize, inFile); imageWidth = bmpHeader.width; imageHeight = bmpHeader.height; fclose(inFile); } char** glyphLayout = NULL; int layoutRows = 0; { FILE* layoutFile = fopen(layoutFilename, "r"); assert(layoutFile); // Count the number of lines in the file while (!feof(layoutFile)) { char c = fgetc(layoutFile); if (c == '\n') { ++layoutRows; } } // Return file position indicator to start rewind(layoutFile); // Allocate enough memory for one string pointer per row glyphLayout = malloc(sizeof(*glyphLayout) * layoutRows); assert(glyphLayout); // Read the file into memory for (int rowIndex = 0; rowIndex < layoutRows; ++rowIndex) { char* line = NULL; size_t len = 0; getline(&line, &len, layoutFile); int newlinePosition = strlen(line) - 1; if (line[newlinePosition] == '\n') { line[newlinePosition] = '\0'; } glyphLayout[rowIndex] = line; } fclose(layoutFile); } printf("Input: %s\n", inFilename); printf("Output: %s\n", outFilename); printf("Width: %d\n", imageWidth); printf("Height: %d\n", imageHeight); printf("Glyph: %dx%d\n\n", glyphWidth, glyphHeight); FILE* outFile = fopen(outFilename, "w"); assert(outFile); // Generate the preamble { fprintf(outFile, "// AUTOMATICALLY GENERATED. DO NOT EDIT.\n"); fprintf(outFile, "\n"); fprintf(outFile, "#pragma once\n"); fprintf(outFile, "\n"); fprintf(outFile, "#include \n"); fprintf(outFile, "#include \n"); fprintf(outFile, "\n"); fprintf(outFile, "\n"); fprintf(outFile, "static const int GLYPH_WIDTH = %d;\n", glyphWidth); fprintf(outFile, "static const int GLYPH_HEIGHT = %d;\n", glyphHeight); fprintf(outFile, "\n"); fprintf(outFile, "\n"); } // Generate the GetGlyphIndex function int glyphCount = 0; { fprintf(outFile, "int GetGlyphIndex(char c)\n"); fprintf(outFile, "{\n"); fprintf(outFile, " switch (c)\n"); fprintf(outFile, " {\n"); for (int row = 0; row < layoutRows; ++row) { int glyphsInRow = strlen(glyphLayout[row]); for (int glyph = 0; glyph < glyphsInRow; ++glyph) { char c = glyphLayout[row][glyph]; fprintf(outFile, " "); if (isalpha(c)) { fprintf(outFile, "case '%c': ", tolower(c)); } fprintf(outFile, "case '%c': { return %d; break; }\n", c, glyphCount); ++glyphCount; } } fprintf(outFile, " default: { assert(NULL); break; }\n"); fprintf(outFile, " }\n"); fprintf(outFile, "}\n\n"); } // Generate the font map with the calculated glyph bytes { fprintf(outFile, "static const uint16_t glyphMap[%d][%d] =\n", glyphCount, glyphHeight); fprintf(outFile, "{\n"); for (int y = 0; y < layoutRows; ++y) { int glyphsInRow = strlen(glyphLayout[y]); for (int x = 0; x < glyphsInRow; ++x) { char c = glyphLayout[y][x]; fprintf(outFile, " // %c\n", c); fprintf(outFile, " {\n"); fprintf(outFile, " "); int count = 0; for (int row = y * glyphHeight; row < (y + 1) * glyphHeight; ++row) { uint16_t val = 0; for (int col = x * glyphWidth; col < (x + 1) * glyphWidth; ++col) { // BMP is laid out bottom-to-top, but we want top-to-bottom (0-indexed) int y = imageHeight - row - 1; uint8_t pixel = imageBuffer[y * imageWidth + col]; int bitPosition = 15 - (col % glyphWidth); val |= (pixel << bitPosition); } fprintf(outFile, "0x%04X,", val); ++count; // Put a newline after four values to keep it orderly if ((count % 4) == 0) { fprintf(outFile, "\n"); fprintf(outFile, " "); count = 0; } } fprintf(outFile, "},\n\n"); } } fprintf(outFile, "};\n"); } fclose(outFile); printf("DONE\n"); return 0; }