Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: third_party/harfbuzz-ng/src/hb-shape.cc

Issue 10915172: harfbuzz-ng roll (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-shape.h ('k') | third_party/harfbuzz-ng/src/hb-shape-plan.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright © 2009 Red Hat, Inc. 2 * Copyright © 2009 Red Hat, Inc.
3 * Copyright © 2012 Google, Inc.
3 * 4 *
4 * This is part of HarfBuzz, a text shaping library. 5 * This is part of HarfBuzz, a text shaping library.
5 * 6 *
6 * Permission is hereby granted, without written agreement and without 7 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this 8 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the 9 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in 10 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software. 11 * all copies of this software.
11 * 12 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE. 17 * DAMAGE.
17 * 18 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 * 24 *
24 * Red Hat Author(s): Behdad Esfahbod 25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
25 */ 27 */
26 28
27 #include "hb-private.hh" 29 #include "hb-private.hh"
28 30
29 #include "hb-shape.h" 31 #include "hb-shaper-private.hh"
30 32 #include "hb-shape-plan-private.hh"
31 #include "hb-buffer-private.hh" 33 #include "hb-buffer-private.hh"
32 34 #include "hb-font-private.hh"
33 #ifdef HAVE_GRAPHITE
34 #include "hb-graphite2-private.hh"
35 #endif
36 #ifdef HAVE_UNISCRIBE
37 # include "hb-uniscribe-private.hh"
38 #endif
39 #ifdef HAVE_OT
40 # include "hb-ot-shape-private.hh"
41 #endif
42 #include "hb-fallback-shape-private.hh"
43
44 typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font,
45 » » » » hb_buffer_t *buffer,
46 » » » » const hb_feature_t *features,
47 » » » » unsigned int num_features);
48
49 #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape}
50 static const struct hb_shaper_pair_t {
51 char name[16];
52 hb_shape_func_t func;
53 } all_shapers[] = {
54 /* v--- Add new shapers in the right place here */
55 #ifdef HAVE_GRAPHITE
56 HB_SHAPER_IMPLEMENT (graphite2),
57 #endif
58 #ifdef HAVE_UNISCRIBE
59 HB_SHAPER_IMPLEMENT (uniscribe),
60 #endif
61 #ifdef HAVE_OT
62 HB_SHAPER_IMPLEMENT (ot),
63 #endif
64 HB_SHAPER_IMPLEMENT (fallback) /* should be last */
65 };
66 #undef HB_SHAPER_IMPLEMENT
67 35
68 36
69 /* Thread-safe, lock-free, shapers */ 37 static void
70 38 parse_space (const char **pp, const char *end)
71 static hb_shaper_pair_t *static_shapers;
72
73 static
74 void free_static_shapers (void)
75 { 39 {
76 if (unlikely (static_shapers != all_shapers)) 40 char c;
77 free (static_shapers); 41 #define ISSPACE(c) ((c)==' '||(c)=='\f'||(c)=='\n'||(c)=='\r'||(c)=='\t'||(c)==' \v')
42 while (*pp < end && (c = **pp, ISSPACE (c)))
43 (*pp)++;
44 #undef ISSPACE
78 } 45 }
79 46
80 static const hb_shaper_pair_t * 47 static hb_bool_t
81 get_shapers (void) 48 parse_char (const char **pp, const char *end, char c)
82 { 49 {
83 retry: 50 parse_space (pp, end);
84 hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_sh apers);
85 51
86 if (unlikely (!shapers)) 52 if (*pp == end || **pp != c)
87 { 53 return false;
88 char *env = getenv ("HB_SHAPER_LIST");
89 if (!env || !*env) {
90 (void) hb_atomic_ptr_cmpexch (&static_shapers, NULL, (const hb_shaper_pair _t *) all_shapers);
91 return (const hb_shaper_pair_t *) all_shapers;
92 }
93 54
94 /* Not found; allocate one. */ 55 (*pp)++;
95 shapers = (hb_shaper_pair_t *) malloc (sizeof (all_shapers)); 56 return true;
96 if (unlikely (!shapers)) 57 }
97 return (const hb_shaper_pair_t *) all_shapers;
98 memcpy (shapers, all_shapers, sizeof (all_shapers));
99 58
100 /* Reorder shaper list to prefer requested shapers. */ 59 static hb_bool_t
101 unsigned int i = 0; 60 parse_uint (const char **pp, const char *end, unsigned int *pv)
102 char *end, *p = env; 61 {
103 for (;;) { 62 char buf[32];
104 end = strchr (p, ','); 63 strncpy (buf, *pp, end - *pp);
105 if (!end) 64 buf[ARRAY_LENGTH (buf) - 1] = '\0';
106 » end = p + strlen (p);
107 65
108 for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++) 66 char *p = buf;
109 » if (end - p == (int) strlen (shapers[j].name) && 67 char *pend = p;
110 » 0 == strncmp (shapers[j].name, p, end - p)) 68 unsigned int v;
111 » {
112 » /* Reorder this shaper to position i */
113 » struct hb_shaper_pair_t t = shapers[j];
114 » memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
115 » shapers[i] = t;
116 » i++;
117 » }
118 69
119 if (!*end) 70 v = strtol (p, &pend, 0);
120 » break;
121 else
122 » p = end + 1;
123 }
124 71
125 if (!hb_atomic_ptr_cmpexch (&static_shapers, NULL, shapers)) { 72 if (p == pend)
126 free (shapers); 73 return false;
127 goto retry;
128 }
129 74
130 #ifdef HAVE_ATEXIT 75 *pv = v;
131 atexit (free_static_shapers); /* First person registers atexit() callback. * / 76 *pp += pend - p;
132 #endif 77 return true;
78 }
79
80 static hb_bool_t
81 parse_feature_value_prefix (const char **pp, const char *end, hb_feature_t *feat ure)
82 {
83 if (parse_char (pp, end, '-'))
84 feature->value = 0;
85 else {
86 parse_char (pp, end, '+');
87 feature->value = 1;
133 } 88 }
134 89
135 return shapers; 90 return true;
91 }
92
93 static hb_bool_t
94 parse_feature_tag (const char **pp, const char *end, hb_feature_t *feature)
95 {
96 const char *p = *pp;
97 char c;
98
99 parse_space (pp, end);
100
101 #define ISALNUM(c) (('a' <= (c) && (c) <= 'z') || ('A' <= (c) && (c) <= 'Z') || ('0' <= (c) && (c) <= '9'))
102 while (*pp < end && (c = **pp, ISALNUM(c)))
103 (*pp)++;
104 #undef ISALNUM
105
106 if (p == *pp)
107 return false;
108
109 feature->tag = hb_tag_from_string (p, *pp - p);
110 return true;
111 }
112
113 static hb_bool_t
114 parse_feature_indices (const char **pp, const char *end, hb_feature_t *feature)
115 {
116 parse_space (pp, end);
117
118 hb_bool_t has_start;
119
120 feature->start = 0;
121 feature->end = (unsigned int) -1;
122
123 if (!parse_char (pp, end, '['))
124 return true;
125
126 has_start = parse_uint (pp, end, &feature->start);
127
128 if (parse_char (pp, end, ':')) {
129 parse_uint (pp, end, &feature->end);
130 } else {
131 if (has_start)
132 feature->end = feature->start + 1;
133 }
134
135 return parse_char (pp, end, ']');
136 }
137
138 static hb_bool_t
139 parse_feature_value_postfix (const char **pp, const char *end, hb_feature_t *fea ture)
140 {
141 return !parse_char (pp, end, '=') || parse_uint (pp, end, &feature->value);
136 } 142 }
137 143
138 144
145 static hb_bool_t
146 parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
147 {
148 return parse_feature_value_prefix (pp, end, feature) &&
149 parse_feature_tag (pp, end, feature) &&
150 parse_feature_indices (pp, end, feature) &&
151 parse_feature_value_postfix (pp, end, feature) &&
152 *pp == end;
153 }
154
155 hb_bool_t
156 hb_feature_from_string (const char *str, int len,
157 hb_feature_t *feature)
158 {
159 if (len < 0)
160 len = strlen (str);
161
162 return parse_one_feature (&str, str + len, feature);
163 }
164
165 void
166 hb_feature_to_string (hb_feature_t *feature,
167 char *buf, unsigned int size)
168 {
169 if (unlikely (!size)) return;
170
171 char s[128];
172 unsigned int len = 0;
173 if (feature->value == 0)
174 s[len++] = '-';
175 hb_tag_to_string (feature->tag, s + len);
176 len += 4;
177 while (len && s[len - 1] == ' ')
178 len--;
179 if (feature->start != 0 || feature->start != (unsigned int) -1)
180 {
181 s[len++] = '[';
182 if (feature->start)
183 len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->start);
184 if (feature->end != feature->start + 1) {
185 s[len++] = ':';
186 if (feature->end != (unsigned int) -1)
187 len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->end);
188 }
189 s[len++] = ']';
190 }
191 if (feature->value > 1)
192 {
193 s[len++] = '=';
194 len += snprintf (s + len, ARRAY_LENGTH (s) - len, "%d", feature->value);
195 }
196 assert (len < ARRAY_LENGTH (s));
197 len = MIN (len, size - 1);
198 memcpy (buf, s, len);
199 s[len] = '\0';
200 }
201
202
139 static const char **static_shaper_list; 203 static const char **static_shaper_list;
140 204
141 static 205 static
142 void free_static_shaper_list (void) 206 void free_static_shaper_list (void)
143 { 207 {
144 free (static_shaper_list); 208 free (static_shaper_list);
145 } 209 }
146 210
147 const char ** 211 const char **
148 hb_shape_list_shapers (void) 212 hb_shape_list_shapers (void)
149 { 213 {
150 retry: 214 retry:
151 const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_l ist); 215 const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_l ist);
152 216
153 if (unlikely (!shaper_list)) 217 if (unlikely (!shaper_list))
154 { 218 {
155 /* Not found; allocate one. */ 219 /* Not found; allocate one. */
156 shaper_list = (const char **) calloc (1 + ARRAY_LENGTH (all_shapers), sizeof (const char *)); 220 shaper_list = (const char **) calloc (1 + HB_SHAPERS_COUNT, sizeof (const ch ar *));
157 if (unlikely (!shaper_list)) { 221 if (unlikely (!shaper_list)) {
158 static const char *nil_shaper_list[] = {NULL}; 222 static const char *nil_shaper_list[] = {NULL};
159 return nil_shaper_list; 223 return nil_shaper_list;
160 } 224 }
161 225
162 const hb_shaper_pair_t *shapers = get_shapers (); 226 const hb_shaper_pair_t *shapers = _hb_shapers_get ();
163 unsigned int i; 227 unsigned int i;
164 for (i = 0; i < ARRAY_LENGTH (all_shapers); i++) 228 for (i = 0; i < HB_SHAPERS_COUNT; i++)
165 shaper_list[i] = shapers[i].name; 229 shaper_list[i] = shapers[i].name;
166 shaper_list[i] = NULL; 230 shaper_list[i] = NULL;
167 231
168 if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) { 232 if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
169 free (shaper_list); 233 free (shaper_list);
170 goto retry; 234 goto retry;
171 } 235 }
172 236
173 #ifdef HAVE_ATEXIT 237 #ifdef HAVE_ATEXIT
174 atexit (free_static_shaper_list); /* First person registers atexit() callbac k. */ 238 atexit (free_static_shaper_list); /* First person registers atexit() callbac k. */
175 #endif 239 #endif
176 } 240 }
177 241
178 return shaper_list; 242 return shaper_list;
179 } 243 }
180 244
181 245
182 hb_bool_t 246 hb_bool_t
183 hb_shape_full (hb_font_t *font, 247 hb_shape_full (hb_font_t *font,
184 hb_buffer_t *buffer, 248 hb_buffer_t *buffer,
185 const hb_feature_t *features, 249 const hb_feature_t *features,
186 unsigned int num_features, 250 unsigned int num_features,
187 const char * const *shaper_list) 251 const char * const *shaper_list)
188 { 252 {
189 hb_font_make_immutable (font); /* So we can safely cache stuff on it */ 253 if (unlikely (!buffer->len))
254 return true;
190 255
191 if (likely (!shaper_list)) { 256 assert (buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE);
192 const hb_shaper_pair_t *shapers = get_shapers (); 257
193 for (unsigned int i = 0; i < ARRAY_LENGTH (all_shapers); i++) 258 buffer->guess_properties ();
194 if (likely (shapers[i].func (font, buffer, features, num_features))) 259
195 return true; 260 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer ->props, features, num_features, shaper_list);
196 } else { 261 hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num _features);
197 while (*shaper_list) { 262 hb_shape_plan_destroy (shape_plan);
198 for (unsigned int i = 0; i < ARRAY_LENGTH (all_shapers); i++) 263
199 » if (0 == strcmp (*shaper_list, all_shapers[i].name)) { 264 if (res)
200 » if (likely (all_shapers[i].func (font, buffer, features, num_features) )) 265 buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
201 » return true; 266 return res;
202 » break;
203 » }
204 shaper_list++;
205 }
206 }
207 return false;
208 } 267 }
209 268
210 void 269 void
211 hb_shape (hb_font_t *font, 270 hb_shape (hb_font_t *font,
212 hb_buffer_t *buffer, 271 hb_buffer_t *buffer,
213 const hb_feature_t *features, 272 const hb_feature_t *features,
214 unsigned int num_features) 273 unsigned int num_features)
215 { 274 {
216 hb_shape_full (font, buffer, features, num_features, NULL); 275 hb_shape_full (font, buffer, features, num_features, NULL);
217 } 276 }
OLDNEW
« no previous file with comments | « third_party/harfbuzz-ng/src/hb-shape.h ('k') | third_party/harfbuzz-ng/src/hb-shape-plan.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698