119 QMap<QString, KoOpenTypeFeatureInfo>
featureInfo = previousFeatureInfo;
121 hb_tag_t table = gpos? HB_OT_TAG_GPOS: HB_OT_TAG_GSUB;
122 uint targetLanguageIndex = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
125 Q_FOREACH(
const QString locale, locales) {
126 QByteArray l(locale.split(
"_").join(
"-").toLatin1());
127 localeTags.append(hb_language_from_string(l.data(), l.size()));
130 hb_language_t languageTag = lang.isEmpty()? HB_LANGUAGE_INVALID: hb_language_from_string(lang.data(), lang.size());
131 uint scriptCount = hb_ot_layout_table_get_script_tags(hbFace.
data(), table, 0,
nullptr,
nullptr);
134 for (
uint script = 0; script < scriptCount; script++) {
135 uint scriptCount = 1;
138 hb_ot_layout_table_get_script_tags(hbFace.
data(), table, script, &scriptCount, &scriptTag);
139 if (!hb_ot_layout_table_select_script(hbFace.
data(), table, 1, &scriptTag, &scriptIndex, &scriptTag)) {
142 scriptIndices.append(scriptIndex);
144 uint languageCount = hb_ot_layout_script_get_language_tags(hbFace.
data(), table, scriptIndex, 0,
nullptr,
nullptr);
146 bool foundLanguage =
false;
148 for(
uint j = 0; j < languageCount; j++) {
151 hb_ot_layout_script_get_language_tags(hbFace.
data(), table, scriptIndex, j, &count, &langTag);
152 if (count < 1)
continue;
153 if (hb_ot_tag_to_language(langTag) == languageTag) {
155 if (hb_ot_layout_script_select_language(hbFace.
data(), table, scriptIndex, count, &langTag, &languageIndex)) {
156 targetLanguageIndex = languageIndex;
157 foundLanguage =
true;
162 if (foundLanguage)
break;
165 QHash<quint32, int> glyphToCodepoint;
166 for (
int i = 0; i<
charMap.size(); i++) {
167 glyphToCodepoint.insert(
charMap.at(i).glyphIndex, i);
170 for (
auto scriptIt = scriptIndices.begin(); scriptIt != scriptIndices.end(); scriptIt++) {
171 uint targetScriptIndex = *scriptIt;
172 uint featureCount = hb_ot_layout_language_get_feature_tags(hbFace.
data(),
176 0,
nullptr,
nullptr);
177 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScriptIndex,
179 0,
nullptr,
nullptr);
180 for(
uint k = 0; k < featureCount; k++) {
183 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScriptIndex,
185 k, &count, &features);
186 if (count < 1)
continue;
187 tags.append(features);
192 for (
auto tagIt = tags.begin(); tagIt != tags.end(); tagIt++) {
194 hb_tag_to_string(*tagIt, c);
195 const QByteArray tagName(c, 4);
199 bool found = hb_ot_layout_language_find_feature (hbFace.
data(), table,
205 if (!found || featureIndicesProcessed.contains(featureIndex)) {
208 featureIndicesProcessed.append(featureIndex);
212 hb_ot_name_id_t labelId = HB_OT_NAME_ID_INVALID;
213 hb_ot_name_id_t toolTipId = HB_OT_NAME_ID_INVALID;
214 hb_ot_name_id_t sampleId = HB_OT_NAME_ID_INVALID;
215 uint namedParameters;
216 hb_ot_name_id_t firstParamId = HB_OT_NAME_ID_INVALID;
218 if (hb_ot_layout_feature_get_name_ids(hbFace.
data(), table, featureIndex, &labelId, &toolTipId, &sampleId, &namedParameters, &firstParamId)) {
220 if (firstParamId != HB_OT_NAME_ID_INVALID) {
221 for (
uint i = 0; i < namedParameters; i++) {
222 nameIds += firstParamId + i;
226 for(
auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
227 if (*nameId == HB_OT_NAME_ID_INVALID) {
232 if (*nameId == sampleId) {
233 testLang.append(languageTag);
235 testLang = localeTags;
237 testLang.append(HB_LANGUAGE_INVALID);
238 for (
auto tag = testLang.begin(); tag != testLang.end(); tag++) {
239 length = hb_ot_name_get_utf8(hbFace.
data(), *nameId, *tag,
nullptr,
nullptr);
246 std::vector<char> buff(
length);
247 hb_ot_name_get_utf8(hbFace.
data(), *nameId, languageTag, &
length, buff.data());
249 const QString nameString = QString::fromUtf8(buff.data(),
length);
250 if (*nameId == labelId) {
251 info.
name = nameString;
252 }
else if (*nameId == toolTipId) {
254 }
else if (*nameId == sampleId) {
270 int lookupCount = hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
275 for (
int i = 0; i < lookupCount; ++i) {
277 uint lookUpIndex = 0;
278 hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
283 if (maxCount < 1 || lookUpsProcessed.contains(lookUpIndex)) {
296 hb_ot_layout_lookup_collect_glyphs (hbFace.
data(), table,
301 glyphsOutput.
data() );
307 hb_codepoint_t currentGlyph = HB_SET_VALUE_INVALID;
308 while(hb_set_next(glyphsInput.
data(), ¤tGlyph)) {
309 if (!glyphToCodepoint.contains(currentGlyph))
continue;
310 const int codePointLocation = glyphToCodepoint.value(currentGlyph);
312 gci.
ucs = codePointInfo.
ucs;
313 bool addSample =
false;
315 uint alt_count = hb_ot_layout_lookup_get_glyph_alternates (hbFace.
data(),
316 lookUpIndex, currentGlyph,
322 for(
uint j = 1; j < alt_count; ++j) {
326 if (addToGlyphs && !addSample) {
335 charMap[codePointLocation] = codePointInfo;
336 if (samples.size() < 6 && addSample) {
337 samples.append(QString::fromUcs4(&gci.
ucs, 1));
339 if (samples.size() >= 6 && samplesOnly) {
344 lookUpsProcessed.append(lookUpIndex);
345 if (info.
sample.isEmpty() && !samples.isEmpty()) {
346 info.
sample = samples.join(
" ");