gfx/harfbuzz/src/hb-shape.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright © 2009 Red Hat, Inc.
michael@0 3 * Copyright © 2012 Google, Inc.
michael@0 4 *
michael@0 5 * This is part of HarfBuzz, a text shaping library.
michael@0 6 *
michael@0 7 * Permission is hereby granted, without written agreement and without
michael@0 8 * license or royalty fees, to use, copy, modify, and distribute this
michael@0 9 * software and its documentation for any purpose, provided that the
michael@0 10 * above copyright notice and the following two paragraphs appear in
michael@0 11 * all copies of this software.
michael@0 12 *
michael@0 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
michael@0 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
michael@0 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
michael@0 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
michael@0 17 * DAMAGE.
michael@0 18 *
michael@0 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
michael@0 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
michael@0 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
michael@0 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
michael@0 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
michael@0 24 *
michael@0 25 * Red Hat Author(s): Behdad Esfahbod
michael@0 26 * Google Author(s): Behdad Esfahbod
michael@0 27 */
michael@0 28
michael@0 29 #include "hb-private.hh"
michael@0 30
michael@0 31 #include "hb-shaper-private.hh"
michael@0 32 #include "hb-shape-plan-private.hh"
michael@0 33 #include "hb-buffer-private.hh"
michael@0 34 #include "hb-font-private.hh"
michael@0 35
michael@0 36
michael@0 37 static void
michael@0 38 parse_space (const char **pp, const char *end)
michael@0 39 {
michael@0 40 char c;
michael@0 41 while (*pp < end && (c = **pp, ISSPACE (c)))
michael@0 42 (*pp)++;
michael@0 43 }
michael@0 44
michael@0 45 static hb_bool_t
michael@0 46 parse_char (const char **pp, const char *end, char c)
michael@0 47 {
michael@0 48 parse_space (pp, end);
michael@0 49
michael@0 50 if (*pp == end || **pp != c)
michael@0 51 return false;
michael@0 52
michael@0 53 (*pp)++;
michael@0 54 return true;
michael@0 55 }
michael@0 56
michael@0 57 static hb_bool_t
michael@0 58 parse_uint (const char **pp, const char *end, unsigned int *pv)
michael@0 59 {
michael@0 60 char buf[32];
michael@0 61 unsigned int len = MIN (ARRAY_LENGTH (buf) - 1, (unsigned int) (end - *pp));
michael@0 62 strncpy (buf, *pp, len);
michael@0 63 buf[len] = '\0';
michael@0 64
michael@0 65 char *p = buf;
michael@0 66 char *pend = p;
michael@0 67 unsigned int v;
michael@0 68
michael@0 69 /* Intentionally use strtol instead of strtoul, such that
michael@0 70 * -1 turns into "big number"... */
michael@0 71 errno = 0;
michael@0 72 v = strtol (p, &pend, 0);
michael@0 73 if (errno || p == pend)
michael@0 74 return false;
michael@0 75
michael@0 76 *pv = v;
michael@0 77 *pp += pend - p;
michael@0 78 return true;
michael@0 79 }
michael@0 80
michael@0 81 static hb_bool_t
michael@0 82 parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feature)
michael@0 83 {
michael@0 84 if (parse_char (pp, end, '-'))
michael@0 85 feature->value = 0;
michael@0 86 else {
michael@0 87 parse_char (pp, end, '+');
michael@0 88 feature->value = 1;
michael@0 89 }
michael@0 90
michael@0 91 return true;
michael@0 92 }
michael@0 93
michael@0 94 static hb_bool_t
michael@0 95 parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
michael@0 96 {
michael@0 97 const char *p = *pp;
michael@0 98 char c;
michael@0 99
michael@0 100 parse_space (pp, end);
michael@0 101
michael@0 102 #define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
michael@0 103 while (*pp < end && (c = **pp, ISALNUM(c)))
michael@0 104 (*pp)++;
michael@0 105 #undef ISALNUM
michael@0 106
michael@0 107 if (p == *pp)
michael@0 108 return false;
michael@0 109
michael@0 110 feature->tag = hb_tag_from_string (p, *pp - p);
michael@0 111 return true;
michael@0 112 }
michael@0 113
michael@0 114 static hb_bool_t
michael@0 115 parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
michael@0 116 {
michael@0 117 parse_space (pp, end);
michael@0 118
michael@0 119 hb_bool_t has_start;
michael@0 120
michael@0 121 feature->start = 0;
michael@0 122 feature->end = (unsigned int) -1;
michael@0 123
michael@0 124 if (!parse_char (pp, end, '['))
michael@0 125 return true;
michael@0 126
michael@0 127 has_start = parse_uint (pp, end, &feature->start);
michael@0 128
michael@0 129 if (parse_char (pp, end, ':')) {
michael@0 130 parse_uint (pp, end, &feature->end);
michael@0 131 } else {
michael@0 132 if (has_start)
michael@0 133 feature->end = feature->start + 1;
michael@0 134 }
michael@0 135
michael@0 136 return parse_char (pp, end, ']');
michael@0 137 }
michael@0 138
michael@0 139 static hb_bool_t
michael@0 140 parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *feature)
michael@0 141 {
michael@0 142 return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value);
michael@0 143 }
michael@0 144
michael@0 145
michael@0 146 static hb_bool_t
michael@0 147 parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
michael@0 148 {
michael@0 149 return parse_feature_value_prefix (pp, end, feature) &&
michael@0 150 parse_feature_tag (pp, end, feature) &&
michael@0 151 parse_feature_indices (pp, end, feature) &&
michael@0 152 parse_feature_value_postfix (pp, end, feature) &&
michael@0 153 *pp == end;
michael@0 154 }
michael@0 155
michael@0 156 /**
michael@0 157 * hb_feature_from_string:
michael@0 158 * @str: (array length=len):
michael@0 159 * @len:
michael@0 160 * @feature: (out):
michael@0 161 *
michael@0 162 *
michael@0 163 *
michael@0 164 * Return value:
michael@0 165 *
michael@0 166 * Since: 1.0
michael@0 167 **/
michael@0 168 hb_bool_t
michael@0 169 hb_feature_from_string (const char *str, int len,
michael@0 170 hb_feature_t *feature)
michael@0 171 {
michael@0 172 if (len < 0)
michael@0 173 len = strlen (str);
michael@0 174
michael@0 175 return parse_one_feature (&str, str + len, feature);
michael@0 176 }
michael@0 177
michael@0 178 /**
michael@0 179 * hb_feature_to_string:
michael@0 180 * @feature:
michael@0 181 * @buf: (array length=size):
michael@0 182 * @size:
michael@0 183 *
michael@0 184 *
michael@0 185 *
michael@0 186 * Since: 1.0
michael@0 187 **/
michael@0 188 void
michael@0 189 hb_feature_to_string (hb_feature_t *feature,
michael@0 190 char *buf, unsigned int size)
michael@0 191 {
michael@0 192 if (unlikely (!size)) return;
michael@0 193
michael@0 194 char s[128];
michael@0 195 unsigned int len = 0;
michael@0 196 if (feature->value == 0)
michael@0 197 s[len++] = '-';
michael@0 198 hb_tag_to_string (feature->tag, s + len);
michael@0 199 len += 4;
michael@0 200 while (len && s[len - 1] == ' ')
michael@0 201 len--;
michael@0 202 if (feature->start != 0 || feature->end != (unsigned int) -1)
michael@0 203 {
michael@0 204 s[len++] = '[';
michael@0 205 if (feature->start)
michael@0 206 len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start));
michael@0 207 if (feature->end != feature->start + 1) {
michael@0 208 s[len++] = ':';
michael@0 209 if (feature->end != (unsigned int) -1)
michael@0 210 len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end));
michael@0 211 }
michael@0 212 s[len++] = ']';
michael@0 213 }
michael@0 214 if (feature->value > 1)
michael@0 215 {
michael@0 216 s[len++] = '=';
michael@0 217 len += MAX (0, snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value));
michael@0 218 }
michael@0 219 assert (len < ARRAY_LENGTH (s));
michael@0 220 len = MIN (len, size - 1);
michael@0 221 memcpy (buf, s, len);
michael@0 222 buf[len] = '\0';
michael@0 223 }
michael@0 224
michael@0 225
michael@0 226 static const char **static_shaper_list;
michael@0 227
michael@0 228 static inline
michael@0 229 void free_static_shaper_list (void)
michael@0 230 {
michael@0 231 free (static_shaper_list);
michael@0 232 }
michael@0 233
michael@0 234 /**
michael@0 235 * hb_shape_list_shapers:
michael@0 236 *
michael@0 237 *
michael@0 238 *
michael@0 239 * Return value: (transfer none):
michael@0 240 *
michael@0 241 * Since: 1.0
michael@0 242 **/
michael@0 243 const char **
michael@0 244 hb_shape_list_shapers (void)
michael@0 245 {
michael@0 246 retry:
michael@0 247 const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
michael@0 248
michael@0 249 if (unlikely (!shaper_list))
michael@0 250 {
michael@0 251 /* Not found; allocate one. */
michael@0 252 shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const char *));
michael@0 253 if (unlikely (!shaper_list)) {
michael@0 254 static const char *nil_shaper_list[] = {NULL};
michael@0 255 return nil_shaper_list;
michael@0 256 }
michael@0 257
michael@0 258 const hb_shaper_pair_t *shapers = _hb_shapers_get ();
michael@0 259 unsigned int i;
michael@0 260 for (i = 0; i < HB_SHAPERS_COUNT; i++)
michael@0 261 shaper_list[i] = shapers[i].name;
michael@0 262 shaper_list[i] = NULL;
michael@0 263
michael@0 264 if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
michael@0 265 free (shaper_list);
michael@0 266 goto retry;
michael@0 267 }
michael@0 268
michael@0 269 #ifdef HAVE_ATEXIT
michael@0 270 atexit (free_static_shaper_list); /* First person registers atexit() callback. */
michael@0 271 #endif
michael@0 272 }
michael@0 273
michael@0 274 return shaper_list;
michael@0 275 }
michael@0 276
michael@0 277
michael@0 278 /**
michael@0 279 * hb_shape_full:
michael@0 280 * @font: a font.
michael@0 281 * @buffer: a buffer.
michael@0 282 * @features: (array length=num_features):
michael@0 283 * @num_features:
michael@0 284 * @shaper_list: (array zero-terminated=1):
michael@0 285 *
michael@0 286 *
michael@0 287 *
michael@0 288 * Return value:
michael@0 289 *
michael@0 290 * Since: 1.0
michael@0 291 **/
michael@0 292 hb_bool_t
michael@0 293 hb_shape_full (hb_font_t *font,
michael@0 294 hb_buffer_t *buffer,
michael@0 295 const hb_feature_t *features,
michael@0 296 unsigned int num_features,
michael@0 297 const char * const *shaper_list)
michael@0 298 {
michael@0 299 if (unlikely (!buffer->len))
michael@0 300 return true;
michael@0 301
michael@0 302 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
michael@0 303
michael@0 304 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list);
michael@0 305 hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
michael@0 306 hb_shape_plan_destroy (shape_plan);
michael@0 307
michael@0 308 if (res)
michael@0 309 buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
michael@0 310 return res;
michael@0 311 }
michael@0 312
michael@0 313 /**
michael@0 314 * hb_shape:
michael@0 315 * @font: a font.
michael@0 316 * @buffer: a buffer.
michael@0 317 * @features: (array length=num_features):
michael@0 318 * @num_features:
michael@0 319 *
michael@0 320 *
michael@0 321 *
michael@0 322 * Since: 1.0
michael@0 323 **/
michael@0 324 void
michael@0 325 hb_shape (hb_font_t *font,
michael@0 326 hb_buffer_t *buffer,
michael@0 327 const hb_feature_t *features,
michael@0 328 unsigned int num_features)
michael@0 329 {
michael@0 330 hb_shape_full (font, buffer, features, num_features, NULL);
michael@0 331 }

mercurial