options.hh revision d03f11f246efec13e48fd68a9ce136db771b22bf
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
303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#ifdef HAVE_CONFIG_H
328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include "config.h"
338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stdlib.h>
368b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stddef.h>
378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <string.h>
388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <stdio.h>
3905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod#include <assert.h>
408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <math.h>
418b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <locale.h>
428b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <errno.h>
438b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <fcntl.h>
4452e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#ifdef HAVE_UNISTD_H
4552e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#include <unistd.h> /* for isatty() */
4652e7b1424a3613122e9ca30879298df42733acdaBehdad Esfahbod#endif
47e2aab4b5db88c368c11cee81368b9ad41399e585Behdad Esfahbod#if defined(_WIN32) || defined(__CYGWIN__)
48bc76449f51f20491a4540b4f240f5a3e0dcb20feBehdad Esfahbod#include <io.h> /* for setmode() under Windows */
498b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
508b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
518b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <hb.h>
52c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#ifdef HAVE_OT
53c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#include <hb-ot.h>
54c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod#endif
558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <glib.h>
568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <glib/gprintf.h>
578b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
58c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod#if !GLIB_CHECK_VERSION (2, 22, 0)
59c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod# define g_mapped_file_unref g_mapped_file_free
60c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod#endif
61c2bc818706df56022c8bb922df2b741cb120f7e4Behdad Esfahbod
628650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod
638650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod/* A few macros copied from hb-private.hh. */
648650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod
658650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#if __GNUC__ >= 4
668650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define HB_UNUSED	__attribute__((unused))
678650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#else
688650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define HB_UNUSED
698650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#endif
708650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod
7169b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod#undef MIN
7269b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbodtemplate <typename Type> static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
7369b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod
7469b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod#undef MAX
7569b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbodtemplate <typename Type> static inline Type MAX (const Type &a, const Type &b) { return a > b ? a : b; }
7669b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod
778650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#undef  ARRAY_LENGTH
788650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbodtemplate <typename Type, unsigned int n>
798650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbodstatic inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
808650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod/* A const version, but does not detect erratically being called on pointers. */
818650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
828650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod
838650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define _ASSERT_STATIC1(_line, _cond)	HB_UNUSED typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
848650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define _ASSERT_STATIC0(_line, _cond)	_ASSERT_STATIC1 (_line, (_cond))
858650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod#define ASSERT_STATIC(_cond)		_ASSERT_STATIC0 (__LINE__, (_cond))
868650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod
8769b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod
88ea5e8a02eb83ad19f3009b0008893f77ce113118Behdad Esfahbodvoid fail (hb_bool_t suggest_help, const char *format, ...) G_GNUC_NORETURN G_GNUC_PRINTF (2, 3);
898b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
908b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
91088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbodextern hb_bool_t debug;
92b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
93b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct option_group_t
94b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
95b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void add_options (struct option_parser_t *parser) = 0;
96b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
97b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void pre_parse (GError **error G_GNUC_UNUSED) {};
98b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  virtual void post_parse (GError **error G_GNUC_UNUSED) {};
99b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
100b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
101b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
102b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct option_parser_t
103b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
104b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_parser_t (const char *usage) {
105b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    memset (this, 0, sizeof (*this));
106b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    usage_str = usage;
107b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    context = g_option_context_new (usage);
1082306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    to_free = g_ptr_array_new ();
109b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
110b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_main_options ();
111b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
112b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~option_parser_t (void) {
113b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_option_context_free (context);
1142306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    g_ptr_array_foreach (to_free, (GFunc) g_free, NULL);
1152306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    g_ptr_array_free (to_free, TRUE);
116b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
117b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
118b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_main_options (void);
119b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
120b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_group (GOptionEntry   *entries,
121b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *name,
122b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *description,
123b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  const gchar    *help_description,
124b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		  option_group_t *option_group);
125b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
1262306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  void free_later (char *p) {
1272306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod    g_ptr_array_add (to_free, p);
1282306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  }
1292306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod
130b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void parse (int *argc, char ***argv);
131b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
132b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  G_GNUC_NORETURN void usage (void) {
133b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_printerr ("Usage: %s [OPTION...] %s\n", g_get_prgname (), usage_str);
134b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    exit (1);
135b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
136b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
1372306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  private:
138b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *usage_str;
139b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GOptionContext *context;
1402306ad46dce1c53b0b1bfabdc04d70e3b99eabb7Behdad Esfahbod  GPtrArray *to_free;
141b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
142b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
143b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
144912c5ff80a255edb8145b9db69e2ed828f8eab5cBehdad Esfahbod#define DEFAULT_MARGIN 16
145109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod#define DEFAULT_FORE "#000000"
146109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod#define DEFAULT_BACK "#FFFFFF"
147cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod#define FONT_SIZE_UPEM 0x7FFFFFFF
148cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod#define FONT_SIZE_NONE 0
149109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
150b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct view_options_t : option_group_t
1513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
152b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  view_options_t (option_parser_t *parser) {
153b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    annotate = false;
1543530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    fore = NULL;
1553530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    back = NULL;
156b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    line_space = 0;
157109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    margin.t = margin.r = margin.b = margin.l = DEFAULT_MARGIN;
158b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
159b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
1603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
1613530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  ~view_options_t (void)
1623530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  {
1633530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (fore);
1643530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (back);
1653530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  }
1663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
167b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
168bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
169088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t annotate;
1703530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *fore;
1713530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *back;
1723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  double line_space;
1733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  struct margin_t {
1743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    double t, r, b, l;
1753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } margin;
176b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
1773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
178109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
179b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct shape_options_t : option_group_t
1803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
181ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  shape_options_t (option_parser_t *parser)
182ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
183b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    direction = language = script = NULL;
184407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod    bot = eot = preserve_default_ignorables = false;
185b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    features = NULL;
186b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    num_features = 0;
187b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    shapers = NULL;
18895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod    utf8_clusters = false;
189376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod    cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
19039b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod    normalize_glyphs = false;
191d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    verify = false;
19250067e280f381918b8e90b26df9e7bf20f98f0bdBehdad Esfahbod    num_iterations = 1;
193b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
194b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
1953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
196ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  ~shape_options_t (void)
197ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
1983530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (direction);
1993530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (language);
2003530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (script);
20190e312cb85df7a6dc350cb62138ab950790e3d15Behdad Esfahbod    free (features);
202ade7459ea7c75b4f33f7cfa43dd5bdfa0c18d6d5Behdad Esfahbod    g_strfreev (shapers);
20390e312cb85df7a6dc350cb62138ab950790e3d15Behdad Esfahbod  }
2043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
205b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
206bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
207ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  void setup_buffer (hb_buffer_t *buffer)
208ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
209516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_direction (buffer, hb_direction_from_string (direction, -1));
210516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_script (buffer, hb_script_from_string (script, -1));
211516857eb51bbb79ff4adf44e3fefbf460f9ee8f8Behdad Esfahbod    hb_buffer_set_language (buffer, hb_language_from_string (language, -1));
2124dc798de19c767b91fd3025c85593fa6809d1340Behdad Esfahbod    hb_buffer_set_flags (buffer, (hb_buffer_flags_t) (HB_BUFFER_FLAG_DEFAULT |
213407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (bot ? HB_BUFFER_FLAG_BOT : 0) |
214407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (eot ? HB_BUFFER_FLAG_EOT : 0) |
215407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod			 (preserve_default_ignorables ? HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES : 0)));
216376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod    hb_buffer_set_cluster_level (buffer, cluster_level);
217c462b32dcb883a7aca066af24c4d28c7a2b7fa28Behdad Esfahbod    hb_buffer_guess_segment_properties (buffer);
2184f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod  }
2194f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod
22005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  static void copy_buffer_properties (hb_buffer_t *dst, hb_buffer_t *src)
22105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
22205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_segment_properties_t props;
22305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_get_segment_properties (src, &props);
22405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_segment_properties (dst, &props);
22505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_flags (dst, hb_buffer_get_flags (src));
22605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_set_cluster_level (dst, hb_buffer_get_cluster_level (src));
22705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
22805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
229321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod  void populate_buffer (hb_buffer_t *buffer, const char *text, int text_len,
230321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod			const char *text_before, const char *text_after)
231ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
2321172dc736280566426eb6dade1a886b2a0ca9aa4Behdad Esfahbod    hb_buffer_clear_contents (buffer);
233321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    if (text_before) {
234321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      unsigned int len = strlen (text_before);
235321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      hb_buffer_add_utf8 (buffer, text_before, len, len, 0);
236321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    }
237b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
238321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    if (text_after) {
239321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod      hb_buffer_add_utf8 (buffer, text_after, -1, 0, 0);
240321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    }
241d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod
24295cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod    if (!utf8_clusters) {
24395cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      /* Reset cluster values to refer to Unicode character index
24495cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod       * instead of UTF-8 index. */
24595cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      unsigned int num_glyphs = hb_buffer_get_length (buffer);
24695cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
24795cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      for (unsigned int i = 0; i < num_glyphs; i++)
24895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      {
24995cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod	info->cluster = i;
25095cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod	info++;
25195cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod      }
252d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod    }
253d5300241680844f5625f32792f7dd7181ed05f9bBehdad Esfahbod
2544f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod    setup_buffer (buffer);
255ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  }
256ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod
257d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer, const char **error=NULL)
258ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
25905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_t *text_buffer = NULL;
26005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (verify)
26105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
26205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      text_buffer = hb_buffer_create ();
26305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (text_buffer, buffer, 0, -1);
26405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
26505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
266d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    if (!hb_shape_full (font, buffer, features, num_features, shapers))
267d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    {
268d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      if (error)
269d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod        *error = "all shapers failed.";
270d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      return false;
271d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    }
272d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
27339b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod    if (normalize_glyphs)
27439b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod      hb_buffer_normalize_glyphs (buffer);
275d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
27605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (verify && !verify_buffer (buffer, text_buffer, font, error))
277d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      return false;
278d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
27905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (text_buffer)
28005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_destroy (text_buffer);
28105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
282d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    return true;
283d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  }
284d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
28505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  bool verify_buffer (hb_buffer_t  *buffer,
28605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod		      hb_buffer_t  *text_buffer,
28705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod		      hb_font_t    *font,
28805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod		      const char  **error=NULL)
28905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
29005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (!verify_buffer_monotone (buffer, error))
29105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return false;
29205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (!verify_buffer_safe_to_break (buffer, text_buffer, font, error))
29305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return false;
29405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    return true;
29505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
29605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
29705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  bool verify_buffer_monotone (hb_buffer_t *buffer, const char **error=NULL)
298d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  {
299d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    /* Check that clusters are monotone. */
300d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
301d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
302d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    {
303d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
304d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
305d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      unsigned int num_glyphs;
306d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
307d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
308d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod      for (unsigned int i = 1; i < num_glyphs; i++)
309d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	if (info[i-1].cluster != info[i].cluster &&
310d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	    (info[i-1].cluster < info[i].cluster) != is_forward)
311d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	{
312d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	  if (error)
313d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	    *error = "clusters are not monotone.";
314d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	  return false;
315d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod	}
316d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    }
317d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod
318d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod    return true;
3194f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod  }
3204f4b114a5592c2f5d128ee795f159b438ad97829Behdad Esfahbod
32105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  bool verify_buffer_safe_to_break (hb_buffer_t  *buffer,
32205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod				    hb_buffer_t  *text_buffer,
32305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod				    hb_font_t    *font,
32405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod				    const char  **error=NULL)
32505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  {
32605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    if (cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
32705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
32805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
32905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      /* Cannot perform this check without monotone clusters.
33005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod       * Then again, unsafe-to-break flag is much harder to use without
33105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod       * monotone clusters. */
33205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      return true;
33305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
33405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
33505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    /* Check that breaking up shaping at safe-to-break is indeed safe. */
33605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
33705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_t *fragment = hb_buffer_create ();
33805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_t *reconstruction = hb_buffer_create ();
33905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    copy_buffer_properties (reconstruction, buffer);
34005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
34105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int num_glyphs;
34205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
34305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
34405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int num_chars;
34505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
34605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
34705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    /* Chop text and shape fragments. */
34805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
34905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int start = 0;
35005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int text_start = forward ? 0 : num_chars;
35105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    unsigned int text_end = text_start;
35205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    for (unsigned int end = 1; end < num_glyphs + 1; end++)
35305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    {
35405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (end < num_glyphs &&
35505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  (info[end].cluster == info[end-1].cluster ||
35605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	   info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
35705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  continue;
35805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
35905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      /* Shape segment corresponding to glyphs start..end. */
36005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (end == num_glyphs)
36105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
36205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod        if (forward)
36305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  text_end = num_chars;
36405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	else
36505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  text_start = 0;
36605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
36705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      else
36805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
36905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	if (forward)
370b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	{
371b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  unsigned int cluster = info[end].cluster;
372b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  while (text_end < num_chars && text[text_end].cluster < cluster)
37305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	    text_end++;
374b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	}
37505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	else
376b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	{
377b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  unsigned int cluster = info[end - 1].cluster;
378b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	  while (text_start && text[text_start - 1].cluster >= cluster)
37905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	    text_start--;
380b262ebcc9c9539076d17751e9bae06a8fd5001ffBehdad Esfahbod	}
38105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
38205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      assert (text_start < text_end);
38305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
3847ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (0)
3857ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod	printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
3867ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
38705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_clear_contents (fragment);
38805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      copy_buffer_properties (fragment, buffer);
3897ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
3907ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      /* TODO: Add pre/post context text. */
3917ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
3927ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (0 < text_start)
3937ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
3947ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (text_end < num_chars)
3957ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod        flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
3967ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      hb_buffer_set_flags (fragment, flags);
3977ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod
39805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (fragment, text_buffer, text_start, text_end);
39905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (!hb_shape_full (font, fragment, features, num_features, shapers))
40005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      {
40105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	if (error)
40205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	  *error = "all shapers failed while shaping fragment.";
403a88e2a73f34067381a81577c3f60bc5c2a6f2eeaBehdad Esfahbod	hb_buffer_destroy (reconstruction);
404a88e2a73f34067381a81577c3f60bc5c2a6f2eeaBehdad Esfahbod	hb_buffer_destroy (fragment);
40505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	return false;
40605fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      }
40705fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      hb_buffer_append (reconstruction, fragment, 0, -1);
40805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
40905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      start = end;
41005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      if (forward)
41105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	text_start = text_end;
41205fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod      else
41305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod	text_end = text_start;
41405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    }
41505fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
4167ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    bool ret = true;
417d03f11f246efec13e48fd68a9ce136db771b22bfBehdad Esfahbod    hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
4187ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    if (diff)
4197ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    {
4207ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      if (error)
4217ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod	*error = "Safe-to-break test failed.";
4227ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod      ret = false;
42305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
42469d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      /* Return the reconstructed result instead so it can be inspected. */
42569d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      hb_buffer_set_length (buffer, 0);
42669d701b02e5ebc3597b0d0576dbab8e1ece51944Behdad Esfahbod      hb_buffer_append (buffer, reconstruction, 0, -1);
4277ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    }
42805fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
42905fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_destroy (reconstruction);
43005fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod    hb_buffer_destroy (fragment);
43105fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
4327ea10c35a34c894e87ee6576d6d4ba3e78535a27Behdad Esfahbod    return ret;
43305fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod  }
43405fabbd03eae7b84ebbce7abbdc55c1d67ceacf9Behdad Esfahbod
435c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod  void shape_closure (const char *text, int text_len,
436c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod		      hb_font_t *font, hb_buffer_t *buffer,
437ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod		      hb_set_t *glyphs)
438ae62166519291057316a9d15cea3f1570fcb5eafBehdad Esfahbod  {
439c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_buffer_reset (buffer);
440c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_buffer_add_utf8 (buffer, text, text_len, 0, text_len);
441c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    setup_buffer (buffer);
442c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod    hb_ot_shape_glyphs_closure (font, buffer, features, num_features, glyphs);
443c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod  }
444c87b317f0eb118e67134e8e419a6d65e0fa40d30Behdad Esfahbod
445407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  /* Buffer properties */
4463530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *direction;
4473530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *language;
4483530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *script;
449407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod
450407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  /* Buffer flags */
451407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t bot;
452407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t eot;
453407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod  hb_bool_t preserve_default_ignorables;
454407f80d62589774f845ef1a6a0a7d841b09d57c6Behdad Esfahbod
4553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  hb_feature_t *features;
4563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  unsigned int num_features;
4573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char **shapers;
45895cefdf96efe43a44133aa8a186155cf4e63e2b7Behdad Esfahbod  hb_bool_t utf8_clusters;
459376d587f36b4ff10342ee6ca3bacd73532ea44c8Behdad Esfahbod  hb_buffer_cluster_level_t cluster_level;
46039b17837b4064d59c18cebb49c1c0b5b8cc0c117Behdad Esfahbod  hb_bool_t normalize_glyphs;
461d2052278f24b3279503d5fa215a7834c2d21f91cBehdad Esfahbod  hb_bool_t verify;
46250067e280f381918b8e90b26df9e7bf20f98f0bdBehdad Esfahbod  unsigned int num_iterations;
463b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
4643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
465109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod
466b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct font_options_t : option_group_t
4673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
468cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  font_options_t (option_parser_t *parser,
469cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod		  int default_font_size_,
470111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod		  unsigned int subpixel_bits_)
471111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  {
472111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod    variations = NULL;
473111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod    num_variations = 0;
474cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    default_font_size = default_font_size_;
475cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    subpixel_bits = subpixel_bits_;
476b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    font_file = NULL;
477b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    face_index = 0;
478cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod    font_size_x = font_size_y = default_font_size;
4798650def73500204b79c651f58b1be3f94a41973dBehdad Esfahbod    font_funcs = NULL;
480b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
481b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    font = NULL;
482b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
483b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
484b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
485b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~font_options_t (void) {
4863530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (font_file);
487111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod    free (variations);
4883530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (font_funcs);
489b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_font_destroy (font);
4903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
4913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
492b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
493b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
494b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_font_t *get_font (void) const;
495bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod
4963530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *font_file;
4973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  int face_index;
498111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  hb_variation_t *variations;
499111f3e55178f7cd5a8ae4e8ae111cb48aea4acb5Behdad Esfahbod  unsigned int num_variations;
500cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  int default_font_size;
501cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  unsigned int subpixel_bits;
502cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  mutable double font_size_x;
503cd4eb96abb90a84b42e9b288e39bad759e4411a0Behdad Esfahbod  mutable double font_size_y;
5043530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *font_funcs;
5053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
506b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  private:
507b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  mutable hb_font_t *font;
508b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
509b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
510b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
511b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct text_options_t : option_group_t
512b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
513b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  text_options_t (option_parser_t *parser) {
514321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    text_before = NULL;
515321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod    text_after = NULL;
516321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod
517b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text = NULL;
518b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text_file = NULL;
519b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
52055aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    fp = NULL;
52155aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    gs = NULL;
5223530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    line = NULL;
5233530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    line_len = (unsigned int) -1;
524b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
525b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
526b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
527b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  ~text_options_t (void) {
5283530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_before);
5293530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_after);
5303530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text);
5313530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (text_file);
53255aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (gs)
5330594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod      g_string_free (gs, true);
53455aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (fp)
53555aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod      fclose (fp);
536b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
537b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
538b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
539b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
540b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void post_parse (GError **error G_GNUC_UNUSED) {
541b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (text && text_file)
542b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      g_set_error (error,
543b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		   G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
54430874b4819a99cc84fa39e794266685e1b8735d2Behdad Esfahbod		   "Only one of text and text-file can be set");
545b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  };
546b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
547b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *get_line (unsigned int *len);
548b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
5493530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_before;
5503530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_after;
551321f73c16efa0730c96e001d65268f4927a0f735Behdad Esfahbod
5523530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text;
5533530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *text_file;
554b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
555b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  private:
55655aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod  FILE *fp;
55755aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod  GString *gs;
5583530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *line;
5593530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  unsigned int line_len;
560b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
561b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
562b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct output_options_t : option_group_t
563b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
5649815a88111072aa51e78e258c5f660993b47d4dfBehdad Esfahbod  output_options_t (option_parser_t *parser,
565ea5e8a02eb83ad19f3009b0008893f77ce113118Behdad Esfahbod		    const char **supported_formats_ = NULL) {
566b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    output_file = NULL;
567b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    output_format = NULL;
5689815a88111072aa51e78e258c5f660993b47d4dfBehdad Esfahbod    supported_formats = supported_formats_;
5696bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod    explicit_output_format = false;
570b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
571f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod    fp = NULL;
572f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
573b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    add_options (parser);
574b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
575f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  ~output_options_t (void) {
5763530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (output_file);
5773530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod    g_free (output_format);
57855aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahbod    if (fp)
579f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod      fclose (fp);
580f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  }
581b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
582b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void add_options (option_parser_t *parser);
583b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
584b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  void post_parse (GError **error G_GNUC_UNUSED)
585b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
5866bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod    if (output_format)
5876bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod      explicit_output_format = true;
5886bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod
589b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (output_file && !output_format) {
590b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      output_format = strrchr (output_file, '.');
591b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      if (output_format)
592e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod      {
593b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	  output_format++; /* skip the dot */
594e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod	  output_format = strdup (output_format);
595e97835ad43f5c68e8cb29599246cae0f4461d663Behdad Esfahbod      }
596b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    }
597b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
598f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod    if (output_file && 0 == strcmp (output_file, "-"))
599f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod      output_file = NULL; /* STDOUT */
600f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  }
601f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
602a75c1b125159f6cfb6b652a9ec40803f7c7e3f71Behdad Esfahbod  FILE *get_file_handle (void);
6033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
6043530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *output_file;
6053530cc2d7c3b7102902cb0e38b0bf9f46188078dBehdad Esfahbod  char *output_format;
606ea5e8a02eb83ad19f3009b0008893f77ce113118Behdad Esfahbod  const char **supported_formats;
6076bad092aa87bc3e6bbf0b9faf07693e6ebbe55f2Behdad Esfahbod  bool explicit_output_format;
608f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod
609f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod  mutable FILE *fp;
610b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod};
6113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
6128b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstruct format_options_t : option_group_t
6138b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
6148b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  format_options_t (option_parser_t *parser) {
6158b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_glyph_names = true;
6168b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_positions = true;
6178b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    show_clusters = true;
618cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod    show_text = false;
619cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod    show_unicode = false;
620cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod    show_line_num = false;
621fdd1770e006ca2d2973c049177ceda87a575e07fBehdad Esfahbod    show_extents = false;
62240bd7e9a1cf422b17f15d0f66547bde9098e6ef3Behdad Esfahbod    show_flags = false;
6236f38845d9c6852812eb1963a1fd7e5ec771e5ce3Behdad Esfahbod    trace = false;
6248b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
6258b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    add_options (parser);
6268b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
6278b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
6288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  void add_options (option_parser_t *parser);
6298b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
630cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_unicode (hb_buffer_t  *buffer,
631cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			  GString      *gs);
632cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_glyphs (hb_buffer_t  *buffer,
633cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			 hb_font_t    *font,
634f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod			 hb_buffer_serialize_format_t format,
635f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod			 hb_buffer_serialize_flags_t flags,
636cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			 GString      *gs);
637cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  void serialize_line_no (unsigned int  line_no,
638cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod			  GString      *gs);
6395db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_buffer_of_text (hb_buffer_t  *buffer,
6405db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 unsigned int  line_no,
6415db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 const char   *text,
6425db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 unsigned int  text_len,
6435db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 hb_font_t    *font,
6445db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				 GString      *gs);
6455db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_message (unsigned int  line_no,
646a9e52a1af4c039bc53090a9c1e4c1136fc542605Behdad Esfahbod			  const char   *type,
6475db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod			  const char   *msg,
6485db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod			  GString      *gs);
6495db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  void serialize_buffer_of_glyphs (hb_buffer_t  *buffer,
6505db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   unsigned int  line_no,
6515db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   const char   *text,
6525db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   unsigned int  text_len,
6535db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   hb_font_t    *font,
654f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod				   hb_buffer_serialize_format_t output_format,
655f9edf1672511c3bcc3796cc79578ffea43b2bda1Behdad Esfahbod				   hb_buffer_serialize_flags_t format_flags,
6565db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod				   GString      *gs);
657cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod
6588b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
659088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_glyph_names;
660088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_positions;
661088c1e27c0fc0cdef999cf1f567e4d5eb2cfb2e4Behdad Esfahbod  hb_bool_t show_clusters;
662cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod  hb_bool_t show_text;
663cc4d9810d6318ca2e4de3b8d62f03b51cc21ee05Behdad Esfahbod  hb_bool_t show_unicode;
664cdc673d97c5ffedb386865a81f54a5cedcbad27cBehdad Esfahbod  hb_bool_t show_line_num;
665fdd1770e006ca2d2973c049177ceda87a575e07fBehdad Esfahbod  hb_bool_t show_extents;
66640bd7e9a1cf422b17f15d0f66547bde9098e6ef3Behdad Esfahbod  hb_bool_t show_flags;
6676f38845d9c6852812eb1963a1fd7e5ec771e5ce3Behdad Esfahbod  hb_bool_t trace;
6688b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod};
6698b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
670a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan/* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
671a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#if defined (_MSC_VER) && (_MSC_VER < 1800)
672a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
673a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#ifndef FLT_RADIX
674a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#define FLT_RADIX 2
675a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#endif
676a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
677a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan__inline long double scalbn (long double x, int exp)
678a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan{
679a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan  return x * (pow ((long double) FLT_RADIX, exp));
680a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan}
681a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan
682a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan__inline float scalbnf (float x, int exp)
683a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan{
684a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan  return x * (pow ((float) FLT_RADIX, exp));
685a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan}
686a49e7b7e40127beba25f39ef3c10d7a77e2bb0f0Chun-wei Fan#endif
6873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
6883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#endif
689