aboutsummaryrefslogtreecommitdiff
path: root/docs/usermanual-integration.xml
blob: 5d31ec2680cebb944bdf75843b4480b52eb292c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
<?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="integration">
  <title>Platform Integration Guide</title>
  <para>
    HarfBuzz was first developed for use with the GNOME and GTK
    software stack commonly found in desktop Linux
    distributions. Nevertheless, it can be used on other operating
    systems and platforms, from iOS and macOS to Windows. It can also
    be used with other application frameworks and components, such as
    Android, Qt, or application-specific widget libraries.
  </para>
  <para>
    This chapter will look at how HarfBuzz fits into a typical
    text-rendering pipeline, and will discuss the APIs available to
    integrate HarfBuzz with contemporary Linux, Mac, and Windows
    software. It will also show how HarfBuzz integrates with popular
    external libraries like FreeType and International Components for
    Unicode (ICU) and describe the HarfBuzz language bindings for
    Python.
  </para>
  <para>
    On a GNOME system, HarfBuzz is designed to tie in with several
    other common system libraries. The most common architecture uses
    Pango at the layer directly "above" HarfBuzz; Pango is responsible
    for text segmentation and for ensuring that each input
    <type>hb_buffer_t</type> passed to HarfBuzz for shaping contains
    Unicode code points that share the same segment properties
    (namely, direction, language, and script, but also higher-level
    properties like the active font, font style, and so on).
  </para>
  <para>
    The layer directly "below" HarfBuzz is typically FreeType, which
    is used to rasterize glyph outlines at the necessary optical size,
    hinting settings, and pixel resolution. FreeType provides APIs for
    accessing font and face information, so HarfBuzz includes
    functions to create <type>hb_face_t</type> and
    <type>hb_font_t</type> objects directly from FreeType
    objects. HarfBuzz can use FreeType's built-in functions for
    <structfield>font_funcs</structfield> vtable in an <type>hb_font_t</type>.
  </para>
  <para>
    FreeType's output is bitmaps of the rasterized glyphs; on a
    typical Linux system these will then be drawn by a graphics
    library like Cairo, but those details are beyond HarfBuzz's
    control. On the other hand, at the top end of the stack, Pango is
    part of the larger GNOME framework, and HarfBuzz does include APIs
    for working with key components of GNOME's higher-level libraries
    &mdash; most notably GLib.
  </para>
  <para>
    For other operating systems or application frameworks, the
    critical integration points are where HarfBuzz gets font and face
    information about the font used for shaping and where HarfBuzz
    gets Unicode data about the input-buffer code points.
  </para>
  <para>
    The font and face information is necessary for text shaping
    because HarfBuzz needs to retrieve the glyph indices for
    particular code points, and to know the extents and advances of
    glyphs. Note that, in an OpenType variable font, both of those
    types of information can change with different variation-axis
    settings.
  </para>
  <para>
    The Unicode information is necessary for shaping because the
    properties of a code point (such as its General Category (gc),
    Canonical Combining Class (ccc), and decomposition) can directly
    impact the shaping moves that HarfBuzz performs.
  </para>
  
  <section id="integration-glib">
    <title>GNOME integration, GLib, and GObject</title>
    <para>
      As mentioned in the preceding section, HarfBuzz offers
      integration APIs to help client programs using the
      GNOME and GTK framework commonly found in desktop Linux
      distributions. 
    </para>
    <para>
      GLib is the main utility library for GNOME applications. It
      provides basic data types and conversions, file abstractions,
      string manipulation, and macros, as well as facilities like
      memory allocation and the main event loop.
    </para>
    <para>
      Where text shaping is concerned, GLib provides several utilities
      that HarfBuzz can take advantage of, including a set of
      Unicode-data functions and a data type for script
      information. Both are useful when working with HarfBuzz
      buffers. To make use of them, you will need to include the
      <filename>hb-glib.h</filename> header file.
    </para>
    <para>
      GLib's <ulink
      url="https://developer.gnome.org/glib/stable/glib-Unicode-Manipulation.html">Unicode
      manipulation API</ulink> includes all the functionality
      necessary to retrieve Unicode data for the
      <structfield>unicode_funcs</structfield> structure of a HarfBuzz
      <type>hb_buffer_t</type>. 
    </para>
    <para>
      The function <function>hb_glib_get_unicode_funcs()</function>
      sets up a <type>hb_unicode_funcs_t</type> structure configured
      with the GLib Unicode functions and returns a pointer to it.
    </para>
    <para>
      You can attach this Unicode-functions structure to your buffer,
      and it will be ready for use with GLib:
    </para>
    <programlisting language="C">
      #include &lt;hb-glib.h&gt;
      ...
      hb_unicode_funcs_t *glibufunctions;
      glibufunctions = hb_glib_get_unicode_funcs();
      hb_buffer_set_unicode_funcs(buf, glibufunctions);
    </programlisting>
    <para>
      For script information, GLib uses the
      <type>GUnicodeScript</type> type. Like HarfBuzz's own
      <type>hb_script_t</type>, this data type is an enumeration
      of Unicode scripts, but text segments passed in from GLib code
      will be tagged with a <type>GUnicodeScript</type>. Therefore,
      when setting the script property on a <type>hb_buffer_t</type>,
      you will need to convert between the <type>GUnicodeScript</type>
      of the input provided by GLib and HarfBuzz's
      <type>hb_script_t</type> type.
    </para>
    <para>
      The <function>hb_glib_script_to_script()</function> function
      takes an <type>GUnicodeScript</type> script identifier as its
      sole argument and returns the corresponding <type>hb_script_t</type>.
      The <function>hb_glib_script_from_script()</function> does the
      reverse, taking an <type>hb_script_t</type> and returning the
      <type>GUnicodeScript</type> identifier for GLib.
    </para>
    <para>
      Finally, GLib also provides a reference-counted object type called <ulink
      url="https://developer.gnome.org/glib/stable/glib-Byte-Arrays.html#GBytes"><type>GBytes</type></ulink>
      that is used for accessing raw memory segments with the benefits
      of GLib's lifecycle management. HarfBuzz provides a
      <function>hb_glib_blob_create()</function> function that lets
      you create an <type>hb_blob_t</type> directly from a
      <type>GBytes</type> object. This function takes only the
      <type>GBytes</type> object as its input; HarfBuzz registers the
      GLib <function>destroy</function> callback automatically.
    </para>
    <para>
      The GNOME platform also features an object system called
      GObject. For HarfBuzz, the main advantage of GObject is a
      feature called <ulink
      url="https://gi.readthedocs.io/en/latest/">GObject
      Introspection</ulink>. This is a middleware facility that can be
      used to generate language bindings for C libraries. HarfBuzz uses it
      to build its Python bindings, which we will look at in a separate section.
    </para>
  </section>
  
  <section id="integration-freetype">
    <title>FreeType integration</title>
    <para>
      FreeType is the free-software font-rendering engine included in
      desktop Linux distributions, Android, ChromeOS, iOS, and multiple Unix
      operating systems, and used by cross-platform programs like
      Chrome, Java, and GhostScript. Used together, HarfBuzz can
      perform shaping on Unicode text segments, outputting the glyph
      IDs that FreeType should rasterize from the active font as well
      as the positions at which those glyphs should be drawn.
    </para>
    <para>
      HarfBuzz provides integration points with FreeType at the
      face-object and font-object level and for the font-functions
      virtual-method structure of a font object. To use the
      FreeType-integration API, include the
      <filename>hb-ft.h</filename> header.
    </para>
    <para>
      In a typical client program, you will create your
      <type>hb_face_t</type> face object and <type>hb_font_t</type>
      font object from a FreeType <type>FT_Face</type>. HarfBuzz
      provides a suite of functions for doing this.
    </para>
    <para>
      In the most common case, you will want to use
      <function>hb_ft_font_create_referenced()</function>, which
      creates both an <type>hb_face_t</type> face object and
      <type>hb_font_t</type> font object (linked to that face object),
      and provides lifecycle management.
    </para>
    <para>
      It is important to note,
      though, that while HarfBuzz makes a distinction between its face and
      font objects, FreeType's <type>FT_Face</type> does not. After
      you create your <type>FT_Face</type>, you must set its size
      parameter using <function>FT_Set_Char_Size()</function>, because
      an <type>hb_font_t</type> is defined as an instance of an
      <type>hb_face_t</type> with size specified.
    </para>
    <programlisting language="C">
      #include &lt;hb-ft.h&gt;
      ...
      FT_New_Face(ft_library, font_path, index, &amp;face);
      FT_Set_Char_Size(face, 0, 1000, 0, 0);
      hb_font_t *font = hb_ft_font_create(face);
    </programlisting>
    <para>
      <function>hb_ft_font_create_referenced()</function> is
      the recommended function for creating an <type>hb_face_t</type> face
      object. This function calls <function>FT_Reference_Face()</function>
      before using the <type>FT_Face</type> and calls 
      <function>FT_Done_Face()</function> when it is finished using the
      <type>FT_Face</type>. Consequently, your client program does not need
      to worry about destroying the <type>FT_Face</type> while HarfBuzz
      is still using it.
    </para>
    <para>
      Although <function>hb_ft_font_create_referenced()</function> is
      the recommended function, there is another variant for client code
      where special circumstances make it necessary. The simpler
      version of the function is <function>hb_ft_font_create()</function>,
      which takes an <type>FT_Face</type> and an optional destroy callback 
      as its arguments. Because <function>hb_ft_font_create()</function> 
      does not offer lifecycle management, however, your client code will
      be responsible for tracking references to the <type>FT_Face</type>
      objects and destroying them when they are no longer needed. If you
      do not have a valid reason for doing this, use
      <function>hb_ft_font_create_referenced()</function>. 
    </para>
    <para>
      After you have created your font object from your
      <type>FT_Face</type>, you can set or retrieve the
      <structfield>load_flags</structfield> of the
      <type>FT_Face</type> through the <type>hb_font_t</type>
      object. HarfBuzz provides
      <function>hb_ft_font_set_load_flags()</function> and
      <function>hb_ft_font_get_load_flags()</function> for this
      purpose. The ability to set the
      <structfield>load_flags</structfield> through the font object
      could be useful for enabling or disabling hinting, for example,
      or to activate vertical layout.
    </para>
    <para>
      HarfBuzz also provides a utility function called
      <function>hb_ft_font_has_changed()</function> that you should
      call whenever you have altered the properties of your underlying
      <type>FT_Face</type>, as well as a
      <function>hb_ft_get_face()</function> that you can call on an
      <type>hb_font_t</type> font object to fetch its underlying <type>FT_Face</type>.
    </para>
    <para>
      With an <type>hb_face_t</type> and <type>hb_font_t</type> both linked
      to your <type>FT_Face</type>, you will typically also want to
      use FreeType for the <structfield>font_funcs</structfield>
      vtable of your <type>hb_font_t</type>. As a reminder, this
      font-functions structure is the set of methods that HarfBuzz
      will use to fetch important information from the font, such as
      the advances and extents of individual glyphs. 
    </para>
    <para>
      All you need to do is call
    </para>
    <programlisting language="C">
      hb_ft_font_set_funcs(font);
    </programlisting>
    <para>
      and HarfBuzz will use FreeType for the font-functions in
      <literal>font</literal>. 
    </para>
    <para>
      As we noted above, an <type>hb_font_t</type> is derived from an
      <type>hb_face_t</type> with size (and, perhaps, other
      parameters, such as variation-axis coordinates)
      specified. Consequently, you can reuse an <type>hb_face_t</type>
      with several <type>hb_font_t</type> objects, and HarfBuzz
      provides functions to simplify this.
    </para>
    <para>
      The <function>hb_ft_face_create_referenced()</function>
      function creates just an <type>hb_face_t</type> from a FreeType
      <type>FT_Face</type> and, as with
      <function>hb_ft_font_create_referenced()</function> above,
      provides lifecycle management for the <type>FT_Face</type>.
    </para>
    <para>
      Similarly, there is an <function>hb_ft_face_create()</function>
      function variant that does not provide the lifecycle-management
      feature. As with the font-object case, if you use this version
      of the function, it will be your client code's respsonsibility
      to track usage of the <type>FT_Face</type> objects.
    </para>
    <para>
      A third variant of this function is
      <function>hb_ft_face_create_cached()</function>, which is the
      same as <function>hb_ft_face_create()</function> except that it
      also uses the <structfield>generic</structfield> field of the
      <type>FT_Face</type> structure to save a pointer to the newly
      created <type>hb_face_t</type>. Subsequently, function calls
      that pass the same <type>FT_Face</type> will get the same
      <type>hb_face_t</type> returned &mdash; and the
      <type>hb_face_t</type> will be correctly reference
      counted. Still, as with
      <function>hb_ft_face_create()</function>, your client code must
      track references to the <type>FT_Face</type> itself, and destroy
      it when it is unneeded.
    </para>
  </section>
  
  <section id="integration-uniscribe">
    <title>Uniscribe integration</title>
    <para>
      If your client program is running on Windows, HarfBuzz offers
      an additional API that can help integrate with Microsoft's
      Uniscribe engine and the Windows GDI.
    </para>
    <para>
      Overall, the Uniscribe API covers a broader set of typographic
      layout functions than HarfBuzz implements, but HarfBuzz's
      shaping API can serve as a drop-in replacement for Uniscribe's shaping
      functionality. In fact, one of HarfBuzz's design goals is to
      accurately reproduce the same output for shaping a given text
      segment that Uniscribe produces &mdash; even to the point of
      duplicating known shaping bugs or deviations from the
      specification &mdash; so you can be confident that your users'
      documents with their existing fonts will not be affected adversely by
      switching to HarfBuzz.
    </para>
    <para>
      At a basic level, HarfBuzz's <function>hb_shape()</function>
      function replaces both the <ulink url=""><function>ScriptShape()</function></ulink>
      and <ulink
      url="https://docs.microsoft.com/en-us/windows/desktop/api/Usp10/nf-usp10-scriptplace"><function>ScriptPlace()</function></ulink>
      functions from Uniscribe. 
    </para>
    <para>
      However, whereas <function>ScriptShape()</function> returns the
      glyphs and clusters for a shaped sequence and
      <function>ScriptPlace()</function> returns the advances and
      offsets for those glyphs, <function>hb_shape()</function>
      handles both. After <function>hb_shape()</function> shapes a
      buffer, the output glyph IDs and cluster IDs are returned as
      an array of <structname>hb_glyph_info_t</structname> structures, and the
      glyph advances and offsets are returned as an array of
      <structname>hb_glyph_position_t</structname> structures. 
    </para>
    <para>
      Your client program only needs to ensure that it converts
      correctly between HarfBuzz's low-level data types (such as
      <type>hb_position_t</type>) and Windows's corresponding types
      (such as <type>GOFFSET</type> and <type>ABC</type>). Be sure you
      read the <xref linkend="buffers-language-script-and-direction"
      /> 
      chapter for a full explanation of how HarfBuzz input buffers are
      used, and see <xref linkend="shaping-buffer-output" /> for the
      details of what <function>hb_shape()</function> returns in the
      output buffer when shaping is complete. 
    </para>
    <para>
      Although <function>hb_shape()</function> itself is functionally
      equivalent to Uniscribe's shaping routines, there are two
      additional HarfBuzz functions you may want to use to integrate
      the libraries in your code. Both are used to link HarfBuzz font
      objects to the equivalent Windows structures.
    </para>
    <para>
      The <function>hb_uniscribe_font_get_logfontw()</function>
      function takes a <type>hb_font_t</type> font object and returns
      a pointer to the <ulink
      url="https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/ns-wingdi-logfontw"><type>LOGFONTW</type></ulink>
      "logical font" that corresponds to it. A <type>LOGFONTW</type>
      structure holds font-wide attributes, including metrics, size,
      and style information.
    </para>
<!--      
     <para>
       In Uniscribe's model, the <type>SCRIPT_CACHE</type> holds the
       device context, including the logical font that the shaping
       functions apply.
       https://docs.microsoft.com/en-us/windows/desktop/Intl/script-cache
    </para>
-->
    <para>
      The <function>hb_uniscribe_font_get_hfont()</function> function
      also takes a <type>hb_font_t</type> font object, but it returns
      an <type>HFONT</type> &mdash; a handle to the underlying logical
      font &mdash; instead.
    </para>
    <para>
      <type>LOGFONTW</type>s and <type>HFONT</type>s are both needed
      by other Uniscribe functions.
    </para>
    <para>
      As a final note, you may notice a reference to an optional
      <literal>uniscribe</literal> shaper back-end in the <xref
      linkend="configuration" /> section of the HarfBuzz manual. This
      option is not a Uniscribe-integration facility.
    </para>
    <para>
      Instead, it is a internal code path used in the
      <command>hb-shape</command> command-line utility, which hands
      shaping functionality over to Uniscribe entirely, when run on a
      Windows system. That allows testing HarfBuzz's native output
      against the Uniscribe engine, for tracking compatibility and
      debugging.
    </para>
    <para>
      Because this back-end is only used when testing HarfBuzz
      functionality, it is disabled by default when building the
      HarfBuzz binaries.
    </para>
  </section>
   
  <section id="integration-coretext">
    <title>Core Text integration</title>
    <para>
      If your client program is running on macOS or iOS, HarfBuzz offers
      an additional API that can help integrate with Apple's
      Core Text engine and the underlying Core Graphics
      framework. HarfBuzz does not attempt to offer the same
      drop-in-replacement functionality for Core Text that it strives
      for with Uniscribe on Windows, but you can still use HarfBuzz
      to perform text shaping in native macOS and iOS applications.
    </para>
    <para>
      Note, though, that if your interest is just in using fonts that
      contain Apple Advanced Typography (AAT) features, then you do
      not need to add Core Text integration. HarfBuzz natively
      supports AAT features and will shape AAT fonts (on any platform)
      automatically, without requiring additional work on your
      part. This includes support for AAT-specific TrueType tables
      such as <literal>mort</literal>, <literal>morx</literal>, and
      <literal>kerx</literal>, which AAT fonts use instead of
      <literal>GSUB</literal> and <literal>GPOS</literal>.
    </para>
    <para>
      On a macOS or iOS system, the primary integration points offered
      by HarfBuzz are for face objects and font objects. 
    </para>
    <para>
      The Apple APIs offer a pair of data structures that map well to
      HarfBuzz's face and font objects. The Core Graphics API, which
      is slightly lower-level than Core Text, provides
      <ulink url="https://developer.apple.com/documentation/coregraphics/cgfontref"><type>CGFontRef</type></ulink>, which enables access to typeface
      properties, but does not include size information. Core Text's
      <ulink url="https://developer.apple.com/documentation/coretext/ctfont-q6r"><type>CTFontRef</type></ulink> is analogous to a HarfBuzz font object,
      with all of the properties required to render text at a specific
      size and configuration.
      Consequently, a HarfBuzz <type>hb_font_t</type> font object can
      be hooked up to a Core Text <type>CTFontRef</type>, and a HarfBuzz
      <type>hb_face_t</type> face object can be hooked up to a
      <type>CGFontRef</type>.
    </para>
    <para>
      You can create a <type>hb_face_t</type> from a
      <type>CGFontRef</type> by using the
      <function>hb_coretext_face_create()</function>. Subsequently,
      you can retrieve the <type>CGFontRef</type> from a
      <type>hb_face_t</type> with <function>hb_coretext_face_get_cg_font()</function>.
    </para>
    <para>
      Likewise, you create a <type>hb_font_t</type> from a
      <type>CTFontRef</type> by calling
      <function>hb_coretext_font_create()</function>, and you can
      fetch the associated <type>CTFontRef</type> from a
      <type>hb_font_t</type> font object with
      <function>hb_coretext_face_get_ct_font()</function>. 
    </para>
    <para>
      HarfBuzz also offers a <function>hb_font_set_ptem()</function>
      that you an use to set the nominal point size on any
      <type>hb_font_t</type> font object. Core Text uses this value to
      implement optical scaling. 
    </para>
    <para>
      When integrating your client code with Core Text, it is
      important to recognize that Core Text <literal>points</literal>
      are not typographic points (standardized at 72 per inch) as the
      term is used elsewhere in OpenType. Instead, Core Text points
      are CSS points, which are standardized at 96 per inch.
    </para>
    <para>
      HarfBuzz's font functions take this distinction into account,
      but it can be an easy detail to miss in cross-platform
      code. 
    </para>
    <para>
      As a final note, you may notice a reference to an optional
      <literal>coretext</literal> shaper back-end in the <xref
      linkend="configuration" /> section of the HarfBuzz manual. This
      option is not a Core Text-integration facility.
    </para>
    <para>
      Instead, it is a internal code path used in the
      <command>hb-shape</command> command-line utility, which hands
      shaping functionality over to Core Text entirely, when run on a
      macOS system. That allows testing HarfBuzz's native output
      against the Core Text engine, for tracking compatibility and debugging.
    </para>
    <para>
      Because this back-end is only used when testing HarfBuzz
      functionality, it is disabled by default when building the
      HarfBuzz binaries.
    </para>
  </section>
  
  <section id="integration-icu">
    <title>ICU integration</title>
    <para>
      Although HarfBuzz includes its own Unicode-data functions, it
      also provides integration APIs for using the International
      Components for Unicode (ICU) library as a source of Unicode data
      on any supported platform.
    </para>
    <para>
      The principal integration point with ICU is the
      <type>hb_unicode_funcs_t</type> Unicode-functions structure
      attached to a buffer. This structure holds the virtual methods
      used for retrieving Unicode character properties, such as
      General Category, Script, Combining Class, decomposition
      mappings, and mirroring information.
    </para>
    <para>
      To use ICU in your client program, you need to call
      <function>hb_icu_get_unicode_funcs()</function>, which creates a
      Unicode-functions structure populated with the ICU function for
      each included method. Subsequently, you can attach the
      Unicode-functions structure to your buffer:
    </para>
    <programlisting language="C">
      hb_unicode_funcs_t *icufunctions;
      icufunctions = hb_icu_get_unicode_funcs();
      hb_buffer_set_unicode_funcs(buf, icufunctions);
    </programlisting>
    <para>
      and ICU will be used for Unicode-data access.
    </para>
    <para>
      HarfBuzz also supplies a pair of functions
      (<function>hb_icu_script_from_script()</function> and
      <function>hb_icu_script_to_script()</function>) for converting
      between ICU's and HarfBuzz's internal enumerations of Unicode
      scripts. The <function>hb_icu_script_from_script()</function>
      function converts from a HarfBuzz <type>hb_script_t</type> to an
      ICU <type>UScriptCode</type>. The
      <function>hb_icu_script_to_script()</function> function does the
      reverse: converting from a <type>UScriptCode</type> identifier
      to a <type>hb_script_t</type>.
    </para>
    <para>
      By default, HarfBuzz's ICU support is built as a separate shared
      library (<filename class="libraryfile">libharfbuzz-icu.so</filename>)
      when compiling HarfBuzz from source. This allows client programs
      that do not need ICU to link against HarfBuzz without unnecessarily
      adding ICU as a dependency. You can also build HarfBuzz with ICU
      support built directly into the main HarfBuzz shared library
      (<filename class="libraryfile">libharfbuzz.so</filename>),
      by specifying the <literal>--with-icu=builtin</literal>
      compile-time option.
    </para>

  </section>
  
  <section id="integration-python">
    <title>Python bindings</title>
    <para>
      As noted in the <xref linkend="integration-glib" /> section,
      HarfBuzz uses a feature called <ulink
      url="https://wiki.gnome.org/Projects/GObjectIntrospection">GObject
      Introspection</ulink> (GI) to provide bindings for Python.
    </para>
    <para>
      At compile time, the GI scanner analyzes the HarfBuzz C source
      and builds metadata objects connecting the language bindings to
      the C library. Your Python code can then use the HarfBuzz binary
      through its Python interface.
    </para>
    <para>
      HarfBuzz's Python bindings support Python 2 and Python 3. To use
      them, you will need to have the <literal>pygobject</literal>
      package installed. Then you should import
      <literal>HarfBuzz</literal> from
      <literal>gi.repository</literal>: 
    </para>
    <programlisting language="Python">
      from gi.repository import HarfBuzz
    </programlisting>
    <para>
      and you can call HarfBuzz functions from Python. Sample code can
      be found in the <filename>sample.py</filename> script in the
      HarfBuzz <filename>src</filename> directory.
    </para>
    <para>
      Do note, however, that the Python API is subject to change
      without advance notice. GI allows the bindings to be
      automatically updated, which is one of its advantages, but you
      may need to update your Python code.
    </para>
  </section>
  
</chapter>