static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face) { static const unsigned maxCount = 32; unsigned scriptCount = maxCount; hb_tag_t scriptTags[maxCount]; hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags); for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) { unsigned languageCount = maxCount; hb_tag_t languageTags[maxCount]; hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags); for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) { unsigned featureIndex; if (hb_ot_layout_language_find_feature( face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzFace::vertTag, &featureIndex) || hb_ot_layout_language_find_feature( face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzFace::vrt2Tag, &featureIndex)) return hb_ot_tag_to_script(scriptTags[scriptIndex]); } } return HB_SCRIPT_INVALID; }
static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face) { static const unsigned maxCount = 32; unsigned scriptCount = maxCount; hb_tag_t scriptTags[maxCount]; hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags); for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) { unsigned languageCount = maxCount; hb_tag_t languageTags[maxCount]; hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags); unsigned featureIndex; for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) { if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzFace::vertTag, &featureIndex)) return hb_ot_tag_to_script(scriptTags[scriptIndex]); } // Try DefaultLangSys if all LangSys failed. if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, HarfBuzzFace::vertTag, &featureIndex)) return hb_ot_tag_to_script(scriptTags[scriptIndex]); } return HB_SCRIPT_INVALID; }
/** * pango_ot_tag_to_script: * @script_tag: A #PangoOTTag OpenType script tag * * Finds the #PangoScript corresponding to @script_tag. * * The 'DFLT' script tag is mapped to %PANGO_SCRIPT_COMMON. * * Note that an OpenType script tag may correspond to multiple * #PangoScript values. In such cases, the #PangoScript value * with the smallest value is returned. * In particular, %PANGO_SCRIPT_HIRAGANA * and %PANGO_SCRIPT_KATAKANA both map to the OT tag 'kana'. * This function will return %PANGO_SCRIPT_HIRAGANA for * 'kana'. * * Return value: #PangoScript corresponding to @script_tag or * %PANGO_SCRIPT_UNKNOWN if none found. * * Since: 1.18 **/ PangoScript pango_ot_tag_to_script (PangoOTTag script_tag) { return (PangoScript) hb_glib_script_from_script (hb_ot_tag_to_script ((hb_tag_t) script_tag)); }
int layoutChars(XeTeXLayoutEngine engine, uint16_t chars[], int32_t offset, int32_t count, int32_t max, bool rightToLeft) { bool res; hb_script_t script = HB_SCRIPT_INVALID; hb_direction_t direction = HB_DIRECTION_LTR; hb_segment_properties_t segment_props; hb_shape_plan_t *shape_plan; hb_font_t* hbFont = engine->font->getHbFont(); hb_face_t* hbFace = hb_font_get_face(hbFont); if (engine->font->getLayoutDirVertical()) direction = HB_DIRECTION_TTB; else if (rightToLeft) direction = HB_DIRECTION_RTL; script = hb_ot_tag_to_script (engine->script); if (hbUnicodeFuncs == NULL) hbUnicodeFuncs = _get_unicode_funcs(); hb_buffer_reset(engine->hbBuffer); hb_buffer_set_unicode_funcs(engine->hbBuffer, hbUnicodeFuncs); hb_buffer_add_utf16(engine->hbBuffer, chars, max, offset, count); hb_buffer_set_direction(engine->hbBuffer, direction); hb_buffer_set_script(engine->hbBuffer, script); hb_buffer_set_language(engine->hbBuffer, engine->language); hb_buffer_guess_segment_properties(engine->hbBuffer); hb_buffer_get_segment_properties(engine->hbBuffer, &segment_props); if (engine->ShaperList == NULL) { // HarfBuzz gives graphite2 shaper a priority, so that for hybrid // Graphite/OpenType fonts, Graphite will be used. However, pre-0.9999 // XeTeX preferred OpenType over Graphite, so we are doing the same // here for sake of backward compatibility. engine->ShaperList = (char**) xcalloc(4, sizeof(char*)); engine->ShaperList[0] = (char*) "ot"; engine->ShaperList[1] = (char*) "graphite2"; engine->ShaperList[2] = (char*) "fallback"; engine->ShaperList[3] = NULL; } shape_plan = hb_shape_plan_create_cached(hbFace, &segment_props, engine->features, engine->nFeatures, engine->ShaperList); res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); if (res) { engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); } else { // all selected shapers failed, retrying with default // we don't use _cached here as the cached plain will always fail. hb_shape_plan_destroy(shape_plan); shape_plan = hb_shape_plan_create(hbFace, &segment_props, engine->features, engine->nFeatures, NULL); res = hb_shape_plan_execute(shape_plan, hbFont, engine->hbBuffer, engine->features, engine->nFeatures); if (res) { engine->shaper = strdup(hb_shape_plan_get_shaper(shape_plan)); hb_buffer_set_content_type(engine->hbBuffer, HB_BUFFER_CONTENT_TYPE_GLYPHS); } else { fprintf(stderr, "\nERROR: all shapers failed\n"); exit(3); } } hb_shape_plan_destroy(shape_plan); int glyphCount = hb_buffer_get_length(engine->hbBuffer); #ifdef DEBUG char buf[1024]; unsigned int consumed; printf ("shaper: %s\n", engine->shaper); hb_buffer_serialize_flags_t flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT; hb_buffer_serialize_format_t format = HB_BUFFER_SERIALIZE_FORMAT_JSON; hb_buffer_serialize_glyphs (engine->hbBuffer, 0, glyphCount, buf, sizeof(buf), &consumed, hbFont, format, flags); if (consumed) printf ("buffer glyphs: %s\n", buf); #endif return glyphCount; }