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