File: | jdk/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc |
Warning: | line 324, column 3 Argument to free() is the address of the global variable '_hb_NullPool', which is not memory allocated by malloc() |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright © 2012 Google, Inc. | |||
3 | * | |||
4 | * This is part of HarfBuzz, a text shaping library. | |||
5 | * | |||
6 | * Permission is hereby granted, without written agreement and without | |||
7 | * license or royalty fees, to use, copy, modify, and distribute this | |||
8 | * software and its documentation for any purpose, provided that the | |||
9 | * above copyright notice and the following two paragraphs appear in | |||
10 | * all copies of this software. | |||
11 | * | |||
12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | |||
13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | |||
14 | * 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 | * DAMAGE. | |||
17 | * | |||
18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | |||
19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
20 | * 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 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |||
23 | * | |||
24 | * Google Author(s): Behdad Esfahbod | |||
25 | */ | |||
26 | ||||
27 | #include "hb.hh" | |||
28 | #include "hb-shape-plan.hh" | |||
29 | #include "hb-shaper.hh" | |||
30 | #include "hb-font.hh" | |||
31 | #include "hb-buffer.hh" | |||
32 | ||||
33 | ||||
34 | /** | |||
35 | * SECTION:hb-shape-plan | |||
36 | * @title: hb-shape-plan | |||
37 | * @short_description: Object representing a shaping plan | |||
38 | * @include: hb.h | |||
39 | * | |||
40 | * Shape plans are an internal mechanism. Each plan contains state | |||
41 | * describing how HarfBuzz will shape a particular text segment, based on | |||
42 | * the combination of segment properties and the capabilities in the | |||
43 | * font face in use. | |||
44 | * | |||
45 | * Shape plans are not used for shaping directly, but can be queried to | |||
46 | * access certain information about how shaping will perform, given a set | |||
47 | * of specific input parameters (script, language, direction, features, | |||
48 | * etc.). | |||
49 | * | |||
50 | * Most client programs will not need to deal with shape plans directly. | |||
51 | **/ | |||
52 | ||||
53 | ||||
54 | /* | |||
55 | * hb_shape_plan_key_t | |||
56 | */ | |||
57 | ||||
58 | bool | |||
59 | hb_shape_plan_key_t::init (bool copy, | |||
60 | hb_face_t *face, | |||
61 | const hb_segment_properties_t *props, | |||
62 | const hb_feature_t *user_features, | |||
63 | unsigned int num_user_features, | |||
64 | const int *coords, | |||
65 | unsigned int num_coords, | |||
66 | const char * const *shaper_list) | |||
67 | { | |||
68 | hb_feature_t *features = nullptr; | |||
69 | if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) | |||
70 | goto bail; | |||
71 | ||||
72 | this->props = *props; | |||
73 | this->num_user_features = num_user_features; | |||
74 | this->user_features = copy ? features : user_features; | |||
75 | if (copy && num_user_features) | |||
76 | { | |||
77 | memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); | |||
78 | /* Make start/end uniform to easier catch bugs. */ | |||
79 | for (unsigned int i = 0; i < num_user_features; i++) | |||
80 | { | |||
81 | if (features[0].start != HB_FEATURE_GLOBAL_START0) | |||
82 | features[0].start = 1; | |||
83 | if (features[0].end != HB_FEATURE_GLOBAL_END((unsigned int) -1)) | |||
84 | features[0].end = 2; | |||
85 | } | |||
86 | } | |||
87 | this->shaper_func = nullptr; | |||
88 | this->shaper_name = nullptr; | |||
89 | #ifndef HB_NO_OT_SHAPE | |||
90 | this->ot.init (face, coords, num_coords); | |||
91 | #endif | |||
92 | ||||
93 | /* | |||
94 | * Choose shaper. | |||
95 | */ | |||
96 | ||||
97 | #define HB_SHAPER_PLAN(shaper) \ | |||
98 | HB_STMT_STARTdo { \ | |||
99 | if (face->data.shaper) \ | |||
100 | { \ | |||
101 | this->shaper_func = _hb_##shaper##_shape; \ | |||
102 | this->shaper_name = #shaper; \ | |||
103 | return true; \ | |||
104 | } \ | |||
105 | } HB_STMT_ENDwhile (0) | |||
106 | ||||
107 | if (unlikely (shaper_list)(__builtin_expect (!!(shaper_list), 0))) | |||
108 | { | |||
109 | for (; *shaper_list; shaper_list++) | |||
110 | if (false) | |||
111 | ; | |||
112 | #define HB_SHAPER_IMPLEMENT(shaper) \ | |||
113 | else if (0 == strcmp (*shaper_list, #shaper)) \ | |||
114 | HB_SHAPER_PLAN (shaper); | |||
115 | #include "hb-shaper-list.hh" | |||
116 | #undef HB_SHAPER_IMPLEMENT | |||
117 | } | |||
118 | else | |||
119 | { | |||
120 | const hb_shaper_entry_t *shapers = _hb_shapers_get (); | |||
121 | for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) | |||
122 | if (false) | |||
123 | ; | |||
124 | #define HB_SHAPER_IMPLEMENT(shaper) \ | |||
125 | else if (shapers[i].func == _hb_##shaper##_shape) \ | |||
126 | HB_SHAPER_PLAN (shaper); | |||
127 | #include "hb-shaper-list.hh" | |||
128 | #undef HB_SHAPER_IMPLEMENT | |||
129 | } | |||
130 | #undef HB_SHAPER_PLAN | |||
131 | ||||
132 | bail: | |||
133 | ::free (features); | |||
134 | return false; | |||
135 | } | |||
136 | ||||
137 | bool | |||
138 | hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other) | |||
139 | { | |||
140 | if (this->num_user_features != other->num_user_features) | |||
141 | return false; | |||
142 | for (unsigned int i = 0; i < num_user_features; i++) | |||
143 | { | |||
144 | if (this->user_features[i].tag != other->user_features[i].tag || | |||
145 | this->user_features[i].value != other->user_features[i].value || | |||
146 | (this->user_features[i].start == HB_FEATURE_GLOBAL_START0 && | |||
147 | this->user_features[i].end == HB_FEATURE_GLOBAL_END((unsigned int) -1)) != | |||
148 | (other->user_features[i].start == HB_FEATURE_GLOBAL_START0 && | |||
149 | other->user_features[i].end == HB_FEATURE_GLOBAL_END((unsigned int) -1))) | |||
150 | return false; | |||
151 | } | |||
152 | return true; | |||
153 | } | |||
154 | ||||
155 | bool | |||
156 | hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other) | |||
157 | { | |||
158 | return hb_segment_properties_equal (&this->props, &other->props) && | |||
159 | this->user_features_match (other) && | |||
160 | #ifndef HB_NO_OT_SHAPE | |||
161 | this->ot.equal (&other->ot) && | |||
162 | #endif | |||
163 | this->shaper_func == other->shaper_func; | |||
164 | } | |||
165 | ||||
166 | ||||
167 | /* | |||
168 | * hb_shape_plan_t | |||
169 | */ | |||
170 | ||||
171 | ||||
172 | /** | |||
173 | * hb_shape_plan_create: (Xconstructor) | |||
174 | * @face: #hb_face_t to use | |||
175 | * @props: The #hb_segment_properties_t of the segment | |||
176 | * @user_features: (array length=num_user_features): The list of user-selected features | |||
177 | * @num_user_features: The number of user-selected features | |||
178 | * @shaper_list: (array zero-terminated=1): List of shapers to try | |||
179 | * | |||
180 | * Constructs a shaping plan for a combination of @face, @user_features, @props, | |||
181 | * and @shaper_list. | |||
182 | * | |||
183 | * Return value: (transfer full): The shaping plan | |||
184 | * | |||
185 | * Since: 0.9.7 | |||
186 | **/ | |||
187 | hb_shape_plan_t * | |||
188 | hb_shape_plan_create (hb_face_t *face, | |||
189 | const hb_segment_properties_t *props, | |||
190 | const hb_feature_t *user_features, | |||
191 | unsigned int num_user_features, | |||
192 | const char * const *shaper_list) | |||
193 | { | |||
194 | return hb_shape_plan_create2 (face, props, | |||
195 | user_features, num_user_features, | |||
196 | nullptr, 0, | |||
197 | shaper_list); | |||
198 | } | |||
199 | ||||
200 | /** | |||
201 | * hb_shape_plan_create2: (Xconstructor) | |||
202 | * @face: #hb_face_t to use | |||
203 | * @props: The #hb_segment_properties_t of the segment | |||
204 | * @user_features: (array length=num_user_features): The list of user-selected features | |||
205 | * @num_user_features: The number of user-selected features | |||
206 | * @coords: (array length=num_coords): The list of variation-space coordinates | |||
207 | * @num_coords: The number of variation-space coordinates | |||
208 | * @shaper_list: (array zero-terminated=1): List of shapers to try | |||
209 | * | |||
210 | * The variable-font version of #hb_shape_plan_create. | |||
211 | * Constructs a shaping plan for a combination of @face, @user_features, @props, | |||
212 | * and @shaper_list, plus the variation-space coordinates @coords. | |||
213 | * | |||
214 | * Return value: (transfer full): The shaping plan | |||
215 | * | |||
216 | * Since: 1.4.0 | |||
217 | **/ | |||
218 | hb_shape_plan_t * | |||
219 | hb_shape_plan_create2 (hb_face_t *face, | |||
220 | const hb_segment_properties_t *props, | |||
221 | const hb_feature_t *user_features, | |||
222 | unsigned int num_user_features, | |||
223 | const int *coords, | |||
224 | unsigned int num_coords, | |||
225 | const char * const *shaper_list) | |||
226 | { | |||
227 | DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list) | |||
228 | "face=%p num_features=%d num_coords=%d shaper_list=%p",_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list) | |||
229 | face,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list) | |||
230 | num_user_features,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list) | |||
231 | num_coords,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list) | |||
232 | shaper_list)_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d num_coords=%d shaper_list=%p" , face, num_user_features, num_coords, shaper_list); | |||
233 | ||||
234 | assert (props->direction != HB_DIRECTION_INVALID)(static_cast <bool> (props->direction != HB_DIRECTION_INVALID ) ? void (0) : __assert_fail ("props->direction != HB_DIRECTION_INVALID" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc" , 234, __extension__ __PRETTY_FUNCTION__)); | |||
235 | ||||
236 | hb_shape_plan_t *shape_plan; | |||
237 | ||||
238 | if (unlikely (!props)(__builtin_expect (!!(!props), 0))) | |||
239 | goto bail; | |||
240 | if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) | |||
241 | goto bail; | |||
242 | ||||
243 | if (unlikely (!face)(__builtin_expect (!!(!face), 0))) | |||
244 | face = hb_face_get_empty (); | |||
245 | hb_face_make_immutable (face); | |||
246 | shape_plan->face_unsafe = face; | |||
247 | ||||
248 | if (unlikely (!shape_plan->key.init (true,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
249 | face,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
250 | props,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
251 | user_features,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
252 | num_user_features,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
253 | coords,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
254 | num_coords,(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0)) | |||
255 | shaper_list))(__builtin_expect (!!(!shape_plan->key.init (true, face, props , user_features, num_user_features, coords, num_coords, shaper_list )), 0))) | |||
256 | goto bail2; | |||
257 | #ifndef HB_NO_OT_SHAPE | |||
258 | if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key))(__builtin_expect (!!(!shape_plan->ot.init0 (face, &shape_plan ->key)), 0))) | |||
259 | goto bail3; | |||
260 | #endif | |||
261 | ||||
262 | return shape_plan; | |||
263 | ||||
264 | #ifndef HB_NO_OT_SHAPE | |||
265 | bail3: | |||
266 | #endif | |||
267 | shape_plan->key.free (); | |||
268 | bail2: | |||
269 | free (shape_plan); | |||
270 | bail: | |||
271 | return hb_shape_plan_get_empty (); | |||
272 | } | |||
273 | ||||
274 | /** | |||
275 | * hb_shape_plan_get_empty: | |||
276 | * | |||
277 | * Fetches the singleton empty shaping plan. | |||
278 | * | |||
279 | * Return value: (transfer full): The empty shaping plan | |||
280 | * | |||
281 | * Since: 0.9.7 | |||
282 | **/ | |||
283 | hb_shape_plan_t * | |||
284 | hb_shape_plan_get_empty () | |||
285 | { | |||
286 | return const_cast<hb_shape_plan_t *> (&Null (hb_shape_plan_t)NullHelper<hb_shape_plan_t>::get_null ()); | |||
287 | } | |||
288 | ||||
289 | /** | |||
290 | * hb_shape_plan_reference: (skip) | |||
291 | * @shape_plan: A shaping plan | |||
292 | * | |||
293 | * Increases the reference count on the given shaping plan. | |||
294 | * | |||
295 | * Return value: (transfer full): @shape_plan | |||
296 | * | |||
297 | * Since: 0.9.7 | |||
298 | **/ | |||
299 | hb_shape_plan_t * | |||
300 | hb_shape_plan_reference (hb_shape_plan_t *shape_plan) | |||
301 | { | |||
302 | return hb_object_reference (shape_plan); | |||
303 | } | |||
304 | ||||
305 | /** | |||
306 | * hb_shape_plan_destroy: (skip) | |||
307 | * @shape_plan: A shaping plan | |||
308 | * | |||
309 | * Decreases the reference count on the given shaping plan. When the | |||
310 | * reference count reaches zero, the shaping plan is destroyed, | |||
311 | * freeing all memory. | |||
312 | * | |||
313 | * Since: 0.9.7 | |||
314 | **/ | |||
315 | void | |||
316 | hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) | |||
317 | { | |||
318 | if (!hb_object_destroy (shape_plan)) return; | |||
319 | ||||
320 | #ifndef HB_NO_OT_SHAPE | |||
321 | shape_plan->ot.fini (); | |||
322 | #endif | |||
323 | shape_plan->key.free (); | |||
324 | free (shape_plan); | |||
| ||||
325 | } | |||
326 | ||||
327 | /** | |||
328 | * hb_shape_plan_set_user_data: (skip) | |||
329 | * @shape_plan: A shaping plan | |||
330 | * @key: The user-data key to set | |||
331 | * @data: A pointer to the user data | |||
332 | * @destroy: (nullable): A callback to call when @data is not needed anymore | |||
333 | * @replace: Whether to replace an existing data with the same key | |||
334 | * | |||
335 | * Attaches a user-data key/data pair to the given shaping plan. | |||
336 | * | |||
337 | * Return value: %true if success, %false otherwise. | |||
338 | * | |||
339 | * Since: 0.9.7 | |||
340 | **/ | |||
341 | hb_bool_t | |||
342 | hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan, | |||
343 | hb_user_data_key_t *key, | |||
344 | void * data, | |||
345 | hb_destroy_func_t destroy, | |||
346 | hb_bool_t replace) | |||
347 | { | |||
348 | return hb_object_set_user_data (shape_plan, key, data, destroy, replace); | |||
349 | } | |||
350 | ||||
351 | /** | |||
352 | * hb_shape_plan_get_user_data: (skip) | |||
353 | * @shape_plan: A shaping plan | |||
354 | * @key: The user-data key to query | |||
355 | * | |||
356 | * Fetches the user data associated with the specified key, | |||
357 | * attached to the specified shaping plan. | |||
358 | * | |||
359 | * Return value: (transfer none): A pointer to the user data | |||
360 | * | |||
361 | * Since: 0.9.7 | |||
362 | **/ | |||
363 | void * | |||
364 | hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, | |||
365 | hb_user_data_key_t *key) | |||
366 | { | |||
367 | return hb_object_get_user_data (shape_plan, key); | |||
368 | } | |||
369 | ||||
370 | /** | |||
371 | * hb_shape_plan_get_shaper: | |||
372 | * @shape_plan: A shaping plan | |||
373 | * | |||
374 | * Fetches the shaper from a given shaping plan. | |||
375 | * | |||
376 | * Return value: (transfer none): The shaper | |||
377 | * | |||
378 | * Since: 0.9.7 | |||
379 | **/ | |||
380 | const char * | |||
381 | hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) | |||
382 | { | |||
383 | return shape_plan->key.shaper_name; | |||
384 | } | |||
385 | ||||
386 | ||||
387 | static bool | |||
388 | _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan, | |||
389 | hb_font_t *font, | |||
390 | hb_buffer_t *buffer, | |||
391 | const hb_feature_t *features, | |||
392 | unsigned int num_features) | |||
393 | { | |||
394 | DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "num_features=%d shaper_func=%p, shaper_name=%s" , num_features, shape_plan->key.shaper_func, shape_plan-> key.shaper_name) | |||
395 | "num_features=%d shaper_func=%p, shaper_name=%s",_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "num_features=%d shaper_func=%p, shaper_name=%s" , num_features, shape_plan->key.shaper_func, shape_plan-> key.shaper_name) | |||
396 | num_features,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "num_features=%d shaper_func=%p, shaper_name=%s" , num_features, shape_plan->key.shaper_func, shape_plan-> key.shaper_name) | |||
397 | shape_plan->key.shaper_func,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "num_features=%d shaper_func=%p, shaper_name=%s" , num_features, shape_plan->key.shaper_func, shape_plan-> key.shaper_name) | |||
398 | shape_plan->key.shaper_name)_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "num_features=%d shaper_func=%p, shaper_name=%s" , num_features, shape_plan->key.shaper_func, shape_plan-> key.shaper_name); | |||
399 | ||||
400 | if (unlikely (!buffer->len)(__builtin_expect (!!(!buffer->len), 0))) | |||
401 | return true; | |||
402 | ||||
403 | assert (!hb_object_is_immutable (buffer))(static_cast <bool> (!hb_object_is_immutable (buffer)) ? void (0) : __assert_fail ("!hb_object_is_immutable (buffer)" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc" , 403, __extension__ __PRETTY_FUNCTION__)); | |||
404 | ||||
405 | buffer->assert_unicode (); | |||
406 | ||||
407 | if (unlikely (hb_object_is_inert (shape_plan))(__builtin_expect (!!(hb_object_is_inert (shape_plan)), 0))) | |||
408 | return false; | |||
409 | ||||
410 | assert (shape_plan->face_unsafe == font->face)(static_cast <bool> (shape_plan->face_unsafe == font ->face) ? void (0) : __assert_fail ("shape_plan->face_unsafe == font->face" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc" , 410, __extension__ __PRETTY_FUNCTION__)); | |||
411 | assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props))(static_cast <bool> (hb_segment_properties_equal (& shape_plan->key.props, &buffer->props)) ? void (0) : __assert_fail ("hb_segment_properties_equal (&shape_plan->key.props, &buffer->props)" , "/home/daniel/Projects/java/jdk/src/java.desktop/share/native/libharfbuzz/hb-shape-plan.cc" , 411, __extension__ __PRETTY_FUNCTION__)); | |||
412 | ||||
413 | #define HB_SHAPER_EXECUTE(shaper) \ | |||
414 | HB_STMT_STARTdo { \ | |||
415 | return font->data.shaper && \ | |||
416 | _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \ | |||
417 | } HB_STMT_ENDwhile (0) | |||
418 | ||||
419 | if (false) | |||
420 | ; | |||
421 | #define HB_SHAPER_IMPLEMENT(shaper) \ | |||
422 | else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \ | |||
423 | HB_SHAPER_EXECUTE (shaper); | |||
424 | #include "hb-shaper-list.hh" | |||
425 | #undef HB_SHAPER_IMPLEMENT | |||
426 | ||||
427 | #undef HB_SHAPER_EXECUTE | |||
428 | ||||
429 | return false; | |||
430 | } | |||
431 | /** | |||
432 | * hb_shape_plan_execute: | |||
433 | * @shape_plan: A shaping plan | |||
434 | * @font: The #hb_font_t to use | |||
435 | * @buffer: The #hb_buffer_t to work upon | |||
436 | * @features: (array length=num_features): Features to enable | |||
437 | * @num_features: The number of features to enable | |||
438 | * | |||
439 | * Executes the given shaping plan on the specified buffer, using | |||
440 | * the given @font and @features. | |||
441 | * | |||
442 | * Return value: %true if success, %false otherwise. | |||
443 | * | |||
444 | * Since: 0.9.7 | |||
445 | **/ | |||
446 | hb_bool_t | |||
447 | hb_shape_plan_execute (hb_shape_plan_t *shape_plan, | |||
448 | hb_font_t *font, | |||
449 | hb_buffer_t *buffer, | |||
450 | const hb_feature_t *features, | |||
451 | unsigned int num_features) | |||
452 | { | |||
453 | bool ret = _hb_shape_plan_execute_internal (shape_plan, font, buffer, | |||
454 | features, num_features); | |||
455 | ||||
456 | if (ret && buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) | |||
457 | buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; | |||
458 | ||||
459 | return ret; | |||
460 | } | |||
461 | ||||
462 | ||||
463 | /* | |||
464 | * Caching | |||
465 | */ | |||
466 | ||||
467 | /** | |||
468 | * hb_shape_plan_create_cached: | |||
469 | * @face: #hb_face_t to use | |||
470 | * @props: The #hb_segment_properties_t of the segment | |||
471 | * @user_features: (array length=num_user_features): The list of user-selected features | |||
472 | * @num_user_features: The number of user-selected features | |||
473 | * @shaper_list: (array zero-terminated=1): List of shapers to try | |||
474 | * | |||
475 | * Creates a cached shaping plan suitable for reuse, for a combination | |||
476 | * of @face, @user_features, @props, and @shaper_list. | |||
477 | * | |||
478 | * Return value: (transfer full): The shaping plan | |||
479 | * | |||
480 | * Since: 0.9.7 | |||
481 | **/ | |||
482 | hb_shape_plan_t * | |||
483 | hb_shape_plan_create_cached (hb_face_t *face, | |||
484 | const hb_segment_properties_t *props, | |||
485 | const hb_feature_t *user_features, | |||
486 | unsigned int num_user_features, | |||
487 | const char * const *shaper_list) | |||
488 | { | |||
489 | return hb_shape_plan_create_cached2 (face, props, | |||
| ||||
490 | user_features, num_user_features, | |||
491 | nullptr, 0, | |||
492 | shaper_list); | |||
493 | } | |||
494 | ||||
495 | /** | |||
496 | * hb_shape_plan_create_cached2: | |||
497 | * @face: #hb_face_t to use | |||
498 | * @props: The #hb_segment_properties_t of the segment | |||
499 | * @user_features: (array length=num_user_features): The list of user-selected features | |||
500 | * @num_user_features: The number of user-selected features | |||
501 | * @coords: (array length=num_coords): The list of variation-space coordinates | |||
502 | * @num_coords: The number of variation-space coordinates | |||
503 | * @shaper_list: (array zero-terminated=1): List of shapers to try | |||
504 | * | |||
505 | * The variable-font version of #hb_shape_plan_create_cached. | |||
506 | * Creates a cached shaping plan suitable for reuse, for a combination | |||
507 | * of @face, @user_features, @props, and @shaper_list, plus the | |||
508 | * variation-space coordinates @coords. | |||
509 | * | |||
510 | * Return value: (transfer full): The shaping plan | |||
511 | * | |||
512 | * Since: 1.4.0 | |||
513 | **/ | |||
514 | hb_shape_plan_t * | |||
515 | hb_shape_plan_create_cached2 (hb_face_t *face, | |||
516 | const hb_segment_properties_t *props, | |||
517 | const hb_feature_t *user_features, | |||
518 | unsigned int num_user_features, | |||
519 | const int *coords, | |||
520 | unsigned int num_coords, | |||
521 | const char * const *shaper_list) | |||
522 | { | |||
523 | DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d shaper_list=%p", face , num_user_features, shaper_list) | |||
524 | "face=%p num_features=%d shaper_list=%p",_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d shaper_list=%p", face , num_user_features, shaper_list) | |||
525 | face,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d shaper_list=%p", face , num_user_features, shaper_list) | |||
526 | num_user_features,_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d shaper_list=%p", face , num_user_features, shaper_list) | |||
527 | shaper_list)_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (nullptr), __PRETTY_FUNCTION__ , false, 0, 0, "face=%p num_features=%d shaper_list=%p", face , num_user_features, shaper_list); | |||
528 | ||||
529 | retry: | |||
530 | hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans; | |||
531 | ||||
532 | bool dont_cache = hb_object_is_inert (face); | |||
533 | ||||
534 | if (likely (!dont_cache)(__builtin_expect (!!(!dont_cache), 1))) | |||
535 | { | |||
536 | hb_shape_plan_key_t key; | |||
537 | if (!key.init (false, | |||
538 | face, | |||
539 | props, | |||
540 | user_features, | |||
541 | num_user_features, | |||
542 | coords, | |||
543 | num_coords, | |||
544 | shaper_list)) | |||
545 | return hb_shape_plan_get_empty (); | |||
546 | ||||
547 | for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) | |||
548 | if (node->shape_plan->key.equal (&key)) | |||
549 | { | |||
550 | DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache")_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (node->shape_plan ), __PRETTY_FUNCTION__, false, 0, 0, "fulfilled from cache"); | |||
551 | return hb_shape_plan_reference (node->shape_plan); | |||
552 | } | |||
553 | } | |||
554 | ||||
555 | hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, | |||
556 | user_features, num_user_features, | |||
557 | coords, num_coords, | |||
558 | shaper_list); | |||
559 | ||||
560 | if (unlikely (dont_cache)(__builtin_expect (!!(dont_cache), 0))) | |||
561 | return shape_plan; | |||
562 | ||||
563 | hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); | |||
564 | if (unlikely (!node)(__builtin_expect (!!(!node), 0))) | |||
565 | return shape_plan; | |||
566 | ||||
567 | node->shape_plan = shape_plan; | |||
568 | node->next = cached_plan_nodes; | |||
569 | ||||
570 | if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node))(__builtin_expect (!!(!face->shape_plans.cmpexch (cached_plan_nodes , node)), 0))) | |||
571 | { | |||
572 | hb_shape_plan_destroy (shape_plan); | |||
573 | free (node); | |||
574 | goto retry; | |||
575 | } | |||
576 | DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache")_hb_debug_msg<(0 +0)> ("SHAPE_PLAN", (shape_plan), __PRETTY_FUNCTION__ , false, 0, 0, "inserted into cache"); | |||
577 | ||||
578 | return hb_shape_plan_reference (shape_plan); | |||
579 | } |