16 #include FT_FREETYPE_H 20 #define ENSURE(action, description...) { if (!(action)) { fprintf(stderr, "Error: "); fprintf(stderr, description); fprintf(stderr, "\n"); exit(-1);}} 38 void writeImageToPNGFile(
image_t * image,
char * filename);
41 #define CHARACTER_RANGE_START 0x20 42 #define CHARACTER_RANGE_END 0x7E 47 #if (GRID_WIDTH*GRID_HEIGHT < (NUMBER_OF_SYMBOLS+CHARACTER_RANGE_END-CHARACTER_RANGE_START+1)) 48 #error Grid too small. Consider increasing GRID_WIDTH or GRID_HEIGHT 53 int main(
int argc,
char * argv[]) {
58 int expectedNumberOfArguments = 7;
60 expectedNumberOfArguments = 8;
62 if (argc != expectedNumberOfArguments) {
64 fprintf(stderr,
"Usage: %s font_file glyph_width glyph_height font_name output_header output_implementation output_png\n", argv[0]);
66 fprintf(stderr,
"Usage: %s font_file glyph_width glyph_height font_name output_header output_implementation\n", argv[0]);
68 fprintf(stderr,
" font_file: Path of the font file to load\n");
69 fprintf(stderr,
" glyph_width: Width of bitmap glyphs, in pixels\n");
70 fprintf(stderr,
" glyph_height: Height of bitmap glyphs, in pixels\n");
71 fprintf(stderr,
" font_name: name of the loaded font\n");
72 fprintf(stderr,
" output_header: Name of the generated C header file\n");
73 fprintf(stderr,
" output_implementation: Name of the generated C source file\n");
75 fprintf(stderr,
" output_png: Name of the generated PNG file\n");
80 char * font_file = argv[1];
81 int requested_glyph_width = atoi(argv[2]);
82 int requested_glyph_height = atoi(argv[3]);
83 char * font_name = argv[4];
84 char * output_header = argv[5];
85 char * output_implementation = argv[6];
87 char * output_png = argv[7];
90 ENSURE(!FT_Init_FreeType(&library),
"Initializing library");
93 ENSURE(!FT_New_Face(library, font_file, 0, &face),
"Loading font file %s", font_file);
95 ENSURE(!FT_Set_Pixel_Sizes(face, requested_glyph_width, requested_glyph_height),
"Setting face pixel size to %dx%d", requested_glyph_width, requested_glyph_height);
103 int maxAboveBaseline = 0;
104 int maxBelowBaseline = 0;
106 ENSURE(!FT_Load_Char(face, character, FT_LOAD_RENDER),
"Loading character 0x%02x", character);
107 int aboveBaseline = face->glyph->bitmap_top;
108 int belowBaseline = face->glyph->bitmap.rows - face->glyph->bitmap_top;
109 int width = face->glyph->bitmap_left + face->glyph->bitmap.width;
110 if (width > maxWidth) {
113 if (aboveBaseline > maxAboveBaseline) {
114 maxAboveBaseline = aboveBaseline;
116 if (belowBaseline > maxBelowBaseline) {
117 maxBelowBaseline = belowBaseline;
122 ENSURE(!FT_Load_Char(face, wideChar, FT_LOAD_RENDER),
"Loading character 0x%02x", wideChar);
123 int aboveBaseline = face->glyph->bitmap_top;
124 int belowBaseline = face->glyph->bitmap.rows - face->glyph->bitmap_top;
125 int width = face->glyph->bitmap_left + face->glyph->bitmap.width;
126 if (width > maxWidth) {
129 if (aboveBaseline > maxAboveBaseline) {
130 maxAboveBaseline = aboveBaseline;
132 if (belowBaseline > maxBelowBaseline) {
133 maxBelowBaseline = belowBaseline;
137 int glyph_width = maxWidth-1;
138 int glyph_height = maxAboveBaseline+maxBelowBaseline;
149 for (
int i = 0; i<bitmap_image.
width;i++) {
150 for (
int j = 0; j<bitmap_image.
height;j++) {
151 pixel_t pixel = {.
red = 0xFF, .green = 0xFF, .blue = 0xFF};
152 if (i%(glyph_width+grid_size) >= glyph_width || j%(glyph_height+grid_size) >= glyph_height) {
153 pixel = (
pixel_t){.
red = 0xFF, .green = 0, .blue = 0};
155 *(bitmap_image.
pixels + j*bitmap_image.
width + i) = pixel;
164 ENSURE(!FT_Load_Char(face, character, FT_LOAD_RENDER),
"Loading character 0x%02x", character);
168 x*(glyph_width+grid_size) + face->glyph->bitmap_left,
169 y*(glyph_height+grid_size) + maxAboveBaseline - face->glyph->bitmap_top
178 ENSURE(!FT_Load_Char(face, wideChar, FT_LOAD_RENDER),
"Loading character 0x%02x", wideChar);
182 x*(glyph_width+grid_size) + face->glyph->bitmap_left,
183 y*(glyph_height+grid_size) + maxAboveBaseline - face->glyph->bitmap_top
188 writeImageToPNGFile(&bitmap_image, output_png);
191 FILE * headerFile = fopen(output_header,
"w");
192 fprintf(headerFile,
"/* Auto-generated by rasterizer */\n\n");
195 fprintf(headerFile,
"#define BITMAP_%s_CHARACTER_WIDTH %d\n", font_name, glyph_width);
196 fprintf(headerFile,
"#define BITMAP_%s_CHARACTER_HEIGHT %d\n\n", font_name, glyph_height);
200 FILE * sourceFile = fopen(output_implementation,
"w");
201 fprintf(sourceFile,
"/* Auto-generated by rasterizer */\n\n");
204 fprintf(sourceFile,
" {\n");
207 for (
int y = 0; y < glyph_height; y++) {
208 fprintf(sourceFile,
" {");
209 for (
int x = 0; x < glyph_width; x++) {
210 pixel_t * pixel = (bitmap_image.
pixels + (y+characterY)*bitmap_image.
width + (x+characterX));
211 fprintf(sourceFile,
"0x%02x", 0xFF - pixel->
green);
212 if (x+1 < glyph_width) {
213 fprintf(sourceFile,
", ");
216 fprintf(sourceFile,
"}");
217 if (y+1 < glyph_height) {
218 fprintf(sourceFile,
",");
220 fprintf(sourceFile,
"\n");
222 fprintf(sourceFile,
" }");
223 fprintf(sourceFile,
",");
224 fprintf(sourceFile,
"\n");
228 fprintf(sourceFile,
" {\n");
231 for (
int y = 0; y < glyph_height; y++) {
232 fprintf(sourceFile,
" {");
233 for (
int x = 0; x < glyph_width; x++) {
234 pixel_t * pixel = (bitmap_image.
pixels + (y+characterY)*bitmap_image.
width + (x+characterX));
235 fprintf(sourceFile,
"0x%02x", 0xFF - pixel->
green);
236 if (x+1 < glyph_width) {
237 fprintf(sourceFile,
", ");
240 fprintf(sourceFile,
"}");
241 if (y+1 < glyph_height) {
242 fprintf(sourceFile,
",");
244 fprintf(sourceFile,
"\n");
246 fprintf(sourceFile,
" }");
248 fprintf(sourceFile,
",");
250 fprintf(sourceFile,
"\n");
253 fprintf(sourceFile,
"};\n");
263 ENSURE(glyphBitmap->pixel_mode == FT_PIXEL_MODE_GRAY,
"Checking glyph is in FT_PIXEL_MODE_GRAY");
264 for (
int j=0;j<glyphBitmap->rows;j++) {
265 for (
int i=0;i<glyphBitmap->width;i++) {
266 uint8_t glyphPixel = *(glyphBitmap->buffer + j*glyphBitmap->pitch + i);
268 *currentPixelPointer = (
pixel_t){.
red = (0xFF-glyphPixel), .green = (0xFF-glyphPixel), .blue = (0xFF-glyphPixel)};
275 void writeImageToPNGFile(
image_t * image,
char * filename) {
276 FILE * file = fopen(filename,
"wb");
277 ENSURE(file !=
NULL,
"Opening file %s", filename);
279 png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL,
NULL,
NULL);
280 ENSURE(png !=
NULL,
"Allocating PNG write structure");
282 png_infop info = png_create_info_struct(png);
283 ENSURE(info !=
NULL,
"Allocating info structure");
285 png_init_io(png, file);
287 png_set_IHDR(png, info,
292 PNG_COMPRESSION_TYPE_DEFAULT,
293 PNG_FILTER_TYPE_DEFAULT);
295 png_write_info(png, info);
297 for (
int j=0;j<image->
height;j++) {
298 png_write_row(png, (png_bytep)(image->
pixels+j*image->
width));
301 png_write_end(png,
NULL);
303 png_free_data(png, info, PNG_FREE_ALL, -1);
304 png_destroy_write_struct(&png, (png_infopp)
NULL);
#define NUMBER_OF_SYMBOLS
void drawGlyphInImage(FT_Bitmap *glyphBitmap, image_t *image, int x, int y)
int main(int argc, char *argv[])
LIBA_BEGIN_DECLS void free(void *ptr)
#define CHARACTER_RANGE_END
#define ENSURE(action, description...)
wchar_t codePointForSymbol[NUMBER_OF_SYMBOLS]
void * malloc(size_t size)
#define CHARACTER_RANGE_START