diff options
-rw-r--r-- | src/gui/text/qrawfont.cpp | 70 | ||||
-rw-r--r-- | src/gui/text/qrawfont.h | 10 | ||||
-rw-r--r-- | tests/auto/gui/text/qrawfont/tst_qrawfont.cpp | 45 |
3 files changed, 86 insertions, 39 deletions
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index dee1abcfbc..f1191bc4b9 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -388,10 +388,7 @@ qreal QRawFont::unitsPerEm() const */ qreal QRawFont::lineThickness() const { - if (!isValid()) - return 0.0; - - return d->fontEngine->lineThickness().toReal(); + return d->isValid() ? d->fontEngine->lineThickness().toReal() : 0.0; } /*! @@ -400,10 +397,7 @@ qreal QRawFont::lineThickness() const */ qreal QRawFont::underlinePosition() const { - if (!isValid()) - return 0.0; - - return d->fontEngine->underlinePosition().toReal(); + return d->isValid() ? d->fontEngine->underlinePosition().toReal() : 0.0; } /*! @@ -459,23 +453,28 @@ int QRawFont::weight() const */ QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const { - if (!d->isValid()) - return QVector<quint32>(); + QVector<quint32> glyphIndexes; + if (!d->isValid() || text.isEmpty()) + return glyphIndexes; + + int numGlyphs = text.size(); + glyphIndexes.resize(numGlyphs); - int nglyphs = text.size(); - QVarLengthGlyphLayoutArray glyphs(nglyphs); - if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) { - glyphs.resize(nglyphs); - if (!glyphIndexesForChars(text.data(), text.size(), glyphs.glyphs, &nglyphs)) { + QGlyphLayout glyphs; + glyphs.numGlyphs = numGlyphs; + glyphs.glyphs = glyphIndexes.data(); + if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) { + glyphIndexes.resize(numGlyphs); + + glyphs.numGlyphs = numGlyphs; + glyphs.glyphs = glyphIndexes.data(); + if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly)) { Q_ASSERT_X(false, Q_FUNC_INFO, "stringToCMap shouldn't fail twice"); return QVector<quint32>(); } } - QVector<quint32> glyphIndexes; - for (int i=0; i<nglyphs; ++i) - glyphIndexes.append(glyphs.glyphs[i]); - + glyphIndexes.resize(numGlyphs); return glyphIndexes; } @@ -491,38 +490,32 @@ QVector<quint32> QRawFont::glyphIndexesForString(const QString &text) const */ bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const { - if (!d->isValid()) + Q_ASSERT(numGlyphs); + if (!d->isValid() || numChars <= 0) { + *numGlyphs = 0; + return false; + } + + if (*numGlyphs <= 0 || !glyphIndexes) { + *numGlyphs = numChars; return false; + } QGlyphLayout glyphs; + glyphs.numGlyphs = *numGlyphs; glyphs.glyphs = glyphIndexes; return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QFontEngine::GlyphIndicesOnly); } /*! + \fn QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const + Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances give the distance from the position of a given glyph to where the next glyph should be drawn to make it appear as if the two glyphs are unspaced. \sa QTextLine::horizontalAdvance(), QFontMetricsF::width() */ -QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const -{ - if (!d->isValid()) - return QVector<QPointF>(); - - int numGlyphs = glyphIndexes.size(); - QVarLengthGlyphLayoutArray glyphs(numGlyphs); - memcpy(glyphs.glyphs, glyphIndexes.data(), numGlyphs * sizeof(quint32)); - - d->fontEngine->recalcAdvances(&glyphs, 0); - - QVector<QPointF> advances; - for (int i=0; i<numGlyphs; ++i) - advances.append(QPointF(glyphs.advances_x[i].toReal(), glyphs.advances_y[i].toReal())); - - return advances; -} /*! Returns the QRawFont's advances for each of the \a glyphIndexes in pixel units. The advances @@ -535,7 +528,8 @@ QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyph */ bool QRawFont::advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const { - if (!d->isValid()) + Q_ASSERT(glyphIndexes && advances); + if (!d->isValid() || numGlyphs <= 0) return false; QGlyphLayout glyphs; diff --git a/src/gui/text/qrawfont.h b/src/gui/text/qrawfont.h index 1dbde27c73..98314809e8 100644 --- a/src/gui/text/qrawfont.h +++ b/src/gui/text/qrawfont.h @@ -94,7 +94,7 @@ public: int weight() const; QVector<quint32> glyphIndexesForString(const QString &text) const; - QVector<QPointF> advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const; + inline QVector<QPointF> advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const; bool glyphIndexesForChars(const QChar *chars, int numChars, quint32 *glyphIndexes, int *numGlyphs) const; bool advancesForGlyphIndexes(const quint32 *glyphIndexes, QPointF *advances, int numGlyphs) const; @@ -147,6 +147,14 @@ private: Q_DECLARE_SHARED(QRawFont) +inline QVector<QPointF> QRawFont::advancesForGlyphIndexes(const QVector<quint32> &glyphIndexes) const +{ + QVector<QPointF> advances(glyphIndexes.size()); + if (advancesForGlyphIndexes(glyphIndexes.constData(), advances.data(), glyphIndexes.size())) + return advances; + return QVector<QPointF>(); +} + QT_END_NAMESPACE QT_END_HEADER diff --git a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp index 7a254546fe..c26964e764 100644 --- a/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp +++ b/tests/auto/gui/text/qrawfont/tst_qrawfont.cpp @@ -267,6 +267,24 @@ void tst_QRawFont::glyphIndices() expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86; QCOMPARE(glyphIndices, expectedGlyphIndices); + + glyphIndices = font.glyphIndexesForString(QString()); + QVERIFY(glyphIndices.isEmpty()); + + QString str(QLatin1String("Foobar")); + int numGlyphs = str.size(); + glyphIndices.resize(numGlyphs); + + QVERIFY(!font.glyphIndexesForChars(str.constData(), 0, glyphIndices.data(), &numGlyphs)); + QCOMPARE(numGlyphs, 0); + + QVERIFY(!font.glyphIndexesForChars(str.constData(), str.size(), glyphIndices.data(), &numGlyphs)); + QCOMPARE(numGlyphs, str.size()); + + QVERIFY(font.glyphIndexesForChars(str.constData(), str.size(), glyphIndices.data(), &numGlyphs)); + QCOMPARE(numGlyphs, str.size()); + + QCOMPARE(glyphIndices, expectedGlyphIndices); } void tst_QRawFont::advances_data() @@ -310,6 +328,33 @@ void tst_QRawFont::advances() QVERIFY(qFuzzyIsNull(advances.at(i).y())); } + + advances = font.advancesForGlyphIndexes(QVector<quint32>()); + QVERIFY(advances.isEmpty()); + + int numGlyphs = glyphIndices.size(); + advances.resize(numGlyphs); + + QVERIFY(!font.advancesForGlyphIndexes(glyphIndices.constData(), advances.data(), 0)); + + QVERIFY(font.advancesForGlyphIndexes(glyphIndices.constData(), advances.data(), numGlyphs)); + + for (int i=0; i<glyphIndices.size(); ++i) { +#ifdef Q_OS_WIN + // In Windows, freetype engine returns advance of 9 when full hinting is used (default) for + // some of the glyphs. + if (font_d->fontEngine->type() == QFontEngine::Freetype + && (hintingPreference == QFont::PreferFullHinting || hintingPreference == QFont::PreferDefaultHinting) + && (i == 0 || i == 5)) { + QEXPECT_FAIL("", "Advance for some glyphs is not the expected with Windows Freetype engine (9 instead of 8)", Continue); + } +#endif + QVERIFY(qFuzzyCompare(qRound(advances.at(i).x()), 8.0)); + if (supportsSubPixelPositions) + QVERIFY(advances.at(i).x() > 8.0); + + QVERIFY(qFuzzyIsNull(advances.at(i).y())); + } } void tst_QRawFont::textLayout() |