[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2-demos] gsoc-2022-chariri-3 b6b79a8 27/36: [ftinspect] Improve
From: |
Werner Lemberg |
Subject: |
[freetype2-demos] gsoc-2022-chariri-3 b6b79a8 27/36: [ftinspect] Improve Font/Face/NI selector. |
Date: |
Wed, 27 Jul 2022 06:32:46 -0400 (EDT) |
branch: gsoc-2022-chariri-3
commit b6b79a8ae125cf06e28ed6aa0320805acb455374
Author: Charlie Jiang <w@chariri.moe>
Commit: Charlie Jiang <w@chariri.moe>
[ftinspect] Improve Font/Face/NI selector.
This commit replaces the 6 buttons switching Font/Face/Named Instance
triplet. Instead, it now squash the triplet selector into three comboboxes
with tiny Previous/Next buttons. All those widgets are lined horizontally
in the bottom the window. This reduces space waste.
Also make tiny changes to the layouts for proper alignment.
* src/ftinspect/widgets/tripletselector.cpp,
src/ftinspect/widgets/tripletselector.hpp: New file, as described.
`TripletSelector` contains all logic for populating the triplets and
calling the engine to load them.
* src/ftinspect/maingui.hpp, src/ftinspect/maingui.cpp: Move out triplet
selection and font loading code. Integrate in `TripletSelector` widget and
adjust the layout. Remove the status bar.
* src/ftinspect/engine/engine.hpp:
Simplify some `FaceID` related code.
Add proper handling of cases when `faceID == -1`.
Add `namedInstanceName` function (also can be used to fetch face name).
TODO: Body of function involving find a face/size object is highly
similar - chances for refactoring?
* src/ftinspect/panels/settingpanel.cpp: Layout change, remove margins.
* src/ftinspect/engine/fontfilemanager.cpp: Fix the bug that deletion isn't
detected in time caused by caching inside `QFileInfo`.
* src/ftinspect/ftinspect.cpp: Remove `MainGUI::setDefaults`.
* src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
---
src/ftinspect/CMakeLists.txt | 1 +
src/ftinspect/engine/engine.cpp | 91 ++++--
src/ftinspect/engine/engine.hpp | 7 +-
src/ftinspect/engine/fontfilemanager.cpp | 1 +
src/ftinspect/ftinspect.cpp | 2 -
src/ftinspect/maingui.cpp | 350 ++--------------------
src/ftinspect/maingui.hpp | 47 +--
src/ftinspect/meson.build | 2 +
src/ftinspect/panels/settingpanel.cpp | 2 +
src/ftinspect/widgets/tripletselector.cpp | 474 ++++++++++++++++++++++++++++++
src/ftinspect/widgets/tripletselector.hpp | 66 +++++
11 files changed, 648 insertions(+), 395 deletions(-)
diff --git a/src/ftinspect/CMakeLists.txt b/src/ftinspect/CMakeLists.txt
index 4fe2a52..e544f7e 100644
--- a/src/ftinspect/CMakeLists.txt
+++ b/src/ftinspect/CMakeLists.txt
@@ -37,6 +37,7 @@ add_executable(ftinspect
"widgets/customwidgets.cpp"
"widgets/glyphindexselector.cpp"
"widgets/fontsizeselector.cpp"
+ "widgets/tripletselector.cpp"
"models/customcomboboxmodels.cpp"
diff --git a/src/ftinspect/engine/engine.cpp b/src/ftinspect/engine/engine.cpp
index da0573b..4ee99d0 100644
--- a/src/ftinspect/engine/engine.cpp
+++ b/src/ftinspect/engine/engine.cpp
@@ -99,13 +99,14 @@ faceRequester(FTC_FaceID ftcFaceID,
if (faceID.fontIndex < 0
|| faceID.fontIndex >= engine->numberOfOpenedFonts())
return FT_Err_Invalid_Argument;
-
+
QString font = engine->fontFileManager_[faceID.fontIndex].filePath();
long faceIndex = faceID.faceIndex;
if (faceID.namedInstanceIndex > 0)
faceIndex += faceID.namedInstanceIndex << 16;
+ *faceP = NULL;
return FT_New_Face(library,
qPrintable(font),
faceIndex,
@@ -175,11 +176,13 @@ Engine::numberOfFaces(int fontIndex)
FT_Face face;
long numFaces = -1;
+ if (fontIndex < 0)
+ return -1;
+
+ auto id = FaceID(fontIndex, 0, 0);
+
// search triplet (fontIndex, 0, 0)
- FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
- (faceIDMap_.value(FaceID(fontIndex,
- 0,
- 0)));
+ FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
if (ftcFaceID)
{
// found
@@ -190,14 +193,13 @@ Engine::numberOfFaces(int fontIndex)
{
// not found; try to load triplet (fontIndex, 0, 0)
ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
- faceIDMap_.insert(FaceID(fontIndex, 0, 0),
- faceCounter_++);
+ faceIDMap_.insert(id, faceCounter_++);
if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
numFaces = face->num_faces;
else
{
- faceIDMap_.remove(FaceID(fontIndex, 0, 0));
+ faceIDMap_.remove(id);
faceCounter_--;
}
}
@@ -214,12 +216,12 @@ Engine::numberOfNamedInstances(int fontIndex,
// we return `n' named instances plus one;
// instance index 0 represents a face without a named instance selected
int numNamedInstances = -1;
+ if (fontIndex < 0)
+ return -1;
+ auto id = FaceID(fontIndex, faceIndex, 0);
// search triplet (fontIndex, faceIndex, 0)
- FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>
- (faceIDMap_.value(FaceID(fontIndex,
- faceIndex,
- 0)));
+ FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
if (ftcFaceID)
{
// found
@@ -230,14 +232,13 @@ Engine::numberOfNamedInstances(int fontIndex,
{
// not found; try to load triplet (fontIndex, faceIndex, 0)
ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
- faceIDMap_.insert(FaceID(fontIndex, faceIndex, 0),
- faceCounter_++);
+ faceIDMap_.insert(id, faceCounter_++);
if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
numNamedInstances = static_cast<int>((face->style_flags >> 16) + 1);
else
{
- faceIDMap_.remove(FaceID(fontIndex, faceIndex, 0));
+ faceIDMap_.remove(id);
faceCounter_--;
}
}
@@ -246,6 +247,48 @@ Engine::numberOfNamedInstances(int fontIndex,
}
+QString
+Engine::namedInstanceName(int fontIndex, long faceIndex, int index)
+{
+ FT_Face face;
+ QString name;
+
+ if (fontIndex < 0)
+ return QString();
+
+ auto id = FaceID(fontIndex, faceIndex, index);
+
+ // search triplet (fontIndex, faceIndex, 0)
+ FTC_FaceID ftcFaceID = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
+ if (ftcFaceID)
+ {
+ // found
+ if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
+ name = QString("%1 %2")
+ .arg(face->family_name)
+ .arg(face->style_name);
+ }
+ else
+ {
+ // not found; try to load triplet (fontIndex, faceIndex, 0)
+ ftcFaceID = reinterpret_cast<FTC_FaceID>(faceCounter_);
+ faceIDMap_.insert(id, faceCounter_++);
+
+ if (!FTC_Manager_LookupFace(cacheManager_, ftcFaceID, &face))
+ name = QString("%1 %2")
+ .arg(face->family_name)
+ .arg(face->style_name);
+ else
+ {
+ faceIDMap_.remove(id);
+ faceCounter_--;
+ }
+ }
+
+ return name;
+}
+
+
int
Engine::currentFontFirstUnicodeCharMap()
{
@@ -267,34 +310,28 @@ Engine::loadFont(int fontIndex,
update();
+ auto id = FaceID(fontIndex, faceIndex, namedInstanceIndex);
+
// search triplet (fontIndex, faceIndex, namedInstanceIndex)
- scaler_.face_id = reinterpret_cast<FTC_FaceID>
- (faceIDMap_.value(FaceID(fontIndex,
- faceIndex,
- namedInstanceIndex)));
+ scaler_.face_id = reinterpret_cast<FTC_FaceID>(faceIDMap_.value(id));
if (scaler_.face_id)
{
// found
if (!FTC_Manager_LookupSize(cacheManager_, &scaler_, &ftSize_))
numGlyphs = ftSize_->face->num_glyphs;
}
- else
+ else if (fontIndex >= 0)
{
// not found; try to load triplet
// (fontIndex, faceIndex, namedInstanceIndex)
scaler_.face_id = reinterpret_cast<FTC_FaceID>(faceCounter_);
- faceIDMap_.insert(FaceID(fontIndex,
- faceIndex,
- namedInstanceIndex),
- faceCounter_++);
+ faceIDMap_.insert(id, faceCounter_++);
if (!FTC_Manager_LookupSize(cacheManager_, &scaler_, &ftSize_))
numGlyphs = ftSize_->face->num_glyphs;
else
{
- faceIDMap_.remove(FaceID(fontIndex,
- faceIndex,
- namedInstanceIndex));
+ faceIDMap_.remove(id);
faceCounter_--;
}
}
diff --git a/src/ftinspect/engine/engine.hpp b/src/ftinspect/engine/engine.hpp
index 2d89647..f4bff2d 100644
--- a/src/ftinspect/engine/engine.hpp
+++ b/src/ftinspect/engine/engine.hpp
@@ -107,17 +107,22 @@ public:
FT_Library ftLibrary() const { return library_; }
FTC_Manager cacheManager() { return cacheManager_; }
+
int dpi() { return dpi_; }
double pointSize() { return pointSize_; }
+
+ int numberOfOpenedFonts();
int currentFontType() const { return fontType_; }
const QString& currentFamilyName() { return curFamilyName_; }
const QString& currentStyleName() { return curStyleName_; }
int currentFontNumberOfGlyphs() { return curNumGlyphs_; }
- int numberOfOpenedFonts();
+
QString glyphName(int glyphIndex);
long numberOfFaces(int fontIndex);
int numberOfNamedInstances(int fontIndex,
long faceIndex);
+ QString namedInstanceName(int fontIndex, long faceIndex, int index);
+
int currentFontFirstUnicodeCharMap();
// Note: the current font face must be properly set
unsigned glyphIndexFromCharCode(int code, int charMapIndex);
diff --git a/src/ftinspect/engine/fontfilemanager.cpp
b/src/ftinspect/engine/fontfilemanager.cpp
index 9931430..c7f4861 100644
--- a/src/ftinspect/engine/fontfilemanager.cpp
+++ b/src/ftinspect/engine/fontfilemanager.cpp
@@ -32,6 +32,7 @@ FontFileManager::append(QStringList newFileNames)
for (auto& name : newFileNames)
{
auto info = QFileInfo(name);
+ info.setCaching(false);
// Filter non-file elements
if (!info.isFile())
diff --git a/src/ftinspect/ftinspect.cpp b/src/ftinspect/ftinspect.cpp
index 128dff4..4060f9c 100644
--- a/src/ftinspect/ftinspect.cpp
+++ b/src/ftinspect/ftinspect.cpp
@@ -24,8 +24,6 @@ main(int argc,
Engine engine;
MainGUI gui(&engine);
- gui.setDefaults();
-
gui.show();
return app.exec();
diff --git a/src/ftinspect/maingui.cpp b/src/ftinspect/maingui.cpp
index ab825ad..1fc93a7 100644
--- a/src/ftinspect/maingui.cpp
+++ b/src/ftinspect/maingui.cpp
@@ -25,7 +25,6 @@ MainGUI::MainGUI(Engine* engine)
createConnections();
createActions();
createMenus();
- createStatusBar();
setupDragDrop();
readSettings();
@@ -132,103 +131,13 @@ MainGUI::openFonts(QStringList const& fileNames)
int oldSize = engine_->numberOfOpenedFonts();
engine_->openFonts(fileNames);
- // if we have new fonts, set the current index to the first new one
- if (oldSize < engine_->numberOfOpenedFonts())
- currentFontIndex_ = oldSize;
-
- showFont();
-}
-
-
-void
-MainGUI::closeFont()
-{
- if (currentFontIndex_ < engine_->numberOfOpenedFonts())
- {
- engine_->removeFont(currentFontIndex_);
- }
-
- // show next font after deletion, i.e., retain index if possible
- int num = engine_->numberOfOpenedFonts();
- if (num)
- {
- if (currentFontIndex_ >= num)
- currentFontIndex_ = num - 1;
- }
- else
- currentFontIndex_ = 0;
-
- showFont();
-}
-
-
-void
-MainGUI::watchCurrentFont()
-{
- showFont();
+ tripletSelector_->repopulateFonts();
}
void
-MainGUI::showFont()
+MainGUI::onTripletChanged()
{
- // we do lazy computation of FT_Face objects
-
- if (currentFontIndex_ < engine_->numberOfOpenedFonts())
- {
- QFileInfo& fileInfo = engine_->fontFileManager()[currentFontIndex_];
- QString fontName = fileInfo.fileName();
-
- engine_->fontFileManager().updateWatching(currentFontIndex_);
- if (fileInfo.isSymLink())
- {
- fontName.prepend("<i>");
- fontName.append("</i>");
- }
-
- if (!fileInfo.exists())
- {
- // On Unix-like systems, the symlink's target gets opened; this
- // implies that deletion of a symlink doesn't make `engine->loadFont'
- // fail since it operates on a file handle pointing to the target.
- // For this reason, we remove the font to enforce a reload.
- engine_->removeFont(currentFontIndex_, false);
- }
-
- fontFilenameLabel_->setText(fontName);
- }
- else
- fontFilenameLabel_->clear();
-
- syncSettings();
- currentNumberOfFaces_
- = engine_->numberOfFaces(currentFontIndex_);
- currentNumberOfNamedInstances_
- = engine_->numberOfNamedInstances(currentFontIndex_,
- currentFaceIndex_);
- currentNumberOfGlyphs_
- = engine_->loadFont(currentFontIndex_,
- currentFaceIndex_,
- currentNamedInstanceIndex_);
-
- if (currentNumberOfGlyphs_ < 0)
- {
- // there might be various reasons why the current
- // (file, face, instance) triplet is invalid or missing;
- // we thus start our timer to periodically test
- // whether the font starts working
- if (currentFontIndex_ > 0
- && currentFontIndex_ < engine_->numberOfOpenedFonts())
- engine_->fontFileManager().timerStart();
- }
-
- fontNameLabel_->setText(QString("%1 %2")
- .arg(engine_->currentFamilyName())
- .arg(engine_->currentStyleName()));
-
- checkCurrentFontIndex();
- checkCurrentFaceIndex();
- checkCurrentNamedInstanceIndex();
auto state = settingPanel_->blockSignals(true);
settingPanel_->checkHinting();
settingPanel_->blockSignals(state);
@@ -247,6 +156,7 @@ MainGUI::repaintCurrentTab()
void
MainGUI::reloadCurrentTabFont()
{
+ syncSettings();
tabs_[tabWidget_->currentIndex()]->reloadFont();
}
@@ -258,180 +168,17 @@ MainGUI::syncSettings()
}
-void
-MainGUI::clearStatusBar()
-{
- statusBar()->clearMessage();
- statusBar()->setStyleSheet("");
-}
-
-
-void
-MainGUI::checkCurrentFontIndex()
-{
- if (engine_->numberOfOpenedFonts() < 2)
- {
- previousFontButton_->setEnabled(false);
- nextFontButton_->setEnabled(false);
- }
- else if (currentFontIndex_ == 0)
- {
- previousFontButton_->setEnabled(false);
- nextFontButton_->setEnabled(true);
- }
- else if (currentFontIndex_ >= engine_->numberOfOpenedFonts() - 1)
- {
- previousFontButton_->setEnabled(true);
- nextFontButton_->setEnabled(false);
- }
- else
- {
- previousFontButton_->setEnabled(true);
- nextFontButton_->setEnabled(true);
- }
-}
-
-
-void
-MainGUI::checkCurrentFaceIndex()
-{
- if (currentNumberOfFaces_ < 2)
- {
- previousFaceButton_->setEnabled(false);
- nextFaceButton_->setEnabled(false);
- }
- else if (currentFaceIndex_ == 0)
- {
- previousFaceButton_->setEnabled(false);
- nextFaceButton_->setEnabled(true);
- }
- else if (currentFaceIndex_ >= currentNumberOfFaces_ - 1)
- {
- previousFaceButton_->setEnabled(true);
- nextFaceButton_->setEnabled(false);
- }
- else
- {
- previousFaceButton_->setEnabled(true);
- nextFaceButton_->setEnabled(true);
- }
-}
-
-
-void
-MainGUI::checkCurrentNamedInstanceIndex()
-{
- if (currentNumberOfNamedInstances_ < 2)
- {
- previousNamedInstanceButton_->setEnabled(false);
- nextNamedInstanceButton_->setEnabled(false);
- }
- else if (currentNamedInstanceIndex_ == 0)
- {
- previousNamedInstanceButton_->setEnabled(false);
- nextNamedInstanceButton_->setEnabled(true);
- }
- else if (currentNamedInstanceIndex_ >= currentNumberOfNamedInstances_ - 1)
- {
- previousNamedInstanceButton_->setEnabled(true);
- nextNamedInstanceButton_->setEnabled(false);
- }
- else
- {
- previousNamedInstanceButton_->setEnabled(true);
- nextNamedInstanceButton_->setEnabled(true);
- }
-}
-
-
-void
-MainGUI::previousFont()
-{
- if (currentFontIndex_ > 0)
- {
- currentFontIndex_--;
- currentFaceIndex_ = 0;
- currentNamedInstanceIndex_ = 0;
- showFont();
- }
-}
-
-
-void
-MainGUI::nextFont()
-{
- if (currentFontIndex_ < engine_->numberOfOpenedFonts() - 1)
- {
- currentFontIndex_++;
- currentFaceIndex_ = 0;
- currentNamedInstanceIndex_ = 0;
- showFont();
- }
-}
-
-
-void
-MainGUI::previousFace()
-{
- if (currentFaceIndex_ > 0)
- {
- currentFaceIndex_--;
- currentNamedInstanceIndex_ = 0;
- showFont();
- }
-}
-
-
-void
-MainGUI::nextFace()
-{
- if (currentFaceIndex_ < currentNumberOfFaces_ - 1)
- {
- currentFaceIndex_++;
- currentNamedInstanceIndex_ = 0;
- showFont();
- }
-}
-
-
-void
-MainGUI::previousNamedInstance()
-{
- if (currentNamedInstanceIndex_ > 0)
- {
- currentNamedInstanceIndex_--;
- showFont();
- }
-}
-
-
-void
-MainGUI::nextNamedInstance()
-{
- if (currentNamedInstanceIndex_ < currentNumberOfNamedInstances_ - 1)
- {
- currentNamedInstanceIndex_++;
- showFont();
- }
-}
-
-
// XXX distances are specified in pixels,
// making the layout dependent on the output device resolution
void
MainGUI::createLayout()
{
// left side
- fontFilenameLabel_ = new QLabel(this);
-
- infoLeftLayout_ = new QHBoxLayout;
- infoLeftLayout_->addWidget(fontFilenameLabel_);
-
settingPanel_ = new SettingPanel(this, engine_);
- leftLayout_ = new QVBoxLayout;
- leftLayout_->addLayout(infoLeftLayout_);
+ leftLayout_ = new QVBoxLayout; // The only point is to set a margin->remove?
leftLayout_->addWidget(settingPanel_);
+ leftLayout_->setContentsMargins(32, 32, 8, 16);
// we don't want to expand the left side horizontally;
// to change the policy we have to use a widget wrapper
@@ -446,8 +193,6 @@ MainGUI::createLayout()
leftWidget_->setSizePolicy(leftWidgetPolicy);
// right side
- fontNameLabel_ = new QLabel(this);
-
singularTab_ = new SingularTab(this, engine_);
continuousTab_ = new ContinuousTab(this, engine_);
@@ -458,43 +203,33 @@ MainGUI::createLayout()
tabWidget_->addTab(singularTab_, tr("Singular Grid View"));
tabs_.append(continuousTab_);
tabWidget_->addTab(continuousTab_, tr("Continuous View"));
-
- previousFontButton_ = new QPushButton(tr("Previous Font"), this);
- nextFontButton_ = new QPushButton(tr("Next Font"), this);
- previousFaceButton_ = new QPushButton(tr("Previous Face"), this);
- nextFaceButton_ = new QPushButton(tr("Next Face"), this);
- previousNamedInstanceButton_
- = new QPushButton(tr("Previous Named Instance"), this);
- nextNamedInstanceButton_ = new QPushButton(tr("Next Named Instance"), this);
-
- fontLayout = new QGridLayout;
- fontLayout->setColumnStretch(0, 2);
- fontLayout->addWidget(nextFontButton_, 0, 1);
- fontLayout->addWidget(previousFontButton_, 1, 1);
- fontLayout->setColumnStretch(2, 1);
- fontLayout->addWidget(nextFaceButton_, 0, 3);
- fontLayout->addWidget(previousFaceButton_, 1, 3);
- fontLayout->setColumnStretch(4, 1);
- fontLayout->addWidget(nextNamedInstanceButton_, 0, 5);
- fontLayout->addWidget(previousNamedInstanceButton_, 1, 5);
- fontLayout->setColumnStretch(6, 2);
+
+ tripletSelector_ = new TripletSelector(this, engine_);
rightLayout_ = new QVBoxLayout;
- rightLayout_->addWidget(fontNameLabel_);
- rightLayout_->addWidget(tabWidget_);
- rightLayout_->addLayout(fontLayout);
+ //rightLayout_->addWidget(fontNameLabel_);
+ rightLayout_->addWidget(tabWidget_); // same for `leftLayout_`: Remove?
+ rightLayout_->setContentsMargins(8, 32, 32, 16);
// for symmetry with the left side use a widget also
rightWidget_ = new QWidget(this);
rightWidget_->setLayout(rightLayout_);
// the whole thing
- ftinspectLayout_ = new QHBoxLayout;
- ftinspectLayout_->addWidget(leftWidget_);
- ftinspectLayout_->addWidget(rightWidget_);
+ mainPartLayout_ = new QHBoxLayout;
+ mainPartLayout_->addWidget(leftWidget_);
+ mainPartLayout_->addWidget(rightWidget_);
+
+ ftinspectLayout_ = new QVBoxLayout;
+ ftinspectLayout_->setSpacing(0);
+ ftinspectLayout_->addLayout(mainPartLayout_);
+ ftinspectLayout_->addWidget(tripletSelector_);
+ ftinspectLayout_->setContentsMargins(0, 0, 0, 0);
ftinspectWidget_ = new QWidget(this);
ftinspectWidget_->setLayout(ftinspectLayout_);
+
+ statusBar()->hide(); // remove the extra space
setCentralWidget(ftinspectWidget_);
setWindowTitle("ftinspect");
}
@@ -504,28 +239,15 @@ void
MainGUI::createConnections()
{
connect(settingPanel_, &SettingPanel::fontReloadNeeded,
- this, &MainGUI::showFont);
+ this, &MainGUI::reloadCurrentTabFont);
connect(settingPanel_, &SettingPanel::repaintNeeded,
this, &MainGUI::repaintCurrentTab);
connect(tabWidget_, &QTabWidget::currentChanged,
this, &MainGUI::reloadCurrentTabFont);
- connect(previousFontButton_, &QPushButton::clicked,
- this, &MainGUI::previousFont);
- connect(nextFontButton_, &QPushButton::clicked,
- this, &MainGUI::nextFont);
- connect(previousFaceButton_, &QPushButton::clicked,
- this, &MainGUI::previousFace);
- connect(nextFaceButton_, &QPushButton::clicked,
- this, &MainGUI::nextFace);
- connect(previousNamedInstanceButton_, &QPushButton::clicked,
- this, &MainGUI::previousNamedInstance);
- connect(nextNamedInstanceButton_, &QPushButton::clicked,
- this, &MainGUI::nextNamedInstance);
-
- connect(&engine_->fontFileManager(), &FontFileManager::currentFileChanged,
- this, &MainGUI::watchCurrentFont);
+ connect(tripletSelector_, &TripletSelector::tripletChanged,
+ this, &MainGUI::onTripletChanged);
}
@@ -538,7 +260,8 @@ MainGUI::createActions()
closeFontAct_ = new QAction(tr("&Close Font"), this);
closeFontAct_->setShortcuts(QKeySequence::Close);
- connect(closeFontAct_, &QAction::triggered, this, &MainGUI::closeFont);
+ connect(closeFontAct_, &QAction::triggered,
+ tripletSelector_, &TripletSelector::closeCurrentFont);
exitAct_ = new QAction(tr("E&xit"), this);
exitAct_->setShortcuts(QKeySequence::Quit);
@@ -566,13 +289,6 @@ MainGUI::createMenus()
}
-void
-MainGUI::createStatusBar()
-{
- statusBar()->showMessage("");
-}
-
-
void
MainGUI::setupDragDrop()
{
@@ -580,20 +296,6 @@ MainGUI::setupDragDrop()
}
-void
-MainGUI::setDefaults()
-{
- // the next four values always non-negative
- currentFontIndex_ = 0;
- currentFaceIndex_ = 0;
- currentNamedInstanceIndex_ = 0;
-
- checkCurrentFontIndex();
- checkCurrentFaceIndex();
- checkCurrentNamedInstanceIndex();
-}
-
-
void
MainGUI::readSettings()
{
diff --git a/src/ftinspect/maingui.hpp b/src/ftinspect/maingui.hpp
index 8475f36..2d95332 100644
--- a/src/ftinspect/maingui.hpp
+++ b/src/ftinspect/maingui.hpp
@@ -6,9 +6,7 @@
#pragma once
#include "engine/engine.hpp"
-#include "widgets/customwidgets.hpp"
-#include "widgets/glyphindexselector.hpp"
-#include "models/customcomboboxmodels.hpp"
+#include "widgets/tripletselector.hpp"
#include "panels/settingpanel.hpp"
#include "panels/singular.hpp"
#include "panels/continuous.hpp"
@@ -53,8 +51,6 @@ public:
MainGUI(Engine* engine);
~MainGUI() override;
- void setDefaults();
-
friend class Engine;
friend FT_Error faceRequester(FTC_FaceID,
FT_Library,
@@ -69,33 +65,14 @@ protected:
private slots:
void about();
void aboutQt();
- void checkCurrentFaceIndex();
- void checkCurrentFontIndex();
- void checkCurrentNamedInstanceIndex();
- void closeFont();
- void showFont();
void repaintCurrentTab();
void reloadCurrentTabFont();
void loadFonts();
- void nextFace();
- void nextFont();
- void nextNamedInstance();
- void previousFace();
- void previousFont();
- void previousNamedInstance();
- void watchCurrentFont();
+ void onTripletChanged();
private:
Engine* engine_;
- int currentFontIndex_;
-
- long currentNumberOfFaces_;
- long currentFaceIndex_;
-
- int currentNumberOfNamedInstances_;
- int currentNamedInstanceIndex_;
-
int currentNumberOfGlyphs_;
// layout related stuff
@@ -105,25 +82,15 @@ private:
QAction *exitAct_;
QAction *loadFontsAct_;
- QGridLayout *fontLayout;
-
- QHBoxLayout *ftinspectLayout_;
- QHBoxLayout *infoLeftLayout_;
-
- QLabel *fontFilenameLabel_;
- QLabel *fontNameLabel_;
+ QVBoxLayout *ftinspectLayout_;
+ QHBoxLayout *mainPartLayout_;
QLocale *locale_;
QMenu *menuFile_;
QMenu *menuHelp_;
-
- QPushButton *nextFaceButton_;
- QPushButton *nextFontButton_;
- QPushButton *nextNamedInstanceButton_;
- QPushButton *previousFaceButton_;
- QPushButton *previousFontButton_;
- QPushButton *previousNamedInstanceButton_;
+
+ TripletSelector* tripletSelector_;
QVBoxLayout *leftLayout_;
QVBoxLayout *rightLayout_;
@@ -142,13 +109,11 @@ private:
void openFonts(QStringList const& fileNames);
void syncSettings();
- void clearStatusBar();
void createActions();
void createConnections();
void createLayout();
void createMenus();
- void createStatusBar();
void setupDragDrop();
void readSettings();
diff --git a/src/ftinspect/meson.build b/src/ftinspect/meson.build
index 50a7a63..ed9a328 100644
--- a/src/ftinspect/meson.build
+++ b/src/ftinspect/meson.build
@@ -36,6 +36,7 @@ if qt5_dep.found()
'widgets/customwidgets.cpp',
'widgets/glyphindexselector.cpp',
'widgets/fontsizeselector.cpp',
+ 'widgets/tripletselector.cpp',
'models/customcomboboxmodels.cpp',
@@ -54,6 +55,7 @@ if qt5_dep.found()
'widgets/customwidgets.hpp',
'widgets/glyphindexselector.hpp',
'widgets/fontsizeselector.hpp',
+ 'widgets/tripletselector.hpp',
'rendering/glyphcontinuous.hpp',
'models/customcomboboxmodels.hpp',
'panels/settingpanel.hpp',
diff --git a/src/ftinspect/panels/settingpanel.cpp
b/src/ftinspect/panels/settingpanel.cpp
index 7825e10..6eeec70 100644
--- a/src/ftinspect/panels/settingpanel.cpp
+++ b/src/ftinspect/panels/settingpanel.cpp
@@ -358,6 +358,8 @@ SettingPanel::createLayout()
mainLayout_ = new QVBoxLayout;
mainLayout_->addWidget(tab_);
setLayout(mainLayout_);
+ mainLayout_->setContentsMargins(0, 0, 0, 0);
+ setContentsMargins(0, 0, 0, 0);
}
diff --git a/src/ftinspect/widgets/tripletselector.cpp
b/src/ftinspect/widgets/tripletselector.cpp
new file mode 100644
index 0000000..6985027
--- /dev/null
+++ b/src/ftinspect/widgets/tripletselector.cpp
@@ -0,0 +1,474 @@
+// tripletselector.cpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#include "tripletselector.hpp"
+
+#include "../engine/engine.hpp"
+
+#include <functional>
+
+TripletSelector::TripletSelector(QWidget* parent,
+ Engine* engine)
+: QWidget(parent),
+ engine_(engine)
+{
+ createLayout();
+ createConnections();
+ checkButtons();
+}
+
+
+TripletSelector::~TripletSelector()
+{
+}
+
+
+void
+TripletSelector::repopulateFonts()
+{
+ auto oldSize = fontComboBox_->count();
+ auto oldIndex = fontComboBox_->currentIndex();
+
+ {
+ QSignalBlocker blk(fontComboBox_);
+ QSignalBlocker blk2(faceComboBox_);
+ QSignalBlocker blk3(niComboBox_);
+ fontComboBox_->clear();
+
+ auto& ffm = engine_->fontFileManager();
+ auto newSize = ffm.size();
+ for (int i = 0; i < newSize; i++)
+ {
+ auto& info = ffm[i];
+ auto name = info.filePath();
+ auto displayName = info.fileName();
+ if (info.isSymbolicLink())
+ displayName += " [symlink]";
+
+ fontComboBox_->addItem(displayName, name);
+ }
+
+ if (newSize > oldSize)
+ {
+ // if we have new fonts, set the current index to the first new one
+ fontComboBox_->setCurrentIndex(oldSize);
+ }
+ else if (newSize < oldSize)
+ {
+ if (oldIndex >= newSize)
+ oldIndex = newSize - 1;
+ if (oldIndex < 0)
+ oldIndex = -1;
+ fontComboBox_->setCurrentIndex(oldIndex);
+ }
+
+ // Note no signal will be emitted from any combobox until this block ends
+ }
+
+ // This will check buttons & reload the triplet
+ repopulateFaces();
+}
+
+
+void
+TripletSelector::repopulateFaces(bool fontSwitched)
+{
+ // Avoid unnecessary recreating, to reduce interruption of user oper
+ auto needToRecreate = fontSwitched;
+ auto oldSize = faceComboBox_->count();
+
+ auto fontIndex = fontComboBox_->currentIndex();
+ auto newSize = engine_->numberOfFaces(fontIndex);
+
+ if (fontIndex < 0 || newSize < 0)
+ {
+ // Clear and go
+ faceComboBox_->clear();
+ repopulateNamedInstances(fontSwitched);
+ return;
+ }
+
+ if (newSize != oldSize)
+ needToRecreate = true;
+
+ std::vector<QString> newFaces;
+ newFaces.reserve(newSize);
+ for (long i = 0; i < newSize; i++)
+ {
+ newFaces.emplace_back(engine_->namedInstanceName(fontIndex, i, 0));
+ if (!needToRecreate && newFaces[i] != faceComboBox_->itemData(i))
+ needToRecreate = true;
+ }
+
+ if (!needToRecreate)
+ {
+ // no need to refersh the combobox
+ repopulateNamedInstances(fontSwitched);
+ return;
+ }
+
+ {
+ QSignalBlocker blk2(faceComboBox_);
+ QSignalBlocker blk3(niComboBox_);
+ faceComboBox_->clear();
+
+ for (long i = 0; i < newSize; i++)
+ {
+ auto& name = newFaces[i];
+ auto displayName = QString("%1: %2").arg(i).arg(name);
+ faceComboBox_->addItem(displayName, name);
+ }
+
+ faceComboBox_->setCurrentIndex(0);
+ // Note no signal will be emitted from any combobox until this block ends
+ }
+
+ // This will check buttons & reload the triplet
+ repopulateNamedInstances(true);
+}
+
+
+void
+TripletSelector::repopulateNamedInstances(bool fontSwitched)
+{
+ // Avoid unnecessary recreating, to reduce interruption of user oper
+ // Similar to `repopulateFaces`
+ auto needToRecreate = fontSwitched;
+ auto oldSize = niComboBox_->count();
+
+ auto fontIndex = fontComboBox_->currentIndex();
+ auto faceIndex = faceComboBox_->currentIndex();
+ auto newSize = engine_->numberOfNamedInstances(fontIndex, faceIndex);
+
+ if (fontIndex < 0 || faceIndex < 0 || newSize < 0)
+ {
+ // Clear and go
+ niComboBox_->clear();
+ checkButtons();
+ loadTriplet();
+ return;
+ }
+
+ if (newSize != oldSize)
+ needToRecreate = true;
+
+ std::vector<QString> newFaces;
+ newFaces.reserve(newSize);
+ for (long i = 0; i < newSize; i++)
+ {
+ newFaces.emplace_back(engine_->namedInstanceName(fontIndex, faceIndex, i));
+ if (!needToRecreate && newFaces[i] != niComboBox_->itemData(i))
+ needToRecreate = true;
+ }
+
+ niComboBox_->setEnabled(newSize > 1);
+
+ if (!needToRecreate)
+ {
+ // no need to refersh the combobox
+ checkButtons();
+ loadTriplet();
+ return;
+ }
+
+ {
+ QSignalBlocker blk3(niComboBox_);
+ niComboBox_->clear();
+
+ for (long i = 0; i < newSize; i++)
+ {
+ auto& name = newFaces[i];
+ auto displayName = QString("%1: %2").arg(i).arg(name);
+ if (i == 0)
+ displayName = "* " + displayName;
+ niComboBox_->addItem(displayName, name);
+ }
+
+ niComboBox_->setCurrentIndex(0);
+ // Note no signal will be emitted from any combobox until this block ends
+ }
+
+ checkButtons();
+ loadTriplet();
+}
+
+
+void
+TripletSelector::closeCurrentFont()
+{
+ auto idx = fontComboBox_->currentIndex();
+ if (idx < 0)
+ return;
+ engine_->fontFileManager().remove(idx);
+
+ // show next font after deletion, i.e., retain index if possible
+ int num = engine_->numberOfOpenedFonts();
+ if (num)
+ {
+ if (idx >= num)
+ idx = num - 1;
+ }
+ else
+ idx = -1;
+
+ {
+ // Shut up when repopulating
+ QSignalBlocker blockerThis(this);
+ QSignalBlocker blockerComboBox(fontComboBox_);
+ repopulateFonts();
+ }
+
+ if (idx != -1)
+ faceComboBox_->setCurrentIndex(idx);
+ updateFont();
+}
+
+
+void
+TripletSelector::updateFont()
+{
+ auto idx = fontComboBox_->currentIndex();
+ auto num = engine_->numberOfOpenedFonts();
+ if (idx < 0)
+ {
+ faceComboBox_->clear();
+ niComboBox_->clear();
+
+ checkButtons();
+ loadTriplet();
+ return;
+ }
+
+ if (num <= 0 || idx >= num)
+ {
+ // out of sync: this shouldn't happen
+ repopulateFonts();
+ return;
+ }
+
+ // This will check buttons & reload the triplet
+ repopulateFaces();
+}
+
+
+void
+TripletSelector::updateFace()
+{
+ auto idx = faceComboBox_->currentIndex();
+ auto num = engine_->numberOfFaces(fontComboBox_->currentIndex());
+
+ if (idx >= num)
+ {
+ // out of sync
+ repopulateFaces();
+ return;
+ }
+
+ // This will check buttons & reload the triplet
+ repopulateNamedInstances();
+}
+
+
+void
+TripletSelector::updateNI()
+{
+ auto idx = niComboBox_->currentIndex();
+ auto num = engine_->numberOfNamedInstances(fontComboBox_->currentIndex(),
+ faceComboBox_->currentIndex());
+
+ if (idx >= num)
+ {
+ // out of sync
+ repopulateNamedInstances();
+ return;
+ }
+
+ checkButtons();
+ loadTriplet();
+}
+
+
+void
+TripletSelector::checkButtons()
+{
+ fontUpButton_->setEnabled(fontComboBox_->currentIndex() > 0);
+ fontDownButton_->setEnabled(fontComboBox_->currentIndex()
+ < fontComboBox_->count() - 1);
+ closeFontButton_->setEnabled(faceComboBox_->currentIndex() >= 0);
+
+ faceUpButton_->setEnabled(faceComboBox_->currentIndex() > 0);
+ faceDownButton_->setEnabled(faceComboBox_->currentIndex()
+ < faceComboBox_->count() - 1);
+
+ niUpButton_->setEnabled(niComboBox_->currentIndex() > 0);
+ niDownButton_->setEnabled(niComboBox_->currentIndex()
+ < niComboBox_->count() - 1);
+}
+
+
+void
+TripletSelector::watchCurrentFont()
+{
+ repopulateFaces(false);
+}
+
+
+void
+TripletSelector::createLayout()
+{
+ fontComboBox_ = new QComboBox(this);
+ faceComboBox_ = new QComboBox(this);
+ niComboBox_ = new QComboBox(this);
+
+ fontComboBox_->setPlaceholderText(tr("No font open"));
+ faceComboBox_->setPlaceholderText(tr("No face available"));
+ niComboBox_->setPlaceholderText(tr("No named instance available"));
+
+ closeFontButton_ = new QToolButton(this);
+ fontUpButton_ = new QToolButton(this);
+ faceUpButton_ = new QToolButton(this);
+ niUpButton_ = new QToolButton(this);
+ fontDownButton_ = new QToolButton(this);
+ faceDownButton_ = new QToolButton(this);
+ niDownButton_ = new QToolButton(this);
+
+ closeFontButton_->setText(tr("Close"));
+ fontUpButton_ ->setText(tr("\xE2\x86\x91"));
+ faceUpButton_ ->setText(tr("\xE2\x86\x91"));
+ niUpButton_ ->setText(tr("\xE2\x86\x91"));
+ fontDownButton_ ->setText(tr("\xE2\x86\x93"));
+ faceDownButton_ ->setText(tr("\xE2\x86\x93"));
+ niDownButton_ ->setText(tr("\xE2\x86\x93"));
+
+ fontComboBox_ ->setSizePolicy(QSizePolicy::Minimum,
QSizePolicy::Expanding);
+ faceComboBox_ ->setSizePolicy(QSizePolicy::Minimum,
QSizePolicy::Expanding);
+ niComboBox_ ->setSizePolicy(QSizePolicy::Minimum,
QSizePolicy::Expanding);
+ closeFontButton_->setSizePolicy(QSizePolicy::Maximum,
QSizePolicy::Expanding);
+ fontUpButton_ ->setFixedSize(30, 30);
+ faceUpButton_ ->setFixedSize(30, 30);
+ niUpButton_ ->setFixedSize(30, 30);
+ fontDownButton_ ->setFixedSize(30, 30);
+ faceDownButton_ ->setFixedSize(30, 30);
+ niDownButton_ ->setFixedSize(30, 30);
+
+ layout_ = new QHBoxLayout;
+ layout_->setSpacing(0);
+ layout_->setContentsMargins(0, 0, 0, 0);
+
+ layout_->addWidget(fontComboBox_);
+ layout_->addWidget(fontUpButton_);
+ layout_->addWidget(fontDownButton_);
+ layout_->addWidget(closeFontButton_);
+ layout_->addWidget(faceComboBox_);
+ layout_->addWidget(faceUpButton_);
+ layout_->addWidget(faceDownButton_);
+ layout_->addWidget(niComboBox_);
+ layout_->addWidget(niUpButton_);
+ layout_->addWidget(niDownButton_);
+
+ setFixedHeight(30);
+ setLayout(layout_);
+ layout_->setContentsMargins(0, 0, 0, 0);
+}
+
+
+void
+TripletSelector::createConnections()
+{
+ connect(fontComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &TripletSelector::updateFont);
+ connect(faceComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &TripletSelector::updateFace);
+ connect(niComboBox_, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ this, &TripletSelector::updateNI);
+
+ connect(closeFontButton_, &QToolButton::clicked,
+ this, &TripletSelector::closeCurrentFont);
+ connect(fontUpButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::previousComboBoxItem, fontComboBox_));
+ connect(faceUpButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::previousComboBoxItem, faceComboBox_));
+ connect(niUpButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::previousComboBoxItem, niComboBox_));
+ connect(fontDownButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::nextComboBoxItem, fontComboBox_));
+ connect(faceDownButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::nextComboBoxItem, faceComboBox_));
+ connect(niDownButton_ , &QToolButton::clicked,
+ this,
+ std::bind(&TripletSelector::nextComboBoxItem, niComboBox_));
+
+ connect(&engine_->fontFileManager(), &FontFileManager::currentFileChanged,
+ this, &TripletSelector::watchCurrentFont);
+}
+
+
+
+void
+TripletSelector::loadTriplet()
+{
+ // we do lazy computation of FT_Face objects
+
+ // TODO really?
+ auto fontIndex = fontComboBox_->currentIndex();
+ auto faceIndex = faceComboBox_->currentIndex();
+ auto instanceIndex = niComboBox_->currentIndex();
+
+ if (fontIndex >= 0 && fontIndex < engine_->numberOfOpenedFonts())
+ {
+ QFileInfo& fileInfo = engine_->fontFileManager()[fontIndex];
+ engine_->fontFileManager().updateWatching(fontIndex);
+
+ if (!fileInfo.exists())
+ {
+ // On Unix-like systems, the symlink's target gets opened; this
+ // implies that deletion of a symlink doesn't make `engine->loadFont'
+ // fail since it operates on a file handle pointing to the target.
+ // For this reason, we remove the font to enforce a reload.
+ engine_->removeFont(fontIndex, false);
+ }
+ }
+
+ auto number = engine_->loadFont(fontIndex, faceIndex, instanceIndex);
+
+ if (number < 0)
+ {
+ // there might be various reasons why the current
+ // (file, face, instance) triplet is invalid or missing;
+ // we thus start our timer to periodically test
+ // whether the font starts working
+ if (faceIndex >= 0 && faceIndex < engine_->numberOfOpenedFonts())
+ engine_->fontFileManager().timerStart();
+ }
+
+ emit tripletChanged();
+}
+
+
+void
+TripletSelector::nextComboBoxItem(QComboBox* c)
+{
+ if (c->currentIndex() < 0 || c->currentIndex() >= c->count() - 1)
+ return;
+ // No need to handle further steps, the event handler will take care of these
+ c->setCurrentIndex(c->currentIndex() + 1);
+}
+
+
+void
+TripletSelector::previousComboBoxItem(QComboBox* c)
+{
+ if (c->currentIndex() <= 0)
+ return;
+ // No need to handle further steps, the event handler will take care of these
+ c->setCurrentIndex(c->currentIndex() - 1);
+}
+
+
+// end of tripletselector.cpp
diff --git a/src/ftinspect/widgets/tripletselector.hpp
b/src/ftinspect/widgets/tripletselector.hpp
new file mode 100644
index 0000000..1c0c603
--- /dev/null
+++ b/src/ftinspect/widgets/tripletselector.hpp
@@ -0,0 +1,66 @@
+// QPushButton.hpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#pragma once
+
+#include <vector>
+#include <QWidget>
+#include <QComboBox>
+#include <QPushButton>
+#include <QToolButton>
+#include <QBoxLayout>
+
+class Engine;
+class TripletSelector
+: public QWidget
+{
+ Q_OBJECT
+
+public:
+ TripletSelector(QWidget* parent,
+ Engine* engine);
+ ~TripletSelector() override;
+
+ void repopulateFonts();
+ void repopulateFaces(bool fontSwitched = true);
+ void repopulateNamedInstances(bool fontSwitched = true);
+ void closeCurrentFont();
+ void updateFont();
+ void updateFace();
+ void updateNI();
+ void loadTriplet();
+
+signals:
+ void tripletChanged();
+
+private:
+ Engine* engine_;
+
+ QComboBox* fontComboBox_;
+ QComboBox* faceComboBox_;
+ QComboBox* niComboBox_;
+
+ QToolButton* closeFontButton_;
+
+ QToolButton* fontUpButton_;
+ QToolButton* fontDownButton_;
+ QToolButton* faceUpButton_;
+ QToolButton* faceDownButton_;
+ QToolButton* niUpButton_;
+ QToolButton* niDownButton_;
+
+ QHBoxLayout* layout_;
+
+ void checkButtons();
+ void watchCurrentFont();
+
+ void createLayout();
+ void createConnections();
+
+ static void nextComboBoxItem(QComboBox* c);
+ static void previousComboBoxItem(QComboBox* c);
+};
+
+
+// end of QPushButton.hpp
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2-demos] gsoc-2022-chariri-3 b6b79a8 27/36: [ftinspect] Improve Font/Face/NI selector.,
Werner Lemberg <=