123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- #include <assert.h>
- #include <ctype.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
-
- int main(int argc, char** argv)
- {
- if (argc != 6)
- {
- fprintf(stderr, "Usage: %s <input image> <layout file> <output header> <glyph width> <glyph height>\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 <assert.h>\n");
- fprintf(outFile, "#include <stdint.h>\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;
- }
|