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);
82 int init_glyphs(Font *, FT_Face, const Range *, bool);
83 int copy_bitmap(const FT_Bitmap *, Image *);
84 int render_grid(Font *, unsigned, unsigned, unsigned, bool, bool);
85 int render_packed(Font *, unsigned, unsigned, bool);
86 int save_defs(const char *, const Font *);
87 int save_png(const char *, const Image *, char);
91 int main(int argc, char **argv)
95 unsigned n_ranges = 0;
106 unsigned padding = 1;
115 char *out_fn = "font.png";
126 while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:f")) != -1)
131 ranges = (Range *)realloc(ranges, (++n_ranges)*sizeof(Range));
132 convert_code_point_range('r', &ranges[n_ranges-1]);
135 size = convert_numeric_option('s', 1);
138 cpl = convert_numeric_option('l', 1);
141 convert_size('c', &cellw, &cellh);
172 margin = convert_numeric_option('m', 0);
175 padding = convert_numeric_option('n', 0);
182 if(!strcmp(out_fn, "-"))
193 err = FT_Init_FreeType(&freetype);
196 fprintf(stderr, "Couldn't initialize FreeType library\n");
200 err = FT_New_Face(freetype, fn, 0, &face);
203 fprintf(stderr, "Couldn't load font file\n");
204 if(err==FT_Err_Unknown_File_Format)
205 fprintf(stderr, "Unknown file format\n");
211 const char *name = FT_Get_Postscript_Name(face);
212 printf("Font name: %s\n", name);
213 printf("Glyphs: %ld\n", face->num_glyphs);
216 err = FT_Set_Pixel_Sizes(face, 0, size);
219 fprintf(stderr, "Couldn't set size\n");
225 ranges = malloc(sizeof(Range));
227 ranges[0].last = 255;
231 sort_and_compact_ranges(ranges, &n_ranges);
234 err = init_font(&font, face, ranges, n_ranges, autohinter);
240 fprintf(stderr, "No glyphs found in the requested range\n");
245 err = render_packed(&font, margin, padding, npot);
247 err = render_grid(&font, cellw, cellh, cpl, seq, npot);
253 for(i=0; (unsigned)i<font.image.w*font.image.h; ++i)
254 font.image.data[i] = 255-font.image.data[i];
256 err = save_png(out_fn, &font.image, alpha);
261 save_defs(def_fn, &font);
263 for(i=0; (unsigned)i<font.n_glyphs; ++i)
264 free(font.glyphs[i].image.data);
267 free(font.image.data);
270 FT_Done_FreeType(freetype);
277 printf("ttf2png 1.1 - True Type Font to PNG converter\n"
278 "Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions\n"
279 "Distributed under the GNU General Public License\n\n");
281 printf("Usage: ttf2png [options] <TTF file>\n\n");
283 printf("Accepted options (default values in [brackets])\n"
284 " -r Range of code points to convert [0,255]\n"
285 " -s Font size to use, in pixels [10]\n"
286 " -l Number of glyphs to put in one line [auto]\n"
287 " -c Glyph cell size, in pixels (grid mode only) [auto]\n"
288 " -o Output file name (or - for stdout) [font.png]\n");
289 printf(" -a Force autohinter\n"
290 " -t Render glyphs to alpha channel\n"
291 " -i Invert colors of the glyphs\n"
292 " -v Increase the level of verbosity\n"
293 " -e Use cells in sequence, without gaps (grid mode only)\n"
294 " -p Pack the glyphs tightly instead of in a grid\n"
295 " -m Margin around image edges (packed mode only) [0]\n"
296 " -n Padding between glyphs (packed mode only) [1]\n"
297 " -f Allow non-power-of-two result\n"
298 " -d File name for writing glyph definitions\n"
299 " -h Print this message\n");
302 int convert_numeric_option(char opt, int min_value)
307 value = strtol(optarg, &ptr, 0);
308 if(value<min_value || *ptr)
310 printf("Invalid option argument in -%c %s\n", opt, optarg);
317 void convert_code_point_range(char opt, Range *range)
322 if(!strcmp(optarg, "all"))
325 range->last = 0x10FFFF;
329 value = str_to_code_point(optarg, &ptr);
330 if(value>0 && *ptr==',')
332 range->first = value;
333 value = str_to_code_point(ptr+1, &ptr);
341 printf("Invalid option argument in -%c %s\n", opt, optarg);
345 unsigned str_to_code_point(const char *nptr, char **endptr)
347 if(nptr[0]=='U' && nptr[1]=='+')
348 return strtoul(nptr+2, endptr, 16);
349 else if(nptr[0]&0x80)
356 *endptr = (char *)nptr;
358 for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
359 if((nptr[bytes]&0xC0)!=0x80)
364 code = nptr[0]&(0x3F>>bytes);
365 for(i=1; i<bytes; ++i)
366 code = (code<<6)|(nptr[i]&0x3F);
369 *endptr = (char *)nptr+bytes;
373 else if(isdigit(nptr[0]))
374 return strtoul(nptr, endptr, 0);
378 *endptr = (char *)nptr+1;
383 void convert_size(char opt, unsigned *width, unsigned *height)
388 if(!strcmp(optarg, "auto"))
394 else if(!strcmp(optarg, "autorect"))
401 value = strtol(optarg, &ptr, 0);
407 value = strtol(ptr+1, &ptr, 0);
421 printf("Invalid option argument in -%c %s\n", opt, optarg);
425 void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges)
432 qsort(ranges, *n_ranges, sizeof(Range), &range_cmp);
433 for(i=0, j=1; j<*n_ranges; ++j)
435 if(ranges[i].last+1>=ranges[j].first)
437 if(ranges[j].last>ranges[i].last)
438 ranges[i].last = ranges[j].last;
444 ranges[i] = ranges[j];
451 int range_cmp(const void *p1, const void *p2)
453 const Range *r1 = (const Range *)p1;
454 const Range *r2 = (const Range *)p2;
455 if(r1->first!=r2->first)
456 return (r1->first<r2->first ? -1 : 1);
457 else if(r1->last!=r2->last)
458 return (r1->last<r2->last ? -1 : 1);
463 unsigned round_to_pot(unsigned n)
475 void *alloc_image_data(size_t a, size_t b)
479 /* Carry out the multiplication manually so we can check for overflow. */
488 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(c/1024*b));
495 fprintf(stderr, "Cannot allocate %lu kbytes of memory for image\n", (unsigned long)(a/1024*b));
499 int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter)
504 font->ascent = (face->size->metrics.ascender+63)>>6;
505 font->descent = (face->size->metrics.descender+63)>>6;
509 printf("Ascent: %d\n", font->ascent);
510 printf("Descent: %d\n", font->descent);
515 for(i=0; i<n_ranges; ++i)
516 if(init_glyphs(font, face, &ranges[i], autohinter))
520 printf("Loaded %u glyphs\n", font->n_glyphs);
523 font->kerning = NULL;
524 for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_glyphs; ++j)
528 FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning);
530 /* FreeType documentation says that vertical kerning is practically
531 never used, so we ignore it. */
536 if(font->n_kerning>=size)
539 font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning));
542 kern = &font->kerning[font->n_kerning++];
543 kern->left_code = font->glyphs[i].code;
544 kern->right_code = font->glyphs[j].code;
545 kern->distance = kerning.x/64;
550 printf("Loaded %d kerning pairs\n", font->n_kerning);
555 int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter)
558 unsigned size = font->n_glyphs;
560 for(i=range->first; i<=range->last; ++i)
563 FT_Bitmap *bmp = &face->glyph->bitmap;
567 n = FT_Get_Char_Index(face, i);
572 flags |= FT_LOAD_FORCE_AUTOHINT;
573 FT_Load_Glyph(face, n, flags);
574 FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
578 printf(" Code point U+%04X", i);
579 if(i>=0x20 && i<0x7F)
581 else if(i>=0xA0 && i<=0x10FFFF)
586 for(bytes=2; i>>(1+bytes*5); ++bytes) ;
587 for(j=0; j<bytes; ++j)
588 utf8[j] = 0x80 | ((i>>((bytes-j-1)*6))&0x3F);
589 utf8[0] |= 0xF0<<(4-bytes);
592 printf(" (%s)", utf8);
594 printf(": glyph %u, size %dx%d\n", n, bmp->width, bmp->rows);
597 if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
599 fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
603 if(font->n_glyphs>=size)
606 font->glyphs = (Glyph *)realloc(font->glyphs, size*sizeof(Glyph));
609 glyph = &font->glyphs[font->n_glyphs++];
612 glyph->offset_x = face->glyph->bitmap_left;
613 glyph->offset_y = face->glyph->bitmap_top-bmp->rows;
614 glyph->advance = (int)(face->glyph->advance.x+32)/64;
616 /* Copy the glyph image since FreeType uses a global buffer, which would
617 be overwritten by the next glyph. Negative pitch means the scanlines
618 start from the bottom. */
619 if(copy_bitmap(bmp, &glyph->image))
626 int copy_bitmap(const FT_Bitmap *bmp, Image *image)
632 image->w = bmp->width;
633 image->h = bmp->rows;
634 if(!image->w || !image->h)
640 image->data = (char *)malloc(image->w*image->h);
643 fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
648 src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
653 for(y=0; y<bmp->rows; ++y)
655 if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
657 for(x=0; x<bmp->width; ++x)
658 dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
662 for(x=0; x<bmp->width; ++x)
673 int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot)
676 int top = 0, bot = 0;
677 unsigned first, last;
678 unsigned maxw = 0, maxh = 0;
680 /* Find extremes of the glyph images. */
681 for(i=0; i<font->n_glyphs; ++i)
685 y = font->glyphs[i].offset_y+font->glyphs[i].image.h;
688 if(font->glyphs[i].offset_y<bot)
689 bot = font->glyphs[i].offset_y;
690 if(font->glyphs[i].image.w>maxw)
691 maxw = font->glyphs[i].image.w;
692 if(font->glyphs[i].image.h>maxh)
693 maxh = font->glyphs[i].image.h;
698 /* Establish a large enough cell to hold all glyphs in the range. */
699 int square = (cellh==cellw);
713 printf("Max size: %u x %u\n", maxw, maxh);
714 printf("Y range: [%d %d]\n", bot, top);
715 printf("Cell size: %u x %u\n", cellw, cellh);
716 if(maxw>cellw || (unsigned)(top-bot)>cellh)
717 fprintf(stderr, "Warning: character size exceeds cell size\n");
722 /* Determine number of characters per line, trying to fit all the glyphs
723 in a square image. */
727 if(cpl>0 && font->n_glyphs/cpl*cellh<=cpl*cellw)
732 first = font->glyphs[0].code;
735 last = font->glyphs[font->n_glyphs-1].code;
737 font->image.w = cpl*cellw;
739 font->image.w = round_to_pot(font->image.w);
741 font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh;
743 font->image.h = (last-first+cpl)/cpl*cellh;
745 font->image.h = round_to_pot(font->image.h);
747 font->image.data = (char *)alloc_image_data(font->image.w, font->image.h);
748 if(!font->image.data)
750 memset(font->image.data, 255, font->image.w*font->image.h);
752 for(i=0; i<font->n_glyphs; ++i)
758 glyph = &font->glyphs[i];
763 ci = glyph->code-first;
768 if(cellw>glyph->image.w)
769 cx += (cellw-glyph->image.w)/2;
770 cy += top-glyph->offset_y-glyph->image.h;
775 for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
777 if(cx+x>=font->image.w || cy+y>=font->image.h)
779 font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
786 int render_packed(Font *font, unsigned margin, unsigned padding, bool npot)
791 unsigned *used_pixels;
792 unsigned cx = margin, cy;
795 /* Compute the total area occupied by glyphs and padding. */
796 for(i=0; i<font->n_glyphs; ++i)
798 size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding);
801 fprintf(stderr, "Overflow in counting total glyph area\n");
807 /* Find an image size that's no higher than wide, allowing for some
808 imperfections in the packing. */
809 for(font->image.w=1;; font->image.w<<=1)
811 if(font->image.w<=margin*2)
813 font->image.h = (area*5/4)/(font->image.w-margin*2)+margin*2;
814 if(font->image.h<=font->image.w)
818 font->image.h = round_to_pot(font->image.h);
820 /* Allocate arrays for storing the image and keeping track of used pixels and
821 glyphs. Since glyphs are rectangular and the image is filled starting from
822 the top, it's enough to track the number of used pixels at the top of each
824 font->image.data = (char *)alloc_image_data(font->image.w, font->image.h);
825 if(!font->image.data)
827 memset(font->image.data, 255, font->image.w*font->image.h);
828 used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
829 memset(used_pixels, 0, font->image.w*sizeof(unsigned));
830 used_glyphs = (char *)malloc(font->n_glyphs);
831 memset(used_glyphs, 0, font->n_glyphs);
833 for(cy=margin; cy+margin<font->image.h;)
838 unsigned best_score = 0;
839 unsigned target_h = 0;
841 /* Find the leftmost free pixel on this row. Also record the lowest
842 extent of glyphs to the left of the free position. */
843 for(; (cx+margin<font->image.w && used_pixels[cx]>cy); ++cx)
844 if(used_pixels[cx]-cy-padding>target_h)
845 target_h = used_pixels[cx]-cy-padding;
847 if(cx+margin>=font->image.w)
854 /* Count the free pixel at this position. */
855 for(w=0; (cx+w+margin<font->image.w && used_pixels[cx+w]<=cy); ++w) ;
857 /* Find a suitable glyph to put here. */
858 for(i=0; i<font->n_glyphs; ++i)
862 g = &font->glyphs[i];
863 if(!used_glyphs[i] && g->image.w<=w)
867 /* Prefer glyphs that would reach exactly as low as the ones left
868 of here. This aims to create a straight edge at the bottom for
869 lining up further glyphs. */
870 score = g->image.h+padding;
871 if(g->image.h==target_h)
890 used_glyphs[glyph-font->glyphs] = 1;
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];
900 for(x=0; x<glyph->image.w+2*padding; ++x)
902 if(cx+x<padding || cx+x>=font->image.w+padding)
904 if(used_pixels[cx+x-padding]<cy+glyph->image.h+padding)
905 used_pixels[cx+x-padding] = cy+glyph->image.h+padding;
908 if(cy+glyph->image.h+margin>used_h)
909 used_h = cy+glyph->image.h+margin;
912 /* Trim the image to the actually used size, in case the original estimate
913 was too pessimistic. */
914 font->image.h = used_h;
916 font->image.h = round_to_pot(font->image.h);
924 int save_defs(const char *fn, const Font *font)
929 out = fopen(fn, "w");
932 fprintf(stderr, "Couldn't open %s\n",fn);
936 fprintf(out, "# Image/font info:\n");
937 fprintf(out, "# width height size ascent descent\n");
938 fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
939 fprintf(out, "\n# Glyph info:\n");
940 fprintf(out, "# code x y width height offset_x offset_y advance\n");
941 for(i=0; i<font->n_glyphs; ++i)
943 const Glyph *g = &font->glyphs[i];
944 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);
946 fprintf(out, "\n# Kerning info:\n");
947 fprintf(out, "# left right distance\n");
948 for(i=0; i<font->n_kerning; ++i)
950 const Kerning *k = &font->kerning[i];
951 fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
959 int save_png(const char *fn, const Image *image, char alpha)
973 out = fopen(fn, "wb");
976 fprintf(stderr, "Couldn't open %s\n",fn);
981 pngs = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
984 fprintf(stderr, "Error writing PNG file\n");
987 pngi = png_create_info_struct(pngs);
990 png_destroy_write_struct(&pngs, NULL);
991 fprintf(stderr, "Error writing PNG file\n");
995 png_init_io(pngs, out);
996 rows = (png_byte **)malloc(image->h*sizeof(png_byte *));
999 data2 = (png_byte *)alloc_image_data(image->w*2, image->h);
1002 for(i=0; i<image->w*image->h; ++i)
1005 data2[i*2+1] = 255-image->data[i];
1007 for(i=0; i<image->h; ++i)
1008 rows[i] = (png_byte *)(data2+i*image->w*2);
1009 color = PNG_COLOR_TYPE_GRAY_ALPHA;
1013 for(i=0; i<image->h; ++i)
1014 rows[i] = (png_byte *)(image->data+i*image->w);
1015 color = PNG_COLOR_TYPE_GRAY;
1017 png_set_IHDR(pngs, pngi, image->w, image->h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1018 png_set_rows(pngs, pngi, rows);
1019 png_write_png(pngs, pngi, PNG_TRANSFORM_IDENTITY, NULL);
1020 png_destroy_write_struct(&pngs, &pngi);
1026 printf("Saved %dx%d PNG image to %s\n", image->w, image->h, fn);