diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2021-01-15 09:11:07 +0100 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2021-01-25 15:56:50 +0100 |
commit | d79a9b1a4f694a227ce62ccab9b44685a9755916 (patch) | |
tree | e943780120ee3abcf987ecd0c05440f9ed5a9b7b /src/gui/text/qfontengine.cpp | |
parent | 80e87ca05c2b421dbca9fc8f9a8f290a3eabc206 (diff) |
Implement vertical subpixel positioning where available
For some use cases, vertical subpixel positioning may be
useful, as it allows you to vertically align text with
other painting primitives. This does impose an overhead,
so we make it opt-int with a render hint on the painter.
Note that this is only supported on Freetype currently.
It might be possible to support on older macOS versions,
prior to Mojave (which has disabled subpixel positioning
entirely), but since it would have limited usefulness
and Freetype is cross-platform anyway, I skipped that.
Note: This drive-by-fixes an issue with subpixel
positioning where glyphs would always be offset by 1/64,
because we added the aliasing offset *after* we had
determined the closest subpixel position. The idea of
this, as far as I can understand, is rather to snap to
nearest subpixel position upwards, not to add an offset
to all glyphs, so it should be added before finding the
correct position. It had a subtle visual effect when
animating the position. It might be that we could get
rid of it entirely, as I haven't been able to reproduce
any issues with that, but I have moved it instead, to
match what I believe the intention was.
[ChangeLog][QtGui][Text] Added render hint flag
QPainter::VerticalSubpixelPositioning which will position
text at subpixel positions vertically whenever supported.
In absence of this, text position will be rounded
vertically as before.
Fixes: QTBUG-35682
Change-Id: I8ce7a72a64e5a0924dac7c244e3e07c2938bfd09
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src/gui/text/qfontengine.cpp')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 55 |
1 files changed, 32 insertions, 23 deletions
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); |