1 <?xml version="1.0"?> 2 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" 3 "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ 4 <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'"> 5 <!ENTITY version SYSTEM "version.xml"> 6 ]> 7 <chapter id="getting-started"> 8 <title>Getting started with HarfBuzz</title> 9 <section> 10 <title>An overview of the HarfBuzz shaping API</title> 11 <para> 12 The core of the HarfBuzz shaping API is the function 13 <function>hb_shape()</function>. This function takes a font, a 14 buffer containing a string of Unicode codepoints and 15 (optionally) a list of font features as its input. It replaces 16 the codepoints in the buffer with the corresponding glyphs from 17 the font, correctly ordered and positioned, and with any of the 18 optional font features applied. 19 </para> 20 <para> 21 In addition to holding the pre-shaping input (the Unicode 22 codepoints that comprise the input string) and the post-shaping 23 output (the glyphs and positions), a HarfBuzz buffer has several 24 properties that affect shaping. The most important are the 25 text-flow direction (e.g., left-to-right, right-to-left, 26 top-to-bottom, or bottom-to-top), the script tag, and the 27 language tag. 28 </para> 29 30 <para> 31 For input string buffers, flags are available to denote when the 32 buffer represents the beginning or end of a paragraph, to 33 indicate whether or not to visibly render Unicode <literal>Default 34 Ignorable</literal> codepoints, and to modify the cluster-merging 35 behavior for the buffer. For shaped output buffers, the 36 individual X and Y offsets and <literal>advances</literal> 37 (the logical dimensions) of each glyph are 38 accessible. HarfBuzz also flags glyphs as 39 <literal>UNSAFE_TO_BREAK</literal> if breaking the string at 40 that glyph (e.g., in a line-breaking or hyphenation process) 41 would require re-shaping the text. 42 </para> 43 44 <para> 45 HarfBuzz also provides methods to compare the contents of 46 buffers, join buffers, normalize buffer contents, and handle 47 invalid codepoints, as well as to determine the state of a 48 buffer (e.g., input codepoints or output glyphs). Buffer 49 lifecycles are managed and all buffers are reference-counted. 50 </para> 51 52 <para> 53 Although the default <function>hb_shape()</function> function is 54 sufficient for most use cases, a variant is also provide that 55 lets you specify which of HarfBuzz's shapers to use on a buffer. 56 </para> 57 58 <para> 59 HarfBuzz can read TrueType fonts, TrueType collections, OpenType 60 fonts, and OpenType collections. Functions are provided to query 61 font objects about metrics, Unicode coverage, available tables and 62 features, and variation selectors. Individual glyphs can also be 63 queried for metrics, variations, and glyph names. OpenType 64 variable fonts are supported, and HarfBuzz allows you to set 65 variation-axis coordinates on font objects. 66 </para> 67 68 <para> 69 HarfBuzz provides glue code to integrate with various other 70 libraries, including FreeType, GObject, and CoreText. Support 71 for integrating with Uniscribe and DirectWrite is experimental 72 at present. 73 </para> 74 </section> 75 76 <section> 77 <title>Terminology</title> 78 <variablelist> 79 <varlistentry> 80 <term>shaper</term> 81 <listitem> 82 <para> 83 In HarfBuzz, a <emphasis>shaper</emphasis> is a 84 handler for a specific script shaping model. HarfBuzz 85 implements separate shapers for Indic, Arabic, Thai and 86 Lao, Khmer, Myanmar, Tibetan, Hangul, Hebrew, the 87 Universal Shaping Engine (USE), and a default shaper for 88 non-complex scripts. 89 </para> 90 </listitem> 91 </varlistentry> 92 93 <varlistentry> 94 <term>cluster</term> 95 <listitem> 96 <para> 97 In text shaping, a <emphasis>cluster</emphasis> is a 98 sequence of codepoints that must be handled as an 99 indivisible unit. Clusters can include codepoint 100 sequences that form a ligature or base-and-mark 101 sequences. Tracking and preserving clusters is important 102 when shaping operations might separate or reorder 103 codepoints. 104 </para> 105 <para> 106 HarfBuzz provides three cluster 107 <emphasis>levels</emphasis> that implement different 108 approaches to the problem of preserving clusters during 109 shaping operations. 110 </para> 111 </listitem> 112 </varlistentry> 113 114 115 </variablelist> 116 117 </section> 118 119 120 <section> 121 <title>A simple shaping example</title> 122 123 <para> 124 Below is the simplest HarfBuzz shaping example possible. 125 </para> 126 <orderedlist numeration="arabic"> 127 <listitem> 128 <para> 129 Create a buffer and put your text in it. 130 </para> 131 </listitem> 132 </orderedlist> 133 <programlisting language="C"> 134 #include <hb.h> 135 hb_buffer_t *buf; 136 buf = hb_buffer_create(); 137 hb_buffer_add_utf8(buf, text, -1, 0, -1); 138 </programlisting> 139 <orderedlist numeration="arabic"> 140 <listitem override="2"> 141 <para> 142 Guess the script, language and direction of the buffer. 143 </para> 144 </listitem> 145 </orderedlist> 146 <programlisting language="C"> 147 hb_buffer_set_direction(buf, HB_DIRECTION_LTR); 148 hb_buffer_set_script(buf, HB_SCRIPT_LATIN); 149 hb_buffer_set_language(buf, hb_language_from_string("en", -1)); 150 </programlisting> 151 <orderedlist numeration="arabic"> 152 <listitem override="3"> 153 <para> 154 Create a face and a font, using FreeType for now. 155 </para> 156 </listitem> 157 </orderedlist> 158 <programlisting language="C"> 159 #include <hb-ft.h> 160 FT_New_Face(ft_library, font_path, index, &face); 161 FT_Set_Char_Size(face, 0, 1000, 0, 0); 162 hb_font_t *font = hb_ft_font_create(face); 163 </programlisting> 164 <orderedlist numeration="arabic"> 165 <listitem override="4"> 166 <para> 167 Shape! 168 </para> 169 </listitem> 170 </orderedlist> 171 <programlisting> 172 hb_shape(font, buf, NULL, 0); 173 </programlisting> 174 <orderedlist numeration="arabic"> 175 <listitem override="5"> 176 <para> 177 Get the glyph and position information. 178 </para> 179 </listitem> 180 </orderedlist> 181 <programlisting language="C"> 182 hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); 183 hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); 184 </programlisting> 185 <orderedlist numeration="arabic"> 186 <listitem override="6"> 187 <para> 188 Iterate over each glyph. 189 </para> 190 </listitem> 191 </orderedlist> 192 <programlisting language="C"> 193 for (i = 0; i < glyph_count; ++i) { 194 glyphid = glyph_info[i].codepoint; 195 x_offset = glyph_pos[i].x_offset / 64.0; 196 y_offset = glyph_pos[i].y_offset / 64.0; 197 x_advance = glyph_pos[i].x_advance / 64.0; 198 y_advance = glyph_pos[i].y_advance / 64.0; 199 draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset); 200 cursor_x += x_advance; 201 cursor_y += y_advance; 202 } 203 </programlisting> 204 <orderedlist numeration="arabic"> 205 <listitem override="7"> 206 <para> 207 Tidy up. 208 </para> 209 </listitem> 210 </orderedlist> 211 <programlisting language="C"> 212 hb_buffer_destroy(buf); 213 hb_font_destroy(hb_ft_font); 214 </programlisting> 215 216 <para> 217 This example shows enough to get us started using HarfBuzz. In 218 the sections that follow, we will use the remainder of 219 HarfBuzz's API to refine and extend the example and improve its 220 text-shaping capabilities. 221 </para> 222 </section> 223 </chapter> 224