| <?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> |