X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-ot-layout.cc;h=a49f339cc085f4cc7fb4b12249bcf37c54015671;hb=18c42850c9327ab4479ff150660a76d4ff6f3e9c;hp=d48ef70b63b47f064303a1563817bd4098f83e2e;hpb=8a3511ac6c795226699c2b36e03401ecdf88f5f8;p=framework%2Fuifw%2Fharfbuzz.git diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index d48ef70..a49f339 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -1,9 +1,9 @@ /* - * Copyright (C) 1998-2004 David Turner and Werner Lemberg - * Copyright (C) 2006 Behdad Esfahbod - * Copyright (C) 2007,2008,2009 Red Hat, Inc. + * Copyright © 1998-2004 David Turner and Werner Lemberg + * Copyright © 2006 Behdad Esfahbod + * Copyright © 2007,2008,2009 Red Hat, Inc. * - * This is part of HarfBuzz, an OpenType Layout engine library. + * This is part of HarfBuzz, a text shaping library. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this @@ -28,64 +28,72 @@ #define HB_OT_LAYOUT_CC -#include "hb-ot-layout-private.h" +#include "hb-ot-layout-private.hh" #include "hb-ot-layout-gdef-private.hh" #include "hb-ot-layout-gsub-private.hh" #include "hb-ot-layout-gpos-private.hh" +#include "hb-ot-head-private.hh" +#include "hb-ot-maxp-private.hh" #include #include +HB_BEGIN_DECLS -void -_hb_ot_layout_init (hb_face_t *face) + +hb_ot_layout_t * +_hb_ot_layout_create (hb_face_t *face) { - hb_ot_layout_t *layout = &face->ot_layout; + /* TODO Remove this object altogether */ + hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t)); + + layout->gdef_blob = Sanitizer::sanitize (hb_face_reference_table (face, HB_OT_TAG_GDEF)); + layout->gdef = Sanitizer::lock_instance (layout->gdef_blob); + + layout->gsub_blob = Sanitizer::sanitize (hb_face_reference_table (face, HB_OT_TAG_GSUB)); + layout->gsub = Sanitizer::lock_instance (layout->gsub_blob); - layout->gdef_blob = Sanitizer::sanitize (hb_face_get_table (face, HB_OT_TAG_GDEF)); - layout->gdef = &Sanitizer::lock_instance (layout->gdef_blob); + layout->gpos_blob = Sanitizer::sanitize (hb_face_reference_table (face, HB_OT_TAG_GPOS)); + layout->gpos = Sanitizer::lock_instance (layout->gpos_blob); - layout->gsub_blob = Sanitizer::sanitize (hb_face_get_table (face, HB_OT_TAG_GSUB)); - layout->gsub = &Sanitizer::lock_instance (layout->gsub_blob); + layout->head_blob = Sanitizer::sanitize (hb_face_reference_table (face, HB_OT_TAG_head)); + layout->head = Sanitizer::lock_instance (layout->head_blob); - layout->gpos_blob = Sanitizer::sanitize (hb_face_get_table (face, HB_OT_TAG_GPOS)); - layout->gpos = &Sanitizer::lock_instance (layout->gpos_blob); + return layout; } void -_hb_ot_layout_fini (hb_face_t *face) +_hb_ot_layout_destroy (hb_ot_layout_t *layout) { - hb_ot_layout_t *layout = &face->ot_layout; - - hb_blob_unlock (layout->gdef_blob); - hb_blob_unlock (layout->gsub_blob); - hb_blob_unlock (layout->gpos_blob); - hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); + hb_blob_destroy (layout->head_blob); - free (layout->new_gdef.klasses); + free (layout); } -static const GDEF& +static inline const GDEF& _get_gdef (hb_face_t *face) { - return HB_LIKELY (face->ot_layout.gdef) ? *face->ot_layout.gdef : Null(GDEF); + return likely (face->ot_layout && face->ot_layout->gdef) ? *face->ot_layout->gdef : Null(GDEF); } - -static const GSUB& +static inline const GSUB& _get_gsub (hb_face_t *face) { - return HB_LIKELY (face->ot_layout.gsub) ? *face->ot_layout.gsub : Null(GSUB); + return likely (face->ot_layout && face->ot_layout->gsub) ? *face->ot_layout->gsub : Null(GSUB); } - -static const GPOS& +static inline const GPOS& _get_gpos (hb_face_t *face) { - return HB_LIKELY (face->ot_layout.gpos) ? *face->ot_layout.gpos : Null(GPOS); + return likely (face->ot_layout && face->ot_layout->gpos) ? *face->ot_layout->gpos : Null(GPOS); +} +static inline const head& +_get_head (hb_face_t *face) +{ + return likely (face->ot_layout && face->ot_layout->head) ? *face->ot_layout->head : Null(head); } @@ -93,213 +101,90 @@ _get_gpos (hb_face_t *face) * GDEF */ -/* TODO the public class_t is a mess */ - hb_bool_t -hb_ot_layout_has_font_glyph_classes (hb_face_t *face) +hb_ot_layout_has_glyph_classes (hb_face_t *face) { return _get_gdef (face).has_glyph_classes (); } -hb_bool_t -_hb_ot_layout_has_new_glyph_classes (hb_face_t *face) -{ - return face->ot_layout.new_gdef.len > 0; -} - -static unsigned int -_hb_ot_layout_get_glyph_property (hb_face_t *face, - hb_codepoint_t glyph) +unsigned int +_hb_ot_layout_get_glyph_property (hb_face_t *face, + hb_glyph_info_t *info) { - hb_ot_layout_class_t klass; - const GDEF &gdef = _get_gdef (face); - - klass = gdef.get_glyph_class (glyph); - - if (!klass && glyph < face->ot_layout.new_gdef.len) - klass = face->ot_layout.new_gdef.klasses[glyph]; - - switch (klass) { - default: - case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; - case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; - case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; - case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; - case GDEF::MarkGlyph: - klass = gdef.get_mark_attachment_type (glyph); - return HB_OT_LAYOUT_GLYPH_CLASS_MARK + (klass << 8); + if (!info->props_cache()) + { + const GDEF &gdef = _get_gdef (face); + info->props_cache() = gdef.get_glyph_props (info->codepoint); } + + return info->props_cache(); } -hb_bool_t -_hb_ot_layout_check_glyph_property (hb_face_t *face, - hb_internal_glyph_info_t *ginfo, - unsigned int lookup_flags, - unsigned int *property_out) +static hb_bool_t +_hb_ot_layout_match_properties (hb_face_t *face, + hb_codepoint_t codepoint, + unsigned int glyph_props, + unsigned int lookup_props) { - unsigned int property; - - if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN) - ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint); - property = ginfo->gproperty; - if (property_out) - *property_out = property; - /* Not covered, if, for example, glyph class is ligature and - * lookup_flags includes LookupFlags::IgnoreLigatures + * lookup_props includes LookupFlags::IgnoreLigatures */ - if (property & lookup_flags & LookupFlag::IgnoreFlags) + if (glyph_props & lookup_props & LookupFlag::IgnoreFlags) return false; - if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) + if (glyph_props & HB_OT_LAYOUT_GLYPH_CLASS_MARK) { /* If using mark filtering sets, the high short of - * lookup_flags has the set index. + * lookup_props has the set index. */ - if (lookup_flags & LookupFlag::UseMarkFilteringSet) - return _get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint); + if (lookup_props & LookupFlag::UseMarkFilteringSet) + return _get_gdef (face).mark_set_covers (lookup_props >> 16, codepoint); - /* The second byte of lookup_flags has the meaning + /* The second byte of lookup_props has the meaning * "ignore marks of attachment type different than * the attachment type specified." */ - if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType) - return (lookup_flags & LookupFlag::MarkAttachmentType) == (property & LookupFlag::MarkAttachmentType); + if (lookup_props & LookupFlag::MarkAttachmentType && glyph_props & LookupFlag::MarkAttachmentType) + return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType); } return true; } hb_bool_t -_hb_ot_layout_skip_mark (hb_face_t *face, - hb_internal_glyph_info_t *ginfo, - unsigned int lookup_flags, - unsigned int *property_out) +_hb_ot_layout_check_glyph_property (hb_face_t *face, + hb_glyph_info_t *ginfo, + unsigned int lookup_props, + unsigned int *property_out) { unsigned int property; - if (ginfo->gproperty == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN) - ginfo->gproperty = _hb_ot_layout_get_glyph_property (face, ginfo->codepoint); - property = ginfo->gproperty; - if (property_out) - *property_out = property; - - if (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK) - { - /* Skip mark if lookup_flags includes LookupFlags::IgnoreMarks */ - if (lookup_flags & LookupFlag::IgnoreMarks) - return true; - - /* If using mark filtering sets, the high short of lookup_flags has the set index. */ - if (lookup_flags & LookupFlag::UseMarkFilteringSet) - return !_get_gdef (face).mark_set_covers (lookup_flags >> 16, ginfo->codepoint); - - /* The second byte of lookup_flags has the meaning "ignore marks of attachment type - * different than the attachment type specified." */ - if (lookup_flags & LookupFlag::MarkAttachmentType && property & LookupFlag::MarkAttachmentType) - return (lookup_flags & LookupFlag::MarkAttachmentType) != (property & LookupFlag::MarkAttachmentType); - } + property = _hb_ot_layout_get_glyph_property (face, ginfo); + (void) (property_out && (*property_out = property)); - return false; + return _hb_ot_layout_match_properties (face, ginfo->codepoint, property, lookup_props); } -void -_hb_ot_layout_set_glyph_class (hb_face_t *face, - hb_codepoint_t glyph, - hb_ot_layout_glyph_class_t klass) +hb_bool_t +_hb_ot_layout_skip_mark (hb_face_t *face, + hb_glyph_info_t *ginfo, + unsigned int lookup_props, + unsigned int *property_out) { - if (HB_OBJECT_IS_INERT (face)) - return; - - /* TODO optimize this? similar to old harfbuzz code for example */ - - hb_ot_layout_t *layout = &face->ot_layout; - hb_ot_layout_class_t gdef_klass; - unsigned int len = layout->new_gdef.len; - - if (HB_UNLIKELY (glyph > 65535)) - return; - - /* XXX this is not threadsafe */ - if (glyph >= len) { - unsigned int new_len; - unsigned char *new_klasses; - - new_len = len == 0 ? 120 : 2 * len; - while (new_len <= glyph) - new_len *= 2; - - if (new_len > 65536) - new_len = 65536; - new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char)); - - if (HB_UNLIKELY (!new_klasses)) - return; - - memset (new_klasses + len, 0, new_len - len); - - layout->new_gdef.klasses = new_klasses; - layout->new_gdef.len = new_len; - } - - switch (klass) { - default: - case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break; - case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break; - case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break; - case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break; - case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break; - } - - layout->new_gdef.klasses[glyph] = gdef_klass; - return; -} - -void -_hb_ot_layout_set_glyph_property (hb_face_t *face, - hb_codepoint_t glyph, - unsigned int property) -{ _hb_ot_layout_set_glyph_class (face, glyph, (hb_ot_layout_glyph_class_t) (property & 0xff)); } + unsigned int property; + property = _hb_ot_layout_get_glyph_property (face, ginfo); + (void) (property_out && (*property_out = property)); -hb_ot_layout_glyph_class_t -hb_ot_layout_get_glyph_class (hb_face_t *face, - hb_codepoint_t glyph) -{ - return (hb_ot_layout_glyph_class_t) (_hb_ot_layout_get_glyph_property (face, glyph) & 0xff); -} + /* If it's a mark, skip it we don't accept it. */ + if (unlikely (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK)) + return !_hb_ot_layout_match_properties (face, ginfo->codepoint, property, lookup_props); -void -hb_ot_layout_set_glyph_class (hb_face_t *face, - hb_codepoint_t glyph, - hb_ot_layout_glyph_class_t klass) -{ - _hb_ot_layout_set_glyph_class (face, glyph, klass); + /* If not a mark, don't skip. */ + return false; } -void -hb_ot_layout_build_glyph_classes (hb_face_t *face, - uint16_t num_total_glyphs, - hb_codepoint_t *glyphs, - unsigned char *klasses, - uint16_t count) -{ - if (HB_OBJECT_IS_INERT (face)) - return; - - hb_ot_layout_t *layout = &face->ot_layout; - if (HB_UNLIKELY (!count || !glyphs || !klasses)) - return; - - if (layout->new_gdef.len == 0) { - layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char)); - layout->new_gdef.len = count; - } - - for (unsigned int i = 0; i < count; i++) - _hb_ot_layout_set_glyph_class (face, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]); -} unsigned int hb_ot_layout_get_attach_points (hb_face_t *face, @@ -312,17 +197,14 @@ hb_ot_layout_get_attach_points (hb_face_t *face, } unsigned int -hb_ot_layout_get_lig_carets (hb_face_t *face, - hb_font_t *font, - hb_codepoint_t glyph, - unsigned int start_offset, - unsigned int *caret_count /* IN/OUT */, - int *caret_array /* OUT */) +hb_ot_layout_get_ligature_carets (hb_font_t *font, + hb_direction_t direction, + hb_codepoint_t glyph, + unsigned int start_offset, + unsigned int *caret_count /* IN/OUT */, + int *caret_array /* OUT */) { - hb_ot_layout_context_t context; - context.font = font; - context.face = face; - return _get_gdef (face).get_lig_carets (&context, glyph, start_offset, caret_count, caret_array); + return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); } /* @@ -359,7 +241,7 @@ hb_ot_layout_table_find_script (hb_face_t *face, hb_tag_t script_tag, unsigned int *script_index) { - ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); if (g.find_script_index (script_tag, script_index)) @@ -369,6 +251,35 @@ hb_ot_layout_table_find_script (hb_face_t *face, if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) return FALSE; + /* try with 'dflt'; MS site has had typos and many fonts use it now :(. + * including many versions of DejaVu Sans Mono! */ + if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) + return FALSE; + + if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; + return FALSE; +} + +hb_bool_t +hb_ot_layout_table_choose_script (hb_face_t *face, + hb_tag_t table_tag, + const hb_tag_t *script_tags, + unsigned int *script_index) +{ + ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX); + const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + while (*script_tags) + { + if (g.find_script_index (*script_tags, script_index)) + return TRUE; + script_tags++; + } + + /* try finding 'DFLT' */ + if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) + return FALSE; + /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ if (g.find_script_index (HB_OT_TAG_DEFAULT_LANGUAGE, script_index)) return FALSE; @@ -410,7 +321,7 @@ hb_ot_layout_script_find_language (hb_face_t *face, hb_tag_t language_tag, unsigned int *language_index) { - ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); + ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX); const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); if (s.find_lang_sys_index (language_tag, language_index)) @@ -486,7 +397,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face, hb_tag_t feature_tag, unsigned int *feature_index) { - ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + ASSERT_STATIC (Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); @@ -529,16 +440,26 @@ hb_ot_layout_has_substitution (hb_face_t *face) return &_get_gsub (face) != &Null(GSUB); } +void +hb_ot_layout_substitute_start (hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->info[i].var1.u32 = buffer->info[i].var2.u32 = 0; +} + hb_bool_t hb_ot_layout_substitute_lookup (hb_face_t *face, hb_buffer_t *buffer, unsigned int lookup_index, hb_mask_t mask) { - hb_ot_layout_context_t context; - context.font = NULL; - context.face = face; - return _get_gsub (face).substitute_lookup (&context, buffer, lookup_index, mask); + return _get_gsub (face).substitute_lookup (face, buffer, lookup_index, mask); +} + +void +hb_ot_layout_substitute_finish (hb_buffer_t *buffer HB_UNUSED) +{ } @@ -552,15 +473,37 @@ hb_ot_layout_has_positioning (hb_face_t *face) return &_get_gpos (face) != &Null(GPOS); } +void +hb_ot_layout_position_start (hb_buffer_t *buffer) +{ + buffer->clear_positions (); +} + hb_bool_t -hb_ot_layout_position_lookup (hb_face_t *face, - hb_font_t *font, +hb_ot_layout_position_lookup (hb_font_t *font, hb_buffer_t *buffer, unsigned int lookup_index, hb_mask_t mask) { - hb_ot_layout_context_t context; - context.font = font; - context.face = face; - return _get_gpos (face).position_lookup (&context, buffer, lookup_index, mask); + return _get_gpos (font->face).position_lookup (font, buffer, lookup_index, mask); } + +void +hb_ot_layout_position_finish (hb_buffer_t *buffer) +{ + GPOS::position_finish (buffer); +} + + +/* + * head + */ + +unsigned int +_hb_ot_layout_get_upem (hb_face_t *face) +{ + return _get_head (face).get_upem (); +} + + +HB_END_DECLS