No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

font_processor.c 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include <assert.h>
  2. #include <ctype.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. int main(int argc, char** argv)
  8. {
  9. if (argc != 6)
  10. {
  11. fprintf(stderr, "Usage: %s <input image> <layout file> <output header> <glyph width> <glyph height>\n", argv[0]);
  12. return 1;
  13. }
  14. const char* inFilename = argv[1];
  15. const char* layoutFilename = argv[2];
  16. const char* outFilename = argv[3];
  17. const int glyphWidth = atoi(argv[4]);
  18. const int glyphHeight = atoi(argv[5]);
  19. int imageWidth;
  20. int imageHeight;
  21. uint8_t* imageBuffer;
  22. {
  23. FILE* inFile = fopen(inFilename, "rb");
  24. assert(inFile);
  25. #pragma pack(push,1)
  26. struct BmpHeader
  27. {
  28. char magic[2];
  29. uint32_t totalSize;
  30. uint32_t reserved;
  31. uint32_t offset;
  32. uint32_t headerSize;
  33. int32_t width;
  34. int32_t height;
  35. uint16_t planes;
  36. uint16_t depth;
  37. uint32_t compression;
  38. uint32_t imageSize;
  39. int32_t horizontalResolution;
  40. int32_t verticalResolution;
  41. uint32_t paletteColorCount;
  42. uint32_t importantColorcount;
  43. } bmpHeader;
  44. #pragma pack(pop)
  45. // Read the BMP header so we know where the image data is located
  46. fread(&bmpHeader, 1, sizeof(bmpHeader), inFile);
  47. assert(bmpHeader.magic[0] == 'B' && bmpHeader.magic[1] == 'M');
  48. assert(bmpHeader.depth == 8);
  49. assert(bmpHeader.headerSize == 40);
  50. // Go to location in file of image data
  51. fseek(inFile, bmpHeader.offset, SEEK_SET);
  52. // Read in the image data
  53. imageBuffer = malloc(bmpHeader.imageSize);
  54. assert(imageBuffer);
  55. fread(imageBuffer, 1, bmpHeader.imageSize, inFile);
  56. imageWidth = bmpHeader.width;
  57. imageHeight = bmpHeader.height;
  58. fclose(inFile);
  59. }
  60. char** glyphLayout = NULL;
  61. int layoutRows = 0;
  62. {
  63. FILE* layoutFile = fopen(layoutFilename, "r");
  64. assert(layoutFile);
  65. // Count the number of lines in the file
  66. while (!feof(layoutFile))
  67. {
  68. char c = fgetc(layoutFile);
  69. if (c == '\n')
  70. {
  71. ++layoutRows;
  72. }
  73. }
  74. // Return file position indicator to start
  75. rewind(layoutFile);
  76. // Allocate enough memory for one string pointer per row
  77. glyphLayout = malloc(sizeof(*glyphLayout) * layoutRows);
  78. assert(glyphLayout);
  79. // Read the file into memory
  80. for (int rowIndex = 0; rowIndex < layoutRows; ++rowIndex)
  81. {
  82. char* line = NULL;
  83. size_t len = 0;
  84. getline(&line, &len, layoutFile);
  85. int newlinePosition = strlen(line) - 1;
  86. if (line[newlinePosition] == '\n')
  87. {
  88. line[newlinePosition] = '\0';
  89. }
  90. glyphLayout[rowIndex] = line;
  91. }
  92. fclose(layoutFile);
  93. }
  94. printf("Input: %s\n", inFilename);
  95. printf("Output: %s\n", outFilename);
  96. printf("Width: %d\n", imageWidth);
  97. printf("Height: %d\n", imageHeight);
  98. printf("Glyph: %dx%d\n\n", glyphWidth, glyphHeight);
  99. FILE* outFile = fopen(outFilename, "w");
  100. assert(outFile);
  101. // Generate the preamble
  102. {
  103. fprintf(outFile, "// AUTOMATICALLY GENERATED. DO NOT EDIT.\n");
  104. fprintf(outFile, "\n");
  105. fprintf(outFile, "#pragma once\n");
  106. fprintf(outFile, "\n");
  107. fprintf(outFile, "#include <assert.h>\n");
  108. fprintf(outFile, "#include <stdint.h>\n");
  109. fprintf(outFile, "\n");
  110. fprintf(outFile, "\n");
  111. fprintf(outFile, "static const int GLYPH_WIDTH = %d;\n", glyphWidth);
  112. fprintf(outFile, "static const int GLYPH_HEIGHT = %d;\n", glyphHeight);
  113. fprintf(outFile, "\n");
  114. fprintf(outFile, "\n");
  115. }
  116. // Generate the GetGlyphIndex function
  117. int glyphCount = 0;
  118. {
  119. fprintf(outFile, "int GetGlyphIndex(char c)\n");
  120. fprintf(outFile, "{\n");
  121. fprintf(outFile, " switch (c)\n");
  122. fprintf(outFile, " {\n");
  123. for (int row = 0; row < layoutRows; ++row)
  124. {
  125. int glyphsInRow = strlen(glyphLayout[row]);
  126. for (int glyph = 0; glyph < glyphsInRow; ++glyph)
  127. {
  128. char c = glyphLayout[row][glyph];
  129. fprintf(outFile, " ");
  130. if (isalpha(c))
  131. {
  132. fprintf(outFile, "case '%c': ", tolower(c));
  133. }
  134. fprintf(outFile, "case '%c': { return %d; break; }\n", c, glyphCount);
  135. ++glyphCount;
  136. }
  137. }
  138. fprintf(outFile, " default: { assert(NULL); break; }\n");
  139. fprintf(outFile, " }\n");
  140. fprintf(outFile, "}\n\n");
  141. }
  142. // Generate the font map with the calculated glyph bytes
  143. {
  144. fprintf(outFile, "static const uint16_t glyphMap[%d][%d] =\n", glyphCount, glyphHeight);
  145. fprintf(outFile, "{\n");
  146. for (int y = 0; y < layoutRows; ++y)
  147. {
  148. int glyphsInRow = strlen(glyphLayout[y]);
  149. for (int x = 0; x < glyphsInRow; ++x)
  150. {
  151. char c = glyphLayout[y][x];
  152. fprintf(outFile, " // %c\n", c);
  153. fprintf(outFile, " {\n");
  154. fprintf(outFile, " ");
  155. int count = 0;
  156. for (int row = y * glyphHeight; row < (y + 1) * glyphHeight; ++row)
  157. {
  158. uint16_t val = 0;
  159. for (int col = x * glyphWidth; col < (x + 1) * glyphWidth; ++col)
  160. {
  161. // BMP is laid out bottom-to-top, but we want top-to-bottom (0-indexed)
  162. int y = imageHeight - row - 1;
  163. uint8_t pixel = imageBuffer[y * imageWidth + col];
  164. int bitPosition = 15 - (col % glyphWidth);
  165. val |= (pixel << bitPosition);
  166. }
  167. fprintf(outFile, "0x%04X,", val);
  168. ++count;
  169. // Put a newline after four values to keep it orderly
  170. if ((count % 4) == 0)
  171. {
  172. fprintf(outFile, "\n");
  173. fprintf(outFile, " ");
  174. count = 0;
  175. }
  176. }
  177. fprintf(outFile, "},\n\n");
  178. }
  179. }
  180. fprintf(outFile, "};\n");
  181. }
  182. fclose(outFile);
  183. printf("DONE\n");
  184. return 0;
  185. }