typedef struct sImage
{
unsigned w, h;
- char *data;
+ unsigned char *data;
} Image;
typedef struct sGlyph
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 copy_bitmap(const FT_Bitmap *, Image *);
+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, "-"))
}
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;
free(font.glyphs);
free(font.kerning);
free(font.image.data);
+ free(ranges);
FT_Done_Face(face);
FT_Done_FreeType(freetype);
" -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");
}
unsigned i, j;
unsigned size = 0;
- font->ascent = (face->size->metrics.ascender+63)>>6;
- font->descent = (face->size->metrics.descender+63)>>6;
+ font->ascent = (face->size->metrics.ascender+63)/64;
+ font->descent = (face->size->metrics.descender-63)/64;
if(verbose>=1)
{
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;
+ kern->distance = (kerning.x+32)/64;
}
}
{
unsigned n;
FT_Bitmap *bmp = &face->glyph->bitmap;
- unsigned x, y;
int flags = 0;
Glyph *glyph;
printf(": glyph %u, size %dx%d\n", n, bmp->width, bmp->rows);
}
- if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY)
+ if(bmp->pixel_mode!=FT_PIXEL_MODE_GRAY && bmp->pixel_mode!=FT_PIXEL_MODE_MONO)
{
- fprintf(stderr, "Warning: Glyph %u skipped, not grayscale\n", n);
+ fprintf(stderr, "Warning: Glyph %u skipped, incompatible pixel mode\n", n);
continue;
}
glyph = &font->glyphs[font->n_glyphs++];
glyph->index = n;
glyph->code = i;
- glyph->image.w = bmp->width;
- glyph->image.h = bmp->rows;
- glyph->image.data = (char *)malloc(bmp->width*bmp->rows);
- if(!glyph->image.data)
- {
- fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", bmp->width*bmp->rows);
- return -1;
- }
glyph->offset_x = face->glyph->bitmap_left;
glyph->offset_y = face->glyph->bitmap_top-bmp->rows;
glyph->advance = (int)(face->glyph->advance.x+32)/64;
/* Copy the glyph image since FreeType uses a global buffer, which would
be overwritten by the next glyph. Negative pitch means the scanlines
start from the bottom. */
- if(bmp->pitch<0)
+ if(copy_bitmap(bmp, &glyph->image))
+ return -1;
+ }
+
+ return 0;
+}
+
+int copy_bitmap(const FT_Bitmap *bmp, Image *image)
+{
+ unsigned x, y;
+ unsigned char *src;
+ unsigned char *dst;
+
+ image->w = bmp->width;
+ image->h = bmp->rows;
+ if(!image->w || !image->h)
+ {
+ image->data = NULL;
+ return 0;
+ }
+
+ image->data = (unsigned char *)malloc(image->w*image->h);
+ if(!image->data)
+ {
+ fprintf(stderr, "Cannot allocate %d bytes of memory for glyph\n", image->w*image->h);
+ return -1;
+ }
+
+ if(bmp->pitch<0)
+ src = bmp->buffer+(bmp->rows-1)*-bmp->pitch;
+ else
+ src = bmp->buffer;
+ dst = image->data;
+
+ for(y=0; y<bmp->rows; ++y)
+ {
+ if(bmp->pixel_mode==FT_PIXEL_MODE_MONO)
{
- for(y=0; y<bmp->rows; ++y) for(x=0; x<bmp->width; ++x)
- glyph->image.data[x+(glyph->image.h-1-y)*glyph->image.w] = bmp->buffer[x-y*bmp->pitch];
+ for(x=0; x<bmp->width; ++x)
+ dst[x] = ((src[x/8]&(0x80>>(x%8))) ? 0xFF : 0x00);
}
else
{
- for(y=0; y<bmp->rows; ++y) for(x=0; x<bmp->width; ++x)
- glyph->image.data[x+y*glyph->image.w] = bmp->buffer[x+y*bmp->pitch];
+ for(x=0; x<bmp->width; ++x)
+ dst[x] = src[x];
}
+
+ src += bmp->pitch;
+ dst += image->w;
}
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);
+ 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);
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
the top, it's enough to track the number of used pixels at the top of each
column. */
- font->image.data = (char *)alloc_image_data(font->image.w, 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);
/* 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);