static int substituteWithVerticalGlyphs(const SimpleFontData* fontData, uint16_t* glyphs, unsigned bufferLength) { HB_FaceRec_* hbFace = fontData->platformData().harfbuzzFace()->face(); if (!hbFace->gsub) { // if there is no GSUB table, treat it as not covered return 0Xffff; } HB_Buffer buffer; hb_buffer_new(&buffer); for (unsigned i = 0; i < bufferLength; ++i) hb_buffer_add_glyph(buffer, glyphs[i], 0, i); HB_UShort scriptIndex; HB_UShort featureIndex; HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'e', 'r', 't'), scriptIndex, 0xffff, &featureIndex); HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'r', 't', '2'), scriptIndex, 0xffff, &featureIndex); HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1); int error = HB_GSUB_Apply_String(hbFace->gsub, buffer); if (!error) { for (unsigned i = 0; i < bufferLength; ++i) glyphs[i] = static_cast<Glyph>(buffer->out_string[i].gindex); } return error; }
static void setupFontFeatures(const FontFeatureSettings* settings, HB_FaceRec_* hbFace) { if (!settings) return; if (hbFace->gsub) HB_GSUB_Clear_Features(hbFace->gsub); if (hbFace->gpos) HB_GPOS_Clear_Features(hbFace->gpos); HB_UShort scriptIndex = 0; HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex); size_t numFeatures = settings->size(); for (size_t i = 0; i < numFeatures; ++i) { if (!settings->at(i).value()) continue; HB_UShort featureIndex = 0; const UChar* tag = settings->at(i).tag().characters(); HB_UInt feature = HB_MAKE_TAG(tag[0], tag[1], tag[2], tag[3]); if (hbFace->gsub && HB_GSUB_Select_Feature(hbFace->gsub, feature, scriptIndex, 0xffff, &featureIndex) == HB_Err_Ok) HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, settings->at(i).value()); else if (hbFace->gpos && HB_GPOS_Select_Feature(hbFace->gpos, feature, scriptIndex, 0xffff, &featureIndex) == HB_Err_Ok) HB_GPOS_Add_Feature(hbFace->gpos, featureIndex, settings->at(i).value()); } }