117 QMap<QString, KoOpenTypeFeatureInfo>
featureInfo = previousFeatureInfo;
119 hb_tag_t table = gpos? HB_OT_TAG_GPOS: HB_OT_TAG_GSUB;
120 uint targetLanguageIndex = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
123 Q_FOREACH(
const QString locale, locales) {
124 QByteArray l(locale.split(
"_").join(
"-").toLatin1());
125 localeTags.append(hb_language_from_string(l.data(), l.size()));
128 hb_language_t languageTag = lang.isEmpty()? HB_LANGUAGE_INVALID: hb_language_from_string(lang.data(), lang.size());
129 uint scriptCount = hb_ot_layout_table_get_script_tags(hbFace.
data(), table, 0,
nullptr,
nullptr);
132 for (
uint script = 0; script < scriptCount; script++) {
133 uint scriptCount = 1;
136 hb_ot_layout_table_get_script_tags(hbFace.
data(), table, script, &scriptCount, &scriptTag);
137 if (!hb_ot_layout_table_select_script(hbFace.
data(), table, 1, &scriptTag, &scriptIndex, &scriptTag)) {
140 scriptIndices.append(scriptIndex);
142 uint languageCount = hb_ot_layout_script_get_language_tags(hbFace.
data(), table, scriptIndex, 0,
nullptr,
nullptr);
144 bool foundLanguage =
false;
146 for(
uint j = 0; j < languageCount; j++) {
149 hb_ot_layout_script_get_language_tags(hbFace.
data(), table, scriptIndex, j, &count, &langTag);
150 if (count < 1)
continue;
151 if (hb_ot_tag_to_language(langTag) == languageTag) {
153 if (hb_ot_layout_script_select_language(hbFace.
data(), table, scriptIndex, count, &langTag, &languageIndex)) {
154 targetLanguageIndex = languageIndex;
155 foundLanguage =
true;
160 if (foundLanguage)
break;
163 QHash<quint32, int> glyphToCodepoint;
164 for (
int i = 0; i<
charMap.size(); i++) {
165 glyphToCodepoint.insert(
charMap.at(i).glyphIndex, i);
168 for (
auto scriptIt = scriptIndices.begin(); scriptIt != scriptIndices.end(); scriptIt++) {
169 uint targetScriptIndex = *scriptIt;
170 uint featureCount = hb_ot_layout_language_get_feature_tags(hbFace.
data(),
174 0,
nullptr,
nullptr);
175 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScriptIndex,
177 0,
nullptr,
nullptr);
178 for(
uint k = 0; k < featureCount; k++) {
181 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScriptIndex,
183 k, &count, &features);
184 if (count < 1)
continue;
185 tags.append(features);
193 for (
auto tagIt = tags.begin(); tagIt != tags.end(); tagIt++) {
195 hb_tag_to_string(*tagIt, c);
196 const QByteArray tagName(c, 4);
200 bool found = hb_ot_layout_language_find_feature (hbFace.
data(), table,
206 if (!found || featureIndicesProcessed.contains(featureIndex)) {
209 featureIndicesProcessed.append(featureIndex);
213 hb_ot_name_id_t labelId = HB_OT_NAME_ID_INVALID;
214 hb_ot_name_id_t toolTipId = HB_OT_NAME_ID_INVALID;
215 hb_ot_name_id_t sampleId = HB_OT_NAME_ID_INVALID;
216 uint namedParameters;
217 hb_ot_name_id_t firstParamId = HB_OT_NAME_ID_INVALID;
219 if (hb_ot_layout_feature_get_name_ids(hbFace.
data(), table, featureIndex, &labelId, &toolTipId, &sampleId, &namedParameters, &firstParamId)) {
221 if (firstParamId != HB_OT_NAME_ID_INVALID) {
222 for (
uint i = 0; i < namedParameters; i++) {
223 nameIds += firstParamId + i;
227 for(
auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
228 if (*nameId == HB_OT_NAME_ID_INVALID) {
233 if (*nameId == sampleId) {
234 testLang.append(languageTag);
236 testLang = localeTags;
238 testLang.append(HB_LANGUAGE_INVALID);
239 for (
auto tag = testLang.begin(); tag != testLang.end(); tag++) {
240 length = hb_ot_name_get_utf8(hbFace.
data(), *nameId, *tag,
nullptr,
nullptr);
247 std::vector<char> buff(
length);
248 hb_ot_name_get_utf8(hbFace.
data(), *nameId, languageTag, &
length, buff.data());
250 const QString nameString = QString::fromUtf8(buff.data(),
length);
251 if (*nameId == labelId) {
252 info.
name = nameString;
253 }
else if (*nameId == toolTipId) {
255 }
else if (*nameId == sampleId) {
271 int lookupCount = hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
276 for (
int i = 0; i < lookupCount; ++i) {
278 uint lookUpIndex = 0;
279 hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
284 if (maxCount < 1 || lookUpsProcessed.contains(lookUpIndex)) {
297 hb_ot_layout_lookup_collect_glyphs (hbFace.
data(), table,
302 glyphsOutput.
data() );
308 hb_codepoint_t currentGlyph = HB_SET_VALUE_INVALID;
309 while(hb_set_next(glyphsInput.
data(), ¤tGlyph)) {
310 if (!glyphToCodepoint.contains(currentGlyph))
continue;
311 const int codePointLocation = glyphToCodepoint.value(currentGlyph);
313 gci.
ucs = codePointInfo.
ucs;
314 bool addSample =
false;
316 uint alt_count = hb_ot_layout_lookup_get_glyph_alternates (hbFace.
data(),
317 lookUpIndex, currentGlyph,
323 for(
uint j = 1; j < alt_count; ++j) {
327 if (addToGlyphs && !addSample) {
336 charMap[codePointLocation] = codePointInfo;
337 if (samples.size() < 6 && addSample) {
338 samples.append(QString::fromUcs4(&gci.
ucs, 1));
340 if (samples.size() >= 6 && samplesOnly) {
345 lookUpsProcessed.append(lookUpIndex);
346 if (info.
sample.isEmpty() && !samples.isEmpty()) {
347 info.
sample = samples.join(
" ");