diff options
author | Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com> | 2015-08-17 17:59:06 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@theqtcompany.com> | 2015-09-02 09:11:31 +0000 |
commit | 54dbdc26bacd3ab776c99ebef734404ef2e08ce5 (patch) | |
tree | 6c3d5614ea3beefd023ab0a259ecf207655ba2ce /src/gui/text/qfontengine.cpp | |
parent | ba94e26b8b233456b004084892464ec55b20800c (diff) |
Move min left/right bearing calculations to QFontEngine baseclass
The logic used in the FreeType font engine can be generalized
and move to the QFontEngine baseclass. This allows the CoreText
font engine to correctly report the minimum left/right bearings,
which decreases the chance that an optimization in QTextLayout's
line breaking algorithm will produce wrong results.
The calculation of left and right bearing has been moved to the
glyph_metrics_t type to reduce code duplication. This allows us
to use the with and height of the bounding box to determine if
the glyph has any contours.
Change-Id: I864697d3f31ed56f22f04666199b6c5023c5e585
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@theqtcompany.com>
Diffstat (limited to 'src/gui/text/qfontengine.cpp')
-rw-r--r-- | src/gui/text/qfontengine.cpp | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 2087bad9f6..102946b545 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -54,6 +54,7 @@ #include <private/qharfbuzz_p.h> #include <algorithm> +#include <limits.h> QT_BEGIN_NAMESPACE @@ -235,10 +236,14 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines() // QFontEngine +#define kBearingNotInitialized std::numeric_limits<qreal>::max() + QFontEngine::QFontEngine(Type type) : m_type(type), ref(0), font_(0), font_destroy_func(0), - face_(0), face_destroy_func(0) + face_(0), face_destroy_func(0), + m_minLeftBearing(kBearingNotInitialized), + m_minRightBearing(kBearingNotInitialized) { faceData.user_data = this; faceData.get_font_table = qt_get_font_table_default; @@ -562,11 +567,55 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) { glyph_metrics_t gi = boundingBox(glyph); - bool isValid = gi.isValid(); if (leftBearing != 0) - *leftBearing = isValid ? gi.x.toReal() : 0.0; + *leftBearing = gi.leftBearing().toReal(); if (rightBearing != 0) - *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0; + *rightBearing = gi.rightBearing().toReal(); +} + +qreal QFontEngine::minLeftBearing() const +{ + if (m_minLeftBearing == kBearingNotInitialized) + minRightBearing(); // Initializes both (see below) + + return m_minLeftBearing; +} + +qreal QFontEngine::minRightBearing() const +{ + if (m_minRightBearing == kBearingNotInitialized) { + + // To balance performance and correctness we only look at a subset of the + // possible glyphs in the font, based on which characters are more likely + // to have a left or right bearing. + static const ushort characterSubset[] = { + '(', 'C', 'F', 'K', 'V', 'X', 'Y', ']', '_', 'f', 'r', '|', + 127, 205, 645, 884, 922, 1070, 12386 + }; + + // The font may have minimum bearings larger than 0, so we have to start at the max + m_minLeftBearing = m_minRightBearing = std::numeric_limits<qreal>::max(); + + for (uint i = 0; i < (sizeof(characterSubset) / sizeof(ushort)); ++i) { + const glyph_t glyph = glyphIndex(characterSubset[i]); + if (!glyph) + continue; + + glyph_metrics_t glyphMetrics = const_cast<QFontEngine *>(this)->boundingBox(glyph); + + // Glyphs with no contours shouldn't contribute to bearings + if (!glyphMetrics.width || !glyphMetrics.height) + continue; + + m_minLeftBearing = qMin(m_minLeftBearing, glyphMetrics.leftBearing().toReal()); + m_minRightBearing = qMin(m_minRightBearing, glyphMetrics.rightBearing().toReal()); + } + + if (m_minLeftBearing == kBearingNotInitialized || m_minRightBearing == kBearingNotInitialized) + qWarning() << "Failed to compute left/right minimum bearings for" << fontDef.family; + } + + return m_minRightBearing; } glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs) @@ -1469,8 +1518,7 @@ QFixed QFontEngine::lastRightBearing(const QGlyphLayout &glyphs, bool round) glyph_t glyph = glyphs.glyphs[glyphs.numGlyphs - 1]; glyph_metrics_t gi = boundingBox(glyph); if (gi.isValid()) - return round ? QFixed(qRound(gi.xoff - gi.x - gi.width)) - : QFixed(gi.xoff - gi.x - gi.width); + return round ? qRound(gi.rightBearing()) : gi.rightBearing(); } return 0; } |