From 6c8c1afdbad505c04a251da05499658b7cc65825 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 5 May 2018 22:27:22 +0300 Subject: [PATCH] Rework the definition file format Distance fields threw off the metrics because the field extends past the actual glyph area. The definitions are now split to abstract metrics and glyph images to allow acccurate metrics to be obtained. A mapping from code points to glyphs was also added to allow later support for glyphs without a dedicated code point such as ligatures. --- Readme | 48 +++++++++++++++++++++++++++++++++++------------- ttf2png.c | 36 +++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/Readme b/Readme index c4fc9d0..0268330 100644 --- a/Readme +++ b/Readme @@ -108,23 +108,24 @@ the image and the font: Field 3: nominal size of the font Fields 4-5: ascent and descent of the font -The keyword "glyph" is followed by eight fields describing a single glyph: +The keyword "code" is followed by two fields establishing a code point to +glyph mapping: - Field 1: the code point of the glyph - Fields 2-3: x and y position of the glyph in the image - Fields 4-5: width and height of the glyph - Fields 6-7: x and y offset of the glyph from its base point - Field 8: advance from this glyph to the next + Field 1: Unicode code point + Field 2: Glyph index -The keyword "kern" is followed by three fields describing kerning between two -glyphs: +The keyword "metrics" is followed by six fields describing the metrics of a +glyph: - Field 1: the code point of the left-hand glyph - Field 2: the code point of the right-hand glyph - Field 3: kerning distance between the glyphs + Field 1: the index of the glyph + Fields 2-3: width and height of the glyph + Fields 4-5: x and y offset of the glyph from its base point + Field 6: advance from this glyph to the next -The following ASCII art image illustrates most of these metrics. Note that in -some fonts, not all of the glyphs fit completely inside the character box. +The following ASCII art image illustrates the basic metrics. The character +box is a conceptual rectangle in which most of the glyphs in the font fit. +Some fonts may contain glyphs that extend outside of the nominal character +box. - - - - - - - - ^ | character box | | @@ -148,6 +149,27 @@ some fonts, not all of the glyphs fit completely inside the character box. |---------------> advance +The keyword "glyph" is followed by six field describing the area of the image +used for the glyph: + + Field 1: the index of the glyph + Fields 2-3: x and y position of the glyph in the image + Fields 4-5: width and height of the glyph + Field 6: border zone included in the image + +The border zone is used with distance field textures to allow the distance +field to extend past the actual glyph. If a glyph has a border, the origin +point in the metrics refers to the glyph's lower left corner. Subtract the +border width from both coordinates to obtain the correct rendering position +for the image. + +The keyword "kern" is followed by three fields describing kerning between two +glyphs: + + Field 1: the index of the left-hand glyph + Field 2: the index of the right-hand glyph + Field 3: kerning distance between the glyphs + Changelog diff --git a/ttf2png.c b/ttf2png.c index 93576c1..f8db322 100644 --- a/ttf2png.c +++ b/ttf2png.c @@ -29,6 +29,7 @@ typedef struct sImage { unsigned w, h; unsigned char *data; + unsigned border; } Image; typedef struct sGlyph @@ -44,8 +45,8 @@ typedef struct sGlyph typedef struct sKerning { - unsigned left_code; - unsigned right_code; + Glyph *left_glyph; + Glyph *right_glyph; int distance; } Kerning; @@ -494,6 +495,7 @@ int init_image(Image *image, size_t w, size_t h) image->w = w; image->h = h; image->data = NULL; + image->border = 0; if(!image->w || !image->h) return 0; @@ -560,8 +562,8 @@ int init_font(Font *font, FT_Face face, const Range *ranges, unsigned n_ranges, } 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; } } @@ -748,6 +750,7 @@ int create_distance_field(const FT_Bitmap *bmp, Image *image, unsigned scale, un if(copy_bitmap(bmp, &base_image)) return -1; + image->border = margin; for(y=0; yh; ++y) for(x=0; xw; ++x) { int bx = (x-margin)*scale+scale/2; @@ -1021,19 +1024,38 @@ int save_defs(const char *fn, const Font *font) 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; in_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; in_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; in_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; in_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); -- 2.43.0