aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-06-02 16:32:31 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-06-02 16:32:31 -0700
commit07dfe284d1cba355dcc808b9083f4ddd5e330816 (patch)
tree2ca978dcf3d4e4f1d524ac1a4c40c7a55d1c4042
parent69adb19d98114d7a35bf73389b9098de33adf42c (diff)
fix: added include file and fixed calls to free instead of interface
-rw-r--r--include/libfont.h363
-rw-r--r--sys/libfont/font.c257
2 files changed, 494 insertions, 126 deletions
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*