X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=ttf2png.c;h=6543a8d8a009b2de12f898c6effcb964707012b1;hb=050869535277b43b09f1d306605bb3a70f4ad6c5;hp=bf9f8d2c728a78f41032078661b88de8960c7f46;hpb=1fb6f37cfa76c47b65331b6fe8217f8973f35885;p=ttf2png.git diff --git a/ttf2png.c b/ttf2png.c index bf9f8d2..6543a8d 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -1,6 +1,6 @@ /* ttf2png - True Type Font to PNG converter -Copyright (c) 2004-2008 Mikko Rasa +Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,16 +78,16 @@ void sort_and_compact_ranges(Range *, unsigned *); int range_cmp(const void *, const void *); unsigned round_to_pot(unsigned); void *alloc_image_data(size_t, size_t); -int init_font(Font *, FT_Face, const Range *, unsigned, bool, unsigned); -int init_glyphs(Font *, FT_Face, const Range *, bool, unsigned); +int init_font(Font *, FT_Face, const Range *, unsigned, bool, unsigned, unsigned); +int init_glyphs(Font *, FT_Face, const Range *, bool, unsigned, unsigned); int copy_bitmap(const FT_Bitmap *, Image *); unsigned sqrti(unsigned); unsigned find_distance_to_edge(const Image *, int, int, unsigned); int create_distance_field(const FT_Bitmap *, Image *, unsigned, unsigned); -int render_grid(Font *, unsigned, unsigned, unsigned, bool, bool); -int render_packed(Font *, unsigned, unsigned, bool); +int render_grid(Font *, unsigned, unsigned, unsigned, bool); +int render_packed(Font *, unsigned, unsigned); int save_defs(const char *, const Font *); -int save_png(const char *, const Image *, char); +int save_png(const char *, const Image *, bool, bool, bool); char verbose = 0; @@ -109,6 +109,7 @@ int main(int argc, char **argv) unsigned padding = 1; bool npot = 0; unsigned distfield = 0; + unsigned border = 0; FT_Library freetype; FT_Face face; @@ -127,7 +128,7 @@ int main(int argc, char **argv) return 1; } - while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:gf:")) != -1) + while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:gf:b:")) != -1) { switch(i) { @@ -184,6 +185,9 @@ int main(int argc, char **argv) case 'f': distfield = convert_numeric_option('f', 1); break; + case 'b': + border = convert_numeric_option('b', 1); + break; } } if(!strcmp(out_fn, "-")) @@ -220,7 +224,15 @@ int main(int argc, char **argv) printf("Glyphs: %ld\n", face->num_glyphs); } - err = FT_Set_Pixel_Sizes(face, 0, (distfield ? size*distfield : size)); + font.size = size; + if(distfield) + { + if(!border) + border = sqrti(font.size); + size *= distfield; + } + + err = FT_Set_Pixel_Sizes(face, 0, size); if(err) { fprintf(stderr, "Couldn't set size\n"); @@ -237,8 +249,7 @@ int main(int argc, char **argv) else sort_and_compact_ranges(ranges, &n_ranges); - font.size = size; - err = init_font(&font, face, ranges, n_ranges, autohinter, distfield); + err = init_font(&font, face, ranges, n_ranges, autohinter, distfield, border); if(err) return 1; @@ -249,18 +260,13 @@ int main(int argc, char **argv) } if(pack) - err = render_packed(&font, margin, padding, npot); + err = render_packed(&font, margin, padding); else - err = render_grid(&font, cellw, cellh, cpl, seq, npot); + err = render_grid(&font, cellw, cellh, cpl, seq); if(err) return 1; - if(invert || distfield) - { - for(i=0; (unsigned)in_glyphs = 0; font->glyphs = NULL; for(i=0; i=1) @@ -562,7 +568,7 @@ int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, return 0; } -int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield) +int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, unsigned distfield, unsigned border) { unsigned i, j; unsigned size = font->n_glyphs; @@ -629,11 +635,9 @@ int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter, u start from the bottom. */ if(distfield) { - unsigned margin = 3; - - glyph->offset_x -= margin; - glyph->offset_y -= margin; - create_distance_field(bmp, &glyph->image, distfield, margin); + glyph->offset_x -= border; + glyph->offset_y -= border; + create_distance_field(bmp, &glyph->image, distfield, border); } else { @@ -780,7 +784,7 @@ int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, un return 0; } -int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot) +int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq) { unsigned i; int top = 0, bot = 0; @@ -845,19 +849,15 @@ int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool s last = font->glyphs[font->n_glyphs-1].code; font->image.w = cpl*cellw; - if(!npot) - font->image.w = round_to_pot(font->image.w); if(seq) font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh; else font->image.h = (last-first+cpl)/cpl*cellh; - if(!npot) - font->image.h = round_to_pot(font->image.h); font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h); if(!font->image.data) return -1; - memset(font->image.data, 255, font->image.w*font->image.h); + memset(font->image.data, 0, font->image.w*font->image.h); for(i=0; in_glyphs; ++i) { @@ -886,14 +886,14 @@ int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool s { if(cx+x>=font->image.w || cy+y>=font->image.h) continue; - font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w]; + font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w]; } } return 0; } -int render_packed(Font *font, unsigned margin, unsigned padding, bool npot) +int render_packed(Font *font, unsigned margin, unsigned padding) { unsigned i; size_t area = 0; @@ -934,7 +934,7 @@ int render_packed(Font *font, unsigned margin, unsigned padding, bool npot) font->image.data = (unsigned char *)alloc_image_data(font->image.w, font->image.h); if(!font->image.data) return -1; - memset(font->image.data, 255, font->image.w*font->image.h); + memset(font->image.data, 0, font->image.w*font->image.h); used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned)); memset(used_pixels, 0, font->image.w*sizeof(unsigned)); used_glyphs = (char *)malloc(font->n_glyphs); @@ -1005,7 +1005,7 @@ int render_packed(Font *font, unsigned margin, unsigned padding, bool npot) { if(cx+x>=font->image.w || cy+y>=font->image.h) continue; - font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w]; + font->image.data[cx+x+(cy+y)*font->image.w] = glyph->image.data[x+y*glyph->image.w]; } for(x=0; ximage.w+2*padding; ++x) { @@ -1022,8 +1022,6 @@ int render_packed(Font *font, unsigned margin, unsigned padding, bool npot) /* Trim the image to the actually used size, in case the original estimate was too pessimistic. */ font->image.h = used_h; - if(!npot) - font->image.h = round_to_pot(font->image.h); free(used_glyphs); free(used_pixels); @@ -1066,15 +1064,17 @@ int save_defs(const char *fn, const Font *font) return 0; } -int save_png(const char *fn, const Image *image, char alpha) +int save_png(const char *fn, const Image *image, bool alpha, bool invert, bool npot) { FILE *out; png_struct *pngs; png_info *pngi; - png_byte **rows; - unsigned i; - png_byte *data2 = 0; + unsigned w, h; + png_byte *row; + unsigned x, y; int color; + unsigned flip_bits = (invert==alpha ? 0xFF : 0x00); + unsigned char *src = image->data; if(!strcmp(fn, "-")) out = stdout; @@ -1102,38 +1102,53 @@ int save_png(const char *fn, const Image *image, char alpha) return -1; } + w = (npot ? image->w : round_to_pot(image->w)); + h = (npot ? image->h : round_to_pot(image->h)); + color = (alpha ? PNG_COLOR_TYPE_GRAY_ALPHA : PNG_COLOR_TYPE_GRAY); + png_set_IHDR(pngs, pngi, w, h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_init_io(pngs, out); - rows = (png_byte **)malloc(image->h*sizeof(png_byte *)); + png_write_info(pngs, pngi); + row = (png_byte *)malloc(w*(1+alpha)); if(alpha) { - data2 = (png_byte *)alloc_image_data(image->w*2, image->h); - if(!data2) - return -1; - for(i=0; iw*image->h; ++i) + for(x=0; xh; ++y) { - data2[i*2] = 255; - data2[i*2+1] = 255-image->data[i]; + for(x=0; xw; ++x) + row[x*2+1] = *src++^flip_bits; + png_write_row(pngs, row); } - for(i=0; ih; ++i) - rows[i] = (png_byte *)(data2+i*image->w*2); - color = PNG_COLOR_TYPE_GRAY_ALPHA; + + for(x=0; xh; ++i) - rows[i] = (png_byte *)(image->data+i*image->w); - color = PNG_COLOR_TYPE_GRAY; + memset(row+image->w, flip_bits, w-image->w); + for(y=0; yh; ++y) + { + for(x=0; xw; ++x) + row[x] = *src++^flip_bits; + png_write_row(pngs, row); + } + + memset(row, flip_bits, w); } - png_set_IHDR(pngs, pngi, image->w, image->h, 8, color, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - png_set_rows(pngs, pngi, rows); - png_write_png(pngs, pngi, PNG_TRANSFORM_IDENTITY, NULL); + + for(; yw, image->h, fn); + printf("Saved %dx%d PNG image to %s\n", w, h, fn); fclose(out);