X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fhb-ot-layout.cc;h=a49f339cc085f4cc7fb4b12249bcf37c54015671;hb=18c42850c9327ab4479ff150660a76d4ff6f3e9c;hp=eef768d186d7ad26190728cd9edbcdb0fe267200;hpb=70e0f2a75ec1559f2f70ada837ce4bc4baca49e3;p=framework%2Fuifw%2Fharfbuzz.git diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index eef768d..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); - /* XXX sanitize */ + 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 = hb_face_get_table (face, HB_OT_TAG_GDEF); - layout->gdef = &GDEF::get_for_data (hb_blob_lock (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 = hb_face_get_table (face, HB_OT_TAG_GSUB); - layout->gsub = &GSUB::get_for_data (hb_blob_lock (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 = hb_face_get_table (face, HB_OT_TAG_GPOS); - layout->gpos = &GPOS::get_for_data (hb_blob_lock (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); } -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,233 +101,110 @@ _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_INTERNAL 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: - /* TODO old harfbuzz doesn't always parse mark attachments as it says it was - * introduced without a version bump, so it may not be safe */ - 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_INTERNAL 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) + 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_INTERNAL 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_bool_t +_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; + property = _hb_ot_layout_get_glyph_property (face, ginfo); + (void) (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); - } - - return false; + return _hb_ot_layout_match_properties (face, ginfo->codepoint, property, lookup_props); } -HB_INTERNAL 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; - int len = layout->new_gdef.len; - - if (HB_UNLIKELY (glyph > 65535)) - return; - - /* XXX this is not threadsafe */ - if (glyph >= len) { - int new_len; - unsigned char *new_klasses; - - new_len = len == 0 ? 120 : 2 * len; - if (new_len > 65535) - new_len = 65535; - 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; -} - -HB_INTERNAL 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]); -} -hb_bool_t +unsigned int hb_ot_layout_get_attach_points (hb_face_t *face, hb_codepoint_t glyph, + unsigned int start_offset, unsigned int *point_count /* IN/OUT */, unsigned int *point_array /* OUT */) { - return _get_gdef (face).get_attach_points (glyph, point_count, point_array); + return _get_gdef (face).get_attach_points (glyph, start_offset, point_count, point_array); } -hb_bool_t -hb_ot_layout_get_lig_carets (hb_face_t *face, - hb_font_t *font, - hb_codepoint_t glyph, - unsigned int *caret_count /* IN/OUT */, - int *caret_array /* OUT */) +unsigned int +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, caret_count, caret_array); + return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array); } /* @@ -339,22 +224,15 @@ get_gsubgpos_table (hb_face_t *face, unsigned int -hb_ot_layout_table_get_script_count (hb_face_t *face, - hb_tag_t table_tag) -{ - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - - return g.get_script_count (); -} - -hb_tag_t -hb_ot_layout_table_get_script_tag (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index) +hb_ot_layout_table_get_script_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *script_count /* IN/OUT */, + hb_tag_t *script_tags /* OUT */) { const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - return g.get_script_tag (script_index); + return g.get_script_tags (start_offset, script_count, script_tags); } hb_bool_t @@ -363,88 +241,77 @@ 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)) return TRUE; /* try finding 'DFLT' */ - if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT, script_index)) + 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_LAYOUT_TAG_DEFAULT_LANGUAGE, script_index)) + /* 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; } -unsigned int -hb_ot_layout_table_get_feature_count (hb_face_t *face, - hb_tag_t table_tag) -{ - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - - return g.get_feature_count (); -} - -hb_tag_t -hb_ot_layout_table_get_feature_tag (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index) +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); - return g.get_feature_tag (feature_index); -} + while (*script_tags) + { + if (g.find_script_index (*script_tags, script_index)) + return TRUE; + script_tags++; + } -hb_bool_t -hb_ot_layout_table_find_feature (hb_face_t *face, - hb_tag_t table_tag, - hb_tag_t feature_tag, - unsigned int *feature_index) -{ - ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + /* try finding 'DFLT' */ + if (g.find_script_index (HB_OT_TAG_DEFAULT_SCRIPT, script_index)) + return FALSE; - if (g.find_feature_index (feature_tag, feature_index)) - return TRUE; + /* 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; - if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; + if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX; return FALSE; } unsigned int -hb_ot_layout_table_get_lookup_count (hb_face_t *face, - hb_tag_t table_tag) +hb_ot_layout_table_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */) { const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - return g.get_lookup_count (); + return g.get_feature_tags (start_offset, feature_count, feature_tags); } unsigned int -hb_ot_layout_script_get_language_count (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index) -{ - const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); - - return s.get_lang_sys_count (); -} - -hb_tag_t -hb_ot_layout_script_get_language_tag (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index) +hb_ot_layout_script_get_language_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int start_offset, + unsigned int *language_count /* IN/OUT */, + hb_tag_t *language_tags /* OUT */) { const Script &s = get_gsubgpos_table (face, table_tag).get_script (script_index); - return s.get_lang_sys_tag (language_index); + return s.get_lang_sys_tags (start_offset, language_count, language_tags); } hb_bool_t @@ -454,14 +321,14 @@ 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)) return TRUE; /* try with 'dflt'; MS site has had typos and many fonts use it now :( */ - if (s.find_lang_sys_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, language_index)) + if (s.find_lang_sys_index (HB_OT_TAG_DEFAULT_LANGUAGE, language_index)) return FALSE; if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX; @@ -483,41 +350,42 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, } unsigned int -hb_ot_layout_language_get_feature_count (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index) +hb_ot_layout_language_get_feature_indexes (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + unsigned int *feature_indexes /* OUT */) { - const LangSys &l = get_gsubgpos_table (face, table_tag).get_script (script_index).get_lang_sys (language_index); + const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); - return l.get_feature_count (); + return l.get_feature_indexes (start_offset, feature_count, feature_indexes); } unsigned int -hb_ot_layout_language_get_feature_index (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index, - unsigned int num_feature) +hb_ot_layout_language_get_feature_tags (hb_face_t *face, + hb_tag_t table_tag, + unsigned int script_index, + unsigned int language_index, + unsigned int start_offset, + unsigned int *feature_count /* IN/OUT */, + hb_tag_t *feature_tags /* OUT */) { const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); - return l.get_feature_index (num_feature); -} + ASSERT_STATIC (sizeof (unsigned int) == sizeof (hb_tag_t)); + unsigned int ret = l.get_feature_indexes (start_offset, feature_count, (unsigned int *) feature_tags); -hb_tag_t -hb_ot_layout_language_get_feature_tag (hb_face_t *face, - hb_tag_t table_tag, - unsigned int script_index, - unsigned int language_index, - unsigned int num_feature) -{ - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const LangSys &l = g.get_script (script_index).get_lang_sys (language_index); - unsigned int feature_index = l.get_feature_index (num_feature); + if (feature_tags) { + unsigned int count = *feature_count; + for (unsigned int i = 0; i < count; i++) + feature_tags[i] = g.get_feature_tag ((unsigned int) feature_tags[i]); + } - return g.get_feature_tag (feature_index); + return ret; } @@ -529,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); @@ -548,27 +416,19 @@ hb_ot_layout_language_find_feature (hb_face_t *face, } unsigned int -hb_ot_layout_feature_get_lookup_count (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index) +hb_ot_layout_feature_get_lookup_indexes (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */) { const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); const Feature &f = g.get_feature (feature_index); - return f.get_lookup_count (); + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); } -unsigned int -hb_ot_layout_feature_get_lookup_index (hb_face_t *face, - hb_tag_t table_tag, - unsigned int feature_index, - unsigned int num_lookup) -{ - const GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const Feature &f = g.get_feature (feature_index); - - return f.get_lookup_index (num_lookup); -} /* * GSUB @@ -580,18 +440,29 @@ 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_ot_layout_feature_mask_t mask) +hb_ot_layout_substitute_lookup (hb_face_t *face, + hb_buffer_t *buffer, + unsigned int lookup_index, + hb_mask_t mask) +{ + return _get_gsub (face).substitute_lookup (face, buffer, lookup_index, mask); +} + +void +hb_ot_layout_substitute_finish (hb_buffer_t *buffer HB_UNUSED) { - hb_ot_layout_context_t context; - context.font = NULL; - context.face = face; - return _get_gsub (face).substitute_lookup (&context, buffer, lookup_index, mask); } + /* * GPOS */ @@ -602,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_buffer_t *buffer, - unsigned int lookup_index, - hb_ot_layout_feature_mask_t mask) +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