| 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 |