Krita Source Code Documentation
Loading...
Searching...
No Matches
KoFontGlyphModel::Private Struct Reference

Classes

struct  CodePointInfo
 
struct  GlyphInfo
 

Public Member Functions

 ~Private ()=default
 

Static Public Member Functions

static QVector< CodePointInfocharMap (FT_FaceSP face)
 
static QMap< QString, KoOpenTypeFeatureInfogetOpenTypeTables (FT_FaceSP face, QVector< CodePointInfo > &charMap, QMap< QString, KoOpenTypeFeatureInfo > previousFeatureInfo, bool gpos, bool samplesOnly, QStringList locales, QLatin1String lang=QLatin1String())
 
static QMap< uint, QVector< GlyphInfo > > getVSData (FT_FaceSP face)
 

Public Attributes

QVector< KoUnicodeBlockDatablocks
 
QVector< CodePointInfocodePoints
 
QMap< QString, KoOpenTypeFeatureInfofeatureData
 

Detailed Description

Definition at line 14 of file KoFontGlyphModel.cpp.

Constructor & Destructor Documentation

◆ ~Private()

KoFontGlyphModel::Private::~Private ( )
default

Member Function Documentation

◆ charMap()

static QVector< CodePointInfo > KoFontGlyphModel::Private::charMap ( FT_FaceSP face)
inlinestatic

Definition at line 69 of file KoFontGlyphModel.cpp.

69 {
71
72 FT_UInt gindex;
73 FT_ULong charcode = FT_Get_First_Char(face.data(), &gindex);
74
75 while (gindex != 0) {
76 CodePointInfo cpi;
77 cpi.ucs = charcode;
78 cpi.glyphIndex = gindex;
79 cpi.utfString = QString::fromUcs4(&cpi.ucs, 1);
80 cpi.glyphs.append(GlyphInfo(cpi.ucs));
81
82 codePoints.append(cpi);
83 charcode = FT_Get_Next_Char(face.data(), charcode, &gindex);
84 }
85
86 return codePoints;
87 }
QVector< CodePointInfo > codePoints

References codePoints, KisLibraryResourcePointer< T, P >::data(), KoFontGlyphModel::Private::CodePointInfo::glyphIndex, KoFontGlyphModel::Private::CodePointInfo::glyphs, KoFontGlyphModel::Private::CodePointInfo::ucs, and KoFontGlyphModel::Private::CodePointInfo::utfString.

◆ getOpenTypeTables()

static QMap< QString, KoOpenTypeFeatureInfo > KoFontGlyphModel::Private::getOpenTypeTables ( FT_FaceSP face,
QVector< CodePointInfo > & charMap,
QMap< QString, KoOpenTypeFeatureInfo > previousFeatureInfo,
bool gpos,
bool samplesOnly,
QStringList locales,
QLatin1String lang = QLatin1String() )
inlinestatic

Definition at line 114 of file KoFontGlyphModel.cpp.

114 {
115 // All of this was referenced from Inkscape's OpenTypeUtil.cpp::readOpenTypeGsubTable
116 // It has since been reworked to include language testing and alternates.
117 QMap<QString, KoOpenTypeFeatureInfo> featureInfo = previousFeatureInfo;
118 hb_face_t_sp hbFace(hb_ft_face_create_referenced(face.data()));
119 hb_tag_t table = gpos? HB_OT_TAG_GPOS: HB_OT_TAG_GSUB;
120 uint targetLanguageIndex = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
121
122 QVector<hb_language_t> localeTags;
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()));
126 }
127
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);
131 QVector<uint> scriptIndices;
132 for (uint script = 0; script < scriptCount; script++) {
133 uint scriptCount = 1;
134 hb_tag_t scriptTag;
135 uint scriptIndex;
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)) {
138 continue;
139 }
140 scriptIndices.append(scriptIndex);
141
142 uint languageCount = hb_ot_layout_script_get_language_tags(hbFace.data(), table, scriptIndex, 0, nullptr, nullptr);
143
144 bool foundLanguage = false;
145
146 for(uint j = 0; j < languageCount; j++) {
147 hb_tag_t langTag;
148 uint count = 1;
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) {
152 uint languageIndex;
153 if (hb_ot_layout_script_select_language(hbFace.data(), table, scriptIndex, count, &langTag, &languageIndex)) {
154 targetLanguageIndex = languageIndex;
155 foundLanguage = true;
156 break;
157 }
158 }
159 }
160 if (foundLanguage) break;
161 }
162
163 QHash<quint32, int> glyphToCodepoint;
164 for (int i = 0; i< charMap.size(); i++) {
165 glyphToCodepoint.insert(charMap.at(i).glyphIndex, i);
166 }
167
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(),
171 table,
172 targetScriptIndex,
173 targetLanguageIndex,
174 0, nullptr, nullptr);
175 hb_ot_layout_language_get_feature_tags(hbFace.data(), table, targetScriptIndex,
176 targetLanguageIndex,
177 0, nullptr, nullptr);
178 for(uint k = 0; k < featureCount; k++) {
179 uint count = 1;
180 hb_tag_t features;
181 hb_ot_layout_language_get_feature_tags(hbFace.data(), table, targetScriptIndex,
182 targetLanguageIndex,
183 k, &count, &features);
184 if (count < 1) continue;
185 tags.append(features);
186 }
187
188
189
191 QVector<uint> featureIndicesProcessed;
192 QVector<uint> lookUpsProcessed;
193 for (auto tagIt = tags.begin(); tagIt != tags.end(); tagIt++) {
194 char c[4];
195 hb_tag_to_string(*tagIt, c);
196 const QByteArray tagName(c, 4);
197 uint featureIndex;
198
199
200 bool found = hb_ot_layout_language_find_feature (hbFace.data(), table,
201 targetScriptIndex,
202 targetLanguageIndex,
203 *tagIt,
204 &featureIndex );
205
206 if (!found || featureIndicesProcessed.contains(featureIndex)) {
207 continue;
208 }
209 featureIndicesProcessed.append(featureIndex);
210
211 KoOpenTypeFeatureInfo info = featureInfo.value(tagName, factory.infoByTag(tagName));
212 if (!featureInfo.contains(tagName)) {
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;
218
219 if (hb_ot_layout_feature_get_name_ids(hbFace.data(), table, featureIndex, &labelId, &toolTipId, &sampleId, &namedParameters, &firstParamId)) {
220 QVector<hb_ot_name_id_t> nameIds = {labelId, toolTipId, sampleId};
221 if (firstParamId != HB_OT_NAME_ID_INVALID) {
222 for (uint i = 0; i < namedParameters; i++) {
223 nameIds += firstParamId + i;
224 }
225 }
226
227 for(auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
228 if (*nameId == HB_OT_NAME_ID_INVALID) {
229 continue;
230 }
231 QVector<hb_language_t> testLang;
232 uint length = 0;
233 if (*nameId == sampleId) {
234 testLang.append(languageTag);
235 } else {
236 testLang = localeTags;
237 }
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);
241 if (length > 0) {
242 length+=1;
243 break;
244 }
245 }
246
247 std::vector<char> buff(length);
248 hb_ot_name_get_utf8(hbFace.data(), *nameId, languageTag, &length, buff.data());
249 if (length > 0) {
250 const QString nameString = QString::fromUtf8(buff.data(), length);
251 if (*nameId == labelId) {
252 info.name = nameString;
253 } else if (*nameId == toolTipId) {
254 info.description = nameString;
255 } else if (*nameId == sampleId) {
256 info.sample = nameString;
257 } else {
258 info.namedParameters.append(nameString);
259 }
260 }
261 }
262 }
263
264 featureInfo.insert(tagName, info);
265 }
266 if (!info.glyphPalette || (samplesOnly && !info.sample.isEmpty())) {
267 continue;
268 }
269
270 QStringList samples;
271 int lookupCount = hb_ot_layout_feature_get_lookups (hbFace.data(), table,
272 featureIndex,
273 0,
274 nullptr,
275 nullptr );
276 for (int i = 0; i < lookupCount; ++i) {
277 uint maxCount = 1;
278 uint lookUpIndex = 0;
279 hb_ot_layout_feature_get_lookups (hbFace.data(), table,
280 featureIndex,
281 i,
282 &maxCount,
283 &lookUpIndex );
284 if (maxCount < 1 || lookUpsProcessed.contains(lookUpIndex)) {
285 continue;
286 }
287
288 // https://github.com/harfbuzz/harfbuzz/issues/673 suggest against checking the lookups,
289 // but if we don't know the input glyphs, initialization can get really slow.
290 // Given this is run only when the model is created, this should be fine for now.
291
292 hb_set_t_sp glyphsBefore (hb_set_create());
293 hb_set_t_sp glyphsInput (hb_set_create());
294 hb_set_t_sp glyphsAfter (hb_set_create());
295 hb_set_t_sp glyphsOutput (hb_set_create());
296
297 hb_ot_layout_lookup_collect_glyphs (hbFace.data(), table,
298 lookUpIndex,
299 glyphsBefore.data(),
300 glyphsInput.data(),
301 glyphsAfter.data(),
302 glyphsOutput.data() );
303
304 GlyphInfo gci;
305 gci.type = OpenType;
306 gci.baseString = tagName;
307
308 hb_codepoint_t currentGlyph = HB_SET_VALUE_INVALID;
309 while(hb_set_next(glyphsInput.data(), &currentGlyph)) {
310 if (!glyphToCodepoint.contains(currentGlyph)) continue;
311 const int codePointLocation = glyphToCodepoint.value(currentGlyph);
312 CodePointInfo codePointInfo = charMap.at(codePointLocation);
313 gci.ucs = codePointInfo.ucs;
314 bool addSample = false;
315
316 uint alt_count = hb_ot_layout_lookup_get_glyph_alternates (hbFace.data(),
317 lookUpIndex, currentGlyph,
318 0,
319 nullptr, nullptr);
320
321 if (alt_count > 0) {
322 // 0 is the default value.
323 for(uint j = 1; j < alt_count; ++j) {
324 gci.featureIndex = j;
325
326 bool addToGlyphs = codePointInfo.addToGlyphsIfNotAlready(gci);
327 if (addToGlyphs && !addSample) {
328 addSample = true;
329 }
330 }
331 info.maxValue = qMax(int(alt_count), info.maxValue);
332 } else {
333 gci.featureIndex = 1;
334 addSample = codePointInfo.addToGlyphsIfNotAlready(gci);
335 }
336 charMap[codePointLocation] = codePointInfo;
337 if (samples.size() < 6 && addSample) {
338 samples.append(QString::fromUcs4(&gci.ucs, 1));
339 }
340 if (samples.size() >= 6 && samplesOnly) {
341 break;
342 }
343 }
344
345 lookUpsProcessed.append(lookUpIndex);
346 if (info.sample.isEmpty() && !samples.isEmpty()) {
347 info.sample = samples.join(" ");
348 }
349 featureInfo.insert(tagName, info);
350
351 }
352
353 }
354 }
355
356 return featureInfo;
357 }
qreal length(const QPointF &vec)
Definition Ellipse.cc:82
unsigned int uint
QMap< QString, KoOpenTypeFeatureInfo > featureInfo() const
featureInfo
static QVector< CodePointInfo > charMap(FT_FaceSP face)
The KoOpenTypeFeatureInfoFactory class.
KoOpenTypeFeatureInfo infoByTag(const QByteArray &tag) const
infoByTag
QString description
Description of the feature.
QString name
User-friendly name.
bool glyphPalette
Whether the feature should be visible in the glyph palette.
QString sample
Sample of the feature, if any. Only used by CVXX features and retrieved from the font.
int maxValue
The maximum value possible, this is by default 1 (on), but for alternate substitution(gsub 3),...

References KoFontGlyphModel::Private::CodePointInfo::addToGlyphsIfNotAlready(), KoFontGlyphModel::Private::GlyphInfo::baseString, charMap(), KisLibraryResourcePointer< T, P >::data(), KoOpenTypeFeatureInfo::description, KoFontGlyphModel::Private::GlyphInfo::featureIndex, KoFontGlyphModel::featureInfo(), KoOpenTypeFeatureInfo::glyphPalette, KoOpenTypeFeatureInfoFactory::infoByTag(), length(), KoOpenTypeFeatureInfo::maxValue, KoOpenTypeFeatureInfo::name, KoOpenTypeFeatureInfo::namedParameters, KoFontGlyphModel::OpenType, KoOpenTypeFeatureInfo::sample, KoFontGlyphModel::Private::GlyphInfo::type, KoFontGlyphModel::Private::GlyphInfo::ucs, and KoFontGlyphModel::Private::CodePointInfo::ucs.

◆ getVSData()

static QMap< uint, QVector< GlyphInfo > > KoFontGlyphModel::Private::getVSData ( FT_FaceSP face)
inlinestatic

Definition at line 89 of file KoFontGlyphModel.cpp.

89 {
90 QMap<uint, QVector<GlyphInfo>> vsData;
91 hb_face_t_sp hbFace(hb_ft_face_create_referenced(face.data()));
92 hb_set_t_sp variationSelectors(hb_set_create());
93 hb_face_collect_variation_selectors(hbFace.data(), variationSelectors.data());
94
95 hb_codepoint_t hbVSPoint = HB_SET_VALUE_INVALID;
96
97 while(hb_set_next(variationSelectors.data(), &hbVSPoint)) {
98 hb_set_t_sp unicodes(hb_set_create());
99
100 hb_face_collect_variation_unicodes(hbFace.data(), hbVSPoint, unicodes.data());
101 hb_codepoint_t hbCodePointPoint = HB_SET_VALUE_INVALID;
102 while(hb_set_next(unicodes.data(), &hbCodePointPoint)) {
103 QVector<GlyphInfo> glyphs = vsData.value(hbCodePointPoint);
104 GlyphInfo gci(hbCodePointPoint);
105 gci.type = UnicodeVariationSelector;
106 gci.baseString = QString::fromUcs4(&hbVSPoint, 1);
107 glyphs.append(gci);
108 vsData.insert(hbCodePointPoint, glyphs);
109 }
110 }
111 return vsData;
112 }

References KoFontGlyphModel::Private::GlyphInfo::baseString, KisLibraryResourcePointer< T, P >::data(), KoFontGlyphModel::Private::GlyphInfo::type, and KoFontGlyphModel::UnicodeVariationSelector.

Member Data Documentation

◆ blocks

QVector<KoUnicodeBlockData> KoFontGlyphModel::Private::blocks

Definition at line 64 of file KoFontGlyphModel.cpp.

◆ codePoints

QVector<CodePointInfo> KoFontGlyphModel::Private::codePoints

Definition at line 62 of file KoFontGlyphModel.cpp.

◆ featureData

QMap<QString, KoOpenTypeFeatureInfo> KoFontGlyphModel::Private::featureData

Definition at line 63 of file KoFontGlyphModel.cpp.


The documentation for this struct was generated from the following file: