From c89b104eff8c264817472585b70e6f57ca74eebd Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 14 Jul 2015 13:08:35 +0300 Subject: [PATCH] Make margin and padding in packed mode controllable --- Readme | 12 ++++++++++++ ttf2png.c | 54 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/Readme b/Readme index 74f4b56..f9effa6 100644 --- a/Readme +++ b/Readme @@ -57,6 +57,14 @@ Command-line options definition file is recommended, as the resulting image can seem rather messy. + -m + Leave a margin around the edges of the generated image. By default glyphs + can touch the edges. Only used with -p. + + -n + Control the amount of padding between glyphs. The default is 1 pixel. + Only used with -p. + -d File name to write glyph definitions. See the section below for details. @@ -124,6 +132,10 @@ some fonts, not all of the glyphs fit completely inside the character box. Changelog +next +- Controllable margin and padding in packed mode +- Do not generate overly large images in sequential grid mode + 1.0 - Improve the packing algorithm - Non-square cells for grid mode diff --git a/ttf2png.c b/ttf2png.c index f8f465f..733453d 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -66,7 +66,7 @@ unsigned round_to_pot(unsigned); void *alloc_image_data(size_t, size_t); int init_font(Font *, FT_Face, unsigned, unsigned, int); int render_grid(Font *, unsigned, unsigned, unsigned, int); -int render_packed(Font *); +int render_packed(Font *, unsigned, unsigned); int save_defs(const char *, const Font *); int save_png(const char *, const Image *, char); @@ -86,6 +86,8 @@ int main(int argc, char **argv) char alpha = 0; char invert = 0; char pack = 0; + int margin = 0; + int padding = 1; FT_Library freetype; FT_Face face; @@ -104,7 +106,7 @@ int main(int argc, char **argv) return 1; } - while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pi")) != -1) + while((i = getopt(argc, argv, "r:s:l:c:o:atvh?ed:pim:n:")) != -1) { char *ptr; int temp; @@ -192,6 +194,12 @@ int main(int argc, char **argv) case 'i': invert = 1; break; + case 'm': + margin = strtol(optarg, NULL, 0); + break; + case 'n': + padding = strtol(optarg, NULL, 0); + break; } } if(!strcmp(out_fn, "-")) @@ -241,7 +249,7 @@ int main(int argc, char **argv) return 1; if(pack) - err = render_packed(&font); + err = render_packed(&font, margin, padding); else err = render_grid(&font, cellw, cellh, cpl, seq); if(err) @@ -291,6 +299,8 @@ void usage() " -v Increase the level of verbosity\n" " -e Use cells in sequence, without gaps\n" " -p Pack the glyphs tightly instead of in a grid\n" + " -m Margin around image edges in packed mode [0]\n" + " -n Padding between packed glyphs [1]\n" " -d File name for writing glyph definitions\n" " -h Print this message\n"); } @@ -555,19 +565,19 @@ int render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, int se return 0; } -int render_packed(Font *font) +int render_packed(Font *font, unsigned margin, unsigned padding) { unsigned i; size_t area = 0; char *used_glyphs; unsigned *used_pixels; - unsigned cx = 0, cy; + unsigned cx = margin, cy; unsigned used_h = 0; /* Compute the total area occupied by glyphs and padding. */ for(i=0; in_glyphs; ++i) { - size_t a = area+(font->glyphs[i].image.w+1)*(font->glyphs[i].image.h+1); + size_t a = area+(font->glyphs[i].image.w+padding)*(font->glyphs[i].image.h+padding); if(aimage.w=1;; font->image.w<<=1) { - font->image.h = (area*5/4)/font->image.w; + if(font->image.w<=margin*2) + continue; + font->image.h = (area*5/4)/(font->image.w-margin*2)+margin*2; if(font->image.h<=font->image.w) break; } @@ -599,7 +611,7 @@ int render_packed(Font *font) used_glyphs = (char *)malloc(font->n_glyphs); memset(used_glyphs, 0, font->n_glyphs); - for(cy=0; cyimage.h;) + for(cy=margin; cy+marginimage.h;) { unsigned w; unsigned x, y; @@ -609,19 +621,19 @@ int render_packed(Font *font) /* Find the leftmost free pixel on this row. Also record the lowest extent of glyphs to the left of the free position. */ - for(; (cximage.w && used_pixels[cx]>cy); ++cx) - if(used_pixels[cx]-cy-1>target_h) - target_h = used_pixels[cx]-cy-1; + for(; (cx+marginimage.w && used_pixels[cx]>cy); ++cx) + if(used_pixels[cx]-cy-padding>target_h) + target_h = used_pixels[cx]-cy-padding; - if(cx>=font->image.w) + if(cx+margin>=font->image.w) { - cx = 0; + cx = margin; ++cy; continue; } /* Count the free pixel at this position. */ - for(w=0; (cx+wimage.w && used_pixels[cx+w]<=cy); ++w) ; + for(w=0; (cx+w+marginimage.w && used_pixels[cx+w]<=cy); ++w) ; /* Find a suitable glyph to put here. */ for(i=0; in_glyphs; ++i) @@ -636,7 +648,7 @@ int render_packed(Font *font) /* Prefer glyphs that would reach exactly as low as the ones left of here. This aims to create a straight edge at the bottom for lining up further glyphs. */ - score = g->image.h+1; + score = g->image.h+padding; if(g->image.h==target_h) score *= g->image.w; else @@ -666,16 +678,16 @@ int render_packed(Font *font) continue; font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w]; } - for(x=0; ximage.w+2; ++x) + for(x=0; ximage.w+2*padding; ++x) { - if(cx+x<1 || cx+x>font->image.w) + if(cx+x=font->image.w+padding) continue; - if(used_pixels[cx+x-1]image.h+1) - used_pixels[cx+x-1] = cy+glyph->image.h+1; + if(used_pixels[cx+x-padding]image.h+padding) + used_pixels[cx+x-padding] = cy+glyph->image.h+padding; } - if(cy+glyph->image.h>used_h) - used_h = cy+glyph->image.h; + if(cy+glyph->image.h+margin>used_h) + used_h = cy+glyph->image.h+margin; } /* Trim the image to the actually used size, in case the original estimate -- 2.43.0