Commits:
-
d33272f0
by Charlie Jiang
at 2022-07-28T21:10:09+08:00
[ftinspect] Support mouse operations in the Continuous View.
Implement right-click and drag operations in the continuous view:
Right-Click: Send the clicked glyph to the Singular Grid View.
Drag:
All Glyphs Source Mode: Left = Plus Index, Right = Minus Index,
Up = Plus Index by one row, Down = Minus by row
Text String Source Mode: Move the string. Current it works pretty
counter-intuitive in Vertical Mode.
Text String Repeated Source Mode: No effect.
TODO: Click on a glyph to open a detail info overlay window.
* src/ftinspect/panels/continuous.cpp, src/ftinspect/panels/continuous.hpp:
Support the described operations. Remove the "Pos" slider and place a
"Reset Pos" button.
* src/ftinspect/rendering/glyphcontinuous.cpp,
src/ftinspect/rendering/glyphcontinuous.hpp: Support the described
operations. Fix a bug about misuse of `setTop`/`setLeft` funcs of `QRect`.
* src/ftinspect/engine/stringrenderer.cpp: Don't check bounding box because
although some glyph may be out of bound when rendering, but after moving,
it may go into the visible area.
* src/ftinspect/engine/stringrenderer.hpp: Add `position` getter, set
position default value to 0.5.
* src/ftinspect/maingui.cpp: Add `switchToSingular` function to support
the right-click action.
* src/ftinspect/widgets/fontsizeselector.cpp,
src/ftinspect/widgets/fontsizeselector.hpp: Add size setters.
* src/ftinspect/panels/singular.cpp, src/ftinspect/panels/singular.cpp:
Add `setCurrentGlyphAndSize` function.
12 changed files:
Changes:
src/ftinspect/engine/stringrenderer.cpp
... |
... |
@@ -561,16 +561,9 @@ StringRenderer::renderLine(int x, |
561
|
561
|
|
562
|
562
|
FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_PIXELS, &bbox);
|
563
|
563
|
|
564
|
|
- // check bounding box; if it is completely outside the
|
565
|
|
- // display surface, we don't need to render it
|
566
|
|
- if (bbox.xMax >= 0
|
567
|
|
- && bbox.yMax >= 0
|
568
|
|
- && bbox.xMin <= width
|
569
|
|
- && bbox.yMin <= height)
|
570
|
|
- {
|
571
|
|
- FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
|
572
|
|
- renderCallback_(image, penPos, ctx);
|
573
|
|
- }
|
|
564
|
+ // Don't check for bounding box here.
|
|
565
|
+ FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
|
|
566
|
+ renderCallback_(image, penPos, ctx);
|
574
|
567
|
|
575
|
568
|
FT_Done_Glyph(image);
|
576
|
569
|
}
|
src/ftinspect/engine/stringrenderer.hpp
... |
... |
@@ -93,6 +93,7 @@ public: |
93
|
93
|
using LineBeginCallback = std::function<void(FT_Vector, double)>;
|
94
|
94
|
|
95
|
95
|
bool isWaterfall() { return waterfall_; }
|
|
96
|
+ double position(){ return position_; }
|
96
|
97
|
|
97
|
98
|
void
|
98
|
99
|
setCallback(RenderCallback cb)
|
... |
... |
@@ -179,7 +180,7 @@ private: |
179
|
180
|
bool waterfall_ = false;
|
180
|
181
|
bool repeated_ = false;
|
181
|
182
|
bool vertical_ = false;
|
182
|
|
- double position_ = 0;
|
|
183
|
+ double position_ = 0.5;
|
183
|
184
|
double rotation_ = 0;
|
184
|
185
|
int kerningDegree_ = KD_None;
|
185
|
186
|
KerningMode kerningMode_ = KM_None;
|
src/ftinspect/maingui.cpp
... |
... |
@@ -154,6 +154,15 @@ MainGUI::onTripletChanged() |
154
|
154
|
}
|
155
|
155
|
|
156
|
156
|
|
|
157
|
+void
|
|
158
|
+MainGUI::switchToSingular(int glyphIndex,
|
|
159
|
+ double sizePoint)
|
|
160
|
+{
|
|
161
|
+ tabWidget_->setCurrentWidget(singularTab_); // this would update the tab
|
|
162
|
+ singularTab_->setCurrentGlyphAndSize(glyphIndex, sizePoint);
|
|
163
|
+}
|
|
164
|
+
|
|
165
|
+
|
157
|
166
|
void
|
158
|
167
|
MainGUI::repaintCurrentTab()
|
159
|
168
|
{
|
... |
... |
@@ -257,6 +266,9 @@ MainGUI::createConnections() |
257
|
266
|
|
258
|
267
|
connect(tripletSelector_, &TripletSelector::tripletChanged,
|
259
|
268
|
this, &MainGUI::onTripletChanged);
|
|
269
|
+
|
|
270
|
+ connect(continuousTab_, &ContinuousTab::switchToSingular,
|
|
271
|
+ this, &MainGUI::switchToSingular);
|
260
|
272
|
}
|
261
|
273
|
|
262
|
274
|
|
src/ftinspect/maingui.hpp
... |
... |
@@ -70,6 +70,7 @@ private slots: |
70
|
70
|
void reloadCurrentTabFont();
|
71
|
71
|
void loadFonts();
|
72
|
72
|
void onTripletChanged();
|
|
73
|
+ void switchToSingular(int glyphIndex, double sizePoint);
|
73
|
74
|
|
74
|
75
|
private:
|
75
|
76
|
Engine* engine_;
|
src/ftinspect/panels/continuous.cpp
... |
... |
@@ -61,7 +61,6 @@ ContinuousTab::syncSettings() |
61
|
61
|
sr.setVertical(verticalCheckBox_->isChecked());
|
62
|
62
|
sr.setKerning(kerningCheckBox_->isChecked());
|
63
|
63
|
sr.setRotation(rotationSpinBox_->value());
|
64
|
|
- sr.setPosition(positionSlider_->value() / 100.0);
|
65
|
64
|
|
66
|
65
|
// Not directly from the combo box
|
67
|
66
|
sr.setCharMapIndex(charMapIndex(), glyphLimitIndex_);
|
... |
... |
@@ -193,7 +192,6 @@ ContinuousTab::checkModeSource() |
193
|
192
|
|| src == GlyphContinuous::SRC_TextStringRepeated;
|
194
|
193
|
indexSelector_->setEnabled(src == GlyphContinuous::SRC_AllGlyphs);
|
195
|
194
|
sourceTextEdit_->setEnabled(isText);
|
196
|
|
- positionSlider_->setEnabled(isText);
|
197
|
195
|
canvas_->setSource(src);
|
198
|
196
|
|
199
|
197
|
{
|
... |
... |
@@ -255,6 +253,13 @@ ContinuousTab::reloadGlyphsAndRepaint() |
255
|
253
|
}
|
256
|
254
|
|
257
|
255
|
|
|
256
|
+void
|
|
257
|
+ContinuousTab::changeBeginIndexFromCanvas(int index)
|
|
258
|
+{
|
|
259
|
+ indexSelector_->setCurrentIndex(index);
|
|
260
|
+}
|
|
261
|
+
|
|
262
|
+
|
258
|
263
|
bool
|
259
|
264
|
ContinuousTab::eventFilter(QObject* watched,
|
260
|
265
|
QEvent* event)
|
... |
... |
@@ -321,12 +326,6 @@ ContinuousTab::createLayout() |
321
|
326
|
waterfallCheckBox_ = new QCheckBox(tr("Waterfall"), this);
|
322
|
327
|
kerningCheckBox_ = new QCheckBox(tr("Kerning"), this);
|
323
|
328
|
|
324
|
|
- positionSlider_ = new QSlider(Qt::Horizontal, this);
|
325
|
|
- positionSlider_->setMinimum(0);
|
326
|
|
- positionSlider_->setMaximum(100);
|
327
|
|
- positionSlider_->setTracking(true);
|
328
|
|
- positionSlider_->setSingleStep(5);
|
329
|
|
-
|
330
|
329
|
modeLabel_ = new QLabel(tr("Mode:"), this);
|
331
|
330
|
sourceLabel_ = new QLabel(tr("Text Source:"), this);
|
332
|
331
|
charMapLabel_ = new QLabel(tr("Char Map:"), this);
|
... |
... |
@@ -335,9 +334,8 @@ ContinuousTab::createLayout() |
335
|
334
|
slantLabel_ = new QLabel(tr("Slanting:"), this);
|
336
|
335
|
strokeRadiusLabel_ = new QLabel(tr("Stroke Radius:"), this);
|
337
|
336
|
rotationLabel_ = new QLabel(tr("Rotation:"), this);
|
338
|
|
- positionLabel_ = new QLabel(tr("Pos"), this);
|
339
|
337
|
|
340
|
|
- positionLabel_->setAlignment(Qt::AlignCenter);
|
|
338
|
+ resetPositionButton_ = new QPushButton(tr("Reset Pos"));
|
341
|
339
|
|
342
|
340
|
xEmboldeningSpinBox_ = new QDoubleSpinBox(this);
|
343
|
341
|
yEmboldeningSpinBox_ = new QDoubleSpinBox(this);
|
... |
... |
@@ -361,10 +359,6 @@ ContinuousTab::createLayout() |
361
|
359
|
rotationSpinBox_->setMinimum(-180);
|
362
|
360
|
rotationSpinBox_->setMaximum(180);
|
363
|
361
|
|
364
|
|
- positionLayout_ = new QVBoxLayout;
|
365
|
|
- positionLayout_->addWidget(positionLabel_);
|
366
|
|
- positionLayout_->addWidget(positionSlider_);
|
367
|
|
-
|
368
|
362
|
bottomLayout_ = new QGridLayout;
|
369
|
363
|
bottomLayout_->addWidget(sourceLabel_, 0, 0);
|
370
|
364
|
bottomLayout_->addWidget(modeLabel_, 1, 0);
|
... |
... |
@@ -387,7 +381,7 @@ ContinuousTab::createLayout() |
387
|
381
|
|
388
|
382
|
bottomLayout_->addWidget(indexSelector_, 0, 4, 1, 1);
|
389
|
383
|
bottomLayout_->addWidget(sourceTextEdit_, 1, 4, 3, 1);
|
390
|
|
- bottomLayout_->addLayout(positionLayout_, 0, 5);
|
|
384
|
+ bottomLayout_->addWidget(resetPositionButton_, 0, 5);
|
391
|
385
|
bottomLayout_->addWidget(waterfallCheckBox_, 1, 5);
|
392
|
386
|
bottomLayout_->addWidget(verticalCheckBox_, 2, 5);
|
393
|
387
|
bottomLayout_->addWidget(kerningCheckBox_, 3, 5);
|
... |
... |
@@ -415,6 +409,10 @@ ContinuousTab::createConnections() |
415
|
409
|
this, &ContinuousTab::wheelNavigate);
|
416
|
410
|
connect(canvas_, &GlyphContinuous::displayingCountUpdated,
|
417
|
411
|
this, &ContinuousTab::setDisplayingCount);
|
|
412
|
+ connect(canvas_, &GlyphContinuous::rightClickGlyph,
|
|
413
|
+ this, &ContinuousTab::switchToSingular);
|
|
414
|
+ connect(canvas_, &GlyphContinuous::beginIndexChangeRequest,
|
|
415
|
+ this, &ContinuousTab::changeBeginIndexFromCanvas);
|
418
|
416
|
|
419
|
417
|
connect(indexSelector_, &GlyphIndexSelector::currentIndexChanged,
|
420
|
418
|
this, &ContinuousTab::repaintGlyph);
|
... |
... |
@@ -425,6 +423,9 @@ ContinuousTab::createConnections() |
425
|
423
|
connect(sourceSelector_, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
426
|
424
|
this, &ContinuousTab::checkModeSource);
|
427
|
425
|
|
|
426
|
+ connect(resetPositionButton_, &QPushButton::clicked,
|
|
427
|
+ canvas_, &GlyphContinuous::resetPositionDelta);
|
|
428
|
+
|
428
|
429
|
connect(xEmboldeningSpinBox_,
|
429
|
430
|
QOverload<double>::of(&QDoubleSpinBox::valueChanged),
|
430
|
431
|
this, &ContinuousTab::repaintGlyph);
|
... |
... |
@@ -450,9 +451,6 @@ ContinuousTab::createConnections() |
450
|
451
|
connect(sourceTextEdit_, &QPlainTextEdit::textChanged,
|
451
|
452
|
this, &ContinuousTab::sourceTextChanged);
|
452
|
453
|
|
453
|
|
- connect(positionSlider_, &QSlider::valueChanged,
|
454
|
|
- this, &ContinuousTab::repaintGlyph);
|
455
|
|
-
|
456
|
454
|
sizeSelector_->installEventFilterForWidget(canvas_);
|
457
|
455
|
sizeSelector_->installEventFilterForWidget(this);
|
458
|
456
|
}
|
... |
... |
@@ -467,8 +465,6 @@ ContinuousTab::setDefaults() |
467
|
465
|
strokeRadiusSpinBox_->setValue(0.02);
|
468
|
466
|
rotationSpinBox_->setValue(0);
|
469
|
467
|
|
470
|
|
- positionSlider_->setValue(50);
|
471
|
|
-
|
472
|
468
|
canvas_->setSourceText(sourceTextEdit_->toPlainText());
|
473
|
469
|
canvas_->setSource(GlyphContinuous::SRC_AllGlyphs);
|
474
|
470
|
}
|
src/ftinspect/panels/continuous.hpp
... |
... |
@@ -48,6 +48,10 @@ public: |
48
|
48
|
void charMapChanged();
|
49
|
49
|
void sourceTextChanged();
|
50
|
50
|
void reloadGlyphsAndRepaint();
|
|
51
|
+ void changeBeginIndexFromCanvas(int index);
|
|
52
|
+
|
|
53
|
+signals:
|
|
54
|
+ void switchToSingular(int glyphIndex, double sizePoint);
|
51
|
55
|
|
52
|
56
|
protected:
|
53
|
57
|
bool eventFilter(QObject* watched, QEvent* event) override;
|
... |
... |
@@ -70,6 +74,8 @@ private: |
70
|
74
|
QComboBox* sourceSelector_;
|
71
|
75
|
QComboBox* charMapSelector_;
|
72
|
76
|
|
|
77
|
+ QPushButton* resetPositionButton_;
|
|
78
|
+
|
73
|
79
|
QLabel* modeLabel_;
|
74
|
80
|
QLabel* sourceLabel_;
|
75
|
81
|
QLabel* charMapLabel_;
|
... |
... |
@@ -78,7 +84,6 @@ private: |
78
|
84
|
QLabel* slantLabel_;
|
79
|
85
|
QLabel* strokeRadiusLabel_;
|
80
|
86
|
QLabel* rotationLabel_;
|
81
|
|
- QLabel* positionLabel_;
|
82
|
87
|
|
83
|
88
|
QDoubleSpinBox* xEmboldeningSpinBox_;
|
84
|
89
|
QDoubleSpinBox* yEmboldeningSpinBox_;
|
... |
... |
@@ -89,14 +94,12 @@ private: |
89
|
94
|
QCheckBox* verticalCheckBox_;
|
90
|
95
|
QCheckBox* waterfallCheckBox_;
|
91
|
96
|
QCheckBox* kerningCheckBox_;
|
92
|
|
- QSlider* positionSlider_;
|
93
|
97
|
|
94
|
98
|
GlyphIndexSelector* indexSelector_;
|
95
|
99
|
QPlainTextEdit* sourceTextEdit_;
|
96
|
100
|
|
97
|
101
|
std::vector<CharMapInfo> charMaps_;
|
98
|
|
-
|
99
|
|
- QVBoxLayout* positionLayout_;
|
|
102
|
+
|
100
|
103
|
QGridLayout* bottomLayout_;
|
101
|
104
|
QVBoxLayout* mainLayout_;
|
102
|
105
|
|
src/ftinspect/panels/singular.cpp
... |
... |
@@ -396,6 +396,15 @@ SingularTab::reloadFont() |
396
|
396
|
}
|
397
|
397
|
|
398
|
398
|
|
|
399
|
+void
|
|
400
|
+SingularTab::setCurrentGlyphAndSize(int glyphIndex,
|
|
401
|
+ double sizePoint)
|
|
402
|
+{
|
|
403
|
+ sizeSelector_->setSizePoint(sizePoint);
|
|
404
|
+ indexSelector_->setCurrentIndex(glyphIndex); // this will auto trigger update
|
|
405
|
+}
|
|
406
|
+
|
|
407
|
+
|
399
|
408
|
void
|
400
|
409
|
SingularTab::syncSettings()
|
401
|
410
|
{
|
src/ftinspect/panels/singular.hpp
... |
... |
@@ -41,6 +41,7 @@ public: |
41
|
41
|
|
42
|
42
|
void repaintGlyph() override;
|
43
|
43
|
void reloadFont() override;
|
|
44
|
+ void setCurrentGlyphAndSize(int glyphIndex, double sizePoint);
|
44
|
45
|
|
45
|
46
|
private slots:
|
46
|
47
|
void setGlyphIndex(int);
|
src/ftinspect/rendering/glyphcontinuous.cpp
... |
... |
@@ -97,6 +97,14 @@ GlyphContinuous::purgeCache() |
97
|
97
|
}
|
98
|
98
|
|
99
|
99
|
|
|
100
|
+void
|
|
101
|
+GlyphContinuous::resetPositionDelta()
|
|
102
|
+{
|
|
103
|
+ positionDelta_ = {};
|
|
104
|
+ repaint();
|
|
105
|
+}
|
|
106
|
+
|
|
107
|
+
|
100
|
108
|
void
|
101
|
109
|
GlyphContinuous::paintEvent(QPaintEvent* event)
|
102
|
110
|
{
|
... |
... |
@@ -131,6 +139,78 @@ GlyphContinuous::resizeEvent(QResizeEvent* event) |
131
|
139
|
}
|
132
|
140
|
|
133
|
141
|
|
|
142
|
+void
|
|
143
|
+GlyphContinuous::mousePressEvent(QMouseEvent* event)
|
|
144
|
+{
|
|
145
|
+ QWidget::mousePressEvent(event);
|
|
146
|
+ if (event->button() == Qt::LeftButton)
|
|
147
|
+ {
|
|
148
|
+ prevPositionDelta_ = positionDelta_;
|
|
149
|
+ mouseDownPostition_ = event->pos();
|
|
150
|
+ prevHoriPosition_ = stringRenderer_.position();
|
|
151
|
+ prevIndex_ = beginIndex_;
|
|
152
|
+ // We need to precalculate this value because after the first change of
|
|
153
|
+ // the begin index, the average line count would change. If we don't use the
|
|
154
|
+ // old value, then moving up/down for the same distance would not return
|
|
155
|
+ // to the original index which is confusing.
|
|
156
|
+ averageLineCount_ = calculateAverageLineCount();
|
|
157
|
+ }
|
|
158
|
+}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+void
|
|
162
|
+GlyphContinuous::mouseMoveEvent(QMouseEvent* event)
|
|
163
|
+{
|
|
164
|
+ QWidget::mouseMoveEvent(event);
|
|
165
|
+ if (event->buttons() != Qt::LeftButton)
|
|
166
|
+ return;
|
|
167
|
+ auto delta = event->pos() - mouseDownPostition_;
|
|
168
|
+ if (source_ == SRC_AllGlyphs)
|
|
169
|
+ {
|
|
170
|
+ auto deltaIndex = -delta.x() / HorizontalUnitLength
|
|
171
|
+ - delta.y() / VerticalUnitLength * averageLineCount_;
|
|
172
|
+ if (prevIndex_ + deltaIndex != beginIndex_)
|
|
173
|
+ emit beginIndexChangeRequest(beginIndex_ + deltaIndex);
|
|
174
|
+ }
|
|
175
|
+ else if (source_ == SRC_TextString)
|
|
176
|
+ {
|
|
177
|
+ positionDelta_ = prevPositionDelta_ + delta;
|
|
178
|
+ positionDelta_.setX(0); // Don't move horizontally
|
|
179
|
+
|
|
180
|
+ // but use the renderer
|
|
181
|
+ auto horiPos = delta.x() / static_cast<double>(width());
|
|
182
|
+ horiPos += prevHoriPosition_;
|
|
183
|
+ horiPos = qBound(0.0, horiPos, 1.0);
|
|
184
|
+ stringRenderer_.setPosition(horiPos);
|
|
185
|
+
|
|
186
|
+ purgeCache();
|
|
187
|
+ repaint();
|
|
188
|
+ }
|
|
189
|
+}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+void
|
|
193
|
+GlyphContinuous::mouseReleaseEvent(QMouseEvent* event)
|
|
194
|
+{
|
|
195
|
+ QWidget::mouseReleaseEvent(event);
|
|
196
|
+ if (event->button() == Qt::LeftButton)
|
|
197
|
+ {
|
|
198
|
+ auto dist = event->pos() - mouseDownPostition_;
|
|
199
|
+ if (dist.manhattanLength() < ClickDragThreshold)
|
|
200
|
+ {
|
|
201
|
+ // TODO: clicked down, open overlay
|
|
202
|
+ }
|
|
203
|
+ }
|
|
204
|
+ else if (event->button() == Qt::RightButton)
|
|
205
|
+ {
|
|
206
|
+ double size;
|
|
207
|
+ auto gl = findGlyphByMouse(event->pos(), &size);
|
|
208
|
+ if (gl)
|
|
209
|
+ emit rightClickGlyph(gl->glyphIndex, size);
|
|
210
|
+ }
|
|
211
|
+}
|
|
212
|
+
|
|
213
|
+
|
134
|
214
|
void
|
135
|
215
|
GlyphContinuous::paintByRenderer()
|
136
|
216
|
{
|
... |
... |
@@ -339,7 +419,7 @@ GlyphContinuous::saveSingleGlyph(FT_Glyph glyph, |
339
|
419
|
|
340
|
420
|
QRect rect;
|
341
|
421
|
QImage* image = engine_->convertGlyphToQImage(glyph, &rect, false);
|
342
|
|
- rect.setTop(height() - rect.top()); // TODO Don't place this here...
|
|
422
|
+ rect.moveTop(height() - rect.top()); // TODO Don't place this here...
|
343
|
423
|
|
344
|
424
|
entry.image = image;
|
345
|
425
|
entry.basePosition = rect;
|
... |
... |
@@ -373,7 +453,7 @@ GlyphContinuous::saveSingleGlyphImage(QImage* image, |
373
|
453
|
|
374
|
454
|
void
|
375
|
455
|
GlyphContinuous::beginDrawCacheLine(QPainter* painter,
|
376
|
|
- const GlyphCacheLine& line)
|
|
456
|
+ GlyphCacheLine& line)
|
377
|
457
|
{
|
378
|
458
|
// Now only used by waterfall mode to draw a size indicator.
|
379
|
459
|
if (!stringRenderer_.isWaterfall())
|
... |
... |
@@ -391,6 +471,7 @@ GlyphContinuous::beginDrawCacheLine(QPainter* painter, |
391
|
471
|
painter->drawText(line.basePosition, sizePrefix);
|
392
|
472
|
|
393
|
473
|
sizeIndicatorOffset_ = metrics.horizontalAdvance(sizePrefix);
|
|
474
|
+ line.sizeIndicatorOffset = sizeIndicatorOffset_;
|
394
|
475
|
}
|
395
|
476
|
|
396
|
477
|
|
... |
... |
@@ -412,10 +493,48 @@ GlyphContinuous::drawCacheGlyph(QPainter* painter, |
412
|
493
|
}
|
413
|
494
|
|
414
|
495
|
QRect rect = entry.basePosition;
|
415
|
|
- rect.setLeft(rect.left() + sizeIndicatorOffset_);
|
|
496
|
+ rect.moveLeft(rect.x() + sizeIndicatorOffset_);
|
|
497
|
+ rect.translate(positionDelta_);
|
416
|
498
|
|
417
|
499
|
painter->drawImage(rect.topLeft(), *entry.image);
|
418
|
500
|
}
|
419
|
501
|
|
420
|
502
|
|
|
503
|
+GlyphCacheEntry*
|
|
504
|
+GlyphContinuous::findGlyphByMouse(QPoint position,
|
|
505
|
+ double* outSizePoint)
|
|
506
|
+{
|
|
507
|
+ position -= positionDelta_;
|
|
508
|
+ for (auto& line : glyphCache_)
|
|
509
|
+ for (auto& entry : line.entries)
|
|
510
|
+ {
|
|
511
|
+ auto rect = entry.basePosition;
|
|
512
|
+ rect.moveLeft(rect.x() + line.sizeIndicatorOffset);
|
|
513
|
+ if (rect.contains(position))
|
|
514
|
+ {
|
|
515
|
+ if (outSizePoint)
|
|
516
|
+ *outSizePoint = line.sizePoint;
|
|
517
|
+ return &entry;
|
|
518
|
+ }
|
|
519
|
+ }
|
|
520
|
+ return NULL;
|
|
521
|
+}
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+int
|
|
525
|
+GlyphContinuous::calculateAverageLineCount()
|
|
526
|
+{
|
|
527
|
+ int averageLineCount = 0;
|
|
528
|
+ for (auto& line : glyphCache_)
|
|
529
|
+ {
|
|
530
|
+ // line.entries.size must < INT_MAX because the total glyph count in
|
|
531
|
+ // the renderer is below that
|
|
532
|
+ averageLineCount += static_cast<int>(line.entries.size());
|
|
533
|
+ }
|
|
534
|
+ if (!glyphCache_.empty())
|
|
535
|
+ averageLineCount /= static_cast<int>(glyphCache_.size());
|
|
536
|
+ return averageLineCount;
|
|
537
|
+}
|
|
538
|
+
|
|
539
|
+
|
421
|
540
|
// end of glyphcontinuous.cpp |
src/ftinspect/rendering/glyphcontinuous.hpp
... |
... |
@@ -43,6 +43,7 @@ struct GlyphCacheLine |
43
|
43
|
{
|
44
|
44
|
QPoint basePosition = {};
|
45
|
45
|
double sizePoint = 0.0;
|
|
46
|
+ int sizeIndicatorOffset;
|
46
|
47
|
std::vector<GlyphCacheEntry> entries;
|
47
|
48
|
};
|
48
|
49
|
|
... |
... |
@@ -87,16 +88,22 @@ public: |
87
|
88
|
void setSourceText(QString text);
|
88
|
89
|
|
89
|
90
|
void purgeCache();
|
|
91
|
+ void resetPositionDelta();
|
90
|
92
|
|
91
|
93
|
signals:
|
92
|
94
|
void wheelNavigate(int steps);
|
93
|
95
|
void wheelResize(int steps);
|
|
96
|
+ void beginIndexChangeRequest(int newIndex);
|
94
|
97
|
void displayingCountUpdated(int newCount);
|
|
98
|
+ void rightClickGlyph(int glyphIndex, double sizePoint);
|
95
|
99
|
|
96
|
100
|
protected:
|
97
|
101
|
void paintEvent(QPaintEvent* event) override;
|
98
|
102
|
void wheelEvent(QWheelEvent* event) override;
|
99
|
103
|
void resizeEvent(QResizeEvent* event) override;
|
|
104
|
+ void mousePressEvent(QMouseEvent* event) override;
|
|
105
|
+ void mouseMoveEvent(QMouseEvent* event) override;
|
|
106
|
+ void mouseReleaseEvent(QMouseEvent* event) override;
|
100
|
107
|
|
101
|
108
|
private:
|
102
|
109
|
Engine* engine_;
|
... |
... |
@@ -108,7 +115,7 @@ private: |
108
|
115
|
double boldX_, boldY_, slant_;
|
109
|
116
|
double strokeRadius_;
|
110
|
117
|
QString text_;
|
111
|
|
- int sizeIndicatorOffset_; // For Waterfall Rendering...
|
|
118
|
+ int sizeIndicatorOffset_ = 0; // For Waterfall Rendering...
|
112
|
119
|
|
113
|
120
|
int displayingCount_ = 0;
|
114
|
121
|
FT_Size_Metrics metrics_;
|
... |
... |
@@ -123,6 +130,11 @@ private: |
123
|
130
|
GlyphCacheLine* currentWritingLine_ = NULL;
|
124
|
131
|
|
125
|
132
|
QPoint positionDelta_;
|
|
133
|
+ double prevHoriPosition_;
|
|
134
|
+ QPoint prevPositionDelta_ = { 0, 0 };
|
|
135
|
+ QPoint mouseDownPostition_ = { 0, 0 };
|
|
136
|
+ int prevIndex_ = -1;
|
|
137
|
+ int averageLineCount_ = 0;
|
126
|
138
|
|
127
|
139
|
void paintByRenderer();
|
128
|
140
|
|
... |
... |
@@ -146,9 +158,18 @@ private: |
146
|
158
|
QRect pos,
|
147
|
159
|
GlyphContext gctx);
|
148
|
160
|
void beginDrawCacheLine(QPainter* painter,
|
149
|
|
- const GlyphCacheLine& line);
|
|
161
|
+ GlyphCacheLine& line);
|
150
|
162
|
void drawCacheGlyph(QPainter* painter,
|
151
|
163
|
const GlyphCacheEntry& entry);
|
|
164
|
+
|
|
165
|
+ GlyphCacheEntry* findGlyphByMouse(QPoint position,
|
|
166
|
+ double* outSizePoint);
|
|
167
|
+ int calculateAverageLineCount();
|
|
168
|
+
|
|
169
|
+ // Mouse constants
|
|
170
|
+ constexpr static int ClickDragThreshold = 10;
|
|
171
|
+ constexpr static int HorizontalUnitLength = 100;
|
|
172
|
+ constexpr static int VerticalUnitLength = 150;
|
152
|
173
|
};
|
153
|
174
|
|
154
|
175
|
|
src/ftinspect/widgets/fontsizeselector.cpp
... |
... |
@@ -29,6 +29,22 @@ FontSizeSelector::selectedUnit() |
29
|
29
|
}
|
30
|
30
|
|
31
|
31
|
|
|
32
|
+void
|
|
33
|
+FontSizeSelector::setSizePixel(int sizePixel)
|
|
34
|
+{
|
|
35
|
+ sizeDoubleSpinBox_->setValue(sizePixel);
|
|
36
|
+ unitsComboBox_->setCurrentIndex(Units_px);
|
|
37
|
+}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+void
|
|
41
|
+FontSizeSelector::setSizePoint(double sizePoint)
|
|
42
|
+{
|
|
43
|
+ sizeDoubleSpinBox_->setValue(sizePoint);
|
|
44
|
+ unitsComboBox_->setCurrentIndex(Units_pt);
|
|
45
|
+}
|
|
46
|
+
|
|
47
|
+
|
32
|
48
|
void
|
33
|
49
|
FontSizeSelector::applyToEngine(Engine* engine)
|
34
|
50
|
{
|
src/ftinspect/widgets/fontsizeselector.hpp
... |
... |
@@ -28,6 +28,8 @@ public: |
28
|
28
|
|
29
|
29
|
double selectedSize();
|
30
|
30
|
Units selectedUnit();
|
|
31
|
+ void setSizePixel(int sizePixel);
|
|
32
|
+ void setSizePoint(double sizePoint);
|
31
|
33
|
|
32
|
34
|
void applyToEngine(Engine* engine);
|
33
|
35
|
void handleWheelResizeBySteps(int steps);
|
|