usermanual-integration.xml 30 KB

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