2 ttf2png - True Type Font to PNG converter
3 Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions
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 int init_image(Image *, 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);
88 int render_packed(Font *, unsigned, unsigned);
89 int save_defs(const char *, const Font *);
90 int save_png(const char *, const Image *, bool, bool, bool);
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);
265 err = render_grid(&font, cellw, cellh, cpl, seq);
269 err = save_png(out_fn, &font.image, (alpha && !distfield), (invert || distfield), npot);
274 save_defs(def_fn, &font);
276 for(i=0; (unsigned)i<font.n_glyphs; ++i)
277 free(font.glyphs[i].image.data);
280 free(font.image.data);
284 FT_Done_FreeType(freetype);
291 printf("ttf2png 1.1 - True Type Font to PNG converter\n"
292 "Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions\n"
293 "Distributed under the GNU General Public License\n\n");
295 printf("Usage: ttf2png [options] <TTF file>\n\n");
297 printf("Accepted options (default values in [brackets])\n"
298 " -r Range of code points to convert [0,255]\n"
299 " -s Font size to use, in pixels [10]\n"
300 " -l Number of glyphs to put in one line [auto]\n"
301 " -c Glyph cell size, in pixels (grid mode only) [auto]\n"
302 " -o Output file name (or - for stdout) [font.png]\n");
303 printf(" -a Force autohinter\n"
304 " -t Render glyphs to alpha channel\n"
305 " -i Invert colors of the glyphs\n"
306 " -v Increase the level of verbosity\n"
307 " -e Use cells in sequence, without gaps (grid mode only)\n"
308 " -p Pack the glyphs tightly instead of in a grid\n"
309 " -m Margin around image edges (packed mode only) [0]\n"
310 " -n Padding between glyphs (packed mode only) [1]\n"
311 " -g Allow non-power-of-two result\n"
312 " -f Create a distance field texture\n"
313 " -d File name for writing glyph definitions\n"
314 " -h Print this message\n");
317 int convert_numeric_option(char opt, int min_value)
322 value = strtol(optarg, &ptr, 0);
323 if(value<min_value || *ptr)
325 printf("Invalid option argument in -%c %s\n", opt, optarg);
332 void convert_code_point_range(char opt, Range *range)
337 if(!strcmp(optarg, "all"))
340 range->last = 0x10FFFF;
344 value = str_to_code_point(optarg, &ptr);
345 if(value>0 && *ptr==',')
347 range->first = value;
348 value = str_to_code_point(ptr+1, &ptr);
356 printf("Invalid option argument in -%c %s\n", opt, optarg);
360 unsigned str_to_code_point(const char *nptr, char **endptr)
362 if(nptr[0]=='U' && nptr[1]=='+')
363 return strtoul(nptr+2, endptr, 16);
364 else if(nptr[0]&0x80)
371 *endptr = (char *)nptr;
373 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
374 if((nptr[bytes]&0xC0)!=0x80)
379 code = nptr[0]&(0x3F>>bytes);
380 for(i=1; i<bytes; ++i)
381 code = (code<<6)|(nptr[i]&0x3F);
384 *endptr = (char *)nptr+bytes;
388 else if(isdigit(nptr[0]))
389 return strtoul(nptr, endptr, 0);
393 *endptr = (char *)nptr+1;
398 void convert_size(char opt, unsigned *width, unsigned *height)
403 if(!strcmp(optarg, "auto"))
409 else if(!strcmp(optarg, "autorect"))
416 value = strtol(optarg, &ptr, 0);
422 value = strtol(ptr+1, &ptr, 0);
436 printf("Invalid option argument in -%c %s\n", opt, optarg);
440 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
447 qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
448 for(i=0, j=1; j<*n_ranges; ++j)
450 if(ranges[i].last+1>=ranges[j].first)
452 if(ranges[j].last>ranges[i].last)
453 ranges[i].last = ranges[j].last;
459 ranges[i] = ranges[j];
466 int range_cmp(const void *p1, const void *p2)
468 const Range *r1 = (const Range *)p1;
469 const Range *r2 = (const Range *)p2;
470 if(r1->first!=r2->first)
471 return (r1->first<r2->first ? -1 : 1);
472 else if(r1->last!=r2->last)
473 return (r1->last<r2->last ? -1 : 1);
478 unsigned round_to_pot(unsigned n)
490 int init_image(Image *image, size_t w, size_t h)
498 if(!image->w || !image->h)
504 fprintf(stderr, "Cannot allocate memory for a %dx%d image\n", image->w, image->h);
508 image->data = malloc(s);
511 fprintf(stderr, "Cannot allocate memory for a %dx%d image\n", image->w, image->h);
518 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter, unsigned distfield, unsigned border)
522 int scale = (distfield>0 ? distfield : 1);
524 font->ascent = (face->size->metrics.ascender/scale+63)/64;
525 font->descent = (face->size->metrics.descender/scale-63)/64;
529 printf("Ascent: %d\n", font->ascent);
530 printf("Descent: %d\n", font->descent);
535 for(i=0; i<n_ranges; ++i)
536 if(init_glyphs(font, face, &ranges[i], autohinter, distfield, border))
540 printf("Loaded %u glyphs\n", font->n_glyphs);
543 font->kerning = NULL;
544 for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
548 FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
550 /* FreeType documentation says that vertical kerning is practically
551 never used, so we ignore it. */
556 if(font->n_kerning>=size)
559 font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
562 kern = &font->kerning[font->n_kerning++];
563 kern->left_code = font->glyphs[i].code;
564 kern->right_code = font->glyphs[j].code;
565 kern->distance = (kerning.x/scale+32)/64;
570 printf("Loaded %d kerning pairs\n", font->n_kerning);
575 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield, unsigned border)
578 unsigned size = font->n_glyphs;
579 int scale = (distfield>0 ? distfield : 1);
581 for(i=range->first; i<=range->last; ++i)
584 FT_Bitmap *bmp = &face->glyph->bitmap;
588 n = FT_Get_Char_Index(face, i);
593 flags |= FT_LOAD_FORCE_AUTOHINT;
594 FT_Load_Glyph(face, n, flags);
595 FT_Render_Glyph(face->glyph, (distfield ? FT_RENDER_MODE_MONO : FT_RENDER_MODE_NORMAL));
599 printf(" Code point U+%04X", i);
600 if(i>=0x20 && i<0x7F)
602 else if(i>=0xA0 && i<=0x10FFFF)
607 for(bytes=2; i>>(1+bytes*5); ++bytes) ;
608 for(j=0; j<bytes; ++j)
609 utf8[j] = 0x80 | ((i>>((bytes-j-1)*6))&0x3F);
610 utf8[0] |= 0xF0<<(4-bytes);
613 printf(" (%s)", utf8);
615 printf(": glyph %u, size %dx%d\n", n, bmp->width/scale, bmp->rows/scale);
618 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
620 fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
624 if(font->n_glyphs>=size)
627 font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
630 glyph = &font->glyphs[font->n_glyphs++];
633 glyph->offset_x = (int)(face->glyph->bitmap_left+scale/2)/scale;
634 glyph->offset_y = (int)(face->glyph->bitmap_top-bmp->rows+scale/2)/scale;
635 glyph->advance = (int)(face->glyph->advance.x/scale+32)/64;
637 /* Copy the glyph image since FreeType uses a global buffer, which would
638 be overwritten by the next glyph. Negative pitch means the scanlines
639 start from the bottom. */
642 glyph->offset_x -= border;
643 glyph->offset_y -= border;
644 create_distance_field(bmp, &glyph->image, distfield, border);
648 if(copy_bitmap(bmp, &glyph->image))
656 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
662 if(init_image(image, bmp->width, bmp->rows))
664 if(!image->w || !image->h)
668 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
673 for(y=0; y<bmp->rows; ++y)
675 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
677 for(x=0; x<bmp->width; ++x)
678 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
682 for(x=0; x<bmp->width; ++x)
693 unsigned sqrti(unsigned num)
695 unsigned result = (num>0xFFFF ? 0xFFFF : 0x100);
696 while(result && result*result>=result+num)
697 result -= (result*result+result-num)/(result*2);
702 unsigned find_distance_to_edge(const Image *image, int origin_x, int origin_y, unsigned range)
706 unsigned char origin_pixel = 0;
707 unsigned closest = range*range;
709 if(origin_x>=0 && (unsigned)origin_x<image->w && origin_y>=0 && (unsigned)origin_y<image->h)
710 origin_pixel = image->data[origin_x+origin_y*image->w];
714 for(i=1; (i<range && i*i<=closest); ++i, --x, --y) for(j=0; j<4; ++j)
717 int dx = (j==0 ? 1 : j==2 ? -1 : 0);
718 int dy = (j==1 ? 1 : j==3 ? -1 : 0);
720 for(k=0; k<i*2; ++k, x+=dx, y+=dy)
722 unsigned char pixel = 0;
723 if(x>=0 && (unsigned)x<image->w && y>=0 && (unsigned)y<image->h)
724 pixel = image->data[x+y*image->w];
726 if((pixel^origin_pixel)&0x80)
728 unsigned d = 2*i*i + k*k - 2*k*i;
735 return sqrti(closest*0x3F01)/range;
738 int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, unsigned margin)
743 if(init_image(image, (bmp->width+scale-1)/scale+2*margin, (bmp->rows+scale-1)/scale+2*margin))
745 if(!image->w || !image->h)
748 if(copy_bitmap(bmp, &base_image))
751 for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
753 int bx = (x-margin)*scale+scale/2;
754 int by = (y-margin)*scale+scale/2;
755 unsigned char pixel = find_distance_to_edge(&base_image, bx, by, margin*scale);
756 if(bx>=0 && (unsigned)bx<base_image.w && by>=0 && (unsigned)by<base_image.h)
757 pixel |= base_image.data[bx+by*base_image.w]&0x80;
760 image->data[x+y*image->w] = pixel;
763 free(base_image.data);
768 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq)
771 int top = 0, bot = 0;
772 unsigned first, n_cells;
773 unsigned maxw = 0, maxh = 0;
775 /* Find extremes of the glyph images. */
776 for(i=0; i<font->n_glyphs; ++i)
780 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
783 if(font->glyphs[i].offset_y<bot)
784 bot = font->glyphs[i].offset_y;
785 if(font->glyphs[i].image.w>maxw)
786 maxw = font->glyphs[i].image.w;
787 if(font->glyphs[i].image.h>maxh)
788 maxh = font->glyphs[i].image.h;
793 /* Establish a large enough cell to hold all glyphs in the range. */
794 int square = (cellh==cellw);
808 printf("Max size: %u x %u\n", maxw, maxh);
809 printf("Y range: [%d %d]\n", bot, top);
810 printf("Cell size: %u x %u\n", cellw, cellh);
811 if(maxw>cellw || (unsigned)(top-bot)>cellh)
812 fprintf(stderr, "Warning: character size exceeds cell size\n");
817 /* Determine number of characters per line, trying to fit all the glyphs
818 in a square image. */
822 if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
827 first = font->glyphs[0].code;
829 n_cells = font->n_glyphs;
833 n_cells = font->glyphs[font->n_glyphs-1].code+1-first;
836 if(init_image(&font->image, cpl*cellw, (n_cells+cpl-1)/cpl*cellh))
838 memset(font->image.data, 0, font->image.w*font->image.h);
840 for(i=0; i<font->n_glyphs; ++i)
846 glyph = &font->glyphs[i];
851 ci = glyph->code-first;
856 if(cellw>glyph->image.w)
857 cx += (cellw-glyph->image.w)/2;
858 cy += top-glyph->offset_y-glyph->image.h;
863 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
865 if(cx+x>=font->image.w || cy+y>=font->image.h)
867 font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w];
874 int render_packed(Font *font, unsigned margin, unsigned padding)
879 unsigned *used_pixels;
880 unsigned cx = margin, cy;
883 /* Compute the total area occupied by glyphs and padding. */
884 for(i=0; i<font->n_glyphs; ++i)
886 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
889 fprintf(stderr, "Overflow in counting total glyph area\n");
895 /* Find an image size that's approximately square. */
896 for(font->image.w=1;; font->image.w<<=1)
898 if(font->image.w<=margin*2)
900 font->image.h = area/(font->image.w-margin*2)+margin*2;
901 if(font->image.h<=font->image.w)
905 /* Add some extra space to accommodate packing imperfections. */
906 font->image.h = font->image.h*3/2;
908 /* Allocate arrays for storing the image and keeping track of used pixels and
909 glyphs. Since glyphs are rectangular and the image is filled starting from
910 the top, it's enough to track the number of used pixels at the top of each
912 if(init_image(&font->image, font->image.w, font->image.h))
914 memset(font->image.data, 0, font->image.w*font->image.h);
915 used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
916 memset(used_pixels, 0, font->image.w*sizeof(unsigned));
917 used_glyphs = (char *)malloc(font->n_glyphs);
918 memset(used_glyphs, 0, font->n_glyphs);
920 for(cy=margin; cy+margin<font->image.h;)
925 unsigned best_score = 0;
926 unsigned target_h = 0;
928 /* Find the leftmost free pixel on this row. Also record the lowest
929 extent of glyphs to the left of the free position. */
930 for(; (cx+margin<font->image.w && used_pixels[cx]>cy); ++cx)
931 if(used_pixels[cx]-cy-padding>target_h)
932 target_h = used_pixels[cx]-cy-padding;
934 if(cx+margin>=font->image.w)
941 /* Count the free pixel at this position. */
942 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
944 /* Find a suitable glyph to put here. */
945 for(i=0; i<font->n_glyphs; ++i)
949 g = &font->glyphs[i];
950 if(!used_glyphs[i] && g->image.w<=w)
954 /* Prefer glyphs that would reach exactly as low as the ones left
955 of here. This aims to create a straight edge at the bottom for
956 lining up further glyphs. */
957 score = g->image.h+padding;
958 if(g->image.h==target_h)
977 used_glyphs[glyph-font->glyphs] = 1;
981 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
983 if(cx+x>=font->image.w || cy+y>=font->image.h)
985 font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w];
987 for(x=0; x<glyph->image.w+2*padding; ++x)
989 if(cx+x<padding || cx+x>=font->image.w+padding)
991 if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
992 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
995 if(cy+glyph->image.h+margin>used_h)
996 used_h = cy+glyph->image.h+margin;
999 /* Trim the image to the actually used size, in case the original estimate
1000 was too pessimistic. */
1001 font->image.h = used_h;
1009 int save_defs(const char *fn, const Font *font)
1014 out = fopen(fn, "w");
1017 fprintf(stderr, "Couldn't open %s\n",fn);
1021 fprintf(out, "# Image/font info:\n");
1022 fprintf(out, "# width height size ascent descent\n");
1023 fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
1024 fprintf(out, "\n# Glyph info:\n");
1025 fprintf(out, "# code x y width height offset_x offset_y advance\n");
1026 for(i=0; i<font->n_glyphs; ++i)
1028 const Glyph *g = &font->glyphs[i];
1029 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);
1031 fprintf(out, "\n# Kerning info:\n");
1032 fprintf(out, "# left right distance\n");
1033 for(i=0; i<font->n_kerning; ++i)
1035 const Kerning *k = &font->kerning[i];
1036 fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
1044 int save_png(const char *fn, const Image *image, bool alpha, bool invert, bool npot)
1053 unsigned flip_bits = (invert==alpha ? 0xFF : 0x00);
1054 unsigned char *src = image->data;
1056 if(!strcmp(fn, "-"))
1060 out = fopen(fn, "wb");
1063 fprintf(stderr, "Couldn't open %s\n",fn);
1068 pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1071 fprintf(stderr, "Error writing PNG file\n");
1074 pngi = png_create_info_struct(pngs);
1077 png_destroy_write_struct(&pngs, NULL);
1078 fprintf(stderr, "Error writing PNG file\n");
1082 w = (npot ? image->w : round_to_pot(image->w));
1083 h = (npot ? image->h : round_to_pot(image->h));
1084 color = (alpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY);
1085 png_set_IHDR(pngs, pngi, w, h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1087 png_init_io(pngs, out);
1088 png_write_info(pngs, pngi);
1089 row = (png_byte *)malloc(w*(1+alpha));
1095 row[x*2+1] = flip_bits;
1097 for(y=0; y<image->h; ++y)
1099 for(x=0; x<image->w; ++x)
1100 row[x*2+1] = *src++^flip_bits;
1101 png_write_row(pngs, row);
1109 memset(row+image->w, flip_bits, w-image->w);
1110 for(y=0; y<image->h; ++y)
1112 for(x=0; x<image->w; ++x)
1113 row[x] = *src++^flip_bits;
1114 png_write_row(pngs, row);
1117 memset(row, flip_bits, w);
1121 png_write_row(pngs, row);
1123 png_write_end(pngs, pngi);
1124 png_destroy_write_struct(&pngs, &pngi);
1128 printf("Saved %dx%d PNG image to %s\n", w, h, fn);