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, 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);
94 int main(int argc, char **argv)
98 unsigned n_ranges = 0;
109 unsigned padding = 1;
111 unsigned distfield = 0;
120 char *out_fn = "font.png";
131 while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:gf:b:")) != -1)
136 ranges = (Range *)realloc(ranges, (++n_ranges)*sizeof(Range));
137 convert_code_point_range('r', &ranges[n_ranges-1]);
140 size = convert_numeric_option('s', 1);
143 cpl = convert_numeric_option('l', 1);
146 convert_size('c', &cellw, &cellh);
177 margin = convert_numeric_option('m', 0);
180 padding = convert_numeric_option('n', 0);
186 distfield = convert_numeric_option('f', 1);
189 border = convert_numeric_option('b', 1);
193 if(!strcmp(out_fn, "-"))
204 err = FT_Init_FreeType(&freetype);
207 fprintf(stderr, "Couldn't initialize FreeType library\n");
211 err = FT_New_Face(freetype, fn, 0, &face);
214 fprintf(stderr, "Couldn't load font file\n");
215 if(err==FT_Err_Unknown_File_Format)
216 fprintf(stderr, "Unknown file format\n");
222 const char *name = FT_Get_Postscript_Name(face);
223 printf("Font name: %s\n", name);
224 printf("Glyphs: %ld\n", face->num_glyphs);
231 border = sqrti(font.size);
235 err = FT_Set_Pixel_Sizes(face, 0, size);
238 fprintf(stderr, "Couldn't set size\n");
244 ranges = malloc(sizeof(Range));
246 ranges[0].last = 255;
250 sort_and_compact_ranges(ranges, &n_ranges);
252 err = init_font(&font, face, ranges, n_ranges, autohinter, distfield, border);
258 fprintf(stderr, "No glyphs found in the requested range\n");
263 err = render_packed(&font, margin, padding, npot);
265 err = render_grid(&font, cellw, cellh, cpl, seq, npot);
269 if(invert || distfield)
271 for(i=0; (unsigned)i<font.image.w*font.image.h; ++i)
272 font.image.data[i] = 255-font.image.data[i];
274 err = save_png(out_fn, &font.image, (alpha && !distfield));
279 save_defs(def_fn, &font);
281 for(i=0; (unsigned)i<font.n_glyphs; ++i)
282 free(font.glyphs[i].image.data);
285 free(font.image.data);
289 FT_Done_FreeType(freetype);
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");
300 printf("Usage: ttf2png [options] <TTF file>\n\n");
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");
322 int convert_numeric_option(char opt, int min_value)
327 value = strtol(optarg, &ptr, 0);
328 if(value<min_value || *ptr)
330 printf("Invalid option argument in -%c %s\n", opt, optarg);
337 void convert_code_point_range(char opt, Range *range)
342 if(!strcmp(optarg, "all"))
345 range->last = 0x10FFFF;
349 value = str_to_code_point(optarg, &ptr);
350 if(value>0 && *ptr==',')
352 range->first = value;
353 value = str_to_code_point(ptr+1, &ptr);
361 printf("Invalid option argument in -%c %s\n", opt, optarg);
365 unsigned str_to_code_point(const char *nptr, char **endptr)
367 if(nptr[0]=='U' && nptr[1]=='+')
368 return strtoul(nptr+2, endptr, 16);
369 else if(nptr[0]&0x80)
376 *endptr = (char *)nptr;
378 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
379 if((nptr[bytes]&0xC0)!=0x80)
384 code = nptr[0]&(0x3F>>bytes);
385 for(i=1; i<bytes; ++i)
386 code = (code<<6)|(nptr[i]&0x3F);
389 *endptr = (char *)nptr+bytes;
393 else if(isdigit(nptr[0]))
394 return strtoul(nptr, endptr, 0);
398 *endptr = (char *)nptr+1;
403 void convert_size(char opt, unsigned *width, unsigned *height)
408 if(!strcmp(optarg, "auto"))
414 else if(!strcmp(optarg, "autorect"))
421 value = strtol(optarg, &ptr, 0);
427 value = strtol(ptr+1, &ptr, 0);
441 printf("Invalid option argument in -%c %s\n", opt, optarg);
445 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
452 qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
453 for(i=0, j=1; j<*n_ranges; ++j)
455 if(ranges[i].last+1>=ranges[j].first)
457 if(ranges[j].last>ranges[i].last)
458 ranges[i].last = ranges[j].last;
464 ranges[i] = ranges[j];
471 int range_cmp(const void *p1, const void *p2)
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);
483 unsigned round_to_pot(unsigned n)
495 void *alloc_image_data(size_t a, size_t b)
499 /* Carry out the multiplication manually so we can check for overflow. */
508 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(c/1024*b));
515 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(a/1024*b));
519 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter, unsigned distfield, unsigned border)
523 int scale = (distfield>0 ? distfield : 1);
525 font->ascent = (face->size->metrics.ascender/scale+63)/64;
526 font->descent = (face->size->metrics.descender/scale-63)/64;
530 printf("Ascent: %d\n", font->ascent);
531 printf("Descent: %d\n", font->descent);
536 for(i=0; i<n_ranges; ++i)
537 if(init_glyphs(font, face, &ranges[i], autohinter, distfield, border))
541 printf("Loaded %u glyphs\n", font->n_glyphs);
544 font->kerning = NULL;
545 for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
549 FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
551 /* FreeType documentation says that vertical kerning is practically
552 never used, so we ignore it. */
557 if(font->n_kerning>=size)
560 font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
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;
571 printf("Loaded %d kerning pairs\n", font->n_kerning);
576 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield, unsigned border)
579 unsigned size = font->n_glyphs;
580 int scale = (distfield>0 ? distfield : 1);
582 for(i=range->first; i<=range->last; ++i)
585 FT_Bitmap *bmp = &face->glyph->bitmap;
589 n = FT_Get_Char_Index(face, i);
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));
600 printf(" Code point U+%04X", i);
601 if(i>=0x20 && i<0x7F)
603 else if(i>=0xA0 && i<=0x10FFFF)
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);
614 printf(" (%s)", utf8);
616 printf(": glyph %u, size %dx%d\n", n, bmp->width/scale, bmp->rows/scale);
619 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
621 fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
625 if(font->n_glyphs>=size)
628 font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
631 glyph = &font->glyphs[font->n_glyphs++];
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;
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. */
643 glyph->offset_x -= border;
644 glyph->offset_y -= border;
645 create_distance_field(bmp, &glyph->image, distfield, border);
649 if(copy_bitmap(bmp, &glyph->image))
657 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
663 image->w = bmp->width;
664 image->h = bmp->rows;
665 if(!image->w || !image->h)
671 image->data = (unsigned char *)malloc(image->w*image->h);
674 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
679 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
684 for(y=0; y<bmp->rows; ++y)
686 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
688 for(x=0; x<bmp->width; ++x)
689 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
693 for(x=0; x<bmp->width; ++x)
704 unsigned sqrti(unsigned num)
706 unsigned result = (num>0xFFFF ? 0xFFFF : 0x100);
707 while(result && result*result>=result+num)
708 result -= (result*result+result-num)/(result*2);
713 unsigned find_distance_to_edge(const Image *image, int origin_x, int origin_y, unsigned range)
717 unsigned char origin_pixel = 0;
718 unsigned closest = range*range;
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];
725 for(i=1; (i<range && i*i<=closest); ++i, --x, --y) for(j=0; j<4; ++j)
728 int dx = (j==0 ? 1 : j==2 ? -1 : 0);
729 int dy = (j==1 ? 1 : j==3 ? -1 : 0);
731 for(k=0; k<i*2; ++k, x+=dx, y+=dy)
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];
737 if((pixel^origin_pixel)&0x80)
739 unsigned d = 2*i*i + k*k - 2*k*i;
746 return sqrti(closest*0x3F01)/range;
749 int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
754 if(!bmp->width || !bmp->rows)
762 if(copy_bitmap(bmp, &base_image))
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);
770 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
771 free(base_image.data);
775 for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
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;
784 image->data[x+y*image->w] = pixel;
787 free(base_image.data);
792 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot)
795 int top = 0, bot = 0;
796 unsigned first, last;
797 unsigned maxw = 0, maxh = 0;
799 /* Find extremes of the glyph images. */
800 for(i=0; i<font->n_glyphs; ++i)
804 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
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;
817 /* Establish a large enough cell to hold all glyphs in the range. */
818 int square = (cellh==cellw);
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");
841 /* Determine number of characters per line, trying to fit all the glyphs
842 in a square image. */
846 if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
851 first = font->glyphs[0].code;
854 last = font->glyphs[font->n_glyphs-1].code;
856 font->image.w = cpl*cellw;
858 font->image.w = round_to_pot(font->image.w);
860 font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh;
862 font->image.h = (last-first+cpl)/cpl*cellh;
864 font->image.h = round_to_pot(font->image.h);
866 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
867 if(!font->image.data)
869 memset(font->image.data, 255, font->image.w*font->image.h);
871 for(i=0; i<font->n_glyphs; ++i)
877 glyph = &font->glyphs[i];
882 ci = glyph->code-first;
887 if(cellw>glyph->image.w)
888 cx += (cellw-glyph->image.w)/2;
889 cy += top-glyph->offset_y-glyph->image.h;
894 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
896 if(cx+x>=font->image.w || cy+y>=font->image.h)
898 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
905 int render_packed(Font *font, unsigned margin, unsigned padding, bool npot)
910 unsigned *used_pixels;
911 unsigned cx = margin, cy;
914 /* Compute the total area occupied by glyphs and padding. */
915 for(i=0; i<font->n_glyphs; ++i)
917 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
920 fprintf(stderr, "Overflow in counting total glyph area\n");
926 /* Find an image size that's approximately square. */
927 for(font->image.w=1;; font->image.w<<=1)
929 if(font->image.w<=margin*2)
931 font->image.h = area/(font->image.w-margin*2)+margin*2;
932 if(font->image.h<=font->image.w)
936 /* Add some extra space to accommodate packing imperfections. */
937 font->image.h = font->image.h*3/2;
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
943 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
944 if(!font->image.data)
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);
952 for(cy=margin; cy+margin<font->image.h;)
957 unsigned best_score = 0;
958 unsigned target_h = 0;
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;
966 if(cx+margin>=font->image.w)
973 /* Count the free pixel at this position. */
974 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
976 /* Find a suitable glyph to put here. */
977 for(i=0; i<font->n_glyphs; ++i)
981 g = &font->glyphs[i];
982 if(!used_glyphs[i] && g->image.w<=w)
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)
1009 used_glyphs[glyph-font->glyphs] = 1;
1013 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
1015 if(cx+x>=font->image.w || cy+y>=font->image.h)
1017 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
1019 for(x=0; x<glyph->image.w+2*padding; ++x)
1021 if(cx+x<padding || cx+x>=font->image.w+padding)
1023 if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
1024 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
1027 if(cy+glyph->image.h+margin>used_h)
1028 used_h = cy+glyph->image.h+margin;
1031 /* Trim the image to the actually used size, in case the original estimate
1032 was too pessimistic. */
1033 font->image.h = used_h;
1035 font->image.h = round_to_pot(font->image.h);
1043 int save_defs(const char *fn, const Font *font)
1048 out = fopen(fn, "w");
1051 fprintf(stderr, "Couldn't open %s\n",fn);
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)
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);
1065 fprintf(out, "\n# Kerning info:\n");
1066 fprintf(out, "# left right distance\n");
1067 for(i=0; i<font->n_kerning; ++i)
1069 const Kerning *k = &font->kerning[i];
1070 fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
1078 int save_png(const char *fn, const Image *image, char alpha)
1085 png_byte *data2 = 0;
1088 if(!strcmp(fn, "-"))
1092 out = fopen(fn, "wb");
1095 fprintf(stderr, "Couldn't open %s\n",fn);
1100 pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1103 fprintf(stderr, "Error writing PNG file\n");
1106 pngi = png_create_info_struct(pngs);
1109 png_destroy_write_struct(&pngs, NULL);
1110 fprintf(stderr, "Error writing PNG file\n");
1114 png_init_io(pngs, out);
1115 rows = (png_byte **)malloc(image->h*sizeof(png_byte *));
1118 data2 = (png_byte *)alloc_image_data(image->w*2, image->h);
1121 for(i=0; i<image->w*image->h; ++i)
1124 data2[i*2+1] = 255-image->data[i];
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;
1132 for(i=0; i<image->h; ++i)
1133 rows[i] = (png_byte *)(image->data+i*image->w);
1134 color = PNG_COLOR_TYPE_GRAY;
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);
1145 printf("Saved %dx%d PNG image to %s\n", image->w, image->h, fn);