<?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="getting-started"> <title>Getting started with HarfBuzz</title> <section> <title>An overview of the HarfBuzz shaping API</title> <para> The core of the HarfBuzz shaping API is the function <function>hb_shape()</function>. This function takes a font, a buffer containing a string of Unicode codepoints and (optionally) a list of font features as its input. It replaces the codepoints in the buffer with the corresponding glyphs from the font, correctly ordered and positioned, and with any of the optional font features applied. </para> <para> In addition to holding the pre-shaping input (the Unicode codepoints that comprise the input string) and the post-shaping output (the glyphs and positions), a HarfBuzz buffer has several properties that affect shaping. The most important are the text-flow direction (e.g., left-to-right, right-to-left, top-to-bottom, or bottom-to-top), the script tag, and the language tag. </para> <para> For input string buffers, flags are available to denote when the buffer represents the beginning or end of a paragraph, to indicate whether or not to visibly render Unicode <literal>Default Ignorable</literal> codepoints, and to modify the cluster-merging behavior for the buffer. For shaped output buffers, the individual X and Y offsets and <literal>advances</literal> (the logical dimensions) of each glyph are accessible. HarfBuzz also flags glyphs as <literal>UNSAFE_TO_BREAK</literal> if breaking the string at that glyph (e.g., in a line-breaking or hyphenation process) would require re-shaping the text. </para> <para> HarfBuzz also provides methods to compare the contents of buffers, join buffers, normalize buffer contents, and handle invalid codepoints, as well as to determine the state of a buffer (e.g., input codepoints or output glyphs). Buffer lifecycles are managed and all buffers are reference-counted. </para> <para> Although the default <function>hb_shape()</function> function is sufficient for most use cases, a variant is also provide that lets you specify which of HarfBuzz's shapers to use on a buffer. </para> <para> HarfBuzz can read TrueType fonts, TrueType collections, OpenType fonts, and OpenType collections. Functions are provided to query font objects about metrics, Unicode coverage, available tables and features, and variation selectors. Individual glyphs can also be queried for metrics, variations, and glyph names. OpenType variable fonts are supported, and HarfBuzz allows you to set variation-axis coordinates on font objects. </para> <para> HarfBuzz provides glue code to integrate with various other libraries, including FreeType, GObject, and CoreText. Support for integrating with Uniscribe and DirectWrite is experimental at present. </para> </section> <section> <title>Terminology</title> <variablelist> <varlistentry> <term>shaper</term> <listitem> <para> In HarfBuzz, a <emphasis>shaper</emphasis> is a handler for a specific script shaping model. HarfBuzz implements separate shapers for Indic, Arabic, Thai and Lao, Khmer, Myanmar, Tibetan, Hangul, Hebrew, the Universal Shaping Engine (USE), and a default shaper for non-complex scripts. </para> </listitem> </varlistentry> <varlistentry> <term>cluster</term> <listitem> <para> In text shaping, a <emphasis>cluster</emphasis> is a sequence of codepoints that must be handled as an indivisible unit. Clusters can include codepoint sequences that form a ligature or base-and-mark sequences. Tracking and preserving clusters is important when shaping operations might separate or reorder codepoints. </para> <para> HarfBuzz provides three cluster <emphasis>levels</emphasis> that implement different approaches to the problem of preserving clusters during shaping operations. </para> </listitem> </varlistentry> </variablelist> </section> <section> <title>A simple shaping example</title> <para> Below is the simplest HarfBuzz shaping example possible. </para> <orderedlist numeration="arabic"> <listitem> <para> Create a buffer and put your text in it. </para> </listitem> </orderedlist> <programlisting language="C"> #include <hb.h> hb_buffer_t *buf; buf = hb_buffer_create(); hb_buffer_add_utf8(buf, text, -1, 0, -1); </programlisting> <orderedlist numeration="arabic"> <listitem override="2"> <para> Guess the script, language and direction of the buffer. </para> </listitem> </orderedlist> <programlisting language="C"> hb_buffer_set_direction(buf, HB_DIRECTION_LTR); hb_buffer_set_script(buf, HB_SCRIPT_LATIN); hb_buffer_set_language(buf, hb_language_from_string("en", -1)); </programlisting> <orderedlist numeration="arabic"> <listitem override="3"> <para> Create a face and a font, using FreeType for now. </para> </listitem> </orderedlist> <programlisting language="C"> #include <hb-ft.h> FT_New_Face(ft_library, font_path, index, &face); FT_Set_Char_Size(face, 0, 1000, 0, 0); hb_font_t *font = hb_ft_font_create(face); </programlisting> <orderedlist numeration="arabic"> <listitem override="4"> <para> Shape! </para> </listitem> </orderedlist> <programlisting> hb_shape(font, buf, NULL, 0); </programlisting> <orderedlist numeration="arabic"> <listitem override="5"> <para> Get the glyph and position information. </para> </listitem> </orderedlist> <programlisting language="C"> hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); </programlisting> <orderedlist numeration="arabic"> <listitem override="6"> <para> Iterate over each glyph. </para> </listitem> </orderedlist> <programlisting language="C"> for (i = 0; i < glyph_count; ++i) { glyphid = glyph_info[i].codepoint; x_offset = glyph_pos[i].x_offset / 64.0; y_offset = glyph_pos[i].y_offset / 64.0; x_advance = glyph_pos[i].x_advance / 64.0; y_advance = glyph_pos[i].y_advance / 64.0; draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset); cursor_x += x_advance; cursor_y += y_advance; } </programlisting> <orderedlist numeration="arabic"> <listitem override="7"> <para> Tidy up. </para> </listitem> </orderedlist> <programlisting language="C"> hb_buffer_destroy(buf); hb_font_destroy(hb_ft_font); </programlisting> <para> This example shows enough to get us started using HarfBuzz. In the sections that follow, we will use the remainder of HarfBuzz's API to refine and extend the example and improve its text-shaping capabilities. </para> </section> </chapter>