Commits:
-
8a4bbbee
by Charlie Jiang
at 2022-07-22T15:00:52+08:00
[ftinspect] Improve Waterfall mode.
* src/ftinspect/rendering/glyphcontinuous.cpp,
src/ftinspect/rendering/glyphcontinuous.hpp:
Don't paint the red square (placeholder for zero x-advance glyphs) when in
Waterfall mode.
Use the `StringRenderer`'s line begin callback to render a font point size
prefix when in Waterfall mode. `sizeIndicatorOffset_` shifts the whole
string right.
* src/ftinspect/engine/stringrenderer.cpp: Fix `pointSize` return type.
Add `isWaterfall` func.
Add support to line begin hook callback.
* src/ftinspect/engine/engine.hpp: `pointSize` func should return `double`.
5 changed files:
Changes:
src/ftinspect/engine/engine.hpp
... |
... |
@@ -108,7 +108,7 @@ public: |
108
|
108
|
FT_Library ftLibrary() const { return library_; }
|
109
|
109
|
FTC_Manager cacheManager() { return cacheManager_; }
|
110
|
110
|
int dpi() { return dpi_; }
|
111
|
|
- int pointSize() { return pointSize_; }
|
|
111
|
+ double pointSize() { return pointSize_; }
|
112
|
112
|
int currentFontType() const { return fontType_; }
|
113
|
113
|
const QString& currentFamilyName() { return curFamilyName_; }
|
114
|
114
|
const QString& currentStyleName() { return curStyleName_; }
|
src/ftinspect/engine/stringrenderer.cpp
... |
... |
@@ -350,7 +350,7 @@ StringRenderer::render(int width, |
350
|
350
|
// Waterfall
|
351
|
351
|
|
352
|
352
|
vertical_ = false;
|
353
|
|
- auto originalSize = engine_->pointSize() * 64;
|
|
353
|
+ auto originalSize = static_cast<int>(engine_->pointSize() * 64);
|
354
|
354
|
auto ptSize = originalSize;
|
355
|
355
|
auto ptHeight = 64 * 72 * height / engine_->dpi();
|
356
|
356
|
auto step = (ptSize * ptSize / ptHeight + 64) & ~63;
|
... |
... |
@@ -431,7 +431,7 @@ StringRenderer::renderLine(int x, |
431
|
431
|
{
|
432
|
432
|
if (x < 0 || y < 0 || x > width || y > height)
|
433
|
433
|
return 0;
|
434
|
|
-
|
|
434
|
+
|
435
|
435
|
y = height - y; // change to Cartesian coordinates
|
436
|
436
|
|
437
|
437
|
FT_Vector pen = { 0, 0 };
|
... |
... |
@@ -462,6 +462,11 @@ StringRenderer::renderLine(int x, |
462
|
462
|
pen.x = (x << 6) - pen.x;
|
463
|
463
|
pen.y = (y << 6) - pen.y;
|
464
|
464
|
|
|
465
|
+ // Need to transform the coord back to normal coord system
|
|
466
|
+ lineBeginCallback_({ (pen.x >> 6),
|
|
467
|
+ height - (pen.y >> 6) },
|
|
468
|
+ engine_->pointSize());
|
|
469
|
+
|
465
|
470
|
for (int i = offset; i < totalCount + offset; i++)
|
466
|
471
|
{
|
467
|
472
|
auto& ctx = activeGlyphs_[i % activeGlyphs_.size()];
|
src/ftinspect/engine/stringrenderer.hpp
... |
... |
@@ -57,7 +57,8 @@ public: |
57
|
57
|
};
|
58
|
58
|
|
59
|
59
|
using RenderCallback = std::function<void(FT_Glyph)>;
|
60
|
|
- /* The glyph pointer may be replaced. In that case, ownership is transfered
|
|
60
|
+ /*
|
|
61
|
+ * The glyph pointer may be replaced. In that case, ownership is transfered
|
61
|
62
|
* to the renderer, and the new glyph will be eventually freed by
|
62
|
63
|
* the renderer. The callback is responsible to free the old glyph.
|
63
|
64
|
* This allows you to do the following:
|
... |
... |
@@ -69,16 +70,32 @@ public: |
69
|
70
|
* }
|
70
|
71
|
*/
|
71
|
72
|
using PreprocessCallback = std::function<void(FT_Glyph*)>;
|
|
73
|
+ /*
|
|
74
|
+ * Called when a new line begins.
|
|
75
|
+ * The 1st parameter is the initial pen position;
|
|
76
|
+ * The 2nd parameter is the current size in points.
|
|
77
|
+ */
|
|
78
|
+ using LineBeginCallback = std::function<void(FT_Vector, double)>;
|
72
|
79
|
|
73
|
|
- void setCharMapIndex(int charMapIndex, int limitIndex);
|
74
|
|
- void setCallback(RenderCallback cb)
|
|
80
|
+ bool isWaterfall() { return waterfall_; }
|
|
81
|
+
|
|
82
|
+ void
|
|
83
|
+ setCallback(RenderCallback cb)
|
75
|
84
|
{
|
76
|
85
|
renderCallback_ = std::move(cb);
|
77
|
86
|
}
|
78
|
|
- void setPreprocessCallback(PreprocessCallback cb)
|
|
87
|
+ void
|
|
88
|
+ setPreprocessCallback(PreprocessCallback cb)
|
79
|
89
|
{
|
80
|
90
|
glyphPreprocessCallback_ = std::move(cb);
|
81
|
91
|
}
|
|
92
|
+ void
|
|
93
|
+ setLineBeginCallback(LineBeginCallback cb)
|
|
94
|
+ {
|
|
95
|
+ lineBeginCallback_ = std::move(cb);
|
|
96
|
+ }
|
|
97
|
+
|
|
98
|
+ void setCharMapIndex(int charMapIndex, int limitIndex);
|
82
|
99
|
void setRepeated(bool repeated) { repeated_ = repeated; }
|
83
|
100
|
void setVertical(bool vertical) { vertical_ = vertical; }
|
84
|
101
|
void setRotation(double rotation);
|
... |
... |
@@ -151,6 +168,7 @@ private: |
151
|
168
|
|
152
|
169
|
RenderCallback renderCallback_;
|
153
|
170
|
PreprocessCallback glyphPreprocessCallback_;
|
|
171
|
+ LineBeginCallback lineBeginCallback_;
|
154
|
172
|
|
155
|
173
|
void reloadGlyphIndices();
|
156
|
174
|
void prepareRendering();
|
src/ftinspect/rendering/glyphcontinuous.cpp
... |
... |
@@ -106,6 +106,11 @@ GlyphContinuous::paintByRenderer(QPainter* painter) |
106
|
106
|
{
|
107
|
107
|
preprocessGlyph(ptr);
|
108
|
108
|
});
|
|
109
|
+ stringRenderer_.setLineBeginCallback(
|
|
110
|
+ [&](FT_Vector pos, double size)
|
|
111
|
+ {
|
|
112
|
+ beginLine(painter, pos, size);
|
|
113
|
+ });
|
109
|
114
|
displayingCount_ = stringRenderer_.render(width(), height(), beginIndex_);
|
110
|
115
|
}
|
111
|
116
|
|
... |
... |
@@ -229,6 +234,32 @@ GlyphContinuous::preprocessGlyph(FT_Glyph* glyphPtr) |
229
|
234
|
}
|
230
|
235
|
|
231
|
236
|
|
|
237
|
+void
|
|
238
|
+GlyphContinuous::beginLine(QPainter* painter,
|
|
239
|
+ FT_Vector pos,
|
|
240
|
+ double sizePoint)
|
|
241
|
+{
|
|
242
|
+ // Now only used by waterfall mode to draw a size indicator.
|
|
243
|
+ if (!stringRenderer_.isWaterfall())
|
|
244
|
+ {
|
|
245
|
+ sizeIndicatorOffset_ = 0;
|
|
246
|
+ return;
|
|
247
|
+ }
|
|
248
|
+
|
|
249
|
+ auto oldFont = painter->font();
|
|
250
|
+ oldFont.setPointSizeF(sizePoint);
|
|
251
|
+ painter->setFont(oldFont);
|
|
252
|
+ auto metrics = painter->fontMetrics();
|
|
253
|
+
|
|
254
|
+ auto sizePrefix = QString("%1: ").arg(sizePoint);
|
|
255
|
+ QPoint posQ = { static_cast<int>(pos.x),
|
|
256
|
+ static_cast<int>(pos.y) };
|
|
257
|
+ painter->drawText(posQ, sizePrefix);
|
|
258
|
+
|
|
259
|
+ sizeIndicatorOffset_ = metrics.horizontalAdvance(sizePrefix);
|
|
260
|
+}
|
|
261
|
+
|
|
262
|
+
|
232
|
263
|
void
|
233
|
264
|
GlyphContinuous::drawSingleGlyph(QPainter* painter, FT_Glyph glyph)
|
234
|
265
|
{
|
... |
... |
@@ -236,7 +267,7 @@ GlyphContinuous::drawSingleGlyph(QPainter* painter, FT_Glyph glyph) |
236
|
267
|
int width = glyph->advance.x ? glyph->advance.x >> 16
|
237
|
268
|
: metrics_.y_ppem / 2;
|
238
|
269
|
|
239
|
|
- if (glyph->advance.x == 0)
|
|
270
|
+ if (glyph->advance.x == 0 && !stringRenderer_.isWaterfall())
|
240
|
271
|
{
|
241
|
272
|
// Draw a red square to indicate
|
242
|
273
|
painter->fillRect(x_, y_ - width, width, width,
|
... |
... |
@@ -245,7 +276,8 @@ GlyphContinuous::drawSingleGlyph(QPainter* painter, FT_Glyph glyph) |
245
|
276
|
|
246
|
277
|
QRect rect;
|
247
|
278
|
QImage* image = engine_->convertGlyphToQImage(glyph, &rect, false);
|
248
|
|
- rect.setTop(height() - rect.top());
|
|
279
|
+ rect.setTop(height() - rect.top()); // TODO Don't place this here...
|
|
280
|
+ rect.setLeft(rect.left() + sizeIndicatorOffset_);
|
249
|
281
|
|
250
|
282
|
painter->drawImage(rect.topLeft(), *image);
|
251
|
283
|
delete image;
|
src/ftinspect/rendering/glyphcontinuous.hpp
... |
... |
@@ -75,6 +75,7 @@ private: |
75
|
75
|
double boldX_, boldY_, slant_;
|
76
|
76
|
double strokeRadius_;
|
77
|
77
|
QString text_;
|
|
78
|
+ int sizeIndicatorOffset_; // For Waterfall Rendering...
|
78
|
79
|
|
79
|
80
|
int displayingCount_ = 0;
|
80
|
81
|
FT_Size_Metrics metrics_;
|
... |
... |
@@ -96,6 +97,9 @@ private: |
96
|
97
|
void prePaint();
|
97
|
98
|
void updateRendererText();
|
98
|
99
|
void preprocessGlyph(FT_Glyph* glyphPtr);
|
|
100
|
+ void beginLine(QPainter* painter,
|
|
101
|
+ FT_Vector pos,
|
|
102
|
+ double sizePoint);
|
99
|
103
|
void drawSingleGlyph(QPainter* painter,
|
100
|
104
|
FT_Glyph glyph);
|
101
|
105
|
};
|
|