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