PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

279 行
9.2KB

  1. /*
  2. TrueType to Adafruit_GFX font converter. Derived from Peter Jakobs'
  3. Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.
  4. NOT AN ARDUINO SKETCH. This is a command-line tool for preprocessing
  5. fonts to be used with the Adafruit_GFX Arduino library.
  6. For UNIX-like systems. Outputs to stdout; redirect to header file, e.g.:
  7. ./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h
  8. REQUIRES FREETYPE LIBRARY. www.freetype.org
  9. Currently this only extracts the printable 7-bit ASCII chars of a font.
  10. Will eventually extend with some int'l chars a la ftGFX, not there yet.
  11. Keep 7-bit fonts around as an option in that case, more compact.
  12. See notes at end for glyph nomenclature & other tidbits.
  13. */
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <stdint.h>
  17. #include <ft2build.h>
  18. #include FT_GLYPH_H
  19. #include "../gfxfont.h" // Adafruit_GFX font structures
  20. #define DPI 141 // Approximate res. of Adafruit 2.8" TFT
  21. // Accumulate bits for output, with periodic hexadecimal byte write
  22. void enbit(uint8_t value) {
  23. static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
  24. if(value) sum |= bit; // Set bit if needed
  25. if(!(bit >>= 1)) { // Advance to next bit, end of byte reached?
  26. if(!firstCall) { // Format output table nicely
  27. if(++row >= 12) { // Last entry on line?
  28. printf(",\n "); // Newline format output
  29. row = 0; // Reset row counter
  30. } else { // Not end of line
  31. printf(", "); // Simple comma delim
  32. }
  33. }
  34. printf("0x%02X", sum); // Write byte value
  35. sum = 0; // Clear for next byte
  36. bit = 0x80; // Reset bit counter
  37. firstCall = 0; // Formatting flag
  38. }
  39. }
  40. int main(int argc, char *argv[]) {
  41. int i, j, err, size, first=' ', last='~',
  42. bitmapOffset = 0, x, y, byte;
  43. char *fontName, c, *ptr;
  44. FT_Library library;
  45. FT_Face face;
  46. FT_Glyph glyph;
  47. FT_Bitmap *bitmap;
  48. FT_BitmapGlyphRec *g;
  49. GFXglyph *table;
  50. uint8_t bit;
  51. // Parse command line. Valid syntaxes are:
  52. // fontconvert [filename] [size]
  53. // fontconvert [filename] [size] [last char]
  54. // fontconvert [filename] [size] [first char] [last char]
  55. // Unless overridden, default first and last chars are
  56. // ' ' (space) and '~', respectively
  57. if(argc < 3) {
  58. fprintf(stderr, "Usage: %s fontfile size [first] [last]\n",
  59. argv[0]);
  60. return 1;
  61. }
  62. size = atoi(argv[2]);
  63. if(argc == 4) {
  64. last = atoi(argv[3]);
  65. } else if(argc == 5) {
  66. first = atoi(argv[3]);
  67. last = atoi(argv[4]);
  68. }
  69. if(last < first) {
  70. i = first;
  71. first = last;
  72. last = i;
  73. }
  74. ptr = strrchr(argv[1], '/'); // Find last slash in filename
  75. if(ptr) ptr++; // First character of filename (path stripped)
  76. else ptr = argv[1]; // No path; font in local dir.
  77. // Allocate space for font name and glyph table
  78. if((!(fontName = malloc(strlen(ptr) + 20))) ||
  79. (!(table = (GFXglyph *)malloc((last - first + 1) *
  80. sizeof(GFXglyph))))) {
  81. fprintf(stderr, "Malloc error\n");
  82. return 1;
  83. }
  84. // Derive font table names from filename. Period (filename
  85. // extension) is truncated and replaced with the font size & bits.
  86. strcpy(fontName, ptr);
  87. ptr = strrchr(fontName, '.'); // Find last period (file ext)
  88. if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append
  89. // Insert font size and 7/8 bit. fontName was alloc'd w/extra
  90. // space to allow this, we're not sprintfing into Forbidden Zone.
  91. sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
  92. // Space and punctuation chars in name replaced w/ underscores.
  93. for(i=0; (c=fontName[i]); i++) {
  94. if(isspace(c) || ispunct(c)) fontName[i] = '_';
  95. }
  96. // Init FreeType lib, load font
  97. if((err = FT_Init_FreeType(&library))) {
  98. fprintf(stderr, "FreeType init error: %d", err);
  99. return err;
  100. }
  101. if((err = FT_New_Face(library, argv[1], 0, &face))) {
  102. fprintf(stderr, "Font load error: %d", err);
  103. FT_Done_FreeType(library);
  104. return err;
  105. }
  106. // << 6 because '26dot6' fixed-point format
  107. FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
  108. // Currently all symbols from 'first' to 'last' are processed.
  109. // Fonts may contain WAY more glyphs than that, but this code
  110. // will need to handle encoding stuff to deal with extracting
  111. // the right symbols, and that's not done yet.
  112. // fprintf(stderr, "%ld glyphs\n", face->num_glyphs);
  113. printf("const uint8_t %sBitmaps[] PROGMEM = {\n ", fontName);
  114. // Process glyphs and output huge bitmap data array
  115. for(i=first, j=0; i<=last; i++, j++) {
  116. // MONO renderer provides clean image with perfect crop
  117. // (no wasted pixels) via bitmap struct.
  118. if((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) {
  119. fprintf(stderr, "Error %d loading char '%c'\n",
  120. err, i);
  121. continue;
  122. }
  123. if((err = FT_Render_Glyph(face->glyph,
  124. FT_RENDER_MODE_MONO))) {
  125. fprintf(stderr, "Error %d rendering char '%c'\n",
  126. err, i);
  127. continue;
  128. }
  129. if((err = FT_Get_Glyph(face->glyph, &glyph))) {
  130. fprintf(stderr, "Error %d getting glyph '%c'\n",
  131. err, i);
  132. continue;
  133. }
  134. bitmap = &face->glyph->bitmap;
  135. g = (FT_BitmapGlyphRec *)glyph;
  136. // Minimal font and per-glyph information is stored to
  137. // reduce flash space requirements. Glyph bitmaps are
  138. // fully bit-packed; no per-scanline pad, though end of
  139. // each character may be padded to next byte boundary
  140. // when needed. 16-bit offset means 64K max for bitmaps,
  141. // code currently doesn't check for overflow. (Doesn't
  142. // check that size & offsets are within bounds either for
  143. // that matter...please convert fonts responsibly.)
  144. table[j].bitmapOffset = bitmapOffset;
  145. table[j].width = bitmap->width;
  146. table[j].height = bitmap->rows;
  147. table[j].xAdvance = face->glyph->advance.x >> 6;
  148. table[j].xOffset = g->left;
  149. table[j].yOffset = 1 - g->top;
  150. for(y=0; y < bitmap->rows; y++) {
  151. for(x=0;x < bitmap->width; x++) {
  152. byte = x / 8;
  153. bit = 0x80 >> (x & 7);
  154. enbit(bitmap->buffer[
  155. y * bitmap->pitch + byte] & bit);
  156. }
  157. }
  158. // Pad end of char bitmap to next byte boundary if needed
  159. int n = (bitmap->width * bitmap->rows) & 7;
  160. if(n) { // Pixel count not an even multiple of 8?
  161. n = 8 - n; // # bits to next multiple
  162. while(n--) enbit(0);
  163. }
  164. bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;
  165. FT_Done_Glyph(glyph);
  166. }
  167. printf(" };\n\n"); // End bitmap array
  168. // Output glyph attributes table (one per character)
  169. printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
  170. for(i=first, j=0; i<=last; i++, j++) {
  171. printf(" { %5d, %3d, %3d, %3d, %4d, %4d }",
  172. table[j].bitmapOffset,
  173. table[j].width,
  174. table[j].height,
  175. table[j].xAdvance,
  176. table[j].xOffset,
  177. table[j].yOffset);
  178. if(i < last) {
  179. printf(", // 0x%02X", i);
  180. if((i >= ' ') && (i <= '~')) {
  181. printf(" '%c'", i);
  182. }
  183. putchar('\n');
  184. }
  185. }
  186. printf(" }; // 0x%02X", last);
  187. if((last >= ' ') && (last <= '~')) printf(" '%c'", last);
  188. printf("\n\n");
  189. // Output font structure
  190. printf("const GFXfont %s PROGMEM = {\n", fontName);
  191. printf(" (uint8_t *)%sBitmaps,\n", fontName);
  192. printf(" (GFXglyph *)%sGlyphs,\n", fontName);
  193. printf(" 0x%02X, 0x%02X, %ld };\n\n",
  194. first, last, face->size->metrics.height >> 6);
  195. printf("// Approx. %d bytes\n",
  196. bitmapOffset + (last - first + 1) * 7 + 7);
  197. // Size estimate is based on AVR struct and pointer sizes;
  198. // actual size may vary.
  199. FT_Done_FreeType(library);
  200. return 0;
  201. }
  202. /* -------------------------------------------------------------------------
  203. Character metrics are slightly different from classic GFX & ftGFX.
  204. In classic GFX: cursor position is the upper-left pixel of each 5x7
  205. character; lower extent of most glyphs (except those w/descenders)
  206. is +6 pixels in Y direction.
  207. W/new GFX fonts: cursor position is on baseline, where baseline is
  208. 'inclusive' (containing the bottom-most row of pixels in most symbols,
  209. except those with descenders; ftGFX is one pixel lower).
  210. Cursor Y will be moved automatically when switching between classic
  211. and new fonts. If you switch fonts, any print() calls will continue
  212. along the same baseline.
  213. ...........#####.. -- yOffset
  214. ..........######..
  215. ..........######..
  216. .........#######..
  217. ........#########.
  218. * = Cursor pos. ........#########.
  219. .......##########.
  220. ......#####..####.
  221. ......#####..####.
  222. *.#.. .....#####...####.
  223. .#.#. ....##############
  224. #...# ...###############
  225. #...# ...###############
  226. ##### ..#####......#####
  227. #...# .#####.......#####
  228. ====== #...# ====== #*###.........#### ======= Baseline
  229. || xOffset
  230. glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
  231. (+Y is down), from the cursor position to the top-left pixel of the
  232. glyph bitmap. i.e. yOffset is typically negative, xOffset is typically
  233. zero but a few glyphs will have other values (even negative xOffsets
  234. sometimes, totally normal). glyph->xAdvance is the distance to move
  235. the cursor on the X axis after drawing the corresponding symbol.
  236. There's also some changes with regard to 'background' color and new GFX
  237. fonts (classic fonts unchanged). See Adafruit_GFX.cpp for explanation.
  238. */