diff options
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; |