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

Classes

struct  CodePointInfo
 
struct  GlyphInfo
 

Public Member Functions

QMap< QString, KoOpenTypeFeatureInfogetOpenTypeTables (FT_FaceSP face, QVector< CodePointInfo > &charMap, QMap< QString, KoOpenTypeFeatureInfo > previousFeatureInfo, bool gpos, bool samplesOnly, QStringList locales, QLatin1String lang=QLatin1String())
 
 ~Private ()=default
 

Static Public Member Functions

static QVector< CodePointInfocharMap (FT_FaceSP face)
 
static QMap< uint, QVector< GlyphInfo > > getVSData (FT_FaceSP face)
 

Public Attributes

QVector< KoUnicodeBlockDatablocks
 
QVector< CodePointInfocodePoints
 
QMap< QString, KoOpenTypeFeatureInfofeatureData
 
KoOpenTypeFeatureInfoFactory openTypeFeaturesFactory
 
KoUnicodeBlockDataFactory unicodeBlockFactory
 

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 71 of file KoFontGlyphModel.cpp.

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

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() )
inline

Definition at line 116 of file KoFontGlyphModel.cpp.

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

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

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.

◆ openTypeFeaturesFactory

KoOpenTypeFeatureInfoFactory KoFontGlyphModel::Private::openTypeFeaturesFactory

Definition at line 65 of file KoFontGlyphModel.cpp.

◆ unicodeBlockFactory

KoUnicodeBlockDataFactory KoFontGlyphModel::Private::unicodeBlockFactory

Definition at line 66 of file KoFontGlyphModel.cpp.


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