27d96b4789
Complete search and replace of QtTest and QtTest/QtTest with QTest, as QtTest includes the whole module. Replace all such instances with correct header includes. See Jira task for more discussion. Fixes: QTBUG-88831 Change-Id: I981cfae18a1cabcabcabee376016b086d9d01f44 Pick-to: 6.0 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
381 lines
12 KiB
C++
381 lines
12 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
|
** Commercial License Usage
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
** accordance with the commercial license agreement provided with the
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
**
|
|
** GNU General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
** General Public License version 3 as published by the Free Software
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
** included in the packaging of this file. Please review the following
|
|
** information to ensure the GNU General Public License requirements will
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <QTest>
|
|
#include <qfont.h>
|
|
#include <qfontmetrics.h>
|
|
#include <qfontdatabase.h>
|
|
#include <private/qfontengine_p.h>
|
|
#include <qstringlist.h>
|
|
#include <qlist.h>
|
|
|
|
class tst_QFontMetrics : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
void same();
|
|
void metrics();
|
|
void boundingRect();
|
|
void elidedText_data();
|
|
void elidedText();
|
|
void veryNarrowElidedText();
|
|
void averageCharWidth();
|
|
void bypassShaping();
|
|
void elidedMultiLength();
|
|
void elidedMultiLengthF();
|
|
void inFontUcs4();
|
|
void lineWidth();
|
|
void mnemonicTextWidth();
|
|
void leadingBelowLine();
|
|
void elidedMetrics();
|
|
void zeroWidthMetrics();
|
|
};
|
|
|
|
void tst_QFontMetrics::same()
|
|
{
|
|
QFont font;
|
|
font.setBold(true);
|
|
QFontMetrics fm(font);
|
|
const QString text = QLatin1String("Some stupid STRING");
|
|
QCOMPARE(fm.size(0, text), fm.size(0, text)) ;
|
|
|
|
for (int i = 10; i <= 32; ++i) {
|
|
font.setPixelSize(i);
|
|
QFontMetrics fm1(font);
|
|
QCOMPARE(fm1.size(0, text), fm1.size(0, text));
|
|
}
|
|
|
|
{
|
|
QImage image;
|
|
QFontMetrics fm2(font, &image);
|
|
QString text2 = QLatin1String("Foo Foo");
|
|
QCOMPARE(fm2.size(0, text2), fm2.size(0, text2)); //used to crash
|
|
}
|
|
|
|
{
|
|
QImage image;
|
|
QFontMetricsF fm3(font, &image);
|
|
QString text2 = QLatin1String("Foo Foo");
|
|
QCOMPARE(fm3.size(0, text2), fm3.size(0, text2)); //used to crash
|
|
}
|
|
}
|
|
|
|
|
|
void tst_QFontMetrics::metrics()
|
|
{
|
|
QFont font;
|
|
|
|
// Query the QFontDatabase for a specific font, store the
|
|
// result in family, style and size.
|
|
QStringList families = QFontDatabase::families();
|
|
if (families.isEmpty())
|
|
return;
|
|
|
|
QStringList::ConstIterator f_it, f_end = families.end();
|
|
for (f_it = families.begin(); f_it != f_end; ++f_it) {
|
|
const QString &family = *f_it;
|
|
|
|
QStringList styles = QFontDatabase::styles(family);
|
|
QStringList::ConstIterator s_it, s_end = styles.end();
|
|
for (s_it = styles.begin(); s_it != s_end; ++s_it) {
|
|
const QString &style = *s_it;
|
|
|
|
if (QFontDatabase::isSmoothlyScalable(family, style)) {
|
|
// smoothly scalable font... don't need to load every pointsize
|
|
font = QFontDatabase::font(family, style, 12);
|
|
|
|
QFontMetrics fontmetrics(font);
|
|
QCOMPARE(fontmetrics.ascent() + fontmetrics.descent(),
|
|
fontmetrics.height());
|
|
|
|
QCOMPARE(fontmetrics.height() + fontmetrics.leading(),
|
|
fontmetrics.lineSpacing());
|
|
} else {
|
|
QList<int> sizes = QFontDatabase::pointSizes(family, style);
|
|
QVERIFY(!sizes.isEmpty());
|
|
QList<int>::ConstIterator z_it, z_end = sizes.end();
|
|
for (z_it = sizes.begin(); z_it != z_end; ++z_it) {
|
|
const int size = *z_it;
|
|
|
|
// Initialize the font, and check if it is an exact match
|
|
font = QFontDatabase::font(family, style, size);
|
|
|
|
QFontMetrics fontmetrics(font);
|
|
QCOMPARE(fontmetrics.ascent() + fontmetrics.descent(),
|
|
fontmetrics.height());
|
|
QCOMPARE(fontmetrics.height() + fontmetrics.leading(),
|
|
fontmetrics.lineSpacing());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void tst_QFontMetrics::boundingRect()
|
|
{
|
|
QFont f;
|
|
f.setPointSize(24);
|
|
QFontMetrics fm(f);
|
|
QRect r = fm.boundingRect(QChar('Y'));
|
|
QVERIFY(r.top() < 0);
|
|
r = fm.boundingRect(QString("Y"));
|
|
QVERIFY(r.top() < 0);
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedText_data()
|
|
{
|
|
QTest::addColumn<QFont>("font");
|
|
QTest::addColumn<QString>("text");
|
|
|
|
QTest::newRow("helvetica hello") << QFont("helvetica",10) << QString("hello") ;
|
|
QTest::newRow("helvetica hello &Bye") << QFont("helvetica",10) << QString("hello&Bye") ;
|
|
}
|
|
|
|
|
|
void tst_QFontMetrics::elidedText()
|
|
{
|
|
QFETCH(QFont, font);
|
|
QFETCH(QString, text);
|
|
QFontMetrics fm(font);
|
|
int w = fm.horizontalAdvance(text);
|
|
QString newtext = fm.elidedText(text,Qt::ElideRight,w+1, 0);
|
|
QCOMPARE(text,newtext); // should not elide
|
|
newtext = fm.elidedText(text,Qt::ElideRight,w-1, 0);
|
|
QVERIFY(text != newtext); // should elide
|
|
}
|
|
|
|
void tst_QFontMetrics::veryNarrowElidedText()
|
|
{
|
|
QFont f;
|
|
QFontMetrics fm(f);
|
|
QString text("hello");
|
|
QCOMPARE(fm.elidedText(text, Qt::ElideRight, 0), QString());
|
|
}
|
|
|
|
void tst_QFontMetrics::averageCharWidth()
|
|
{
|
|
QFont f;
|
|
QFontMetrics fm(f);
|
|
QVERIFY(fm.averageCharWidth() != 0);
|
|
QFontMetricsF fmf(f);
|
|
QVERIFY(fmf.averageCharWidth() != 0);
|
|
}
|
|
|
|
void tst_QFontMetrics::bypassShaping()
|
|
{
|
|
QFont f;
|
|
f.setStyleStrategy(QFont::PreferNoShaping);
|
|
f.setKerning(false);
|
|
|
|
QFontMetricsF fm(f);
|
|
QString text = " A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z";
|
|
qreal textWidth = fm.horizontalAdvance(text);
|
|
QVERIFY(textWidth != 0);
|
|
qreal charsWidth = 0;
|
|
for (int i = 0; i < text.size(); ++i)
|
|
charsWidth += fm.horizontalAdvance(text[i]);
|
|
QCOMPARE(textWidth, charsWidth);
|
|
}
|
|
|
|
template<class FontMetrics, typename PrimitiveType> void elidedMultiLength_helper()
|
|
{
|
|
QString text1 = QLatin1String("Long Text 1\x9cShorter\x9csmall");
|
|
QString text1_long = "Long Text 1";
|
|
QString text1_short = "Shorter";
|
|
QString text1_small = "small";
|
|
FontMetrics fm = FontMetrics(QFont());
|
|
PrimitiveType width_long = fm.size(0, text1_long).width();
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, 8000), text1_long);
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long + 1), text1_long);
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_long - 1), text1_short);
|
|
PrimitiveType width_short = fm.size(0, text1_short).width();
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short + 1), text1_short);
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_short - 1), text1_small);
|
|
|
|
// Not even wide enough for "small" - should use ellipsis
|
|
QChar ellipsisChar(0x2026);
|
|
QString text1_el = QString::fromLatin1("s") + ellipsisChar;
|
|
PrimitiveType width_small = fm.horizontalAdvance(text1_el);
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_small + 1), text1_el);
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedMultiLength()
|
|
{
|
|
elidedMultiLength_helper<QFontMetrics, int>();
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedMultiLengthF()
|
|
{
|
|
elidedMultiLength_helper<QFontMetricsF, qreal>();
|
|
}
|
|
|
|
void tst_QFontMetrics::inFontUcs4()
|
|
{
|
|
int id = QFontDatabase::addApplicationFont(":/fonts/ucs4font.ttf");
|
|
QVERIFY(id >= 0);
|
|
|
|
QFont font("QtTestUcs4");
|
|
{
|
|
QFontMetrics fm(font);
|
|
QVERIFY(fm.inFontUcs4(0x1D7FF));
|
|
}
|
|
|
|
{
|
|
QFontMetricsF fm(font);
|
|
QVERIFY(fm.inFontUcs4(0x1D7FF));
|
|
}
|
|
|
|
{
|
|
QFontEngine *engine = QFontPrivate::get(font)->engineForScript(QChar::Script_Common);
|
|
QGlyphLayout glyphs;
|
|
glyphs.numGlyphs = 3;
|
|
uint buf[3];
|
|
glyphs.glyphs = buf;
|
|
|
|
QString string;
|
|
{
|
|
string.append(QChar::highSurrogate(0x1D7FF));
|
|
string.append(QChar::lowSurrogate(0x1D7FF));
|
|
|
|
glyphs.numGlyphs = 3;
|
|
glyphs.glyphs[0] = 0;
|
|
QVERIFY(engine->stringToCMap(string.constData(), string.size(),
|
|
&glyphs, &glyphs.numGlyphs,
|
|
QFontEngine::GlyphIndicesOnly));
|
|
QCOMPARE(glyphs.numGlyphs, 1);
|
|
QCOMPARE(glyphs.glyphs[0], uint(1));
|
|
}
|
|
{
|
|
string.clear();
|
|
string.append(QChar::ObjectReplacementCharacter);
|
|
|
|
glyphs.numGlyphs = 3;
|
|
glyphs.glyphs[0] = 0;
|
|
QVERIFY(engine->stringToCMap(string.constData(), string.size(),
|
|
&glyphs, &glyphs.numGlyphs,
|
|
QFontEngine::GlyphIndicesOnly));
|
|
QVERIFY(glyphs.glyphs[0] != 1);
|
|
}
|
|
}
|
|
|
|
QFontDatabase::removeApplicationFont(id);
|
|
}
|
|
|
|
void tst_QFontMetrics::lineWidth()
|
|
{
|
|
// QTBUG-13009, QTBUG-13011
|
|
QFont smallFont;
|
|
smallFont.setPointSize(8);
|
|
smallFont.setWeight(QFont::Light);
|
|
const QFontMetrics smallFontMetrics(smallFont);
|
|
|
|
QFont bigFont;
|
|
bigFont.setPointSize(40);
|
|
bigFont.setWeight(QFont::Black);
|
|
const QFontMetrics bigFontMetrics(bigFont);
|
|
|
|
QVERIFY(smallFontMetrics.lineWidth() >= 1);
|
|
QVERIFY(smallFontMetrics.lineWidth() < bigFontMetrics.lineWidth());
|
|
}
|
|
|
|
void tst_QFontMetrics::mnemonicTextWidth()
|
|
{
|
|
// QTBUG-41593
|
|
QFont f;
|
|
QFontMetrics fm(f);
|
|
const QString f1 = "File";
|
|
const QString f2 = "&File";
|
|
|
|
QCOMPARE(fm.size(Qt::TextShowMnemonic, f1), fm.size(Qt::TextShowMnemonic, f2));
|
|
QCOMPARE(fm.size(Qt::TextHideMnemonic, f1), fm.size(Qt::TextHideMnemonic, f2));
|
|
}
|
|
|
|
void tst_QFontMetrics::leadingBelowLine()
|
|
{
|
|
QScriptLine line;
|
|
line.leading = 10;
|
|
line.leadingIncluded = true;
|
|
line.ascent = 5;
|
|
QCOMPARE(line.height(), line.ascent + line.descent + line.leading);
|
|
QCOMPARE(line.base(), line.ascent);
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedMetrics()
|
|
{
|
|
QString testFont = QFINDTESTDATA("fonts/testfont.ttf");
|
|
QVERIFY(!testFont.isEmpty());
|
|
|
|
int id = QFontDatabase::addApplicationFont(testFont);
|
|
QVERIFY(id >= 0);
|
|
|
|
QFont font(QFontDatabase::applicationFontFamilies(id).at(0));
|
|
font.setPixelSize(12.0);
|
|
|
|
QFontMetricsF metrics(font);
|
|
QString s = QStringLiteral("VeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongText");
|
|
|
|
QRectF boundingRect = metrics.boundingRect(s);
|
|
|
|
QString elided = metrics.elidedText(s, Qt::ElideRight, boundingRect.width() / 2.0);
|
|
|
|
QRectF elidedBoundingRect = metrics.boundingRect(elided);
|
|
|
|
QCOMPARE(boundingRect.height(), elidedBoundingRect.height());
|
|
QCOMPARE(boundingRect.y(), elidedBoundingRect.y());
|
|
|
|
QFontDatabase::removeApplicationFont(id);
|
|
}
|
|
|
|
void tst_QFontMetrics::zeroWidthMetrics()
|
|
{
|
|
QString zwnj(QChar(0x200c));
|
|
QString zwsp(QChar(0x200b));
|
|
|
|
QFont font;
|
|
QFontMetricsF fm(font);
|
|
QCOMPARE(fm.horizontalAdvance(zwnj), 0);
|
|
QCOMPARE(fm.horizontalAdvance(zwsp), 0);
|
|
QCOMPARE(fm.boundingRect(zwnj).width(), 0);
|
|
QCOMPARE(fm.boundingRect(zwsp).width(), 0);
|
|
|
|
QString string1 = QStringLiteral("(") + zwnj + QStringLiteral(")");
|
|
QString string2 = QStringLiteral("(") + zwnj + zwnj + QStringLiteral(")");
|
|
QString string3 = QStringLiteral("(") + zwsp + QStringLiteral(")");
|
|
QString string4 = QStringLiteral("(") + zwsp + zwsp + QStringLiteral(")");
|
|
|
|
QCOMPARE(fm.horizontalAdvance(string1), fm.horizontalAdvance(string2));
|
|
QCOMPARE(fm.horizontalAdvance(string3), fm.horizontalAdvance(string4));
|
|
QCOMPARE(fm.boundingRect(string1).width(), fm.boundingRect(string2).width());
|
|
QCOMPARE(fm.boundingRect(string3).width(), fm.boundingRect(string4).width());
|
|
}
|
|
|
|
QTEST_MAIN(tst_QFontMetrics)
|
|
#include "tst_qfontmetrics.moc"
|