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);
223 err = FT_Set_Pixel_Sizes(face, 0, (distfield ? size*distfield : size));
226 fprintf(stderr, "Couldn't set size\n");
232 ranges = malloc(sizeof(Range));
234 ranges[0].last = 255;
238 sort_and_compact_ranges(ranges, &n_ranges);
241 err = init_font(&font, face, ranges, n_ranges, autohinter, distfield);
247 fprintf(stderr, "No glyphs found in the requested range\n");
252 err = render_packed(&font, margin, padding, npot);
254 err = render_grid(&font, cellw, cellh, cpl, seq, npot);
258 if(invert || distfield)
260 for(i=0; (unsigned)i<font.image.w*font.image.h; ++i)
261 font.image.data[i] = 255-font.image.data[i];
263 err = save_png(out_fn, &font.image, (alpha && !distfield));
268 save_defs(def_fn, &font);
270 for(i=0; (unsigned)i<font.n_glyphs; ++i)
271 free(font.glyphs[i].image.data);
274 free(font.image.data);
278 FT_Done_FreeType(freetype);
285 printf("ttf2png 1.1 - True Type Font to PNG converter\n"
286 "Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions\n"
287 "Distributed under the GNU General Public License\n\n");
289 printf("Usage: ttf2png [options] <TTF file>\n\n");
291 printf("Accepted options (default values in [brackets])\n"
292 " -r Range of code points to convert [0,255]\n"
293 " -s Font size to use, in pixels [10]\n"
294 " -l Number of glyphs to put in one line [auto]\n"
295 " -c Glyph cell size, in pixels (grid mode only) [auto]\n"
296 " -o Output file name (or - for stdout) [font.png]\n");
297 printf(" -a Force autohinter\n"
298 " -t Render glyphs to alpha channel\n"
299 " -i Invert colors of the glyphs\n"
300 " -v Increase the level of verbosity\n"
301 " -e Use cells in sequence, without gaps (grid mode only)\n"
302 " -p Pack the glyphs tightly instead of in a grid\n"
303 " -m Margin around image edges (packed mode only) [0]\n"
304 " -n Padding between glyphs (packed mode only) [1]\n"
305 " -g Allow non-power-of-two result\n"
306 " -f Create a distance field texture\n"
307 " -d File name for writing glyph definitions\n"
308 " -h Print this message\n");
311 int convert_numeric_option(char opt, int min_value)
316 value = strtol(optarg, &ptr, 0);
317 if(value<min_value || *ptr)
319 printf("Invalid option argument in -%c %s\n", opt, optarg);
326 void convert_code_point_range(char opt, Range *range)
331 if(!strcmp(optarg, "all"))
334 range->last = 0x10FFFF;
338 value = str_to_code_point(optarg, &ptr);
339 if(value>0 && *ptr==',')
341 range->first = value;
342 value = str_to_code_point(ptr+1, &ptr);
350 printf("Invalid option argument in -%c %s\n", opt, optarg);
354 unsigned str_to_code_point(const char *nptr, char **endptr)
356 if(nptr[0]=='U' && nptr[1]=='+')
357 return strtoul(nptr+2, endptr, 16);
358 else if(nptr[0]&0x80)
365 *endptr = (char *)nptr;
367 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
368 if((nptr[bytes]&0xC0)!=0x80)
373 code = nptr[0]&(0x3F>>bytes);
374 for(i=1; i<bytes; ++i)
375 code = (code<<6)|(nptr[i]&0x3F);
378 *endptr = (char *)nptr+bytes;
382 else if(isdigit(nptr[0]))
383 return strtoul(nptr, endptr, 0);
387 *endptr = (char *)nptr+1;
392 void convert_size(char opt, unsigned *width, unsigned *height)
397 if(!strcmp(optarg, "auto"))
403 else if(!strcmp(optarg, "autorect"))
410 value = strtol(optarg, &ptr, 0);
416 value = strtol(ptr+1, &ptr, 0);
430 printf("Invalid option argument in -%c %s\n", opt, optarg);
434 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
441 qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
442 for(i=0, j=1; j<*n_ranges; ++j)
444 if(ranges[i].last+1>=ranges[j].first)
446 if(ranges[j].last>ranges[i].last)
447 ranges[i].last = ranges[j].last;
453 ranges[i] = ranges[j];
460 int range_cmp(const void *p1, const void *p2)
462 const Range *r1 = (const Range *)p1;
463 const Range *r2 = (const Range *)p2;
464 if(r1->first!=r2->first)
465 return (r1->first<r2->first ? -1 : 1);
466 else if(r1->last!=r2->last)
467 return (r1->last<r2->last ? -1 : 1);
472 unsigned round_to_pot(unsigned n)
484 void *alloc_image_data(size_t a, size_t b)
488 /* Carry out the multiplication manually so we can check for overflow. */
497 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(c/1024*b));
504 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(a/1024*b));
508 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter, unsigned distfield)
512 int scale = (distfield>0 ? distfield : 1);
514 font->ascent = (face->size->metrics.ascender/scale+63)/64;
515 font->descent = (face->size->metrics.descender/scale-63)/64;
519 printf("Ascent: %d\n", font->ascent);
520 printf("Descent: %d\n", font->descent);
525 for(i=0; i<n_ranges; ++i)
526 if(init_glyphs(font, face, &ranges[i], autohinter, distfield))
530 printf("Loaded %u glyphs\n", font->n_glyphs);
533 font->kerning = NULL;
534 for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
538 FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
540 /* FreeType documentation says that vertical kerning is practically
541 never used, so we ignore it. */
546 if(font->n_kerning>=size)
549 font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
552 kern = &font->kerning[font->n_kerning++];
553 kern->left_code = font->glyphs[i].code;
554 kern->right_code = font->glyphs[j].code;
555 kern->distance = (kerning.x/scale+32)/64;
560 printf("Loaded %d kerning pairs\n", font->n_kerning);
565 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield)
568 unsigned size = font->n_glyphs;
569 int scale = (distfield>0 ? distfield : 1);
571 for(i=range->first; i<=range->last; ++i)
574 FT_Bitmap *bmp = &face->glyph->bitmap;
578 n = FT_Get_Char_Index(face, i);
583 flags |= FT_LOAD_FORCE_AUTOHINT;
584 FT_Load_Glyph(face, n, flags);
585 FT_Render_Glyph(face->glyph, (distfield ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL));
589 printf(" Code point U+%04X", i);
590 if(i>=0x20 && i<0x7F)
592 else if(i>=0xA0 && i<=0x10FFFF)
597 for(bytes=2; i>>(1+bytes*5); ++bytes) ;
598 for(j=0; j<bytes; ++j)
599 utf8[j] = 0x80 | ((i>>((bytes-j-1)*6))&0x3F);
600 utf8[0] |= 0xF0<<(4-bytes);
603 printf(" (%s)", utf8);
605 printf(": glyph %u, size %dx%d\n", n, bmp->width/scale, bmp->rows/scale);
608 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
610 fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
614 if(font->n_glyphs>=size)
617 font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
620 glyph = &font->glyphs[font->n_glyphs++];
623 glyph->offset_x = (int)(face->glyph->bitmap_left+scale/2)/scale;
624 glyph->offset_y = (int)(face->glyph->bitmap_top-bmp->rows+scale/2)/scale;
625 glyph->advance = (int)(face->glyph->advance.x/scale+32)/64;
627 /* Copy the glyph image since FreeType uses a global buffer, which would
628 be overwritten by the next glyph. Negative pitch means the scanlines
629 start from the bottom. */
634 glyph->offset_x -= margin;
635 glyph->offset_y -= margin;
636 create_distance_field(bmp, &glyph->image, distfield, margin);
640 if(copy_bitmap(bmp, &glyph->image))
648 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
654 image->w = bmp->width;
655 image->h = bmp->rows;
656 if(!image->w || !image->h)
662 image->data = (unsigned char *)malloc(image->w*image->h);
665 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
670 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
675 for(y=0; y<bmp->rows; ++y)
677 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
679 for(x=0; x<bmp->width; ++x)
680 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
684 for(x=0; x<bmp->width; ++x)
695 unsigned sqrti(unsigned num)
697 unsigned result = num;
698 while(result*result>num)
700 unsigned diff = result*result-num;
704 result -= (diff+result)/(result*2);
710 unsigned find_distance_to_edge(const Image *image, int origin_x, int origin_y, unsigned range)
714 unsigned char origin_pixel = 0;
715 unsigned closest = range*range;
717 if(origin_x>=0 && (unsigned)origin_x<image->w && origin_y>=0 && (unsigned)origin_y<image->h)
718 origin_pixel = image->data[origin_x+origin_y*image->w];
722 for(i=1; (i<range && i*i<=closest); ++i, --x, --y) for(j=0; j<4; ++j)
725 int dx = (j==0 ? 1 : j==2 ? -1 : 0);
726 int dy = (j==1 ? 1 : j==3 ? -1 : 0);
728 for(k=0; k<i*2; ++k, x+=dx, y+=dy)
730 unsigned char pixel = 0;
731 if(x>=0 && (unsigned)x<image->w && y>=0 && (unsigned)y<image->h)
732 pixel = image->data[x+y*image->w];
734 if((pixel^origin_pixel)&0x80)
736 unsigned d = 2*i*i + k*k - 2*k*i;
743 return sqrti(closest)*0x7F/range;
746 int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
751 if(!bmp->width || !bmp->rows)
759 if(copy_bitmap(bmp, &base_image))
762 image->w = (base_image.w-1)/scale+2*margin+1;
763 image->h = (base_image.h-1)/scale+2*margin+1;
764 image->data = (unsigned char *)malloc(image->w*image->h);
767 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
768 free(base_image.data);
772 for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
774 int bx = (x-margin)*scale+scale/2;
775 int by = (y-margin)*scale+scale/2;
776 unsigned char pixel = find_distance_to_edge(&base_image, bx, by, margin*scale);
777 if(bx>=0 && (unsigned)bx<base_image.w && by>=0 && (unsigned)by<base_image.h)
778 pixel |= base_image.data[bx+by*base_image.w]&0x80;
781 image->data[x+y*image->w] = pixel;
784 free(base_image.data);
789 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot)
792 int top = 0, bot = 0;
793 unsigned first, last;
794 unsigned maxw = 0, maxh = 0;
796 /* Find extremes of the glyph images. */
797 for(i=0; i<font->n_glyphs; ++i)
801 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
804 if(font->glyphs[i].offset_y<bot)
805 bot = font->glyphs[i].offset_y;
806 if(font->glyphs[i].image.w>maxw)
807 maxw = font->glyphs[i].image.w;
808 if(font->glyphs[i].image.h>maxh)
809 maxh = font->glyphs[i].image.h;
814 /* Establish a large enough cell to hold all glyphs in the range. */
815 int square = (cellh==cellw);
829 printf("Max size: %u x %u\n", maxw, maxh);
830 printf("Y range: [%d %d]\n", bot, top);
831 printf("Cell size: %u x %u\n", cellw, cellh);
832 if(maxw>cellw || (unsigned)(top-bot)>cellh)
833 fprintf(stderr, "Warning: character size exceeds cell size\n");
838 /* Determine number of characters per line, trying to fit all the glyphs
839 in a square image. */
843 if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
848 first = font->glyphs[0].code;
851 last = font->glyphs[font->n_glyphs-1].code;
853 font->image.w = cpl*cellw;
855 font->image.w = round_to_pot(font->image.w);
857 font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh;
859 font->image.h = (last-first+cpl)/cpl*cellh;
861 font->image.h = round_to_pot(font->image.h);
863 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
864 if(!font->image.data)
866 memset(font->image.data, 255, font->image.w*font->image.h);
868 for(i=0; i<font->n_glyphs; ++i)
874 glyph = &font->glyphs[i];
879 ci = glyph->code-first;
884 if(cellw>glyph->image.w)
885 cx += (cellw-glyph->image.w)/2;
886 cy += top-glyph->offset_y-glyph->image.h;
891 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
893 if(cx+x>=font->image.w || cy+y>=font->image.h)
895 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
902 int render_packed(Font *font, unsigned margin, unsigned padding, bool npot)
907 unsigned *used_pixels;
908 unsigned cx = margin, cy;
911 /* Compute the total area occupied by glyphs and padding. */
912 for(i=0; i<font->n_glyphs; ++i)
914 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
917 fprintf(stderr, "Overflow in counting total glyph area\n");
923 /* Find an image size that's approximately square. */
924 for(font->image.w=1;; font->image.w<<=1)
926 if(font->image.w<=margin*2)
928 font->image.h = area/(font->image.w-margin*2)+margin*2;
929 if(font->image.h<=font->image.w)
933 /* Add some extra space to accommodate packing imperfections. */
934 font->image.h = font->image.h*3/2;
936 /* Allocate arrays for storing the image and keeping track of used pixels and
937 glyphs. Since glyphs are rectangular and the image is filled starting from
938 the top, it's enough to track the number of used pixels at the top of each
940 font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h);
941 if(!font->image.data)
943 memset(font->image.data, 255, font->image.w*font->image.h);
944 used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
945 memset(used_pixels, 0, font->image.w*sizeof(unsigned));
946 used_glyphs = (char *)malloc(font->n_glyphs);
947 memset(used_glyphs, 0, font->n_glyphs);
949 for(cy=margin; cy+margin<font->image.h;)
954 unsigned best_score = 0;
955 unsigned target_h = 0;
957 /* Find the leftmost free pixel on this row. Also record the lowest
958 extent of glyphs to the left of the free position. */
959 for(; (cx+margin<font->image.w && used_pixels[cx]>cy); ++cx)
960 if(used_pixels[cx]-cy-padding>target_h)
961 target_h = used_pixels[cx]-cy-padding;
963 if(cx+margin>=font->image.w)
970 /* Count the free pixel at this position. */
971 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
973 /* Find a suitable glyph to put here. */
974 for(i=0; i<font->n_glyphs; ++i)
978 g = &font->glyphs[i];
979 if(!used_glyphs[i] && g->image.w<=w)
983 /* Prefer glyphs that would reach exactly as low as the ones left
984 of here. This aims to create a straight edge at the bottom for
985 lining up further glyphs. */
986 score = g->image.h+padding;
987 if(g->image.h==target_h)
1006 used_glyphs[glyph-font->glyphs] = 1;
1010 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
1012 if(cx+x>=font->image.w || cy+y>=font->image.h)
1014 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
1016 for(x=0; x<glyph->image.w+2*padding; ++x)
1018 if(cx+x<padding || cx+x>=font->image.w+padding)
1020 if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
1021 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
1024 if(cy+glyph->image.h+margin>used_h)
1025 used_h = cy+glyph->image.h+margin;
1028 /* Trim the image to the actually used size, in case the original estimate
1029 was too pessimistic. */
1030 font->image.h = used_h;
1032 font->image.h = round_to_pot(font->image.h);
1040 int save_defs(const char *fn, const Font *font)
1045 out = fopen(fn, "w");
1048 fprintf(stderr, "Couldn't open %s\n",fn);
1052 fprintf(out, "# Image/font info:\n");
1053 fprintf(out, "# width height size ascent descent\n");
1054 fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
1055 fprintf(out, "\n# Glyph info:\n");
1056 fprintf(out, "# code x y width height offset_x offset_y advance\n");
1057 for(i=0; i<font->n_glyphs; ++i)
1059 const Glyph *g = &font->glyphs[i];
1060 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);
1062 fprintf(out, "\n# Kerning info:\n");
1063 fprintf(out, "# left right distance\n");
1064 for(i=0; i<font->n_kerning; ++i)
1066 const Kerning *k = &font->kerning[i];
1067 fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
1075 int save_png(const char *fn, const Image *image, char alpha)
1082 png_byte *data2 = 0;
1085 if(!strcmp(fn, "-"))
1089 out = fopen(fn, "wb");
1092 fprintf(stderr, "Couldn't open %s\n",fn);
1097 pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1100 fprintf(stderr, "Error writing PNG file\n");
1103 pngi = png_create_info_struct(pngs);
1106 png_destroy_write_struct(&pngs, NULL);
1107 fprintf(stderr, "Error writing PNG file\n");
1111 png_init_io(pngs, out);
1112 rows = (png_byte **)malloc(image->h*sizeof(png_byte *));
1115 data2 = (png_byte *)alloc_image_data(image->w*2, image->h);
1118 for(i=0; i<image->w*image->h; ++i)
1121 data2[i*2+1] = 255-image->data[i];
1123 for(i=0; i<image->h; ++i)
1124 rows[i] = (png_byte *)(data2+i*image->w*2);
1125 color = PNG_COLOR_TYPE_GRAY_ALPHA;
1129 for(i=0; i<image->h; ++i)
1130 rows[i] = (png_byte *)(image->data+i*image->w);
1131 color = PNG_COLOR_TYPE_GRAY;
1133 png_set_IHDR(pngs, pngi, image->w, image->h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1134 png_set_rows(pngs, pngi, rows);
1135 png_write_png(pngs, pngi, PNG_TRANSFORM_IDENTITY, NULL);
1136 png_destroy_write_struct(&pngs, &pngi);
1142 printf("Saved %dx%d PNG image to %s\n", image->w, image->h, fn);