| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright © 2009,2010 Red Hat, Inc. | 2 * Copyright © 2009,2010 Red Hat, Inc. |
| 3 * Copyright © 2010,2011,2012 Google, Inc. | 3 * Copyright © 2010,2011,2012 Google, Inc. |
| 4 * | 4 * |
| 5 * This is part of HarfBuzz, a text shaping library. | 5 * This is part of HarfBuzz, a text shaping library. |
| 6 * | 6 * |
| 7 * Permission is hereby granted, without written agreement and without | 7 * Permission is hereby granted, without written agreement and without |
| 8 * license or royalty fees, to use, copy, modify, and distribute this | 8 * license or royalty fees, to use, copy, modify, and distribute this |
| 9 * software and its documentation for any purpose, provided that the | 9 * software and its documentation for any purpose, provided that the |
| 10 * above copyright notice and the following two paragraphs appear in | 10 * above copyright notice and the following two paragraphs appear in |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 | 51 |
| 52 | 52 |
| 53 static hb_tag_t horizontal_features[] = { | 53 static hb_tag_t horizontal_features[] = { |
| 54 HB_TAG('c','a','l','t'), | 54 HB_TAG('c','a','l','t'), |
| 55 HB_TAG('c','l','i','g'), | 55 HB_TAG('c','l','i','g'), |
| 56 HB_TAG('c','u','r','s'), | 56 HB_TAG('c','u','r','s'), |
| 57 HB_TAG('k','e','r','n'), | 57 HB_TAG('k','e','r','n'), |
| 58 HB_TAG('r','c','l','t'), | 58 HB_TAG('r','c','l','t'), |
| 59 }; | 59 }; |
| 60 | 60 |
| 61 /* Note: | |
| 62 * Technically speaking, vrt2 and vert are mutually exclusive. | |
| 63 * According to the spec, valt and vpal are also mutually exclusive. | |
| 64 * But we apply them all for now. | |
| 65 */ | |
| 66 static hb_tag_t vertical_features[] = { | 61 static hb_tag_t vertical_features[] = { |
| 67 HB_TAG('v','a','l','t'), | |
| 68 HB_TAG('v','e','r','t'), | 62 HB_TAG('v','e','r','t'), |
| 69 HB_TAG('v','k','r','n'), | |
| 70 HB_TAG('v','p','a','l'), | |
| 71 HB_TAG('v','r','t','2'), | |
| 72 }; | 63 }; |
| 73 | 64 |
| 74 | 65 |
| 75 | 66 |
| 76 static void | 67 static void |
| 77 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, | 68 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, |
| 78 const hb_segment_properties_t *props, | 69 const hb_segment_properties_t *props, |
| 79 const hb_feature_t *user_features, | 70 const hb_feature_t *user_features, |
| 80 unsigned int num_user_features) | 71 unsigned int num_user_features) |
| 81 { | 72 { |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 | 283 |
| 293 | 284 |
| 294 /* Substitute */ | 285 /* Substitute */ |
| 295 | 286 |
| 296 static inline void | 287 static inline void |
| 297 hb_ot_mirror_chars (hb_ot_shape_context_t *c) | 288 hb_ot_mirror_chars (hb_ot_shape_context_t *c) |
| 298 { | 289 { |
| 299 if (HB_DIRECTION_IS_FORWARD (c->target_direction)) | 290 if (HB_DIRECTION_IS_FORWARD (c->target_direction)) |
| 300 return; | 291 return; |
| 301 | 292 |
| 302 hb_unicode_funcs_t *unicode = c->buffer->unicode; | 293 hb_buffer_t *buffer = c->buffer; |
| 294 hb_unicode_funcs_t *unicode = buffer->unicode; |
| 303 hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); | 295 hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); |
| 304 | 296 |
| 305 unsigned int count = c->buffer->len; | 297 unsigned int count = buffer->len; |
| 298 hb_glyph_info_t *info = buffer->info; |
| 306 for (unsigned int i = 0; i < count; i++) { | 299 for (unsigned int i = 0; i < count; i++) { |
| 307 hb_codepoint_t codepoint = unicode->mirroring (c->buffer->info[i].codepoint)
; | 300 hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint); |
| 308 if (likely (codepoint == c->buffer->info[i].codepoint)) | 301 if (likely (codepoint == info[i].codepoint)) |
| 309 c->buffer->info[i].mask |= rtlm_mask; | 302 info[i].mask |= rtlm_mask; |
| 310 else | 303 else |
| 311 c->buffer->info[i].codepoint = codepoint; | 304 info[i].codepoint = codepoint; |
| 312 } | 305 } |
| 313 } | 306 } |
| 314 | 307 |
| 315 static inline void | 308 static inline void |
| 316 hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) | 309 hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) |
| 317 { | 310 { |
| 318 hb_ot_map_t *map = &c->plan->map; | 311 hb_ot_map_t *map = &c->plan->map; |
| 312 hb_buffer_t *buffer = c->buffer; |
| 319 | 313 |
| 320 hb_mask_t global_mask = map->get_global_mask (); | 314 hb_mask_t global_mask = map->get_global_mask (); |
| 321 c->buffer->reset_masks (global_mask); | 315 buffer->reset_masks (global_mask); |
| 322 | 316 |
| 323 if (c->plan->shaper->setup_masks) | 317 if (c->plan->shaper->setup_masks) |
| 324 c->plan->shaper->setup_masks (c->plan, c->buffer, c->font); | 318 c->plan->shaper->setup_masks (c->plan, buffer, c->font); |
| 325 | 319 |
| 326 for (unsigned int i = 0; i < c->num_user_features; i++) | 320 for (unsigned int i = 0; i < c->num_user_features; i++) |
| 327 { | 321 { |
| 328 const hb_feature_t *feature = &c->user_features[i]; | 322 const hb_feature_t *feature = &c->user_features[i]; |
| 329 if (!(feature->start == 0 && feature->end == (unsigned int)-1)) { | 323 if (!(feature->start == 0 && feature->end == (unsigned int)-1)) { |
| 330 unsigned int shift; | 324 unsigned int shift; |
| 331 hb_mask_t mask = map->get_mask (feature->tag, &shift); | 325 hb_mask_t mask = map->get_mask (feature->tag, &shift); |
| 332 c->buffer->set_masks (feature->value << shift, mask, feature->start, featu
re->end); | 326 buffer->set_masks (feature->value << shift, mask, feature->start, feature-
>end); |
| 333 } | 327 } |
| 334 } | 328 } |
| 335 } | 329 } |
| 336 | 330 |
| 337 static inline void | 331 static inline void |
| 338 hb_ot_map_glyphs_fast (hb_buffer_t *buffer) | 332 hb_ot_map_glyphs_fast (hb_buffer_t *buffer) |
| 339 { | 333 { |
| 340 /* Normalization process sets up glyph_index(), we just copy it. */ | 334 /* Normalization process sets up glyph_index(), we just copy it. */ |
| 341 unsigned int count = buffer->len; | 335 unsigned int count = buffer->len; |
| 342 for (unsigned int i = 0; i < count; i++) | 336 for (unsigned int i = 0; i < count; i++) |
| 343 buffer->info[i].codepoint = buffer->info[i].glyph_index(); | 337 buffer->info[i].codepoint = buffer->info[i].glyph_index(); |
| 344 } | 338 } |
| 345 | 339 |
| 346 static inline void | 340 static inline void |
| 347 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) | 341 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) |
| 348 { | 342 { |
| 349 unsigned int count = c->buffer->len; | 343 unsigned int count = c->buffer->len; |
| 344 hb_glyph_info_t *info = c->buffer->info; |
| 350 for (unsigned int i = 0; i < count; i++) | 345 for (unsigned int i = 0; i < count; i++) |
| 351 c->buffer->info[i].glyph_props() = _hb_glyph_info_get_general_category (&c->
buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ? | 346 _hb_glyph_info_set_glyph_props (&info[i], |
| 352 » » » » HB_OT_LAYOUT_GLYPH_PROPS_MARK : | 347 » » » » _hb_glyph_info_get_general_category (&info[i
]) |
| 353 » » » » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH; | 348 » » » » == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_M
ARK ? |
| 349 » » » » HB_OT_LAYOUT_GLYPH_PROPS_MARK : |
| 350 » » » » HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH); |
| 354 } | 351 } |
| 355 | 352 |
| 356 static inline void | 353 static inline void |
| 357 hb_ot_substitute_default (hb_ot_shape_context_t *c) | 354 hb_ot_substitute_default (hb_ot_shape_context_t *c) |
| 358 { | 355 { |
| 356 hb_buffer_t *buffer = c->buffer; |
| 357 |
| 359 if (c->plan->shaper->preprocess_text) | 358 if (c->plan->shaper->preprocess_text) |
| 360 c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font); | 359 c->plan->shaper->preprocess_text (c->plan, buffer, c->font); |
| 361 | 360 |
| 362 hb_ot_mirror_chars (c); | 361 hb_ot_mirror_chars (c); |
| 363 | 362 |
| 364 HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index); | 363 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); |
| 365 | 364 |
| 366 _hb_ot_shape_normalize (c->plan, c->buffer, c->font); | 365 _hb_ot_shape_normalize (c->plan, buffer, c->font); |
| 367 | 366 |
| 368 hb_ot_shape_setup_masks (c); | 367 hb_ot_shape_setup_masks (c); |
| 369 | 368 |
| 370 /* This is unfortunate to go here, but necessary... */ | 369 /* This is unfortunate to go here, but necessary... */ |
| 371 if (!hb_ot_layout_has_positioning (c->face)) | 370 if (!hb_ot_layout_has_positioning (c->face)) |
| 372 _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, c->buff
er); | 371 _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer)
; |
| 373 | 372 |
| 374 hb_ot_map_glyphs_fast (c->buffer); | 373 hb_ot_map_glyphs_fast (buffer); |
| 375 | 374 |
| 376 HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index); | 375 HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index); |
| 377 } | 376 } |
| 378 | 377 |
| 379 static inline void | 378 static inline void |
| 380 hb_ot_substitute_complex (hb_ot_shape_context_t *c) | 379 hb_ot_substitute_complex (hb_ot_shape_context_t *c) |
| 381 { | 380 { |
| 382 hb_ot_layout_substitute_start (c->font, c->buffer); | 381 hb_buffer_t *buffer = c->buffer; |
| 382 |
| 383 hb_ot_layout_substitute_start (c->font, buffer); |
| 383 | 384 |
| 384 if (!hb_ot_layout_has_glyph_classes (c->face)) | 385 if (!hb_ot_layout_has_glyph_classes (c->face)) |
| 385 hb_synthesize_glyph_classes (c); | 386 hb_synthesize_glyph_classes (c); |
| 386 | 387 |
| 387 c->plan->substitute (c->font, c->buffer); | 388 c->plan->substitute (c->font, buffer); |
| 388 | 389 |
| 389 hb_ot_layout_substitute_finish (c->font, c->buffer); | 390 hb_ot_layout_substitute_finish (c->font, buffer); |
| 390 | 391 |
| 391 return; | 392 return; |
| 392 } | 393 } |
| 393 | 394 |
| 394 static inline void | 395 static inline void |
| 395 hb_ot_substitute (hb_ot_shape_context_t *c) | 396 hb_ot_substitute (hb_ot_shape_context_t *c) |
| 396 { | 397 { |
| 397 hb_ot_substitute_default (c); | 398 hb_ot_substitute_default (c); |
| 398 hb_ot_substitute_complex (c); | 399 hb_ot_substitute_complex (c); |
| 399 } | 400 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 410 buffer->pos[i].x_advance = 0; | 411 buffer->pos[i].x_advance = 0; |
| 411 buffer->pos[i].y_advance = 0; | 412 buffer->pos[i].y_advance = 0; |
| 412 } | 413 } |
| 413 } | 414 } |
| 414 | 415 |
| 415 static inline void | 416 static inline void |
| 416 zero_mark_widths_by_gdef (hb_buffer_t *buffer) | 417 zero_mark_widths_by_gdef (hb_buffer_t *buffer) |
| 417 { | 418 { |
| 418 unsigned int count = buffer->len; | 419 unsigned int count = buffer->len; |
| 419 for (unsigned int i = 0; i < count; i++) | 420 for (unsigned int i = 0; i < count; i++) |
| 420 if ((buffer->info[i].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK)) | 421 if (_hb_glyph_info_is_mark (&buffer->info[i])) |
| 421 { | 422 { |
| 422 buffer->pos[i].x_advance = 0; | 423 buffer->pos[i].x_advance = 0; |
| 423 buffer->pos[i].y_advance = 0; | 424 buffer->pos[i].y_advance = 0; |
| 424 } | 425 } |
| 425 } | 426 } |
| 426 | 427 |
| 427 static inline void | 428 static inline void |
| 428 hb_ot_position_default (hb_ot_shape_context_t *c) | 429 hb_ot_position_default (hb_ot_shape_context_t *c) |
| 429 { | 430 { |
| 430 hb_ot_layout_position_start (c->font, c->buffer); | 431 hb_direction_t direction = c->buffer->props.direction; |
| 431 | |
| 432 unsigned int count = c->buffer->len; | 432 unsigned int count = c->buffer->len; |
| 433 hb_glyph_info_t *info = c->buffer->info; |
| 434 hb_glyph_position_t *pos = c->buffer->pos; |
| 433 for (unsigned int i = 0; i < count; i++) | 435 for (unsigned int i = 0; i < count; i++) |
| 434 { | 436 { |
| 435 c->font->get_glyph_advance_for_direction (c->buffer->info[i].codepoint, | 437 c->font->get_glyph_advance_for_direction (info[i].codepoint, |
| 436 » » » » » c->buffer->props.direction, | 438 » » » » » direction, |
| 437 » » » » » &c->buffer->pos[i].x_advance, | 439 » » » » » &pos[i].x_advance, |
| 438 » » » » » &c->buffer->pos[i].y_advance); | 440 » » » » » &pos[i].y_advance); |
| 439 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint, | 441 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
| 440 » » » » » » c->buffer->props.direction, | 442 » » » » » » direction, |
| 441 » » » » » » &c->buffer->pos[i].x_offset, | 443 » » » » » » &pos[i].x_offset, |
| 442 » » » » » » &c->buffer->pos[i].y_offset); | 444 » » » » » » &pos[i].y_offset); |
| 443 | 445 |
| 444 } | 446 } |
| 447 } |
| 448 |
| 449 static inline bool |
| 450 hb_ot_position_complex (hb_ot_shape_context_t *c) |
| 451 { |
| 452 bool ret = false; |
| 453 unsigned int count = c->buffer->len; |
| 445 | 454 |
| 446 switch (c->plan->shaper->zero_width_marks) | 455 switch (c->plan->shaper->zero_width_marks) |
| 447 { | 456 { |
| 448 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 457 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
| 449 zero_mark_widths_by_gdef (c->buffer); | 458 zero_mark_widths_by_gdef (c->buffer); |
| 450 break; | 459 break; |
| 451 | 460 |
| 452 /* Not currently used for any shaper: | 461 /* Not currently used for any shaper: |
| 453 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 462 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
| 454 zero_mark_widths_by_unicode (c->buffer); | 463 zero_mark_widths_by_unicode (c->buffer); |
| 455 break; | 464 break; |
| 456 */ | 465 */ |
| 457 | 466 |
| 458 default: | 467 default: |
| 459 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 468 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 460 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 469 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
| 461 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 470 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
| 462 break; | 471 break; |
| 463 } | 472 } |
| 464 } | |
| 465 | |
| 466 static inline bool | |
| 467 hb_ot_position_complex (hb_ot_shape_context_t *c) | |
| 468 { | |
| 469 bool ret = false; | |
| 470 unsigned int count = c->buffer->len; | |
| 471 | 473 |
| 472 if (hb_ot_layout_has_positioning (c->face)) | 474 if (hb_ot_layout_has_positioning (c->face)) |
| 473 { | 475 { |
| 476 hb_glyph_info_t *info = c->buffer->info; |
| 477 hb_glyph_position_t *pos = c->buffer->pos; |
| 478 |
| 474 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ | 479 /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */ |
| 475 | 480 |
| 476 for (unsigned int i = 0; i < count; i++) { | 481 for (unsigned int i = 0; i < count; i++) { |
| 477 c->font->add_glyph_origin_for_direction (c->buffer->info[i].codepoint, | 482 c->font->add_glyph_origin_for_direction (info[i].codepoint, |
| 478 HB_DIRECTION_LTR, | 483 HB_DIRECTION_LTR, |
| 479 » » » » » &c->buffer->pos[i].x_offset, | 484 » » » » » &pos[i].x_offset, |
| 480 » » » » » &c->buffer->pos[i].y_offset); | 485 » » » » » &pos[i].y_offset); |
| 481 } | 486 } |
| 482 | 487 |
| 483 c->plan->position (c->font, c->buffer); | 488 c->plan->position (c->font, c->buffer); |
| 484 | 489 |
| 485 for (unsigned int i = 0; i < count; i++) { | 490 for (unsigned int i = 0; i < count; i++) { |
| 486 c->font->subtract_glyph_origin_for_direction (c->buffer->info[i].codepoint
, | 491 c->font->subtract_glyph_origin_for_direction (info[i].codepoint, |
| 487 HB_DIRECTION_LTR, | 492 HB_DIRECTION_LTR, |
| 488 » » » » » » &c->buffer->pos[i].x_offset, | 493 » » » » » » &pos[i].x_offset, |
| 489 » » » » » » &c->buffer->pos[i].y_offset)
; | 494 » » » » » » &pos[i].y_offset); |
| 490 } | 495 } |
| 491 | 496 |
| 492 ret = true; | 497 ret = true; |
| 493 } | 498 } |
| 494 | 499 |
| 495 switch (c->plan->shaper->zero_width_marks) | 500 switch (c->plan->shaper->zero_width_marks) |
| 496 { | 501 { |
| 497 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: | 502 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE: |
| 498 zero_mark_widths_by_unicode (c->buffer); | 503 zero_mark_widths_by_unicode (c->buffer); |
| 499 break; | 504 break; |
| 500 | 505 |
| 501 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: | 506 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
| 502 zero_mark_widths_by_gdef (c->buffer); | 507 zero_mark_widths_by_gdef (c->buffer); |
| 503 break; | 508 break; |
| 504 | 509 |
| 505 default: | 510 default: |
| 506 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: | 511 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: |
| 507 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: | 512 //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY: |
| 508 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: | 513 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
| 509 break; | 514 break; |
| 510 } | 515 } |
| 511 | 516 |
| 512 hb_ot_layout_position_finish (c->font, c->buffer); | |
| 513 | |
| 514 return ret; | 517 return ret; |
| 515 } | 518 } |
| 516 | 519 |
| 517 static inline void | 520 static inline void |
| 518 hb_ot_position (hb_ot_shape_context_t *c) | 521 hb_ot_position (hb_ot_shape_context_t *c) |
| 519 { | 522 { |
| 523 hb_ot_layout_position_start (c->font, c->buffer); |
| 524 |
| 520 hb_ot_position_default (c); | 525 hb_ot_position_default (c); |
| 521 | 526 |
| 522 hb_bool_t fallback = !hb_ot_position_complex (c); | 527 hb_bool_t fallback = !hb_ot_position_complex (c); |
| 523 | 528 |
| 529 hb_ot_layout_position_finish (c->font, c->buffer); |
| 530 |
| 524 if (fallback && c->plan->shaper->fallback_position) | 531 if (fallback && c->plan->shaper->fallback_position) |
| 525 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); | 532 _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); |
| 526 | 533 |
| 527 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) | 534 if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) |
| 528 hb_buffer_reverse (c->buffer); | 535 hb_buffer_reverse (c->buffer); |
| 529 | 536 |
| 530 /* Visual fallback goes here. */ | 537 /* Visual fallback goes here. */ |
| 531 | 538 |
| 532 if (fallback) | 539 if (fallback) |
| 533 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); | 540 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); |
| 534 } | 541 } |
| 535 | 542 |
| 536 | 543 |
| 537 /* Post-process */ | 544 /* Post-process */ |
| 538 | 545 |
| 539 static void | 546 static void |
| 540 hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) | 547 hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c) |
| 541 { | 548 { |
| 542 if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) | 549 if (c->buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES) |
| 543 return; | 550 return; |
| 544 | 551 |
| 545 hb_codepoint_t space = 0; | 552 hb_codepoint_t space; |
| 553 enum { |
| 554 SPACE_DONT_KNOW, |
| 555 SPACE_AVAILABLE, |
| 556 SPACE_UNAVAILABLE |
| 557 } space_status = SPACE_DONT_KNOW; |
| 546 | 558 |
| 547 unsigned int count = c->buffer->len; | 559 unsigned int count = c->buffer->len; |
| 560 hb_glyph_info_t *info = c->buffer->info; |
| 561 hb_glyph_position_t *pos = c->buffer->pos; |
| 562 unsigned int j = 0; |
| 548 for (unsigned int i = 0; i < count; i++) | 563 for (unsigned int i = 0; i < count; i++) |
| 549 if (unlikely (!is_a_ligature (c->buffer->info[i]) && | 564 { |
| 550 » » _hb_glyph_info_is_default_ignorable (&c->buffer->info[i]))) | 565 if (unlikely (!_hb_glyph_info_ligated (&info[i]) && |
| 566 » » _hb_glyph_info_is_default_ignorable (&info[i]))) |
| 551 { | 567 { |
| 552 if (!space) { | 568 if (space_status == SPACE_DONT_KNOW) |
| 553 /* We assume that the space glyph is not gid0. */ | 569 » space_status = c->font->get_glyph (' ', 0, &space) ? SPACE_AVAILABLE : S
PACE_UNAVAILABLE; |
| 554 if (unlikely (!c->font->get_glyph (' ', 0, &space)) || !space) | 570 |
| 555 » return; /* No point! */ | 571 if (space_status == SPACE_AVAILABLE) |
| 572 { |
| 573 » info[i].codepoint = space; |
| 574 » pos[i].x_advance = 0; |
| 575 » pos[i].y_advance = 0; |
| 556 } | 576 } |
| 557 c->buffer->info[i].codepoint = space; | 577 else |
| 558 c->buffer->pos[i].x_advance = 0; | 578 » continue; /* Delete it. */ |
| 559 c->buffer->pos[i].y_advance = 0; | |
| 560 } | 579 } |
| 580 if (j != i) |
| 581 { |
| 582 info[j] = info[i]; |
| 583 pos[j] = pos[i]; |
| 584 } |
| 585 j++; |
| 586 } |
| 587 c->buffer->len = j; |
| 561 } | 588 } |
| 562 | 589 |
| 563 | 590 |
| 564 /* Pull it all together! */ | 591 /* Pull it all together! */ |
| 565 | 592 |
| 566 static void | 593 static void |
| 567 hb_ot_shape_internal (hb_ot_shape_context_t *c) | 594 hb_ot_shape_internal (hb_ot_shape_context_t *c) |
| 568 { | 595 { |
| 569 c->buffer->deallocate_var_all (); | 596 c->buffer->deallocate_var_all (); |
| 570 | 597 |
| 571 /* Save the original direction, we use it later. */ | 598 /* Save the original direction, we use it later. */ |
| 572 c->target_direction = c->buffer->props.direction; | 599 c->target_direction = c->buffer->props.direction; |
| 573 | 600 |
| 574 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props0); | 601 _hb_buffer_allocate_unicode_vars (c->buffer); |
| 575 HB_BUFFER_ALLOCATE_VAR (c->buffer, unicode_props1); | |
| 576 | 602 |
| 577 c->buffer->clear_output (); | 603 c->buffer->clear_output (); |
| 578 | 604 |
| 579 hb_set_unicode_props (c->buffer); | 605 hb_set_unicode_props (c->buffer); |
| 580 hb_insert_dotted_circle (c->buffer, c->font); | 606 hb_insert_dotted_circle (c->buffer, c->font); |
| 581 hb_form_clusters (c->buffer); | 607 hb_form_clusters (c->buffer); |
| 582 | 608 |
| 583 hb_ensure_native_direction (c->buffer); | 609 hb_ensure_native_direction (c->buffer); |
| 584 | 610 |
| 585 hb_ot_substitute (c); | 611 hb_ot_substitute (c); |
| 586 hb_ot_position (c); | 612 hb_ot_position (c); |
| 587 | 613 |
| 588 hb_ot_hide_default_ignorables (c); | 614 hb_ot_hide_default_ignorables (c); |
| 589 | 615 |
| 590 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1); | 616 _hb_buffer_deallocate_unicode_vars (c->buffer); |
| 591 HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0); | |
| 592 | 617 |
| 593 c->buffer->props.direction = c->target_direction; | 618 c->buffer->props.direction = c->target_direction; |
| 594 | 619 |
| 595 c->buffer->deallocate_var_all (); | 620 c->buffer->deallocate_var_all (); |
| 596 } | 621 } |
| 597 | 622 |
| 598 | 623 |
| 599 hb_bool_t | 624 hb_bool_t |
| 600 _hb_ot_shape (hb_shape_plan_t *shape_plan, | 625 _hb_ot_shape (hb_shape_plan_t *shape_plan, |
| 601 hb_font_t *font, | 626 hb_font_t *font, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 hb_set_t copy; | 692 hb_set_t copy; |
| 668 copy.init (); | 693 copy.init (); |
| 669 do { | 694 do { |
| 670 copy.set (glyphs); | 695 copy.set (glyphs); |
| 671 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) | 696 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index)
;) |
| 672 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); | 697 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
| 673 } while (!copy.is_equal (glyphs)); | 698 } while (!copy.is_equal (glyphs)); |
| 674 | 699 |
| 675 hb_shape_plan_destroy (shape_plan); | 700 hb_shape_plan_destroy (shape_plan); |
| 676 } | 701 } |
| OLD | NEW |