options.cc revision 97796453aab56873809a15b5e316cba8acea7449
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
293bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodview_options_t view_opts[1];
313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodshape_options_t shape_opts[1];
323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodfont_options_t font_opts[1];
333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3497796453aab56873809a15b5e316cba8acea7449Behdad Esfahbodconst char *out_file = "/dev/stdout";
3597796453aab56873809a15b5e316cba8acea7449Behdad Esfahbodhb_bool_t debug = FALSE;
363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
383bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
393bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_margin (const char *name G_GNUC_UNUSED,
403bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      const char *arg,
413bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      gpointer    data G_GNUC_UNUSED,
423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      GError    **error G_GNUC_UNUSED)
433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  view_options_t::margin_t &m = view_opts->margin;
4597796453aab56873809a15b5e316cba8acea7449Behdad Esfahbod  switch (sscanf (arg, "%lf %lf %lf %lf", &m.t, &m.r, &m.b, &m.l)) {
463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 1: m.r = m.t;
473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 2: m.b = m.t;
483bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 3: m.l = m.r;
493bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    case 4: return TRUE;
503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    default:
513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod		   "%s argument should be one to four space-separated numbers",
533bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod		   name);
543bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      return FALSE;
553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
593bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_shapers (const char *name G_GNUC_UNUSED,
613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	       const char *arg,
623bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	       gpointer    data G_GNUC_UNUSED,
633bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	       GError    **error G_GNUC_UNUSED)
643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->shapers = g_strsplit (arg, ",", 0);
663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
683bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
693bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
703bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic void
713bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_space (char **pp)
723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char c;
743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)=='\v')
753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (c = **pp, ISSPACE (c))
763bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    (*pp)++;
773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#undef ISSPACE
783bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
793bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_char (char **pp, char c)
823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
833bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  parse_space (pp);
843bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
853bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (**pp != c)
863bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  (*pp)++;
893bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
923bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
933bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_uint (char **pp, unsigned int *pv)
943bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p = *pp;
963bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  unsigned int v;
973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
983bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  v = strtol (p, pp, 0);
993bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1003bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (p == *pp)
1013bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
1023bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  *pv = v;
1043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
1053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1063bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1073bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1083bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1093bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_value_prefix (char **pp, hb_feature_t *feature)
1103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (parse_char (pp, '-'))
1123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    feature->value = 0;
1133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  else {
1143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    parse_char (pp, '+');
1153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    feature->value = 1;
1163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
1173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
1193bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1203bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_tag (char **pp, hb_feature_t *feature)
1233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1243bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p = *pp, c;
1253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  parse_space (pp);
1273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
1293bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (c = **pp, ISALNUM(c))
1303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    (*pp)++;
1313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod#undef ISALNUM
1323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (p == *pp)
1343bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return FALSE;
1353bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  **pp = '\0';
1373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  feature->tag = hb_tag_from_string (p);
1383bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  **pp = c;
1393bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1403bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
1413bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_indices (char **pp, hb_feature_t *feature)
1453bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  hb_bool_t has_start;
1473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1483bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  feature->start = 0;
1493bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  feature->end = (unsigned int) -1;
1503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (!parse_char (pp, '['))
1523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return TRUE;
1533bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1543bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  has_start = parse_uint (pp, &feature->start);
1553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (parse_char (pp, ':')) {
1573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    parse_uint (pp, &feature->end);
1583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } else {
1593bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (has_start)
1603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      feature->end = feature->start + 1;
1613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
1623bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1633bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return parse_char (pp, ']');
1643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_feature_value_postfix (char **pp, hb_feature_t *feature)
1683bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1693bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return !parse_char (pp, '=') || parse_uint (pp, &feature->value);
1703bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1713bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1733bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic hb_bool_t
1743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_one_feature (char **pp, hb_feature_t *feature)
1753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1763bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return parse_feature_value_prefix (pp, feature) &&
1773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_tag (pp, feature) &&
1783bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_indices (pp, feature) &&
1793bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 parse_feature_value_postfix (pp, feature) &&
1803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	 (parse_char (pp, ',') || **pp == '\0');
1813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1833bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic void
1843bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodskip_one_feature (char **pp)
1853bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
1863bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *e;
1873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  e = strchr (*pp, ',');
1883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (e)
1893bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    *pp = e + 1;
1903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  else
1913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    *pp = *pp + strlen (*pp);
1923bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
1933bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
1943bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gboolean
1953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_features (const char *name G_GNUC_UNUSED,
1963bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	        const char *arg,
1973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	        gpointer    data G_GNUC_UNUSED,
1983bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	        GError    **error G_GNUC_UNUSED)
1993bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2003bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *s = (char *) arg;
2013bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *p;
2023bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->num_features = 0;
2043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->features = NULL;
2053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2063bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (!*s)
2073bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    return TRUE;
2083bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2093bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  /* count the features first, so we can allocate memory */
2103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  p = s;
2113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  do {
2123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    shape_opts->num_features++;
2133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    p = strchr (p, ',');
2143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (p)
2153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      p++;
2163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  } while (p);
2173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->features = (hb_feature_t *) calloc (shape_opts->num_features, sizeof (*shape_opts->features));
2193bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2203bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  /* now do the actual parsing */
2213bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  p = s;
2223bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->num_features = 0;
2233bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  while (*p) {
2243bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (parse_one_feature (&p, &shape_opts->features[shape_opts->num_features]))
2253bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      shape_opts->num_features++;
2263bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    else
2273bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      skip_one_feature (&p);
2283bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
2293bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2303bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return TRUE;
2313bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2323bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2333bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2343bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic gchar *
2353bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodshapers_to_string (void)
2363bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2373bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  GString *shapers = g_string_new (NULL);
2383bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  const char **shaper_list = hb_shape_list_shapers ();
2393bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2403bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  for (; *shaper_list; shaper_list++) {
2413bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    g_string_append (shapers, *shaper_list);
2423bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    g_string_append_c (shapers, ',');
2433bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
2443bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_string_truncate (shapers, MAX (0, (gint)shapers->len - 1));
2453bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2463bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  return g_string_free (shapers, FALSE);
2473bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2483bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2493bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodstatic G_GNUC_NORETURN gboolean
2503bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodshow_version (const char *name G_GNUC_UNUSED,
2513bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      const char *arg G_GNUC_UNUSED,
2523bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      gpointer    data G_GNUC_UNUSED,
2533bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod	      GError    **error G_GNUC_UNUSED)
2543bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2553bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_printf ("%s (%s) %s\n", g_get_prgname (), PACKAGE_NAME, PACKAGE_VERSION);
2563bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2573bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  char *shapers = shapers_to_string ();
2583bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_printf ("Available shapers: %s\n", shapers);
2593bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_free (shapers);
2603bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (strcmp (HB_VERSION_STRING, hb_version_string ()))
2613bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    g_printf ("Linked HarfBuzz library has a different version: %s\n", hb_version_string ());
2623bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2633bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  exit(0);
2643bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
2653bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2663bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2673bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodvoid
2683bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbodparse_options (int argc, char *argv[])
2693bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod{
2703bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  GOptionEntry entries[] =
2713bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  {
2723bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"version",		0, G_OPTION_FLAG_NO_ARG,
27397796453aab56873809a15b5e316cba8acea7449Behdad Esfahbod			      G_OPTION_ARG_CALLBACK,	(gpointer) &show_version,	"Show version numbers",			NULL},
2743bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"debug",		0, 0, G_OPTION_ARG_NONE,	&debug,				"Free all resources before exit",	NULL},
2753bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"output",		0, 0, G_OPTION_ARG_STRING,	&out_file,			"Set output file name",			"filename"},
2763bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2773bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"annotate",	0, 0, G_OPTION_ARG_NONE,	&view_opts->annotate,		"Annotate output rendering",		NULL},
2783bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"background",	0, 0, G_OPTION_ARG_STRING,	&view_opts->back,		"Set background color",			"red/#rrggbb/#rrggbbaa"},
2793bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"foreground",	0, 0, G_OPTION_ARG_STRING,	&view_opts->fore,		"Set foreground color",			"red/#rrggbb/#rrggbbaa"},
2803bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"line-space",	0, 0, G_OPTION_ARG_DOUBLE,	&view_opts->line_space,		"Set space between lines (default: 0)",	"units"},
2813bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"margin",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_margin,	"Margin around output",			"one to four numbers"},
2823bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2833bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"shapers",		0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_shapers,	"Comma-separated list of shapers",	"list"},
2843bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"direction",	0, 0, G_OPTION_ARG_STRING,	&shape_opts->direction,		"Set text direction (default: auto)",	"ltr/rtl/ttb/btt"},
2853bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"language",	0, 0, G_OPTION_ARG_STRING,	&shape_opts->language,		"Set text language (default: $LANG)",	"langstr"},
2863bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"script",		0, 0, G_OPTION_ARG_STRING,	&shape_opts->script,		"Set text script (default: auto)",	"ISO-15924 tag"},
2873bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"features",	0, 0, G_OPTION_ARG_CALLBACK,	(gpointer) &parse_features,	"Font features to apply to text",	"TODO"},
2883bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2893bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"face-index",	0, 0, G_OPTION_ARG_INT,		&font_opts->face_index,		"Face index (default: 0)",		"index"},
2903bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {"font-size",	0, 0, G_OPTION_ARG_DOUBLE,	&font_opts->font_size,		"Font size",				"size"},
2913bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2923bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    {NULL}
2933bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  };
2943bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  GError *parse_error = NULL;
2953bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  GOptionContext *context;
2963bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2973bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  context = g_option_context_new ("- FONT-FILE TEXT");
2983bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
2993bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_option_context_add_main_entries (context, entries, NULL);
3003bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3013bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (!g_option_context_parse (context, &argc, &argv, &parse_error))
3023bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  {
3033bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    if (parse_error != NULL)
3043bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      fail ("%s", parse_error->message);
3053bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    else
3063bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod      fail ("Option parse error");
3073bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    exit(1);
3083bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
3093bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  g_option_context_free(context);
3103bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3113bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  if (argc != 3) {
3123bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    g_printerr ("Usage: %s [OPTION...] FONT-FILE TEXT\n", g_get_prgname ());
3133bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod    exit (1);
3143bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  }
3153bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod
3163bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  font_opts->font_file = argv[1];
3173bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod  shape_opts->text = argv[2];
3183bb300ee78a40f9ded21ab19283863b733aeb677Behdad Esfahbod}
319