From 07dfe284d1cba355dcc808b9083f4ddd5e330816 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 2 Jun 2020 16:32:31 -0700 Subject: fix: added include file and fixed calls to free instead of interface --- include/libfont.h | 363 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sys/libfont/font.c | 257 ++++++++++++++++++------------------- 2 files changed, 494 insertions(+), 126 deletions(-) create mode 100644 include/libfont.h diff --git a/include/libfont.h b/include/libfont.h new file mode 100644 index 0000000..964c446 --- /dev/null +++ b/include/libfont.h @@ -0,0 +1,363 @@ +#pragma once + +typedef struct font·Info font·Info; +typedef struct font·TabElt font·TabElt; +typedef struct font·Vertex font·Vertex; +typedef struct font·Bitmap font·Bitmap; + +struct font·TabElt +{ + int glyph1; // use font·glyph_index + int glyph2; + int advance; +}; + +enum +{ + font·Vmove = 1, + font·Vline, + font·Vcurve, + font·Vcubic +}; + +struct font·Vertex +{ + short x, y; + short cx, cy; + short cx1, cy1; + uchar type, padding; +}; + +/* glyph shapes */ + +/* Query the font vertical metrics without having to create a font first */ +void font·scaledvmetrics(uchar *data, int index, float size, float *ascent, float *descent, float *lineGap); + +/* + * This function will determine the number of fonts in a font file. TrueType + * collection (.ttc) files may contain multiple fonts, while TrueType font + * (.ttf) files only contain one font. The number of fonts can be used for + * indexing with the previous function where the index is between zero and one + * less than the total fonts. If an error occurs, -1 is returned. + */ +int font·number(uchar *data); + +/* + * Each .ttf/.ttc file may have more than one font. Each font has a sequential + * index number starting from 0. Call this function to get the font offset for + * a given index; it returns -1 if the index is out of range. A regular .ttf + * file will only define one font and it always be at offset 0, so it will + * return '0' for index 0, and -1 for all other indices. + */ +int font·offsetfor(uchar *data, int index); + +/* + * Given an offset into the file that defines a font, this function builds + * the necessary cached info for the rest of the system. Returns nil on failure. + */ +font·Info *font·make(uchar *data, int offset, mem·Allocator, void *heap); +void font·free(font·Info *info); + + +/* character to glyph-index conversion */ + +/* + * If you're going to perform multiple operations on the same character + * and you want a speed-up, call this function with the character you're + * going to process, then use glyph-based functions instead of the + * codepoint-based functions. + * Returns 0 if the character codepoint is not defined in the font. + */ +int font·glyph_index(font·Info *info, int codepoint); + + +/* character properties */ + +/* + * computes a scale factor to produce a font whose "height" is 'pixels' tall. + * Height is measured as the distance from the highest ascender to the lowest + * descender; in other words, it's equivalent to calling font·GetFontVMetrics + * and computing: + * scale = pixels / (ascent - descent) + * so if you prefer to measure height by the ascent only, use a similar calculation. + */ +float font·scaleheightto(font·Info *info, float pixels); + +/* + * computes a scale factor to produce a font whose EM size is mapped to + * 'pixels' tall. This is probably what traditional APIs compute, but + * I'm not positive. + */ +float font·scaleheighttoem(font·Info *info, float pixels); + +/* + * ascent is the coordinate above the baseline the font extends; descent + * is the coordinate below the baseline the font extends (i.e. it is typically negative) + * linegap is the spacing between one row's descent and the next row's ascent... + * so you should advance the vertical position by "*ascent - *descent + *lineGap" + * these are expressed in unscaled coordinates, so you must multiply by + * the scale factor for a given size + */ +void font·vmetrics(font·Info *info, int *ascent, int *descent, int *linegap); + + +/* the bounding box around all possible characters */ +void font·bbox(font·Info *info, int *x0, int *y0, int *x1, int *y1); + +/* + * leftSideBearing is the offset from the current horizontal position to the left edge of the character + * advanceWidth is the offset from the current horizontal position to the next horizontal position + * these are expressed in unscaled coordinates + */ +void font·code_hmetrics(font·Info *info, int codepoint, int *advance, int *lsb); + +/* an additional amount to add to the 'advance' value between ch1 and ch2 */ +int font·code_kernadvance(font·Info *info, int ch1, int ch2); + +/* Gets the bounding box of the visible part of the glyph, in unscaled coordinates */ +int font·code_box(font·Info *info, int codepoint, int *x0, int *y0, int *x1, int *y1); + +/* as above, but takes one or more glyph indices for greater efficiency */ +void font·glyph_hmetrics(font·Info *info, int glyph_index, int *advance, int *lsb); +int font·glyph_kernadvance(font·Info *info, int glyph1, int glyph2); +int font·glyph_box(font·Info *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); + +/* + * Retrieves a complete list of all of the kerning pairs provided by the font + * font·kerntab never writes more than table_length entries and returns how many entries it did write. + * The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) + */ +int font·kerntablen(font·Info *info); +int font·kerntab(font·Info *info, font·TabElt *tab, int len); + +/* returns non-zero if nothing is drawn for this glyph */ +int font·glyph_empty(font·Info *info, int glyph_index); + +/* + * returns # of vertices and fills *vertices with the pointer to them + * these are expressed in "unscaled" coordinates + * + * the shape is a series of contours. Each one starts with + * a STBTT_moveto, then consists of a series of mixed + * STBTT_lineto and STBTT_curveto segments. A lineto + * draws a line from previous endpoint to its x,y; a curveto + * draws a quadratic bezier from previous endpoint to + * its x,y, using cx,cy as the bezier control point. + */ +int font·code_shape(font·Info *info, int unicode_codepoint, font·Vertex **vertices); +int font·glyph_shape(font·Info *info, int glyph_index, font·Vertex **vertices); + +/* frees the data allocated above */ +void font·freeshape(font·Info *info, font·Vertex *verts); + +/* + * fills svg with the character's SVG data. + * returns data size or 0 if SVG not found. + */ +int font·code_svg(font·Info *info, int unicode_codepoint, char **svg); +int font·glyph_svg(font·Info *info, int gl, char **svg); + +/* bitmap rendering */ + +/* frees the bitmap allocated below */ +void font·freebitmap(uchar *bitmap, void *userdata); + +/* + * allocates a large-enough single-channel 8bpp bitmap and renders the + * specified character/glyph at the specified scale into it, with + * antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). + * *width & *height are filled out with the width & height of the bitmap, + * which is stored left-to-right, top-to-bottom. + + * xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap + */ +uchar *font·code_makebitmap(font·Info *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); + +/* + * the same as font·GetCodepoitnBitmap, but you can specify a subpixel + * shift for the character + */ +uchar *font·code_makebitmap_subpixel(font·Info *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); + +/* + * the same as font·codepointbitmap, but you pass in storage for the bitmap + * in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap + * is clipped to out_w/out_h bytes. Call font·codepointbitmapbox to get the + * width and height and positioning info for it first. + */ +void font·code_fillbitmap(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); + +/* + * same as font·MakeCodepointBitmap, but you can specify a subpixel + * shift for the character + */ +void font·code_fillbitmap_subpixel(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); + +/* + * same as font·MakeCodepointBitmapSubpixel, but prefiltering + * is performed (see font·PackSetOversampling) + */ +void font·code_fillbitmap_subpixel_prefilter(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); + +/* + * get the bbox of the bitmap centered around the glyph origin; so the + * bitmap width is ix1-ix0, height is iy1-iy0, and location to place + * the bitmap top left is (leftSideBearing*scale,iy0). + * (Note that the bitmap uses y-increases-down, but the shape uses + * y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) + */ +void font·code_bitmapbox(font·Info *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); + +/* + * same as font·GetCodepointBitmapBox, but you can specify a subpixel + * shift for the character + */ +void font·code_bitmapbox_subpixel(font·Info *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + +/* + * the following functions are equivalent to the above functions, but operate + * on glyph indices instead of Unicode codepoints (for efficiency) + */ +uchar *font·glyph_makebitmap(font·Info *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); +uchar *font·glyph_makebitmap_subpixel(font·Info *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); +void font·glyph_fillbitmap(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); +void font·glyph_fillbitmap_subpixel(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +void font·glyph_fillbitmap_subpixel_prefilter(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); +void font·glyph_bitmapbox(font·Info *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); +void font·glyph_bitmapbox_subpixel(font·Info *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); + +/* signed distance function (or field) rendering */ + +/* frees the SDF bitmap allocated below */ +void font·freesdf(font·Info *info, uchar *bitmap); + +/* + * These functions compute a discretized SDF field for a single character, suitable for storing + * in a single-channel texture, sampling with bilinear filtering, and testing against + * larger than some threshold to produce scalable fonts. + * info -- the font + * scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap + * glyph/codepoint -- the character to generate the SDF for + * padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), + * which allows effects like bit outlines + * onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) + * pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) + * if positive, > onedge_value is inside; if negative, < onedge_value is inside + * width,height -- output height & width of the SDF bitmap (including padding) + * xoff,yoff -- output origin of the character + * return value -- a 2D array of bytes 0..255, width*height in size + * + * pixel_dist_scale & onedge_value are a scale & bias that allows you to make + * optimal use of the limited 0..255 for your application, trading off precision + * and special effects. SDF values outside the range 0..255 are clamped to 0..255. + * + * Example: + * scale = font·ScaleForPixelHeight(22) + * padding = 5 + * onedge_value = 180 + * pixel_dist_scale = 180/5.0 = 36.0 + * + * This will create an SDF bitmap in which the character is about 22 pixels + * high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled + * shape, sample the SDF at each pixel and fill the pixel if the SDF value + * is greater than or equal to 180/255. (You'll actually want to antialias, + * which is beyond the scope of this example.) Additionally, you can compute + * offset outlines (e.g. to stroke the character border inside & outside, + * or only outside). For example, to fill outside the character up to 3 SDF + * pixels, you would compare against (180-36.0*3)/255 = 72/255. The above + * choice of variables maps a range from 5 pixels outside the shape to + * 2 pixels inside the shape to 0..255; this is intended primarily for apply + * outside effects only (the interior range is needed to allow proper + * antialiasing of the font at *smaller* sizes) + * + * The function computes the SDF analytically at each SDF pixel, not by e.g. + * building a higher-res bitmap and approximating it. In theory the quality + * should be as high as possible for an SDF of this size & representation, but + * unclear if this is true in practice (perhaps building a higher-res bitmap + * and computing from that can allow drop-out prevention). + + * The algorithm has not been optimized at all, so expect it to be slow + * if computing lots of characters or very large sizes. + */ + + +uchar *font·glyph_sdf(font·Info *info, float scale, int glyph, int padding, uchar onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +uchar *font·code_sdf(font·Info *info, float scale, int codepoint, int padding, uchar onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); + + +/* + * Finding the right font... + * + * You should really just solve this offline, keep your own tables + * of what font is what, and don't try to get it out of the .ttf file. + * That's because getting it out of the .ttf file is really hard, because + * the names in the file can appear in many possible encodings, in many + * possible languages, and e.g. if you need a case-insensitive comparison, + * the details of that depend on the encoding & language in a complex way + * (actually underspecified in truetype, but also gigantic). + * + * But you can use the provided functions in two possible ways: + * font·findmatchingfont() will use *case-sensitive* comparisons on + * unicode-encoded names to try to find the font you want; + * you can run this before calling font·init() + * + * font·getfontnamestring() lets you get any of the various strings + * from the file yourself and do your own comparisons on them. + * You have to have called font·init() first. + */ + + +/* + * returns the offset (not index) of the font that matches, or -1 if none + * if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". + * if you use any other flag, use a font name like "Arial"; this checks + * the 'macStyle' header field; i don't know if fonts set this consistently + */ +int font·findmatch(uchar *fontdata, char *name, int flags); +#define FONT_MACSTYLE_DONTCARE 0 +#define FONT_MACSTYLE_BOLD 1 +#define FONT_MACSTYLE_ITALIC 2 +#define FONT_MACSTYLE_UNDERSCORE 4 +#define FONT_MACSTYLE_NONE 8 // <= not same as 0, this makes us check the bitfield is 0 + +/* + * returns the string (which may be big-endian double byte, e.g. for unicode) + * and puts the length in bytes in *length. + * + * some of the values for the IDs are below; for more see the truetype spec: + * http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html + * http://www.microsoft.com/typography/otspec/name.htm + */ + +char *font·name(font·Info *font, int *length, int platformID, int encodingID, int languageID, int nameID); + +enum { // platformID + font·platform_unicode = 0, + font·platform_mac = 1, + font·platform_iso = 2, +}; + +enum { // encodingID for STBTT_PLATFORM_ID_UNICODE + font·unicode_eid_unicode_1_0 = 0, + font·unicode_eid_unicode_1_1 = 1, + font·unicode_eid_iso_10646 = 2, + font·unicode_eid_unicode_2_0_bmp = 3, + font·unicode_eid_unicode_2_0_full = 4 +}; + +enum { // encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes + font·mac_eid_roman =0, font·mac_eid_arabic =4, + font·mac_eid_japanese =1, font·mac_eid_hebrew =5, + font·mac_eid_chinese_trad =2, font·mac_eid_greek =6, + font·mac_eid_korean =3, font·mac_eid_russian =7 +}; + +enum { // languageID for STBTT_PLATFORM_ID_MAC + font·mac_lang_english =0 , font·stbtt_mac_lang_japanese =11, + font·mac_lang_arabic =12, font·stbtt_mac_lang_korean =23, + font·mac_lang_dutch =4 , font·stbtt_mac_lang_russian =32, + font·mac_lang_french =1 , font·stbtt_mac_lang_spanish =6 , + font·mac_lang_german =2 , font·stbtt_mac_lang_swedish =5 , + font·mac_lang_hebrew =10, font·stbtt_mac_lang_chinese_simplified =33, + font·mac_lang_italian =3 , font·stbtt_mac_lang_chinese_trad =19 +}; diff --git a/sys/libfont/font.c b/sys/libfont/font.c index 734ca25..efd3e21 100644 --- a/sys/libfont/font.c +++ b/sys/libfont/font.c @@ -391,7 +391,7 @@ int init(font·Info *info, uchar *data, int offset) { uint32 cmap, t; - int32 i,numTables; + int32 i, ntab; info->data = data; info->fontstart = offset; @@ -477,9 +477,9 @@ init(font·Info *info, uchar *data, int offset) // find a cmap encoding table we understand *now* to avoid searching // later. (todo: could make this installable) // the same regardless of glyph. - numTables = ttushort(data + cmap + 2); + ntab = ttushort(data + cmap + 2); info->index_map = 0; - for (i=0; i < numTables; ++i) { + for (i=0; i < ntab; ++i) { uint32 encoding_record = cmap + 4 + 8 * i; // find an encoding we understand: switch(ttushort(data+encoding_record)) { @@ -659,9 +659,9 @@ font·glyph_index(font·Info *info, int unicode_codepoint) } int -font·code_shape(font·Info *info, int unicode_codepoint, font·Vertex **vertices) +font·code_shape(font·Info *info, int unicode_codepoint, font·Vertex **verts) { - return font·glyph_shape(info, font·glyph_index(info, unicode_codepoint), vertices); + return font·glyph_shape(info, font·glyph_index(info, unicode_codepoint), verts); } static @@ -737,36 +737,37 @@ font·glyph_empty(font·Info *info, int glyph_index) static int -close_shape(font·Vertex *vertices, int num_vertices, int was_off, int start_off, +close_shape(font·Vertex *verts, int num_verts, int was_off, int start_off, int32 sx, int32 sy, int32 scx, int32 scy, int32 cx, int32 cy) { if (start_off) { if (was_off) - setvertex(&vertices[num_vertices++], font·Vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - setvertex(&vertices[num_vertices++], font·Vcurve, sx,sy,scx,scy); + setvertex(&verts[num_verts++], font·Vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); + setvertex(&verts[num_verts++], font·Vcurve, sx,sy,scx,scy); } else { if (was_off) - setvertex(&vertices[num_vertices++], font·Vcurve,sx,sy,cx,cy); + setvertex(&verts[num_verts++], font·Vcurve,sx,sy,cx,cy); else - setvertex(&vertices[num_vertices++], font·Vline,sx,sy,0,0); + setvertex(&verts[num_verts++], font·Vline,sx,sy,0,0); } - return num_vertices; + return num_verts; } static int -glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) +glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pverts) { short numberOfContours; uchar *endPtsOfContours; uchar *data = info->data; - font·Vertex *vertices=0; - int num_vertices=0; + font·Vertex *verts = nil; + int num_verts = 0; int g = glyph_offset(info, glyph_index); - *pvertices = nil; + *pverts = nil; - if (g < 0) return 0; + if (g < 0) + return 0; numberOfContours = ttshort(data + g); @@ -781,13 +782,13 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) n = 1+ttushort(endPtsOfContours + numberOfContours*2-2); - m = n + 2*numberOfContours; // a loose bound on how many vertices we might need - vertices = info->alloc(info->heap, m, sizeof(vertices[0])); - if (vertices == 0) + m = n + 2*numberOfContours; // a loose bound on how many verts we might need + verts = info->alloc(info->heap, m, sizeof(verts[0])); + if (verts == 0) return 0; next_move = 0; - flagcount=0; + flagcount = 0; // in first pass, we load uninterpreted data into the allocated array // above, shifted to the end of the array so we won't overwrite it when @@ -804,13 +805,13 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) flagcount = *points++; } else --flagcount; - vertices[off+i].type = flags; + verts[off+i].type = flags; } // now load x coordinates x=0; for (i=0; i < n; ++i) { - flags = vertices[off+i].type; + flags = verts[off+i].type; if (flags & 2) { short dx = *points++; x += (flags & 16) ? dx : -dx; // ??? @@ -820,13 +821,13 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) points += 2; } } - vertices[off+i].x = (short) x; + verts[off+i].x = (short) x; } // now load y coordinates y=0; for (i=0; i < n; ++i) { - flags = vertices[off+i].type; + flags = verts[off+i].type; if (flags & 4) { short dy = *points++; y += (flags & 32) ? dy : -dy; // ??? @@ -836,20 +837,20 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) points += 2; } } - vertices[off+i].y = (short) y; + verts[off+i].y = (short) y; } // now convert them to our format - num_vertices=0; + num_verts=0; sx = sy = cx = cy = scx = scy = 0; for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - x = (short) vertices[off+i].x; - y = (short) vertices[off+i].y; + flags = verts[off+i].type; + x = (short) verts[off+i].x; + y = (short) verts[off+i].y; if (next_move == i) { if (i != 0) - num_vertices = close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + num_verts = close_shape(verts, num_verts, was_off, start_off, sx,sy,scx,scy,cx,cy); // now start the new one start_off = !(flags & 1); @@ -858,47 +859,47 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) // where we can start, and we need to save some state for when we wraparound. scx = x; scy = y; - if (!(vertices[off+i+1].type & 1)) { + if (!(verts[off+i+1].type & 1)) { // next point is also a curve point, so interpolate an on-point curve - sx = (x + (int32) vertices[off+i+1].x) >> 1; - sy = (y + (int32) vertices[off+i+1].y) >> 1; + sx = (x + (int32) verts[off+i+1].x) >> 1; + sy = (y + (int32) verts[off+i+1].y) >> 1; } else { // otherwise just use the next point as our start point - sx = (int32) vertices[off+i+1].x; - sy = (int32) vertices[off+i+1].y; + sx = (int32) verts[off+i+1].x; + sy = (int32) verts[off+i+1].y; ++i; // we're using point i+1 as the starting point, so skip it } } else { sx = x; sy = y; } - setvertex(&vertices[num_vertices++], font·Vmove,sx,sy,0,0); + setvertex(&verts[num_verts++], font·Vmove,sx,sy,0,0); was_off = 0; next_move = 1 + ttushort(endPtsOfContours+j*2); ++j; } else { if (!(flags & 1)) { // if it's a curve if (was_off) // two off-curve control points in a row means interpolate an on-curve midpoint - setvertex(&vertices[num_vertices++], font·Vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); + setvertex(&verts[num_verts++], font·Vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); cx = x; cy = y; was_off = 1; } else { if (was_off) - setvertex(&vertices[num_vertices++], font·Vcurve, x,y, cx, cy); + setvertex(&verts[num_verts++], font·Vcurve, x,y, cx, cy); else - setvertex(&vertices[num_vertices++], font·Vline, x,y,0,0); + setvertex(&verts[num_verts++], font·Vline, x,y,0,0); was_off = 0; } } } - num_vertices = close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); + num_verts = close_shape(verts, num_verts, was_off, start_off, sx,sy,scx,scy,cx,cy); } else if (numberOfContours < 0) { // Compound shapes. int more = 1; uchar *comp = data + g + 10; - num_vertices = 0; - vertices = 0; + num_verts = 0; + verts = 0; while (more) { ushort flags, gidx; int comp_num_verts = 0, i; @@ -942,7 +943,7 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) // Get indexed glyph. comp_num_verts = font·glyph_shape(info, gidx, &comp_verts); if (comp_num_verts > 0) { - // Transform vertices. + // Transform verts. for (i = 0; i < comp_num_verts; ++i) { font·Vertex* v = &comp_verts[i]; short x,y; @@ -953,24 +954,24 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); } - // Append vertices. - tmp = info->alloc(info->heap, num_vertices+comp_num_verts, sizeof(font·Vertex)); + // Append verts. + tmp = info->alloc(info->heap, num_verts+comp_num_verts, sizeof(font·Vertex)); if (!tmp) { - if (vertices) free(vertices); - if (comp_verts) free(comp_verts); + if (verts) info->free(info->heap, verts); + if (comp_verts) info->free(info->heap, comp_verts); return 0; } - if (num_vertices > 0) - memcpy(tmp, vertices, num_vertices*sizeof(font·Vertex)); + if (num_verts > 0) + memcpy(tmp, verts, num_verts*sizeof(font·Vertex)); - memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(font·Vertex)); + memcpy(tmp+num_verts, comp_verts, comp_num_verts*sizeof(font·Vertex)); - if (vertices) - free(vertices); + if (verts) + info->free(info->heap, verts); - vertices = tmp; - free(comp_verts); - num_vertices += comp_num_verts; + verts = tmp; + info->free(info->heap, comp_verts); + num_verts += comp_num_verts; } // More components ? more = flags & (1<<5); @@ -979,8 +980,8 @@ glyph_shape_tt(font·Info *info, int glyph_index, font·Vertex **pvertices) // numberOfCounters == 0, do nothing } - *pvertices = vertices; - return num_vertices; + *pverts = verts; + return num_verts; } typedef struct @@ -991,8 +992,8 @@ typedef struct float x, y; int32 min_x, max_x, min_y, max_y; - font·Vertex *pvertices; - int num_vertices; + font·Vertex *pverts; + int num_verts; } csctx; #define CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, nil, 0} @@ -1015,11 +1016,11 @@ static void csctx_v(csctx *c, uchar type, int32 x, int32 y, int32 cx, int32 cy, track_vertex(c, cx1, cy1); } } else { - setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); - c->pvertices[c->num_vertices].cx1 = (short) cx1; - c->pvertices[c->num_vertices].cy1 = (short) cy1; + setvertex(&c->pverts[c->num_verts], type, x, y, cx, cy); + c->pverts[c->num_verts].cx1 = (short) cx1; + c->pverts[c->num_verts].cy1 = (short) cy1; } - c->num_vertices++; + c->num_verts++; } static void csctx_close_shape(csctx *ctx) @@ -1357,56 +1358,60 @@ run_charstring(font·Info *info, int glyph_index, csctx *c) #undef STBTT__CSERR } -static int glyph_shape_t2(font·Info *info, int glyph_index, font·Vertex **pvertices) +static int glyph_shape_t2(font·Info *info, int glyph_index, font·Vertex **pverts) { - // runs the charstring twice, once to count and once to output (to avoid realloc) - csctx count_ctx = CSCTX_INIT(1); - csctx output_ctx = CSCTX_INIT(0); - if (run_charstring(info, glyph_index, &count_ctx)) { - *pvertices = info->alloc(info->heap, count_ctx.num_vertices, sizeof(font·Vertex)); - output_ctx.pvertices = *pvertices; - if (run_charstring(info, glyph_index, &output_ctx)) { - assert(output_ctx.num_vertices == count_ctx.num_vertices); - return output_ctx.num_vertices; - } - } - *pvertices = nil; - return 0; + // runs the charstring twice, once to count and once to output (to avoid realloc) + csctx count_ctx = CSCTX_INIT(1); + csctx output_ctx = CSCTX_INIT(0); + if (run_charstring(info, glyph_index, &count_ctx)) { + *pverts = info->alloc(info->heap, count_ctx.num_verts, sizeof(font·Vertex)); + output_ctx.pverts = *pverts; + if (run_charstring(info, glyph_index, &output_ctx)) { + assert(output_ctx.num_verts == count_ctx.num_verts); + return output_ctx.num_verts; + } + } + *pverts = nil; + return 0; } static int glyph_info_t2(font·Info *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) { - csctx c = CSCTX_INIT(1); - int r = run_charstring(info, glyph_index, &c); - if (x0) *x0 = r ? c.min_x : 0; - if (y0) *y0 = r ? c.min_y : 0; - if (x1) *x1 = r ? c.max_x : 0; - if (y1) *y1 = r ? c.max_y : 0; - return r ? c.num_vertices : 0; + + csctx c = CSCTX_INIT(1); + int r = run_charstring(info, glyph_index, &c); + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; + + return r ? c.num_verts : 0; } int -font·glyph_shape(font·Info *info, int glyph_index, font·Vertex **pvertices) +font·glyph_shape(font·Info *info, int glyph_index, font·Vertex **pverts) { - if (!info->cff.size) - return glyph_shape_tt(info, glyph_index, pvertices); - else - return glyph_shape_t2(info, glyph_index, pvertices); + if (!info->cff.size) + return glyph_shape_tt(info, glyph_index, pverts); + else + return glyph_shape_t2(info, glyph_index, pverts); } void -font·glyph_hmetrics(font·Info *info, int glyph_index, int *advanceWidth, int *leftSideBearing) +font·glyph_hmetrics(font·Info *info, int glyph_index, int *adv, int *lsb) { - ushort numOfLongHorMetrics = ttushort(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) *advanceWidth = ttshort(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) *leftSideBearing = ttshort(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) *advanceWidth = ttshort(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) *leftSideBearing = ttshort(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } + ushort n; + + n = ttushort(info->data+info->hhea + 34); + if (glyph_index < n) { + if (adv) *adv = ttshort(info->data + info->hmtx + 4*glyph_index); + if (lsb) *lsb = ttshort(info->data + info->hmtx + 4*glyph_index + 2); + } else { + if (adv) *adv = ttshort(info->data + info->hmtx + 4*(n-1)); + if (lsb) *lsb = ttshort(info->data + info->hmtx + 4*n + 2*(glyph_index - n)); + } } int @@ -1783,7 +1788,7 @@ font·scaleheighttoem(font·Info *info, float pixels) void font·freeshape(font·Info *info, font·Vertex *v) { - free(v); + info->free(info->heap, v); } static @@ -2480,7 +2485,7 @@ tesselate_cubic(Point *points, int *num_points, float x0, float y0, float x1, fl // returns number of contours static Point * -flatten(font·Vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, mem·Allocator mem, void *heap) +flatten(font·Vertex *verts, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, mem·Allocator mem, void *heap) { Point *points=0; int num_points=0; @@ -2490,7 +2495,7 @@ flatten(font·Vertex *vertices, int num_verts, float objspace_flatness, int **co // count how many "moves" there are to get the contour count for (i=0; i < num_verts; ++i) - if (vertices[i].type == font·Vmove) + if (verts[i].type == font·Vmove) ++n; *num_contours = n; @@ -2515,7 +2520,7 @@ flatten(font·Vertex *vertices, int num_verts, float objspace_flatness, int **co num_points = 0; n= -1; for (i=0; i < num_verts; ++i) { - switch (vertices[i].type) { + switch (verts[i].type) { case font·Vmove: // start the next contour if (n >= 0) @@ -2523,27 +2528,27 @@ flatten(font·Vertex *vertices, int num_verts, float objspace_flatness, int **co ++n; start = num_points; - x = vertices[i].x, y = vertices[i].y; + x = verts[i].x, y = verts[i].y; add_point(points, num_points++, x,y); break; case font·Vline: - x = vertices[i].x, y = vertices[i].y; + x = verts[i].x, y = verts[i].y; add_point(points, num_points++, x, y); break; case font·Vcurve: tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, + verts[i].cx, verts[i].cy, + verts[i].x, verts[i].y, objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; + x = verts[i].x, y = verts[i].y; break; case font·Vcubic: tesselate_cubic(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].cx1, vertices[i].cy1, - vertices[i].x, vertices[i].y, + verts[i].cx, verts[i].cy, + verts[i].cx1, verts[i].cy1, + verts[i].x, verts[i].y, objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; + x = verts[i].x, y = verts[i].y; break; } } @@ -2561,12 +2566,12 @@ error: static void -rasterize(font·Bitmap *result, float flatness_in_pixels, font·Vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, mem·Allocator mal, void *heap) +rasterize(font·Bitmap *result, float flatness_in_pixels, font·Vertex *verts, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, mem·Allocator mal, void *heap) { float scale = (scale_x > scale_y) ? scale_y : scale_x; int winding_count = 0; int *winding_lengths = nil; - Point *windings = flatten(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, mal, heap); + Point *windings = flatten(verts, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, mal, heap); if (windings) { rasterize_points(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, mal, heap); free(winding_lengths); @@ -2585,13 +2590,13 @@ font·glyph_makebitmap_subpixel(font·Info *info, float scale_x, float scale_y, { int ix0,iy0,ix1,iy1; font·Bitmap gbm; - font·Vertex *vertices; - int num_verts = font·glyph_shape(info, glyph, &vertices); + font·Vertex *verts; + int num_verts = font·glyph_shape(info, glyph, &verts); if (scale_x == 0) scale_x = scale_y; if (scale_y == 0) { if (scale_x == 0) { - free(vertices); + info->free(info->heap, verts); return nil; } scale_y = scale_x; @@ -2614,10 +2619,10 @@ font·glyph_makebitmap_subpixel(font·Info *info, float scale_x, float scale_y, if (gbm.pixels) { gbm.stride = gbm.w; - rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->mal, info->heap); + rasterize(&gbm, 0.35f, verts, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->mal, info->heap); } } - free(vertices); + info->free(info->heap, verts); return gbm.pixels; } @@ -2631,8 +2636,8 @@ void font·glyph_fillbitmap_subpixel(font·Info *info, uchar *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) { int ix0,iy0; - font·Vertex *vertices; - int num_verts = font·glyph_shape(info, glyph, &vertices); + font·Vertex *verts; + int num_verts = font·glyph_shape(info, glyph, &verts); font·Bitmap gbm; font·glyph_bitmapbox_subpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); @@ -2642,9 +2647,9 @@ font·glyph_fillbitmap_subpixel(font·Info *info, uchar *output, int out_w, int gbm.stride = out_stride; if (gbm.w && gbm.h) - rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->mal, info->heap); + rasterize(&gbm, 0.35f, verts, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->mal, info->heap); - free(vertices); + info->free(info->heap, verts); } void @@ -3230,8 +3235,8 @@ font·glyph_sdf(font·Info *info, float scale, int glyph, int padding, uchar one data[(y-iy0)*w+(x-ix0)] = (uchar) val; } } - free(precompute); - free(verts); + info->free(info->heap,precompute); + info->free(info->heap, verts); } return data; } @@ -3243,9 +3248,9 @@ font·code_sdf(font·Info *info, float scale, int codepoint, int padding, uchar } void -font·freesdf(uchar *bitmap, void *userdata) +font·freesdf(font·Info* info, uchar *bitmap) { - free(bitmap); + info->free(info->heap, bitmap); } char* -- cgit v1.2.1