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