From 633be0c0c9ae91ab068ee84d4eb5f32328cf6280 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 14 Apr 2018 16:45:10 +0300 Subject: [PATCH] Support multiple disjoint code point ranges --- Readme | 4 +- ttf2png.c | 113 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 69 insertions(+), 48 deletions(-) diff --git a/Readme b/Readme index 7ce6e70..9d10f6c 100644 --- a/Readme +++ b/Readme @@ -15,7 +15,8 @@ Command-line options Range of code points to convert, specified as unicode code points. The default is 0,255, matching the ISO-8859-1 (Latin-1) character set. Code points can be specified as plain numbers, unicode code points (U+xxxx) or - UTF-8 characters. + UTF-8 characters. This option can be specified multiple times to add + more ranges to be converted. -s Font size to use. The default is 10 pixels. @@ -137,6 +138,7 @@ Changelog next - Alternate ways of specifying code point ranges +- Multiple code point ranges can be specified 1.1 - Controllable margin and padding in packed mode diff --git a/ttf2png.c b/ttf2png.c index 58b9016..2a087ff 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -61,16 +61,23 @@ typedef struct sFont Image image; } Font; +typedef struct sRange +{ + unsigned first; + unsigned last; +} Range; + typedef int bool; void usage(void); int convert_numeric_option(char, int); -void convert_code_point_range(char, unsigned *, unsigned *); +void convert_code_point_range(char, Range *); unsigned str_to_code_point(const char *, char **); void convert_size(char, unsigned *, unsigned *); unsigned round_to_pot(unsigned); void *alloc_image_data(size_t, size_t); -int init_font(Font *, FT_Face, unsigned, unsigned, bool); +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 save_defs(const char *, const Font *); @@ -81,8 +88,8 @@ char verbose = 0; int main(int argc, char **argv) { char *fn; - unsigned begin = 0; - unsigned end = 255; + Range *ranges = NULL; + unsigned n_ranges = 0; unsigned size = 10; unsigned cpl = 0; unsigned cellw = 0; @@ -117,7 +124,8 @@ int main(int argc, char **argv) switch(i) { case 'r': - convert_code_point_range('r', &begin, &end); + ranges = (Range *)realloc(ranges, (++n_ranges)*sizeof(Range)); + convert_code_point_range('r', &ranges[n_ranges-1]); break; case 's': size = convert_numeric_option('s', 1); @@ -206,7 +214,7 @@ int main(int argc, char **argv) } font.size = size; - err = init_font(&font, face, begin, end, autohinter); + err = init_font(&font, face, ranges, n_ranges, autohinter); if(err) return 1; @@ -288,26 +296,26 @@ int convert_numeric_option(char opt, int min_value) return value; } -void convert_code_point_range(char opt, unsigned *begin, unsigned *end) +void convert_code_point_range(char opt, Range *range) { int value; char *ptr; if(!strcmp(optarg, "all")) { - *begin = 0; - *end = 0x10FFFF; + range->first = 0; + range->last = 0x10FFFF; return; } value = str_to_code_point(optarg, &ptr); if(value>0 && *ptr==',') { - *begin = value; + range->first = value; value = str_to_code_point(ptr+1, &ptr); if(value>0 && !*ptr) { - *end = value; + range->last = value; return; } } @@ -432,7 +440,7 @@ void *alloc_image_data(size_t a, size_t b) return ptr; } -int init_font(Font *font, FT_Face face, unsigned first, unsigned last, bool autohinter) +int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, bool autohinter) { unsigned i, j; unsigned size = 0; @@ -448,7 +456,52 @@ int init_font(Font *font, FT_Face face, unsigned first, unsigned last, bool auto font->n_glyphs = 0; font->glyphs = NULL; - for(i=first; i<=last; ++i) + for(i=0; i=1) + printf("Loaded %u glyphs\n", font->n_glyphs); + + font->n_kerning = 0; + font->kerning = NULL; + for(i=0; in_glyphs; ++i) for(j=0; jn_glyphs; ++j) + if(j!=i) + { + FT_Vector kerning; + FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning); + + /* FreeType documentation says that vertical kerning is practically + never used, so we ignore it. */ + if(kerning.x) + { + Kerning *kern; + + if(font->n_kerning>=size) + { + size += 16; + font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning)); + } + + kern = &font->kerning[font->n_kerning++]; + kern->left_code = font->glyphs[i].code; + kern->right_code = font->glyphs[j].code; + kern->distance = kerning.x/64; + } + } + + if(verbose>=1) + printf("Loaded %d kerning pairs\n", font->n_kerning); + + return 0; +} + +int init_glyphs(Font *font, FT_Face face, const Range *range, bool autohinter) +{ + unsigned i, j; + unsigned size = font->n_glyphs; + + for(i=range->first; i<=range->last; ++i) { unsigned n; FT_Bitmap *bmp = &face->glyph->bitmap; @@ -528,40 +581,6 @@ int init_font(Font *font, FT_Face face, unsigned first, unsigned last, bool auto } } - if(verbose>=1) - printf("Loaded %u glyphs\n", font->n_glyphs); - - size = 0; - font->n_kerning = 0; - font->kerning = NULL; - for(i=0; in_glyphs; ++i) for(j=0; jn_glyphs; ++j) - if(j!=i) - { - FT_Vector kerning; - FT_Get_Kerning(face, font->glyphs[i].index, font->glyphs[j].index, FT_KERNING_DEFAULT, &kerning); - - /* FreeType documentation says that vertical kerning is practically - never used, so we ignore it. */ - if(kerning.x) - { - Kerning *kern; - - if(font->n_kerning>=size) - { - size += 16; - font->kerning = (Kerning *)realloc(font->kerning, size*sizeof(Kerning)); - } - - kern = &font->kerning[font->n_kerning++]; - kern->left_code = font->glyphs[i].code; - kern->right_code = font->glyphs[j].code; - kern->distance = kerning.x/64; - } - } - - if(verbose>=1) - printf("Loaded %d kerning pairs\n", font->n_kerning); - return 0; } -- 2.45.2