X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=ttf2png.c;h=e39c328c2a2b3a7dc90eb726d3de7be6dedd1d51;hb=3ea6caa46577f716fa0e5cb46574469c44ee74ed;hp=2a087ff3ac02eff7acfe403821f6a6704e672f23;hpb=633be0c0c9ae91ab068ee84d4eb5f32328cf6280;p=ttf2png.git diff --git a/ttf2png.c b/ttf2png.c index 2a087ff..e39c328 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -74,12 +74,14 @@ int convert_numeric_option(char, int); void convert_code_point_range(char, Range *); unsigned str_to_code_point(const char *, char **); void convert_size(char, unsigned *, unsigned *); +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); int init_glyphs(Font *, FT_Face, const Range *, bool); -int render_grid(Font *, unsigned, unsigned, unsigned, bool); -int render_packed(Font *, unsigned, unsigned); +int render_grid(Font *, unsigned, unsigned, unsigned, bool, bool); +int render_packed(Font *, unsigned, unsigned, bool); int save_defs(const char *, const Font *); int save_png(const char *, const Image *, char); @@ -101,6 +103,7 @@ int main(int argc, char **argv) bool pack = 0; unsigned margin = 0; unsigned padding = 1; + bool npot = 0; FT_Library freetype; FT_Face face; @@ -119,7 +122,7 @@ int main(int argc, char **argv) return 1; } - while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:")) != -1) + while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:f")) != -1) { switch(i) { @@ -170,6 +173,9 @@ int main(int argc, char **argv) case 'n': padding = convert_numeric_option('n', 0); break; + case 'f': + npot = 1; + break; } } if(!strcmp(out_fn, "-")) @@ -213,6 +219,16 @@ int main(int argc, char **argv) return 1; } + if(!n_ranges) + { + ranges = malloc(sizeof(Range)); + ranges[0].first = 0; + ranges[0].last = 255; + n_ranges = 1; + } + else + sort_and_compact_ranges(ranges, &n_ranges); + font.size = size; err = init_font(&font, face, ranges, n_ranges, autohinter); if(err) @@ -225,9 +241,9 @@ int main(int argc, char **argv) } if(pack) - err = render_packed(&font, margin, padding); + err = render_packed(&font, margin, padding, npot); else - err = render_grid(&font, cellw, cellh, cpl, seq); + err = render_grid(&font, cellw, cellh, cpl, seq, npot); if(err) return 1; @@ -277,6 +293,7 @@ void usage(void) " -p Pack the glyphs tightly instead of in a grid\n" " -m Margin around image edges (packed mode only) [0]\n" " -n Padding between glyphs (packed mode only) [1]\n" + " -f Allow non-power-of-two result\n" " -d File name for writing glyph definitions\n" " -h Print this message\n"); } @@ -404,6 +421,44 @@ void convert_size(char opt, unsigned *width, unsigned *height) exit(1); } +void sort_and_compact_ranges(Range *ranges, unsigned *n_ranges) +{ + unsigned i, j; + + if(!*n_ranges) + return; + + qsort(ranges, *n_ranges, sizeof(Range), &range_cmp); + for(i=0, j=1; j<*n_ranges; ++j) + { + if(ranges[i].last+1>=ranges[j].first) + { + if(ranges[j].last>ranges[i].last) + ranges[i].last = ranges[j].last; + } + else + { + ++i; + if(i!=j) + ranges[i] = ranges[j]; + } + } + + *n_ranges = i+1; +} + +int range_cmp(const void *p1, const void *p2) +{ + const Range *r1 = (const Range *)p1; + const Range *r2 = (const Range *)p2; + if(r1->first!=r2->first) + return (r1->firstfirst ? -1 : 1); + else if(r1->last!=r2->last) + return (r1->lastlast ? -1 : 1); + else + return 0; +} + unsigned round_to_pot(unsigned n) { n -= 1; @@ -584,7 +639,7 @@ int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter) return 0; } -int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq) +int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool seq, bool npot) { unsigned i; int top = 0, bot = 0; @@ -648,11 +703,15 @@ int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool s first -= first%cpl; last = font->glyphs[font->n_glyphs-1].code; - font->image.w = round_to_pot(cpl*cellw); + font->image.w = cpl*cellw; + if(!npot) + font->image.w = round_to_pot(font->image.w); if(seq) - font->image.h = round_to_pot((font->n_glyphs+cpl-1)/cpl*cellh); + font->image.h = (font->n_glyphs+cpl-1)/cpl*cellh; else - font->image.h = round_to_pot((last-first+cpl)/cpl*cellh); + font->image.h = (last-first+cpl)/cpl*cellh; + if(!npot) + font->image.h = round_to_pot(font->image.h); font->image.data = (char *)alloc_image_data(font->image.w, font->image.h); if(!font->image.data) @@ -693,7 +752,7 @@ int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, bool s return 0; } -int render_packed(Font *font, unsigned margin, unsigned padding) +int render_packed(Font *font, unsigned margin, unsigned padding, bool npot) { unsigned i; size_t area = 0; @@ -724,7 +783,8 @@ int render_packed(Font *font, unsigned margin, unsigned padding) if(font->image.h<=font->image.w) break; } - font->image.h = round_to_pot(font->image.h); + if(!npot) + font->image.h = round_to_pot(font->image.h); /* Allocate arrays for storing the image and keeping track of used pixels and glyphs. Since glyphs are rectangular and the image is filled starting from @@ -820,7 +880,9 @@ int render_packed(Font *font, unsigned margin, unsigned padding) /* Trim the image to the actually used size, in case the original estimate was too pessimistic. */ - font->image.h = round_to_pot(used_h); + font->image.h = used_h; + if(!npot) + font->image.h = round_to_pot(font->image.h); free(used_glyphs); free(used_pixels);