options.cc revision 4451168e5d1ea26560899e9a9733b3a3f1853050
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#include "options.hh"
283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
29b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#if HAVE_FREETYPE
30b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#include <hb-ft.h>
31b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif
323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
34b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodbool debug = FALSE;
35b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
36b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic gchar *
37b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodshapers_to_string (void)
38b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
39b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GString *shapers = g_string_new (NULL);
40b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char **shaper_list = hb_shape_list_shapers ();
41b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
42b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  for (; *shaper_list; shaper_list++) {
43b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_string_append (shapers, *shaper_list);
44b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_string_append_c (shapers, ',');
45b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
46b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_string_truncate (shapers, MAX (0, (gint)shapers->len - 1));
47b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
48b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  return g_string_free (shapers, FALSE);
49b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
50b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
51b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic G_GNUC_NORETURN gboolean
52b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodshow_version (const char *name G_GNUC_UNUSED,
53b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	      const char *arg G_GNUC_UNUSED,
54b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	      gpointer    data G_GNUC_UNUSED,
55b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	      GError    **error G_GNUC_UNUSED)
56b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
57b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_printf ("%s (%s) %s\n", g_get_prgname (), PACKAGE_NAME, PACKAGE_VERSION);
58b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
59b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  char *shapers = shapers_to_string ();
60b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_printf ("Available shapers: %s\n", shapers);
61b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_free (shapers);
62b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (strcmp (HB_VERSION_STRING, hb_version_string ()))
63b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    g_printf ("Linked HarfBuzz library has a different version: %s\n", hb_version_string ());
64b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
65b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  exit(0);
66b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
67b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
68b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
69b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid
70b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodoption_parser_t::add_main_options (void)
71b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
72b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GOptionEntry entries[] =
73b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
74b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"version",		0, G_OPTION_FLAG_NO_ARG,
75b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			      G_OPTION_ARG_CALLBACK,	(gpointer) &show_version,	"Show version numbers",			NULL},
76b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"debug",		0, 0, G_OPTION_ARG_NONE,	&debug,				"Free all resources before exit",	NULL},
77b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {NULL}
78b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  };
79b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_option_context_add_main_entries (context, entries, NULL);
80b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
81b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
82b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic gboolean
83b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodpre_parse (GOptionContext *context G_GNUC_UNUSED,
84b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	   GOptionGroup *group G_GNUC_UNUSED,
85b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	   gpointer data,
86b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	   GError **error)
87b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
88b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_group_t *option_group = (option_group_t *) data;
89b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_group->pre_parse (error);
90b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  return *error == NULL;
91b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
92b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
93b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic gboolean
94b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodpost_parse (GOptionContext *context G_GNUC_UNUSED,
95b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	    GOptionGroup *group G_GNUC_UNUSED,
96b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	    gpointer data,
97b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	    GError **error)
98b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
99b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_group_t *option_group = static_cast<option_group_t *>(data);
100b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  option_group->post_parse (error);
101b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  return *error == NULL;
102b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
103b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
104b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid
105b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodoption_parser_t::add_group (GOptionEntry   *entries,
106b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			    const gchar    *name,
107b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			    const gchar    *description,
108b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			    const gchar    *help_description,
109b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			    option_group_t *option_group)
110b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
111b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GOptionGroup *group = g_option_group_new (name, description, help_description,
112b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod					    static_cast<gpointer>(option_group), NULL);
113b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_option_group_add_entries (group, entries);
114b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_option_group_set_parse_hooks (group, pre_parse, post_parse);
115b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  g_option_context_add_group (context, group);
116b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
117b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
118b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid
119b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodoption_parser_t::parse (int *argc, char ***argv)
120b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
121b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GError *parse_error = NULL;
122b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (!g_option_context_parse (context, argc, argv, &parse_error))
123b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
124b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (parse_error != NULL)
125b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      fail (TRUE, "%s", parse_error->message);
126b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    else
127b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      fail (TRUE, "Option parse error");
128b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
129b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
1303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
1333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_margin (const char *name G_GNUC_UNUSED,
1343bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      const char *arg,
135bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod	      gpointer    data,
1363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      GError    **error G_GNUC_UNUSED)
1373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
138bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod  view_options_t *view_opts = (view_options_t *) data;
1393bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  view_options_t::margin_t &m = view_opts->margin;
14097796453aab56873809a15b5e316cba8acea7449Behdad Esfahbod  switch (sscanf (arg, "%lf %lf %lf %lf", &m.t, &m.r, &m.b, &m.l)) {
1413bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 1: m.r = m.t;
1423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 2: m.b = m.t;
1433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 3: m.l = m.r;
1443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 4: return TRUE;
1453bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    default:
1463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
1473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod		   "%s argument should be one to four space-separated numbers",
1483bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod		   name);
1493bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      return FALSE;
1503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
1513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1533bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1543bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
1553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_shapers (const char *name G_GNUC_UNUSED,
1563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	       const char *arg,
157bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod	       gpointer    data,
1583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	       GError    **error G_GNUC_UNUSED)
1593bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
160bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod  shape_options_t *shape_opts = (shape_options_t *) data;
1613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->shapers = g_strsplit (arg, ",", 0);
1623bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
1633bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic void
1673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_space (char **pp)
1683bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1693bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char c;
1703bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v')
1713bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (c = **pp, ISSPACE (c))
1723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    (*pp)++;
1733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#undef ISSPACE
1743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1763bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_char (char **pp, char c)
1783bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1793bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  parse_space (pp);
1803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (**pp != c)
1823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
1833bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1843bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  (*pp)++;
1853bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
1863bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1893bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_uint (char **pp, unsigned int *pv)
1903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p = *pp;
1923bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  unsigned int v;
1933bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1943bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  v = strtol (p, pp, 0);
1953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1963bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (p == *pp)
1973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
1983bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1993bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  *pv = v;
2003bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
2013bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2023bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
2053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_value_prefix (char **pp, hb_feature_t *feature)
2063bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2073bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (parse_char (pp, '-'))
2083bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    feature->value = 0;
2093bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  else {
2103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    parse_char (pp, '+');
2113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    feature->value = 1;
2123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
2133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
2153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
2183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_tag (char **pp, hb_feature_t *feature)
2193bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2203bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p = *pp, c;
2213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  parse_space (pp);
2233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2243bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
2253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (c = **pp, ISALNUM(c))
2263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    (*pp)++;
2273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#undef ISALNUM
2283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2293bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (p == *pp)
2303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
2313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2324c9fe88d30036340fe592bcbc375049b84602b8bBehdad Esfahbod  feature->tag = hb_tag_from_string (p, *pp - p);
2333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
2343bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2353bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
2373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_indices (char **pp, hb_feature_t *feature)
2383bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2393bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  hb_bool_t has_start;
2403bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2413bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  feature->start = 0;
2423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  feature->end = (unsigned int) -1;
2433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (!parse_char (pp, '['))
2453bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return TRUE;
2463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  has_start = parse_uint (pp, &feature->start);
2483bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2493bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (parse_char (pp, ':')) {
2503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    parse_uint (pp, &feature->end);
2513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } else {
2523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (has_start)
2533bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      feature->end = feature->start + 1;
2543bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
2553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return parse_char (pp, ']');
2573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2593bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
2603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_value_postfix (char **pp, hb_feature_t *feature)
2613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2623bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return !parse_char (pp, '=') || parse_uint (pp, &feature->value);
2633bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
2673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_one_feature (char **pp, hb_feature_t *feature)
2683bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2693bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return parse_feature_value_prefix (pp, feature) &&
2703bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_tag (pp, feature) &&
2713bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_indices (pp, feature) &&
2723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_value_postfix (pp, feature) &&
2733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 (parse_char (pp, ',') || **pp == '\0');
2743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2763bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic void
2773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodskip_one_feature (char **pp)
2783bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2793bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *e;
2803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  e = strchr (*pp, ',');
2813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (e)
2823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    *pp = e + 1;
2833bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  else
2843bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    *pp = *pp + strlen (*pp);
2853bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2863bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
2883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_features (const char *name G_GNUC_UNUSED,
2893bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	        const char *arg,
290bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod	        gpointer    data,
2913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	        GError    **error G_GNUC_UNUSED)
2923bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
293bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod  shape_options_t *shape_opts = (shape_options_t *) data;
2943bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *s = (char *) arg;
2953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p;
2963bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->num_features = 0;
2983bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->features = NULL;
2993bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3003bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (!*s)
3013bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return TRUE;
3023bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  /* count the features first, so we can allocate memory */
3043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  p = s;
3053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  do {
3063bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    shape_opts->num_features++;
3073bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    p = strchr (p, ',');
3083bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (p)
3093bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      p++;
3103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } while (p);
3113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
3133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  /* now do the actual parsing */
3153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  p = s;
3163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->num_features = 0;
3173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (*p) {
3183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (parse_one_feature (&p, &shape_opts->features[shape_opts->num_features]))
3193bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      shape_opts->num_features++;
3203bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    else
3213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      skip_one_feature (&p);
3223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
3233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3243bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
3253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
3263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodvoid
329b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_options_t::add_options (option_parser_t *parser)
3303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
3313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  GOptionEntry entries[] =
3323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  {
333bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"annotate",	0, 0, G_OPTION_ARG_NONE,	&this->annotate,		"Annotate output rendering",				NULL},
334bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"background",	0, 0, G_OPTION_ARG_STRING,	&this->back,			"Set background color (default: "DEFAULT_BACK")",	"red/#rrggbb/#rrggbbaa"},
335bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"foreground",	0, 0, G_OPTION_ARG_STRING,	&this->fore,			"Set foreground color (default: "DEFAULT_FORE")",	"red/#rrggbb/#rrggbbaa"},
336bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"line-space",	0, 0, G_OPTION_ARG_DOUBLE,	&this->line_space,		"Set space between lines (default: 0)",			"units"},
337109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    {"margin",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_margin,	"Margin around output (default: "G_STRINGIFY(DEFAULT_MARGIN)")","one to four numbers"},
338109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    {NULL}
339109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  };
340b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  parser->add_group (entries,
341b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "view",
342b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "View options:",
343b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Options controlling the output rendering",
344b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     this);
345109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod}
3463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
347109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbodvoid
348b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodshape_options_t::add_options (option_parser_t *parser)
349109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod{
350109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  GOptionEntry entries[] =
351109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  {
3523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"shapers",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_shapers,	"Comma-separated list of shapers",	"list"},
353bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"direction",	0, 0, G_OPTION_ARG_STRING,	&this->direction,		"Set text direction (default: auto)",	"ltr/rtl/ttb/btt"},
354bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"language",	0, 0, G_OPTION_ARG_STRING,	&this->language,		"Set text language (default: $LANG)",	"langstr"},
355bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"script",		0, 0, G_OPTION_ARG_STRING,	&this->script,			"Set text script (default: auto)",	"ISO-15924 tag"},
3563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"features",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_features,	"Font features to apply to text",	"TODO"},
357109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    {NULL}
358109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  };
359b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  parser->add_group (entries,
360b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "shape",
361b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Shape options:",
362b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Options controlling the shaping process",
363b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     this);
364109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod}
3653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
366109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbodvoid
367b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodfont_options_t::add_options (option_parser_t *parser)
368109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod{
369109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  GOptionEntry entries[] =
370109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  {
371b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"font-file",	0, 0, G_OPTION_ARG_STRING,	&this->font_file,		"Font file-name",					"filename"},
372b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"face-index",	0, 0, G_OPTION_ARG_INT,		&this->face_index,		"Face index (default: 0)",                              "index"},
373bc4b07b05ea9e39eb9f966eb2c3e1c737efa77ffBehdad Esfahbod    {"font-size",	0, 0, G_OPTION_ARG_DOUBLE,	&this->font_size,		"Font size (default: "G_STRINGIFY(DEFAULT_FONT_SIZE)")","size"},
374109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod    {NULL}
375109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  };
376b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  parser->add_group (entries,
377b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "font",
378b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Font options:",
379b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Options controlling the font",
380b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     this);
381109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod}
3823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
383109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbodvoid
384b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodtext_options_t::add_options (option_parser_t *parser)
385109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod{
386109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  GOptionEntry entries[] =
387109cb382898f491eed733dba4ef5ba12de94aaf6Behdad Esfahbod  {
388b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"text",		0, 0, G_OPTION_ARG_STRING,	&this->text,			"Set input text",			"string"},
389b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"text-file",	0, 0, G_OPTION_ARG_STRING,	&this->text_file,		"Set input text file-name",		"filename"},
3903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {NULL}
3913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  };
392b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  parser->add_group (entries,
393b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "text",
394b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Text options:",
395b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Options controlling the input text",
396b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     this);
397b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
398b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
399b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid
400b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodoutput_options_t::add_options (option_parser_t *parser)
401b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
402b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  GOptionEntry entries[] =
403b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
404b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"output",		0, 0, G_OPTION_ARG_STRING,	&this->output_file,		"Set output file-name (default: stdout)","filename"},
405b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {"format",		0, 0, G_OPTION_ARG_STRING,	&this->output_format,		"Set output format",			"format"},
406b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    {NULL}
407b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  };
408b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  parser->add_group (entries,
409b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "output",
410b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Output options:",
411b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     "Options controlling the output",
412b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod		     this);
413b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
4143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
4153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
4163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
417b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodhb_font_t *
418b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodfont_options_t::get_font (void) const
419b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
420b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (font)
421b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    return font;
422b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
423b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_blob_t *blob = NULL;
424b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
425b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  /* Create the blob */
4263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  {
4274451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    char *font_data;
4284451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    unsigned int len = 0;
429b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_destroy_func_t destroy;
430b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    void *user_data;
431b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    hb_memory_mode_t mm;
432b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
4334451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    /* This is a hell of a lot of code for just reading a file! */
434b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (!font_file)
435b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      fail (TRUE, "No font file set");
436b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
4374451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    if (0 == strcmp (font_file, "-")) {
4384451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      /* read it */
4394451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      GString *gs = g_string_new (NULL);
4404451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      char buf[BUFSIZ];
4414451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod#if HAVE_IO_H
4424451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      _setmode (fileno (stdin), O_BINARY);
4434451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod#endif
4444451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      while (!feof (stdin)) {
4454451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	size_t ret = fread (buf, 1, sizeof (buf), stdin);
4464451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	if (ferror (stdin))
4474451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  fail (FALSE, "Failed reading font from standard input: %s",
4484451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod		strerror (errno));
4494451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	g_string_append_len (gs, buf, ret);
4504451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      }
4514451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      len = gs->len;
4524451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      font_data = g_string_free (gs, FALSE);
4534451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      user_data = font_data;
4544451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      destroy = (hb_destroy_func_t) g_free;
4554451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      mm = HB_MEMORY_MODE_WRITABLE;
4564451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    } else {
4574451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      GMappedFile *mf = g_mapped_file_new (font_file, FALSE, NULL);
4584451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      if (mf) {
4594451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	font_data = g_mapped_file_get_contents (mf);
4604451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	len = g_mapped_file_get_length (mf);
4614451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	if (len) {
4624451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  destroy = (hb_destroy_func_t) g_mapped_file_unref;
4634451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  user_data = (void *) mf;
4644451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE;
4654451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	} else
4664451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  g_mapped_file_unref (mf);
4674451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      }
4684451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      if (!len) {
4694451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	/* GMappedFile is buggy, it doesn't fail if file isn't regular.
4704451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	 * Try reading.
4714451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	 * https://bugzilla.gnome.org/show_bug.cgi?id=659212 */
4724451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod        GError *error = NULL;
4734451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	gsize l;
4744451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	if (g_file_get_contents (font_file, &font_data, &l, &error)) {
4754451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  len = l;
4764451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  destroy = (hb_destroy_func_t) g_free;
4774451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  user_data = (void *) font_data;
4784451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  mm = HB_MEMORY_MODE_WRITABLE;
4794451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	} else {
4804451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  fail (FALSE, "Failed reading font file `%s': %s",
4814451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod		g_filename_display_name (font_file),
4824451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod		error->message);
4834451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	  //g_error_free (error);
4844451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod	}
4854451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod      }
4864451168e5d1ea26560899e9a9733b3a3f1853050Behdad Esfahbod    }
487b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
488b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    blob = hb_blob_create (font_data, len, mm, user_data, destroy);
489b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
490b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
491b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  /* Create the face */
492b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_face_t *face = hb_face_create (blob, face_index);
493b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_blob_destroy (blob);
494b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
495b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
496b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  font = hb_font_create (face);
497b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
498b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  unsigned int upem = hb_face_get_upem (face);
499b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_font_set_scale (font, font_size * upem, font_size * upem);
500b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_face_destroy (face);
501b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
502b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#if HAVE_FREETYPE
503b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  hb_ft_font_set_funcs (font);
504b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif
505b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
506b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  return font;
507b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
508b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
509b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
510b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodconst char *
511b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodtext_options_t::get_line (unsigned int *len)
512b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
513b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (!text) {
514b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (!text_file)
515b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      fail (TRUE, "At least one of text or text-file must be set");
516b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
517b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    GMappedFile *mf = g_mapped_file_new (text_file, FALSE, NULL);
518b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    if (!mf)
519639b5957d9c7b6d8bef6784e3467ccc055ddeea4Behdad Esfahbod      fail (FALSE, "Failed opening text file `%s'", g_filename_display_name (text_file));
520b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text = g_mapped_file_get_contents (mf);
521b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text_len = g_mapped_file_get_length (mf);
5223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
5233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
524b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (text_len == (unsigned int) -1)
525b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text_len = strlen (text);
526b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
527b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (!text_len) {
528b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    *len = 0;
529b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    return NULL;
530b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
531b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
532b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *ret = text;
533b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  const char *p = (const char *) memchr (text, '\n', text_len);
534b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  unsigned int ret_len;
535b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  if (!p) {
536b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    ret_len = text_len;
537b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text += ret_len;
538b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text_len = 0;
539b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  } else {
540b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    ret_len = p - ret;
541b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text += ret_len + 1;
542b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    text_len -= ret_len + 1;
5433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
5443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
545b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  *len = ret_len;
546b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  return ret;
5473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
548