OLD | NEW |
1 /* | 1 /* |
2 * Copyright © 2012 Google, Inc. | 2 * Copyright © 2012 Google, Inc. |
3 * | 3 * |
4 * This is part of HarfBuzz, a text shaping library. | 4 * This is part of HarfBuzz, a text shaping library. |
5 * | 5 * |
6 * Permission is hereby granted, without written agreement and without | 6 * Permission is hereby granted, without written agreement and without |
7 * license or royalty fees, to use, copy, modify, and distribute this | 7 * license or royalty fees, to use, copy, modify, and distribute this |
8 * software and its documentation for any purpose, provided that the | 8 * software and its documentation for any purpose, provided that the |
9 * above copyright notice and the following two paragraphs appear in | 9 * above copyright notice and the following two paragraphs appear in |
10 * all copies of this software. | 10 * all copies of this software. |
(...skipping 11 matching lines...) Expand all Loading... |
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 * | 23 * |
24 * Google Author(s): Behdad Esfahbod | 24 * Google Author(s): Behdad Esfahbod |
25 */ | 25 */ |
26 | 26 |
27 #include "hb-shape-plan-private.hh" | 27 #include "hb-shape-plan-private.hh" |
28 #include "hb-shaper-private.hh" | 28 #include "hb-shaper-private.hh" |
29 #include "hb-font-private.hh" | 29 #include "hb-font-private.hh" |
30 #include "hb-buffer-private.hh" | 30 #include "hb-buffer-private.hh" |
31 | 31 |
| 32 |
| 33 #ifndef HB_DEBUG_SHAPE_PLAN |
| 34 #define HB_DEBUG_SHAPE_PLAN (HB_DEBUG+0) |
| 35 #endif |
| 36 |
| 37 |
32 #define HB_SHAPER_IMPLEMENT(shaper) \ | 38 #define HB_SHAPER_IMPLEMENT(shaper) \ |
33 HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ | 39 HB_SHAPER_DATA_ENSURE_DECLARE(shaper, face) \ |
34 HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) | 40 HB_SHAPER_DATA_ENSURE_DECLARE(shaper, font) |
35 #include "hb-shaper-list.hh" | 41 #include "hb-shaper-list.hh" |
36 #undef HB_SHAPER_IMPLEMENT | 42 #undef HB_SHAPER_IMPLEMENT |
37 | 43 |
38 | 44 |
39 static void | 45 static void |
40 hb_shape_plan_plan (hb_shape_plan_t *shape_plan, | 46 hb_shape_plan_plan (hb_shape_plan_t *shape_plan, |
41 const hb_feature_t *user_features, | 47 const hb_feature_t *user_features, |
42 unsigned int num_user_features, | 48 unsigned int num_user_features, |
43 const char * const *shaper_list) | 49 const char * const *shaper_list) |
44 { | 50 { |
| 51 DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, |
| 52 "num_features=%d shaper_list=%p", |
| 53 num_user_features, |
| 54 shaper_list); |
| 55 |
45 const hb_shaper_pair_t *shapers = _hb_shapers_get (); | 56 const hb_shaper_pair_t *shapers = _hb_shapers_get (); |
46 | 57 |
47 #define HB_SHAPER_PLAN(shaper) \ | 58 #define HB_SHAPER_PLAN(shaper) \ |
48 HB_STMT_START { \ | 59 HB_STMT_START { \ |
49 if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) {
\ | 60 if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) {
\ |
50 HB_SHAPER_DATA (shaper, shape_plan) = \ | 61 HB_SHAPER_DATA (shaper, shape_plan) = \ |
51 HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_
features, num_user_features); \ | 62 HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_
features, num_user_features); \ |
52 shape_plan->shaper_func = _hb_##shaper##_shape; \ | 63 shape_plan->shaper_func = _hb_##shaper##_shape; \ |
53 shape_plan->shaper_name = #shaper; \ | 64 shape_plan->shaper_name = #shaper; \ |
54 return; \ | 65 return; \ |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 * | 108 * |
98 * Since: 1.0 | 109 * Since: 1.0 |
99 **/ | 110 **/ |
100 hb_shape_plan_t * | 111 hb_shape_plan_t * |
101 hb_shape_plan_create (hb_face_t *face, | 112 hb_shape_plan_create (hb_face_t *face, |
102 const hb_segment_properties_t *props, | 113 const hb_segment_properties_t *props, |
103 const hb_feature_t *user_features, | 114 const hb_feature_t *user_features, |
104 unsigned int num_user_features, | 115 unsigned int num_user_features, |
105 const char * const *shaper_list) | 116 const char * const *shaper_list) |
106 { | 117 { |
| 118 DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, |
| 119 "face=%p num_features=%d shaper_list=%p", |
| 120 face, |
| 121 num_user_features, |
| 122 shaper_list); |
| 123 |
107 hb_shape_plan_t *shape_plan; | 124 hb_shape_plan_t *shape_plan; |
108 hb_feature_t *features = NULL; | 125 hb_feature_t *features = NULL; |
109 | 126 |
110 if (unlikely (!face)) | 127 if (unlikely (!face)) |
111 face = hb_face_get_empty (); | 128 face = hb_face_get_empty (); |
112 if (unlikely (!props || hb_object_is_inert (face))) | 129 if (unlikely (!props || hb_object_is_inert (face))) |
113 return hb_shape_plan_get_empty (); | 130 return hb_shape_plan_get_empty (); |
114 if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_featur
es * sizeof (hb_feature_t)))) | 131 if (num_user_features && !(features = (hb_feature_t *) malloc (num_user_featur
es * sizeof (hb_feature_t)))) |
115 return hb_shape_plan_get_empty (); | 132 return hb_shape_plan_get_empty (); |
116 if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) { | 133 if (!(shape_plan = hb_object_create<hb_shape_plan_t> ())) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 * | 281 * |
265 * Since: 1.0 | 282 * Since: 1.0 |
266 **/ | 283 **/ |
267 hb_bool_t | 284 hb_bool_t |
268 hb_shape_plan_execute (hb_shape_plan_t *shape_plan, | 285 hb_shape_plan_execute (hb_shape_plan_t *shape_plan, |
269 hb_font_t *font, | 286 hb_font_t *font, |
270 hb_buffer_t *buffer, | 287 hb_buffer_t *buffer, |
271 const hb_feature_t *features, | 288 const hb_feature_t *features, |
272 unsigned int num_features) | 289 unsigned int num_features) |
273 { | 290 { |
| 291 DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, |
| 292 "num_features=%d shaper_func=%p", |
| 293 num_features, |
| 294 shape_plan->shaper_func); |
| 295 |
274 if (unlikely (hb_object_is_inert (shape_plan) || | 296 if (unlikely (hb_object_is_inert (shape_plan) || |
275 hb_object_is_inert (font) || | 297 hb_object_is_inert (font) || |
276 hb_object_is_inert (buffer))) | 298 hb_object_is_inert (buffer))) |
277 return false; | 299 return false; |
278 | 300 |
279 assert (shape_plan->face_unsafe == font->face); | 301 assert (shape_plan->face_unsafe == font->face); |
280 assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); | 302 assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); |
281 | 303 |
282 #define HB_SHAPER_EXECUTE(shaper) \ | 304 #define HB_SHAPER_EXECUTE(shaper) \ |
283 HB_STMT_START { \ | 305 HB_STMT_START { \ |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 * | 398 * |
377 * Since: 1.0 | 399 * Since: 1.0 |
378 **/ | 400 **/ |
379 hb_shape_plan_t * | 401 hb_shape_plan_t * |
380 hb_shape_plan_create_cached (hb_face_t *face, | 402 hb_shape_plan_create_cached (hb_face_t *face, |
381 const hb_segment_properties_t *props, | 403 const hb_segment_properties_t *props, |
382 const hb_feature_t *user_features, | 404 const hb_feature_t *user_features, |
383 unsigned int num_user_features, | 405 unsigned int num_user_features, |
384 const char * const *shaper_list) | 406 const char * const *shaper_list) |
385 { | 407 { |
| 408 DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, |
| 409 "face=%p num_features=%d shaper_list=%p", |
| 410 face, |
| 411 num_user_features, |
| 412 shaper_list); |
| 413 |
386 hb_shape_plan_proposal_t proposal = { | 414 hb_shape_plan_proposal_t proposal = { |
387 *props, | 415 *props, |
388 shaper_list, | 416 shaper_list, |
389 user_features, | 417 user_features, |
390 num_user_features, | 418 num_user_features, |
391 NULL | 419 NULL |
392 }; | 420 }; |
393 | 421 |
394 if (shaper_list) { | 422 if (shaper_list) { |
395 /* Choose shaper. Adapted from hb_shape_plan_plan(). */ | 423 /* Choose shaper. Adapted from hb_shape_plan_plan(). |
396 #define HB_SHAPER_PLAN(shaper) \ | 424 * Must choose shaper exactly the same way as that function. */ |
397 » HB_STMT_START { \ | |
398 » if (hb_##shaper##_shaper_face_data_ensure (face)) \ | |
399 » proposal.shaper_func = _hb_##shaper##_shape; \ | |
400 » } HB_STMT_END | |
401 | |
402 for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_ite
m++) | 425 for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_ite
m++) |
403 if (0) | 426 if (0) |
404 ; | 427 ; |
405 #define HB_SHAPER_IMPLEMENT(shaper) \ | 428 #define HB_SHAPER_IMPLEMENT(shaper) \ |
406 else if (0 == strcmp (*shaper_item, #shaper)) \ | 429 else if (0 == strcmp (*shaper_item, #shaper) && \ |
407 » HB_SHAPER_PLAN (shaper); | 430 » hb_##shaper##_shaper_face_data_ensure (face)) \ |
| 431 { \ |
| 432 » proposal.shaper_func = _hb_##shaper##_shape; \ |
| 433 » break; \ |
| 434 } |
408 #include "hb-shaper-list.hh" | 435 #include "hb-shaper-list.hh" |
409 #undef HB_SHAPER_IMPLEMENT | 436 #undef HB_SHAPER_IMPLEMENT |
410 | 437 |
411 #undef HB_SHAPER_PLAN | 438 if (unlikely (!proposal.shaper_func)) |
412 | |
413 if (unlikely (!proposal.shaper_list)) | |
414 return hb_shape_plan_get_empty (); | 439 return hb_shape_plan_get_empty (); |
415 } | 440 } |
416 | 441 |
417 | 442 |
418 retry: | 443 retry: |
419 hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atom
ic_ptr_get (&face->shape_plans); | 444 hb_face_t::plan_node_t *cached_plan_nodes = (hb_face_t::plan_node_t *) hb_atom
ic_ptr_get (&face->shape_plans); |
420 for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next
) | 445 for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next
) |
421 if (hb_shape_plan_matches (node->shape_plan, &proposal)) | 446 if (hb_shape_plan_matches (node->shape_plan, &proposal)) |
| 447 { |
| 448 DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); |
422 return hb_shape_plan_reference (node->shape_plan); | 449 return hb_shape_plan_reference (node->shape_plan); |
| 450 } |
423 | 451 |
424 /* Not found. */ | 452 /* Not found. */ |
425 | 453 |
426 hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features
, num_user_features, shaper_list); | 454 hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features
, num_user_features, shaper_list); |
427 | 455 |
428 /* Don't add the plan to the cache if there were user features with non-global
ranges */ | 456 /* Don't add the plan to the cache if there were user features with non-global
ranges */ |
429 | 457 |
430 if (hb_non_global_user_features_present (user_features, num_user_features)) | 458 if (hb_non_global_user_features_present (user_features, num_user_features)) |
431 return shape_plan; | 459 return shape_plan; |
432 | 460 |
433 hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (h
b_face_t::plan_node_t)); | 461 hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (h
b_face_t::plan_node_t)); |
434 if (unlikely (!node)) | 462 if (unlikely (!node)) |
435 return shape_plan; | 463 return shape_plan; |
436 | 464 |
437 node->shape_plan = shape_plan; | 465 node->shape_plan = shape_plan; |
438 node->next = cached_plan_nodes; | 466 node->next = cached_plan_nodes; |
439 | 467 |
440 if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) { | 468 if (!hb_atomic_ptr_cmpexch (&face->shape_plans, cached_plan_nodes, node)) { |
441 hb_shape_plan_destroy (shape_plan); | 469 hb_shape_plan_destroy (shape_plan); |
442 free (node); | 470 free (node); |
443 goto retry; | 471 goto retry; |
444 } | 472 } |
| 473 DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache"); |
445 | 474 |
446 return hb_shape_plan_reference (shape_plan); | 475 return hb_shape_plan_reference (shape_plan); |
447 } | 476 } |
448 | 477 |
449 /** | 478 /** |
450 * hb_shape_plan_get_shaper: | 479 * hb_shape_plan_get_shaper: |
451 * @shape_plan: a shape plan. | 480 * @shape_plan: a shape plan. |
452 * | 481 * |
453 * | 482 * |
454 * | 483 * |
455 * Return value: (transfer none): | 484 * Return value: (transfer none): |
456 * | 485 * |
457 * Since: 1.0 | 486 * Since: 1.0 |
458 **/ | 487 **/ |
459 const char * | 488 const char * |
460 hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) | 489 hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) |
461 { | 490 { |
462 return shape_plan->shaper_name; | 491 return shape_plan->shaper_name; |
463 } | 492 } |
OLD | NEW |