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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 include/libfont.h (limited to 'include') 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 +}; -- cgit v1.2.1