aboutsummaryrefslogtreecommitdiff
path: root/include/libfont.h
blob: 860d8d4c875b783367c045e9c49d7c689f06b976 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
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(font·Info *info, uchar *bitmap);

/*
 * 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
};