2 ttf2png - True Type Font to PNG converter
3 Copyright (c) 2004-2008 Mikko Rasa
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.
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.
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
26 #include FT_FREETYPE_H
45 typedef struct sKerning
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);
82 int init_glyphs(Font *, FT_Face, const Range *, bool, 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);
94 int main(int argc, char **argv)
98 unsigned n_ranges = 0;
109 unsigned padding = 1;
111 unsigned distfield = 0;
119 char *out_fn = "font.png";
130 while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:gf:")) != -1)
135 ranges = (Range *)realloc(ranges, (++n_ranges)*sizeof(Range));
136 convert_code_point_range('r', &ranges[n_ranges-1]);
139 size = convert_numeric_option('s', 1);
142 cpl = convert_numeric_option('l', 1);
145 convert_size('c', &cellw, &cellh);
176 margin = convert_numeric_option('m', 0);
179 padding = convert_numeric_option('n', 0);
185 distfield = convert_numeric_option('f', 1);
189 if(!strcmp(out_fn, "-"))
200 err = FT_Init_FreeType(&freetype);
203 fprintf(stderr, "Couldn't initialize FreeType library\n");
207 err = FT_New_Face(freetype, fn, 0, &face);
210 fprintf(stderr, "Couldn't load font file\n");
211 if(err==FT_Err_Unknown_File_Format)
212 fprintf(stderr, "Unknown file format\n");
218 const char *name = FT_Get_Postscript_Name(face);
219 printf("Font name: %s\n", name);
220 printf("Glyphs: %ld\n", face->num_glyphs);
227 err = FT_Set_Pixel_Sizes(face, 0, size);
230 fprintf(stderr, "Couldn't set size\n");
236 ranges = malloc(sizeof(Range));
238 ranges[0].last = 255;
242 sort_and_compact_ranges(ranges, &n_ranges);
244 err = init_font(&font, face, ranges, n_ranges, autohinter, distfield);
250 fprintf(stderr, "No glyphs found in the requested range\n");
255 err = render_packed(&font, margin, padding, npot);
257 err = render_grid(&font, cellw, cellh, cpl, seq, npot);
261 if(invert || distfield)
263 for(i=0; (unsigned)i<font.image.w*font.image.h; ++i)
264 font.image.data[i] = 255-font.image.data[i];
266 err = save_png(out_fn, &font.image, (alpha && !distfield));
271 save_defs(def_fn, &font);
273 for(i=0; (unsigned)i<font.n_glyphs; ++i)
274 free(font.glyphs[i].image.data);
277 free(font.image.data);
281 FT_Done_FreeType(freetype);
288 printf("ttf2png 1.1 - True Type Font to PNG converter\n"
289 "Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions\n"
290 "Distributed under the GNU General Public License\n\n");
292 printf("Usage: ttf2png [options] <TTF file>\n\n");
294 printf("Accepted options (default values in [brackets])\n"
295 " -r Range of code points to convert [0,255]\n"
296 " -s Font size to use, in pixels [10]\n"
297 " -l Number of glyphs to put in one line [auto]\n"
298 " -c Glyph cell size, in pixels (grid mode only) [auto]\n"
299 " -o Output file name (or - for stdout) [font.png]\n");
300 printf(" -a Force autohinter\n"
301 " -t Render glyphs to alpha channel\n"
302 " -i Invert colors of the glyphs\n"
303 " -v Increase the level of verbosity\n"
304 " -e Use cells in sequence, without gaps (grid mode only)\n"
305 " -p Pack the glyphs tightly instead of in a grid\n"
306 " -m Margin around image edges (packed mode only) [0]\n"
307 " -n Padding between glyphs (packed mode only) [1]\n"
308 " -g Allow non-power-of-two result\n"
309 " -f Create a distance field texture\n"
310 " -d File name for writing glyph definitions\n"
311 " -h Print this message\n");
314 int convert_numeric_option(char opt, int min_value)
319 value = strtol(optarg, &ptr, 0);
320 if(value<min_value || *ptr)
322 printf("Invalid option argument in -%c %s\n", opt, optarg);
329 void convert_code_point_range(char opt, Range *range)
334 if(!strcmp(optarg, "all"))
337 range->last = 0x10FFFF;
341 value = str_to_code_point(optarg, &ptr);
342 if(value>0 && *ptr==',')
344 range->first = value;
345 value = str_to_code_point(ptr+1, &ptr);
353 printf("Invalid option argument in -%c %s\n", opt, optarg);
357 unsigned str_to_code_point(const char *nptr, char **endptr)
359 if(nptr[0]=='U' && nptr[1]=='+')
360 return strtoul(nptr+2, endptr, 16);
361 else if(nptr[0]&0x80)
368 *endptr = (char *)nptr;
370 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
371 if((nptr[bytes]&0xC0)!=0x80)
376 code = nptr[0]&(0x3F>>bytes);
377 for(i=1; i<bytes; ++i)
378 code = (code<<6)|(nptr[i]&0x3F);
381 *endptr = (char *)nptr+bytes;
385 else if(isdigit(nptr[0]))
386 return strtoul(nptr, endptr, 0);
390 *endptr = (char *)nptr+1;
395 void convert_size(char opt, unsigned *width, unsigned *height)
400 if(!strcmp(optarg, "auto"))
406 else if(!strcmp(optarg, "autorect"))
413 value = strtol(optarg, &ptr, 0);
419 value = strtol(ptr+1, &ptr, 0);
433 printf("Invalid option argument in -%c %s\n", opt, optarg);
437 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
444 qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
445 for(i=0, j=1; j<*n_ranges; ++j)
447 if(ranges[i].last+1>=ranges[j].first)
449 if(ranges[j].last>ranges[i].last)
450 ranges[i].last = ranges[j].last;
456 ranges[i] = ranges[j];
463 int range_cmp(const void *p1, const void *p2)
465 const Range *r1 = (const Range *)p1;
466 const Range *r2 = (const Range *)p2;
467 if(r1->first!=r2->first)
468 return (r1->first<r2->first ? -1 : 1);
469 else if(r1->last!=r2->last)
470 return (r1->last<r2->last ? -1 : 1);
475 unsigned round_to_pot(unsigned n)
487 void *alloc_image_data(size_t a, size_t b)
491 /* Carry out the multiplication manually so we can check for overflow. */
500 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(c/1024*b));
507 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(a/1024*b));
511 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter, unsigned distfield)
515 int scale = (distfield>0 ? distfield : 1);
517 font->ascent = (face->size->metrics.ascender/scale+63)/64;
518 font->descent = (face->size->metrics.descender/scale-63)/64;
522 printf("Ascent: %d\n", font->ascent);
523 printf("Descent: %d\n", font->descent);
528 for(i=0; i<n_ranges; ++i)
529 if(init_glyphs(font, face, &ranges[i], autohinter, distfield))
533 printf("Loaded %u glyphs\n", font->n_glyphs);
536 font->kerning = NULL;
537 for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
541 FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
543 /* FreeType documentation says that vertical kerning is practically
544 never used, so we ignore it. */
549 if(font->n_kerning>=size)
552 font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
555 kern = &font->kerning[font->n_kerning++];
556 kern->left_code = font->glyphs[i].code;
557 kern->right_code = font->glyphs[j].code;
558 kern->distance = (kerning.x/scale+32)/64;
563 printf("Loaded %d kerning pairs\n", font->n_kerning);
568 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield)
571 unsigned size = font->n_glyphs;
572 int scale = (distfield>0 ? distfield : 1);
574 for(i=range->first; i<=range->last; ++i)
577 FT_Bitmap *bmp = &face->glyph->bitmap;
581 n = FT_Get_Char_Index(face, i);
586 flags |= FT_LOAD_FORCE_AUTOHINT;
587 FT_Load_Glyph(face, n, flags);
588 FT_Render_Glyph(face->glyph, (distfield ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL));
592 printf(" Code point U+%04X", i);
593 if(i>=0x20 && i<0x7F)
595 else if(i>=0xA0 && i<=0x10FFFF)
600 for(bytes=2; i>>(1+bytes*5); ++bytes) ;
601 for(j=0; j<bytes; ++j)
602 utf8[j] = 0x80 | ((i>>((bytes-j-1)*6))&0x3F);
603 utf8[0] |= 0xF0<<(4-bytes);
606 printf(" (%s)", utf8);
608 printf(": glyph %u, size %dx%d\n", n, bmp->width/scale, bmp->rows/scale);
611 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
613 fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
617 if(font->n_glyphs>=size)
620 font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
623 glyph = &font->glyphs[font->n_glyphs++];
626 glyph->offset_x = (int)(face->glyph->bitmap_left+scale/2)/scale;
627 glyph->offset_y = (int)(face->glyph->bitmap_top-bmp->rows+scale/2)/scale;
628 glyph->advance = (int)(face->glyph->advance.x/scale+32)/64;
630 /* Copy the glyph image since FreeType uses a global buffer, which would
631 be overwritten by the next glyph. Negative pitch means the scanlines
632 start from the bottom. */
637 glyph->offset_x -= margin;
638 glyph->offset_y -= margin;
639 create_distance_field(bmp, &glyph->image, distfield, margin);
643 if(copy_bitmap(bmp, &glyph->image))
651 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
657 image->w = bmp->width;
658 image->h = bmp->rows;
659 if(!image->w || !image->h)
665 image->data = (unsigned char *)malloc(image->w*image->h);
668 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
673 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
678 for(y=0; y<bmp->rows; ++y)
680 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
682 for(x=0; x<bmp->width; ++x)
683 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
687 for(x=0; x<bmp->width; ++x)
698 unsigned sqrti(unsigned num)
700 unsigned result = (num>0xFFFF ? 0xFFFF : 0x100);
701 while(result && result*result>=result+num)
702 result -= (result*result+result-num)/(result*2);
707 unsigned find_distance_to_edge(const Image *image, int origin_x, int origin_y, unsigned range)
711 unsigned char origin_pixel = 0;
712 unsigned closest = range*range;
714 if(origin_x>=0 && (unsigned)origin_x<image->w && origin_y>=0 && (unsigned)origin_y<image->h)
715 origin_pixel = image->data[origin_x+origin_y*image->w];
719 for(i=1; (i<range && i*i<=closest); ++i, --x, --y) for(j=0; j<4; ++j)
722 int dx = (j==0 ? 1 : j==2 ? -1 : 0);
723 int dy = (j==1 ? 1 : j==3 ? -1 : 0);
725 for(k=0; k<i*2; ++k, x+=dx, y+=dy)
727 unsigned char pixel = 0;
728 if(x>=0 && (unsigned)x<image->w && y>=0 && (unsigned)y<image->h)
729 pixel = image->data[x+y*image->w];
731 if((pixel^origin_pixel)&0x80)
733 unsigned d = 2*i*i + k*k - 2*k*i;
740 return sqrti(closest*0x3F01)/range;
743 int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
748 if(!bmp->width || !bmp->rows)
756 if(copy_bitmap(bmp, &base_image))
759 image->w = (base_image.w-1)/scale+2*margin+1;
760 image->h = (base_image.h-1)/scale+2*margin+1;
761 image->data = (unsigned char *)malloc(image->w*image->h);
764 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
765 free(base_image.data);
769 for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
771 int bx = (x-margin)*scale+scale/2;
772 int by = (y-margin)*scale+scale/2;
773 unsigned char pixel = find_distance_to_edge(&base_image, bx, by, margin*scale);
774 if(bx>=0 && (unsigned)bx<base_image.w && by>=0 && (unsigned)by<base_image.h)
775 pixel |= base_image.data[bx+by*base_image.w]&0x80;
778 image->data[x+y*image->w] = pixel;
781 free(base_image.data);
786 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot)
789 int top = 0, bot = 0;
790 unsigned first, last;
791 unsigned maxw = 0, maxh = 0;
793 /* Find extremes of the glyph images. */
794 for(i=0; i<font->n_glyphs; ++i)
798 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
801 if(font->glyphs[i].offset_y<bot)
802 bot = font->glyphs[i].offset_y;
803 if(font->glyphs[i].image.w>maxw)
804 maxw = font->glyphs[i].image.w;
805 if(font->glyphs[i].image.h>maxh)
806 maxh = font->glyphs[i].image.h;
811 /* Establish a large enough cell to hold all glyphs in the range. */
812 int square = (cellh==cellw);
826 printf("Max size: %u x %u\n", maxw, maxh);
827 printf("Y range: [%d %d]\n", bot, top);
828 printf("Cell size: %u x %u\n", cellw, cellh);
829 if(maxw>cellw || (unsigned)(top-bot)>cellh)
830 fprintf(stderr, "Warning: character size exceeds cell size\n");
835 /* Determine number of characters per line, trying to fit all the glyphs
836 in a square image. */
840 if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
845 first = font->glyphs[0].code;
848 last = font->glyphs[font->n_glyphs-1].code;
850 font->image.w = cpl*cellw;
852 font->image.w = round_to_pot(font->image.w);
854 font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh;
856 font->image.h = (last-first+cpl)/cpl*cellh;
858 font->image.h = round_to_pot(font->image.h);
860 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
861 if(!font->image.data)
863 memset(font->image.data, 255, font->image.w*font->image.h);
865 for(i=0; i<font->n_glyphs; ++i)
871 glyph = &font->glyphs[i];
876 ci = glyph->code-first;
881 if(cellw>glyph->image.w)
882 cx += (cellw-glyph->image.w)/2;
883 cy += top-glyph->offset_y-glyph->image.h;
888 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
890 if(cx+x>=font->image.w || cy+y>=font->image.h)
892 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
899 int render_packed(Font *font, unsigned margin, unsigned padding, bool npot)
904 unsigned *used_pixels;
905 unsigned cx = margin, cy;
908 /* Compute the total area occupied by glyphs and padding. */
909 for(i=0; i<font->n_glyphs; ++i)
911 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
914 fprintf(stderr, "Overflow in counting total glyph area\n");
920 /* Find an image size that's approximately square. */
921 for(font->image.w=1;; font->image.w<<=1)
923 if(font->image.w<=margin*2)
925 font->image.h = area/(font->image.w-margin*2)+margin*2;
926 if(font->image.h<=font->image.w)
930 /* Add some extra space to accommodate packing imperfections. */
931 font->image.h = font->image.h*3/2;
933 /* Allocate arrays for storing the image and keeping track of used pixels and
934 glyphs. Since glyphs are rectangular and the image is filled starting from
935 the top, it's enough to track the number of used pixels at the top of each
937 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
938 if(!font->image.data)
940 memset(font->image.data, 255, font->image.w*font->image.h);
941 used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
942 memset(used_pixels, 0, font->image.w*sizeof(unsigned));
943 used_glyphs = (char *)malloc(font->n_glyphs);
944 memset(used_glyphs, 0, font->n_glyphs);
946 for(cy=margin; cy+margin<font->image.h;)
951 unsigned best_score = 0;
952 unsigned target_h = 0;
954 /* Find the leftmost free pixel on this row. Also record the lowest
955 extent of glyphs to the left of the free position. */
956 for(; (cx+margin<font->image.w && used_pixels[cx]>cy); ++cx)
957 if(used_pixels[cx]-cy-padding>target_h)
958 target_h = used_pixels[cx]-cy-padding;
960 if(cx+margin>=font->image.w)
967 /* Count the free pixel at this position. */
968 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
970 /* Find a suitable glyph to put here. */
971 for(i=0; i<font->n_glyphs; ++i)
975 g = &font->glyphs[i];
976 if(!used_glyphs[i] && g->image.w<=w)
980 /* Prefer glyphs that would reach exactly as low as the ones left
981 of here. This aims to create a straight edge at the bottom for
982 lining up further glyphs. */
983 score = g->image.h+padding;
984 if(g->image.h==target_h)
1003 used_glyphs[glyph-font->glyphs] = 1;
1007 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
1009 if(cx+x>=font->image.w || cy+y>=font->image.h)
1011 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
1013 for(x=0; x<glyph->image.w+2*padding; ++x)
1015 if(cx+x<padding || cx+x>=font->image.w+padding)
1017 if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
1018 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
1021 if(cy+glyph->image.h+margin>used_h)
1022 used_h = cy+glyph->image.h+margin;
1025 /* Trim the image to the actually used size, in case the original estimate
1026 was too pessimistic. */
1027 font->image.h = used_h;
1029 font->image.h = round_to_pot(font->image.h);
1037 int save_defs(const char *fn, const Font *font)
1042 out = fopen(fn, "w");
1045 fprintf(stderr, "Couldn't open %s\n",fn);
1049 fprintf(out, "# Image/font info:\n");
1050 fprintf(out, "# width height size ascent descent\n");
1051 fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
1052 fprintf(out, "\n# Glyph info:\n");
1053 fprintf(out, "# code x y width height offset_x offset_y advance\n");
1054 for(i=0; i<font->n_glyphs; ++i)
1056 const Glyph *g = &font->glyphs[i];
1057 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);
1059 fprintf(out, "\n# Kerning info:\n");
1060 fprintf(out, "# left right distance\n");
1061 for(i=0; i<font->n_kerning; ++i)
1063 const Kerning *k = &font->kerning[i];
1064 fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
1072 int save_png(const char *fn, const Image *image, char alpha)
1079 png_byte *data2 = 0;
1082 if(!strcmp(fn, "-"))
1086 out = fopen(fn, "wb");
1089 fprintf(stderr, "Couldn't open %s\n",fn);
1094 pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1097 fprintf(stderr, "Error writing PNG file\n");
1100 pngi = png_create_info_struct(pngs);
1103 png_destroy_write_struct(&pngs, NULL);
1104 fprintf(stderr, "Error writing PNG file\n");
1108 png_init_io(pngs, out);
1109 rows = (png_byte **)malloc(image->h*sizeof(png_byte *));
1112 data2 = (png_byte *)alloc_image_data(image->w*2, image->h);
1115 for(i=0; i<image->w*image->h; ++i)
1118 data2[i*2+1] = 255-image->data[i];
1120 for(i=0; i<image->h; ++i)
1121 rows[i] = (png_byte *)(data2+i*image->w*2);
1122 color = PNG_COLOR_TYPE_GRAY_ALPHA;
1126 for(i=0; i<image->h; ++i)
1127 rows[i] = (png_byte *)(image->data+i*image->w);
1128 color = PNG_COLOR_TYPE_GRAY;
1130 png_set_IHDR(pngs, pngi, image->w, image->h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1131 png_set_rows(pngs, pngi, rows);
1132 png_write_png(pngs, pngi, PNG_TRANSFORM_IDENTITY, NULL);
1133 png_destroy_write_struct(&pngs, &pngi);
1139 printf("Saved %dx%d PNG image to %s\n", image->w, image->h, fn);