68 unsigned int num_user_features) |
68 unsigned int num_user_features) |
69 { |
69 { |
70 hb_ot_map_builder_t *map = &planner->map; |
70 hb_ot_map_builder_t *map = &planner->map; |
71 |
71 |
72 map->add_global_bool_feature (HB_TAG('r','v','r','n')); |
72 map->add_global_bool_feature (HB_TAG('r','v','r','n')); |
73 map->add_gsub_pause (NULL); |
73 map->add_gsub_pause (nullptr); |
74 |
74 |
75 switch (props->direction) { |
75 switch (props->direction) { |
76 case HB_DIRECTION_LTR: |
76 case HB_DIRECTION_LTR: |
77 map->add_global_bool_feature (HB_TAG ('l','t','r','a')); |
77 map->add_global_bool_feature (HB_TAG ('l','t','r','a')); |
78 map->add_global_bool_feature (HB_TAG ('l','t','r','m')); |
78 map->add_global_bool_feature (HB_TAG ('l','t','r','m')); |
170 const int *coords, |
174 const int *coords, |
171 unsigned int num_coords) |
175 unsigned int num_coords) |
172 { |
176 { |
173 hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); |
177 hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); |
174 if (unlikely (!plan)) |
178 if (unlikely (!plan)) |
175 return NULL; |
179 return nullptr; |
176 |
180 |
177 hb_ot_shape_planner_t planner (shape_plan); |
181 hb_ot_shape_planner_t planner (shape_plan); |
178 |
182 |
179 planner.shaper = hb_ot_shape_complex_categorize (&planner); |
183 planner.shaper = hb_ot_shape_complex_categorize (&planner); |
180 |
184 |
269 } |
273 } |
270 |
274 |
271 static void |
275 static void |
272 hb_form_clusters (hb_buffer_t *buffer) |
276 hb_form_clusters (hb_buffer_t *buffer) |
273 { |
277 { |
274 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) || |
278 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII)) |
275 buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
|
276 return; |
279 return; |
277 |
280 |
278 /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ |
281 /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */ |
279 unsigned int base = 0; |
282 unsigned int base = 0; |
280 unsigned int count = buffer->len; |
283 unsigned int count = buffer->len; |
282 for (unsigned int i = 1; i < count; i++) |
285 for (unsigned int i = 1; i < count; i++) |
283 { |
286 { |
284 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && |
287 if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) && |
285 !_hb_glyph_info_is_joiner (&info[i]))) |
288 !_hb_glyph_info_is_joiner (&info[i]))) |
286 { |
289 { |
287 buffer->merge_clusters (base, i); |
290 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
|
291 buffer->merge_clusters (base, i); |
|
292 else |
|
293 buffer->unsafe_to_break (base, i); |
288 base = i; |
294 base = i; |
289 } |
295 } |
290 } |
296 } |
291 buffer->merge_clusters (base, count); |
297 if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES) |
|
298 buffer->merge_clusters (base, count); |
|
299 else |
|
300 buffer->unsafe_to_break (base, count); |
292 } |
301 } |
293 |
302 |
294 static void |
303 static void |
295 hb_ensure_native_direction (hb_buffer_t *buffer) |
304 hb_ensure_native_direction (hb_buffer_t *buffer) |
296 { |
305 { |
360 !c->plan->has_frac) |
369 !c->plan->has_frac) |
361 return; |
370 return; |
362 |
371 |
363 hb_buffer_t *buffer = c->buffer; |
372 hb_buffer_t *buffer = c->buffer; |
364 |
373 |
365 /* TODO look in pre/post context text also. */ |
374 hb_mask_t pre_mask, post_mask; |
|
375 if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) |
|
376 { |
|
377 pre_mask = c->plan->numr_mask | c->plan->frac_mask; |
|
378 post_mask = c->plan->frac_mask | c->plan->dnom_mask; |
|
379 } |
|
380 else |
|
381 { |
|
382 pre_mask = c->plan->frac_mask | c->plan->dnom_mask; |
|
383 post_mask = c->plan->numr_mask | c->plan->frac_mask; |
|
384 } |
|
385 |
366 unsigned int count = buffer->len; |
386 unsigned int count = buffer->len; |
367 hb_glyph_info_t *info = buffer->info; |
387 hb_glyph_info_t *info = buffer->info; |
368 for (unsigned int i = 0; i < count; i++) |
388 for (unsigned int i = 0; i < count; i++) |
369 { |
389 { |
370 if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */ |
390 if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */ |
377 while (end < count && |
397 while (end < count && |
378 _hb_glyph_info_get_general_category (&info[end]) == |
398 _hb_glyph_info_get_general_category (&info[end]) == |
379 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
399 HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) |
380 end++; |
400 end++; |
381 |
401 |
|
402 buffer->unsafe_to_break (start, end); |
|
403 |
382 for (unsigned int j = start; j < i; j++) |
404 for (unsigned int j = start; j < i; j++) |
383 info[j].mask |= c->plan->numr_mask | c->plan->frac_mask; |
405 info[j].mask |= pre_mask; |
384 info[i].mask |= c->plan->frac_mask; |
406 info[i].mask |= c->plan->frac_mask; |
385 for (unsigned int j = i + 1; j < end; j++) |
407 for (unsigned int j = i + 1; j < end; j++) |
386 info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask; |
408 info[j].mask |= post_mask; |
387 |
409 |
388 i = end - 1; |
410 i = end - 1; |
389 } |
411 } |
390 } |
412 } |
391 } |
413 } |
492 if (j) |
514 if (j) |
493 { |
515 { |
494 /* Merge cluster backward. */ |
516 /* Merge cluster backward. */ |
495 if (cluster < info[j - 1].cluster) |
517 if (cluster < info[j - 1].cluster) |
496 { |
518 { |
|
519 unsigned int mask = info[i].mask; |
497 unsigned int old_cluster = info[j - 1].cluster; |
520 unsigned int old_cluster = info[j - 1].cluster; |
498 for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) |
521 for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--) |
499 info[k - 1].cluster = cluster; |
522 buffer->set_cluster (info[k - 1], cluster, mask); |
500 } |
523 } |
501 continue; |
524 continue; |
502 } |
525 } |
503 |
526 |
504 if (i + 1 < count) |
527 if (i + 1 < count) |
560 static inline void |
583 static inline void |
561 hb_ot_substitute_default (hb_ot_shape_context_t *c) |
584 hb_ot_substitute_default (hb_ot_shape_context_t *c) |
562 { |
585 { |
563 hb_buffer_t *buffer = c->buffer; |
586 hb_buffer_t *buffer = c->buffer; |
564 |
587 |
565 hb_ot_shape_initialize_masks (c); |
|
566 |
|
567 hb_ot_mirror_chars (c); |
588 hb_ot_mirror_chars (c); |
568 |
589 |
569 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); |
590 HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index); |
570 |
591 |
571 _hb_ot_shape_normalize (c->plan, buffer, c->font); |
592 _hb_ot_shape_normalize (c->plan, buffer, c->font); |
670 } |
691 } |
671 |
692 |
672 static inline void |
693 static inline void |
673 hb_ot_position_complex (hb_ot_shape_context_t *c) |
694 hb_ot_position_complex (hb_ot_shape_context_t *c) |
674 { |
695 { |
675 hb_ot_layout_position_start (c->font, c->buffer); |
|
676 |
|
677 unsigned int count = c->buffer->len; |
696 unsigned int count = c->buffer->len; |
|
697 hb_glyph_info_t *info = c->buffer->info; |
|
698 hb_glyph_position_t *pos = c->buffer->pos; |
678 |
699 |
679 /* If the font has no GPOS, AND, no fallback positioning will |
700 /* If the font has no GPOS, AND, no fallback positioning will |
680 * happen, AND, direction is forward, then when zeroing mark |
701 * happen, AND, direction is forward, then when zeroing mark |
681 * widths, we shift the mark with it, such that the mark |
702 * widths, we shift the mark with it, such that the mark |
682 * is positioned hanging over the previous glyph. When |
703 * is positioned hanging over the previous glyph. When |
687 */ |
708 */ |
688 bool adjust_offsets_when_zeroing = c->fallback_positioning && |
709 bool adjust_offsets_when_zeroing = c->fallback_positioning && |
689 !c->plan->shaper->fallback_position && |
710 !c->plan->shaper->fallback_position && |
690 HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); |
711 HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); |
691 |
712 |
|
713 /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ |
|
714 |
|
715 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ |
|
716 if (c->font->has_glyph_h_origin_func ()) |
|
717 for (unsigned int i = 0; i < count; i++) |
|
718 c->font->add_glyph_h_origin (info[i].codepoint, |
|
719 &pos[i].x_offset, |
|
720 &pos[i].y_offset); |
|
721 |
|
722 hb_ot_layout_position_start (c->font, c->buffer); |
|
723 |
692 switch (c->plan->shaper->zero_width_marks) |
724 switch (c->plan->shaper->zero_width_marks) |
693 { |
725 { |
694 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
726 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: |
695 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
727 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
696 break; |
728 break; |
700 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
732 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
701 break; |
733 break; |
702 } |
734 } |
703 |
735 |
704 if (likely (!c->fallback_positioning)) |
736 if (likely (!c->fallback_positioning)) |
705 { |
|
706 hb_glyph_info_t *info = c->buffer->info; |
|
707 hb_glyph_position_t *pos = c->buffer->pos; |
|
708 |
|
709 /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ |
|
710 |
|
711 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ |
|
712 if (c->font->has_glyph_h_origin_func ()) |
|
713 for (unsigned int i = 0; i < count; i++) |
|
714 c->font->add_glyph_h_origin (info[i].codepoint, |
|
715 &pos[i].x_offset, |
|
716 &pos[i].y_offset); |
|
717 |
|
718 c->plan->position (c->font, c->buffer); |
737 c->plan->position (c->font, c->buffer); |
719 |
|
720 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ |
|
721 if (c->font->has_glyph_h_origin_func ()) |
|
722 for (unsigned int i = 0; i < count; i++) |
|
723 c->font->subtract_glyph_h_origin (info[i].codepoint, |
|
724 &pos[i].x_offset, |
|
725 &pos[i].y_offset); |
|
726 |
|
727 } |
|
728 |
738 |
729 switch (c->plan->shaper->zero_width_marks) |
739 switch (c->plan->shaper->zero_width_marks) |
730 { |
740 { |
731 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
741 case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: |
732 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
742 zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); |
740 |
750 |
741 /* Finishing off GPOS has to follow a certain order. */ |
751 /* Finishing off GPOS has to follow a certain order. */ |
742 hb_ot_layout_position_finish_advances (c->font, c->buffer); |
752 hb_ot_layout_position_finish_advances (c->font, c->buffer); |
743 hb_ot_zero_width_default_ignorables (c); |
753 hb_ot_zero_width_default_ignorables (c); |
744 hb_ot_layout_position_finish_offsets (c->font, c->buffer); |
754 hb_ot_layout_position_finish_offsets (c->font, c->buffer); |
|
755 |
|
756 /* The nil glyph_h_origin() func returns 0, so no need to apply it. */ |
|
757 if (c->font->has_glyph_h_origin_func ()) |
|
758 for (unsigned int i = 0; i < count; i++) |
|
759 c->font->subtract_glyph_h_origin (info[i].codepoint, |
|
760 &pos[i].x_offset, |
|
761 &pos[i].y_offset); |
745 } |
762 } |
746 |
763 |
747 static inline void |
764 static inline void |
748 hb_ot_position (hb_ot_shape_context_t *c) |
765 hb_ot_position (hb_ot_shape_context_t *c) |
749 { |
766 { |
765 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); |
782 _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); |
766 |
783 |
767 _hb_buffer_deallocate_gsubgpos_vars (c->buffer); |
784 _hb_buffer_deallocate_gsubgpos_vars (c->buffer); |
768 } |
785 } |
769 |
786 |
|
787 static inline void |
|
788 hb_propagate_flags (hb_buffer_t *buffer) |
|
789 { |
|
790 /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. |
|
791 * Simplifies using them. */ |
|
792 |
|
793 if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) |
|
794 return; |
|
795 |
|
796 hb_glyph_info_t *info = buffer->info; |
|
797 |
|
798 foreach_cluster (buffer, start, end) |
|
799 { |
|
800 unsigned int mask = 0; |
|
801 for (unsigned int i = start; i < end; i++) |
|
802 if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) |
|
803 { |
|
804 mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; |
|
805 break; |
|
806 } |
|
807 if (mask) |
|
808 for (unsigned int i = start; i < end; i++) |
|
809 info[i].mask |= mask; |
|
810 } |
|
811 } |
770 |
812 |
771 /* Pull it all together! */ |
813 /* Pull it all together! */ |
772 |
814 |
773 static void |
815 static void |
774 hb_ot_shape_internal (hb_ot_shape_context_t *c) |
816 hb_ot_shape_internal (hb_ot_shape_context_t *c) |
791 |
833 |
792 _hb_buffer_allocate_unicode_vars (c->buffer); |
834 _hb_buffer_allocate_unicode_vars (c->buffer); |
793 |
835 |
794 c->buffer->clear_output (); |
836 c->buffer->clear_output (); |
795 |
837 |
|
838 hb_ot_shape_initialize_masks (c); |
796 hb_set_unicode_props (c->buffer); |
839 hb_set_unicode_props (c->buffer); |
797 hb_insert_dotted_circle (c->buffer, c->font); |
840 hb_insert_dotted_circle (c->buffer, c->font); |
|
841 |
798 hb_form_clusters (c->buffer); |
842 hb_form_clusters (c->buffer); |
799 |
843 |
800 hb_ensure_native_direction (c->buffer); |
844 hb_ensure_native_direction (c->buffer); |
801 |
845 |
802 if (c->plan->shaper->preprocess_text) |
846 if (c->plan->shaper->preprocess_text) |
807 |
851 |
808 hb_ot_hide_default_ignorables (c); |
852 hb_ot_hide_default_ignorables (c); |
809 |
853 |
810 if (c->plan->shaper->postprocess_glyphs) |
854 if (c->plan->shaper->postprocess_glyphs) |
811 c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); |
855 c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); |
|
856 |
|
857 hb_propagate_flags (c->buffer); |
812 |
858 |
813 _hb_buffer_deallocate_unicode_vars (c->buffer); |
859 _hb_buffer_deallocate_unicode_vars (c->buffer); |
814 |
860 |
815 c->buffer->props.direction = c->target_direction; |
861 c->buffer->props.direction = c->target_direction; |
816 |
862 |
880 unsigned int num_features, |
926 unsigned int num_features, |
881 hb_set_t *glyphs) |
927 hb_set_t *glyphs) |
882 { |
928 { |
883 hb_ot_shape_plan_t plan; |
929 hb_ot_shape_plan_t plan; |
884 |
930 |
885 const char *shapers[] = {"ot", NULL}; |
931 const char *shapers[] = {"ot", nullptr}; |
886 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, |
932 hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, |
887 features, num_features, shapers); |
933 features, num_features, shapers); |
888 |
934 |
889 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL; |
935 bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL; |
890 |
936 |
891 unsigned int count = buffer->len; |
937 unsigned int count = buffer->len; |
892 hb_glyph_info_t *info = buffer->info; |
938 hb_glyph_info_t *info = buffer->info; |
893 for (unsigned int i = 0; i < count; i++) |
939 for (unsigned int i = 0; i < count; i++) |
894 add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs); |
940 add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs); |
895 |
941 |
896 hb_set_t lookups; |
942 hb_set_t *lookups = hb_set_create (); |
897 lookups.init (); |
943 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups); |
898 hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups); |
|
899 |
944 |
900 /* And find transitive closure. */ |
945 /* And find transitive closure. */ |
901 hb_set_t copy; |
946 hb_set_t *copy = hb_set_create (); |
902 copy.init (); |
|
903 do { |
947 do { |
904 copy.set (glyphs); |
948 copy->set (glyphs); |
905 for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index);) |
949 for (hb_codepoint_t lookup_index = -1; hb_set_next (lookups, &lookup_index);) |
906 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
950 hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs); |
907 } while (!copy.is_equal (glyphs)); |
951 } while (!copy->is_equal (glyphs)); |
|
952 hb_set_destroy (copy); |
|
953 |
|
954 hb_set_destroy (lookups); |
908 |
955 |
909 hb_shape_plan_destroy (shape_plan); |
956 hb_shape_plan_destroy (shape_plan); |
910 } |
957 } |