[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[freetype2-demos] master 8969c8a 24/41: [ftinspect] Add left/right click
From: |
Werner Lemberg |
Subject: |
[freetype2-demos] master 8969c8a 24/41: [ftinspect] Add left/right click behaviour to the continuous view. |
Date: |
Mon, 3 Oct 2022 11:27:02 -0400 (EDT) |
branch: master
commit 8969c8a24a9d576a3ce8295010390ea41b4d85bc
Author: Charlie Jiang <w@chariri.moe>
Commit: Werner Lemberg <wl@gnu.org>
[ftinspect] Add left/right click behaviour to the continuous view.
Left clicking will open the glyph details pane, and right clicking will
switch to the singular tab.
* src/ftinspect/panels/glyphdetails.cpp,
src/ftinspect/panels/glyphdetails.hpp:
New files, add the `GlyphDetails` class.
* src/ftinspect/glyphcomponents/glyphcontinuous.cpp,
src/ftinspect/glyphcomponents/glyphcontinuous.hpp:
Add `mouseReleaseEvent` event handler which emits the new
`updateGlyphDetails` and `rightClickGlyph` signals.
* src/ftinspect/glyphcomponents/glyphbitmap.cpp,
src/ftinspect/glyphcomponents/glyphbitmap.hpp:
Add `GlyphBitmapWidget` to show the enlarged bitmap.
* src/ftinspect/panels/continuous.cpp, src/ftinspect/panels/continuous.hpp:
Add code to update the details panel, and wire up events.
* src/ftinspect/maingui.cpp, src/ftinspect/maingui.hpp:
Add code to initialize the glyph details panel, and wire up components and
events.
* src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
---
src/ftinspect/CMakeLists.txt | 1 +
src/ftinspect/glyphcomponents/glyphbitmap.cpp | 82 +++++++
src/ftinspect/glyphcomponents/glyphbitmap.hpp | 26 ++
src/ftinspect/glyphcomponents/glyphcontinuous.cpp | 25 ++
src/ftinspect/glyphcomponents/glyphcontinuous.hpp | 3 +
src/ftinspect/maingui.cpp | 38 ++-
src/ftinspect/maingui.hpp | 6 +
src/ftinspect/meson.build | 3 +
src/ftinspect/panels/continuous.cpp | 27 ++-
src/ftinspect/panels/continuous.hpp | 15 +-
src/ftinspect/panels/glyphdetails.cpp | 274 ++++++++++++++++++++++
src/ftinspect/panels/glyphdetails.hpp | 94 ++++++++
12 files changed, 590 insertions(+), 4 deletions(-)
diff --git a/src/ftinspect/CMakeLists.txt b/src/ftinspect/CMakeLists.txt
index 098f331..ace3301 100644
--- a/src/ftinspect/CMakeLists.txt
+++ b/src/ftinspect/CMakeLists.txt
@@ -49,6 +49,7 @@ add_executable(ftinspect
"panels/settingpanelmmgx.cpp"
"panels/singular.cpp"
"panels/continuous.cpp"
+ "panels/glyphdetails.cpp"
)
target_link_libraries(ftinspect
Qt5::Core Qt5::Widgets
diff --git a/src/ftinspect/glyphcomponents/glyphbitmap.cpp
b/src/ftinspect/glyphcomponents/glyphbitmap.cpp
index a25b5a1..90a0b81 100644
--- a/src/ftinspect/glyphcomponents/glyphbitmap.cpp
+++ b/src/ftinspect/glyphcomponents/glyphbitmap.cpp
@@ -87,6 +87,88 @@ GlyphBitmap::paint(QPainter* painter,
qAlpha(p)));
}
#endif
+
+}
+
+
+GlyphBitmapWidget::GlyphBitmapWidget(QWidget* parent)
+: QWidget(parent)
+{
+ setToolTip(tr("Click to inspect in Singular Grid View."));
+}
+
+
+GlyphBitmapWidget::~GlyphBitmapWidget()
+{
+ delete bitmapItem_;
+ bitmapItem_ = NULL;
+}
+
+
+void
+GlyphBitmapWidget::updateImage(QImage* image,
+ QRect rect)
+{
+ rect.moveTop(0);
+ rect.moveLeft(0);
+
+ delete bitmapItem_;
+ auto* copied = new QImage(image->copy());
+ bitmapItem_ = new GlyphBitmap(copied, rect);
+
+ repaint();
+}
+
+
+void
+GlyphBitmapWidget::releaseImage()
+{
+ delete bitmapItem_;
+ bitmapItem_ = NULL;
+ repaint();
+}
+
+
+void
+GlyphBitmapWidget::paintEvent(QPaintEvent* event)
+{
+ if (!bitmapItem_)
+ return;
+ auto s = size();
+ auto br = bitmapItem_->boundingRect();
+ double xScale = s.width() / br.width();
+ double yScale = s.height() / br.height();
+ auto scale = std::min(xScale, yScale);
+
+ QPainter painter(this);
+ painter.fillRect(rect(), Qt::white);
+ painter.scale(scale, scale);
+
+ QStyleOptionGraphicsItem ogi;
+ ogi.exposedRect = br;
+ bitmapItem_->paint(&painter, &ogi, this);
+
+ double scaledLineWidth = 4 / scale;
+ painter.setPen(QPen(Qt::black, scaledLineWidth));
+ scaledLineWidth /= 2;
+ painter.drawRect(br.adjusted(scaledLineWidth, scaledLineWidth,
+ -scaledLineWidth, -scaledLineWidth));
+}
+
+
+QSize
+GlyphBitmapWidget::sizeHint() const
+{
+ return { 300, 300 };
+}
+
+
+void
+GlyphBitmapWidget::mouseReleaseEvent(QMouseEvent* event)
+{
+ QWidget::mouseReleaseEvent(event);
+ if (event->button() == Qt::LeftButton)
+ emit clicked();
}
diff --git a/src/ftinspect/glyphcomponents/glyphbitmap.hpp
b/src/ftinspect/glyphcomponents/glyphbitmap.hpp
index d2dafd7..52cfd22 100644
--- a/src/ftinspect/glyphcomponents/glyphbitmap.hpp
+++ b/src/ftinspect/glyphcomponents/glyphbitmap.hpp
@@ -39,4 +39,30 @@ private:
};
+// Sometimes we don't want a complicated QGraphicsView
+// for this kind of work...
+class GlyphBitmapWidget
+: public QWidget
+{
+ Q_OBJECT
+public:
+ GlyphBitmapWidget(QWidget* parent);
+ ~GlyphBitmapWidget() override;
+
+ void updateImage(QImage* image, QRect rect);
+ void releaseImage();
+
+signals:
+ void clicked();
+
+protected:
+ void paintEvent(QPaintEvent* event) override;
+ QSize sizeHint() const override;
+ void mouseReleaseEvent(QMouseEvent* event) override;
+
+private:
+ GlyphBitmap* bitmapItem_ = NULL;
+};
+
+
// end of glyphbitmap.hpp
diff --git a/src/ftinspect/glyphcomponents/glyphcontinuous.cpp
b/src/ftinspect/glyphcomponents/glyphcontinuous.cpp
index 37f7db5..ebdac27 100644
--- a/src/ftinspect/glyphcomponents/glyphcontinuous.cpp
+++ b/src/ftinspect/glyphcomponents/glyphcontinuous.cpp
@@ -220,6 +220,31 @@ GlyphContinuous::mouseMoveEvent(QMouseEvent* event)
}
+void
+GlyphContinuous::mouseReleaseEvent(QMouseEvent* event)
+{
+ if (!mouseOperationEnabled_)
+ return;
+ if (event->button() == Qt::LeftButton)
+ {
+ auto dist = event->pos() - mouseDownPostition_;
+ if (dist.manhattanLength() < ClickDragThreshold)
+ {
+ auto gl = findGlyphByMouse(event->pos(), NULL);
+ if (gl)
+ emit updateGlyphDetails(gl, stringRenderer_.charMapIndex(), true);
+ }
+ }
+ else if (event->button() == Qt::RightButton)
+ {
+ double size;
+ auto gl = findGlyphByMouse(event->pos(), &size);
+ if (gl)
+ emit rightClickGlyph(gl->glyphIndex, size);
+ }
+}
+
+
void
GlyphContinuous::paintByRenderer()
{
diff --git a/src/ftinspect/glyphcomponents/glyphcontinuous.hpp
b/src/ftinspect/glyphcomponents/glyphcontinuous.hpp
index 7366de9..87c822c 100644
--- a/src/ftinspect/glyphcomponents/glyphcontinuous.hpp
+++ b/src/ftinspect/glyphcomponents/glyphcontinuous.hpp
@@ -107,6 +107,8 @@ signals:
void wheelZoom(int steps);
void beginIndexChangeRequest(int newIndex);
void displayingCountUpdated(int newCount);
+ void rightClickGlyph(int glyphIndex, double sizePoint);
+ void updateGlyphDetails(GlyphCacheEntry* ctxt, int charMapIndex, bool open);
protected:
void paintEvent(QPaintEvent* event) override;
@@ -114,6 +116,7 @@ protected:
void resizeEvent(QResizeEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
+ void mouseReleaseEvent(QMouseEvent* event) override;
private:
Engine* engine_;
diff --git a/src/ftinspect/maingui.cpp b/src/ftinspect/maingui.cpp
index b4a38dc..c08e01a 100644
--- a/src/ftinspect/maingui.cpp
+++ b/src/ftinspect/maingui.cpp
@@ -175,6 +175,22 @@ MainGUI::switchTab()
}
+void
+MainGUI::switchToSingular(int glyphIndex,
+ double sizePoint)
+{
+ tabWidget_->setCurrentWidget(singularTab_); // this would update the tab
+ singularTab_->setCurrentGlyphAndSize(glyphIndex, sizePoint);
+}
+
+
+void
+MainGUI::closeDockWidget()
+{
+ glyphDetailsDockWidget_->hide();
+}
+
+
void
MainGUI::repaintCurrentTab()
{
@@ -206,6 +222,13 @@ MainGUI::applySettings()
void
MainGUI::createLayout()
{
+ // floating
+ glyphDetailsDockWidget_ = new QDockWidget(tr("Glyph Details"), this);
+ glyphDetails_ = new GlyphDetails(glyphDetailsDockWidget_, engine_);
+ glyphDetailsDockWidget_->setWidget(glyphDetails_);
+ glyphDetailsDockWidget_->setFloating(true);
+ glyphDetailsDockWidget_->hide();
+
// left side
settingPanel_ = new SettingPanel(this, engine_);
@@ -221,7 +244,8 @@ MainGUI::createLayout()
// right side
singularTab_ = new SingularTab(this, engine_);
- continuousTab_ = new ContinuousTab(this, engine_);
+ continuousTab_ = new ContinuousTab(this, engine_,
+ glyphDetailsDockWidget_, glyphDetails_);
tabWidget_ = new QTabWidget(this);
tabWidget_->setObjectName("mainTab"); // for stylesheet
@@ -287,6 +311,18 @@ MainGUI::createConnections()
connect(tripletSelector_, &TripletSelector::tripletChanged,
this, &MainGUI::onTripletChanged);
+
+ connect(continuousTab_, &ContinuousTab::switchToSingular,
+ this, &MainGUI::switchToSingular);
+ connect(glyphDetails_, &GlyphDetails::closeDockWidget,
+ this, &MainGUI::closeDockWidget);
+ connect(glyphDetails_, &GlyphDetails::switchToSingular,
+ [&] (int index)
+ {
+ switchToSingular(index, -1);
+ if (glyphDetailsDockWidget_->isFloating())
+ glyphDetailsDockWidget_->hide();
+ });
}
diff --git a/src/ftinspect/maingui.hpp b/src/ftinspect/maingui.hpp
index 44c6014..d375231 100644
--- a/src/ftinspect/maingui.hpp
+++ b/src/ftinspect/maingui.hpp
@@ -11,6 +11,7 @@
#include "panels/abstracttab.hpp"
#include "panels/singular.hpp"
#include "panels/continuous.hpp"
+#include "panels/glyphdetails.hpp"
#include <vector>
#include <QAction>
@@ -54,6 +55,8 @@ private slots:
void loadFonts();
void onTripletChanged();
void switchTab();
+ void switchToSingular(int glyphIndex, double sizePoint);
+ void closeDockWidget();
private:
Engine* engine_;
@@ -92,6 +95,9 @@ private:
ContinuousTab* continuousTab_;
QWidget* lastTab_ = NULL;
+ QDockWidget* glyphDetailsDockWidget_;
+ GlyphDetails* glyphDetails_;
+
void openFonts(QStringList const& fileNames);
void applySettings();
diff --git a/src/ftinspect/meson.build b/src/ftinspect/meson.build
index 392ec8a..9167e8b 100644
--- a/src/ftinspect/meson.build
+++ b/src/ftinspect/meson.build
@@ -50,6 +50,7 @@ if qt5_dep.found()
'panels/settingpanelmmgx.cpp',
'panels/singular.cpp',
'panels/continuous.cpp',
+ 'panels/glyphdetails.cpp',
'ftinspect.cpp',
'maingui.cpp',
@@ -59,6 +60,7 @@ if qt5_dep.found()
moc_files = qt5.preprocess(
moc_headers: [
'engine/fontfilemanager.hpp',
+ 'glyphcomponents/glyphbitmap.hpp',
'glyphcomponents/glyphcontinuous.hpp',
'widgets/customwidgets.hpp',
'widgets/tripletselector.hpp',
@@ -71,6 +73,7 @@ if qt5_dep.found()
'panels/settingpanelmmgx.hpp',
'panels/singular.hpp',
'panels/continuous.hpp',
+ 'panels/glyphdetails.hpp',
],
dependencies: qt5_dep)
diff --git a/src/ftinspect/panels/continuous.cpp
b/src/ftinspect/panels/continuous.cpp
index c10a7ef..ef52034 100644
--- a/src/ftinspect/panels/continuous.cpp
+++ b/src/ftinspect/panels/continuous.cpp
@@ -4,6 +4,7 @@
#include "continuous.hpp"
+#include "glyphdetails.hpp"
#include "../uihelper.hpp"
#include <climits>
@@ -12,9 +13,13 @@
ContinuousTab::ContinuousTab(QWidget* parent,
- Engine* engine)
+ Engine* engine,
+ QDockWidget* gdWidget,
+ GlyphDetails* glyphDetails)
: QWidget(parent),
- engine_(engine)
+ engine_(engine),
+ glyphDetailsWidget_(gdWidget),
+ glyphDetails_(glyphDetails)
{
createLayout();
@@ -228,6 +233,20 @@ ContinuousTab::reloadGlyphsAndRepaint()
}
+void
+ContinuousTab::updateGlyphDetails(GlyphCacheEntry* ctxt,
+ int charMapIndex,
+ bool open)
+{
+ glyphDetails_->updateGlyph(*ctxt, charMapIndex);
+ if (open)
+ {
+ glyphDetailsWidget_->show();
+ glyphDetailsWidget_->activateWindow();
+ }
+}
+
+
void
ContinuousTab::openWaterfallConfig()
{
@@ -467,8 +486,12 @@ ContinuousTab::createConnections()
this, &ContinuousTab::wheelZoom);
connect(canvas_, &GlyphContinuous::displayingCountUpdated,
indexSelector_, &GlyphIndexSelector::setShowingCount);
+ connect(canvas_, &GlyphContinuous::rightClickGlyph,
+ this, &ContinuousTab::switchToSingular);
connect(canvas_, &GlyphContinuous::beginIndexChangeRequest,
this, &ContinuousTab::setGlyphBeginindex);
+ connect(canvas_, &GlyphContinuous::updateGlyphDetails,
+ this, &ContinuousTab::updateGlyphDetails);
connect(indexSelector_, &GlyphIndexSelector::currentIndexChanged,
this, &ContinuousTab::repaintGlyph);
diff --git a/src/ftinspect/panels/continuous.hpp
b/src/ftinspect/panels/continuous.hpp
index deec32a..2daaa9f 100644
--- a/src/ftinspect/panels/continuous.hpp
+++ b/src/ftinspect/panels/continuous.hpp
@@ -22,15 +22,18 @@
#include <QGridLayout>
#include <QBoxLayout>
#include <QPlainTextEdit>
+#include <QDockWidget>
#include <QCheckBox>
+class GlyphDetails;
class WaterfallConfigDialog;
class ContinuousTab
: public QWidget, public AbstractTab
{
Q_OBJECT
public:
- ContinuousTab(QWidget* parent, Engine* engine);
+ ContinuousTab(QWidget* parent, Engine* engine,
+ QDockWidget* gdWidget, GlyphDetails* glyphDetails);
~ContinuousTab() override = default;
void repaintGlyph() override;
@@ -38,6 +41,10 @@ public:
void highlightGlyph(int index);
void applySettings();
+signals:
+ // if sizePoint <= 0, then don't change size.
+ void switchToSingular(int glyphIndex, double sizePoint);
+
protected:
bool eventFilter(QObject* watched, QEvent* event) override;
@@ -88,6 +95,9 @@ private:
QGridLayout* bottomLayout_;
QVBoxLayout* mainLayout_;
+ QDockWidget* glyphDetailsWidget_;
+ GlyphDetails* glyphDetails_;
+
WaterfallConfigDialog* wfConfigDialog_;
void createLayout();
@@ -106,6 +116,9 @@ private:
void sourceTextChanged();
void presetStringSelected();
void reloadGlyphsAndRepaint();
+ void updateGlyphDetails(GlyphCacheEntry* ctxt,
+ int charMapIndex,
+ bool open);
void openWaterfallConfig();
void showToolTip();
diff --git a/src/ftinspect/panels/glyphdetails.cpp
b/src/ftinspect/panels/glyphdetails.cpp
new file mode 100644
index 0000000..c412029
--- /dev/null
+++ b/src/ftinspect/panels/glyphdetails.cpp
@@ -0,0 +1,274 @@
+// glyphdetails.cpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#include "glyphdetails.hpp"
+
+#include "../engine/stringrenderer.hpp"
+#include "../glyphcomponents/glyphcontinuous.hpp"
+#include "../uihelper.hpp"
+#include "../engine/engine.hpp"
+
+
+GlyphDetails::GlyphDetails(QWidget* parent,
+ Engine* engine)
+: QWidget(parent),
+ engine_(engine)
+{
+ createLayout();
+ createConnections();
+}
+
+
+GlyphDetails::~GlyphDetails()
+{
+}
+
+
+void
+GlyphDetails::updateGlyph(GlyphCacheEntry& ctxt, int charMapIndex)
+{
+ auto& cMaps = engine_->currentFontCharMaps();
+
+ glyphIndex_ = ctxt.glyphIndex;
+ glyphIndexLabel_->setText(QString::number(ctxt.glyphIndex));
+ if (charMapIndex < 0 || static_cast<unsigned>(charMapIndex) >= cMaps.size())
+ {
+ charCodePromptLabel_->setVisible(false);
+ charCodeLabel_->setVisible(false);
+ }
+ else
+ {
+ charCodePromptLabel_->setVisible(true);
+ charCodeLabel_->setVisible(true);
+ charCodeLabel_->setText(
+ cMaps[charMapIndex].stringifyIndexShort(ctxt.charCode));
+ }
+
+ auto glyphName = engine_->glyphName(ctxt.glyphIndex);
+ if (glyphName.isEmpty())
+ glyphName = "(none)";
+ glyphNameLabel_->setText(glyphName);
+
+ auto rect = ctxt.basePosition.translated(-(ctxt.penPos.x()),
+ -(ctxt.penPos.y()));
+ bitmapWidget_->updateImage(ctxt.image, rect);
+
+ // load glyphs in all units
+ dpi_ = engine_->dpi();
+ engine_->reloadFont();
+
+ engine_->loadGlyphIntoSlotWithoutCache(ctxt.glyphIndex, true);
+ fontUnitMetrics_ = engine_->currentFaceSlot()->metrics;
+ engine_->loadGlyphIntoSlotWithoutCache(ctxt.glyphIndex, false);
+ pixelMetrics_ = engine_->currentFaceSlot()->metrics;
+
+ changeUnit(unitButtonGroup_->checkedId());
+
+ inkSizeLabel_->setText(QString("(%1, %2) px")
+ .arg(rect.width())
+ .arg(rect.height()));
+ bitmapOffsetLabel_->setText(QString("(%1, %2) px")
+ .arg(rect.x())
+ .arg(rect.y()));
+}
+
+
+void
+GlyphDetails::keyReleaseEvent(QKeyEvent* event)
+{
+ if (event->key() == Qt::Key_Escape)
+ emit closeDockWidget();
+ else
+ QWidget::keyReleaseEvent(event);
+}
+
+
+void
+GlyphDetails::createLayout()
+{
+ unitButtonGroup_ = new QButtonGroup(this);
+ fontUnitButton_ = new QRadioButton(tr("Font Unit"), this);
+ pointButton_ = new QRadioButton(tr("Point"), this);
+ pixelButton_ = new QRadioButton(tr("Pixel"), this);
+ unitButtonGroup_->addButton(fontUnitButton_, DU_FontUnit);
+ unitButtonGroup_->addButton(pointButton_, DU_Point);
+ unitButtonGroup_->addButton(pixelButton_, DU_Pixel);
+ fontUnitButton_->setChecked(true);
+
+ glyphIndexPromptLabel_ = new QLabel(tr("Grid Index:"), this);
+ charCodePromptLabel_ = new QLabel(tr("Char Code:"), this);
+ glyphNamePromptLabel_ = new QLabel(tr("Glyph Name:"), this);
+
+ bboxSizePromptLabel_ = new QLabel(tr("Bounding Box Size:"), this);
+ horiBearingPromptLabel_ = new QLabel(tr("Hori. Bearing:"), this);
+ horiAdvancePromptLabel_ = new QLabel(tr("Hori. Advance:"), this);
+ vertBearingPromptLabel_ = new QLabel(tr("Vert. Bearing:"), this);
+ vertAdvancePromptLabel_ = new QLabel(tr("Vert. Advance:"), this);
+
+ inkSizePromptLabel_ = new QLabel(tr("Ink Size:"), this);
+ bitmapOffsetPromptLabel_ = new QLabel(tr("Bitmap Offset:"), this);
+
+ glyphIndexLabel_ = new QLabel(this);
+ charCodeLabel_ = new QLabel(this);
+ glyphNameLabel_ = new QLabel(this);
+
+ bboxSizeLabel_ = new QLabel(this);
+ horiBearingLabel_ = new QLabel(this);
+ horiAdvanceLabel_ = new QLabel(this);
+ vertBearingLabel_ = new QLabel(this);
+ vertAdvanceLabel_ = new QLabel(this);
+
+ inkSizeLabel_ = new QLabel(this);
+ bitmapOffsetLabel_ = new QLabel(this);
+
+ bitmapWidget_ = new GlyphBitmapWidget(this);
+
+ setLabelSelectable(glyphIndexLabel_);
+ setLabelSelectable(charCodeLabel_);
+ setLabelSelectable(glyphNameLabel_);
+ setLabelSelectable(bboxSizeLabel_);
+ setLabelSelectable(horiBearingLabel_);
+ setLabelSelectable(horiAdvanceLabel_);
+ setLabelSelectable(vertBearingLabel_);
+ setLabelSelectable(vertAdvanceLabel_);
+ setLabelSelectable(inkSizeLabel_);
+ setLabelSelectable(bitmapOffsetLabel_);
+
+ // Tooltips
+ fontUnitButton_->setToolTip(tr("Unit for most metrics entries below"));
+ pointButton_ ->setToolTip(tr("Unit for most metrics entries below"));
+ pixelButton_ ->setToolTip(tr("Unit for most metrics entries below"));
+ bboxSizeLabel_->setToolTip(
+ tr("Glyph bounding box (in unit specified above)"));
+ horiBearingLabel_->setToolTip(
+ tr("Bearing for horizontal layout (in unit specified above)"));
+ horiAdvanceLabel_->setToolTip(
+ tr("Advance for horizontal layout (in unit specified above)"));
+ vertBearingLabel_->setToolTip(
+ tr("Bearing for vertical layout (in unit specified above)"));
+ vertAdvanceLabel_->setToolTip(
+ tr("Advance for vertical layout (in unit specified above)"));
+ inkSizeLabel_->setToolTip(
+ tr("The tightest bounding box size (always in pixels)"));
+ bitmapOffsetLabel_->setToolTip(
+ tr("Offset from the most top-left point to the bitmap (always in
pixels)"));
+ bitmapWidget_->setToolTip(tr("Bitmap preview"));
+
+ // Layouting
+ unitLayout_ = new QHBoxLayout;
+ unitLayout_->addWidget(fontUnitButton_);
+ unitLayout_->addWidget(pointButton_);
+ unitLayout_->addWidget(pixelButton_);
+
+ layout_ = new QGridLayout;
+ gridLayout2ColAddLayout(layout_, unitLayout_);
+ gridLayout2ColAddItem(layout_, new QSpacerItem(0, 18));
+
+ gridLayout2ColAddWidget(layout_, glyphIndexPromptLabel_, glyphIndexLabel_);
+ gridLayout2ColAddWidget(layout_, charCodePromptLabel_ , charCodeLabel_ );
+ gridLayout2ColAddWidget(layout_, glyphNamePromptLabel_ , glyphNameLabel_ );
+ gridLayout2ColAddItem(layout_, new QSpacerItem(0, 18));
+
+ gridLayout2ColAddWidget(layout_, bboxSizePromptLabel_, bboxSizeLabel_ );
+ gridLayout2ColAddWidget(layout_, horiBearingPromptLabel_, horiBearingLabel_);
+ gridLayout2ColAddWidget(layout_, horiAdvancePromptLabel_, horiAdvanceLabel_);
+ gridLayout2ColAddWidget(layout_, vertBearingPromptLabel_, vertBearingLabel_);
+ gridLayout2ColAddWidget(layout_, vertAdvancePromptLabel_, vertAdvanceLabel_);
+ gridLayout2ColAddItem(layout_, new QSpacerItem(0, 18));
+
+ gridLayout2ColAddWidget(layout_, inkSizePromptLabel_, inkSizeLabel_);
+ gridLayout2ColAddWidget(layout_, bitmapOffsetPromptLabel_,
+ bitmapOffsetLabel_);
+ gridLayout2ColAddItem(layout_, new QSpacerItem(0, 18));
+
+ auto bmapRowPos = gridLayout2ColAddWidget(layout_, bitmapWidget_);
+
+ layout_->setColumnStretch(1, 1);
+ layout_->setRowStretch(bmapRowPos, 1);
+
+ setLayout(layout_);
+ setContentsMargins(12, 12, 12, 12);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+
+void
+GlyphDetails::createConnections()
+{
+ connect(unitButtonGroup_, &QButtonGroup::idClicked,
+ this, &GlyphDetails::changeUnit);
+
+ connect(bitmapWidget_, &GlyphBitmapWidget::clicked,
+ this, &GlyphDetails::bitmapWidgetClicked);
+}
+
+
+void
+GlyphDetails::changeUnit(int unitId)
+{
+ QString unitSuffix;
+ double bboxW = -1, bboxH = -1;
+ double horiBearingX = -1, horiBearingY = -1;
+ double horiAdvance = -1;
+ double vertBearingX = -1, vertBearingY = -1;
+ double vertAdvance = -1;
+ switch (static_cast<DisplayUnit>(unitId))
+ {
+ case DU_FontUnit:
+ unitSuffix = "";
+ bboxW = fontUnitMetrics_.width;
+ bboxH = fontUnitMetrics_.height;
+ horiBearingX = fontUnitMetrics_.horiBearingX;
+ horiBearingY = fontUnitMetrics_.horiBearingY;
+ horiAdvance = fontUnitMetrics_.horiAdvance;
+ vertBearingX = fontUnitMetrics_.vertBearingX;
+ vertBearingY = fontUnitMetrics_.vertBearingY;
+ vertAdvance = fontUnitMetrics_.vertAdvance;
+ break;
+
+ case DU_Point:
+ unitSuffix = " pt";
+ // 1.125 = 72 / 64
+ bboxW = pixelMetrics_.width * 1.125 / dpi_;
+ bboxH = pixelMetrics_.height * 1.125 / dpi_;
+ horiBearingX = pixelMetrics_.horiBearingX * 1.125 / dpi_;
+ horiBearingY = pixelMetrics_.horiBearingY * 1.125 / dpi_;
+ horiAdvance = pixelMetrics_.horiAdvance * 1.125 / dpi_;
+ vertBearingX = pixelMetrics_.vertBearingX * 1.125 / dpi_;
+ vertBearingY = pixelMetrics_.vertBearingY * 1.125 / dpi_;
+ vertAdvance = pixelMetrics_.vertAdvance * 1.125 / dpi_;
+ break;
+
+ case DU_Pixel:
+ unitSuffix = " px";
+ bboxW = pixelMetrics_.width/ 64.0;
+ bboxH = pixelMetrics_.height/ 64.0;
+ horiBearingX = pixelMetrics_.horiBearingX/ 64.0;
+ horiBearingY = pixelMetrics_.horiBearingY/ 64.0;
+ horiAdvance = pixelMetrics_.horiAdvance/ 64.0;
+ vertBearingX = pixelMetrics_.vertBearingX/ 64.0;
+ vertBearingY = pixelMetrics_.vertBearingY/ 64.0;
+ vertAdvance = pixelMetrics_.vertAdvance/ 64.0;
+ break;
+ }
+
+ auto tmpl = QString("%1") + unitSuffix;
+ auto tmplPair = QString("(%1, %2)") + unitSuffix;
+ bboxSizeLabel_->setText(tmplPair.arg(bboxW).arg(bboxH));
+ horiBearingLabel_->setText(tmplPair.arg(horiBearingX).arg(horiBearingY));
+ horiAdvanceLabel_->setText(tmpl.arg(horiAdvance));
+ vertBearingLabel_->setText(tmplPair.arg(vertBearingX).arg(vertBearingY));
+ vertAdvanceLabel_->setText(tmpl.arg(vertAdvance));
+}
+
+
+void
+GlyphDetails::bitmapWidgetClicked()
+{
+ if (glyphIndex_ >= 0)
+ emit switchToSingular(glyphIndex_);
+}
+
+
+// end of glyphdetails.cpp
diff --git a/src/ftinspect/panels/glyphdetails.hpp
b/src/ftinspect/panels/glyphdetails.hpp
new file mode 100644
index 0000000..99b6139
--- /dev/null
+++ b/src/ftinspect/panels/glyphdetails.hpp
@@ -0,0 +1,94 @@
+// glyphdetails.hpp
+
+// Copyright (C) 2022 by Charlie Jiang.
+
+#pragma once
+
+#include "../glyphcomponents/glyphbitmap.hpp"
+
+#include <QWidget>
+#include <QLabel>
+#include <QGridLayout>
+#include <QBoxLayout>
+#include <QImage>
+#include <QRadioButton>
+#include <QButtonGroup>
+
+#include <freetype/freetype.h>
+
+struct GlyphCacheEntry;
+class Engine;
+class GlyphDetails
+: public QWidget
+{
+ Q_OBJECT
+
+public:
+ GlyphDetails(QWidget* parent, Engine* engine);
+ ~GlyphDetails() override;
+
+ void updateGlyph(GlyphCacheEntry& ctxt,
+ int charMapIndex);
+
+signals:
+ void switchToSingular(int index);
+ void closeDockWidget();
+
+protected:
+ void keyReleaseEvent(QKeyEvent* event) override;
+
+private:
+ Engine* engine_ = NULL;
+ int glyphIndex_ = -1;
+
+ enum DisplayUnit : int
+ {
+ DU_FontUnit,
+ DU_Point,
+ DU_Pixel
+ };
+
+ QButtonGroup* unitButtonGroup_;
+ QRadioButton* fontUnitButton_;
+ QRadioButton* pointButton_;
+ QRadioButton* pixelButton_;
+
+ QLabel* glyphIndexPromptLabel_;
+ QLabel* charCodePromptLabel_;
+ QLabel* glyphNamePromptLabel_;
+ QLabel* bboxSizePromptLabel_;
+ QLabel* horiBearingPromptLabel_;
+ QLabel* horiAdvancePromptLabel_;
+ QLabel* vertBearingPromptLabel_;
+ QLabel* vertAdvancePromptLabel_;
+ QLabel* inkSizePromptLabel_;
+ QLabel* bitmapOffsetPromptLabel_;
+
+ QLabel* glyphIndexLabel_;
+ QLabel* charCodeLabel_;
+ QLabel* glyphNameLabel_;
+ QLabel* bboxSizeLabel_;
+ QLabel* horiBearingLabel_;
+ QLabel* horiAdvanceLabel_;
+ QLabel* vertBearingLabel_;
+ QLabel* vertAdvanceLabel_;
+ QLabel* inkSizeLabel_;
+ QLabel* bitmapOffsetLabel_;
+
+ GlyphBitmapWidget* bitmapWidget_;
+
+ QHBoxLayout* unitLayout_;
+ QGridLayout* layout_;
+
+ int dpi_;
+ FT_Glyph_Metrics fontUnitMetrics_, pixelMetrics_;
+
+ void createLayout();
+ void createConnections();
+
+ void changeUnit(int unitId);
+ void bitmapWidgetClicked();
+};
+
+
+// end of glyphdetails.hpp
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [freetype2-demos] master 8969c8a 24/41: [ftinspect] Add left/right click behaviour to the continuous view.,
Werner Lemberg <=