gfx/harfbuzz/src/hb-shape.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/harfbuzz/src/hb-shape.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,331 @@
     1.4 +/*
     1.5 + * Copyright © 2009  Red Hat, Inc.
     1.6 + * Copyright © 2012  Google, Inc.
     1.7 + *
     1.8 + *  This is part of HarfBuzz, a text shaping library.
     1.9 + *
    1.10 + * Permission is hereby granted, without written agreement and without
    1.11 + * license or royalty fees, to use, copy, modify, and distribute this
    1.12 + * software and its documentation for any purpose, provided that the
    1.13 + * above copyright notice and the following two paragraphs appear in
    1.14 + * all copies of this software.
    1.15 + *
    1.16 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    1.17 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    1.18 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    1.19 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    1.20 + * DAMAGE.
    1.21 + *
    1.22 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    1.23 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.24 + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    1.25 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    1.26 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    1.27 + *
    1.28 + * Red Hat Author(s): Behdad Esfahbod
    1.29 + * Google Author(s): Behdad Esfahbod
    1.30 + */
    1.31 +
    1.32 +#include "hb-private.hh"
    1.33 +
    1.34 +#include "hb-shaper-private.hh"
    1.35 +#include "hb-shape-plan-private.hh"
    1.36 +#include "hb-buffer-private.hh"
    1.37 +#include "hb-font-private.hh"
    1.38 +
    1.39 +
    1.40 +static void
    1.41 +parse_space (const char **pp, const char *end)
    1.42 +{
    1.43 +  char c;
    1.44 +  while (*pp < end && (c = **pp, ISSPACE (c)))
    1.45 +    (*pp)++;
    1.46 +}
    1.47 +
    1.48 +static hb_bool_t
    1.49 +parse_char (const char **pp, const char *end, char c)
    1.50 +{
    1.51 +  parse_space (pp, end);
    1.52 +
    1.53 +  if (*pp == end || **pp != c)
    1.54 +    return false;
    1.55 +
    1.56 +  (*pp)++;
    1.57 +  return true;
    1.58 +}
    1.59 +
    1.60 +static hb_bool_t
    1.61 +parse_uint (const char **pp, const char *end, unsigned int *pv)
    1.62 +{
    1.63 +  char buf[32];
    1.64 +  unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
    1.65 +  strncpy (buf, *pp, len);
    1.66 +  buf[len] = '\0';
    1.67 +
    1.68 +  char *p = buf;
    1.69 +  char *pend = p;
    1.70 +  unsigned int v;
    1.71 +
    1.72 +  /* Intentionally use strtol instead of strtoul, such that
    1.73 +   * -1 turns into "big number"... */
    1.74 +  errno = 0;
    1.75 +  v = strtol (p, &pend, 0);
    1.76 +  if (errno || p == pend)
    1.77 +    return false;
    1.78 +
    1.79 +  *pv = v;
    1.80 +  *pp += pend - p;
    1.81 +  return true;
    1.82 +}
    1.83 +
    1.84 +static hb_bool_t
    1.85 +parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
    1.86 +{
    1.87 +  if (parse_char (pp, end, '-'))
    1.88 +    feature->value = 0;
    1.89 +  else {
    1.90 +    parse_char (pp, end, '+');
    1.91 +    feature->value = 1;
    1.92 +  }
    1.93 +
    1.94 +  return true;
    1.95 +}
    1.96 +
    1.97 +static hb_bool_t
    1.98 +parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
    1.99 +{
   1.100 +  const char *p = *pp;
   1.101 +  char c;
   1.102 +
   1.103 +  parse_space (pp, end);
   1.104 +
   1.105 +#define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
   1.106 +  while (*pp < end && (c = **pp, ISALNUM(c)))
   1.107 +    (*pp)++;
   1.108 +#undef ISALNUM
   1.109 +
   1.110 +  if (p == *pp)
   1.111 +    return false;
   1.112 +
   1.113 +  feature->tag = hb_tag_from_string (p, *pp - p);
   1.114 +  return true;
   1.115 +}
   1.116 +
   1.117 +static hb_bool_t
   1.118 +parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
   1.119 +{
   1.120 +  parse_space (pp, end);
   1.121 +
   1.122 +  hb_bool_t has_start;
   1.123 +
   1.124 +  feature->start = 0;
   1.125 +  feature->end = (unsigned int) -1;
   1.126 +
   1.127 +  if (!parse_char (pp, end, '['))
   1.128 +    return true;
   1.129 +
   1.130 +  has_start = parse_uint (pp, end, &feature->start);
   1.131 +
   1.132 +  if (parse_char (pp, end, ':')) {
   1.133 +    parse_uint (pp, end, &feature->end);
   1.134 +  } else {
   1.135 +    if (has_start)
   1.136 +      feature->end = feature->start + 1;
   1.137 +  }
   1.138 +
   1.139 +  return parse_char (pp, end, ']');
   1.140 +}
   1.141 +
   1.142 +static hb_bool_t
   1.143 +parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
   1.144 +{
   1.145 +  return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value);
   1.146 +}
   1.147 +
   1.148 +
   1.149 +static hb_bool_t
   1.150 +parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
   1.151 +{
   1.152 +  return parse_feature_value_prefix (pp, end, feature) &&
   1.153 +	 parse_feature_tag (pp, end, feature) &&
   1.154 +	 parse_feature_indices (pp, end, feature) &&
   1.155 +	 parse_feature_value_postfix (pp, end, feature) &&
   1.156 +	 *pp == end;
   1.157 +}
   1.158 +
   1.159 +/**
   1.160 + * hb_feature_from_string:
   1.161 + * @str: (array length=len):
   1.162 + * @len: 
   1.163 + * @feature: (out):
   1.164 + *
   1.165 + * 
   1.166 + *
   1.167 + * Return value: 
   1.168 + *
   1.169 + * Since: 1.0
   1.170 + **/
   1.171 +hb_bool_t
   1.172 +hb_feature_from_string (const char *str, int len,
   1.173 +			hb_feature_t *feature)
   1.174 +{
   1.175 +  if (len < 0)
   1.176 +    len = strlen (str);
   1.177 +
   1.178 +  return parse_one_feature (&str, str + len, feature);
   1.179 +}
   1.180 +
   1.181 +/**
   1.182 + * hb_feature_to_string:
   1.183 + * @feature: 
   1.184 + * @buf: (array length=size):
   1.185 + * @size: 
   1.186 + *
   1.187 + * 
   1.188 + *
   1.189 + * Since: 1.0
   1.190 + **/
   1.191 +void
   1.192 +hb_feature_to_string (hb_feature_t *feature,
   1.193 +		      char *buf, unsigned int size)
   1.194 +{
   1.195 +  if (unlikely (!size)) return;
   1.196 +
   1.197 +  char s[128];
   1.198 +  unsigned int len = 0;
   1.199 +  if (feature->value == 0)
   1.200 +    s[len++] = '-';
   1.201 +  hb_tag_to_string (feature->tag, s + len);
   1.202 +  len += 4;
   1.203 +  while (len && s[len - 1] == ' ')
   1.204 +    len--;
   1.205 +  if (feature->start != 0 || feature->end != (unsigned int) -1)
   1.206 +  {
   1.207 +    s[len++] = '[';
   1.208 +    if (feature->start)
   1.209 +      len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start));
   1.210 +    if (feature->end != feature->start + 1) {
   1.211 +      s[len++] = ':';
   1.212 +      if (feature->end != (unsigned int) -1)
   1.213 +	len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end));
   1.214 +    }
   1.215 +    s[len++] = ']';
   1.216 +  }
   1.217 +  if (feature->value > 1)
   1.218 +  {
   1.219 +    s[len++] = '=';
   1.220 +    len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value));
   1.221 +  }
   1.222 +  assert (len < ARRAY_LENGTH (s));
   1.223 +  len = MIN (len, size - 1);
   1.224 +  memcpy (buf, s, len);
   1.225 +  buf[len] = '\0';
   1.226 +}
   1.227 +
   1.228 +
   1.229 +static const char **static_shaper_list;
   1.230 +
   1.231 +static inline
   1.232 +void free_static_shaper_list (void)
   1.233 +{
   1.234 +  free (static_shaper_list);
   1.235 +}
   1.236 +
   1.237 +/**
   1.238 + * hb_shape_list_shapers:
   1.239 + *
   1.240 + * 
   1.241 + *
   1.242 + * Return value: (transfer none):
   1.243 + *
   1.244 + * Since: 1.0
   1.245 + **/
   1.246 +const char **
   1.247 +hb_shape_list_shapers (void)
   1.248 +{
   1.249 +retry:
   1.250 +  const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
   1.251 +
   1.252 +  if (unlikely (!shaper_list))
   1.253 +  {
   1.254 +    /* Not found; allocate one. */
   1.255 +    shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
   1.256 +    if (unlikely (!shaper_list)) {
   1.257 +      static const char *nil_shaper_list[] = {NULL};
   1.258 +      return nil_shaper_list;
   1.259 +    }
   1.260 +
   1.261 +    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
   1.262 +    unsigned int i;
   1.263 +    for (i = 0; i < HB_SHAPERS_COUNT; i++)
   1.264 +      shaper_list[i] = shapers[i].name;
   1.265 +    shaper_list[i] = NULL;
   1.266 +
   1.267 +    if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
   1.268 +      free (shaper_list);
   1.269 +      goto retry;
   1.270 +    }
   1.271 +
   1.272 +#ifdef HAVE_ATEXIT
   1.273 +    atexit (free_static_shaper_list); /* First person registers atexit() callback. */
   1.274 +#endif
   1.275 +  }
   1.276 +
   1.277 +  return shaper_list;
   1.278 +}
   1.279 +
   1.280 +
   1.281 +/**
   1.282 + * hb_shape_full:
   1.283 + * @font: a font.
   1.284 + * @buffer: a buffer.
   1.285 + * @features: (array length=num_features):
   1.286 + * @num_features: 
   1.287 + * @shaper_list: (array zero-terminated=1):
   1.288 + *
   1.289 + * 
   1.290 + *
   1.291 + * Return value: 
   1.292 + *
   1.293 + * Since: 1.0
   1.294 + **/
   1.295 +hb_bool_t
   1.296 +hb_shape_full (hb_font_t          *font,
   1.297 +	       hb_buffer_t        *buffer,
   1.298 +	       const hb_feature_t *features,
   1.299 +	       unsigned int        num_features,
   1.300 +	       const char * const *shaper_list)
   1.301 +{
   1.302 +  if (unlikely (!buffer->len))
   1.303 +    return true;
   1.304 +
   1.305 +  assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
   1.306 +
   1.307 +  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
   1.308 +  hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
   1.309 +  hb_shape_plan_destroy (shape_plan);
   1.310 +
   1.311 +  if (res)
   1.312 +    buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
   1.313 +  return res;
   1.314 +}
   1.315 +
   1.316 +/**
   1.317 + * hb_shape:
   1.318 + * @font: a font.
   1.319 + * @buffer: a buffer.
   1.320 + * @features: (array length=num_features):
   1.321 + * @num_features: 
   1.322 + *
   1.323 + * 
   1.324 + *
   1.325 + * Since: 1.0
   1.326 + **/
   1.327 +void
   1.328 +hb_shape (hb_font_t           *font,
   1.329 +	  hb_buffer_t         *buffer,
   1.330 +	  const hb_feature_t  *features,
   1.331 +	  unsigned int         num_features)
   1.332 +{
   1.333 +  hb_shape_full (font, buffer, features, num_features, NULL);
   1.334 +}

mercurial