| <?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, most object constructors return an “empty” object | |
| singleton on allocation failure rather than | |
| <literal>NULL</literal>. Constructors whose names end in | |
| <literal>_or_fail</literal>, such as | |
| <function>hb_blob_create_or_fail()</function> and | |
| <function>hb_blob_create_from_file_or_fail()</function>, instead | |
| return <literal>NULL</literal> on failure. Check their return | |
| values before using the objects, and consult each constructor's | |
| API Reference documentation for its failure behavior. | |
| </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> |