This commit is contained in:
Marcus Priesch 2017-10-10 00:39:53 +02:00
parent 325e41ae6a
commit 965ac84918
82 changed files with 26066 additions and 0 deletions

View file

@ -0,0 +1,12 @@
all: fontconvert
CC = gcc
CFLAGS = -Wall -I/usr/local/include/freetype2 -I/usr/include/freetype2 -I/usr/include
LIBS = -lfreetype
fontconvert: fontconvert.c
$(CC) $(CFLAGS) $< $(LIBS) -o $@
strip $@
clean:
rm -f fontconvert

View file

@ -0,0 +1,284 @@
/*
TrueType to Adafruit_GFX font converter. Derived from Peter Jakobs'
Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.
NOT AN ARDUINO SKETCH. This is a command-line tool for preprocessing
fonts to be used with the Adafruit_GFX Arduino library.
For UNIX-like systems. Outputs to stdout; redirect to header file, e.g.:
./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h
REQUIRES FREETYPE LIBRARY. www.freetype.org
Currently this only extracts the printable 7-bit ASCII chars of a font.
Will eventually extend with some int'l chars a la ftGFX, not there yet.
Keep 7-bit fonts around as an option in that case, more compact.
See notes at end for glyph nomenclature & other tidbits.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <ft2build.h>
#include FT_GLYPH_H
#include "../gfxfont.h" // Adafruit_GFX font structures
#define DPI 141 // Approximate res. of Adafruit 2.8" TFT
// Accumulate bits for output, with periodic hexadecimal byte write
void enbit(uint8_t value) {
static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
if(value) sum |= bit; // Set bit if needed
if(!(bit >>= 1)) { // Advance to next bit, end of byte reached?
if(!firstCall) { // Format output table nicely
if(++row >= 12) { // Last entry on line?
printf(",\n "); // Newline format output
row = 0; // Reset row counter
} else { // Not end of line
printf(", "); // Simple comma delim
}
}
printf("0x%02X", sum); // Write byte value
sum = 0; // Clear for next byte
bit = 0x80; // Reset bit counter
firstCall = 0; // Formatting flag
}
}
int main(int argc, char *argv[]) {
int i, j, err, size, first=' ', last='~',
bitmapOffset = 0, x, y, byte;
char *fontName, c, *ptr;
FT_Library library;
FT_Face face;
FT_Glyph glyph;
FT_Bitmap *bitmap;
FT_BitmapGlyphRec *g;
GFXglyph *table;
uint8_t bit;
// Parse command line. Valid syntaxes are:
// fontconvert [filename] [size]
// fontconvert [filename] [size] [last char]
// fontconvert [filename] [size] [first char] [last char]
// Unless overridden, default first and last chars are
// ' ' (space) and '~', respectively
if(argc < 3) {
fprintf(stderr, "Usage: %s fontfile size [first] [last]\n",
argv[0]);
return 1;
}
size = atoi(argv[2]);
if(argc == 4) {
last = atoi(argv[3]);
} else if(argc == 5) {
first = atoi(argv[3]);
last = atoi(argv[4]);
}
if(last < first) {
i = first;
first = last;
last = i;
}
ptr = strrchr(argv[1], '/'); // Find last slash in filename
if(ptr) ptr++; // First character of filename (path stripped)
else ptr = argv[1]; // No path; font in local dir.
// Allocate space for font name and glyph table
if((!(fontName = malloc(strlen(ptr) + 20))) ||
(!(table = (GFXglyph *)malloc((last - first + 1) *
sizeof(GFXglyph))))) {
fprintf(stderr, "Malloc error\n");
return 1;
}
// Derive font table names from filename. Period (filename
// extension) is truncated and replaced with the font size & bits.
strcpy(fontName, ptr);
ptr = strrchr(fontName, '.'); // Find last period (file ext)
if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append
// Insert font size and 7/8 bit. fontName was alloc'd w/extra
// space to allow this, we're not sprintfing into Forbidden Zone.
sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
// Space and punctuation chars in name replaced w/ underscores.
for(i=0; (c=fontName[i]); i++) {
if(isspace(c) || ispunct(c)) fontName[i] = '_';
}
// Init FreeType lib, load font
if((err = FT_Init_FreeType(&library))) {
fprintf(stderr, "FreeType init error: %d", err);
return err;
}
if((err = FT_New_Face(library, argv[1], 0, &face))) {
fprintf(stderr, "Font load error: %d", err);
FT_Done_FreeType(library);
return err;
}
// << 6 because '26dot6' fixed-point format
FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
// Currently all symbols from 'first' to 'last' are processed.
// Fonts may contain WAY more glyphs than that, but this code
// will need to handle encoding stuff to deal with extracting
// the right symbols, and that's not done yet.
// fprintf(stderr, "%ld glyphs\n", face->num_glyphs);
printf("const uint8_t %sBitmaps[] PROGMEM = {\n ", fontName);
// Process glyphs and output huge bitmap data array
for(i=first, j=0; i<=last; i++, j++) {
// MONO renderer provides clean image with perfect crop
// (no wasted pixels) via bitmap struct.
if((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) {
fprintf(stderr, "Error %d loading char '%c'\n",
err, i);
continue;
}
if((err = FT_Render_Glyph(face->glyph,
FT_RENDER_MODE_MONO))) {
fprintf(stderr, "Error %d rendering char '%c'\n",
err, i);
continue;
}
if((err = FT_Get_Glyph(face->glyph, &glyph))) {
fprintf(stderr, "Error %d getting glyph '%c'\n",
err, i);
continue;
}
bitmap = &face->glyph->bitmap;
g = (FT_BitmapGlyphRec *)glyph;
// Minimal font and per-glyph information is stored to
// reduce flash space requirements. Glyph bitmaps are
// fully bit-packed; no per-scanline pad, though end of
// each character may be padded to next byte boundary
// when needed. 16-bit offset means 64K max for bitmaps,
// code currently doesn't check for overflow. (Doesn't
// check that size & offsets are within bounds either for
// that matter...please convert fonts responsibly.)
table[j].bitmapOffset = bitmapOffset;
table[j].width = bitmap->width;
table[j].height = bitmap->rows;
table[j].xAdvance = face->glyph->advance.x >> 6;
table[j].xOffset = g->left;
table[j].yOffset = 1 - g->top;
for(y=0; y < bitmap->rows; y++) {
for(x=0;x < bitmap->width; x++) {
byte = x / 8;
bit = 0x80 >> (x & 7);
enbit(bitmap->buffer[
y * bitmap->pitch + byte] & bit);
}
}
// Pad end of char bitmap to next byte boundary if needed
int n = (bitmap->width * bitmap->rows) & 7;
if(n) { // Pixel count not an even multiple of 8?
n = 8 - n; // # bits to next multiple
while(n--) enbit(0);
}
bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;
FT_Done_Glyph(glyph);
}
printf(" };\n\n"); // End bitmap array
// Output glyph attributes table (one per character)
printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
for(i=first, j=0; i<=last; i++, j++) {
printf(" { %5d, %3d, %3d, %3d, %4d, %4d }",
table[j].bitmapOffset,
table[j].width,
table[j].height,
table[j].xAdvance,
table[j].xOffset,
table[j].yOffset);
if(i < last) {
printf(", // 0x%02X", i);
if((i >= ' ') && (i <= '~')) {
printf(" '%c'", i);
}
putchar('\n');
}
}
printf(" }; // 0x%02X", last);
if((last >= ' ') && (last <= '~')) printf(" '%c'", last);
printf("\n\n");
// Output font structure
printf("const GFXfont %s PROGMEM = {\n", fontName);
printf(" (uint8_t *)%sBitmaps,\n", fontName);
printf(" (GFXglyph *)%sGlyphs,\n", fontName);
if (face->size->metrics.height == 0) {
// No face height info, assume fixed width and get from a glyph.
printf(" 0x%02X, 0x%02X, %d };\n\n",
first, last, table[0].height);
} else {
printf(" 0x%02X, 0x%02X, %ld };\n\n",
first, last, face->size->metrics.height >> 6);
}
printf("// Approx. %d bytes\n",
bitmapOffset + (last - first + 1) * 7 + 7);
// Size estimate is based on AVR struct and pointer sizes;
// actual size may vary.
FT_Done_FreeType(library);
return 0;
}
/* -------------------------------------------------------------------------
Character metrics are slightly different from classic GFX & ftGFX.
In classic GFX: cursor position is the upper-left pixel of each 5x7
character; lower extent of most glyphs (except those w/descenders)
is +6 pixels in Y direction.
W/new GFX fonts: cursor position is on baseline, where baseline is
'inclusive' (containing the bottom-most row of pixels in most symbols,
except those with descenders; ftGFX is one pixel lower).
Cursor Y will be moved automatically when switching between classic
and new fonts. If you switch fonts, any print() calls will continue
along the same baseline.
...........#####.. -- yOffset
..........######..
..........######..
.........#######..
........#########.
* = Cursor pos. ........#########.
.......##########.
......#####..####.
......#####..####.
*.#.. .....#####...####.
.#.#. ....##############
#...# ...###############
#...# ...###############
##### ..#####......#####
#...# .#####.......#####
====== #...# ====== #*###.........#### ======= Baseline
|| xOffset
glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
(+Y is down), from the cursor position to the top-left pixel of the
glyph bitmap. i.e. yOffset is typically negative, xOffset is typically
zero but a few glyphs will have other values (even negative xOffsets
sometimes, totally normal). glyph->xAdvance is the distance to move
the cursor on the X axis after drawing the corresponding symbol.
There's also some changes with regard to 'background' color and new GFX
fonts (classic fonts unchanged). See Adafruit_GFX.cpp for explanation.
*/

View file

@ -0,0 +1,88 @@
### A short guide to use fontconvert.c to create your own fonts using MinGW.
#### STEP 1: INSTALL MinGW
Install MinGW (Minimalist GNU for Windows) from [MinGW.org](http://www.mingw.org/).
Please read carefully the instructions found on [Getting started page](http://www.mingw.org/wiki/Getting_Started).
I suggest installing with the "Graphical User Interface Installer".
To complete your initial installation you should further install some "packages".
For our purpose you should only install the "Basic Setup" packages.
To do that:
1. Open the MinGW Installation Manager
2. From the left panel click "Basic Setup".
3. On the right panel choose "mingw32-base", "mingw-gcc-g++", "mingw-gcc-objc" and "msys-base"
and click "Mark for installation"
4. From the Menu click "Installation" and then "Apply changes". In the pop-up window select "Apply".
#### STEP 2: INSTALL Freetype Library
To read about the freetype project visit [freetype.org](https://www.freetype.org/).
To Download the latest version of freetype go to [download page](http://download.savannah.gnu.org/releases/freetype/)
and choose "freetype-2.7.tar.gz" file (or a newer version if available).
To avoid long cd commands later in the command prompt, I suggest you unzip the file in the C:\ directory.
(I also renamed the folder to "ft27")
Before you build the library it's good to read these articles:
* [Using MSYS with MinGW](http://www.mingw.org/wiki/MSYS)
* [Installation and Use of Supplementary Libraries with MinGW](http://www.mingw.org/wiki/LibraryPathHOWTO)
* [Include Path](http://www.mingw.org/wiki/IncludePathHOWTO)
Inside the unzipped folder there is another folder named "docs". Open it and read the INSTALL.UNIX (using notepad).
Pay attention to paragraph 3 (Build and Install the Library). So, let's begin the installation.
To give the appropriate commands we will use the MSYS command prompt (not cmd.exe of windows) which is UNIX like.
Follow the path C:\MinGW\msys\1.0 and double click "msys.bat". The command prompt environment appears.
Enter "ft27" directory using the cd commands:
```
cd /c
cd ft27
```
and then type one by one the commands:
```
./configure --prefix=/mingw
make
make install
```
Once you're finished, go inside "C:\MinGW\include" and there should be a new folder named "freetype2".
That, hopefully, means that you have installed the library correctly !!
#### STEP 3: Build fontconvert.c
Before proceeding I suggest you make a copy of Adafruit_GFX_library folder in C:\ directory.
Then, inside "fontconvert" folder open the "makefile" with an editor ( I used notepad++).
Change the commands so in the end the program looks like :
```
all: fontconvert
CC = gcc
CFLAGS = -Wall -I c:/mingw/include/freetype2
LIBS = -lfreetype
fontconvert: fontconvert.c
$(CC) $(CFLAGS) $< $(LIBS) -o $@
clean:
rm -f fontconvert
```
Go back in the command prompt and with a cd command enter the fontconvert directory.
```
cd /c/adafruit_gfx_library\fontconvert
```
Give the command:
```
make
```
This command will, eventually, create a "fontconvert.exe" file inside fontconvert directory.
#### STEP 4: Create your own font header files
Now that you have an executable file, you can use it to create your own fonts to work with Adafruit GFX lib.
So, if we suppose that you already have a .ttf file with your favorite fonts, jump to the command prompt and type:
```
./fontconvert yourfonts.ttf 9 > yourfonts9pt7b.h
```
You can read more details at: [learn.adafruit](https://learn.adafruit.com/adafruit-gfx-graphics-library/using-fonts).
Taraaaaaammm !! you've just created your new font header file. Put it inside the "Fonts" folder, grab a cup of coffee
and start playing with your Arduino (or whatever else ....)+ display module project.

View file

@ -0,0 +1,38 @@
#!/bin/bash
# Ugly little Bash script, generates a set of .h files for GFX using
# GNU FreeFont sources. There are three fonts: 'Mono' (Courier-like),
# 'Sans' (Helvetica-like) and 'Serif' (Times-like); four styles: regular,
# bold, oblique or italic, and bold+oblique or bold+italic; and four
# sizes: 9, 12, 18 and 24 point. No real error checking or anything,
# this just powers through all the combinations, calling the fontconvert
# utility and redirecting the output to a .h file for each combo.
# Adafruit_GFX repository does not include the source outline fonts
# (huge zipfile, different license) but they're easily acquired:
# http://savannah.gnu.org/projects/freefont/
convert=./fontconvert
inpath=~/Desktop/freefont/
outpath=../Fonts/
fonts=(FreeMono FreeSans FreeSerif)
styles=("" Bold Italic BoldItalic Oblique BoldOblique)
sizes=(9 12 18 24)
for f in ${fonts[*]}
do
for index in ${!styles[*]}
do
st=${styles[$index]}
for si in ${sizes[*]}
do
infile=$inpath$f$st".ttf"
if [ -f $infile ] # Does source combination exist?
then
outfile=$outpath$f$st$si"pt7b.h"
# printf "%s %s %s > %s\n" $convert $infile $si $outfile
$convert $infile $si > $outfile
fi
done
done
done