/*
ttf2png - True Type Font to PNG converter
-Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions
+Copyright (c) 2004-2021 Mikko Rasa, Mikkosoft Productions
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
{
unsigned w, h;
unsigned char *data;
+ unsigned border;
} Image;
typedef struct sGlyph
typedef struct sKerning
{
- unsigned left_code;
- unsigned right_code;
+ Glyph *left_glyph;
+ Glyph *right_glyph;
int distance;
} Kerning;
unsigned last;
} Range;
-typedef int bool;
+typedef unsigned char bool;
void usage(void);
int convert_numeric_option(char, int);
void convert_code_point_range(char, Range *);
-unsigned str_to_code_point(const char *, char **);
+int 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 *);
void usage(void)
{
- printf("ttf2png 1.1 - True Type Font to PNG converter\n"
- "Copyright (c) 2004-2018 Mikko Rasa, Mikkosoft Productions\n"
+ printf("ttf2png 2.0 - True Type Font to PNG converter\n"
+ "Copyright (c) 2004-2021 Mikko Rasa, Mikkosoft Productions\n"
"Distributed under the GNU General Public License\n\n");
printf("Usage: ttf2png [options] <TTF file>\n\n");
" -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"
- " -g Allow non-power-of-two result\n"
- " -f Create a distance field texture\n"
+ " -g Allow non-power-of-two result\n");
+ printf(" -f Create a distance field texture\n"
+ " -b Specify distance field border zone width\n"
" -d File name for writing glyph definitions\n"
" -h Print this message\n");
}
}
value = str_to_code_point(optarg, &ptr);
- if(value>0 && *ptr==',')
+ if(value>=0 && *ptr==',')
{
range->first = value;
value = str_to_code_point(ptr+1, &ptr);
- if(value>0 && !*ptr)
+ if(value>=(int)range->first && !*ptr)
{
range->last = value;
return;
exit(1);
}
-unsigned str_to_code_point(const char *nptr, char **endptr)
+int str_to_code_point(const char *nptr, char **endptr)
{
if(nptr[0]=='U' && nptr[1]=='+')
return strtoul(nptr+2, endptr, 16);
for(bytes=1; (bytes<4 && (nptr[0]&(0x80>>bytes))); ++bytes)
if((nptr[bytes]&0xC0)!=0x80)
- return 0;
+ return -1;
if(bytes<2)
- return 0;
+ return -1;
code = nptr[0]&(0x3F>>bytes);
for(i=1; i<bytes; ++i)
image->w = w;
image->h = h;
image->data = NULL;
+ image->border = 0;
if(!image->w || !image->h)
return 0;
}
kern = &font->kerning[font->n_kerning++];
- kern->left_code = font->glyphs[i].code;
- kern->right_code = font->glyphs[j].code;
+ kern->left_glyph = &font->glyphs[i];
+ kern->right_glyph = &font->glyphs[j];
kern->distance = (kerning.x/scale+32)/64;
}
}
if(copy_bitmap(bmp, &base_image))
return -1;
+ image->border = margin;
for(y=0; y<image->h; ++y) for(x=0; x<image->w; ++x)
{
int bx = (x-margin)*scale+scale/2;
{
unsigned i;
size_t area = 0;
- char *used_glyphs;
+ bool *used_glyphs;
unsigned *used_pixels;
unsigned cx = margin, cy;
unsigned used_h = 0;
memset(font->image.data, 0, font->image.w*font->image.h);
used_pixels = (unsigned *)malloc(font->image.w*sizeof(unsigned));
memset(used_pixels, 0, font->image.w*sizeof(unsigned));
- used_glyphs = (char *)malloc(font->n_glyphs);
+ used_glyphs = (bool *)malloc(font->n_glyphs);
memset(used_glyphs, 0, font->n_glyphs);
for(cy=margin; cy+margin<font->image.h;)
fprintf(out, "# Image/font info:\n");
fprintf(out, "# width height size ascent descent\n");
fprintf(out, "font %d %d %d %d %d\n", font->image.w, font->image.h, font->size, font->ascent, font->descent);
+
+ fprintf(out, "\n# Code point mapping:\n");
+ fprintf(out, "# code index\n");
+ for(i=0; i<font->n_glyphs; ++i)
+ {
+ const Glyph *g = &font->glyphs[i];
+ fprintf(out, "code %u %u\n", g->code, g->index);
+ }
+
+ fprintf(out, "\n# Metrics info:\n");
+ fprintf(out, "# index width height offset_x offset_y advance\n");
+ for(i=0; i<font->n_glyphs; ++i)
+ {
+ const Glyph *g = &font->glyphs[i];
+ int b = g->image.border;
+ fprintf(out, "metrics %u %u %u %d %d %d\n", g->index, g->image.w-2*b, g->image.h-2*b, g->offset_x+b, g->offset_y+b, g->advance);
+ }
+
fprintf(out, "\n# Glyph info:\n");
- fprintf(out, "# code x y width height offset_x offset_y advance\n");
+ fprintf(out, "# index x y width height border\n");
for(i=0; i<font->n_glyphs; ++i)
{
const Glyph *g = &font->glyphs[i];
- 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, "glyph %u %u %u %u %u %u\n", g->index, g->x, g->y, g->image.w, g->image.h, g->image.border);
}
+
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);
+ fprintf(out, "kern %u %u %d\n", k->left_glyph->index, k->right_glyph->index, k->distance);
}
fclose(out);