Commits:
-
f563855d
by Charlie Jiang at 2023-08-06T09:37:06+00:00
[ftinspect] Fix named instances switching.
* src/ftinspect/engine/mmgx.cpp, src/ftinspect/engine/mmgx.hpp:
Load the default values of MMGX axes from the named instance instead of
the global default one.
* src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
Switch the named instance using `FT_Set_Named_Instance` when loading
fonts.
-
399eb8cf
by Charlie Jiang at 2023-08-06T09:37:06+00:00
[ftinspect] Fix default named instance handling.
Now the named instance selector no longer doubles the default named instance.
`FT_Get_Default_Named_Instance` is used to get the default NI index.
The default one is labeled as " (default)".
* src/ftinspect/widgets/tripletselector.cpp: Properly handle the new 1-based
named instance indices. Label the default NI correctly.
* src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
Add `Engine::defualtNamedInstanceIndex`.
* src/ftinspect/engine/mmgx.cpp: Change comments.
5 changed files:
Changes:
src/ftinspect/engine/engine.cpp
... |
... |
@@ -71,6 +71,7 @@ FaceID::operator<(const FaceID& other) const |
71
|
71
|
// font, face, and named instance indices. Getting a key from a value is
|
72
|
72
|
// slow, but this must be done only once, since `faceRequester` is only
|
73
|
73
|
// called if the font is not yet in the cache.
|
|
74
|
+// Note: Instance indices start from 1, and 0 is used to indicate no MM/GX handling.
|
74
|
75
|
|
75
|
76
|
FT_Error
|
76
|
77
|
faceRequester(FTC_FaceID ftcFaceID,
|
... |
... |
@@ -101,8 +102,7 @@ faceRequester(FTC_FaceID ftcFaceID, |
101
|
102
|
QString font = engine->fontFileManager_[faceID.fontIndex].filePath();
|
102
|
103
|
long faceIndex = faceID.faceIndex;
|
103
|
104
|
|
104
|
|
- if (faceID.namedInstanceIndex > 0)
|
105
|
|
- faceIndex += faceID.namedInstanceIndex << 16;
|
|
105
|
+ faceIndex += (faceID.namedInstanceIndex) << 16;
|
106
|
106
|
|
107
|
107
|
*faceP = NULL;
|
108
|
108
|
return FT_New_Face(library,
|
... |
... |
@@ -227,8 +227,8 @@ int |
227
|
227
|
Engine::numberOfNamedInstances(int fontIndex,
|
228
|
228
|
long faceIndex)
|
229
|
229
|
{
|
230
|
|
- // We return `n` named instances plus one;
|
231
|
|
- // instance index 0 represents a face without a named instance selected.
|
|
230
|
+ // With the new `FT_Get_Default_Named_Instance` func, we no longer to return
|
|
231
|
+ // one more entries.
|
232
|
232
|
int numNamedInstances = -1;
|
233
|
233
|
if (fontIndex < 0)
|
234
|
234
|
return -1;
|
... |
... |
@@ -237,7 +237,7 @@ Engine::numberOfNamedInstances(int fontIndex, |
237
|
237
|
[&](FT_Face face)
|
238
|
238
|
{
|
239
|
239
|
numNamedInstances
|
240
|
|
- = static_cast<int>((face->style_flags >> 16) + 1);
|
|
240
|
+ = static_cast<int>((face->style_flags >> 16));
|
241
|
241
|
});
|
242
|
242
|
|
243
|
243
|
return numNamedInstances;
|
... |
... |
@@ -264,6 +264,25 @@ Engine::namedInstanceName(int fontIndex, |
264
|
264
|
}
|
265
|
265
|
|
266
|
266
|
|
|
267
|
+unsigned
|
|
268
|
+Engine::defaultNamedInstanceIndex(int fontIndex,
|
|
269
|
+ int faceIndex)
|
|
270
|
+{
|
|
271
|
+ if (fontIndex < 0)
|
|
272
|
+ return 0;
|
|
273
|
+ unsigned ret = 0;
|
|
274
|
+ withFace(FaceID(fontIndex, faceIndex, 0),
|
|
275
|
+ [&](FT_Face face)
|
|
276
|
+ {
|
|
277
|
+ if (FT_Get_Default_Named_Instance(face, &ret) != 0)
|
|
278
|
+ {
|
|
279
|
+ // XXX error handling?
|
|
280
|
+ }
|
|
281
|
+ });
|
|
282
|
+ return ret;
|
|
283
|
+}
|
|
284
|
+
|
|
285
|
+
|
267
|
286
|
bool
|
268
|
287
|
Engine::currentFontTricky()
|
269
|
288
|
{
|
... |
... |
@@ -359,6 +378,8 @@ Engine::loadFont(int fontIndex, |
359
|
378
|
else
|
360
|
379
|
fontType_ = FontType_Other;
|
361
|
380
|
|
|
381
|
+ switchNamedInstance(namedInstanceIndex);
|
|
382
|
+
|
362
|
383
|
curCharMaps_.clear();
|
363
|
384
|
curCharMaps_.reserve(ftFallbackFace_->num_charmaps);
|
364
|
385
|
for (int i = 0; i < ftFallbackFace_->num_charmaps; i++)
|
... |
... |
@@ -366,7 +387,8 @@ Engine::loadFont(int fontIndex, |
366
|
387
|
|
367
|
388
|
SFNTName::get(this, curSFNTNames_);
|
368
|
389
|
loadPaletteInfos();
|
369
|
|
- curMMGXState_ = MMGXAxisInfo::get(this, curMMGXAxes_);
|
|
390
|
+ curMMGXState_ = MMGXAxisInfo::get(
|
|
391
|
+ this, static_cast<unsigned>(namedInstanceIndex), curMMGXAxes_);
|
370
|
392
|
}
|
371
|
393
|
|
372
|
394
|
curNumGlyphs_ = numGlyphs;
|
... |
... |
@@ -1035,4 +1057,25 @@ Engine::loadPaletteInfos() |
1035
|
1057
|
}
|
1036
|
1058
|
|
1037
|
1059
|
|
|
1060
|
+void
|
|
1061
|
+Engine::switchNamedInstance(int index)
|
|
1062
|
+{
|
|
1063
|
+ if (!ftFallbackFace_ || !FT_HAS_MULTIPLE_MASTERS(ftFallbackFace_))
|
|
1064
|
+ return;
|
|
1065
|
+ auto err = FT_Set_Named_Instance(ftFallbackFace_, index);
|
|
1066
|
+ if (err)
|
|
1067
|
+ {
|
|
1068
|
+ // XXX error handling
|
|
1069
|
+ }
|
|
1070
|
+ if (ftSize_)
|
|
1071
|
+ {
|
|
1072
|
+ err = FT_Set_Named_Instance(ftSize_->face, index);
|
|
1073
|
+ if (err)
|
|
1074
|
+ {
|
|
1075
|
+ // XXX error handling
|
|
1076
|
+ }
|
|
1077
|
+ }
|
|
1078
|
+}
|
|
1079
|
+
|
|
1080
|
+
|
1038
|
1081
|
// end of engine.cpp |
src/ftinspect/engine/engine.hpp
... |
... |
@@ -145,6 +145,8 @@ public: |
145
|
145
|
QString namedInstanceName(int fontIndex,
|
146
|
146
|
long faceIndex,
|
147
|
147
|
int index);
|
|
148
|
+ unsigned defaultNamedInstanceIndex(int fontIndex,
|
|
149
|
+ int faceIndex);
|
148
|
150
|
|
149
|
151
|
bool currentFontTricky();
|
150
|
152
|
bool currentFontBitmapOnly();
|
... |
... |
@@ -286,6 +288,7 @@ private: |
286
|
288
|
|
287
|
289
|
void queryEngine();
|
288
|
290
|
void loadPaletteInfos();
|
|
291
|
+ void switchNamedInstance(int index);
|
289
|
292
|
|
290
|
293
|
// It is safe to put the implementation into the corresponding cpp file.
|
291
|
294
|
template <class Func>
|
src/ftinspect/engine/mmgx.cpp
... |
... |
@@ -10,7 +10,8 @@ |
10
|
10
|
|
11
|
11
|
|
12
|
12
|
MMGXState
|
13
|
|
-MMGXAxisInfo::get(Engine* engine,
|
|
13
|
+MMGXAxisInfo::get(Engine* engine,
|
|
14
|
+ unsigned namedInstanceIndex,
|
14
|
15
|
std::vector<MMGXAxisInfo>& infos)
|
15
|
16
|
{
|
16
|
17
|
auto face = engine->currentFallbackFtFace();
|
... |
... |
@@ -37,6 +38,12 @@ MMGXAxisInfo::get(Engine* engine, |
37
|
38
|
return state;
|
38
|
39
|
}
|
39
|
40
|
|
|
41
|
+ FT_Var_Named_Style* namedInstance = nullptr;
|
|
42
|
+ // named instance index starts from 1, but we need to reference using a
|
|
43
|
+ // 0-based index.
|
|
44
|
+ if (namedInstanceIndex > 0 && namedInstanceIndex <= mm->num_namedstyles)
|
|
45
|
+ namedInstance = &mm->namedstyle[namedInstanceIndex - 1];
|
|
46
|
+
|
40
|
47
|
infos.resize(mm->num_axis);
|
41
|
48
|
|
42
|
49
|
auto& sfnt = engine->currentFontSFNTNames();
|
... |
... |
@@ -54,6 +61,9 @@ MMGXAxisInfo::get(Engine* engine, |
54
|
61
|
FT_Get_Var_Axis_Flags(mm, i, &flags);
|
55
|
62
|
info.hidden = (flags & FT_VAR_AXIS_FLAG_HIDDEN) != 0;
|
56
|
63
|
|
|
64
|
+ if (namedInstance)
|
|
65
|
+ info.def = namedInstance->coords[i] / 65536.0;
|
|
66
|
+
|
57
|
67
|
auto nameSet = false;
|
58
|
68
|
if (state == MMGXState::GX_OVF)
|
59
|
69
|
{
|
src/ftinspect/engine/mmgx.hpp
... |
... |
@@ -33,6 +33,7 @@ struct MMGXAxisInfo |
33
|
33
|
bool isMM;
|
34
|
34
|
|
35
|
35
|
static MMGXState get(Engine* engine,
|
|
36
|
+ unsigned namedInstanceIndex,
|
36
|
37
|
std::vector<MMGXAxisInfo>& infos);
|
37
|
38
|
|
38
|
39
|
|
src/ftinspect/widgets/tripletselector.cpp
... |
... |
@@ -162,7 +162,7 @@ TripletSelector::repopulateNamedInstances(bool fontSwitched) |
162
|
162
|
newFaces.reserve(newSize);
|
163
|
163
|
for (long i = 0; i < newSize; i++)
|
164
|
164
|
{
|
165
|
|
- newFaces.emplace_back(engine_->namedInstanceName(fontIndex, faceIndex, i));
|
|
165
|
+ newFaces.emplace_back(engine_->namedInstanceName(fontIndex, faceIndex, i + 1));
|
166
|
166
|
if (!needToRecreate && newFaces[i] != niComboBox_->itemData(i))
|
167
|
167
|
needToRecreate = true;
|
168
|
168
|
}
|
... |
... |
@@ -181,16 +181,19 @@ TripletSelector::repopulateNamedInstances(bool fontSwitched) |
181
|
181
|
QSignalBlocker blk3(niComboBox_);
|
182
|
182
|
niComboBox_->clear();
|
183
|
183
|
|
184
|
|
- for (long i = 0; i < newSize; i++)
|
|
184
|
+ // Returned index starts from 1, therefore minus 1.
|
|
185
|
+ auto defaultId = engine_->defaultNamedInstanceIndex(fontIndex, faceIndex) - 1;
|
|
186
|
+ for (unsigned i = 0; i < static_cast<unsigned>(newSize); i++)
|
185
|
187
|
{
|
186
|
188
|
auto& name = newFaces[i];
|
187
|
|
- auto displayName = QString("%1: %2").arg(i).arg(name);
|
188
|
|
- if (i == 0)
|
189
|
|
- displayName = "* " + displayName;
|
|
189
|
+ auto displayName = QString("%1: %2").arg(i + 1).arg(name);
|
|
190
|
+ if (i == defaultId)
|
|
191
|
+ displayName = displayName + " (default)";
|
190
|
192
|
niComboBox_->addItem(displayName, name);
|
191
|
193
|
}
|
192
|
194
|
|
193
|
|
- niComboBox_->setCurrentIndex(0);
|
|
195
|
+ if (defaultId >= 0 && newSize > 0)
|
|
196
|
+ niComboBox_->setCurrentIndex(static_cast<int>(defaultId));
|
194
|
197
|
// Note: no signal is emitted from any combobox until this block ends.
|
195
|
198
|
}
|
196
|
199
|
|
... |
... |
@@ -460,10 +463,9 @@ TripletSelector::loadTriplet() |
460
|
463
|
|
461
|
464
|
if (faceIndex < 0)
|
462
|
465
|
faceIndex = 0;
|
463
|
|
- if (instanceIndex < 0)
|
464
|
|
- instanceIndex = 0;
|
465
|
|
-
|
466
|
|
- engine_->loadFont(fontIndex, faceIndex, instanceIndex);
|
|
466
|
+ if (instanceIndex < 0 || niComboBox_->count() == 0)
|
|
467
|
+ instanceIndex = -1; // No instance available.
|
|
468
|
+ engine_->loadFont(fontIndex, faceIndex, instanceIndex + 1);
|
467
|
469
|
|
468
|
470
|
// TODO: This may mess up with bitmap-only fonts.
|
469
|
471
|
if (!engine_->fontValid())
|
|