]> git.tdb.fi Git - ttf2png.git/blob - ttf2png.c
Bump version to 2.0
[ttf2png.git] / ttf2png.c
1 /*
2 ttf2png - True Type Font to PNG converter
3 Copyright (c) 2004-2021 Mikko Rasa, Mikkosoft Productions
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <unistd.h>
23 #include <getopt.h>
24 #include <png.h>
25 #include <ft2build.h>
26 #include FT_FREETYPE_H
27
28 typedef struct sImage
29 {
30         unsigned w, h;
31         unsigned char *data;
32         unsigned border;
33 } Image;
34
35 typedef struct sGlyph
36 {
37         unsigned index;
38         unsigned code;
39         Image image;
40         unsigned x, y;
41         int offset_x;
42         int offset_y;
43         int advance;
44 } Glyph;
45
46 typedef struct sKerning
47 {
48         Glyph *left_glyph;
49         Glyph *right_glyph;
50         int distance;
51 } Kerning;
52
53 typedef struct sFont
54 {
55         unsigned size;
56         int ascent;
57         int descent;
58         unsigned n_glyphs;
59         Glyph *glyphs;
60         unsigned n_kerning;
61         Kerning *kerning;
62         Image image;
63 } Font;
64
65 typedef struct sRange
66 {
67         unsigned first;
68         unsigned last;
69 } Range;
70
71 typedef unsigned char bool;
72
73 void usage(void);
74 int convert_numeric_option(char, int);
75 void convert_code_point_range(char, Range *);
76 int str_to_code_point(const char *, char **);
77 void convert_size(char, unsigned *, unsigned *);
78 void sort_and_compact_ranges(Range *, unsigned *);
79 int range_cmp(const void *, const void *);
80 unsigned round_to_pot(unsigned);
81 int init_image(Image *, size_t, size_t);
82 int init_font(Font *, FT_Face, const Range *, unsigned, bool, unsigned, unsigned);
83 int init_glyphs(Font *, FT_Face, const Range *, bool, unsigned, unsigned);
84 int copy_bitmap(const FT_Bitmap *, Image *);
85 unsigned sqrti(unsigned);
86 unsigned find_distance_to_edge(const Image *, int, int, unsigned);
87 int create_distance_field(const FT_Bitmap *, Image *, unsigned, unsigned);
88 int render_grid(Font *, unsigned, unsigned, unsigned, bool);
89 int render_packed(Font *, unsigned, unsigned);
90 int save_defs(const char *, const Font *);
91 int save_png(const char *, const Image *, bool, bool, bool);
92
93 char verbose = 0;
94
95 int main(int argc, char **argv)
96 {
97         char *fn;
98         Range *ranges = NULL;
99         unsigned n_ranges = 0;
100         unsigned size = 10;
101         unsigned cpl = 0;
102         unsigned cellw = 0;
103         unsigned cellh = 0;
104         bool autohinter = 0;
105         bool seq = 0;
106         bool alpha = 0;
107         bool invert = 0;
108         bool pack = 0;
109         unsigned margin = 0;
110         unsigned padding = 1;
111         bool npot = 0;
112         unsigned distfield = 0;
113         unsigned border = 0;
114
115         FT_Library freetype;
116         FT_Face face;
117
118         int err;
119         int i;
120
121         char *out_fn = "font.png";
122         char *def_fn = NULL;
123
124         Font font;
125
126         if(argc<2)
127         {
128                 usage();
129                 return 1;
130         }
131
132         while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:gf:b:")) != -1)
133         {
134                 switch(i)
135                 {
136                 case 'r':
137                         ranges = (Range *)realloc(ranges, (++n_ranges)*sizeof(Range));
138                         convert_code_point_range('r', &ranges[n_ranges-1]);
139                         break;
140                 case 's':
141                         size = convert_numeric_option('s', 1);
142                         break;
143                 case 'l':
144                         cpl = convert_numeric_option('l', 1);
145                         break;
146                 case 'c':
147                         convert_size('c', &cellw, &cellh);
148                         break;
149                 case 'o':
150                         out_fn = optarg;
151                         break;
152                 case 'a':
153                         autohinter = 1;
154                         break;
155                 case 't':
156                         alpha = 1;
157                         break;
158                 case 'v':
159                         ++verbose;
160                         break;
161                 case 'h':
162                 case '?':
163                         usage();
164                         return 0;
165                 case 'e':
166                         seq = 1;
167                         break;
168                 case 'd':
169                         def_fn = optarg;
170                         break;
171                 case 'p':
172                         pack = 1;
173                         break;
174                 case 'i':
175                         invert = 1;
176                         break;
177                 case 'm':
178                         margin = convert_numeric_option('m', 0);
179                         break;
180                 case 'n':
181                         padding = convert_numeric_option('n', 0);
182                         break;
183                 case 'g':
184                         npot = 1;
185                         break;
186                 case 'f':
187                         distfield = convert_numeric_option('f', 1);
188                         break;
189                 case 'b':
190                         border = convert_numeric_option('b', 1);
191                         break;
192                 }
193         }
194         if(!strcmp(out_fn, "-"))
195                 verbose = 0;
196
197         if(optind!=argc-1)
198         {
199                 usage();
200                 return 1;
201         }
202
203         fn = argv[optind];
204
205         err = FT_Init_FreeType(&freetype);
206         if(err)
207         {
208                 fprintf(stderr, "Couldn't initialize FreeType library\n");
209                 return 1;
210         }
211
212         err = FT_New_Face(freetype, fn, 0, &face);
213         if(err)
214         {
215                 fprintf(stderr, "Couldn't load font file\n");
216                 if(err==FT_Err_Unknown_File_Format)
217                         fprintf(stderr, "Unknown file format\n");
218                 return 1;
219         }
220
221         if(verbose)
222         {
223                 const char *name = FT_Get_Postscript_Name(face);
224                 printf("Font name: %s\n", name);
225                 printf("Glyphs:    %ld\n", face->num_glyphs);
226         }
227
228         font.size = size;
229         if(distfield)
230         {
231                 if(!border)
232                         border = sqrti(font.size);
233                 size *= distfield;
234         }
235
236         err = FT_Set_Pixel_Sizes(face, 0, size);
237         if(err)
238         {
239                 fprintf(stderr, "Couldn't set size\n");
240                 return 1;
241         }
242
243         if(!n_ranges)
244         {
245                 ranges = malloc(sizeof(Range));
246                 ranges[0].first = 0;
247                 ranges[0].last = 255;
248                 n_ranges = 1;
249         }
250         else
251                 sort_and_compact_ranges(ranges, &n_ranges);
252
253         err = init_font(&font, face, ranges, n_ranges, autohinter, distfield, border);
254         if(err)
255                 return 1;
256
257         if(!font.n_glyphs)
258         {
259                 fprintf(stderr, "No glyphs found in the requested range\n");
260                 return 1;
261         }
262
263         if(pack)
264                 err = render_packed(&font, margin, padding);
265         else
266                 err = render_grid(&font, cellw, cellh, cpl, seq);
267         if(err)
268                 return 1;
269
270         err = save_png(out_fn, &font.image, (alpha && !distfield), (invert || distfield), npot);
271         if(err)
272                 return 1;
273
274         if(def_fn)
275                 save_defs(def_fn, &font);
276
277         for(i=0; (unsigned)i<font.n_glyphs; ++i)
278                 free(font.glyphs[i].image.data);
279         free(font.glyphs);
280         free(font.kerning);
281         free(font.image.data);
282         free(ranges);
283
284         FT_Done_Face(face);
285         FT_Done_FreeType(freetype);
286
287         return 0;
288 }
289
290 void usage(void)
291 {
292         printf("ttf2png 2.0 - True Type Font to PNG converter\n"
293                 "Copyright (c) 2004-2021  Mikko Rasa, Mikkosoft Productions\n"
294                 "Distributed under the GNU General Public License\n\n");
295
296         printf("Usage: ttf2png [options] <TTF file>\n\n");
297
298         printf("Accepted options (default values in [brackets])\n"
299                 "  -r  Range of code points to convert [0,255]\n"
300                 "  -s  Font size to use, in pixels [10]\n"
301                 "  -l  Number of glyphs to put in one line [auto]\n"
302                 "  -c  Glyph cell size, in pixels (grid mode only) [auto]\n"
303                 "  -o  Output file name (or - for stdout) [font.png]\n");
304         printf("  -a  Force autohinter\n"
305                 "  -t  Render glyphs to alpha channel\n"
306                 "  -i  Invert colors of the glyphs\n"
307                 "  -v  Increase the level of verbosity\n"
308                 "  -e  Use cells in sequence, without gaps (grid mode only)\n"
309                 "  -p  Pack the glyphs tightly instead of in a grid\n"
310                 "  -m  Margin around image edges (packed mode only) [0]\n"
311                 "  -n  Padding between glyphs (packed mode only) [1]\n"
312                 "  -g  Allow non-power-of-two result\n");
313         printf("  -f  Create a distance field texture\n"
314                 "  -b  Specify distance field border zone width\n"
315                 "  -d  File name for writing glyph definitions\n"
316                 "  -h  Print this message\n");
317 }
318
319 int convert_numeric_option(char opt, int min_value)
320 {
321         int value;
322         char *ptr;
323
324         value = strtol(optarg, &ptr, 0);
325         if(value<min_value || *ptr)
326         {
327                 printf("Invalid option argument in -%c %s\n", opt, optarg);
328                 exit(1);
329         }
330
331         return value;
332 }
333
334 void convert_code_point_range(char opt, Range *range)
335 {
336         int value;
337         char *ptr;
338
339         if(!strcmp(optarg, "all"))
340         {
341                 range->first = 0;
342                 range->last = 0x10FFFF;
343                 return;
344         }
345
346         value = str_to_code_point(optarg, &ptr);
347         if(value>=0 && *ptr==',')
348         {
349                 range->first = value;
350                 value = str_to_code_point(ptr+1, &ptr);
351                 if(value>=(int)range->first && !*ptr)
352                 {
353                         range->last = value;
354                         return;
355                 }
356         }
357
358         printf("Invalid option argument in -%c %s\n", opt, optarg);
359         exit(1);
360 }
361
362 int str_to_code_point(const char *nptr, char **endptr)
363 {
364         if(nptr[0]=='U' && nptr[1]=='+')
365                 return strtoul(nptr+2, endptr, 16);
366         else if(nptr[0]&0x80)
367         {
368                 unsigned bytes;
369                 unsigned code;
370                 unsigned i;
371
372                 if(endptr)
373                         *endptr = (char *)nptr;
374
375                 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
376                         if((nptr[bytes]&0xC0)!=0x80)
377                                 return -1;
378                 if(bytes<2)
379                         return -1;
380
381                 code = nptr[0]&(0x3F>>bytes);
382                 for(i=1; i<bytes; ++i)
383                         code = (code<<6)|(nptr[i]&0x3F);
384
385                 if(endptr)
386                         *endptr = (char *)nptr+bytes;
387
388                 return code;
389         }
390         else if(isdigit(nptr[0]))
391                 return strtoul(nptr, endptr, 0);
392         else
393         {
394                 if(endptr)
395                         *endptr = (char *)nptr+1;
396                 return *nptr;
397         }
398 }
399
400 void convert_size(char opt, unsigned *width, unsigned *height)
401 {
402         int value;
403         char *ptr;
404
405         if(!strcmp(optarg, "auto"))
406         {
407                 *width = 0;
408                 *height = 0;
409                 return;
410         }
411         else if(!strcmp(optarg, "autorect"))
412         {
413                 *width = 0;
414                 *height = 1;
415                 return;
416         }
417
418         value = strtol(optarg, &ptr, 0);
419         if(value>0)
420         {
421                 *width = value;
422                 if(*ptr=='x')
423                 {
424                         value = strtol(ptr+1, &ptr, 0);
425                         if(value>0 && !*ptr)
426                         {
427                                 *height = value;
428                                 return;
429                         }
430                 }
431                 else if(!*ptr)
432                 {
433                         *height = *width;
434                         return;
435                 }
436         }
437
438         printf("Invalid option argument in -%c %s\n", opt, optarg);
439         exit(1);
440 }
441
442 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
443 {
444         unsigned i, j;
445
446         if(!*n_ranges)
447                 return;
448
449         qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
450         for(i=0, j=1; j<*n_ranges; ++j)
451         {
452                 if(ranges[i].last+1>=ranges[j].first)
453                 {
454                         if(ranges[j].last>ranges[i].last)
455                                 ranges[i].last = ranges[j].last;
456                 }
457                 else
458                 {
459                         ++i;
460                         if(i!=j)
461                                 ranges[i] = ranges[j];
462                 }
463         }
464
465         *n_ranges = i+1;
466 }
467
468 int range_cmp(const void *p1, const void *p2)
469 {
470         const Range *r1 = (const Range *)p1;
471         const Range *r2 = (const Range *)p2;
472         if(r1->first!=r2->first)
473                 return (r1->first<r2->first ? -1 : 1);
474         else if(r1->last!=r2->last)
475                 return (r1->last<r2->last ? -1 : 1);
476         else
477                 return 0;
478 }
479
480 unsigned round_to_pot(unsigned n)
481 {
482         n -= 1;
483         n |= n>>1;
484         n |= n>>2;
485         n |= n>>4;
486         n |= n>>8;
487         n |= n>>16;
488
489         return n+1;
490 }
491
492 int init_image(Image *image, size_t w, size_t h)
493 {
494         size_t s;
495
496         image->w = w;
497         image->h = h;
498         image->data = NULL;
499         image->border = 0;
500
501         if(!image->w || !image->h)
502                 return 0;
503
504         s = w*h;
505         if(s/h!=w)
506         {
507                 fprintf(stderr, "Cannot allocate memory for a %dx%d image\n", image->w, image->h);
508                 return -1;
509         }
510
511         image->data = malloc(s);
512         if(!image->data)
513         {
514                 fprintf(stderr, "Cannot allocate memory for a %dx%d image\n", image->w, image->h);
515                 return -1;
516         }
517
518         return 0;
519 }
520
521 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter, unsigned distfield, unsigned border)
522 {
523         unsigned i, j;
524         unsigned size = 0;
525         int scale = (distfield>0 ? distfield : 1);
526
527         font->ascent = (face->size->metrics.ascender/scale+63)/64;
528         font->descent = (face->size->metrics.descender/scale-63)/64;
529
530         if(verbose>=1)
531         {
532                 printf("Ascent:    %d\n", font->ascent);
533                 printf("Descent:   %d\n", font->descent);
534         }
535
536         font->n_glyphs = 0;
537         font->glyphs = NULL;
538         for(i=0; i<n_ranges; ++i)
539                 if(init_glyphs(font, face, &ranges[i], autohinter, distfield, border))
540                         return -1;
541
542         if(verbose>=1)
543                 printf("Loaded %u glyphs\n", font->n_glyphs);
544
545         font->n_kerning = 0;
546         font->kerning = NULL;
547         for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
548                 if(j!=i)
549                 {
550                         FT_Vector kerning;
551                         FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
552
553                         /* FreeType documentation says that vertical kerning is practically
554                         never used, so we ignore it. */
555                         if(kerning.x)
556                         {
557                                 Kerning *kern;
558
559                                 if(font->n_kerning>=size)
560                                 {
561                                         size += 16;
562                                         font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
563                                 }
564
565                                 kern = &font->kerning[font->n_kerning++];
566                                 kern->left_glyph = &font->glyphs[i];
567                                 kern->right_glyph = &font->glyphs[j];
568                                 kern->distance = (kerning.x/scale+32)/64;
569                         }
570                 }
571
572         if(verbose>=1)
573                 printf("Loaded %d kerning pairs\n", font->n_kerning);
574
575         return 0;
576 }
577
578 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield, unsigned border)
579 {
580         unsigned i, j;
581         unsigned size = font->n_glyphs;
582         int scale = (distfield>0 ? distfield : 1);
583
584         for(i=range->first; i<=range->last; ++i)
585         {
586                 unsigned n;
587                 FT_Bitmap *bmp = &face->glyph->bitmap;
588                 int flags = 0;
589                 Glyph *glyph;
590
591                 n = FT_Get_Char_Index(face, i);
592                 if(!n)
593                         continue;
594
595                 if(autohinter)
596                         flags |= FT_LOAD_FORCE_AUTOHINT;
597                 FT_Load_Glyph(face, n, flags);
598                 FT_Render_Glyph(face->glyph, (distfield ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL));
599
600                 if(verbose>=2)
601                 {
602                         printf("  Code point U+%04X", i);
603                         if(i>=0x20 && i<0x7F)
604                                 printf(" (%c)", i);
605                         else if(i>=0xA0 && i<=0x10FFFF)
606                         {
607                                 char utf8[5];
608                                 unsigned bytes;
609
610                                 for(bytes=2; i>>(1+bytes*5); ++bytes) ;
611                                 for(j=0; j<bytes; ++j)
612                                         utf8[j] = 0x80 | ((i>>((bytes-j-1)*6))&0x3F);
613                                 utf8[0] |= 0xF0<<(4-bytes);
614                                 utf8[j] = 0;
615
616                                 printf(" (%s)", utf8);
617                         }
618                         printf(": glyph %u, size %dx%d\n", n, bmp->width/scale, bmp->rows/scale);
619                 }
620
621                 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
622                 {
623                         fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
624                         continue;
625                 }
626
627                 if(font->n_glyphs>=size)
628                 {
629                         size += 16;
630                         font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
631                 }
632
633                 glyph = &font->glyphs[font->n_glyphs++];
634                 glyph->index = n;
635                 glyph->code = i;
636                 glyph->offset_x = (int)(face->glyph->bitmap_left+scale/2)/scale;
637                 glyph->offset_y = (int)(face->glyph->bitmap_top-bmp->rows+scale/2)/scale;
638                 glyph->advance = (int)(face->glyph->advance.x/scale+32)/64;
639
640                 /* Copy the glyph image since FreeType uses a global buffer, which would
641                 be overwritten by the next glyph.  Negative pitch means the scanlines
642                 start from the bottom. */
643                 if(distfield)
644                 {
645                         glyph->offset_x -= border;
646                         glyph->offset_y -= border;
647                         create_distance_field(bmp, &glyph->image, distfield, border);
648                 }
649                 else
650                 {
651                         if(copy_bitmap(bmp, &glyph->image))
652                                 return -1;
653                 }
654         }
655
656         return 0;
657 }
658
659 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
660 {
661         unsigned x, y;
662         unsigned char *src;
663         unsigned char *dst;
664
665         if(init_image(image, bmp->width, bmp->rows))
666                 return -1;
667         if(!image->w || !image->h)
668                 return 0;
669
670         if(bmp->pitch<0)
671                 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
672         else
673                 src = bmp->buffer;
674         dst = image->data;
675
676         for(y=0; y<bmp->rows; ++y)
677         {
678                 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
679                 {
680                         for(x=0; x<bmp->width; ++x)
681                                 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
682                 }
683                 else
684                 {
685                         for(x=0; x<bmp->width; ++x)
686                                 dst[x] = src[x];
687                 }
688
689                 src += bmp->pitch;
690                 dst += image->w;
691         }
692
693         return 0;
694 }
695
696 unsigned sqrti(unsigned num)
697 {
698         unsigned result = (num>0xFFFF ? 0xFFFF : 0x100);
699         while(result && result*result>=result+num)
700                 result -= (result*result+result-num)/(result*2);
701
702         return result;
703 }
704
705 unsigned find_distance_to_edge(const Image *image, int origin_x, int origin_y, unsigned range)
706 {
707         unsigned i, j;
708         int x, y;
709         unsigned char origin_pixel = 0;
710         unsigned closest = range*range;
711
712         if(origin_x>=0 && (unsigned)origin_x<image->w && origin_y>=0 && (unsigned)origin_y<image->h)
713                 origin_pixel = image->data[origin_x+origin_y*image->w];
714
715         x = origin_x-1;
716         y = origin_y-1;
717         for(i=1; (i<range && i*i<=closest); ++i, --x, --y) for(j=0; j<4; ++j)
718         {
719                 unsigned k;
720                 int dx = (j==0 ? 1 : j==2 ? -1 : 0);
721                 int dy = (j==1 ? 1 : j==3 ? -1 : 0);
722
723                 for(k=0; k<i*2; ++k, x+=dx, y+=dy)
724                 {
725                         unsigned char pixel = 0;
726                         if(x>=0 && (unsigned)x<image->w && y>=0 && (unsigned)y<image->h)
727                                 pixel = image->data[x+y*image->w];
728                                 
729                         if((pixel^origin_pixel)&0x80)
730                         {
731                                 unsigned d = 2*i*i + k*k - 2*k*i;
732                                 if(d<closest)
733                                         closest = d;
734                         }
735                 }
736         }
737
738         return sqrti(closest*0x3F01)/range;
739 }
740
741 int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
742 {
743         unsigned x, y;
744         Image base_image;
745
746         if(init_image(image, (bmp->width+scale-1)/scale+2*margin, (bmp->rows+scale-1)/scale+2*margin))
747                 return -1;
748         if(!image->w || !image->h)
749                 return 0;
750
751         if(copy_bitmap(bmp, &base_image))
752                 return -1;
753
754         image->border = margin;
755         for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
756         {
757                 int bx = (x-margin)*scale+scale/2;
758                 int by = (y-margin)*scale+scale/2;
759                 unsigned char pixel = find_distance_to_edge(&base_image, bx, by, margin*scale);
760                 if(bx>=0 && (unsigned)bx<base_image.w && by>=0 && (unsigned)by<base_image.h)
761                         pixel |= base_image.data[bx+by*base_image.w]&0x80;
762                 if(!(pixel&0x80))
763                         pixel = 0x80-pixel;
764                 image->data[x+y*image->w] = pixel;
765         }
766
767         free(base_image.data);
768
769         return 0;
770 }
771
772 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq)
773 {
774         unsigned i;
775         int top = 0, bot = 0;
776         unsigned first, n_cells;
777         unsigned maxw = 0, maxh = 0;
778
779         /* Find extremes of the glyph images. */
780         for(i=0; i<font->n_glyphs; ++i)
781         {
782                 int y;
783
784                 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
785                 if(y>top)
786                         top = y;
787                 if(font->glyphs[i].offset_y<bot)
788                         bot = font->glyphs[i].offset_y;
789                 if(font->glyphs[i].image.w>maxw)
790                         maxw = font->glyphs[i].image.w;
791                 if(font->glyphs[i].image.h>maxh)
792                         maxh = font->glyphs[i].image.h;
793         }
794
795         if(cellw==0)
796         {
797                 /* Establish a large enough cell to hold all glyphs in the range. */
798                 int square = (cellh==cellw);
799                 cellw = maxw;
800                 cellh = top-bot;
801                 if(square)
802                 {
803                         if(cellh>cellw)
804                                 cellw = cellh;
805                         else
806                                 cellh = cellw;
807                 }
808         }
809
810         if(verbose>=1)
811         {
812                 printf("Max size:  %u x %u\n", maxw, maxh);
813                 printf("Y range:   [%d %d]\n", bot, top);
814                 printf("Cell size: %u x %u\n", cellw, cellh);
815                 if(maxw>cellw || (unsigned)(top-bot)>cellh)
816                         fprintf(stderr, "Warning: character size exceeds cell size\n");
817         }
818
819         if(cpl==0)
820         {
821                 /* Determine number of characters per line, trying to fit all the glyphs
822                 in a square image. */
823                 for(i=1;; i<<=1)
824                 {
825                         cpl = i/cellw;
826                         if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
827                                 break;
828                 }
829         }
830
831         first = font->glyphs[0].code;
832         if(seq)
833                 n_cells = font->n_glyphs;
834         else
835         {
836                 first -= first%cpl;
837                 n_cells = font->glyphs[font->n_glyphs-1].code+1-first;
838         }
839
840         if(init_image(&font->image, cpl*cellw, (n_cells+cpl-1)/cpl*cellh))
841                 return -1;
842         memset(font->image.data, 0, font->image.w*font->image.h);
843
844         for(i=0; i<font->n_glyphs; ++i)
845         {
846                 Glyph *glyph;
847                 unsigned ci, cx, cy;
848                 unsigned x, y;
849
850                 glyph = &font->glyphs[i];
851
852                 if(seq)
853                         ci = i;
854                 else
855                         ci = glyph->code-first;
856
857                 cx = (ci%cpl)*cellw;
858                 cy = (ci/cpl)*cellh;
859
860                 if(cellw>glyph->image.w)
861                         cx += (cellw-glyph->image.w)/2;
862                 cy += top-glyph->offset_y-glyph->image.h;
863
864                 glyph->x = cx;
865                 glyph->y = cy;
866
867                 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
868                 {
869                         if(cx+x>=font->image.w || cy+y>=font->image.h)
870                                 continue;
871                         font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w];
872                 }
873         }
874
875         return 0;
876 }
877
878 int render_packed(Font *font, unsigned margin, unsigned padding)
879 {
880         unsigned i;
881         size_t area = 0;
882         bool *used_glyphs;
883         unsigned *used_pixels;
884         unsigned cx = margin, cy;
885         unsigned used_h = 0;
886
887         /* Compute the total area occupied by glyphs and padding. */
888         for(i=0; i<font->n_glyphs; ++i)
889         {
890                 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
891                 if(a<area)
892                 {
893                         fprintf(stderr, "Overflow in counting total glyph area\n");
894                         return -1;
895                 }
896                 area = a;
897         }
898
899         /* Find an image size that's approximately square. */
900         for(font->image.w=1;; font->image.w<<=1)
901         {
902                 if(font->image.w<=margin*2)
903                         continue;
904                 font->image.h = area/(font->image.w-margin*2)+margin*2;
905                 if(font->image.h<=font->image.w)
906                         break;
907         }
908
909         /* Add some extra space to accommodate packing imperfections. */
910         font->image.h = font->image.h*3/2;
911
912         /* Allocate arrays for storing the image and keeping track of used pixels and
913         glyphs.  Since glyphs are rectangular and the image is filled starting from
914         the top, it's enough to track the number of used pixels at the top of each
915         column. */
916         if(init_image(&font->image, font->image.w, font->image.h))
917                 return -1;
918         memset(font->image.data, 0, font->image.w*font->image.h);
919         used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
920         memset(used_pixels, 0, font->image.w*sizeof(unsigned));
921         used_glyphs = (bool *)malloc(font->n_glyphs);
922         memset(used_glyphs, 0, font->n_glyphs);
923
924         for(cy=margin; cy+margin<font->image.h;)
925         {
926                 unsigned w;
927                 unsigned x, y;
928                 Glyph *glyph = NULL;
929                 unsigned best_score = 0;
930                 unsigned target_h = 0;
931
932                 /* Find the leftmost free pixel on this row.  Also record the lowest
933                 extent of glyphs to the left of the free position. */
934                 for(; (cx+margin<font->image.w && used_pixels[cx]>cy); ++cx)
935                         if(used_pixels[cx]-cy-padding>target_h)
936                                 target_h = used_pixels[cx]-cy-padding;
937
938                 if(cx+margin>=font->image.w)
939                 {
940                         cx = margin;
941                         ++cy;
942                         continue;
943                 }
944
945                 /* Count the free pixel at this position. */
946                 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
947
948                 /* Find a suitable glyph to put here. */
949                 for(i=0; i<font->n_glyphs; ++i)
950                 {
951                         Glyph *g;
952
953                         g = &font->glyphs[i];
954                         if(!used_glyphs[i] && g->image.w<=w)
955                         {
956                                 unsigned score;
957
958                                 /* Prefer glyphs that would reach exactly as low as the ones left
959                                 of here.  This aims to create a straight edge at the bottom for
960                                 lining up further glyphs. */
961                                 score = g->image.h+padding;
962                                 if(g->image.h==target_h)
963                                         score *= g->image.w;
964                                 else
965                                         score += g->image.w;
966
967                                 if(score>best_score)
968                                 {
969                                         glyph = g;
970                                         best_score = score;
971                                 }
972                         }
973                 }
974
975                 if(!glyph)
976                 {
977                         cx += w;
978                         continue;
979                 }
980
981                 used_glyphs[glyph-font->glyphs] = 1;
982                 glyph->x = cx;
983                 glyph->y = cy;
984
985                 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
986                 {
987                         if(cx+x>=font->image.w || cy+y>=font->image.h)
988                                 continue;
989                         font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w];
990                 }
991                 for(x=0; x<glyph->image.w+2*padding; ++x)
992                 {
993                         if(cx+x<padding || cx+x>=font->image.w+padding)
994                                 continue;
995                         if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
996                                 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
997                 }
998
999                 if(cy+glyph->image.h+margin>used_h)
1000                         used_h = cy+glyph->image.h+margin;
1001         }
1002
1003         /* Trim the image to the actually used size, in case the original estimate
1004         was too pessimistic. */
1005         font->image.h = used_h;
1006
1007         free(used_glyphs);
1008         free(used_pixels);
1009
1010         return 0;
1011 }
1012
1013 int save_defs(const char *fn, const Font *font)
1014 {
1015         FILE *out;
1016         unsigned i;
1017
1018         out = fopen(fn, "w");
1019         if(!out)
1020         {
1021                 fprintf(stderr, "Couldn't open %s\n",fn);
1022                 return -1;
1023         }
1024
1025         fprintf(out, "# Image/font info:\n");
1026         fprintf(out, "# width height size ascent descent\n");
1027         fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
1028
1029         fprintf(out, "\n# Code point mapping:\n");
1030         fprintf(out, "# code index\n");
1031         for(i=0; i<font->n_glyphs; ++i)
1032         {
1033                 const Glyph *g = &font->glyphs[i];
1034                 fprintf(out, "code %u %u\n", g->code, g->index);
1035         }
1036
1037         fprintf(out, "\n# Metrics info:\n");
1038         fprintf(out, "# index width height offset_x offset_y advance\n");
1039         for(i=0; i<font->n_glyphs; ++i)
1040         {
1041                 const Glyph *g = &font->glyphs[i];
1042                 int b = g->image.border;
1043                 fprintf(out, "metrics %u %u %u %d %d %d\n", g->index, g->image.w-2*b, g->image.h-2*b, g->offset_x+b, g->offset_y+b, g->advance);
1044         }
1045
1046         fprintf(out, "\n# Glyph info:\n");
1047         fprintf(out, "# index x y width height border\n");
1048         for(i=0; i<font->n_glyphs; ++i)
1049         {
1050                 const Glyph *g = &font->glyphs[i];
1051                 fprintf(out, "glyph %u %u %u %u %u %u\n", g->index, g->x, g->y, g->image.w, g->image.h, g->image.border);
1052         }
1053
1054         fprintf(out, "\n# Kerning info:\n");
1055         fprintf(out, "# left right distance\n");
1056         for(i=0; i<font->n_kerning; ++i)
1057         {
1058                 const Kerning *k = &font->kerning[i];
1059                 fprintf(out, "kern %u %u %d\n", k->left_glyph->index, k->right_glyph->index, k->distance);
1060         }
1061
1062         fclose(out);
1063
1064         return 0;
1065 }
1066
1067 int save_png(const char *fn, const Image *image, bool alpha, bool invert, bool npot)
1068 {
1069         FILE *out;
1070         png_struct *pngs;
1071         png_info *pngi;
1072         unsigned w, h;
1073         png_byte *row;
1074         unsigned x, y;
1075         int color;
1076         unsigned flip_bits = (invert==alpha ? 0xFF : 0x00);
1077         unsigned char *src = image->data;
1078
1079         if(!strcmp(fn, "-"))
1080                 out = stdout;
1081         else
1082         {
1083                 out = fopen(fn, "wb");
1084                 if(!out)
1085                 {
1086                         fprintf(stderr, "Couldn't open %s\n",fn);
1087                         return -1;
1088                 }
1089         }
1090
1091         pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1092         if(!pngs)
1093         {
1094                 fprintf(stderr, "Error writing PNG file\n");
1095                 return -1;
1096         }
1097         pngi = png_create_info_struct(pngs);
1098         if(!pngi)
1099         {
1100                 png_destroy_write_struct(&pngs, NULL);
1101                 fprintf(stderr, "Error writing PNG file\n");
1102                 return -1;
1103         }
1104
1105         w = (npot ? image->w : round_to_pot(image->w));
1106         h = (npot ? image->h : round_to_pot(image->h));
1107         color = (alpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY);
1108         png_set_IHDR(pngs, pngi, w, h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1109
1110         png_init_io(pngs, out);
1111         png_write_info(pngs, pngi);
1112         row = (png_byte *)malloc(w*(1+alpha));
1113         if(alpha)
1114         {
1115                 for(x=0; x<w; ++x)
1116                 {
1117                         row[x*2] = 255;
1118                         row[x*2+1] = flip_bits;
1119                 }
1120                 for(y=0; y<image->h; ++y)
1121                 {
1122                         for(x=0; x<image->w; ++x)
1123                                 row[x*2+1] = *src++^flip_bits;
1124                         png_write_row(pngs, row);
1125                 }
1126
1127                 for(x=0; x<w; ++x)
1128                         row[x*2+1] = 0;
1129         }
1130         else
1131         {
1132                 memset(row+image->w, flip_bits, w-image->w);
1133                 for(y=0; y<image->h; ++y)
1134                 {
1135                         for(x=0; x<image->w; ++x)
1136                                 row[x] = *src++^flip_bits;
1137                         png_write_row(pngs, row);
1138                 }
1139
1140                 memset(row, flip_bits, w);
1141         }
1142
1143         for(; y<h; ++y)
1144                 png_write_row(pngs, row);
1145
1146         png_write_end(pngs, pngi);
1147         png_destroy_write_struct(&pngs, &pngi);
1148         free(row);
1149
1150         if(verbose)
1151                 printf("Saved %dx%d PNG image to %s\n", w, h, fn);
1152
1153         fclose(out);
1154
1155         return 0;
1156 }