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

Classes

struct  CodePointInfo
 
struct  GlyphInfo
 
struct  InfoNode
 

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

59 {
61
62 FT_UInt gindex;
63 FT_ULong charcode = FT_Get_First_Char(face.data(), &gindex);
64
65 while (gindex != 0) {
66 CodePointInfo cpi;
67 cpi.ucs = charcode;
68 cpi.glyphIndex = gindex;
69 cpi.utfString = QString::fromUcs4(&cpi.ucs, 1);
70 cpi.glyphs.append(GlyphInfo(cpi.ucs));
71
72 codePoints.append(cpi);
73 charcode = FT_Get_Next_Char(face.data(), charcode, &gindex);
74 }
75
76 return codePoints;
77 }
QVector< CodePointInfo > codePoints

References codePoints, KisLibraryResourcePointer< T, P >::data(), KoFontGlyphModel::Private::CodePointInfo::glyphIndex, KoFontGlyphModel::Private::CodePointInfo::glyphs, KoFontGlyphModel::Private::InfoNode::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 104 of file KoFontGlyphModel.cpp.

104 {
105 // All of this was referenced from Inkscape's OpenTypeUtil.cpp::readOpenTypeGsubTable
106 // It has since been reworked to include language testing and alternates.
107 QMap<QString, KoOpenTypeFeatureInfo> featureInfo = previousFeatureInfo;
108 hb_face_t_sp hbFace(hb_ft_face_create_referenced(face.data()));
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;
112
113 QVector<hb_language_t> localeTags;
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()));
117 }
118
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);
124
125 for(uint j = 0; j < languageCount; j++) {
126 hb_tag_t langTag;
127 uint count = 1;
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) {
131 targetLanguage = j;
132 targetScript = script;
133 break;
134 }
135 }
136 }
137
138 uint featureCount = hb_ot_layout_language_get_feature_tags(hbFace.data(),
139 table,
140 targetScript,
141 targetLanguage,
142 0, nullptr, nullptr);
143 hb_ot_layout_language_get_feature_tags(hbFace.data(), table, targetScript,
144 targetLanguage,
145 0, nullptr, nullptr);
146 for(uint k = 0; k < featureCount; k++) {
147 uint count = 1;
148 hb_tag_t features;
149 hb_ot_layout_language_get_feature_tags(hbFace.data(), table, targetScript,
150 targetLanguage,
151 k, &count, &features);
152 if (count < 1) continue;
153 tags.append(features);
154 }
155
156 QHash<quint32, int> glyphToCodepoint;
157 for (int i = 0; i< charMap.size(); i++) {
158 glyphToCodepoint.insert(charMap.at(i).glyphIndex, i);
159 }
160
162 for (auto it = tags.begin(); it != tags.end(); it++) {
163 char c[4];
164 hb_tag_to_string(*it, c);
165 const QLatin1String tagName(c, 4);
166 uint featureIndex;
167
168 QVector<uint> lookUpsProcessed;
169 bool found = hb_ot_layout_language_find_feature (hbFace.data(), table,
170 targetScript,
171 targetLanguage,
172 *it,
173 &featureIndex );
174
175 if (!found) {
176 continue;
177 }
178
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;
184 KoOpenTypeFeatureInfo info = factory.infoByTag(tagName);
185 if (hb_ot_layout_feature_get_name_ids(hbFace.data(), table, featureIndex, &labelId, &toolTipId, &sampleId, &namedParameters, &firstParamId)) {
186 QVector<hb_ot_name_id_t> nameIds = {labelId, toolTipId, sampleId};
187 if (firstParamId != HB_OT_NAME_ID_INVALID) {
188 for (uint i = 0; i < namedParameters; i++) {
189 nameIds += firstParamId + i;
190 }
191 }
192
193 for(auto nameId = nameIds.begin(); nameId != nameIds.end(); nameId++) {
194 if (*nameId == HB_OT_NAME_ID_INVALID) {
195 continue;
196 }
197 QVector<hb_language_t> testLang;
198 uint length = 0;
199 if (*nameId == sampleId) {
200 testLang.append(languageTag);
201 } else {
202 testLang = localeTags;
203 }
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);
207 if (length > 0) {
208 length+=1;
209 break;
210 }
211 }
212
213 std::vector<char> buff(length);
214 hb_ot_name_get_utf8(hbFace.data(), *nameId, languageTag, &length, buff.data());
215 if (length > 0) {
216 const QString nameString = QString::fromUtf8(buff.data(), length);
217 if (*nameId == labelId) {
218 info.name = nameString;
219 } else if (*nameId == toolTipId) {
220 info.description = nameString;
221 } else if (*nameId == sampleId) {
222 info.sample = nameString;
223 } else {
224 info.namedParameters.append(nameString);
225 }
226 }
227 }
228 }
229
230 featureInfo.insert(tagName, info);
231 if (!info.glyphPalette || (samplesOnly && !info.sample.isEmpty())) {
232 continue;
233 }
234
235 QStringList samples;
236 int lookupCount = hb_ot_layout_feature_get_lookups (hbFace.data(), table,
237 featureIndex,
238 0,
239 nullptr,
240 nullptr );
241 for (int i = 0; i < lookupCount; ++i) {
242 uint maxCount = 1;
243 uint lookUpIndex = 0;
244 hb_ot_layout_feature_get_lookups (hbFace.data(), table,
245 featureIndex,
246 i,
247 &maxCount,
248 &lookUpIndex );
249 if (maxCount < 1 || lookUpsProcessed.contains(lookUpIndex)) {
250 continue;
251 }
252
253 // https://github.com/harfbuzz/harfbuzz/issues/673 suggest against checking the lookups,
254 // but if we don't know the input glyphs, initialization can get really slow.
255 // Given this is run only when the model is created, this should be fine for now.
256
257 hb_set_t_sp glyphsBefore (hb_set_create());
258 hb_set_t_sp glyphsInput (hb_set_create());
259 hb_set_t_sp glyphsAfter (hb_set_create());
260 hb_set_t_sp glyphsOutput (hb_set_create());
261
262 hb_ot_layout_lookup_collect_glyphs (hbFace.data(), table,
263 lookUpIndex,
264 glyphsBefore.data(),
265 glyphsInput.data(),
266 glyphsAfter.data(),
267 glyphsOutput.data() );
268
269 GlyphInfo gci;
270 gci.type = OpenType;
271 gci.baseString = tagName;
272
273 hb_codepoint_t currentGlyph = HB_SET_VALUE_INVALID;
274 while(hb_set_next(glyphsInput.data(), &currentGlyph)) {
275 if (!glyphToCodepoint.contains(currentGlyph)) continue;
276 const int codePointLocation = glyphToCodepoint.value(currentGlyph);
277 CodePointInfo codePointInfo = charMap.at(codePointLocation);
278 gci.ucs = codePointInfo.ucs;
279 bool addSample = false;
280
281 uint alt_count = hb_ot_layout_lookup_get_glyph_alternates (hbFace.data(),
282 lookUpIndex, currentGlyph,
283 0,
284 nullptr, nullptr);
285
286 if (alt_count > 0) {
287 // 0 is the default value.
288 for(uint j = 1; j < alt_count; ++j) {
289 gci.featureIndex = j;
290 codePointInfo.glyphs.append(gci);
291 }
292 info.maxValue = qMax(int(alt_count), info.maxValue);
293 addSample = true;
294 } else {
295 gci.featureIndex = 1;
296 codePointInfo.glyphs.append(gci);
297 addSample = true;
298 }
299 charMap[codePointLocation] = codePointInfo;
300 if (samples.size() < 6 && addSample) {
301 samples.append(QString::fromUcs4(&gci.ucs, 1));
302 }
303 if (samples.size() >= 6 && samplesOnly) {
304 break;
305 }
306 }
307
308 lookUpsProcessed.append(lookUpIndex);
309 if (info.sample.isEmpty() && !samples.isEmpty()) {
310 info.sample = samples.join(" ");
311 }
312 featureInfo.insert(tagName, info);
313
314 }
315
316 }
317
318
319 return featureInfo;
320 }
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 QLatin1String &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::GlyphInfo::baseString, charMap(), KisLibraryResourcePointer< T, P >::data(), KoOpenTypeFeatureInfo::description, KoFontGlyphModel::Private::GlyphInfo::featureIndex, KoFontGlyphModel::featureInfo(), KoOpenTypeFeatureInfo::glyphPalette, KoFontGlyphModel::Private::CodePointInfo::glyphs, KoOpenTypeFeatureInfoFactory::infoByTag(), length(), KoOpenTypeFeatureInfo::maxValue, KoOpenTypeFeatureInfo::name, KoOpenTypeFeatureInfo::namedParameters, KoFontGlyphModel::OpenType, KoOpenTypeFeatureInfo::sample, KoFontGlyphModel::Private::GlyphInfo::type, and KoFontGlyphModel::Private::InfoNode::ucs.

◆ getVSData()

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

Definition at line 79 of file KoFontGlyphModel.cpp.

79 {
80 QMap<uint, QVector<GlyphInfo>> vsData;
81 hb_face_t_sp hbFace(hb_ft_face_create_referenced(face.data()));
82 hb_set_t_sp variationSelectors(hb_set_create());
83 hb_face_collect_variation_selectors(hbFace.data(), variationSelectors.data());
84
85 hb_codepoint_t hbVSPoint = HB_SET_VALUE_INVALID;
86
87 while(hb_set_next(variationSelectors.data(), &hbVSPoint)) {
88 hb_set_t_sp unicodes(hb_set_create());
89
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)) {
93 QVector<GlyphInfo> glyphs = vsData.value(hbCodePointPoint);
94 GlyphInfo gci(hbCodePointPoint);
95 gci.type = UnicodeVariationSelector;
96 gci.baseString = QString::fromUcs4(&hbVSPoint, 1);
97 glyphs.append(gci);
98 vsData.insert(hbCodePointPoint, glyphs);
99 }
100 }
101 return vsData;
102 }

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

◆ codePoints

QVector<CodePointInfo> KoFontGlyphModel::Private::codePoints

Definition at line 52 of file KoFontGlyphModel.cpp.

◆ featureData

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

Definition at line 53 of file KoFontGlyphModel.cpp.


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