13bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod/*
23bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * Copyright © 2011  Google, Inc.
33bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *
43bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
53bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *
63bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * Permission is hereby granted, without written agreement and without
73bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
83bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * software and its documentation for any purpose, provided that the
93bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * all copies of this software.
113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *
123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * DAMAGE.
173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *
183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
193bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
203bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod *
243bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod * Google Author(s): Behdad Esfahbod
253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod */
263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#ifndef OPTIONS_HH
283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#define OPTIONS_HH
293bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3017f40b7cad240eadeccdf23eb11da7ed52252ca2Behdad Esfahbod#include "hb-private.hh"
318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stdlib.h>
338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stddef.h>
348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <string.h>
358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stdio.h>
3605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod#include <assert.h>
378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <math.h>
388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <locale.h>
398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <errno.h>
408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <fcntl.h>
4152e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#ifdef HAVE_UNISTD_H
4252e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#include <unistd.h> /* for isatty() */
4352e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#endif
44e2aab4b5db88c368c11cee81368b9ad41399e585Behdad Esfahbod#if defined(_WIN32) || defined(__CYGWIN__)
45bc76449f51f20491a4540b4f240f5a3e0dcb20feBehdad Esfahbod#include <io.h> /* for setmode() under Windows */
468b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
478b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
488b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <hb.h>
49c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#ifdef HAVE_OT
50c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#include <hb-ot.h>
51c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#endif
528b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <glib.h>
538b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <glib/gprintf.h>
548b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
55c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod#if !GLIB_CHECK_VERSION (2, 22, 0)
56c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod# define g_mapped_file_unref g_mapped_file_free
57c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod#endif
58c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod
59ea5e8a02eb83ad19f3009b0008893f77ce113118Behdad Esfahbodvoid fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
608b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
61088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbodextern hb_bool_t debug;
62b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
63b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct option_group_t
64b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
65b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void add_options (struct option_parser_t *parser) = 0;
66b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
67b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void pre_parse (GError **error G_GNUC_UNUSED) {};
68b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void post_parse (GError **error G_GNUC_UNUSED) {};
69b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
70b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
71b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
72b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct option_parser_t
73b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
74b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_parser_t (const char *usage) {
75b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    memset (this, 0, sizeof (*this));
76b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    usage_str = usage;
77b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    context = g_option_context_new (usage);
782306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    to_free = g_ptr_array_new ();
79b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
80b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_main_options ();
81b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
82b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~option_parser_t (void) {
83b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_option_context_free (context);
84dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    g_ptr_array_foreach (to_free, (GFunc) g_free, nullptr);
852306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    g_ptr_array_free (to_free, TRUE);
86b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
87b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
88b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_main_options (void);
89b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
90b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_group (GOptionEntry   *entries,
91b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *name,
92b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *description,
93b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *help_description,
94b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  option_group_t *option_group);
95b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
962306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  void free_later (char *p) {
972306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    g_ptr_array_add (to_free, p);
982306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  }
992306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod
100b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void parse (int *argc, char ***argv);
101b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
102b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  G_GNUC_NORETURN void usage (void) {
103b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_printerr ("Usage: %s [OPTION...] %s\n", g_get_prgname (), usage_str);
104b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    exit (1);
105b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
106b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
1072306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  private:
108b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *usage_str;
109b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GOptionContext *context;
1102306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  GPtrArray *to_free;
111b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
112b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
113b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
114912c5ff80a255edb8145b9db69e2ed828f8eab5cBehdad Esfahbod#define DEFAULT_MARGIN 16
115109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod#define DEFAULT_FORE "#000000"
116109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod#define DEFAULT_BACK "#FFFFFF"
117cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod#define FONT_SIZE_UPEM 0x7FFFFFFF
118cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod#define FONT_SIZE_NONE 0
119109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
120b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct view_options_t : option_group_t
1213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
122b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  view_options_t (option_parser_t *parser) {
123b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    annotate = false;
124dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    fore = nullptr;
125dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    back = nullptr;
126b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    line_space = 0;
127109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN;
128b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
129b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
1303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
1313530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  ~view_options_t (void)
1323530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  {
1333530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (fore);
1343530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (back);
1353530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  }
1363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
137b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
138bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
139088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t annotate;
1403530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *fore;
1413530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *back;
1423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  double line_space;
1433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  struct margin_t {
1443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    double t, r, b, l;
1453bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } margin;
146b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
1473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
148109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
149b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct shape_options_t : option_group_t
1503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
151ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  shape_options_t (option_parser_t *parser)
152ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
153dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    direction = language = script = nullptr;
154407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod    bot = eot = preserve_default_ignorables = false;
155dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    features = nullptr;
156b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    num_features = 0;
157dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    shapers = nullptr;
15895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod    utf8_clusters = false;
159376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod    cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
16039b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod    normalize_glyphs = false;
161d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    verify = false;
16250067e280f381918b8e90b26df9e7bf20f98f0bdBehdad Esfahbod    num_iterations = 1;
163b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
164b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
1653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
166ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  ~shape_options_t (void)
167ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
1683530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (direction);
1693530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (language);
1703530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (script);
17190e312cb85df7a6dc350cb62138ab950790e3d15Behdad Esfahbod    free (features);
172ade7459ea7c75b4f33f7cfa43dd5bdfa0c18d6d5Behdad Esfahbod    g_strfreev (shapers);
17390e312cb85df7a6dc350cb62138ab950790e3d15Behdad Esfahbod  }
1743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
175b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
176bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
177ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  void setup_buffer (hb_buffer_t *buffer)
178ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
179516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_direction (buffer, hb_direction_from_string (direction, -1));
180516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_script (buffer, hb_script_from_string (script, -1));
181516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_language (buffer, hb_language_from_string (language, -1));
1824dc798de19c767b91fd3025c85593fa6809d1340Behdad Esfahbod    hb_buffer_set_flags (buffer, (hb_buffer_flags_t) (HB_BUFFER_FLAG_DEFAULT |
183407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (bot ? HB_BUFFER_FLAG_BOT : 0) |
184407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (eot ? HB_BUFFER_FLAG_EOT : 0) |
185407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0)));
186376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod    hb_buffer_set_cluster_level (buffer, cluster_level);
187c462b32dcb883a7aca066af24c4d28c7a2b7fa28Behdad Esfahbod    hb_buffer_guess_segment_properties (buffer);
1884f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod  }
1894f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod
19005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  static void copy_buffer_properties (hb_buffer_t *dst, hb_buffer_t *src)
19105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
19205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_segment_properties_t props;
19305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_get_segment_properties (src, &props);
19405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_segment_properties (dst, &props);
19505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_flags (dst, hb_buffer_get_flags (src));
19605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_cluster_level (dst, hb_buffer_get_cluster_level (src));
19705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
19805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
199321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod  void populate_buffer (hb_buffer_t *buffer, const char *text, int text_len,
200321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod			const char *text_before, const char *text_after)
201ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
2021172dc736280566426eb6dade1a886b2a0ca9aa4Behdad Esfahbod    hb_buffer_clear_contents (buffer);
203321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    if (text_before) {
204321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      unsigned int len = strlen (text_before);
205321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      hb_buffer_add_utf8 (buffer, text_before, len, len, 0);
206321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    }
207b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
208321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    if (text_after) {
209321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      hb_buffer_add_utf8 (buffer, text_after, -1, 0, 0);
210321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    }
211d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod
21295cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod    if (!utf8_clusters) {
21395cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      /* Reset cluster values to refer to Unicode character index
21495cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod       * instead of UTF-8 index. */
21595cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      unsigned int num_glyphs = hb_buffer_get_length (buffer);
216dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod      hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, nullptr);
21795cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      for (unsigned int i = 0; i < num_glyphs; i++)
21895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      {
21995cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod	info->cluster = i;
22095cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod	info++;
22195cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      }
222d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod    }
223d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod
2244f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod    setup_buffer (buffer);
225ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  }
226ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod
227dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod  hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer, const char **error=nullptr)
228ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
229dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    hb_buffer_t *text_buffer = nullptr;
23005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (verify)
23105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
23205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      text_buffer = hb_buffer_create ();
23305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (text_buffer, buffer, 0, -1);
23405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
23505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
236d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    if (!hb_shape_full (font, buffer, features, num_features, shapers))
237d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    {
238d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      if (error)
239d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod        *error = "all shapers failed.";
240d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      return false;
241d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    }
242d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
24339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod    if (normalize_glyphs)
24439b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod      hb_buffer_normalize_glyphs (buffer);
245d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
24605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (verify && !verify_buffer (buffer, text_buffer, font, error))
247d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      return false;
248d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
24905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (text_buffer)
25005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_destroy (text_buffer);
25105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
252d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    return true;
253d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  }
254d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
25505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  bool verify_buffer (hb_buffer_t  *buffer,
25605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod		      hb_buffer_t  *text_buffer,
25705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod		      hb_font_t    *font,
258dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod		      const char  **error=nullptr)
25905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
26005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (!verify_buffer_monotone (buffer, error))
26105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return false;
26205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (!verify_buffer_safe_to_break (buffer, text_buffer, font, error))
26305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return false;
26405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    return true;
26505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
26605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
267dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod  bool verify_buffer_monotone (hb_buffer_t *buffer, const char **error=nullptr)
268d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  {
269d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    /* Check that clusters are monotone. */
270d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
271d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
272d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    {
273d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
274d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
275d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      unsigned int num_glyphs;
276d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
277d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
278d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      for (unsigned int i = 1; i < num_glyphs; i++)
279d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	if (info[i-1].cluster != info[i].cluster &&
280d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	    (info[i-1].cluster < info[i].cluster) != is_forward)
281d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	{
282d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	  if (error)
283d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	    *error = "clusters are not monotone.";
284d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	  return false;
285d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	}
286d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    }
287d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
288d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    return true;
2894f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod  }
2904f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod
29105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  bool verify_buffer_safe_to_break (hb_buffer_t  *buffer,
29205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod				    hb_buffer_t  *text_buffer,
29305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod				    hb_font_t    *font,
294dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod				    const char  **error=nullptr)
29505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
29605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
29705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
29805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
29905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      /* Cannot perform this check without monotone clusters.
30005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod       * Then again, unsafe-to-break flag is much harder to use without
30105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod       * monotone clusters. */
30205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return true;
30305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
30405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
30505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    /* Check that breaking up shaping at safe-to-break is indeed safe. */
30605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
30705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_t *fragment = hb_buffer_create ();
30805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_t *reconstruction = hb_buffer_create ();
30905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    copy_buffer_properties (reconstruction, buffer);
31005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
31105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int num_glyphs;
31205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
31305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
31405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int num_chars;
31505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
31605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
31705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    /* Chop text and shape fragments. */
31805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
31905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int start = 0;
32005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int text_start = forward ? 0 : num_chars;
32105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int text_end = text_start;
32205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    for (unsigned int end = 1; end < num_glyphs + 1; end++)
32305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
32405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (end < num_glyphs &&
32505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  (info[end].cluster == info[end-1].cluster ||
32605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	   info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
32705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  continue;
32805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
32905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      /* Shape segment corresponding to glyphs start..end. */
33005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (end == num_glyphs)
33105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
33205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod        if (forward)
33305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  text_end = num_chars;
33405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	else
33505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  text_start = 0;
33605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
33705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      else
33805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
33905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	if (forward)
340b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	{
341b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  unsigned int cluster = info[end].cluster;
342b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  while (text_end < num_chars && text[text_end].cluster < cluster)
34305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	    text_end++;
344b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	}
34505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	else
346b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	{
347b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  unsigned int cluster = info[end - 1].cluster;
348b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  while (text_start && text[text_start - 1].cluster >= cluster)
34905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	    text_start--;
350b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	}
35105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
35205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      assert (text_start < text_end);
35305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
3547ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (0)
3557ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod	printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
3567ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
35705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_clear_contents (fragment);
35805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      copy_buffer_properties (fragment, buffer);
3597ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
3607ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      /* TODO: Add pre/post context text. */
3617ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
3627ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (0 < text_start)
3637ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
3647ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (text_end < num_chars)
3657ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
3667ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      hb_buffer_set_flags (fragment, flags);
3677ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
36805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (fragment, text_buffer, text_start, text_end);
36905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (!hb_shape_full (font, fragment, features, num_features, shapers))
37005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
37105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	if (error)
37205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  *error = "all shapers failed while shaping fragment.";
373a88e2a73f34067381a81577c3f60bc5c2a6f2eeaBehdad Esfahbod	hb_buffer_destroy (reconstruction);
374a88e2a73f34067381a81577c3f60bc5c2a6f2eeaBehdad Esfahbod	hb_buffer_destroy (fragment);
37505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	return false;
37605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
37705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (reconstruction, fragment, 0, -1);
37805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
37905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      start = end;
38005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (forward)
38105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	text_start = text_end;
38205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      else
38305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	text_end = text_start;
38405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
38505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
3867ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    bool ret = true;
387d03f11f246efec13e48fd68a9ce136db771b22bfBehdad Esfahbod    hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
3887ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    if (diff)
3897ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    {
3907ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (error)
3917ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod	*error = "Safe-to-break test failed.";
3927ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      ret = false;
39305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
39469d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      /* Return the reconstructed result instead so it can be inspected. */
39569d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      hb_buffer_set_length (buffer, 0);
39669d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      hb_buffer_append (buffer, reconstruction, 0, -1);
3977ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    }
39805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
39905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_destroy (reconstruction);
40005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_destroy (fragment);
40105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
4027ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    return ret;
40305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
40405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
405c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod  void shape_closure (const char *text, int text_len,
406c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod		      hb_font_t *font, hb_buffer_t *buffer,
407ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod		      hb_set_t *glyphs)
408ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
409c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_buffer_reset (buffer);
410c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
411c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    setup_buffer (buffer);
412c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_ot_shape_glyphs_closure (font, buffer, features, num_features, glyphs);
413c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod  }
414c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod
415407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  /* Buffer properties */
4163530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *direction;
4173530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *language;
4183530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *script;
419407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod
420407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  /* Buffer flags */
421407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t bot;
422407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t eot;
423407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t preserve_default_ignorables;
424407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod
4253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  hb_feature_t *features;
4263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  unsigned int num_features;
4273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char **shapers;
42895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod  hb_bool_t utf8_clusters;
429376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod  hb_buffer_cluster_level_t cluster_level;
43039b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod  hb_bool_t normalize_glyphs;
431d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  hb_bool_t verify;
43250067e280f381918b8e90b26df9e7bf20f98f0bdBehdad Esfahbod  unsigned int num_iterations;
433b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
4343bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
435109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
436b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct font_options_t : option_group_t
4373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
438cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  font_options_t (option_parser_t *parser,
439cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod		  int default_font_size_,
440111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod		  unsigned int subpixel_bits_)
441111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  {
442dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    variations = nullptr;
443111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod    num_variations = 0;
444cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    default_font_size = default_font_size_;
445cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    subpixel_bits = subpixel_bits_;
446dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    font_file = nullptr;
447b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    face_index = 0;
448cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    font_size_x = font_size_y = default_font_size;
449dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    font_funcs = nullptr;
450b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
451dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    font = nullptr;
452b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
453b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
454b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
455b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~font_options_t (void) {
4563530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (font_file);
457111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod    free (variations);
4583530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (font_funcs);
459b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_font_destroy (font);
4603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
4613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
462b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
463b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
464b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_font_t *get_font (void) const;
465bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
4663530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *font_file;
4673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  int face_index;
468111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  hb_variation_t *variations;
469111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  unsigned int num_variations;
470cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  int default_font_size;
471cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  unsigned int subpixel_bits;
472cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  mutable double font_size_x;
473cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  mutable double font_size_y;
4743530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *font_funcs;
4753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
476b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  private:
477b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  mutable hb_font_t *font;
478b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
479b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
480b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
481b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct text_options_t : option_group_t
482b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
483b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  text_options_t (option_parser_t *parser) {
484dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    text_before = nullptr;
485dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    text_after = nullptr;
486321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod
487dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    text = nullptr;
488dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    text_file = nullptr;
489b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
490dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    fp = nullptr;
491dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    gs = nullptr;
492dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    line = nullptr;
4933530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    line_len = (unsigned int) -1;
494b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
495b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
496b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
497b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~text_options_t (void) {
4983530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_before);
4993530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_after);
5003530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text);
5013530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_file);
50255aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (gs)
5030594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      g_string_free (gs, true);
50455aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (fp)
50555aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod      fclose (fp);
506b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
507b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
508b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
509b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
510b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void post_parse (GError **error G_GNUC_UNUSED) {
511b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (text && text_file)
512b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      g_set_error (error,
513b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		   G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
51430874b4819a99cc84fa39e794266685e1b8735d2Behdad Esfahbod		   "Only one of text and text-file can be set");
515b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  };
516b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
517b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *get_line (unsigned int *len);
518b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
5193530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_before;
5203530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_after;
521321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod
5223530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text;
5233530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_file;
524b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
525b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  private:
52655aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod  FILE *fp;
52755aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod  GString *gs;
5283530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *line;
5293530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  unsigned int line_len;
530b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
531b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
532b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct output_options_t : option_group_t
533b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
5349815a88111072aa51e78e258c5f660993b47d4dfBehdad Esfahbod  output_options_t (option_parser_t *parser,
535dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod		    const char **supported_formats_ = nullptr) {
536dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    output_file = nullptr;
537dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    output_format = nullptr;
5389815a88111072aa51e78e258c5f660993b47d4dfBehdad Esfahbod    supported_formats = supported_formats_;
5396bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod    explicit_output_format = false;
540b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
541dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod    fp = nullptr;
542f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
543b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
544b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
545f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  ~output_options_t (void) {
5463530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (output_file);
5473530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (output_format);
54855aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (fp)
549f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod      fclose (fp);
550f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  }
551b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
552b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
553b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
554b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void post_parse (GError **error G_GNUC_UNUSED)
555b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
5566bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod    if (output_format)
5576bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod      explicit_output_format = true;
5586bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod
559b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (output_file && !output_format) {
560b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      output_format = strrchr (output_file, '.');
561b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      if (output_format)
562e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod      {
563b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	  output_format++; /* skip the dot */
564e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod	  output_format = strdup (output_format);
565e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod      }
566b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    }
567b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
568f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod    if (output_file && 0 == strcmp (output_file, "-"))
569dbdbfe3d7b36613d893832dcb1884c756c20bfdaBehdad Esfahbod      output_file = nullptr; /* STDOUT */
570f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  }
571f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
572a75c1b125159f6cfb6b652a9ec40803f7c7e3f71Behdad Esfahbod  FILE *get_file_handle (void);
5733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
5743530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *output_file;
5753530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *output_format;
576ea5e8a02eb83ad19f3009b0008893f77ce113118Behdad Esfahbod  const char **supported_formats;
5776bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod  bool explicit_output_format;
578f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
579f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  mutable FILE *fp;
580b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
5813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
5828b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstruct format_options_t : option_group_t
5838b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
5848b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  format_options_t (option_parser_t *parser) {
5858b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_glyph_names = true;
5868b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_positions = true;
5878b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_clusters = true;
588cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod    show_text = false;
589cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod    show_unicode = false;
590cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod    show_line_num = false;
591fdd1770e006ca2d2973c049177ceda87a575e07fBehdad Esfahbod    show_extents = false;
59240bd7e9a1cf422b17f15d0f66547bde9098e6ef3Behdad Esfahbod    show_flags = false;
5936f38845d9c6852812eb1963a1fd7e5ec771e5ce3Behdad Esfahbod    trace = false;
5948b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
5958b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    add_options (parser);
5968b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
5978b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
5988b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  void add_options (option_parser_t *parser);
5998b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
600cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_unicode (hb_buffer_t  *buffer,
601cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			  GString      *gs);
602cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_glyphs (hb_buffer_t  *buffer,
603cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			 hb_font_t    *font,
604f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod			 hb_buffer_serialize_format_t format,
605f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod			 hb_buffer_serialize_flags_t flags,
606cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			 GString      *gs);
607cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_line_no (unsigned int  line_no,
608cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			  GString      *gs);
6095db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_buffer_of_text (hb_buffer_t  *buffer,
6105db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 unsigned int  line_no,
6115db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 const char   *text,
6125db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 unsigned int  text_len,
6135db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 hb_font_t    *font,
6145db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 GString      *gs);
6155db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_message (unsigned int  line_no,
616a9e52a1af4c039bc53090a9c1e4c1136fc542605Behdad Esfahbod			  const char   *type,
6175db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod			  const char   *msg,
6185db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod			  GString      *gs);
6195db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_buffer_of_glyphs (hb_buffer_t  *buffer,
6205db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   unsigned int  line_no,
6215db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   const char   *text,
6225db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   unsigned int  text_len,
6235db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   hb_font_t    *font,
624f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod				   hb_buffer_serialize_format_t output_format,
625f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod				   hb_buffer_serialize_flags_t format_flags,
6265db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   GString      *gs);
627cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod
6288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
629088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_glyph_names;
630088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_positions;
631088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_clusters;
632cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod  hb_bool_t show_text;
633cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod  hb_bool_t show_unicode;
634cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  hb_bool_t show_line_num;
635fdd1770e006ca2d2973c049177ceda87a575e07fBehdad Esfahbod  hb_bool_t show_extents;
63640bd7e9a1cf422b17f15d0f66547bde9098e6ef3Behdad Esfahbod  hb_bool_t show_flags;
6376f38845d9c6852812eb1963a1fd7e5ec771e5ce3Behdad Esfahbod  hb_bool_t trace;
6388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod};
6398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
640a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
641a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#if defined (_MSC_VER) && (_MSC_VER < 1800)
642a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
643a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#ifndef FLT_RADIX
644a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#define FLT_RADIX 2
645a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#endif
646a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
647a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan__inline long double scalbn (long double x, int exp)
648a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan{
649a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan  return x * (pow ((long double) FLT_RADIX, exp));
650a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan}
651a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
652a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan__inline float scalbnf (float x, int exp)
653a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan{
654a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan  return x * (pow ((float) FLT_RADIX, exp));
655a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan}
656a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#endif
6573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
6583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#endif
659