519 lines
22 KiB
XML
519 lines
22 KiB
XML
<?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>
|
|
<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>
|