typedef struct sGlyph
{
+ unsigned index;
unsigned code;
Image image;
unsigned x, y;
int advance;
} Glyph;
+typedef struct sKerning
+{
+ unsigned left_code;
+ unsigned right_code;
+ int distance;
+} Kerning;
+
typedef struct sFont
{
unsigned size;
int descent;
unsigned n_glyphs;
Glyph *glyphs;
+ unsigned n_kerning;
+ Kerning *kerning;
Image image;
} Font;
render_grid(&font, cellw, cellh, cpl, seq);
if(invert)
{
- for(i=0; i<font.image.w*font.image.h; ++i)
+ for(i=0; (unsigned)i<font.image.w*font.image.h; ++i)
font.image.data[i] = 255-font.image.data[i];
}
save_png(out_fn, &font.image, alpha);
if(def_fn)
save_defs(def_fn, &font);
- for(i=0; i<font.n_glyphs; ++i)
+ for(i=0; (unsigned)i<font.n_glyphs; ++i)
free(font.glyphs[i].image.data);
free(font.glyphs);
free(font.image.data);
{
printf("ttf2png - True Type Font to PNG converter\n"
"Copyright (c) 2004-2008 Mikko Rasa, Mikkosoft Productions\n"
- "Distributed under the GNU General Public License\n\n"
- "Usage: ttf2png [options] <TTF file>\n\n"
- "Accepted options (default values in [brackets])\n"
+ "Distributed under the GNU General Public License\n\n");
+
+ printf("Usage: ttf2png [options] <TTF file>\n\n");
+
+ printf("Accepted options (default values in [brackets])\n"
" -r Range of characters to convert [0,255]\n"
" -s Font size to use, in pixels [10]\n"
" -l Number of characters to put in one line [auto]\n"
" -c Character cell size, in pixels [auto]\n"
- " -o Output file name (or - for stdout) [font.png]\n"
- " -a Force autohinter\n"
+ " -o Output file name (or - for stdout) [font.png]\n");
+ printf(" -a Force autohinter\n"
" -t Render glyphs to alpha channel\n"
" -i Invert colors of the glyphs\n"
" -v Increase the level of verbosity\n"
void init_font(Font *font, FT_Face face, unsigned first, unsigned last, int autohinter)
{
- unsigned i;
+ unsigned i, j;
unsigned size = 0;
font->ascent = (face->size->metrics.ascender+63)>>6;
}
glyph = &font->glyphs[font->n_glyphs++];
+ glyph->index = n;
glyph->code = i;
glyph->image.w = bmp->width;
glyph->image.h = bmp->rows;
if(verbose>=1)
printf("Loaded %u glyphs\n", font->n_glyphs);
+
+ size = 0;
+ font->n_kerning = 0;
+ font->kerning = NULL;
+ for(i=0; i<font->n_glyphs; ++i) for(j=0; j<font->n_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);
}
void render_grid(Font *font, unsigned cellw, unsigned cellh, unsigned cpl, int seq)
printf("Max size: %u x %u\n", maxw, maxh);
printf("Y range: [%d %d]\n", bot, top);
printf("Cell size: %u x %u\n", cellw, cellh);
- if(maxw>cellw || top-bot>cellh)
+ if(maxw>cellw || (unsigned)(top-bot)>cellh)
fprintf(stderr, "Warning: character size exceeds cell size\n");
}
for(i=0; i<font->n_glyphs; ++i)
{
Glyph *glyph;
- int ci, cx, cy;
+ unsigned ci, cx, cy;
unsigned x, y;
glyph = &font->glyphs[i];
for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
{
- if(cx+x<0 || cx+x>=font->image.w || cy+y<0 || cy+y>=font->image.h)
+ if(cx+x>=font->image.w || cy+y>=font->image.h)
continue;
font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
}
for(y=0; y<glyph->image.h; ++y) for(x=0; x<glyph->image.w; ++x)
{
- if(cx+x<0 || cx+x>=font->image.w || cy+y<0 || cy+y>=font->image.h)
+ if(cx+x>=font->image.w || cy+y>=font->image.h)
continue;
font->image.data[cx+x+(cy+y)*font->image.w] = 255-glyph->image.data[x+y*glyph->image.w];
}
fprintf(out, "# Image/font info:\n");
fprintf(out, "# width height size ascent descent\n");
- fprintf(out, "%d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
+ fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
fprintf(out, "\n# Glyph info:\n");
fprintf(out, "# code x y width height offset_x offset_y advance\n");
for(i=0; i<font->n_glyphs; ++i)
{
const Glyph *g = &font->glyphs[i];
- fprintf(out, "%u %u %u %u %u %d %d %d\n", g->code, g->x, g->y, g->image.w, g->image.h, g->offset_x, g->offset_y, g->advance);
+ fprintf(out, "glyph %u %u %u %u %u %d %d %d\n", g->code, g->x, g->y, g->image.w, g->image.h, g->offset_x, g->offset_y, g->advance);
+ }
+ fprintf(out, "\n# Kerning info:\n");
+ fprintf(out, "# left right distance\n");
+ for(i=0; i<font->n_kerning; ++i)
+ {
+ const Kerning *k = &font->kerning[i];
+ fprintf(out, "kern %u %u %d\n", k->left_code, k->right_code, k->distance);
}
fclose(out);
FILE *out;
png_struct *pngs;
png_info *pngi;
- png_byte *rows[image->h];
- int i;
+ png_byte **rows;
+ unsigned i;
png_byte *data2;
int color;
}
png_init_io(pngs, out);
+ rows = (png_byte **)malloc(image->h*sizeof(png_byte *));
if(alpha)
{
data2 = (png_byte *)malloc(image->w*image->h*2);
png_set_rows(pngs, pngi, rows);
png_write_png(pngs, pngi, PNG_TRANSFORM_IDENTITY, NULL);
png_destroy_write_struct(&pngs, &pngi);
+ free(rows);
if(alpha)
free(data2);