gfx/harfbuzz/src/hb-shape.cc

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial