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 46 <section id="object-model-object-types"> 47 <title>Objects in HarfBuzz</title> 48 <para> 49 <emphasis>Object types:</emphasis> Opaque struct types are used 50 for what HarfBuzz loosely calls "objects." This doesn’t have 51 much to do with the terminology from object-oriented programming 52 (OOP), although some of the concepts are similar. 53 </para> 54 <para> 55 In HarfBuzz, all object types provide certain 56 lifecycle-management APIs. Objects are reference-counted, and 57 constructed with various <function>create()</function> methods, referenced via 58 <function>reference()</function> and dereferenced using 59 <function>destroy()</function>. 60 </para> 61 <para> 62 For example, 63 the <literal>hb_buffer_t</literal> object has 64 <function>hb_buffer_create()</function> as its constructor, 65 <function>hb_buffer_reference()</function> to reference, and 66 <function>hb_buffer_destroy()</function> to dereference. 67 </para> 68 <para> 69 After construction, each object's properties are accessible only 70 through the setter and getter functions described in the API 71 Reference manual. 72 </para> 73 <para> 74 Note that many object types can be marked as read-only or immutable, 75 facilitating their use in multi-threaded environments. 76 </para> 77 <para> 78 Key object types provided by HarfBuzz include: 79 </para> 80 <itemizedlist spacing="compact"> 81 <listitem> 82 <para> 83 <emphasis>blobs</emphasis>, which act as low-level wrappers around binary 84 data. Blobs are typically used to hold the contents of a 85 binary font file. 86 </para> 87 </listitem> 88 <listitem> 89 <para> 90 <emphasis>faces</emphasis>, which represent typefaces from a 91 font file, but without specific parameters (such as size) set. 92 </para> 93 </listitem> 94 <listitem> 95 <para> 96 <emphasis>fonts</emphasis>, which represent instances of a 97 face with all of their parameters specified. 98 </para> 99 </listitem> 100 <listitem> 101 <para> 102 <emphasis>buffers</emphasis>, which hold Unicode code points 103 for characters (before shaping) and the shaped glyph output 104 (after shaping). 105 </para> 106 </listitem> 107 <listitem> 108 <para> 109 <emphasis>shape plans</emphasis>, which store the settings 110 that HarfBuzz will use when shaping a particular text 111 segment. Shape plans are not generally used by client 112 programs directly, but as we will see in a later chapter, 113 they are still valuable to understand. 114 </para> 115 </listitem> 116 </itemizedlist> 117 118 </section> 119 120 121 122 <section id="object-model-lifecycle"> 123 <title>Object lifecycle management</title> 124 <para> 125 Each object type in HarfBuzz provides a 126 <function>create()</function> method. Some object types provide 127 additional variants of <function>create()</function> to handle 128 special cases or to speed up common tasks; those variants are 129 documented in the API reference. For example, 130 <function>hb_blob_create_from_file()</function> constructs a new 131 blob directly from the contents of a file. 132 </para> 133 <para> 134 All objects are created with an initial reference count of 135 <literal>1</literal>. Client programs can increase the reference 136 count on an object by calling its 137 <function>reference()</function> method. Whenever a client 138 program is finished with an object, it should call its 139 corresponding <function>destroy()</function> method. The destroy 140 method will decrease the reference count on the object and, 141 whenever the reference count reaches zero, it will also destroy 142 the object and free all of the associated memory. 143 </para> 144 <para> 145 All of HarfBuzz's object-lifecycle-management APIs are 146 thread-safe (unless you compiled HarfBuzz from source with the 147 <literal>HB_NO_MT</literal> configuration flag), even when the 148 object as a whole is not thread-safe. 149 It is also permissible to <function>reference()</function> or to 150 <function>destroy()</function> the <literal>NULL</literal> 151 value. 152 </para> 153 <para> 154 Some objects are thread-safe after they have been constructed 155 and set up. The general pattern is to 156 <function>create()</function> the object, make a few 157 <function>set_*()</function> calls to set up the 158 object, and then use it without further modification. 159 </para> 160 <para> 161 To ensure that such an object is not modified, client programs 162 can explicitly mark an object as immutable. HarfBuzz provides 163 <function>make_immutable()</function> methods to mark an object 164 as immutable and <function>is_immutable()</function> methods to 165 test whether or not an object is immutable. Attempts to use 166 setter functions on immutable objects will fail silently; see the API 167 Reference manual for specifics. 168 </para> 169 <para> 170 Note also that there are no "make mutable" methods. If client 171 programs need to alter an object previously marked as immutable, 172 they will need to make a duplicate of the original. 173 </para> 174 <para> 175 Finally, object constructors (and, indeed, as much of the 176 shaping API as possible) will never return 177 <literal>NULL</literal>. Instead, if there is an allocation 178 error, each constructor will return an “empty” object 179 singleton. 180 </para> 181 <para> 182 These empty-object singletons are inert and safe (although 183 typically useless) to pass around. This design choice avoids 184 having to check for <literal>NULL</literal> pointers all 185 throughout the code. 186 </para> 187 <para> 188 In addition, this “empty” object singleton can also be accessed 189 using the <function>get_empty()</function> method of the object 190 type in question. 191 </para> 192 </section> 193 194 195 <section id="object-model-user-data"> 196 <title>User data</title> 197 <para> 198 To better integrate with client programs, HarfBuzz's objects 199 offer a "user data" mechanism that can be used to attach 200 arbitrary data to the object. User-data attachment can be 201 useful for tying the lifecycles of various pieces of data 202 together, or for creating language bindings. 203 </para> 204 <para> 205 Each object type has a <function>set_user_data()</function> 206 method and a <function>get_user_data()</function> method. The 207 <function>set_user_data()</function> methods take a client-provided 208 <literal>key</literal> and a pointer, 209 <literal>user_data</literal>, pointing to the data itself. Once 210 the key-data pair has been attached to the object, the 211 <function>get_user_data()</function> method can be called with 212 the key, returning the <function>user_data</function> pointer. 213 </para> 214 <para> 215 The <function>set_user_data()</function> methods also support an 216 optional <function>destroy</function> callback. Client programs 217 can set the <function>destroy</function> callback and receive 218 notification from HarfBuzz whenever the object is destructed. 219 </para> 220 <para> 221 Finally, each <function>set_user_data()</function> method allows 222 the client program to set a <literal>replace</literal> Boolean 223 indicating whether or not the function call should replace any 224 existing <literal>user_data</literal> 225 associated with the specified key. 226 </para> 227 </section> 228 229 230 231 <section id="object-model-blobs"> 232 <title>Blobs</title> 233 <para> 234 While most of HarfBuzz's object types are specific to the 235 shaping process, <emphasis>blobs</emphasis> are somewhat 236 different. 237 </para> 238 <para> 239 Blobs are an abstraction designed to negotiate lifecycle and 240 permissions for raw pieces of data. For example, when you load 241 the raw font data into memory and want to pass it to HarfBuzz, 242 you do so in a <literal>hb_blob_t</literal> wrapper. 243 </para> 244 <para> 245 This allows you to take advantage of HarfBuzz's 246 reference-counting and <function>destroy</function> 247 callbacks. If you allocated the memory for the data using 248 <function>malloc()</function>, you would create the blob using 249 </para> 250 <programlisting language="C"> 251 hb_blob_create (data, length, HB_MEMORY_MODE_WRITABLE, data, free) 252 </programlisting> 253 <para> 254 That way, HarfBuzz will call <function>free()</function> on the 255 allocated memory whenever the blob drops its last reference and 256 is deconstructed. Consequently, the user code can stop worrying 257 about freeing memory and let the reference-counting machinery 258 take care of that. 259 </para> 260 <para> 261 Most of the time, blobs are read-only, facilitating their use in 262 immutable objects. 263 </para> 264 </section> 265 266</chapter> 267