<?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="object-model">
  <title>The HarfBuzz object model</title>
  <section id="object-model-intro">
    <title>An overview of data types in HarfBuzz</title>
    <para>
      HarfBuzz features two kinds of data types: non-opaque,
      pass-by-value types and opaque, heap-allocated types.  This kind
      of separation is common in C libraries that have to provide
      API/ABI compatibility (almost) indefinitely.
    </para>
    <para>
      <emphasis>Value types:</emphasis> The non-opaque, pass-by-value
      types include integer types, enums, and small structs.  Exposing
      a struct in the public API makes it impossible to expand the
      struct in the future. As such, exposing structs is reserved for
      cases where it’s extremely inefficient to do otherwise.
    </para>
    <para>
      In HarfBuzz, several structs, like <literal>hb_glyph_info_t</literal> and
      <literal>hb_glyph_position_t</literal>, fall into that efficiency-sensitive
      category and are non-opaque.
    </para>
    <para>
      For all non-opaque structs where future extensibility may be
      necessary, reserved members are included to hold space for
      possible future members.  As such, it’s important to provide
      <function>equal()</function>, and <function>hash()</function>
      methods for such structs, allowing users of the API do
      effectively deal with the type without having to
      adapt their code to future changes.
    </para>
    <para>
      Important value types provided by HarfBuzz include the structs
      for working with Unicode code points, glyphs, and tags for font
      tables and features, as well as the enums for many Unicode and
      OpenType properties.
    </para>
  </section>

  <section id="object-model-object-types">
    <title>Objects in HarfBuzz</title>
    <para>
      <emphasis>Object types:</emphasis> Opaque struct types are used
      for what HarfBuzz loosely calls "objects."  This doesn’t have
      much to do with the terminology from object-oriented programming
      (OOP), although some of the concepts are similar.
    </para>
    <para>
      In HarfBuzz, all object types provide certain
      lifecycle-management APIs.  Objects are reference-counted, and
      constructed with various <function>create()</function> methods, referenced via
      <function>reference()</function> and dereferenced using
      <function>destroy()</function>.
    </para>
    <para>
      For example,
      the <literal>hb_buffer_t</literal> object has
      <function>hb_buffer_create()</function> as its constructor,
      <function>hb_buffer_reference()</function> to reference, and
      <function>hb_buffer_destroy()</function> to dereference.
    </para>
    <para>
      After construction, each object's properties are accessible only
      through the setter and getter functions described in the API
      Reference manual.
    </para>
    <para>
      Note that many object types can be marked as read-only or immutable,
      facilitating their use in multi-threaded environments.
    </para>
    <para>
      Key object types provided by HarfBuzz include:
    </para>
    <itemizedlist spacing="compact">
      <listitem>
	<para>
	  <emphasis>blobs</emphasis>, which act as low-level wrappers around binary
	  data. Blobs are typically used to hold the contents of a
	  binary font file.
	</para>
      </listitem>
      <listitem>
	<para>
	  <emphasis>faces</emphasis>, which represent typefaces from a
	  font file, but without specific parameters (such as size) set.
	</para>
      </listitem>
      <listitem>
	<para>
	  <emphasis>fonts</emphasis>, which represent instances of a
	  face with all of their parameters specified.
	</para>
      </listitem>
      <listitem>
	<para>
	  <emphasis>buffers</emphasis>, which hold Unicode code points
	  for characters (before shaping) and the shaped glyph output
	  (after shaping).
	</para>
      </listitem>
      <listitem>
	<para>
	  <emphasis>shape plans</emphasis>, which store the settings
	  that HarfBuzz will use when shaping a particular text
	  segment. Shape plans are not generally used by client
	  programs directly, but as we will see in a later chapter,
	  they are still valuable to understand.
	</para>
      </listitem>
    </itemizedlist>

  </section>



  <section id="object-model-lifecycle">
    <title>Object lifecycle management</title>
    <para>
      Each object type in HarfBuzz provides a
      <function>create()</function> method. Some object types provide
      additional variants of <function>create()</function> to handle
      special cases or to speed up common tasks; those variants are
      documented in the API reference. For example,
      <function>hb_blob_create_from_file()</function> constructs a new
      blob directly from the contents of a file.
    </para>
    <para>
      All objects are created with an initial reference count of
      <literal>1</literal>. Client programs can increase the reference
      count on an object by calling its
      <function>reference()</function> method. Whenever a client
      program is finished with an object, it should call its
      corresponding <function>destroy()</function> method. The destroy
      method will decrease the reference count on the object and,
      whenever the reference count reaches zero, it will also destroy
      the object and free all of the associated memory.
    </para>
    <para>
      All of HarfBuzz's object-lifecycle-management APIs are
      thread-safe (unless you compiled HarfBuzz from source with the
      <literal>HB_NO_MT</literal> configuration flag), even when the
      object as a whole is not thread-safe.
      It is also permissible to <function>reference()</function> or to
      <function>destroy()</function> the <literal>NULL</literal>
      value.
    </para>
    <para>
      Some objects are thread-safe after they have been constructed
      and set up. The general pattern is to
      <function>create()</function> the object, make a few
      <function>set_*()</function> calls to set up the
      object, and then use it without further modification.
    </para>
    <para>
      To ensure that such an object is not modified, client programs
      can explicitly mark an object as immutable. HarfBuzz provides
      <function>make_immutable()</function> methods to mark an object
      as immutable and <function>is_immutable()</function> methods to
      test whether or not an object is immutable. Attempts to use
      setter functions on immutable objects will fail silently; see the API
      Reference manual for specifics.
    </para>
    <para>
      Note also that there are no "make mutable" methods. If client
      programs need to alter an object previously marked as immutable,
      they will need to make a duplicate of the original.
    </para>
    <para>
      Finally, object constructors (and, indeed, as much of the
      shaping API as possible) will never return
      <literal>NULL</literal>.  Instead, if there is an allocation
      error, each constructor will return an “empty” object
      singleton.
    </para>
    <para>
      These empty-object singletons are inert and safe (although
      typically useless) to pass around.  This design choice avoids
      having to check for <literal>NULL</literal> pointers all
      throughout the code.
    </para>
    <para>
      In addition, this “empty” object singleton can also be accessed
      using the <function>get_empty()</function> method of the object
      type in question.
    </para>
  </section>


  <section id="object-model-user-data">
    <title>User data</title>
    <para>
      To better integrate with client programs, HarfBuzz's objects
      offer a "user data" mechanism that can be used to attach
      arbitrary data to the object.  User-data attachment can be
      useful for tying the lifecycles of various pieces of data
      together, or for creating language bindings.
    </para>
    <para>
      Each object type has a <function>set_user_data()</function>
      method and a <function>get_user_data()</function> method. The
      <function>set_user_data()</function> methods take a client-provided
      <literal>key</literal> and a pointer,
      <literal>user_data</literal>, pointing to the data itself. Once
      the key-data pair has been attached to the object, the
      <function>get_user_data()</function> method can be called with
      the key, returning the <function>user_data</function> pointer.
    </para>
    <para>
      The <function>set_user_data()</function> methods also support an
      optional <function>destroy</function> callback. Client programs
      can set the <function>destroy</function> callback and receive
      notification from HarfBuzz whenever the object is destructed.
    </para>
    <para>
      Finally, each <function>set_user_data()</function> method allows
      the client program to set a <literal>replace</literal> Boolean
      indicating whether or not the function call should replace any
      existing <literal>user_data</literal>
      associated with the specified key.
    </para>
  </section>



  <section id="object-model-blobs">
    <title>Blobs</title>
    <para>
      While most of HarfBuzz's object types are specific to the
      shaping process, <emphasis>blobs</emphasis> are somewhat
      different.
    </para>
    <para>
      Blobs are an abstraction designed to negotiate lifecycle and
      permissions for raw pieces of data.  For example, when you load
      the raw font data into memory and want to pass it to HarfBuzz,
      you do so in a <literal>hb_blob_t</literal> wrapper.
    </para>
    <para>
      This allows you to take advantage of HarfBuzz's
      reference-counting and <function>destroy</function>
      callbacks. If you allocated the memory for the data using
      <function>malloc()</function>, you would create the blob using
    </para>
    <programlisting language="C">
      hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, data, free)
    </programlisting>
    <para>
      That way, HarfBuzz will call <function>free()</function> on the
      allocated memory whenever the blob drops its last reference and
      is deconstructed.  Consequently, the user code can stop worrying
      about freeing memory and let the reference-counting machinery
      take care of that.
    </para>
    <para>
      Most of the time, blobs are read-only, facilitating their use in
      immutable objects.
    </para>
  </section>

</chapter>