1289bc8172
Move some code (like registrations of meta types) from init() to initTestCase() in the process. Change-Id: I57db5156647cfadab554fbed853b2e68b2815f3b Reviewed-by: Frederik Gladhorn <frederik.gladhorn@theqtcompany.com>
335 lines
10 KiB
C++
335 lines
10 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
** Contact: http://www.qt.io/licensing/
|
|
**
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:LGPL21$
|
|
** 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 http://www.qt.io/terms-conditions. For further
|
|
** information use the contact form at http://www.qt.io/contact-us.
|
|
**
|
|
** GNU Lesser General Public License Usage
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
** following information to ensure the GNU Lesser General Public License
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
**
|
|
** As a special exception, The Qt Company gives you certain additional
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
|
|
#include <QtTest/QtTest>
|
|
#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 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;
|
|
QFontDatabase fdb;
|
|
|
|
// Query the QFontDatabase for a specific font, store the
|
|
// result in family, style and size.
|
|
QStringList families = fdb.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 = fdb.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 (fdb.isSmoothlyScalable(family, style)) {
|
|
// smoothly scalable font... don't need to load every pointsize
|
|
font = fdb.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 = fdb.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 = fdb.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.width(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::ForceIntegerMetrics);
|
|
QFontMetrics 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";
|
|
int textWidth = fm.width(text, -1, Qt::TextBypassShaping);
|
|
QVERIFY(textWidth != 0);
|
|
int charsWidth = 0;
|
|
for (int i = 0; i < text.size(); ++i)
|
|
charsWidth += fm.width(text[i]);
|
|
// This assertion is needed in Qt WebKit's WebCore::Font::offsetForPositionForSimpleText
|
|
QCOMPARE(textWidth, charsWidth);
|
|
}
|
|
|
|
template<class FontMetrics> 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());
|
|
int 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);
|
|
int 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;
|
|
int width_small = fm.width(text1_el);
|
|
QCOMPARE(fm.elidedText(text1,Qt::ElideRight, width_small + 1), text1_el);
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedMultiLength()
|
|
{
|
|
elidedMultiLength_helper<QFontMetrics>();
|
|
}
|
|
|
|
void tst_QFontMetrics::elidedMultiLengthF()
|
|
{
|
|
elidedMultiLength_helper<QFontMetricsF>();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
QTEST_MAIN(tst_QFontMetrics)
|
|
#include "tst_qfontmetrics.moc"
|