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