summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qfixed_p.h4
-rw-r--r--src/gui/painting/qpaintengine.cpp2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp26
-rw-r--r--src/gui/painting/qpainter.cpp10
-rw-r--r--src/gui/painting/qpainter.h1
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp25
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h29
-rw-r--r--src/gui/text/coretext/qfontengine_coretext.mm17
-rw-r--r--src/gui/text/coretext/qfontengine_coretext_p.h15
-rw-r--r--src/gui/text/freetype/qfontengine_ft.cpp65
-rw-r--r--src/gui/text/freetype/qfontengine_ft_p.h72
-rw-r--r--src/gui/text/qdistancefield.cpp2
-rw-r--r--src/gui/text/qfontengine.cpp55
-rw-r--r--src/gui/text/qfontengine_p.h33
-rw-r--r--src/gui/text/qrawfont.cpp6
-rw-r--r--src/gui/text/qtextengine.cpp2
-rw-r--r--src/gui/text/windows/qwindowsfontengine.cpp9
-rw-r--r--src/gui/text/windows/qwindowsfontengine_p.h9
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp30
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite_p.h25
-rw-r--r--src/opengl/qopenglpaintengine.cpp22
-rw-r--r--src/opengl/qopengltextureglyphcache.cpp4
-rw-r--r--src/opengl/qopengltextureglyphcache_p.h4
23 files changed, 315 insertions, 152 deletions
diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
index 90d214fe96..7580069153 100644
--- a/src/gui/painting/qfixed_p.h
+++ b/src/gui/painting/qfixed_p.h
@@ -196,6 +196,10 @@ struct QFixedPoint {
constexpr static QFixedPoint fromPointF(const QPointF &p) {
return QFixedPoint(QFixed::fromReal(p.x()), QFixed::fromReal(p.y()));
}
+ constexpr inline bool operator==(const QFixedPoint &other) const
+ {
+ return x == other.x && y == other.y;
+ }
};
Q_DECLARE_TYPEINFO(QFixedPoint, Q_PRIMITIVE_TYPE);
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index 5a0d268c1e..42606a93f0 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -766,7 +766,7 @@ void QPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
bool((painter()->renderHints() & QPainter::TextAntialiasing)
&& !(painter()->font().styleStrategy() & QFont::NoAntialias)));
for (int i = 0; i < ti.glyphs.numGlyphs; ++i) {
- QImage glyph = ti.fontEngine->bitmapForGlyph(glyphs[i], QFixed(), QTransform());
+ QImage glyph = ti.fontEngine->bitmapForGlyph(glyphs[i], QFixedPoint(), QTransform());
painter()->drawImage(positions[i].x.toReal(), positions[i].y.toReal(), glyph);
}
painter()->restore();
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index ca1c4f831e..26f8de5b8b 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -2812,6 +2812,9 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
+ bool verticalSubPixelPositions = fontEngine->supportsVerticalSubPixelPositions()
+ && (s->renderHints & QPainter::VerticalSubpixelPositioning) != 0;
+
if (fontEngine->hasInternalCaching()) {
QFontEngine::GlyphFormat neededFormat =
painter()->device()->devType() == QInternal::Widget
@@ -2822,7 +2825,9 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
neededFormat = QFontEngine::Format_Mono;
for (int i = 0; i < numGlyphs; i++) {
- QFixed spp = fontEngine->subPixelPositionForX(positions[i].x);
+ QFixedPoint spp = fontEngine->subPixelPositionFor(positions[i]);
+ if (!verticalSubPixelPositions)
+ spp.y = 0;
const QFontEngine::Glyph *alphaMap = fontEngine->glyphData(glyphs[i], spp, neededFormat, s->matrix);
if (!alphaMap)
@@ -2847,9 +2852,13 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
Q_UNREACHABLE();
};
+ QFixed y = verticalSubPixelPositions
+ ? qFloor(positions[i].y)
+ : qRound(positions[i].y);
+
alphaPenBlt(alphaMap->data, bytesPerLine, depth,
qFloor(positions[i].x) + alphaMap->x,
- qRound(positions[i].y) - alphaMap->y,
+ qFloor(y) - alphaMap->y,
alphaMap->width, alphaMap->height,
fontEngine->expectsGammaCorrectedBlending());
}
@@ -2864,7 +2873,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
fontEngine->setGlyphCache(nullptr, cache);
}
- cache->populate(fontEngine, numGlyphs, glyphs, positions);
+ cache->populate(fontEngine, numGlyphs, glyphs, positions, s->renderHints);
cache->fillInPendingGlyphs();
const QImage &image = cache->image();
@@ -2881,15 +2890,20 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
int margin = fontEngine->glyphMargin(glyphFormat);
const uchar *bits = image.bits();
for (int i=0; i<numGlyphs; ++i) {
+ QFixedPoint subPixelPosition = fontEngine->subPixelPositionFor(positions[i]);
+ if (!verticalSubPixelPositions)
+ subPixelPosition.y = 0;
- QFixed subPixelPosition = fontEngine->subPixelPositionForX(positions[i].x);
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(glyphs[i], subPixelPosition);
const QTextureGlyphCache::Coord &c = cache->coords[glyph];
if (c.isNull())
continue;
int x = qFloor(positions[i].x) + c.baseLineX - margin;
- int y = qRound(positions[i].y) - c.baseLineY - margin;
+ int y = (verticalSubPixelPositions
+ ? qFloor(positions[i].y)
+ : qRound(positions[i].y));
+ y -= c.baseLineY + margin;
// printf("drawing [%d %d %d %d] baseline [%d %d], glyph: %d, to: %d %d, pos: %d %d\n",
// c.x, c.y,
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index f965761567..38ce9bf604 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1429,6 +1429,16 @@ void QPainterPrivate::updateState(QPainterState *newState)
a smooth pixmap transformation algorithm (such as bilinear) rather
than nearest neighbor.
+ \value VerticalSubpixelPositioning Allow text to be positioned at fractions
+ of pixels vertically as well as horizontally, if this is supported by the
+ font engine. This is currently supported by Freetype on all platforms when
+ the hinting preference is QFont::PreferNoHinting, and also on macOS. For
+ most use cases this will not improve visual quality, but may increase memory
+ consumption and some reduction in text rendering performance. Therefore, enabling
+ this is not recommended unless the use case requires it. One such use case could
+ be aligning glyphs with other visual primitives.
+ This value was added in Qt 6.1.
+
\value LosslessImageRendering Use a lossless image rendering, whenever possible.
Currently, this hint is only used when QPainter is employed to output a PDF
file through QPrinter or QPdfWriter, where drawImage()/drawPixmap() calls
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 68f5fc421b..8d471e938d 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -87,6 +87,7 @@ public:
Antialiasing = 0x01,
TextAntialiasing = 0x02,
SmoothPixmapTransform = 0x04,
+ VerticalSubpixelPositioning = 0x08,
LosslessImageRendering = 0x40,
};
Q_FLAG(RenderHint)
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 3728060caf..dfb937ed84 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -64,7 +64,7 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
QImage images[NumSubpixelPositions];
int numImages = 0;
for (int i = 0; i < NumSubpixelPositions; ++i) {
- QImage img = textureMapForGlyph(glyph, QFixed::fromReal(i / 12.0));
+ QImage img = textureMapForGlyph(glyph, QFixedPoint(QFixed::fromReal(i / 12.0), 0));
if (numImages == 0) {
QPainterPath path;
@@ -92,8 +92,11 @@ int QTextureGlyphCache::calculateSubPixelPositionCount(glyph_t glyph) const
return numImages;
}
-bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
- const QFixedPoint *positions)
+bool QTextureGlyphCache::populate(QFontEngine *fontEngine,
+ int numGlyphs,
+ const glyph_t *glyphs,
+ const QFixedPoint *positions,
+ QPainter::RenderHints renderHints)
{
#ifdef CACHE_DEBUG
printf("Populating with %d glyphs\n", numGlyphs);
@@ -105,6 +108,8 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
const int paddingDoubled = padding * 2;
bool supportsSubPixelPositions = fontEngine->supportsSubPixelPositions();
+ bool verticalSubPixelPositions = fontEngine->supportsVerticalSubPixelPositions()
+ && (renderHints & QPainter::VerticalSubpixelPositioning) != 0;
if (fontEngine->m_subPixelPositionCount == 0) {
if (!supportsSubPixelPositions) {
fontEngine->m_subPixelPositionCount = 1;
@@ -127,10 +132,12 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
for (int i=0; i < numGlyphs; ++i) {
const glyph_t glyph = glyphs[i];
- QFixed subPixelPosition;
+ QFixedPoint subPixelPosition;
if (supportsSubPixelPositions) {
- QFixed x = positions != nullptr ? positions[i].x : QFixed();
- subPixelPosition = fontEngine->subPixelPositionForX(x);
+ QFixedPoint pos = positions != nullptr ? positions[i] : QFixedPoint();
+ subPixelPosition = fontEngine->subPixelPositionFor(pos);
+ if (!verticalSubPixelPositions)
+ subPixelPosition.y = 0;
}
if (coords.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
@@ -263,7 +270,7 @@ void QTextureGlyphCache::fillInPendingGlyphs()
m_pendingGlyphs.clear();
}
-QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const
+QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, const QFixedPoint &subPixelPosition) const
{
switch (m_format) {
case QFontEngine::Format_A32:
@@ -317,7 +324,9 @@ void QImageTextureGlyphCache::createTextureData(int width, int height)
m_image.fill(0);
}
-void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subPixelPosition)
+void QImageTextureGlyphCache::fillTexture(const Coord &c,
+ glyph_t g,
+ const QFixedPoint &subPixelPosition)
{
QImage mask = textureMapForGlyph(g, subPixelPosition);
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index e34687d816..a401778a63 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -83,7 +83,8 @@ public:
struct GlyphAndSubPixelPosition
{
- GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
+ GlyphAndSubPixelPosition(glyph_t g, const QFixedPoint &spp)
+ : glyph(g), subPixelPosition(spp) {}
bool operator==(const GlyphAndSubPixelPosition &other) const
{
@@ -91,7 +92,7 @@ public:
}
glyph_t glyph;
- QFixed subPixelPosition;
+ QFixedPoint subPixelPosition;
};
struct Coord {
@@ -109,8 +110,11 @@ public:
}
};
- bool populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs,
- const QFixedPoint *positions);
+ bool populate(QFontEngine *fontEngine,
+ int numGlyphs,
+ const glyph_t *glyphs,
+ const QFixedPoint *positions,
+ QPainter::RenderHints renderHints = QPainter::RenderHints());
bool hasPendingGlyphs() const { return !m_pendingGlyphs.isEmpty(); }
void fillInPendingGlyphs();
@@ -119,7 +123,9 @@ public:
virtual int glyphPadding() const { return 0; }
virtual void beginFillTexture() { }
- virtual void fillTexture(const Coord &coord, glyph_t glyph, QFixed subPixelPosition) = 0;
+ virtual void fillTexture(const Coord &coord,
+ glyph_t glyph,
+ const QFixedPoint &subPixelPosition) = 0;
virtual void endFillTexture() { }
inline void createCache(int width, int height) {
@@ -141,7 +147,7 @@ public:
virtual int maxTextureWidth() const { return QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH; }
virtual int maxTextureHeight() const { return -1; }
- QImage textureMapForGlyph(glyph_t g, QFixed subPixelPosition) const;
+ QImage textureMapForGlyph(glyph_t g, const QFixedPoint &subPixelPosition) const;
protected:
int calculateSubPixelPositionCount(glyph_t) const;
@@ -156,9 +162,12 @@ protected:
int m_currentRowHeight; // Height of last row
};
-inline size_t qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g)
+inline size_t qHash(const QTextureGlyphCache::GlyphAndSubPixelPosition &g, size_t seed = 0)
{
- return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
+ return qHashMulti(seed,
+ g.glyph,
+ g.subPixelPosition.x.value(),
+ g.subPixelPosition.y.value());
}
@@ -171,7 +180,9 @@ public:
virtual void createTextureData(int width, int height) override;
virtual void resizeTextureData(int width, int height) override;
- virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) override;
+ virtual void fillTexture(const Coord &c,
+ glyph_t glyph,
+ const QFixedPoint &subPixelPosition) override;
inline const QImage &image() const { return m_image; }
diff --git a/src/gui/text/coretext/qfontengine_coretext.mm b/src/gui/text/coretext/qfontengine_coretext.mm
index 0070e18ade..33a3f22e67 100644
--- a/src/gui/text/coretext/qfontengine_coretext.mm
+++ b/src/gui/text/coretext/qfontengine_coretext.mm
@@ -531,7 +531,7 @@ static void qcoretextfontengine_scaleMetrics(glyph_metrics_t &br, const QTransfo
}
}
-glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, GlyphFormat format)
+glyph_metrics_t QCoreTextFontEngine::alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &matrix, GlyphFormat format)
{
if (matrix.type() > QTransform::TxScale)
return QFontEngine::alphaMapBoundingBox(glyph, subPixelPosition, matrix, format);
@@ -713,7 +713,7 @@ qreal QCoreTextFontEngine::fontSmoothingGamma()
return 2.0;
}
-QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, const QColor &color)
+QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &matrix, const QColor &color)
{
glyph_metrics_t br = alphaMapBoundingBox(glyph, subPixelPosition, matrix, glyphFormat);
@@ -773,8 +773,9 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMakeScale(matrix.m11(), matrix.m22()));
CGGlyph cgGlyph = glyph;
- qreal pos_x = -br.x.truncate() + subPixelPosition.toReal();
- qreal pos_y = im.height() + br.y.toReal();
+
+ qreal pos_x = -br.x.truncate() + subPixelPosition.x.toReal();
+ qreal pos_y = im.height() + br.y.toReal() - subPixelPosition.y.toReal();
if (!hasColorGlyphs()) {
CGContextSetTextMatrix(ctx, cgMatrix);
@@ -817,12 +818,12 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition
return im;
}
-QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition)
{
return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
}
-QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &x)
+QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &x)
{
if (x.type() > QTransform::TxScale)
return QFontEngine::alphaMapForGlyph(glyph, subPixelPosition, x);
@@ -844,7 +845,7 @@ QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosit
return alphaMap;
}
-QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &x)
+QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &x)
{
if (x.type() > QTransform::TxScale)
return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, x);
@@ -852,7 +853,7 @@ QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPo
return imageForGlyph(glyph, subPixelPosition, x);
}
-QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color)
+QImage QCoreTextFontEngine::bitmapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color)
{
if (t.type() > QTransform::TxScale)
return QFontEngine::bitmapForGlyph(glyph, subPixelPosition, t, color);
diff --git a/src/gui/text/coretext/qfontengine_coretext_p.h b/src/gui/text/coretext/qfontengine_coretext_p.h
index 1239072677..361153b37a 100644
--- a/src/gui/text/coretext/qfontengine_coretext_p.h
+++ b/src/gui/text/coretext/qfontengine_coretext_p.h
@@ -91,7 +91,8 @@ public:
bool canRender(const QChar *string, int len) const override;
int synthesized() const override { return synthesisFlags; }
- bool supportsSubPixelPositions() const override { return true; }
+ bool supportsHorizontalSubPixelPositions() const override { return true; }
+ bool supportsVerticalSubPixelPositions() const override { return false; }
QFixed lineThickness() const override;
QFixed underlinePosition() const override;
@@ -101,11 +102,11 @@ public:
FaceId faceId() const override;
bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const override;
void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) override;
- QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition) override;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
- QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
- glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) override;
- QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
+ QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition) override;
+ QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &t) override;
+ QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &, const QTransform &matrix, GlyphFormat) override;
+ QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override;
QFixed emSquareSize() const override;
void doKerning(QGlyphLayout *g, ShaperFlags flags) const override;
@@ -132,7 +133,7 @@ public:
protected:
QCoreTextFontEngine(const QFontDef &def);
void init();
- QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &m, const QColor &color = QColor());
+ QImage imageForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &m, const QColor &color = QColor());
void loadAdvancesForGlyphs(QVarLengthArray<CGGlyph> &cgGlyphs, QGlyphLayout *glyphs) const;
bool hasColorGlyphs() const;
bool shouldAntialias() const;
diff --git a/src/gui/text/freetype/qfontengine_ft.cpp b/src/gui/text/freetype/qfontengine_ft.cpp
index 2937857f71..42985fcaa6 100644
--- a/src/gui/text/freetype/qfontengine_ft.cpp
+++ b/src/gui/text/freetype/qfontengine_ft.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -943,7 +943,7 @@ static inline void transformBoundingBox(int *left, int *top, int *right, int *bo
}
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
- QFixed subPixelPosition,
+ const QFixedPoint &subPixelPosition,
GlyphFormat format,
bool fetchMetricsOnly,
bool disableOutlineDrawing) const
@@ -967,8 +967,8 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
FT_Matrix matrix = freetype->matrix;
FT_Vector v;
- v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.value());
- v.y = 0;
+ v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.x.value());
+ v.y = format == Format_Mono ? 0 : FT_Pos(-subPixelPosition.y.value());
FT_Set_Transform(face, &matrix, &v);
bool hsubpixel = false;
@@ -1644,7 +1644,11 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag
} else {
if (!face)
face = lockFace();
- g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyphs->glyphs[i], 0, Format_None, true);
+ g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr,
+ glyphs->glyphs[i],
+ QFixedPoint(),
+ Format_None,
+ true);
if (g)
glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
else
@@ -1685,7 +1689,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
if (!g) {
if (!face)
face = lockFace();
- g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyphs.glyphs[i], 0, Format_None, true);
+ g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr,
+ glyphs.glyphs[i],
+ QFixedPoint(),
+ Format_None,
+ true);
}
if (g) {
QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
@@ -1730,7 +1738,11 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
Glyph *g = cacheEnabled ? defaultGlyphSet.getGlyph(glyph) : nullptr;
if (!g) {
face = lockFace();
- g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, 0, Format_None, true);
+ g = loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr,
+ glyph,
+ QFixedPoint(),
+ Format_None,
+ true);
}
if (g) {
overall.x = g->x;
@@ -1762,10 +1774,13 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matrix)
{
- return alphaMapBoundingBox(glyph, 0, matrix, QFontEngine::Format_None);
+ return alphaMapBoundingBox(glyph, QFixedPoint(), matrix, QFontEngine::Format_None);
}
-glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format)
+glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &matrix,
+ QFontEngine::GlyphFormat format)
{
Glyph *g = loadGlyphFor(glyph, subPixelPosition, format, matrix, true);
@@ -1828,8 +1843,10 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng
return img;
}
-QFontEngine::Glyph *QFontEngineFT::glyphData(glyph_t glyphIndex, QFixed subPixelPosition,
- QFontEngine::GlyphFormat neededFormat, const QTransform &t)
+QFontEngine::Glyph *QFontEngineFT::glyphData(glyph_t glyphIndex,
+ const QFixedPoint &subPixelPosition,
+ QFontEngine::GlyphFormat neededFormat,
+ const QTransform &t)
{
Q_ASSERT(cacheEnabled);
@@ -1854,7 +1871,7 @@ static inline bool is2dRotation(const QTransform &t)
}
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
- QFixed subPixelPosition,
+ const QFixedPoint &subPixelPosition,
GlyphFormat format,
const QTransform &t,
bool fetchBoundingBox,
@@ -1882,12 +1899,14 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
return glyph;
}
-QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, const QFixedPoint &subPixelPosition)
{
return alphaMapForGlyph(g, subPixelPosition, QTransform());
}
-QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t)
{
const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono;
@@ -1902,7 +1921,9 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const
return img;
}
-QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t)
{
if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
@@ -1923,7 +1944,10 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
}
-QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t, const QColor &color)
+QImage QFontEngineFT::bitmapForGlyph(glyph_t g,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t,
+ const QColor &color)
{
Q_UNUSED(color);
@@ -1952,7 +1976,7 @@ QImage QFontEngineFT::bitmapForGlyph(glyph_t g, QFixed subPixelPosition, const Q
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- defaultGlyphSet.removeGlyphFromCache(glyph, 0);
+ defaultGlyphSet.removeGlyphFromCache(glyph, QFixedPoint());
}
int QFontEngineFT::glyphCount() const
@@ -2033,7 +2057,8 @@ void QFontEngineFT::QGlyphSet::clear()
glyph_data.clear();
}
-void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index,
+ const QFixedPoint &subPixelPosition)
{
if (useFastGlyphData(index, subPixelPosition)) {
if (fast_glyph_data[index]) {
@@ -2047,7 +2072,9 @@ void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPix
}
}
-void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph)
+void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index,
+ const QFixedPoint &subPixelPosition,
+ Glyph *glyph)
{
if (useFastGlyphData(index, subPixelPosition)) {
if (!fast_glyph_data[index])
diff --git a/src/gui/text/freetype/qfontengine_ft_p.h b/src/gui/text/freetype/qfontengine_ft_p.h
index 8962327cd1..e9234e7d69 100644
--- a/src/gui/text/freetype/qfontengine_ft_p.h
+++ b/src/gui/text/freetype/qfontengine_ft_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -143,7 +143,7 @@ public:
struct GlyphAndSubPixelPosition
{
- GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
+ GlyphAndSubPixelPosition(glyph_t g, const QFixedPoint spp) : glyph(g), subPixelPosition(spp) {}
bool operator==(const GlyphAndSubPixelPosition &other) const
{
@@ -151,7 +151,7 @@ public:
}
glyph_t glyph;
- QFixed subPixelPosition;
+ QFixedPoint subPixelPosition;
};
struct QGlyphSet
@@ -161,13 +161,14 @@ public:
FT_Matrix transformationMatrix;
bool outline_drawing;
- void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition);
+ void removeGlyphFromCache(glyph_t index, const QFixedPoint &subPixelPosition);
void clear();
- inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const {
- return (index < 256 && subPixelPosition == 0);
+ inline bool useFastGlyphData(glyph_t index, const QFixedPoint &subPixelPosition) const {
+ return (index < 256 && subPixelPosition.x == 0 && subPixelPosition.y == 0);
}
- inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const;
- void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
+ inline Glyph *getGlyph(glyph_t index,
+ const QFixedPoint &subPixelPositionX = QFixedPoint()) const;
+ void setGlyph(glyph_t index, const QFixedPoint &spp, Glyph *glyph);
inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
@@ -182,12 +183,17 @@ private:
QFontEngine::FaceId faceId() const override;
QFontEngine::Properties properties() const override;
QFixed emSquareSize() const override;
- bool supportsSubPixelPositions() const override
+ bool supportsHorizontalSubPixelPositions() const override
{
return default_hint_style == HintLight ||
default_hint_style == HintNone;
}
+ bool supportsVerticalSubPixelPositions() const override
+ {
+ return supportsHorizontalSubPixelPositions();
+ }
+
bool getSfntTableData(uint tag, uchar *buffer, uint *length) const override;
int synthesized() const override;
@@ -219,17 +225,19 @@ private:
glyph_metrics_t boundingBox(glyph_t glyph, const QTransform &matrix) override;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const override;
- QImage alphaMapForGlyph(glyph_t g) override { return alphaMapForGlyph(g, 0); }
- QImage alphaMapForGlyph(glyph_t, QFixed) override;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
- QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
- QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
+ QImage alphaMapForGlyph(glyph_t g) override { return alphaMapForGlyph(g, QFixedPoint()); }
+ QImage alphaMapForGlyph(glyph_t, const QFixedPoint &) override;
+ QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &t) override;
+ QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
+ QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color) override;
glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
- QFixed subPixelPosition,
+ const QFixedPoint &subPixelPosition,
const QTransform &matrix,
QFontEngine::GlyphFormat format) override;
- Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition,
- GlyphFormat neededFormat, const QTransform &t) override;
+ Glyph *glyphData(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ GlyphFormat neededFormat,
+ const QTransform &t) override;
bool hasInternalCaching() const override { return cacheEnabled; }
bool expectsGammaCorrectedBlending() const override;
@@ -252,10 +260,24 @@ private:
inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
- inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const
+ inline Glyph *loadGlyph(uint glyph,
+ const QFixedPoint &subPixelPosition,
+ GlyphFormat format = Format_None,
+ bool fetchMetricsOnly = false,
+ bool disableOutlineDrawing = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
- Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const;
- Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false);
+ Glyph *loadGlyph(QGlyphSet *set,
+ uint glyph,
+ const QFixedPoint &subPixelPosition,
+ GlyphFormat = Format_None,
+ bool fetchMetricsOnly = false,
+ bool disableOutlineDrawing = false) const;
+ Glyph *loadGlyphFor(glyph_t g,
+ const QFixedPoint &subPixelPosition,
+ GlyphFormat format,
+ const QTransform &t,
+ bool fetchBoundingBox = false,
+ bool disableOutlineDrawing = false);
QGlyphSet *loadGlyphSet(const QTransform &matrix);
@@ -341,12 +363,16 @@ private:
Q_DECLARE_TYPEINFO(QFontEngineFT::QGlyphSet, Q_RELOCATABLE_TYPE);
-inline size_t qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
+inline size_t qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g, size_t seed)
{
- return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
+ return qHashMulti(seed,
+ g.glyph,
+ g.subPixelPosition.x.value(),
+ g.subPixelPosition.y.value());
}
-inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index, QFixed subPixelPosition) const
+inline QFontEngineFT::Glyph *QFontEngineFT::QGlyphSet::getGlyph(glyph_t index,
+ const QFixedPoint &subPixelPosition) const
{
if (useFastGlyphData(index, subPixelPosition))
return fast_glyph_data[index];
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index c621d7bab8..a3fdfd63d1 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -780,7 +780,7 @@ bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine)
const glyph_t glyph = fe->glyphIndex('O');
if (glyph != 0)
- im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform());
+ im = fe->alphaMapForGlyph(glyph, QFixedPoint(), QTransform());
Q_ASSERT(fe->ref.loadRelaxed() == 0);
delete fe;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index d526dcc7ac..0a8de97b38 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -796,7 +796,7 @@ void QFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int n
addBitmapFontToPath(x, y, g, path, flags);
}
-QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/)
+QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QFixedPoint &/*subPixelPosition*/)
{
// For font engines don't support subpixel positioning
return alphaMapForGlyph(glyph);
@@ -812,9 +812,9 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
return i;
}
-QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition, const QTransform &t)
{
- if (! supportsSubPixelPositions())
+ if (!supportsHorizontalSubPixelPositions() && !supportsVerticalSubPixelPositions())
return alphaMapForGlyph(glyph, t);
QImage i = alphaMapForGlyph(glyph, subPixelPosition);
@@ -825,7 +825,7 @@ QImage QFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, con
return i;
}
-QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &t)
+QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, const QFixedPoint &/*subPixelPosition*/, const QTransform &t)
{
const QImage alphaMask = alphaMapForGlyph(glyph, t);
QImage rgbMask(alphaMask.width(), alphaMask.height(), QImage::Format_RGB32);
@@ -842,32 +842,37 @@ QImage QFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed /*subPixelPosition
return rgbMask;
}
-QImage QFontEngine::bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform&, const QColor &)
+QImage QFontEngine::bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform&, const QColor &)
{
Q_UNUSED(subPixelPosition);
return QImage();
}
-QFixed QFontEngine::subPixelPositionForX(QFixed x) const
+QFixedPoint QFontEngine::subPixelPositionFor(const QFixedPoint &position) const
{
- if (m_subPixelPositionCount <= 1 || !supportsSubPixelPositions())
- return QFixed();
+ if (m_subPixelPositionCount <= 1
+ || (!supportsHorizontalSubPixelPositions()
+ && !supportsVerticalSubPixelPositions())) {
+ return QFixedPoint();
+ }
- QFixed subPixelPosition;
- if (x != 0) {
- subPixelPosition = x - x.floor();
- QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
+ auto f = [&](QFixed v) {
+ if (v != 0) {
+ v = v - v.floor() + QFixed::fromFixed(1);
+ QFixed fraction = (v / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
+ v = fraction / QFixed(m_subPixelPositionCount);
+ }
+ return v;
+ };
- // Compensate for precision loss in fixed point to make sure we are always drawing at a subpixel position over
- // the lower boundary for the selected rasterization by adding 1/64.
- subPixelPosition = fraction / QFixed(m_subPixelPositionCount) + QFixed::fromReal(0.015625);
- }
- return subPixelPosition;
+ return QFixedPoint(f(position.x), f(position.y));
}
-QFontEngine::Glyph *QFontEngine::glyphData(glyph_t, QFixed,
- QFontEngine::GlyphFormat, const QTransform &)
+QFontEngine::Glyph *QFontEngine::glyphData(glyph_t,
+ const QFixedPoint &,
+ QFontEngine::GlyphFormat,
+ const QTransform &)
{
return nullptr;
}
@@ -2215,7 +2220,7 @@ QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph)
return engine(which)->alphaMapForGlyph(stripped(glyph));
}
-QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition)
{
const int which = highByte(glyph);
return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition);
@@ -2227,13 +2232,17 @@ QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, const QTransform &t)
return engine(which)->alphaMapForGlyph(stripped(glyph), t);
}
-QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t)
{
const int which = highByte(glyph);
return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition, t);
}
-QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t)
{
const int which = highByte(glyph);
return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 9b71a2fd0d..1169e0b779 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -176,8 +176,17 @@ public:
SynthesizedStretch = 0x4
};
virtual int synthesized() const { return 0; }
- virtual bool supportsSubPixelPositions() const { return false; }
- virtual QFixed subPixelPositionForX(QFixed x) const;
+ inline bool supportsSubPixelPositions() const
+ {
+ return supportsHorizontalSubPixelPositions() || supportsVerticalSubPixelPositions();
+ }
+ virtual bool supportsHorizontalSubPixelPositions() const { return false; }
+ virtual bool supportsVerticalSubPixelPositions() const { return false; }
+ virtual QFixedPoint subPixelPositionFor(const QFixedPoint &position) const;
+ QFixed subPixelPositionForX(const QFixed &x) const
+ {
+ return subPixelPositionFor(QFixedPoint(x, 0)).x;
+ }
virtual QFixed emSquareSize() const { return ascent(); }
@@ -201,15 +210,15 @@ public:
*/
// ### Refactor this into a smaller and more flexible API.
virtual QImage alphaMapForGlyph(glyph_t);
- virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition);
+ virtual QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition);
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t);
- virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
- virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
- virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor());
- virtual Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition, GlyphFormat neededFormat, const QTransform &t);
+ virtual QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t);
+ virtual QImage bitmapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t, const QColor &color = QColor());
+ virtual Glyph *glyphData(glyph_t glyph, const QFixedPoint &subPixelPosition, GlyphFormat neededFormat, const QTransform &t);
virtual bool hasInternalCaching() const { return false; }
- virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
+ virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint &/*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/)
{
return boundingBox(glyph, matrix);
}
@@ -472,10 +481,10 @@ public:
virtual QFixed xHeight() const override;
virtual QFixed averageCharWidth() const override;
virtual QImage alphaMapForGlyph(glyph_t) override;
- virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override;
+ virtual QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override;
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t) override;
- virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
- virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t) override;
+ virtual QImage alphaMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
+ virtual QImage alphaRGBMapForGlyph(glyph_t, const QFixedPoint &subPixelPosition, const QTransform &t) override;
virtual QFixed lineThickness() const override;
virtual QFixed underlinePosition() const override;
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index 918cec6fa2..00a2939e79 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -281,12 +281,12 @@ QImage QRawFont::alphaMapForGlyph(quint32 glyphIndex, AntialiasingType antialias
return QImage();
if (d->fontEngine->glyphFormat == QFontEngine::Format_ARGB)
- return d->fontEngine->bitmapForGlyph(glyphIndex, QFixed(), transform);
+ return d->fontEngine->bitmapForGlyph(glyphIndex, QFixedPoint(), transform);
if (antialiasingType == SubPixelAntialiasing)
- return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixed(), transform);
+ return d->fontEngine->alphaRGBMapForGlyph(glyphIndex, QFixedPoint(), transform);
- return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixed(), transform);
+ return d->fontEngine->alphaMapForGlyph(glyphIndex, QFixedPoint(), transform);
}
/*!
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index d3a28d8d02..f8ce0ba8af 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1736,7 +1736,7 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
g.glyphs[i] |= (engineIdx << 24);
}
- if (!actualFontEngine->supportsSubPixelPositions()) {
+ if (!actualFontEngine->supportsHorizontalSubPixelPositions()) {
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] = g.advances[i].round();
}
diff --git a/src/gui/text/windows/qwindowsfontengine.cpp b/src/gui/text/windows/qwindowsfontengine.cpp
index 3335fcdc99..f4ef9f8a23 100644
--- a/src/gui/text/windows/qwindowsfontengine.cpp
+++ b/src/gui/text/windows/qwindowsfontengine.cpp
@@ -1043,7 +1043,10 @@ QWindowsNativeImage *QWindowsFontEngine::drawGDIGlyph(HFONT font, glyph_t glyph,
return ni;
}
-glyph_metrics_t QWindowsFontEngine::alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat format)
+glyph_metrics_t QWindowsFontEngine::alphaMapBoundingBox(glyph_t glyph,
+ const QFixedPoint &,
+ const QTransform &matrix,
+ GlyphFormat format)
{
int margin = 0;
if (format == QFontEngine::Format_A32 || format == QFontEngine::Format_ARGB)
@@ -1108,7 +1111,9 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo
#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D
-QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed, const QTransform &t)
+QImage QWindowsFontEngine::alphaRGBMapForGlyph(glyph_t glyph,
+ const QFixedPoint &,
+ const QTransform &t)
{
HFONT font = hfont;
diff --git a/src/gui/text/windows/qwindowsfontengine_p.h b/src/gui/text/windows/qwindowsfontengine_p.h
index 22130924ad..57b619bc1c 100644
--- a/src/gui/text/windows/qwindowsfontengine_p.h
+++ b/src/gui/text/windows/qwindowsfontengine_p.h
@@ -107,8 +107,13 @@ public:
QImage alphaMapForGlyph(glyph_t t) override { return alphaMapForGlyph(t, QTransform()); }
QImage alphaMapForGlyph(glyph_t, const QTransform &xform) override;
- QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override;
- glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat) override;
+ QImage alphaRGBMapForGlyph(glyph_t t,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &xform) override;
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
+ const QFixedPoint &,
+ const QTransform &matrix,
+ GlyphFormat) override;
QFontEngine *cloneWithSize(qreal pixelSize) const override;
Qt::HANDLE handle() const override;
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
index c17139ab8b..20063a0610 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
@@ -602,7 +602,9 @@ qreal QWindowsFontEngineDirectWrite::maxCharWidth() const
return m_maxAdvanceWidth.toReal();
}
-QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t)
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t)
{
QImage im = imageForGlyph(glyph, subPixelPosition, glyphMargin(Format_A8), t);
@@ -621,21 +623,22 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub
return alphaMap;
}
-QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition)
+QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition)
{
return alphaMapForGlyph(glyph, subPixelPosition, QTransform());
}
-bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const
+bool QWindowsFontEngineDirectWrite::supportsHorizontalSubPixelPositions() const
{
return true;
}
QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
- QFixed subPixelPosition,
- int margin,
- const QTransform &originalTransform,
- const QColor &color)
+ const QFixedPoint &subPixelPosition,
+ int margin,
+ const QTransform &originalTransform,
+ const QColor &color)
{
UINT16 glyphIndex = t;
FLOAT glyphAdvance = 0;
@@ -659,7 +662,7 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t,
xform.scale(fontDef.stretch / 100.0, 1.0);
DWRITE_MATRIX transform;
- transform.dx = subPixelPosition.toReal();
+ transform.dx = subPixelPosition.x.toReal();
transform.dy = 0;
transform.m11 = xform.m11();
transform.m12 = xform.m12();
@@ -880,7 +883,7 @@ void QWindowsFontEngineDirectWrite::renderGlyphRun(QImage *destination,
}
QImage QWindowsFontEngineDirectWrite::alphaRGBMapForGlyph(glyph_t t,
- QFixed subPixelPosition,
+ const QFixedPoint &subPixelPosition,
const QTransform &xform)
{
QImage mask = imageForGlyph(t,
@@ -936,7 +939,7 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN
}
glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph,
- QFixed subPixelPosition,
+ const QFixedPoint &subPixelPosition,
const QTransform &originalTransform,
GlyphFormat format)
{
@@ -966,7 +969,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
glyphRun.glyphOffsets = &glyphOffset;
DWRITE_MATRIX transform;
- transform.dx = subPixelPosition.toReal();
+ transform.dx = subPixelPosition.x.toReal();
transform.dy = 0;
transform.m11 = matrix.m11();
transform.m12 = matrix.m12();
@@ -1008,7 +1011,10 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph
}
}
-QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t, const QColor &color)
+QImage QWindowsFontEngineDirectWrite::bitmapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t,
+ const QColor &color)
{
return imageForGlyph(glyph, subPixelPosition, glyphMargin(QFontEngine::Format_ARGB), t, color);
}
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
index 5be021d37a..4d19c3908a 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
@@ -97,7 +97,7 @@ public:
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
glyph_metrics_t boundingBox(glyph_t g) override;
- glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed,
+ glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, const QFixedPoint&,
const QTransform &matrix, GlyphFormat) override;
QFixed capHeight() const override;
@@ -105,12 +105,19 @@ public:
qreal maxCharWidth() const override;
FaceId faceId() const override;
- bool supportsSubPixelPositions() const override;
+ bool supportsHorizontalSubPixelPositions() const override;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) override;
- QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) override;
- QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) override;
- QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color) override;
+ QImage alphaMapForGlyph(glyph_t glyph, const QFixedPoint &subPixelPosition) override;
+ QImage alphaMapForGlyph(glyph_t glyph,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t) override;
+ QImage alphaRGBMapForGlyph(glyph_t t,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &xform) override;
+ QImage bitmapForGlyph(glyph_t,
+ const QFixedPoint &subPixelPosition,
+ const QTransform &t,
+ const QColor &color) override;
QFontEngine *cloneWithSize(qreal pixelSize) const override;
Qt::HANDLE handle() const override;
@@ -126,7 +133,11 @@ public:
void initializeHeightMetrics() const override;
private:
- QImage imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform, const QColor &color = QColor());
+ QImage imageForGlyph(glyph_t t,
+ const QFixedPoint &subPixelPosition,
+ int margin,
+ const QTransform &xform,
+ const QColor &color = QColor());
void collectMetrics();
void renderGlyphRun(QImage *destination, float r, float g, float b, float a, IDWriteGlyphRunAnalysis *glyphAnalysis, const QRect &boundingRect);
static QString filenameFromFontFile(IDWriteFontFile *fontFile);
diff --git a/src/opengl/qopenglpaintengine.cpp b/src/opengl/qopenglpaintengine.cpp
index 3bb3496de5..9c8325ca11 100644
--- a/src/opengl/qopenglpaintengine.cpp
+++ b/src/opengl/qopenglpaintengine.cpp
@@ -1797,11 +1797,13 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly
if (recreateVertexArrays) {
cache->setPaintEnginePrivate(this);
if (!cache->populate(fe, staticTextItem->numGlyphs,
- staticTextItem->glyphs, staticTextItem->glyphPositions)) {
+ staticTextItem->glyphs, staticTextItem->glyphPositions,
+ s->renderHints)) {
// No space for glyphs in cache. We need to reset it and try again.
cache->clear();
cache->populate(fe, staticTextItem->numGlyphs,
- staticTextItem->glyphs, staticTextItem->glyphPositions);
+ staticTextItem->glyphs, staticTextItem->glyphPositions,
+ s->renderHints);
}
if (cache->hasPendingGlyphs()) {
@@ -1874,10 +1876,15 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly
textureCoordinates->clear();
bool supportsSubPixelPositions = fe->supportsSubPixelPositions();
+ bool verticalSubPixelPositions = fe->supportsVerticalSubPixelPositions()
+ && (s->renderHints & QPainter::VerticalSubpixelPositioning) != 0;
for (int i=0; i<staticTextItem->numGlyphs; ++i) {
- QFixed subPixelPosition;
- if (supportsSubPixelPositions)
- subPixelPosition = fe->subPixelPositionForX(staticTextItem->glyphPositions[i].x);
+ QFixedPoint subPixelPosition;
+ if (supportsSubPixelPositions) {
+ subPixelPosition = fe->subPixelPositionFor(staticTextItem->glyphPositions[i]);
+ if (!verticalSubPixelPositions)
+ subPixelPosition.y = 0;
+ }
QTextureGlyphCache::GlyphAndSubPixelPosition glyph(staticTextItem->glyphs[i], subPixelPosition);
@@ -1886,7 +1893,10 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly
continue;
int x = qFloor(staticTextItem->glyphPositions[i].x.toReal() * cache->transform().m11()) + c.baseLineX - margin;
- int y = qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22()) - c.baseLineY - margin;
+ int y = verticalSubPixelPositions
+ ? qRound(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22())
+ : qFloor(staticTextItem->glyphPositions[i].y.toReal() * cache->transform().m22());
+ y -= c.baseLineY + margin;
vertexCoordinates->addQuad(QRectF(x, y, c.w, c.h));
textureCoordinates->addQuad(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
diff --git a/src/opengl/qopengltextureglyphcache.cpp b/src/opengl/qopengltextureglyphcache.cpp
index a38d4328cc..6c8971fddb 100644
--- a/src/opengl/qopengltextureglyphcache.cpp
+++ b/src/opengl/qopengltextureglyphcache.cpp
@@ -421,7 +421,9 @@ void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
}
}
-void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)
+void QOpenGLTextureGlyphCache::fillTexture(const Coord &c,
+ glyph_t glyph,
+ const QFixedPoint &subPixelPosition)
{
QOpenGLContext *ctx = QOpenGLContext::currentContext();
if (ctx == nullptr) {
diff --git a/src/opengl/qopengltextureglyphcache_p.h b/src/opengl/qopengltextureglyphcache_p.h
index 15ecd6209b..5b30881e55 100644
--- a/src/opengl/qopengltextureglyphcache_p.h
+++ b/src/opengl/qopengltextureglyphcache_p.h
@@ -115,7 +115,9 @@ public:
virtual void createTextureData(int width, int height) override;
virtual void resizeTextureData(int width, int height) override;
- virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition) override;
+ virtual void fillTexture(const Coord &c,
+ glyph_t glyph,
+ const QFixedPoint &subPixelPosition) override;
virtual int glyphPadding() const override;
virtual int maxTextureWidth() const override;
virtual int maxTextureHeight() const override;