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