forked from harfbuzz/harfbuzz
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathusermanual-fonts-and-faces.xml
518 lines (511 loc) · 21.9 KB
/
usermanual-fonts-and-faces.xml
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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
<?xml version="1.0"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
<!ENTITY version SYSTEM "version.xml">
]>
<chapter id="fonts-and-faces">
<title>Fonts, faces, and output</title>
<para>
In the previous chapter, we saw how to set up a buffer and fill
it with text as Unicode code points. In order to shape this
buffer text with HarfBuzz, you will need also need a font
object.
</para>
<para>
HarfBuzz provides abstractions to help you cache and reuse the
heavier parts of working with binary fonts, so we will look at
how to do that. We will also look at how to work with the
FreeType font-rendering library and at how you can customize
HarfBuzz to work with other libraries.
</para>
<para>
Finally, we will look at how to work with OpenType variable
fonts, the latest update to the OpenType font format, and at
some other recent additions to OpenType.
</para>
<section id="fonts-and-faces-objects">
<title>Font and face objects</title>
<para>
The outcome of shaping a run of text depends on the contents of
a specific font file (such as the substitutions and positioning
moves in the 'GSUB' and 'GPOS' tables), so HarfBuzz makes
accessing those internals fast.
</para>
<para>
An <type>hb_face_t</type> represents a <emphasis>face</emphasis>
in HarfBuzz. This data type is a wrapper around an
<type>hb_blob_t</type> blob that holds the contents of a binary
font file. Since HarfBuzz supports TrueType Collections and
OpenType Collections (each of which can include multiple
typefaces), a HarfBuzz face also requires an index number
specifying which typeface in the file you want to use. Most of
the font files you will encounter in the wild include just a
single face, however, so most of the time you would pass in
<literal>0</literal> as the index when you create a face:
</para>
<programlisting language="C">
hb_blob_t* blob = hb_blob_create_from_file(file);
...
hb_face_t* face = hb_face_create(blob, 0);
</programlisting>
<para>
On its own, a face object is not quite ready to use for
shaping. The typeface must be set to a specific point size in
order for some details (such as hinting) to work. In addition,
if the font file in question is an OpenType Variable Font, then
you may need to specify one or more variation-axis settings (or a
named instance) in order to get the output you need.
</para>
<para>
In HarfBuzz, you do this by creating a <emphasis>font</emphasis>
object from your face.
</para>
<para>
Font objects also have the advantage of being considerably
lighter-weight than face objects (remember that a face contains
the contents of a binary font file mapped into memory). As a
result, you can cache and reuse a font object, but you could
also create a new one for each additional size you needed.
Creating new fonts incurs some additional overhead, of course,
but whether or not it is excessive is your call in the end. In
contrast, face objects are substantially larger, and you really
should cache them and reuse them whenever possible.
</para>
<para>
You can create a font object from a face object:
</para>
<programlisting language="C">
hb_font_t* hb_font = hb_font_create(hb_face);
</programlisting>
<para>
After creating a font, there are a few properties you should
set. Many fonts enable and disable hints based on the size it
is used at, so setting this is important for font
objects. <function>hb_font_set_ppem(font, x_ppem,
y_ppem)</function> sets the pixels-per-EM value of the font. You
can also set the point size of the font with
<function>hb_font_set_ptem(font, ptem)</function>. HarfBuzz uses the
industry standard 72 points per inch.
</para>
<para>
HarfBuzz lets you specify the degree subpixel precision you want
through a scaling factor. You can set horizontal and
vertical scaling factors on the
font by calling <function>hb_font_set_scale(font, x_scale,
y_scale)</function>.
</para>
<para>
There may be times when you are handed a font object and need to
access the face object that it comes from. For that, you can call
</para>
<programlisting language="C">
hb_face = hb_font_get_face(hb_font);
</programlisting>
<para>
You can also create a font object from an existing font object
using the <function>hb_font_create_sub_font()</function>
function. This creates a child font object that is initiated
with the same attributes as its parent; it can be used to
quickly set up a new font for the purpose of overriding a specific
font-functions method.
</para>
<para>
All face objects and font objects are lifecycle-managed by
HarfBuzz. After creating a face, you increase its reference
count with <function>hb_face_reference(face)</function> and
decrease it with
<function>hb_face_destroy(face)</function>. Likewise, you
increase the reference count on a font with
<function>hb_font_reference(font)</function> and decrease it
with <function>hb_font_destroy(font)</function>.
</para>
<para>
You can also attach user data to face objects and font objects.
</para>
</section>
<section id="fonts-and-faces-custom-functions">
<title>Customizing font functions</title>
<para>
During shaping, HarfBuzz frequently needs to query font objects
to get at the contents and parameters of the glyphs in a font
file. It includes a built-in set of functions that is tailored
to working with OpenType fonts. However, as was the case with
Unicode functions in the buffers chapter, HarfBuzz also wants to
make it easy for you to assign a substitute set of font
functions if you are developing a program to work with a library
or platform that provides its own font functions.
</para>
<para>
Therefore, the HarfBuzz API defines a set of virtual
methods for accessing font-object properties, and you can
replace the defaults with your own selections without
interfering with the shaping process. Each font object in
HarfBuzz includes a structure called
<literal>font_funcs</literal> that serves as a vtable for the
font object. The virtual methods in
<literal>font_funcs</literal> are:
</para>
<itemizedlist>
<listitem>
<para>
<function>hb_font_get_font_h_extents_func_t</function>: returns
the extents of the font for horizontal text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_font_v_extents_func_t</function>: returns
the extents of the font for vertical text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_nominal_glyph_func_t</function>: returns
the font's nominal glyph for a given code point.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_variation_glyph_func_t</function>: returns
the font's glyph for a given code point when it is followed by a
given Variation Selector.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_nominal_glyphs_func_t</function>: returns
the font's nominal glyphs for a series of code points.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_advance_func_t</function>: returns
the advance for a glyph.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_h_advance_func_t</function>: returns
the advance for a glyph for horizontal text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_v_advance_func_t</function>:returns
the advance for a glyph for vertical text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_advances_func_t</function>: returns
the advances for a series of glyphs.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_h_advances_func_t</function>: returns
the advances for a series of glyphs for horizontal text .
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_v_advances_func_t</function>: returns
the advances for a series of glyphs for vertical text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_origin_func_t</function>: returns
the origin coordinates of a glyph.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_h_origin_func_t</function>: returns
the origin coordinates of a glyph for horizontal text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_v_origin_func_t</function>: returns
the origin coordinates of a glyph for vertical text.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_extents_func_t</function>: returns
the extents for a glyph.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_contour_point_func_t</function>:
returns the coordinates of a specific contour point from a glyph.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_name_func_t</function>: returns the
name of a glyph (from its glyph index).
</para>
</listitem>
<listitem>
<para>
<function>hb_font_get_glyph_from_name_func_t</function>: returns
the glyph index that corresponds to a given glyph name.
</para>
</listitem>
<listitem>
<para>
<function>hb_font_draw_glyph_func_t</function>: gets the outlines
of a glyph (by calling #hb_draw_funcs_t callbacks).
</para>
</listitem>
<listitem>
<para>
<function>hb_font_paint_glyph_func_t</function>: paints a glyph
(by calling #hb_paint_funcs_t callbacks).
</para>
</listitem>
</itemizedlist>
<para>
You can create new font-functions by calling
<function>hb_font_funcs_create()</function>:
</para>
<programlisting language="C">
hb_font_funcs_t *ffunctions = hb_font_funcs_create ();
hb_font_set_funcs (font, ffunctions, font_data, destroy);
</programlisting>
<para>
The individual methods can each be set with their own setter
function, such as
<function>hb_font_funcs_set_nominal_glyph_func(ffunctions,
func, user_data, destroy)</function>.
</para>
<para>
Font-functions structures can be reused for multiple font
objects, and can be reference counted with
<function>hb_font_funcs_reference()</function> and
<function>hb_font_funcs_destroy()</function>. Just like other
objects in HarfBuzz, you can set user-data for each
font-functions structure and assign a destroy callback for
it.
</para>
<para>
You can also mark a font-functions structure as immutable,
with <function>hb_font_funcs_make_immutable()</function>. This
is especially useful if your code is a library or framework that
will have its own client programs. By marking your
font-functions structures as immutable, you prevent your client
programs from changing the configuration and introducing
inconsistencies and errors downstream.
</para>
<para>
To override only some functions while using the default implementation
for the others, you will need to create a sub-font. By default, the
sub-font uses the font functions of its parent except for the functions
that were explicitly set. The following code will override only the
<function>hb_font_get_nominal_glyph_func_t</function> for the sub-font:
</para>
<programlisting language="C">
hb_font_t *subfont = hb_font_create_sub_font (font)
hb_font_funcs_t *ffunctions = hb_font_funcs_create ();
hb_font_funcs_set_nominal_glyph_func (ffunctions, func, user_data, destroy);
hb_font_set_funcs (subfont, ffunctions, font_data, destroy);
hb_font_funcs_destroy (ffunctions);
</programlisting>
</section>
<section id="fonts-and-faces-native-opentype">
<title>Font objects and HarfBuzz's native OpenType implementation</title>
<para>
By default, whenever HarfBuzz creates a font object, it will
configure the font to use a built-in set of font functions that
supports contemporary OpenType font internals. If you want to
work with OpenType or TrueType fonts, you should be able to use
these functions without difficulty.
</para>
<para>
Many of the methods in the font-functions structure deal with
the fundamental properties of glyphs that are required for
shaping text: extents (the maximums and minimums on each axis),
origins (the <literal>(0,0)</literal> coordinate point which
glyphs are drawn in reference to), and advances (the amount that
the cursor needs to be moved after drawing each glyph, including
any empty space for the glyph's side bearings).
</para>
<para>
As you can see in the list of functions, there are separate "horizontal"
and "vertical" variants depending on whether the text is set in
the horizontal or vertical direction. For some scripts, fonts
that are designed to support text set horizontally or vertically (for
example, in Japanese) may include metrics for both text
directions. When fonts don't include this information, HarfBuzz
does its best to transform what the font provides.
</para>
<para>
In addition to the direction-specific functions, HarfBuzz
provides some higher-level functions for fetching information
like extents and advances for a glyph. If you call
</para>
<programlisting language="C">
hb_font_get_glyph_advance_for_direction(font, direction, extents);
</programlisting>
<para>
then you can provide any <type>hb_direction_t</type> as the
<parameter>direction</parameter> parameter, and HarfBuzz will
use the correct function variant for the text direction. There
are similar higher-level versions of the functions for fetching
extents, origin coordinates, and contour-point
coordinates. There are also addition and subtraction functions
for moving points with respect to the origin.
</para>
<para>
There are also methods for fetching the glyph ID that
corresponds to a Unicode code point (possibly when followed by a
variation-selector code point), fetching the glyph name from the
font, and fetching the glyph ID that corresponds to a glyph name
you already have.
</para>
<para>
HarfBuzz also provides functions for converting between glyph
names and string
variables. <function>hb_font_glyph_to_string(font, glyph, s,
size)</function> retrieves the name for the glyph ID
<parameter>glyph</parameter> from the font object. It generates a
generic name of the form <literal>gidDDD</literal> (where DDD is
the glyph index) if there is no name for the glyph in the
font. The <function>hb_font_glyph_from_string(font, s, len,
glyph)</function> takes an input string <parameter>s</parameter>
and looks for a glyph with that name in the font, returning its
glyph ID in the <parameter>glyph</parameter>
output parameter. It automatically parses
<literal>gidDDD</literal> and <literal>uniUUUU</literal> strings.
</para>
</section>
<section id="fonts-and-faces-variable">
<title>Working with OpenType Variable Fonts</title>
<para>
If you are working with OpenType Variable Fonts, there are a few
additional functions you should use to specify the
variation-axis settings of your font object. Without doing so,
your variable font's font object can still be used, but only at
the default setting for every axis (which, of course, is
sometimes what you want, but does not cover general usage).
</para>
<para>
HarfBuzz manages variation settings in the
<type>hb_variation_t</type> data type, which holds a <property>tag</property> for the
variation-axis identifier tag and a <property>value</property> for its
setting. You can retrieve the list of variation axes in a font
binary from the face object (not from a font object, notably) by
calling <function>hb_ot_var_get_axis_count(face)</function> to
find the number of axes, then using
<function>hb_ot_var_get_axis_infos()</function> to collect the
axis structures:
</para>
<programlisting language="C">
axes = hb_ot_var_get_axis_count(face);
...
hb_ot_var_get_axis_infos(face, 0, axes, axes_array);
</programlisting>
<para>
For each axis returned in the array, you can can access the
identifier in its <property>tag</property>. HarfBuzz also has
tag definitions predefined for the five standard axes specified
in OpenType (<literal>ital</literal> for italic,
<literal>opsz</literal> for optical size,
<literal>slnt</literal> for slant, <literal>wdth</literal> for
width, and <literal>wght</literal> for weight). Each axis also
has a <property>min_value</property>, a
<property>default_value</property>, and a <property>max_value</property>.
</para>
<para>
To set your font object's variation settings, you call the
<function>hb_font_set_variations()</function> function with an
array of <type>hb_variation_t</type> variation settings. Let's
say our font has weight and width axes. We need to specify each
of the axes by tag and assign a value on the axis:
</para>
<programlisting language="C">
unsigned int variation_count = 2;
hb_variation_t variation_data[variation_count];
variation_data[0].tag = HB_OT_TAG_VAR_AXIS_WIDTH;
variation_data[1].tag = HB_OT_TAG_VAR_AXIS_WEIGHT;
variation_data[0].value = 80;
variation_data[1].value = 750;
...
hb_font_set_variations(font, variation_data, variation_count);
</programlisting>
<para>
That should give us a slightly condensed font ("normal" on the
<literal>wdth</literal> axis is 100) at a noticeably bolder
weight ("regular" is 400 on the <literal>wght</literal> axis).
</para>
<para>
In practice, though, you should always check that the value you
want to set on the axis is within the
[<property>min_value</property>,<property>max_value</property>]
range actually implemented in the font's variation axis. After
all, a font might only provide lighter-than-regular weights, and
setting a heavier value on the <literal>wght</literal> axis will
not change that.
</para>
<para>
Once your variation settings are specified on your font object,
however, shaping with a variable font is just like shaping a
static font.
</para>
<para>
In addition to providing the variation axes themselves, fonts may also
pre-define certain variation coordinates as named instances. HarfBuzz
makes these coordinates (and their associated names) available via
<function>hb_ot_var_named_instance_get_design_coords()</function> and
<function>hb_ot_var_named_instance_get_subfamily_name_id()</function>.
</para>
<para>
Applications should treat named instances like multiple independent,
static fonts.
</para>
</section>
<section id="glyphs-and-rendering">
<title>Glyphs and rendering</title>
<para>
The main purpose of HarfBuzz is shaping, which creates a list of positioned
glyphs as output. The remaining task for text layout is to convert this list
into rendered output. While HarfBuzz does not handle rasterization of glyphs
per se, it does have APIs that provide access to the font data that is needed
to perform this task.
</para>
<para>
Traditionally, the shapes of glyphs in scalable fonts are provided as quadratic
or cubic Beziér curves defining outlines to be filled. To obtain the outlines
for a glyph, call <function>hb_font_draw_glyph()</function> and pass a
<type>hb_draw_funcs_t</type> struct. The callbacks in that struct will be called
for each segment of the outline. Note that this API provides access to outlines
as they are defined in the font, without applying hinting to fit the curves
to the pixel grid.
</para>
<para>
Fonts may provide pre-rendered images for glyphs instead of or in addition to
outlines. This is most common for fonts that contain colored glyphs, such as
Emoji. To access these images, use <function>hb_ot_color_reference_png()</function>
or <function>hb_ot_color_reference_svg()</function>.
</para>
<para>
Another way in which fonts provide colored glyphs is via paint graphs that
combine glyph outlines with gradients and allow for transformations and
compositing. In its simplest form, this can be presented as a series of
layers that are rendered on top of each other, each with its own color.
HarfBuzz has the <function>hb_ot_color_glyph_get_layers()</function> to
access glyph data in this form.
</para>
<para>
In the general case, you have to use <function>hb_font_paint_glyph()</function>
and pass a <type>hb_paint_funcs_t</type> struct with callbacks to obtain paint
graphs for glyphs that have them. The <function>hb_font_paint_glyph()</function>
API can handle outline and image glyphs as well, so it provides a unified API for
access to glyph rendering information.
</para>
</section>
</chapter>