| 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 */
GFXglyph::width
uint8_t width
Definition: gfxfont.h:13
GFXglyph::xAdvance
uint8_t xAdvance
Definition: gfxfont.h:14
GFXglyph
Definition: gfxfont.h:10
DPI
#define DPI
Definition: fontconvert.c:27
GFXglyph::bitmapOffset
uint16_t bitmapOffset
Definition: gfxfont.h:12
GFXglyph::xOffset
int8_t xOffset
Definition: gfxfont.h:15
GFXglyph::yOffset
int8_t yOffset
Definition: gfxfont.h:15
x
int32_t x
Definition: LTC2492_Thermocouple_Meter.ino:119
main
int main(int argc, char *argv[])
Definition: fontconvert.c:49
GFXglyph::height
uint8_t height
Definition: gfxfont.h:13
i
static int i
Definition: DC2430A.ino:184
enbit
void enbit(uint8_t value)
Definition: fontconvert.c:30