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);
bool pack = 0;
unsigned margin = 0;
unsigned padding = 1;
+ bool npot = 0;
FT_Library freetype;
FT_Face face;
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)
{
case 'n':
padding = convert_numeric_option('n', 0);
break;
+ case 'f':
+ npot = 1;
+ break;
}
}
if(!strcmp(out_fn, "-"))
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)
}
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;
" -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");
}
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->first<r2->first ? -1 : 1);
+ else if(r1->last!=r2->last)
+ return (r1->last<r2->last ? -1 : 1);
+ else
+ return 0;
+}
+
unsigned round_to_pot(unsigned n)
{
n -= 1;
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;
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)
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;
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
/* 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);