hb_tag_t getIndFeature(XeTeXFont font, hb_tag_t script, hb_tag_t language, unsigned int index) { hb_tag_t rval = 0; hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); for (int i = 0; i < 2; ++i) { unsigned int scriptIndex, langIndex = 0; hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { unsigned int featCount = hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); hb_tag_t* featList = (hb_tag_t*) xcalloc(featCount, sizeof(hb_tag_t*)); hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, &featCount, featList); if (index < featCount) { rval = featList[index]; break; } index -= featCount; } } } return rval; }
unsigned int countFeatures(XeTeXFont font, hb_tag_t script, hb_tag_t language) { unsigned int rval = 0; hb_face_t* face = hb_font_get_face(((XeTeXFontInst*)font)->getHbFont()); for (int i = 0; i < 2; ++i) { unsigned int scriptIndex, langIndex = 0; hb_tag_t tableTag = i == 0 ? HB_OT_TAG_GSUB : HB_OT_TAG_GPOS; if (hb_ot_layout_table_find_script(face, tableTag, script, &scriptIndex)) { if (hb_ot_layout_script_find_language(face, tableTag, scriptIndex, language, &langIndex) || language == 0) { rval += hb_ot_layout_language_get_feature_tags(face, tableTag, scriptIndex, langIndex, 0, NULL, NULL); } } } return rval; }
/** * hb_ot_layout_collect_lookups: * * Since: 0.9.8 **/ void hb_ot_layout_collect_lookups (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */) { if (!scripts) { /* All scripts */ unsigned int count = hb_ot_layout_table_get_script_tags (face, table_tag, 0, NULL, NULL); for (unsigned int script_index = 0; script_index < count; script_index++) _hb_ot_layout_collect_lookups_languages (face, table_tag, script_index, languages, features, lookup_indexes); } else { for (; *scripts; scripts++) { unsigned int script_index; if (hb_ot_layout_table_find_script (face, table_tag, *scripts, &script_index)) _hb_ot_layout_collect_lookups_languages (face, table_tag, script_index, languages, features, lookup_indexes); } } }
bool OpenTypeCapsSupport::supportsOpenTypeFeature( hb_script_t script, uint32_t tag) const { hb_face_t* face = hb_font_get_face(m_harfBuzzFace->getScaledFont()); ASSERT(face); ASSERT((tag == HB_TAG('s', 'm', 'c', 'p') || tag == HB_TAG('c', '2', 's', 'c') || tag == HB_TAG('p', 'c', 'a', 'p') || tag == HB_TAG('c', '2', 'p', 'c') || tag == HB_TAG('s', 'u', 'p', 's') || tag == HB_TAG('s', 'u', 'b', 's') || tag == HB_TAG('t', 'i', 't', 'l') || tag == HB_TAG('u', 'n', 'i', 'c') || tag == HB_TAG('v', 'e', 'r', 't'))); bool result = false; if (!hb_ot_layout_has_substitution(face)) return false; // Get the OpenType tag(s) that match this script code const size_t kMaxScriptTags = 4; hb_tag_t scriptTags[kMaxScriptTags] = { HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE, HB_TAG_NONE }; hb_ot_tags_from_script(static_cast<hb_script_t>(script), &scriptTags[0], &scriptTags[1]); // Replace the first remaining NONE with DEFAULT for (size_t i = 0; i < kMaxScriptTags; ++i) { if (scriptTags[i] == HB_TAG_NONE) { scriptTags[i] = HB_OT_TAG_DEFAULT_SCRIPT; break; } } // Now check for 'smcp' under the first of those scripts that is present const hb_tag_t kGSUB = HB_TAG('G', 'S', 'U', 'B'); for (size_t j = 0; j < kMaxScriptTags; ++j) { if (scriptTags[j] == HB_TAG_NONE) break; unsigned scriptIndex; if (hb_ot_layout_table_find_script(face, kGSUB, scriptTags[j], &scriptIndex)) { if (hb_ot_layout_language_find_feature(face, kGSUB, scriptIndex, HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, tag, nullptr)) { result = true; } break; } } return result; }