Blame docs/usermanual-hello-harfbuzz.xml

Packit 874993
<chapter id="hello-harfbuzz">
Packit 874993
  <title>Hello, Harfbuzz</title>
Packit 874993
  <para>
Packit 874993
    Here's the simplest Harfbuzz that can possibly work. We will improve
Packit 874993
    it later.
Packit 874993
  </para>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem>
Packit 874993
      <para>
Packit 874993
        Create a buffer and put your text in it.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  #include <hb.h>
Packit 874993
  hb_buffer_t *buf;
Packit 874993
  buf = hb_buffer_create();
Packit 874993
  hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="2">
Packit 874993
      <para>
Packit 874993
        Guess the script, language and direction of the buffer.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  hb_buffer_guess_segment_properties(buf);
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="3">
Packit 874993
      <para>
Packit 874993
        Create a face and a font, using FreeType for now.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  #include <hb-ft.h>
Packit 874993
  FT_New_Face(ft_library, font_path, index, &face)
Packit 874993
  hb_font_t *font = hb_ft_font_create(face);
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="4">
Packit 874993
      <para>
Packit 874993
        Shape!
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting>
Packit 874993
  hb_shape(font, buf, NULL, 0);
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="5">
Packit 874993
      <para>
Packit 874993
        Get the glyph and position information.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  hb_glyph_info_t *glyph_info    = hb_buffer_get_glyph_infos(buf, &glyph_count);
Packit 874993
  hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="6">
Packit 874993
      <para>
Packit 874993
        Iterate over each glyph.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  for (i = 0; i < glyph_count; ++i) {
Packit 874993
    glyphid = glyph_info[i].codepoint;
Packit 874993
    x_offset = glyph_pos[i].x_offset / 64.0;
Packit 874993
    y_offset = glyph_pos[i].y_offset / 64.0;
Packit 874993
    x_advance = glyph_pos[i].x_advance / 64.0;
Packit 874993
    y_advance = glyph_pos[i].y_advance / 64.0;
Packit 874993
    draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
Packit 874993
    cursor_x += x_advance;
Packit 874993
    cursor_y += y_advance;
Packit 874993
  }
Packit 874993
</programlisting>
Packit 874993
  <orderedlist numeration="arabic">
Packit 874993
    <listitem override="7">
Packit 874993
      <para>
Packit 874993
        Tidy up.
Packit 874993
      </para>
Packit 874993
    </listitem>
Packit 874993
  </orderedlist>
Packit 874993
  <programlisting language="C">
Packit 874993
  hb_buffer_destroy(buf);
Packit 874993
  hb_font_destroy(hb_ft_font);
Packit 874993
</programlisting>
Packit 874993
  <section id="what-harfbuzz-doesnt-do">
Packit 874993
    <title>What Harfbuzz doesn't do</title>
Packit 874993
    <para>
Packit 874993
      The code above will take a UTF8 string, shape it, and give you the
Packit 874993
      information required to lay it out correctly on a single
Packit 874993
      horizontal (or vertical) line using the font provided. That is the
Packit 874993
      extent of Harfbuzz's responsibility.
Packit 874993
    </para>
Packit 874993
    <para>
Packit 874993
      If you are implementing a text layout engine you may have other
Packit 874993
      responsibilities, that Harfbuzz will not help you with:
Packit 874993
    </para>
Packit 874993
    <itemizedlist>
Packit 874993
      <listitem>
Packit 874993
        <para>
Packit 874993
          Harfbuzz won't help you with bidirectionality. If you want to
Packit 874993
          lay out text with mixed Hebrew and English, you will need to
Packit 874993
          ensure that the buffer provided to Harfbuzz has those
Packit 874993
          characters in the correct layout order. This will be different
Packit 874993
          from the logical order in which the Unicode text is stored. In
Packit 874993
          other words, the user will hit the keys in the following
Packit 874993
          sequence:
Packit 874993
        </para>
Packit 874993
        <programlisting>
Packit 874993
A B C [space] ג ב א [space] D E F
Packit 874993
        </programlisting>
Packit 874993
        <para>
Packit 874993
          but will expect to see in the output:
Packit 874993
        </para>
Packit 874993
        <programlisting>
Packit 874993
ABC אבג DEF
Packit 874993
        </programlisting>
Packit 874993
        <para>
Packit 874993
          This reordering is called <emphasis>bidi processing</emphasis>
Packit 874993
          ("bidi" is short for bidirectional), and there's an
Packit 874993
          algorithm as an annex to the Unicode Standard which tells you how
Packit 874993
          to reorder a string from logical order into presentation order.
Packit 874993
          Before sending your string to Harfbuzz, you may need to apply the
Packit 874993
          bidi algorithm to it. Libraries such as ICU and fribidi can do
Packit 874993
          this for you.
Packit 874993
        </para>
Packit 874993
      </listitem>
Packit 874993
      <listitem>
Packit 874993
        <para>
Packit 874993
          Harfbuzz won't help you with text that contains different font
Packit 874993
          properties. For instance, if you have the string "a
Packit 874993
          <emphasis>huge</emphasis> breakfast", and you expect
Packit 874993
          "huge" to be italic, you will need to send three
Packit 874993
          strings to Harfbuzz: <literal>a</literal>, in your Roman font;
Packit 874993
          <literal>huge</literal> using your italic font; and
Packit 874993
          <literal>breakfast</literal> using your Roman font again.
Packit 874993
          Similarly if you change font, font size, script, language or
Packit 874993
          direction within your string, you will need to shape each run
Packit 874993
          independently and then output them independently. Harfbuzz
Packit 874993
          expects to shape a run of characters sharing the same
Packit 874993
          properties.
Packit 874993
        </para>
Packit 874993
      </listitem>
Packit 874993
      <listitem>
Packit 874993
        <para>
Packit 874993
          Harfbuzz won't help you with line breaking, hyphenation or
Packit 874993
          justification. As mentioned above, it lays out the string
Packit 874993
          along a <emphasis>single line</emphasis> of, notionally,
Packit 874993
          infinite length. If you want to find out where the potential
Packit 874993
          word, sentence and line break points are in your text, you
Packit 874993
          could use the ICU library's break iterator functions.
Packit 874993
        </para>
Packit 874993
        <para>
Packit 874993
          Harfbuzz can tell you how wide a shaped piece of text is, which is
Packit 874993
          useful input to a justification algorithm, but it knows nothing
Packit 874993
          about paragraphs, lines or line lengths. Nor will it adjust the
Packit 874993
          space between words to fit them proportionally into a line. If you
Packit 874993
          want to layout text in paragraphs, you will probably want to send
Packit 874993
          each word of your text to Harfbuzz to determine its shaped width
Packit 874993
          after glyph substitutions, then work out how many words will fit
Packit 874993
          on a line, and then finally output each word of the line separated
Packit 874993
          by a space of the correct size to fully justify the paragraph.
Packit 874993
        </para>
Packit 874993
      </listitem>
Packit 874993
    </itemizedlist>
Packit 874993
    <para>
Packit 874993
      As a layout engine implementor, Harfbuzz will help you with the
Packit 874993
      interface between your text and your font, and that's something
Packit 874993
      that you'll need - what you then do with the glyphs that your font
Packit 874993
      returns is up to you. The example we saw above enough to get us
Packit 874993
      started using Harfbuzz. Now we are going to use the remainder of
Packit 874993
      Harfbuzz's API to refine that example and improve our text shaping
Packit 874993
      capabilities.
Packit 874993
    </para>
Packit 874993
  </section>
Packit 874993
</chapter>