usermanual-object-model.xml 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <?xml version="1.0"?>
  2. <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
  4. <!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
  5. <!ENTITY version SYSTEM "version.xml">
  6. ]>
  7. <chapter id="object-model">
  8. <title>The HarfBuzz object model</title>
  9. <section id="object-model-intro">
  10. <title>An overview of data types in HarfBuzz</title>
  11. <para>
  12. HarfBuzz features two kinds of data types: non-opaque,
  13. pass-by-value types and opaque, heap-allocated types. This kind
  14. of separation is common in C libraries that have to provide
  15. API/ABI compatibility (almost) indefinitely.
  16. </para>
  17. <para>
  18. <emphasis>Value types:</emphasis> The non-opaque, pass-by-value
  19. types include integer types, enums, and small structs. Exposing
  20. a struct in the public API makes it impossible to expand the
  21. struct in the future. As such, exposing structs is reserved for
  22. cases where it’s extremely inefficient to do otherwise.
  23. </para>
  24. <para>
  25. In HarfBuzz, several structs, like <literal>hb_glyph_info_t</literal> and
  26. <literal>hb_glyph_position_t</literal>, fall into that efficiency-sensitive
  27. category and are non-opaque.
  28. </para>
  29. <para>
  30. For all non-opaque structs where future extensibility may be
  31. necessary, reserved members are included to hold space for
  32. possible future members. As such, it’s important to provide
  33. <function>equal()</function>, and <function>hash()</function>
  34. methods for such structs, allowing users of the API do
  35. effectively deal with the type without having to
  36. adapt their code to future changes.
  37. </para>
  38. <para>
  39. Important value types provided by HarfBuzz include the structs
  40. for working with Unicode code points, glyphs, and tags for font
  41. tables and features, as well as the enums for many Unicode and
  42. OpenType properties.
  43. </para>
  44. </section>
  45. <section id="object-model-object-types">
  46. <title>Objects in HarfBuzz</title>
  47. <para>
  48. <emphasis>Object types:</emphasis> Opaque struct types are used
  49. for what HarfBuzz loosely calls "objects." This doesn’t have
  50. much to do with the terminology from object-oriented programming
  51. (OOP), although some of the concepts are similar.
  52. </para>
  53. <para>
  54. In HarfBuzz, all object types provide certain
  55. lifecycle-management APIs. Objects are reference-counted, and
  56. constructed with various <function>create()</function> methods, referenced via
  57. <function>reference()</function> and dereferenced using
  58. <function>destroy()</function>.
  59. </para>
  60. <para>
  61. For example,
  62. the <literal>hb_buffer_t</literal> object has
  63. <function>hb_buffer_create()</function> as its constructor,
  64. <function>hb_buffer_reference()</function> to reference, and
  65. <function>hb_buffer_destroy()</function> to dereference.
  66. </para>
  67. <para>
  68. After construction, each object's properties are accessible only
  69. through the setter and getter functions described in the API
  70. Reference manual.
  71. </para>
  72. <para>
  73. Note that many object types can be marked as read-only or immutable,
  74. facilitating their use in multi-threaded environments.
  75. </para>
  76. <para>
  77. Key object types provided by HarfBuzz include:
  78. </para>
  79. <itemizedlist spacing="compact">
  80. <listitem>
  81. <para>
  82. <emphasis>blobs</emphasis>, which act as low-level wrappers around binary
  83. data. Blobs are typically used to hold the contents of a
  84. binary font file.
  85. </para>
  86. </listitem>
  87. <listitem>
  88. <para>
  89. <emphasis>faces</emphasis>, which represent typefaces from a
  90. font file, but without specific parameters (such as size) set.
  91. </para>
  92. </listitem>
  93. <listitem>
  94. <para>
  95. <emphasis>fonts</emphasis>, which represent instances of a
  96. face with all of their parameters specified.
  97. </para>
  98. </listitem>
  99. <listitem>
  100. <para>
  101. <emphasis>buffers</emphasis>, which hold Unicode code points
  102. for characters (before shaping) and the shaped glyph output
  103. (after shaping).
  104. </para>
  105. </listitem>
  106. <listitem>
  107. <para>
  108. <emphasis>shape plans</emphasis>, which store the settings
  109. that HarfBuzz will use when shaping a particular text
  110. segment. Shape plans are not generally used by client
  111. programs directly, but as we will see in a later chapter,
  112. they are still valuable to understand.
  113. </para>
  114. </listitem>
  115. </itemizedlist>
  116. </section>
  117. <section id="object-model-lifecycle">
  118. <title>Object lifecycle management</title>
  119. <para>
  120. Each object type in HarfBuzz provides a
  121. <function>create()</function> method. Some object types provide
  122. additional variants of <function>create()</function> to handle
  123. special cases or to speed up common tasks; those variants are
  124. documented in the API reference. For example,
  125. <function>hb_blob_create_from_file()</function> constructs a new
  126. blob directly from the contents of a file.
  127. </para>
  128. <para>
  129. All objects are created with an initial reference count of
  130. <literal>1</literal>. Client programs can increase the reference
  131. count on an object by calling its
  132. <function>reference()</function> method. Whenever a client
  133. program is finished with an object, it should call its
  134. corresponding <function>destroy()</function> method. The destroy
  135. method will decrease the reference count on the object and,
  136. whenever the reference count reaches zero, it will also destroy
  137. the object and free all of the associated memory.
  138. </para>
  139. <para>
  140. All of HarfBuzz's object-lifecycle-management APIs are
  141. thread-safe (unless you compiled HarfBuzz from source with the
  142. <literal>HB_NO_MT</literal> configuration flag), even when the
  143. object as a whole is not thread-safe.
  144. It is also permissible to <function>reference()</function> or to
  145. <function>destroy()</function> the <literal>NULL</literal>
  146. value.
  147. </para>
  148. <para>
  149. Some objects are thread-safe after they have been constructed
  150. and set up. The general pattern is to
  151. <function>create()</function> the object, make a few
  152. <function>set_*()</function> calls to set up the
  153. object, and then use it without further modification.
  154. </para>
  155. <para>
  156. To ensure that such an object is not modified, client programs
  157. can explicitly mark an object as immutable. HarfBuzz provides
  158. <function>make_immutable()</function> methods to mark an object
  159. as immutable and <function>is_immutable()</function> methods to
  160. test whether or not an object is immutable. Attempts to use
  161. setter functions on immutable objects will fail silently; see the API
  162. Reference manual for specifics.
  163. </para>
  164. <para>
  165. Note also that there are no "make mutable" methods. If client
  166. programs need to alter an object previously marked as immutable,
  167. they will need to make a duplicate of the original.
  168. </para>
  169. <para>
  170. Finally, object constructors (and, indeed, as much of the
  171. shaping API as possible) will never return
  172. <literal>NULL</literal>. Instead, if there is an allocation
  173. error, each constructor will return an “empty” object
  174. singleton.
  175. </para>
  176. <para>
  177. These empty-object singletons are inert and safe (although
  178. typically useless) to pass around. This design choice avoids
  179. having to check for <literal>NULL</literal> pointers all
  180. throughout the code.
  181. </para>
  182. <para>
  183. In addition, this “empty” object singleton can also be accessed
  184. using the <function>get_empty()</function> method of the object
  185. type in question.
  186. </para>
  187. </section>
  188. <section id="object-model-user-data">
  189. <title>User data</title>
  190. <para>
  191. To better integrate with client programs, HarfBuzz's objects
  192. offer a "user data" mechanism that can be used to attach
  193. arbitrary data to the object. User-data attachment can be
  194. useful for tying the lifecycles of various pieces of data
  195. together, or for creating language bindings.
  196. </para>
  197. <para>
  198. Each object type has a <function>set_user_data()</function>
  199. method and a <function>get_user_data()</function> method. The
  200. <function>set_user_data()</function> methods take a client-provided
  201. <literal>key</literal> and a pointer,
  202. <literal>user_data</literal>, pointing to the data itself. Once
  203. the key-data pair has been attached to the object, the
  204. <function>get_user_data()</function> method can be called with
  205. the key, returning the <function>user_data</function> pointer.
  206. </para>
  207. <para>
  208. The <function>set_user_data()</function> methods also support an
  209. optional <function>destroy</function> callback. Client programs
  210. can set the <function>destroy</function> callback and receive
  211. notification from HarfBuzz whenever the object is destructed.
  212. </para>
  213. <para>
  214. Finally, each <function>set_user_data()</function> method allows
  215. the client program to set a <literal>replace</literal> Boolean
  216. indicating whether or not the function call should replace any
  217. existing <literal>user_data</literal>
  218. associated with the specified key.
  219. </para>
  220. </section>
  221. <section id="object-model-blobs">
  222. <title>Blobs</title>
  223. <para>
  224. While most of HarfBuzz's object types are specific to the
  225. shaping process, <emphasis>blobs</emphasis> are somewhat
  226. different.
  227. </para>
  228. <para>
  229. Blobs are an abstraction designed to negotiate lifecycle and
  230. permissions for raw pieces of data. For example, when you load
  231. the raw font data into memory and want to pass it to HarfBuzz,
  232. you do so in a <literal>hb_blob_t</literal> wrapper.
  233. </para>
  234. <para>
  235. This allows you to take advantage of HarfBuzz's
  236. reference-counting and <function>destroy</function>
  237. callbacks. If you allocated the memory for the data using
  238. <function>malloc()</function>, you would create the blob using
  239. </para>
  240. <programlisting language="C">
  241. hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, data, free)
  242. </programlisting>
  243. <para>
  244. That way, HarfBuzz will call <function>free()</function> on the
  245. allocated memory whenever the blob drops its last reference and
  246. is deconstructed. Consequently, the user code can stop worrying
  247. about freeing memory and let the reference-counting machinery
  248. take care of that.
  249. </para>
  250. <para>
  251. Most of the time, blobs are read-only, facilitating their use in
  252. immutable objects.
  253. </para>
  254. </section>
  255. </chapter>