src/hb-ot-layout-common-private.hh | 1 src/hb-ot-layout-gsubgpos-private.hh | 2 src/hb-ot-layout-private.hh | 6 src/hb-ot-shape-complex-arabic.cc | 2 src/hb-ot-shape-complex-indic-private.hh | 4 src/hb-ot-shape-complex-private.hh | 5 src/hb-ot-shape-fallback.cc | 38 +++++ src/hb-ot-shape-normalize-private.hh | 2 src/hb-ot-shape-normalize.cc | 88 ++++++++++--- src/hb-ot-shape-private.hh | 4 src/hb-ot-shape.cc | 198 +++++++++++++++---------------- src/hb-unicode-private.hh | 7 - src/hb-unicode.cc | 2 13 files changed, 219 insertions(+), 140 deletions(-)
New commits: commit b00321ea78793d9b3592b5173a9800e6322424fe Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 22:33:32 2012 -0400 [OT] Avoid calling get_glyph() twice Essentially move the glyph mapping to normalization process. The effect on Devanagari is small (but observable). Should be more observable in simple text, like ASCII. diff --git a/src/hb-ot-shape-normalize-private.hh b/src/hb-ot-shape-normalize-private.hh index f222c07..462b87d 100644 --- a/src/hb-ot-shape-normalize-private.hh +++ b/src/hb-ot-shape-normalize-private.hh @@ -32,6 +32,8 @@ #include "hb-font.h" #include "hb-buffer.h" +/* buffer var allocations, used during the normalization process */ +#define glyph_index() var1.u32 enum hb_ot_shape_normalization_mode_t { HB_OT_SHAPE_NORMALIZATION_MODE_DECOMPOSED, diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index ccaf1d7..e6092d6 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -258,16 +258,25 @@ compose_func (hb_unicode_funcs_t *unicode, return found; } + +static inline void +set_glyph (hb_glyph_info_t &info, hb_font_t *font) +{ + hb_font_get_glyph (font, info.codepoint, 0, &info.glyph_index()); +} + static inline void -output_char (hb_buffer_t *buffer, hb_codepoint_t unichar) +output_char (hb_buffer_t *buffer, hb_codepoint_t unichar, hb_codepoint_t glyph) { + buffer->cur().glyph_index() = glyph; buffer->output_glyph (unichar); _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode); } static inline void -next_char (hb_buffer_t *buffer) +next_char (hb_buffer_t *buffer, hb_codepoint_t glyph) { + buffer->cur().glyph_index() = glyph; buffer->next_glyph (); } @@ -282,31 +291,31 @@ decompose (hb_font_t *font, hb_buffer_t *buffer, bool shortest, hb_codepoint_t ab) { - hb_codepoint_t a, b, glyph; + hb_codepoint_t a, b, a_glyph, b_glyph; if (!decompose_func (buffer->unicode, ab, &a, &b) || - (b && !font->get_glyph (b, 0, &glyph))) + (b && !font->get_glyph (b, 0, &b_glyph))) return false; - bool has_a = font->get_glyph (a, 0, &glyph); + bool has_a = font->get_glyph (a, 0, &a_glyph); if (shortest && has_a) { /* Output a and b */ - output_char (buffer, a); + output_char (buffer, a, a_glyph); if (b) - output_char (buffer, b); + output_char (buffer, b, b_glyph); return true; } if (decompose (font, buffer, shortest, a)) { if (b) - output_char (buffer, b); + output_char (buffer, b, b_glyph); return true; } if (has_a) { - output_char (buffer, a); + output_char (buffer, a, a_glyph); if (b) - output_char (buffer, b); + output_char (buffer, b, b_glyph); return true; } @@ -319,18 +328,18 @@ decompose_compatibility (hb_font_t *font, hb_buffer_t *buffer, { unsigned int len, i; hb_codepoint_t decomposed[HB_UNICODE_MAX_DECOMPOSITION_LEN]; + hb_codepoint_t glyphs[HB_UNICODE_MAX_DECOMPOSITION_LEN]; len = buffer->unicode->decompose_compatibility (u, decomposed); if (!len) return false; - hb_codepoint_t glyph; for (i = 0; i < len; i++) - if (!font->get_glyph (decomposed[i], 0, &glyph)) + if (!font->get_glyph (decomposed[i], 0, &glyphs[i])) return false; for (i = 0; i < len; i++) - output_char (buffer, decomposed[i]); + output_char (buffer, decomposed[i], glyphs[i]); return true; } @@ -343,15 +352,38 @@ decompose_current_character (hb_font_t *font, hb_buffer_t *buffer, /* Kind of a cute waterfall here... */ if (shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph)) - next_char (buffer); + next_char (buffer, glyph); else if (decompose (font, buffer, shortest, buffer->cur().codepoint)) skip_char (buffer); else if (!shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph)) - next_char (buffer); + next_char (buffer, glyph); else if (decompose_compatibility (font, buffer, buffer->cur().codepoint)) skip_char (buffer); - else - next_char (buffer); + else { + /* A glyph-not-found case... */ + font->get_glyph (buffer->cur().codepoint, 0, &glyph); + next_char (buffer, glyph); + } +} + +static inline void +handle_variation_selector_cluster (hb_font_t *font, hb_buffer_t *buffer, + unsigned int end) +{ + for (; buffer->idx < end - 1;) { + if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { + /* The next two lines are some ugly lines... But work. */ + font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &buffer->cur().glyph_index()); + buffer->replace_glyphs (2, 1, &buffer->cur().codepoint); + } else { + set_glyph (buffer->cur(), font); + buffer->next_glyph (); + } + } + if (likely (buffer->idx < end)) { + set_glyph (buffer->cur(), font); + buffer->next_glyph (); + } } static void @@ -361,8 +393,7 @@ decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer, /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */ for (unsigned int i = buffer->idx; i < end; i++) if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { - while (buffer->idx < end) - next_char (buffer); + handle_variation_selector_cluster (font, buffer, end); return; } @@ -457,7 +488,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, buffer->clear_output (); count = buffer->len; unsigned int starter = 0; - next_char (buffer); + buffer->next_glyph (); while (buffer->idx < count) { hb_codepoint_t composed, glyph; @@ -478,19 +509,20 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, font->get_glyph (composed, 0, &glyph)) { /* Composes. */ - next_char (buffer); /* Copy to out-buffer. */ + buffer->next_glyph (); /* Copy to out-buffer. */ if (unlikely (buffer->in_error)) return; buffer->merge_out_clusters (starter, buffer->out_len); buffer->out_len--; /* Remove the second composable. */ buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */ + set_glyph (buffer->out_info[starter], font); _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); continue; } /* Blocked, or doesn't compose. */ - next_char (buffer); + buffer->next_glyph (); if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) starter = buffer->out_len - 1; diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index b4745c5..2062102 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -308,28 +308,12 @@ hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) } static inline void -hb_ot_map_glyphs (hb_font_t *font, - hb_buffer_t *buffer) +hb_ot_map_glyphs_fast (hb_buffer_t *buffer) { - hb_codepoint_t glyph; - - buffer->clear_output (); - - unsigned int count = buffer->len - 1; - for (buffer->idx = 0; buffer->idx < count;) { - if (unlikely (buffer->unicode->is_variation_selector (buffer->cur(+1).codepoint))) { - font->get_glyph (buffer->cur().codepoint, buffer->cur(+1).codepoint, &glyph); - buffer->replace_glyphs (2, 1, &glyph); - } else { - font->get_glyph (buffer->cur().codepoint, 0, &glyph); - buffer->replace_glyph (glyph); - } - } - if (likely (buffer->idx < buffer->len)) { - font->get_glyph (buffer->cur().codepoint, 0, &glyph); - buffer->replace_glyph (glyph); - } - buffer->swap_buffers (); + /* Normalization process sets up glyph_index(), we just copy it. */ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->info[i].codepoint = buffer->info[i].glyph_index(); } static inline void @@ -337,6 +321,8 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) { hb_ot_mirror_chars (c); + HB_BUFFER_ALLOCATE_VAR (c->buffer, glyph_index); + _hb_ot_shape_normalize (c->font, c->buffer, c->plan->shaper->normalization_preference ? c->plan->shaper->normalization_preference (c->plan) : @@ -344,7 +330,9 @@ hb_ot_substitute_default (hb_ot_shape_context_t *c) hb_ot_shape_setup_masks (c); - hb_ot_map_glyphs (c->font, c->buffer); + hb_ot_map_glyphs_fast (c->buffer); + + HB_BUFFER_DEALLOCATE_VAR (c->buffer, glyph_index); } static inline void @@ -558,6 +546,16 @@ _hb_ot_shape (hb_shape_plan_t *shape_plan, } + +static inline void +hb_ot_map_glyphs_dumb (hb_font_t *font, + hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + font->get_glyph (buffer->cur().codepoint, 0, &buffer->cur().codepoint); +} + void hb_ot_shape_glyphs_closure (hb_font_t *font, hb_buffer_t *buffer, @@ -574,7 +572,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, /* TODO: normalization? have shapers do closure()? */ /* TODO: Deal with mirrored chars? */ - hb_ot_map_glyphs (font, buffer); + hb_ot_map_glyphs_dumb (font, buffer); /* Seed it. It's user's responsibility to have cleard glyphs * if that's what they desire. */ commit 12c0875eafa4bd92db650e5acca046d99594d1e6 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 22:00:53 2012 -0400 [OT] Remove redundant check diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 0fab82b..b4745c5 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -279,7 +279,7 @@ hb_ot_mirror_chars (hb_ot_shape_context_t *c) for (unsigned int i = 0; i < count; i++) { hb_codepoint_t codepoint = unicode->mirroring (c->buffer->info[i].codepoint); if (likely (codepoint == c->buffer->info[i].codepoint)) - c->buffer->info[i].mask |= rtlm_mask; /* TODO this should be moved to before setting user-feature masks */ + c->buffer->info[i].mask |= rtlm_mask; else c->buffer->info[i].codepoint = codepoint; } @@ -313,9 +313,6 @@ hb_ot_map_glyphs (hb_font_t *font, { hb_codepoint_t glyph; - if (unlikely (!buffer->len)) - return; - buffer->clear_output (); unsigned int count = buffer->len - 1; commit 5c60b70c89b4e0a6512d9fd1ab5394dd76feb742 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 21:58:07 2012 -0400 [OT] More code shuffling around Preparing for merging map_glyphs() and normalize(). diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index d1e1d6c..0fab82b 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -217,34 +217,13 @@ struct hb_ot_shape_context_t /* Transient stuff */ hb_direction_t target_direction; - hb_bool_t applied_position_complex; }; -static void -hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) -{ - hb_ot_map_t *map = &c->plan->map; - - hb_mask_t global_mask = map->get_global_mask (); - c->buffer->reset_masks (global_mask); - - if (c->plan->shaper->setup_masks) - c->plan->shaper->setup_masks (c->plan, c->buffer, c->font); - - for (unsigned int i = 0; i < c->num_user_features; i++) - { - const hb_feature_t *feature = &c->user_features[i]; - if (!(feature->start == 0 && feature->end == (unsigned int)-1)) { - unsigned int shift; - hb_mask_t mask = map->get_mask (feature->tag, &shift); - c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end); - } - } -} /* Main shaper */ + /* Prepare */ static void @@ -287,14 +266,13 @@ hb_ensure_native_direction (hb_buffer_t *buffer) /* Substitute */ -static void -hb_mirror_chars (hb_ot_shape_context_t *c) +static inline void +hb_ot_mirror_chars (hb_ot_shape_context_t *c) { - hb_unicode_funcs_t *unicode = c->buffer->unicode; - if (HB_DIRECTION_IS_FORWARD (c->target_direction)) return; + hb_unicode_funcs_t *unicode = c->buffer->unicode; hb_mask_t rtlm_mask = c->plan->map.get_1_mask (HB_TAG ('r','t','l','m')); unsigned int count = c->buffer->len; @@ -307,9 +285,31 @@ hb_mirror_chars (hb_ot_shape_context_t *c) } } -static void -hb_map_glyphs (hb_font_t *font, - hb_buffer_t *buffer) +static inline void +hb_ot_shape_setup_masks (hb_ot_shape_context_t *c) +{ + hb_ot_map_t *map = &c->plan->map; + + hb_mask_t global_mask = map->get_global_mask (); + c->buffer->reset_masks (global_mask); + + if (c->plan->shaper->setup_masks) + c->plan->shaper->setup_masks (c->plan, c->buffer, c->font); + + for (unsigned int i = 0; i < c->num_user_features; i++) + { + const hb_feature_t *feature = &c->user_features[i]; + if (!(feature->start == 0 && feature->end == (unsigned int)-1)) { + unsigned int shift; + hb_mask_t mask = map->get_mask (feature->tag, &shift); + c->buffer->set_masks (feature->value << shift, mask, feature->start, feature->end); + } + } +} + +static inline void +hb_ot_map_glyphs (hb_font_t *font, + hb_buffer_t *buffer) { hb_codepoint_t glyph; @@ -335,15 +335,22 @@ hb_map_glyphs (hb_font_t *font, buffer->swap_buffers (); } -static void -hb_substitute_default (hb_ot_shape_context_t *c) +static inline void +hb_ot_substitute_default (hb_ot_shape_context_t *c) { - hb_mirror_chars (c); + hb_ot_mirror_chars (c); + + _hb_ot_shape_normalize (c->font, c->buffer, + c->plan->shaper->normalization_preference ? + c->plan->shaper->normalization_preference (c->plan) : + HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT); + + hb_ot_shape_setup_masks (c); - hb_map_glyphs (c->font, c->buffer); + hb_ot_map_glyphs (c->font, c->buffer); } -static void +static inline void hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) { unsigned int count = c->buffer->len; @@ -354,7 +361,7 @@ hb_synthesize_glyph_classes (hb_ot_shape_context_t *c) } -static void +static inline void hb_ot_substitute_complex (hb_ot_shape_context_t *c) { hb_ot_layout_substitute_start (c->font, c->buffer); @@ -370,11 +377,17 @@ hb_ot_substitute_complex (hb_ot_shape_context_t *c) return; } +static inline void +hb_ot_substitute (hb_ot_shape_context_t *c) +{ + hb_ot_substitute_default (c); + hb_ot_substitute_complex (c); +} /* Position */ -static void -hb_position_default (hb_ot_shape_context_t *c) +static inline void +hb_ot_position_default (hb_ot_shape_context_t *c) { hb_ot_layout_position_start (c->font, c->buffer); @@ -391,9 +404,10 @@ hb_position_default (hb_ot_shape_context_t *c) } } -static void +static inline bool hb_ot_position_complex (hb_ot_shape_context_t *c) { + bool ret = false; if (hb_ot_layout_has_positioning (c->face)) { @@ -416,22 +430,22 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) &c->buffer->pos[i].y_offset); } - c->applied_position_complex = true; + ret = true; } hb_ot_layout_position_finish (c->font, c->buffer, c->plan->shaper->zero_width_attached_marks); - return; + return ret; } -static void -hb_position_complex_fallback (hb_ot_shape_context_t *c) +static inline void +hb_ot_position_complex_fallback (hb_ot_shape_context_t *c) { _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer); } -static void -hb_truetype_kern (hb_ot_shape_context_t *c) +static inline void +hb_ot_truetype_kern (hb_ot_shape_context_t *c) { /* TODO Check for kern=0 */ unsigned int count = c->buffer->len; @@ -455,14 +469,34 @@ hb_truetype_kern (hb_ot_shape_context_t *c) } } -static void +static inline void hb_position_complex_fallback_visual (hb_ot_shape_context_t *c) { - hb_truetype_kern (c); + hb_ot_truetype_kern (c); +} + +static inline void +hb_ot_position (hb_ot_shape_context_t *c) +{ + hb_ot_position_default (c); + + hb_bool_t fallback = !hb_ot_position_complex (c); + + if (fallback) + hb_ot_position_complex_fallback (c); + + if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) + hb_buffer_reverse (c->buffer); + + if (fallback) + hb_position_complex_fallback_visual (c); } + +/* Post-process */ + static void -hb_hide_zerowidth (hb_ot_shape_context_t *c) +hb_ot_hide_zerowidth (hb_ot_shape_context_t *c) { hb_codepoint_t space; if (!c->font->get_glyph (' ', 0, &space)) @@ -479,7 +513,7 @@ hb_hide_zerowidth (hb_ot_shape_context_t *c) } -/* Do it! */ +/* Pull it all together! */ static void hb_ot_shape_internal (hb_ot_shape_context_t *c) @@ -495,43 +529,14 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->clear_output (); hb_set_unicode_props (c->buffer); - hb_form_clusters (c->buffer); hb_ensure_native_direction (c->buffer); - _hb_ot_shape_normalize (c->font, c->buffer, - c->plan->shaper->normalization_preference ? - c->plan->shaper->normalization_preference (c->plan) : - HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT); - - hb_ot_shape_setup_masks (c); - - /* SUBSTITUTE */ - { - hb_substitute_default (c); - - hb_ot_substitute_complex (c); - } - - /* POSITION */ - { - hb_position_default (c); - - hb_ot_position_complex (c); - - hb_bool_t position_fallback = !c->applied_position_complex; - if (position_fallback) - hb_position_complex_fallback (c); - - if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) - hb_buffer_reverse (c->buffer); - - if (position_fallback) - hb_position_complex_fallback_visual (c); - } + hb_ot_substitute (c); + hb_ot_position (c); - hb_hide_zerowidth (c); + hb_ot_hide_zerowidth (c); HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props1); HB_BUFFER_DEALLOCATE_VAR (c->buffer, unicode_props0); @@ -572,7 +577,7 @@ hb_ot_shape_glyphs_closure (hb_font_t *font, /* TODO: normalization? have shapers do closure()? */ /* TODO: Deal with mirrored chars? */ - hb_map_glyphs (font, buffer); + hb_ot_map_glyphs (font, buffer); /* Seed it. It's user's responsibility to have cleard glyphs * if that's what they desire. */ commit cd0c6e148f6d078b364370cb2f808b793b921be2 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 21:48:55 2012 -0400 Shuffle buffer variable allocations around To room for more allocations, coming. diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index 510aec9..e101782 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -39,9 +39,9 @@ /* buffer var allocations, used during the GSUB/GPOS processing */ -#define glyph_props() var1.u16[1] /* GDEF glyph properties */ -#define syllable() var2.u8[0] /* GSUB/GPOS shaping boundaries */ -#define lig_props() var2.u8[1] /* GSUB/GPOS ligature tracking */ +#define glyph_props() var1.u16[0] /* GDEF glyph properties */ +#define syllable() var1.u8[2] /* GSUB/GPOS shaping boundaries */ +#define lig_props() var1.u8[3] /* GSUB/GPOS ligature tracking */ #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot) diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index b014c74..2a96b7d 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -30,7 +30,7 @@ /* buffer var allocations */ -#define arabic_shaping_action() complex_var_temporary_u8() /* arabic shaping action */ +#define arabic_shaping_action() complex_var_u8_0() /* arabic shaping action */ /* diff --git a/src/hb-ot-shape-complex-indic-private.hh b/src/hb-ot-shape-complex-indic-private.hh index 719d287..79daba5 100644 --- a/src/hb-ot-shape-complex-indic-private.hh +++ b/src/hb-ot-shape-complex-indic-private.hh @@ -35,8 +35,8 @@ /* buffer var allocations */ -#define indic_category() complex_var_persistent_u8_0() /* indic_category_t */ -#define indic_position() complex_var_persistent_u8_1() /* indic_matra_category_t */ +#define indic_category() complex_var_u8_0() /* indic_category_t */ +#define indic_position() complex_var_u8_1() /* indic_matra_category_t */ #define INDIC_TABLE_ELEMENT_TYPE uint8_t diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index baece32..efff325 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -35,9 +35,8 @@ /* buffer var allocations, used by complex shapers */ -#define complex_var_persistent_u8_0() var2.u8[2] -#define complex_var_persistent_u8_1() var2.u8[3] -#define complex_var_temporary_u8() var2.u8[0] +#define complex_var_u8_0() var2.u8[2] +#define complex_var_u8_1() var2.u8[3] diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh index 975665e..f856045 100644 --- a/src/hb-ot-shape-private.hh +++ b/src/hb-ot-shape-private.hh @@ -34,8 +34,8 @@ /* buffer var allocations, used during the entire shaping process */ -#define unicode_props0() var1.u8[0] -#define unicode_props1() var1.u8[1] +#define unicode_props0() var2.u8[0] +#define unicode_props1() var2.u8[1] commit 8d1eef3f32fb539de2a72804fa3834acc18daab5 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 21:31:52 2012 -0400 Minor diff --git a/src/hb-ot-shape-normalize.cc b/src/hb-ot-shape-normalize.cc index b5e0b4d..ccaf1d7 100644 --- a/src/hb-ot-shape-normalize.cc +++ b/src/hb-ot-shape-normalize.cc @@ -258,13 +258,25 @@ compose_func (hb_unicode_funcs_t *unicode, return found; } -static void -output_glyph (hb_buffer_t *buffer, hb_codepoint_t glyph) +static inline void +output_char (hb_buffer_t *buffer, hb_codepoint_t unichar) { - buffer->output_glyph (glyph); + buffer->output_glyph (unichar); _hb_glyph_info_set_unicode_props (&buffer->prev(), buffer->unicode); } +static inline void +next_char (hb_buffer_t *buffer) +{ + buffer->next_glyph (); +} + +static inline void +skip_char (hb_buffer_t *buffer) +{ + buffer->skip_glyph (); +} + static bool decompose (hb_font_t *font, hb_buffer_t *buffer, bool shortest, @@ -279,22 +291,22 @@ decompose (hb_font_t *font, hb_buffer_t *buffer, bool has_a = font->get_glyph (a, 0, &glyph); if (shortest && has_a) { /* Output a and b */ - output_glyph (buffer, a); + output_char (buffer, a); if (b) - output_glyph (buffer, b); + output_char (buffer, b); return true; } if (decompose (font, buffer, shortest, a)) { if (b) - output_glyph (buffer, b); + output_char (buffer, b); return true; } if (has_a) { - output_glyph (buffer, a); + output_char (buffer, a); if (b) - output_glyph (buffer, b); + output_char (buffer, b); return true; } @@ -318,7 +330,7 @@ decompose_compatibility (hb_font_t *font, hb_buffer_t *buffer, return false; for (i = 0; i < len; i++) - output_glyph (buffer, decomposed[i]); + output_char (buffer, decomposed[i]); return true; } @@ -331,15 +343,15 @@ decompose_current_character (hb_font_t *font, hb_buffer_t *buffer, /* Kind of a cute waterfall here... */ if (shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph)) - buffer->next_glyph (); + next_char (buffer); else if (decompose (font, buffer, shortest, buffer->cur().codepoint)) - buffer->skip_glyph (); + skip_char (buffer); else if (!shortest && font->get_glyph (buffer->cur().codepoint, 0, &glyph)) - buffer->next_glyph (); + next_char (buffer); else if (decompose_compatibility (font, buffer, buffer->cur().codepoint)) - buffer->skip_glyph (); + skip_char (buffer); else - buffer->next_glyph (); + next_char (buffer); } static void @@ -350,7 +362,7 @@ decompose_multi_char_cluster (hb_font_t *font, hb_buffer_t *buffer, for (unsigned int i = buffer->idx; i < end; i++) if (unlikely (buffer->unicode->is_variation_selector (buffer->info[i].codepoint))) { while (buffer->idx < end) - buffer->next_glyph (); + next_char (buffer); return; } @@ -445,7 +457,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, buffer->clear_output (); count = buffer->len; unsigned int starter = 0; - buffer->next_glyph (); + next_char (buffer); while (buffer->idx < count) { hb_codepoint_t composed, glyph; @@ -466,11 +478,11 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, font->get_glyph (composed, 0, &glyph)) { /* Composes. */ - buffer->next_glyph (); /* Copy to out-buffer. */ + next_char (buffer); /* Copy to out-buffer. */ if (unlikely (buffer->in_error)) return; buffer->merge_out_clusters (starter, buffer->out_len); - buffer->out_len--; /* Remove the second composble. */ + buffer->out_len--; /* Remove the second composable. */ buffer->out_info[starter].codepoint = composed; /* Modify starter and carry on. */ _hb_glyph_info_set_unicode_props (&buffer->out_info[starter], buffer->unicode); @@ -478,7 +490,7 @@ _hb_ot_shape_normalize (hb_font_t *font, hb_buffer_t *buffer, } /* Blocked, or doesn't compose. */ - buffer->next_glyph (); + next_char (buffer); if (_hb_glyph_info_get_modified_combining_class (&buffer->prev()) == 0) starter = buffer->out_len - 1; commit 56c9e7c004e802ddcb8c704346026f1d7a812f9f Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 21:12:30 2012 -0400 Fill out combining class resetting for fallback shaping Thai/Lao/Tibetan diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index 71aed89..abc7e2b 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -49,7 +49,9 @@ recategorize_combining_class (unsigned int modified_combining_class) * from hb-unicode.cc. */ switch (modified_combining_class) { + /* Hebrew */ + case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */ case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */ case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */ @@ -79,7 +81,9 @@ recategorize_combining_class (unsigned int modified_combining_class) case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */ break; + /* Arabic and Syriac */ + case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */ case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */ case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */ @@ -94,7 +98,39 @@ recategorize_combining_class (unsigned int modified_combining_class) case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */ return HB_UNICODE_COMBINING_CLASS_BELOW; - /* TODO Thai, Lao, and Tibetan */ + + /* Thai */ + + /* Note: to be useful we also need to position U+0E3A that has ccc=9 (virama). + * But viramas can be both above and below based on the codepoint / script. */ + + case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */ + return HB_UNICODE_COMBINING_CLASS_BELOW; + + case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */ + return HB_UNICODE_COMBINING_CLASS_ABOVE; + + + /* Lao */ + + case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */ + return HB_UNICODE_COMBINING_CLASS_BELOW; + + case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */ + return HB_UNICODE_COMBINING_CLASS_ABOVE; + + + /* Tibetan */ + + case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */ + return HB_UNICODE_COMBINING_CLASS_BELOW; + + case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/ + return HB_UNICODE_COMBINING_CLASS_ABOVE; + + case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */ + return HB_UNICODE_COMBINING_CLASS_BELOW; + } return modified_combining_class; diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh index b2af7c8..53214b9 100644 --- a/src/hb-unicode-private.hh +++ b/src/hb-unicode-private.hh @@ -260,8 +260,9 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; /* Thai * - * Modify U+0E38 and U+0E39 (ccc=104) to be reordered before U+0E3A (ccc=9). - * Uniscribe does this too. + * Modify U+0E38 and U+0E39 (ccc=103) to be reordered before U+0E3A (ccc=9). + * Assign 3, which is unassigned otherwise. + * Uniscribe does this reordering too. */ #define HB_MODIFIED_COMBINING_CLASS_CCC103 3 /* sara u / sara uu */ #define HB_MODIFIED_COMBINING_CLASS_CCC107 107 /* mai * */ @@ -273,7 +274,7 @@ extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil; /* Tibetan */ #define HB_MODIFIED_COMBINING_CLASS_CCC129 129 /* sign aa */ #define HB_MODIFIED_COMBINING_CLASS_CCC130 130 /* sign i */ -#define HB_MODIFIED_COMBINING_CLASS_CCC133 132 /* sign u */ +#define HB_MODIFIED_COMBINING_CLASS_CCC132 132 /* sign u */ #endif /* HB_UNICODE_PRIVATE_HH */ diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 30dc7de..8979eaa 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -358,7 +358,7 @@ _hb_modified_combining_class[256] = HB_MODIFIED_COMBINING_CLASS_CCC129, HB_MODIFIED_COMBINING_CLASS_CCC130, 131, - HB_MODIFIED_COMBINING_CLASS_CCC133, + HB_MODIFIED_COMBINING_CLASS_CCC132, 133, 134, 135, 136, 137, 138, 139, commit a321e1d51e0e7fa02738410e8d6e77c841bc6b13 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 18:30:34 2012 -0400 Revert "Reject lookups with no subTable" This reverts commit 30ec9002d84e8b49290e782e6192069821ffa942. See previous commit. diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index fad813f..cea5b75 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -314,7 +314,6 @@ struct Lookup TRACE_SANITIZE (); /* Real sanitize of the subtables is done by GSUB/GPOS/... */ if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false); - if (!subTable.len) TRACE_RETURN (false); if (unlikely (lookupFlag & LookupFlag::UseMarkFilteringSet)) { USHORT &markFilteringSet = StructAfter<USHORT> (subTable); commit 2eaf482b371034ce6ebfaedee98049b036fd3493 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Aug 9 18:30:05 2012 -0400 Revert "[GSUB/GPOS] Reject Context/ChainContext lookups with zero input" This reverts commit 0981068b75710397f08e0d2d776a0a2ea68d7117. I was confused. Even if we access coverage[0] unconditionally, we don't need bound checks since the array machinary already handles that. diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh index fd5fb19..ba2a7e0 100644 --- a/src/hb-ot-layout-gsubgpos-private.hh +++ b/src/hb-ot-layout-gsubgpos-private.hh @@ -928,7 +928,6 @@ struct ContextFormat3 TRACE_SANITIZE (); if (!c->check_struct (this)) return TRACE_RETURN (false); unsigned int count = glyphCount; - if (unlikely (!glyphCount)) return TRACE_RETURN (false); if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false); for (unsigned int i = 0; i < count; i++) if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false); @@ -1467,7 +1466,6 @@ struct ChainContextFormat3 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false); OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack); if (!input.sanitize (c, this)) return TRACE_RETURN (false); - if (unlikely (!input.len)) return TRACE_RETURN (false); OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input); if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false); ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead); _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/harfbuzz