80 QMap<uint, QVector<GlyphInfo>> vsData;
83 hb_face_collect_variation_selectors(hbFace.
data(), variationSelectors.
data());
85 hb_codepoint_t hbVSPoint = HB_SET_VALUE_INVALID;
87 while(hb_set_next(variationSelectors.
data(), &hbVSPoint)) {
90 hb_face_collect_variation_unicodes(hbFace.
data(), hbVSPoint, unicodes.
data());
91 hb_codepoint_t hbCodePointPoint = HB_SET_VALUE_INVALID;
92 while(hb_set_next(unicodes.
data(), &hbCodePointPoint)) {
96 gci.
baseString = QString::fromUcs4(&hbVSPoint, 1);
98 vsData.insert(hbCodePointPoint, glyphs);
107 QMap<QString, KoOpenTypeFeatureInfo>
featureInfo = previousFeatureInfo;
109 hb_tag_t table = gpos? HB_OT_TAG_GPOS: HB_OT_TAG_GSUB;
110 uint targetLanguage = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
111 uint targetScript = 0;
114 Q_FOREACH(
const QString locale, locales) {
115 QLatin1String l(locale.split(
"_").join(
"-").toLatin1());
116 localeTags.append(hb_language_from_string(l.data(), l.size()));
119 hb_language_t languageTag = lang.isEmpty()? HB_LANGUAGE_INVALID: hb_language_from_string(lang.data(), lang.size());
120 uint scriptCount = hb_ot_layout_table_get_script_tags(hbFace.
data(), table, 0,
nullptr,
nullptr);
122 for (
uint script = 0; script < scriptCount; script++) {
123 uint languageCount = hb_ot_layout_script_get_language_tags(hbFace.
data(), table, script, 0,
nullptr,
nullptr);
125 for(
uint j = 0; j < languageCount; j++) {
128 hb_ot_layout_script_get_language_tags(hbFace.
data(), table, script, j, &count, &langTag);
129 if (count < 1)
continue;
130 if (hb_ot_tag_to_language(langTag) == languageTag) {
132 targetScript = script;
138 uint featureCount = hb_ot_layout_language_get_feature_tags(hbFace.
data(),
142 0,
nullptr,
nullptr);
143 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScript,
145 0,
nullptr,
nullptr);
146 for(
uint k = 0; k < featureCount; k++) {
149 hb_ot_layout_language_get_feature_tags(hbFace.
data(), table, targetScript,
151 k, &count, &features);
152 if (count < 1)
continue;
153 tags.append(features);
156 QHash<quint32, int> glyphToCodepoint;
157 for (
int i = 0; i<
charMap.size(); i++) {
158 glyphToCodepoint.insert(
charMap.at(i).glyphIndex, i);
162 for (
auto it = tags.begin(); it != tags.end(); it++) {
164 hb_tag_to_string(*it, c);
165 const QLatin1String tagName(c, 4);
169 bool found = hb_ot_layout_language_find_feature (hbFace.
data(), table,
179 hb_ot_name_id_t labelId = HB_OT_NAME_ID_INVALID;
180 hb_ot_name_id_t toolTipId = HB_OT_NAME_ID_INVALID;
181 hb_ot_name_id_t sampleId = HB_OT_NAME_ID_INVALID;
182 uint namedParameters;
183 hb_ot_name_id_t firstParamId = HB_OT_NAME_ID_INVALID;
185 if (hb_ot_layout_feature_get_name_ids(hbFace.
data(), table, featureIndex, &labelId, &toolTipId, &sampleId, &namedParameters, &firstParamId)) {
187 if (firstParamId != HB_OT_NAME_ID_INVALID) {
188 for (
uint i = 0; i < namedParameters; i++) {
189 nameIds += firstParamId + i;
193 for(
auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
194 if (*nameId == HB_OT_NAME_ID_INVALID) {
199 if (*nameId == sampleId) {
200 testLang.append(languageTag);
202 testLang = localeTags;
204 testLang.append(HB_LANGUAGE_INVALID);
205 for (
auto tag = testLang.begin(); tag != testLang.end(); tag++) {
206 length = hb_ot_name_get_utf8(hbFace.
data(), *nameId, *tag,
nullptr,
nullptr);
213 std::vector<char> buff(
length);
214 hb_ot_name_get_utf8(hbFace.
data(), *nameId, languageTag, &
length, buff.data());
216 const QString nameString = QString::fromUtf8(buff.data(),
length);
217 if (*nameId == labelId) {
218 info.
name = nameString;
219 }
else if (*nameId == toolTipId) {
221 }
else if (*nameId == sampleId) {
236 int lookupCount = hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
241 for (
int i = 0; i < lookupCount; ++i) {
243 uint lookUpIndex = 0;
244 hb_ot_layout_feature_get_lookups (hbFace.
data(), table,
249 if (maxCount < 1 || lookUpsProcessed.contains(lookUpIndex)) {
262 hb_ot_layout_lookup_collect_glyphs (hbFace.
data(), table,
267 glyphsOutput.
data() );
273 hb_codepoint_t currentGlyph = HB_SET_VALUE_INVALID;
274 while(hb_set_next(glyphsInput.
data(), ¤tGlyph)) {
275 if (!glyphToCodepoint.contains(currentGlyph))
continue;
276 const int codePointLocation = glyphToCodepoint.value(currentGlyph);
278 gci.
ucs = codePointInfo.
ucs;
279 bool addSample =
false;
281 uint alt_count = hb_ot_layout_lookup_get_glyph_alternates (hbFace.
data(),
282 lookUpIndex, currentGlyph,
288 for(
uint j = 1; j < alt_count; ++j) {
290 codePointInfo.
glyphs.append(gci);
296 codePointInfo.
glyphs.append(gci);
299 charMap[codePointLocation] = codePointInfo;
300 if (samples.size() < 6 && addSample) {
301 samples.append(QString::fromUcs4(&gci.
ucs, 1));
303 if (samples.size() >= 6 && samplesOnly) {
308 lookUpsProcessed.append(lookUpIndex);
309 if (info.
sample.isEmpty() && !samples.isEmpty()) {
310 info.
sample = samples.join(
" ");