hb-shape.cc revision 60cb18a5dea2d30793f89e80995bb729c014864a
115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009  Red Hat, Inc.
3e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod * Copyright © 2012  Google, Inc.
415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
615232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod *
715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * Permission is hereby granted, without written agreement and without
815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
915232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * software and its documentation for any purpose, provided that the
1015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
1115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * all copies of this software.
1215232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod *
1315232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1515232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1615232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * DAMAGE.
1815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod *
1915232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
2015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2115232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2215232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2315232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2415232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod *
2515232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
26e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod * Google Author(s): Behdad Esfahbod
2715232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod */
2815232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod
29c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh"
3015232e26f4a89dab1b6de35ad9d3d16e75bf93d0Behdad Esfahbod
31027857d0412477fb4427dcb8a8c45287c272e143Behdad Esfahbod#include "hb-shaper-private.hh"
325b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod#include "hb-shape-plan-private.hh"
3322da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-buffer-private.hh"
345b95c148cc485f79fd7018bc4520b4cb5f728a18Behdad Esfahbod#include "hb-font-private.hh"
352f50d873680ce0a43b6ec79df1ac946b91f31e63Behdad Esfahbod
3602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
37e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic void
38e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_space (const char **pp, const char *end)
39e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
40e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char c;
41e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  while (*pp < end && (c = **pp, ISSPACE (c)))
42e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    (*pp)++;
43e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
44e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
45e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
46e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_char (const char **pp, const char *end, char c)
47e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
48e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  parse_space (pp, end);
49e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
50e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (*pp == end || **pp != c)
51e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    return false;
52e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
53e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  (*pp)++;
54e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return true;
55e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
56e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
57e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
58e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_uint (const char **pp, const char *end, unsigned int *pv)
59e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
60e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char buf[32];
61847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
62847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  strncpy (buf, *pp, len);
63847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  buf[len] = '\0';
64e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
65e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char *p = buf;
66e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char *pend = p;
67e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  unsigned int v;
68e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
698da51112696ec8641d7dd9184b7ab1dd48458813Behdad Esfahbod  /* Intentionally use strtol instead of strtoul, such that
708da51112696ec8641d7dd9184b7ab1dd48458813Behdad Esfahbod   * -1 turns into "big number"... */
71847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  errno = 0;
72e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  v = strtol (p, &pend, 0);
73847794e929831750e97525137ab5e285ccd1064eBehdad Esfahbod  if (errno || p == pend)
74e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    return false;
75e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
76e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  *pv = v;
77e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  *pp += pend - p;
78e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return true;
79e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
80e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
81e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
8260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbodparse_bool (const char **pp, const char *end, unsigned int *pv)
8360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod{
8460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  parse_space (pp, end);
8560cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod
8660cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  const char *p = *pp;
8760cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  while (*pp < end && ISALPHA(**pp))
8860cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod    (*pp)++;
8960cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod
9060cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  /* CSS allows on/off as aliases 1/0. */
9160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  if (*pp - p == 2 || 0 == strncmp (p, "on", 2))
9260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod    *pv = 1;
9360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  else if (*pp - p == 3 || 0 == strncmp (p, "off", 2))
9460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod    *pv = 0;
9560cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  else
9660cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod    return false;
9760cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod
9860cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  return true;
9960cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod}
10060cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod
10160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbodstatic hb_bool_t
102e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
103e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
104e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (parse_char (pp, end, '-'))
105e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    feature->value = 0;
106e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  else {
107e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    parse_char (pp, end, '+');
108e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    feature->value = 1;
109e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  }
110e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
111e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return true;
112e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
113e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
114e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
115e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
116e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
1172ee5f665ded86147acedc400153c0b3a90fe07c6Behdad Esfahbod  parse_space (pp, end);
1182ee5f665ded86147acedc400153c0b3a90fe07c6Behdad Esfahbod
119e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  const char *p = *pp;
120e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char c;
121e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
122e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  while (*pp < end && (c = **pp, ISALNUM(c)))
123e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    (*pp)++;
124e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
125f4fe9baefdb7e0ff9946f88b6f4b55738fa30cdfBehdad Esfahbod  if (p == *pp || *pp - p > 4)
126e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    return false;
127e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
128e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  feature->tag = hb_tag_from_string (p, *pp - p);
129e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return true;
130e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
131e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
132e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
133e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
134e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
135e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  parse_space (pp, end);
136e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
137e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  hb_bool_t has_start;
138e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
139e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  feature->start = 0;
140e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  feature->end = (unsigned int) -1;
141e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
142e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (!parse_char (pp, end, '['))
143e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    return true;
144e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
145e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  has_start = parse_uint (pp, end, &feature->start);
146e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
147e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (parse_char (pp, end, ':')) {
148e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    parse_uint (pp, end, &feature->end);
149e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  } else {
150e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    if (has_start)
151e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod      feature->end = feature->start + 1;
152e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  }
153e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
154e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return parse_char (pp, end, ']');
155e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
156e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
157e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
158e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
159e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
160e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod  bool had_equal = parse_char (pp, end, '=');
16160cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  bool had_value = parse_uint (pp, end, &feature->value) ||
16260cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod                   parse_bool (pp, end, &feature->value);
16360cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod  /* CSS doesn't use equal-sign between tag and value.
16460cb18a5dea2d30793f89e80995bb729c014864aBehdad Esfahbod   * If there was an equal-sign, then there *must* be a value.
165e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod   * A value without an eqaul-sign is ok, but not required. */
166e15fa7a8cffbe6a67b1048d7b87b7df77d8b1686Behdad Esfahbod  return !had_equal || had_value;
167e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
168e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
169e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
170e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodstatic hb_bool_t
171e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodparse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
172e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
173e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return parse_feature_value_prefix (pp, end, feature) &&
174e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod	 parse_feature_tag (pp, end, feature) &&
175e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod	 parse_feature_indices (pp, end, feature) &&
176e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod	 parse_feature_value_postfix (pp, end, feature) &&
177e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod	 *pp == end;
178e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
179e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
180288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/**
181288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_feature_from_string:
182288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @str: (array length=len):
183288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @len:
184288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @feature: (out):
185288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
186288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
187288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
188288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value:
189288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
190288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0
191288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/
192e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_bool_t
193e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_feature_from_string (const char *str, int len,
194e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod			hb_feature_t *feature)
195e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
196e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (len < 0)
197e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    len = strlen (str);
198e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
199e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  return parse_one_feature (&str, str + len, feature);
200e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
201e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
202288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/**
203288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_feature_to_string:
204288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @feature:
205288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buf: (array length=size):
206288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @size:
207288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
208288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
209288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
210288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0
211288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/
212e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodvoid
213e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbodhb_feature_to_string (hb_feature_t *feature,
214e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod		      char *buf, unsigned int size)
215e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod{
216e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (unlikely (!size)) return;
217e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
218e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  char s[128];
219e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  unsigned int len = 0;
220e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (feature->value == 0)
221e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    s[len++] = '-';
222e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  hb_tag_to_string (feature->tag, s + len);
223e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  len += 4;
224e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  while (len && s[len - 1] == ' ')
225e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    len--;
2261c7e55511a870f2689680ca8f977e00879f3b3e3Behdad Esfahbod  if (feature->start != 0 || feature->end != (unsigned int) -1)
227e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  {
228e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    s[len++] = '[';
229e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    if (feature->start)
23038b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start));
231e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    if (feature->end != feature->start + 1) {
232e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod      s[len++] = ':';
233e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod      if (feature->end != (unsigned int) -1)
23438b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end));
235e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    }
236e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    s[len++] = ']';
237e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  }
238e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  if (feature->value > 1)
239e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  {
240e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod    s[len++] = '=';
24138b8b40526a85f33521542e24d1e0c82588efc85Behdad Esfahbod    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value));
242e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  }
243e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  assert (len < ARRAY_LENGTH (s));
244e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  len = MIN (len, size - 1);
245e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod  memcpy (buf, s, len);
2467235f33f9e5e031622a00a84f4b2e98f16803579Behdad Esfahbod  buf[len] = '\0';
247e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod}
248e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
249e30ebd2794b37bd8ec716a258d5cb017fb1dfadcBehdad Esfahbod
250f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodstatic const char **static_shaper_list;
251f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
252e9171af55cc6a402eb20db4ea74c86a0b1e70e85Behdad Esfahbodstatic inline
253f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodvoid free_static_shaper_list (void)
254f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod{
255f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  free (static_shaper_list);
256f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod}
2579da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod
258288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/**
259288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape_list_shapers:
260288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
261288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
262288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
263288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value: (transfer none):
264288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
265288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0
266288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/
2679da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbodconst char **
2689da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbodhb_shape_list_shapers (void)
2699da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod{
270f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbodretry:
271f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
272f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
273f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  if (unlikely (!shaper_list))
274f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  {
275f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    /* Not found; allocate one. */
276bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
277f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    if (unlikely (!shaper_list)) {
278f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod      static const char *nil_shaper_list[] = {NULL};
279f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod      return nil_shaper_list;
280f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    }
281f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
282bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
283f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    unsigned int i;
284bd26b4d21f59312805d294f46f15182adbcc47daBehdad Esfahbod    for (i = 0; i < HB_SHAPERS_COUNT; i++)
285f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod      shaper_list[i] = shapers[i].name;
286f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    shaper_list[i] = NULL;
287f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
288f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
289f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod      free (shaper_list);
290f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod      goto retry;
291f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    }
292f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
293f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod#ifdef HAVE_ATEXIT
294f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
295f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod#endif
296f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  }
297f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
298f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod  return shaper_list;
2999da554504e30a326fc57b28cdb0e57108bfa9555Behdad Esfahbod}
30002aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbod
301f64b2ebf82c5f355cd95806478cd30c00b1a2731Behdad Esfahbod
302288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/**
303288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape_full:
304288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @font: a font.
305288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buffer: a buffer.
306288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @features: (array length=num_features):
307288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @num_features:
308288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @shaper_list: (array zero-terminated=1):
309288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
310288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
311288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
312288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Return value:
313288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
314288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0
315288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/
31602aeca985b570763342c35e99af90025bfa088d5Behdad Esfahbodhb_bool_t
3170501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbodhb_shape_full (hb_font_t          *font,
3180501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod	       hb_buffer_t        *buffer,
3190501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod	       const hb_feature_t *features,
3200501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod	       unsigned int        num_features,
3210501573deda3a8dcdfcea491392f554f21ed0154Behdad Esfahbod	       const char * const *shaper_list)
3223286fc0e9adc3f2874c9409e7fdb09e4d2b7dda1Behdad Esfahbod{
323b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod  if (unlikely (!buffer->len))
324b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod    return true;
325b6b7ba1313bf686e6ed567183466104c90504a67Behdad Esfahbod
32696fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
32796fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod
3282f87cebe1062c7007021ebd05c1664e60da80825Behdad Esfahbod  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
329c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod  hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
330c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod  hb_shape_plan_destroy (shape_plan);
33196fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod
33296fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod  if (res)
33396fdc04e5c6daafce3d45e7508418e4db94df44cBehdad Esfahbod    buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
334c32c096a429da3e64896cf42ff5ab8c775d3c2ecBehdad Esfahbod  return res;
3353286fc0e9adc3f2874c9409e7fdb09e4d2b7dda1Behdad Esfahbod}
3363ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod
337288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod/**
338288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * hb_shape:
339288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @font: a font.
340288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @buffer: a buffer.
341288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @features: (array length=num_features):
342288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * @num_features:
343288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
344288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
345288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod *
346288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod * Since: 1.0
347288f2899979bcc9e68f8115cb76e3271ed0e17bcBehdad Esfahbod **/
3483ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbodvoid
3493ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbodhb_shape (hb_font_t           *font,
3503ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod	  hb_buffer_t         *buffer,
3513ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod	  const hb_feature_t  *features,
3523ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod	  unsigned int         num_features)
3533ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod{
3546bd9b479b8b2befbb0847282e93beade197c8038Behdad Esfahbod  hb_shape_full (font, buffer, features, num_features, NULL);
3553ca6c4ecc299295b6682fa2b6b9f83b213223badBehdad Esfahbod}
356