Home | History | Annotate | Download | only in docs
      1 <chapter id="hello-harfbuzz">
      2   <title>Hello, Harfbuzz</title>
      3   <para>
      4     Here's the simplest Harfbuzz that can possibly work. We will improve
      5     it later.
      6   </para>
      7   <orderedlist numeration="arabic">
      8     <listitem>
      9       <para>
     10         Create a buffer and put your text in it.
     11       </para>
     12     </listitem>
     13   </orderedlist>
     14   <programlisting language="C">
     15   #include &lt;hb.h&gt;
     16   hb_buffer_t *buf;
     17   buf = hb_buffer_create();
     18   hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
     19 </programlisting>
     20   <orderedlist numeration="arabic">
     21     <listitem override="2">
     22       <para>
     23         Guess the script, language and direction of the buffer.
     24       </para>
     25     </listitem>
     26   </orderedlist>
     27   <programlisting language="C">
     28   hb_buffer_guess_segment_properties(buf);
     29 </programlisting>
     30   <orderedlist numeration="arabic">
     31     <listitem override="3">
     32       <para>
     33         Create a face and a font, using FreeType for now.
     34       </para>
     35     </listitem>
     36   </orderedlist>
     37   <programlisting language="C">
     38   #include &lt;hb-ft.h&gt;
     39   FT_New_Face(ft_library, font_path, index, &amp;face)
     40   hb_font_t *font = hb_ft_font_create(face);
     41 </programlisting>
     42   <orderedlist numeration="arabic">
     43     <listitem override="4">
     44       <para>
     45         Shape!
     46       </para>
     47     </listitem>
     48   </orderedlist>
     49   <programlisting>
     50   hb_shape(font, buf, NULL, 0);
     51 </programlisting>
     52   <orderedlist numeration="arabic">
     53     <listitem override="5">
     54       <para>
     55         Get the glyph and position information.
     56       </para>
     57     </listitem>
     58   </orderedlist>
     59   <programlisting language="C">
     60   hb_glyph_info_t *glyph_info    = hb_buffer_get_glyph_infos(buf, &amp;glyph_count);
     61   hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &amp;glyph_count);
     62 </programlisting>
     63   <orderedlist numeration="arabic">
     64     <listitem override="6">
     65       <para>
     66         Iterate over each glyph.
     67       </para>
     68     </listitem>
     69   </orderedlist>
     70   <programlisting language="C">
     71   for (i = 0; i &lt; glyph_count; ++i) {
     72     glyphid = glyph_info[i].codepoint;
     73     x_offset = glyph_pos[i].x_offset / 64.0;
     74     y_offset = glyph_pos[i].y_offset / 64.0;
     75     x_advance = glyph_pos[i].x_advance / 64.0;
     76     y_advance = glyph_pos[i].y_advance / 64.0;
     77     draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
     78     cursor_x += x_advance;
     79     cursor_y += y_advance;
     80   }
     81 </programlisting>
     82   <orderedlist numeration="arabic">
     83     <listitem override="7">
     84       <para>
     85         Tidy up.
     86       </para>
     87     </listitem>
     88   </orderedlist>
     89   <programlisting language="C">
     90   hb_buffer_destroy(buf);
     91   hb_font_destroy(hb_ft_font);
     92 </programlisting>
     93   <section id="what-harfbuzz-doesnt-do">
     94     <title>What Harfbuzz doesn't do</title>
     95     <para>
     96       The code above will take a UTF8 string, shape it, and give you the
     97       information required to lay it out correctly on a single
     98       horizontal (or vertical) line using the font provided. That is the
     99       extent of Harfbuzz's responsibility.
    100     </para>
    101     <para>
    102       If you are implementing a text layout engine you may have other
    103       responsibilities, that Harfbuzz will not help you with:
    104     </para>
    105     <itemizedlist>
    106       <listitem>
    107         <para>
    108           Harfbuzz won't help you with bidirectionality. If you want to
    109           lay out text with mixed Hebrew and English, you will need to
    110           ensure that the buffer provided to Harfbuzz has those
    111           characters in the correct layout order. This will be different
    112           from the logical order in which the Unicode text is stored. In
    113           other words, the user will hit the keys in the following
    114           sequence:
    115         </para>
    116         <programlisting>
    117 A B C [space]    [space] D E F
    118         </programlisting>
    119         <para>
    120           but will expect to see in the output:
    121         </para>
    122         <programlisting>
    123 ABC  DEF
    124         </programlisting>
    125         <para>
    126           This reordering is called <emphasis>bidi processing</emphasis>
    127           (&quot;bidi&quot; is short for bidirectional), and there's an
    128           algorithm as an annex to the Unicode Standard which tells you how
    129           to reorder a string from logical order into presentation order.
    130           Before sending your string to Harfbuzz, you may need to apply the
    131           bidi algorithm to it. Libraries such as ICU and fribidi can do
    132           this for you.
    133         </para>
    134       </listitem>
    135       <listitem>
    136         <para>
    137           Harfbuzz won't help you with text that contains different font
    138           properties. For instance, if you have the string &quot;a
    139           <emphasis>huge</emphasis> breakfast&quot;, and you expect
    140           &quot;huge&quot; to be italic, you will need to send three
    141           strings to Harfbuzz: <literal>a</literal>, in your Roman font;
    142           <literal>huge</literal> using your italic font; and
    143           <literal>breakfast</literal> using your Roman font again.
    144           Similarly if you change font, font size, script, language or
    145           direction within your string, you will need to shape each run
    146           independently and then output them independently. Harfbuzz
    147           expects to shape a run of characters sharing the same
    148           properties.
    149         </para>
    150       </listitem>
    151       <listitem>
    152         <para>
    153           Harfbuzz won't help you with line breaking, hyphenation or
    154           justification. As mentioned above, it lays out the string
    155           along a <emphasis>single line</emphasis> of, notionally,
    156           infinite length. If you want to find out where the potential
    157           word, sentence and line break points are in your text, you
    158           could use the ICU library's break iterator functions.
    159         </para>
    160         <para>
    161           Harfbuzz can tell you how wide a shaped piece of text is, which is
    162           useful input to a justification algorithm, but it knows nothing
    163           about paragraphs, lines or line lengths. Nor will it adjust the
    164           space between words to fit them proportionally into a line. If you
    165           want to layout text in paragraphs, you will probably want to send
    166           each word of your text to Harfbuzz to determine its shaped width
    167           after glyph substitutions, then work out how many words will fit
    168           on a line, and then finally output each word of the line separated
    169           by a space of the correct size to fully justify the paragraph.
    170         </para>
    171       </listitem>
    172     </itemizedlist>
    173     <para>
    174       As a layout engine implementor, Harfbuzz will help you with the
    175       interface between your text and your font, and that's something
    176       that you'll need - what you then do with the glyphs that your font
    177       returns is up to you. The example we saw above enough to get us
    178       started using Harfbuzz. Now we are going to use the remainder of
    179       Harfbuzz's API to refine that example and improve our text shaping
    180       capabilities.
    181     </para>
    182   </section>
    183 </chapter>