| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <?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>
|