2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-15 12:36:27 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the test suite of the Qt Toolkit.
|
|
|
|
**
|
2016-01-15 12:36:27 +00:00
|
|
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
2012-09-19 12:28:29 +00:00
|
|
|
** 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
|
2015-01-28 08:44:43 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-15 12:36:27 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-09-19 12:28:29 +00:00
|
|
|
**
|
2016-01-15 12:36:27 +00:00
|
|
|
** 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.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-11-26 16:31:50 +00:00
|
|
|
#include <QTest>
|
2012-01-13 03:05:50 +00:00
|
|
|
#include <QtGui/QFontDatabase>
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
#include <qrawfont.h>
|
|
|
|
#include <private/qrawfont_p.h>
|
|
|
|
|
|
|
|
class tst_QRawFont: public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
#if !defined(QT_NO_RAWFONT)
|
|
|
|
private slots:
|
2011-08-17 23:24:09 +00:00
|
|
|
void init();
|
2012-01-13 03:05:50 +00:00
|
|
|
void initTestCase();
|
2011-08-17 23:24:09 +00:00
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
void invalidRawFont();
|
|
|
|
|
|
|
|
void explicitRawFontNotLoadedInDatabase_data();
|
|
|
|
void explicitRawFontNotLoadedInDatabase();
|
|
|
|
|
|
|
|
void explicitRawFontNotAvailableInSystem_data();
|
|
|
|
void explicitRawFontNotAvailableInSystem();
|
|
|
|
|
|
|
|
void correctFontData_data();
|
|
|
|
void correctFontData();
|
|
|
|
|
|
|
|
void glyphIndices();
|
|
|
|
|
|
|
|
void advances_data();
|
|
|
|
void advances();
|
|
|
|
|
|
|
|
void textLayout();
|
|
|
|
|
|
|
|
void fontTable_data();
|
|
|
|
void fontTable();
|
|
|
|
|
|
|
|
void supportedWritingSystems_data();
|
|
|
|
void supportedWritingSystems();
|
|
|
|
|
|
|
|
void supportsCharacter_data();
|
|
|
|
void supportsCharacter();
|
|
|
|
|
|
|
|
void supportsUcs4Character_data();
|
|
|
|
void supportsUcs4Character();
|
|
|
|
|
|
|
|
void fromFont_data();
|
|
|
|
void fromFont();
|
|
|
|
|
|
|
|
void copyConstructor_data();
|
|
|
|
void copyConstructor();
|
|
|
|
|
|
|
|
void detach_data();
|
|
|
|
void detach();
|
|
|
|
|
|
|
|
void unsupportedWritingSystem_data();
|
|
|
|
void unsupportedWritingSystem();
|
2011-05-06 13:45:37 +00:00
|
|
|
|
|
|
|
void rawFontSetPixelSize_data();
|
|
|
|
void rawFontSetPixelSize();
|
2011-07-19 16:36:05 +00:00
|
|
|
|
|
|
|
void multipleRawFontsFromData();
|
2014-05-12 07:09:24 +00:00
|
|
|
|
|
|
|
void rawFontFromInvalidData();
|
2015-11-25 12:47:27 +00:00
|
|
|
|
|
|
|
void kernedAdvances();
|
2018-01-08 12:29:38 +00:00
|
|
|
|
|
|
|
void fallbackFontsOrder();
|
|
|
|
|
2018-02-05 12:41:37 +00:00
|
|
|
void qtbug65923_partal_clone_data();
|
|
|
|
void qtbug65923_partal_clone();
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
private:
|
|
|
|
QString testFont;
|
|
|
|
QString testFontBoldItalic;
|
2016-08-03 12:45:02 +00:00
|
|
|
QString testFontOs2V1;
|
2011-04-27 10:05:43 +00:00
|
|
|
#endif // QT_NO_RAWFONT
|
|
|
|
};
|
|
|
|
|
|
|
|
#if !defined(QT_NO_RAWFONT)
|
|
|
|
Q_DECLARE_METATYPE(QFont::HintingPreference)
|
|
|
|
Q_DECLARE_METATYPE(QFont::Style)
|
|
|
|
Q_DECLARE_METATYPE(QFont::Weight)
|
|
|
|
Q_DECLARE_METATYPE(QFontDatabase::WritingSystem)
|
|
|
|
|
2011-08-17 23:24:09 +00:00
|
|
|
void tst_QRawFont::init()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
void tst_QRawFont::initTestCase()
|
|
|
|
{
|
|
|
|
testFont = QFINDTESTDATA("testfont.ttf");
|
|
|
|
testFontBoldItalic = QFINDTESTDATA("testfont_bold_italic.ttf");
|
2016-08-03 12:45:02 +00:00
|
|
|
testFontOs2V1 = QFINDTESTDATA("testfont_os2_v1.ttf");
|
2012-01-13 03:05:50 +00:00
|
|
|
if (testFont.isEmpty() || testFontBoldItalic.isEmpty())
|
|
|
|
QFAIL("qrawfont unittest font files not found!");
|
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
if (QFontDatabase::families().count() == 0)
|
2012-01-13 03:05:50 +00:00
|
|
|
QSKIP("No fonts available!!!");
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
void tst_QRawFont::invalidRawFont()
|
|
|
|
{
|
|
|
|
QRawFont font;
|
|
|
|
QVERIFY(!font.isValid());
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(font.pixelSize(), 0.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(font.familyName().isEmpty());
|
|
|
|
QCOMPARE(font.style(), QFont::StyleNormal);
|
|
|
|
QCOMPARE(font.weight(), -1);
|
|
|
|
QCOMPARE(font.ascent(), 0.0);
|
|
|
|
QCOMPARE(font.descent(), 0.0);
|
|
|
|
QVERIFY(font.glyphIndexesForString(QLatin1String("Test")).isEmpty());
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::explicitRawFontNotLoadedInDatabase_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::explicitRawFontNotLoadedInDatabase()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont font(testFont, 10, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
2020-08-06 06:47:37 +00:00
|
|
|
QVERIFY(!QFontDatabase::families().contains(font.familyName()));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::explicitRawFontNotAvailableInSystem_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::explicitRawFontNotAvailableInSystem()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont rawfont(testFont, 10, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
QFont font(rawfont.familyName(), 10);
|
|
|
|
|
|
|
|
QVERIFY(!font.exactMatch());
|
|
|
|
QVERIFY(font.family() != QFontInfo(font).family());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::correctFontData_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::addColumn<QString>("expectedFamilyName");
|
|
|
|
QTest::addColumn<QFont::Style>("style");
|
|
|
|
QTest::addColumn<QFont::Weight>("weight");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
QTest::addColumn<qreal>("unitsPerEm");
|
2011-05-02 08:06:44 +00:00
|
|
|
QTest::addColumn<qreal>("pixelSize");
|
2016-08-03 12:45:02 +00:00
|
|
|
QTest::addColumn<int>("capHeight");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
int hintingPreferences[] = {
|
|
|
|
int(QFont::PreferDefaultHinting),
|
|
|
|
int(QFont::PreferNoHinting),
|
|
|
|
int(QFont::PreferVerticalHinting),
|
|
|
|
int(QFont::PreferFullHinting),
|
|
|
|
-1
|
|
|
|
};
|
|
|
|
int *hintingPreference = hintingPreferences;
|
|
|
|
|
|
|
|
while (*hintingPreference >= 0) {
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFont;
|
2011-04-27 10:05:43 +00:00
|
|
|
QString title = fileName
|
|
|
|
+ QLatin1String(": hintingPreference=")
|
|
|
|
+ QString::number(*hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QString::fromLatin1("QtBidiTestFont")
|
|
|
|
<< QFont::StyleNormal
|
|
|
|
<< QFont::Normal
|
|
|
|
<< QFont::HintingPreference(*hintingPreference)
|
2013-06-17 10:01:00 +00:00
|
|
|
<< qreal(1000.0)
|
2016-08-03 12:45:02 +00:00
|
|
|
<< qreal(10.0)
|
|
|
|
<< 7;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
fileName = testFontBoldItalic;
|
2011-04-27 10:05:43 +00:00
|
|
|
title = fileName
|
|
|
|
+ QLatin1String(": hintingPreference=")
|
|
|
|
+ QString::number(*hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QString::fromLatin1("QtBidiTestFont")
|
|
|
|
<< QFont::StyleItalic
|
|
|
|
<< QFont::Bold
|
|
|
|
<< QFont::HintingPreference(*hintingPreference)
|
2013-06-17 10:01:00 +00:00
|
|
|
<< qreal(1000.0)
|
2016-08-03 12:45:02 +00:00
|
|
|
<< qreal(10.0)
|
|
|
|
<< 7;
|
|
|
|
|
|
|
|
fileName = testFontOs2V1;
|
|
|
|
title = fileName
|
|
|
|
+ QLatin1String(": hintingPreference=")
|
|
|
|
+ QString::number(*hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QString::fromLatin1("QtBidiTestFont")
|
|
|
|
<< QFont::StyleNormal
|
|
|
|
<< QFont::Normal
|
|
|
|
<< QFont::HintingPreference(*hintingPreference)
|
|
|
|
<< qreal(1000.0)
|
|
|
|
<< qreal(10.0)
|
|
|
|
<< 7;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
++hintingPreference;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::correctFontData()
|
|
|
|
{
|
|
|
|
QFETCH(QString, fileName);
|
|
|
|
QFETCH(QString, expectedFamilyName);
|
|
|
|
QFETCH(QFont::Style, style);
|
|
|
|
QFETCH(QFont::Weight, weight);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
QFETCH(qreal, unitsPerEm);
|
2011-05-02 08:06:44 +00:00
|
|
|
QFETCH(qreal, pixelSize);
|
2016-08-03 12:45:02 +00:00
|
|
|
QFETCH(int, capHeight);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QRawFont font(fileName, 10, hintingPreference);
|
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
QCOMPARE(font.familyName(), expectedFamilyName);
|
|
|
|
QCOMPARE(font.style(), style);
|
|
|
|
QCOMPARE(font.weight(), int(weight));
|
|
|
|
QCOMPARE(font.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(font.unitsPerEm(), unitsPerEm);
|
|
|
|
QCOMPARE(font.pixelSize(), pixelSize);
|
2016-08-03 12:45:02 +00:00
|
|
|
|
|
|
|
// Some platforms return the actual fractional height of the
|
|
|
|
// H character when the value is missing from the OS/2 table,
|
|
|
|
// so we ceil it off to match (any touched pixel counts).
|
|
|
|
QCOMPARE(qCeil(font.capHeight()), capHeight);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::glyphIndices()
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont font(testFont, 10);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("Foobar"));
|
|
|
|
QList<quint32> expectedGlyphIndices;
|
2011-04-27 10:05:43 +00:00
|
|
|
expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86;
|
|
|
|
|
|
|
|
QCOMPARE(glyphIndices, expectedGlyphIndices);
|
2012-10-11 13:19:34 +00:00
|
|
|
|
|
|
|
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);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::advances_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::advances()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont font(testFont, 10, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
QRawFontPrivate *font_d = QRawFontPrivate::get(font);
|
|
|
|
QVERIFY(font_d->fontEngine != 0);
|
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<quint32> glyphIndices;
|
2011-04-27 10:05:43 +00:00
|
|
|
glyphIndices << 44 << 83 << 83 << 70 << 69 << 86; // "Foobar"
|
|
|
|
|
|
|
|
bool supportsSubPixelPositions = font_d->fontEngine->supportsSubPixelPositions();
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<QPointF> advances = font.advancesForGlyphIndexes(glyphIndices);
|
2014-02-21 08:22:22 +00:00
|
|
|
|
2015-01-08 10:59:23 +00:00
|
|
|
bool mayDiffer = font_d->fontEngine->type() == QFontEngine::Freetype
|
|
|
|
&& (hintingPreference == QFont::PreferFullHinting
|
|
|
|
|| hintingPreference == QFont::PreferDefaultHinting);
|
2014-02-21 08:22:22 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < glyphIndices.size(); ++i) {
|
2015-01-08 10:59:23 +00:00
|
|
|
if ((i == 0 || i == 5) && mayDiffer) {
|
|
|
|
QVERIFY2(qRound(advances.at(i).x()) == 8
|
|
|
|
|| qRound(advances.at(i).x()) == 9,
|
|
|
|
qPrintable(QStringLiteral("%1 != %2 && %1 != %3")
|
|
|
|
.arg(qRound(advances.at(i).x()))
|
|
|
|
.arg(8)
|
|
|
|
.arg(9)));
|
|
|
|
} else {
|
|
|
|
QCOMPARE(qRound(advances.at(i).x()), 8);
|
2014-02-21 08:22:22 +00:00
|
|
|
}
|
2015-01-08 10:59:23 +00:00
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
if (supportsSubPixelPositions)
|
|
|
|
QVERIFY(advances.at(i).x() > 8.0);
|
|
|
|
|
|
|
|
QVERIFY(qFuzzyIsNull(advances.at(i).y()));
|
|
|
|
}
|
2012-10-11 13:19:34 +00:00
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
advances = font.advancesForGlyphIndexes(QList<quint32>());
|
2012-10-11 13:19:34 +00:00
|
|
|
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));
|
|
|
|
|
2014-02-21 08:22:22 +00:00
|
|
|
for (int i = 0; i < glyphIndices.size(); ++i) {
|
2015-01-08 10:59:23 +00:00
|
|
|
if ((i == 0 || i == 5) && mayDiffer) {
|
|
|
|
QVERIFY2(qRound(advances.at(i).x()) == 8
|
|
|
|
|| qRound(advances.at(i).x()) == 9,
|
|
|
|
qPrintable(QStringLiteral("%1 != %2 && %1 != %3")
|
|
|
|
.arg(qRound(advances.at(i).x()))
|
|
|
|
.arg(8)
|
|
|
|
.arg(9)));
|
|
|
|
} else {
|
|
|
|
QCOMPARE(qRound(advances.at(i).x()), 8);
|
2012-10-11 13:19:34 +00:00
|
|
|
}
|
2015-01-08 10:59:23 +00:00
|
|
|
|
2012-10-11 13:19:34 +00:00
|
|
|
if (supportsSubPixelPositions)
|
|
|
|
QVERIFY(advances.at(i).x() > 8.0);
|
|
|
|
|
|
|
|
QVERIFY(qFuzzyIsNull(advances.at(i).y()));
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::textLayout()
|
|
|
|
{
|
2020-11-02 18:48:25 +00:00
|
|
|
int id = QFontDatabase::addApplicationFont(testFont);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(id >= 0);
|
|
|
|
|
|
|
|
QString familyName = QString::fromLatin1("QtBidiTestFont");
|
|
|
|
QFont font(familyName);
|
2011-05-02 08:06:44 +00:00
|
|
|
font.setPixelSize(18.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
QCOMPARE(QFontInfo(font).family(), familyName);
|
|
|
|
|
|
|
|
QTextLayout layout(QLatin1String("Foobar"));
|
|
|
|
layout.setFont(font);
|
2012-05-15 17:02:53 +00:00
|
|
|
layout.setCacheEnabled(true);
|
2011-04-27 10:05:43 +00:00
|
|
|
layout.beginLayout();
|
|
|
|
layout.createLine();
|
|
|
|
layout.endLayout();
|
|
|
|
|
2011-05-10 07:43:00 +00:00
|
|
|
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
|
|
|
QCOMPARE(glyphRuns.size(), 1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2011-05-10 07:43:00 +00:00
|
|
|
QGlyphRun glyphs = glyphRuns.at(0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2011-05-10 07:43:00 +00:00
|
|
|
QRawFont rawFont = glyphs.rawFont();
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(rawFont.isValid());
|
|
|
|
QCOMPARE(rawFont.familyName(), familyName);
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 18.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<quint32> expectedGlyphIndices;
|
2011-04-27 10:05:43 +00:00
|
|
|
expectedGlyphIndices << 44 << 83 << 83 << 70 << 69 << 86;
|
|
|
|
|
|
|
|
QCOMPARE(glyphs.glyphIndexes(), expectedGlyphIndices);
|
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
QVERIFY(QFontDatabase::removeApplicationFont(id));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::fontTable_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QByteArray>("tagName");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
QTest::addColumn<int>("offset");
|
|
|
|
QTest::addColumn<quint32>("expectedValue");
|
|
|
|
|
|
|
|
QTest::newRow("Head table, magic number, default hinting")
|
|
|
|
<< QByteArray("head")
|
|
|
|
<< QFont::PreferDefaultHinting
|
|
|
|
<< 12
|
|
|
|
<< (QSysInfo::ByteOrder == QSysInfo::BigEndian
|
|
|
|
? 0x5F0F3CF5
|
|
|
|
: 0xF53C0F5F);
|
|
|
|
|
|
|
|
QTest::newRow("Head table, magic number, no hinting")
|
|
|
|
<< QByteArray("head")
|
|
|
|
<< QFont::PreferNoHinting
|
|
|
|
<< 12
|
|
|
|
<< (QSysInfo::ByteOrder == QSysInfo::BigEndian
|
|
|
|
? 0x5F0F3CF5
|
|
|
|
: 0xF53C0F5F);
|
|
|
|
|
|
|
|
QTest::newRow("Head table, magic number, vertical hinting")
|
|
|
|
<< QByteArray("head")
|
|
|
|
<< QFont::PreferVerticalHinting
|
|
|
|
<< 12
|
|
|
|
<< (QSysInfo::ByteOrder == QSysInfo::BigEndian
|
|
|
|
? 0x5F0F3CF5
|
|
|
|
: 0xF53C0F5F);
|
|
|
|
|
|
|
|
QTest::newRow("Head table, magic number, full hinting")
|
|
|
|
<< QByteArray("head")
|
|
|
|
<< QFont::PreferFullHinting
|
|
|
|
<< 12
|
|
|
|
<< (QSysInfo::ByteOrder == QSysInfo::BigEndian
|
|
|
|
? 0x5F0F3CF5
|
|
|
|
: 0xF53C0F5F);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::fontTable()
|
|
|
|
{
|
|
|
|
QFETCH(QByteArray, tagName);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
QFETCH(int, offset);
|
|
|
|
QFETCH(quint32, expectedValue);
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont font(testFont, 10, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
QByteArray table = font.fontTable(tagName);
|
|
|
|
QVERIFY(!table.isEmpty());
|
|
|
|
|
|
|
|
const quint32 *value = reinterpret_cast<const quint32 *>(table.constData() + offset);
|
|
|
|
QCOMPARE(*value, expectedValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef QList<QFontDatabase::WritingSystem> WritingSystemList;
|
|
|
|
Q_DECLARE_METATYPE(WritingSystemList)
|
|
|
|
|
|
|
|
void tst_QRawFont::supportedWritingSystems_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::addColumn<WritingSystemList>("writingSystems");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
for (int hintingPreference=QFont::PreferDefaultHinting;
|
|
|
|
hintingPreference<=QFont::PreferFullHinting;
|
|
|
|
++hintingPreference) {
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(QString::fromLatin1("testfont.ttf, hintingPreference=%1")
|
|
|
|
.arg(hintingPreference)))
|
2012-01-13 03:05:50 +00:00
|
|
|
<< testFont
|
2011-04-27 10:05:43 +00:00
|
|
|
<< (QList<QFontDatabase::WritingSystem>()
|
|
|
|
<< QFontDatabase::Latin
|
|
|
|
<< QFontDatabase::Hebrew
|
|
|
|
<< QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin
|
|
|
|
<< QFont::HintingPreference(hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(QString::fromLatin1("testfont_bold_italic.ttf, hintingPreference=%1")
|
|
|
|
.arg(hintingPreference)))
|
2012-01-13 03:05:50 +00:00
|
|
|
<< testFontBoldItalic
|
2011-04-27 10:05:43 +00:00
|
|
|
<< (QList<QFontDatabase::WritingSystem>()
|
|
|
|
<< QFontDatabase::Latin
|
|
|
|
<< QFontDatabase::Hebrew
|
|
|
|
<< QFontDatabase::Devanagari
|
|
|
|
<< QFontDatabase::Vietnamese) // Vietnamese uses same unicode bits as Latin
|
|
|
|
<< QFont::HintingPreference(hintingPreference);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::supportedWritingSystems()
|
|
|
|
{
|
|
|
|
QFETCH(QString, fileName);
|
|
|
|
QFETCH(WritingSystemList, writingSystems);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
|
|
|
QRawFont font(fileName, 10, hintingPreference);
|
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
WritingSystemList actualWritingSystems = font.supportedWritingSystems();
|
|
|
|
QCOMPARE(actualWritingSystems.size(), writingSystems.size());
|
|
|
|
|
|
|
|
foreach (QFontDatabase::WritingSystem writingSystem, writingSystems)
|
|
|
|
QVERIFY(actualWritingSystems.contains(writingSystem));
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::supportsCharacter_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
QTest::addColumn<QChar>("character");
|
|
|
|
QTest::addColumn<bool>("shouldBeSupported");
|
|
|
|
|
|
|
|
const char *fileNames[2] = {
|
2012-01-13 03:05:50 +00:00
|
|
|
"testfont.ttf",
|
|
|
|
"testfont_bold_italic.ttf"
|
2011-04-27 10:05:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (int hintingPreference=QFont::PreferDefaultHinting;
|
|
|
|
hintingPreference<=QFont::PreferFullHinting;
|
|
|
|
++hintingPreference) {
|
|
|
|
|
|
|
|
for (int i=0; i<2; ++i) {
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = QFINDTESTDATA(fileNames[i]);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// Latin text
|
|
|
|
for (char ch='!'; ch<='~'; ++ch) {
|
|
|
|
QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
|
|
|
|
.arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(hintingPreference)
|
|
|
|
<< QChar::fromLatin1(ch)
|
|
|
|
<< true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hebrew text
|
|
|
|
for (quint16 ch=0x05D0; ch<=0x05EA; ++ch) {
|
|
|
|
QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
|
|
|
|
.arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(hintingPreference)
|
|
|
|
<< QChar(ch)
|
|
|
|
<< true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(QString::fromLatin1("Missing character, %1, hintingPreference=%2")
|
|
|
|
.arg(fileName).arg(hintingPreference)))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(hintingPreference)
|
|
|
|
<< QChar(0xD8)
|
|
|
|
<< false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::supportsCharacter()
|
|
|
|
{
|
|
|
|
QFETCH(QString, fileName);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
QFETCH(QChar, character);
|
|
|
|
QFETCH(bool, shouldBeSupported);
|
|
|
|
|
|
|
|
QRawFont font(fileName, 10, hintingPreference);
|
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
QCOMPARE(font.supportsCharacter(character), shouldBeSupported);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::supportsUcs4Character_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
QTest::addColumn<quint32>("ucs4");
|
|
|
|
QTest::addColumn<bool>("shouldBeSupported");
|
|
|
|
|
|
|
|
// Gothic text
|
|
|
|
for (int hintingPreference=QFont::PreferDefaultHinting;
|
|
|
|
hintingPreference<=QFont::PreferFullHinting;
|
|
|
|
++hintingPreference) {
|
|
|
|
for (quint32 ch=0x10330; ch<=0x1034A; ++ch) {
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFont;
|
2011-04-27 10:05:43 +00:00
|
|
|
QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
|
|
|
|
.arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(hintingPreference)
|
|
|
|
<< ch
|
|
|
|
<< true;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFontBoldItalic;
|
2011-04-27 10:05:43 +00:00
|
|
|
QString title = QString::fromLatin1("%1, character=0x%2, hintingPreference=%3")
|
|
|
|
.arg(fileName).arg(QString::number(ch, 16)).arg(hintingPreference);
|
|
|
|
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(hintingPreference)
|
|
|
|
<< ch
|
|
|
|
<< false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::supportsUcs4Character()
|
|
|
|
{
|
|
|
|
QFETCH(QString, fileName);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
QFETCH(quint32, ucs4);
|
|
|
|
QFETCH(bool, shouldBeSupported);
|
|
|
|
|
|
|
|
QRawFont font(fileName, 10, hintingPreference);
|
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
|
|
|
QCOMPARE(font.supportsCharacter(ucs4), shouldBeSupported);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::fromFont_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("fileName");
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
QTest::addColumn<QString>("familyName");
|
|
|
|
QTest::addColumn<QFontDatabase::WritingSystem>("writingSystem");
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
QTest::addColumn<QFont::StyleStrategy>("styleStrategy");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
for (int i=QFont::PreferDefaultHinting; i<=QFont::PreferFullHinting; ++i) {
|
|
|
|
QString titleBase = QString::fromLatin1("%2, hintingPreference=%1, writingSystem=%3")
|
|
|
|
.arg(i);
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFont;
|
2011-04-27 10:05:43 +00:00
|
|
|
QFontDatabase::WritingSystem writingSystem = QFontDatabase::Any;
|
|
|
|
|
|
|
|
QString title = titleBase.arg(fileName).arg(writingSystem);
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(i)
|
|
|
|
<< "QtBidiTestFont"
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
<< writingSystem
|
|
|
|
<< QFont::PreferDefault;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFont;
|
2011-04-27 10:05:43 +00:00
|
|
|
QFontDatabase::WritingSystem writingSystem = QFontDatabase::Hebrew;
|
|
|
|
|
|
|
|
QString title = titleBase.arg(fileName).arg(writingSystem);
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(i)
|
|
|
|
<< "QtBidiTestFont"
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
<< writingSystem
|
|
|
|
<< QFont::PreferDefault;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QString fileName = testFont;
|
2011-04-27 10:05:43 +00:00
|
|
|
QFontDatabase::WritingSystem writingSystem = QFontDatabase::Latin;
|
|
|
|
|
|
|
|
QString title = titleBase.arg(fileName).arg(writingSystem);
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::HintingPreference(i)
|
|
|
|
<< "QtBidiTestFont"
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
<< writingSystem
|
|
|
|
<< QFont::PreferDefault;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
QString fileName = testFont;
|
|
|
|
QFontDatabase::WritingSystem writingSystem = QFontDatabase::Arabic;
|
|
|
|
|
|
|
|
QString title = QStringLiteral("No font merging + unsupported script");
|
|
|
|
QTest::newRow(qPrintable(title))
|
|
|
|
<< fileName
|
|
|
|
<< QFont::PreferDefaultHinting
|
|
|
|
<< "QtBidiTestFont"
|
|
|
|
<< writingSystem
|
|
|
|
<< QFont::NoFontMerging;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::fromFont()
|
|
|
|
{
|
|
|
|
QFETCH(QString, fileName);
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
QFETCH(QString, familyName);
|
|
|
|
QFETCH(QFontDatabase::WritingSystem, writingSystem);
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
QFETCH(QFont::StyleStrategy, styleStrategy);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
int id = QFontDatabase::addApplicationFont(fileName);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(id >= 0);
|
|
|
|
|
|
|
|
QFont font(familyName);
|
|
|
|
font.setHintingPreference(hintingPreference);
|
2011-05-02 08:06:44 +00:00
|
|
|
font.setPixelSize(26.0);
|
Fix bug with NoFontMerging when font does not support script
When using NoFontMerging, no fallbacks should be resolved. If the
font does not support a specific character in the text, we should
display a box instead of merging it with another font.
But in practice, Qt would still apply the fallback mechanism for
one specific case: If the font itself does not support the script
of the text, we would get no match and do a search for a fallback
instead. Since NoFontMerging is set, we would then force this
as preresolved for *all* scripts in the QFont's private data
(logically, the match should only have a single response for
NoFontMerging).
The end result was that if you set the font family before updating
the text, you would get broken rendering. This can happen e.g. in
Qt Quick, where you could update the font family of a text label
while it contains characters which are not supported by the new
font. Qt would then pick a fallback instead. When you subsequently
update the text, the fallback would already be preresolved for
whatever script this is. If it does not support the updated text,
we would then see boxes, even if the requested font actually would
have supported it.
The fix is simply to do an additional pass if NoFontMerging is set
and we were not able to match with the specified script. Since
the same family might be available in different foundries, with
different writing system support, we still want to do a pass first
to see if we can match the exact script of the text.
Note that QRawFont::fromFont() exploited the bug by using
NoFontMerging for getting the fallback font for a specific
writing system. To keep this working without having to rewrite
fromFont() and risk introducing regressions, we add an argument
to make the findFont() function behave as before. It isn't
super-pretty, but since it is private API it is hopefully fine.
[ChangeLog][QtGui][Text] Fixed an issue with NoFontMerging and
changing font families dynamically, where boxes would be seen in
place of the correct text.
Pick-to: 5.15 6.1 6.2
Done-with: Andy Shaw
Fixes: QTBUG-81770
Change-Id: Ide9a36d7528a1040172c5864fa99e7a82eac4e83
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
2021-08-18 09:47:16 +00:00
|
|
|
if (styleStrategy != QFont::PreferDefault)
|
|
|
|
font.setStyleStrategy(styleStrategy);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QRawFont rawFont = QRawFont::fromFont(font, writingSystem);
|
|
|
|
QVERIFY(rawFont.isValid());
|
2011-08-17 23:24:09 +00:00
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QCOMPARE(rawFont.familyName(), familyName);
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 26.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
QVERIFY(QFontDatabase::removeApplicationFont(id));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::copyConstructor_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::copyConstructor()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
|
|
|
{
|
|
|
|
QString rawFontFamilyName;
|
2011-05-02 08:06:44 +00:00
|
|
|
qreal rawFontPixelSize;
|
2011-04-27 10:05:43 +00:00
|
|
|
qreal rawFontAscent;
|
|
|
|
qreal rawFontDescent;
|
|
|
|
int rawFontTableSize;
|
|
|
|
|
|
|
|
QRawFont outerRawFont;
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont rawFont(testFont, 11, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(rawFont.isValid());
|
|
|
|
|
|
|
|
rawFontFamilyName = rawFont.familyName();
|
|
|
|
rawFontPixelSize = rawFont.pixelSize();
|
|
|
|
rawFontAscent = rawFont.ascent();
|
|
|
|
rawFontDescent = rawFont.descent();
|
|
|
|
rawFontTableSize = rawFont.fontTable("glyf").size();
|
|
|
|
QVERIFY(rawFontTableSize > 0);
|
|
|
|
|
|
|
|
{
|
|
|
|
QRawFont otherRawFont(rawFont);
|
|
|
|
QVERIFY(otherRawFont.isValid());
|
|
|
|
QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(otherRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(otherRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
QRawFont otherRawFont = rawFont;
|
|
|
|
QVERIFY(otherRawFont.isValid());
|
|
|
|
QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(otherRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(otherRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
outerRawFont = rawFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
QVERIFY(outerRawFont.isValid());
|
|
|
|
QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(outerRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(outerRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(outerRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(outerRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::detach_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::detach()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
|
|
|
{
|
|
|
|
QString rawFontFamilyName;
|
2011-05-02 08:06:44 +00:00
|
|
|
qreal rawFontPixelSize;
|
2011-04-27 10:05:43 +00:00
|
|
|
qreal rawFontAscent;
|
|
|
|
qreal rawFontDescent;
|
|
|
|
int rawFontTableSize;
|
|
|
|
|
|
|
|
QRawFont outerRawFont;
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QRawFont rawFont(testFont, 11, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(rawFont.isValid());
|
|
|
|
|
|
|
|
rawFontFamilyName = rawFont.familyName();
|
|
|
|
rawFontPixelSize = rawFont.pixelSize();
|
|
|
|
rawFontAscent = rawFont.ascent();
|
|
|
|
rawFontDescent = rawFont.descent();
|
|
|
|
rawFontTableSize = rawFont.fontTable("glyf").size();
|
|
|
|
QVERIFY(rawFontTableSize > 0);
|
|
|
|
|
|
|
|
{
|
|
|
|
QRawFont otherRawFont(rawFont);
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
otherRawFont.loadFromFile(testFont, rawFontPixelSize, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QVERIFY(otherRawFont.isValid());
|
|
|
|
QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(otherRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(otherRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
QRawFont otherRawFont = rawFont;
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
otherRawFont.loadFromFile(testFont, rawFontPixelSize, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QVERIFY(otherRawFont.isValid());
|
|
|
|
QCOMPARE(otherRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(otherRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(otherRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(otherRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(otherRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(otherRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
outerRawFont = rawFont;
|
|
|
|
|
2012-01-13 03:05:50 +00:00
|
|
|
rawFont.loadFromFile(testFont, rawFontPixelSize, hintingPreference);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QVERIFY(outerRawFont.isValid());
|
|
|
|
QCOMPARE(outerRawFont.pixelSize(), rawFontPixelSize);
|
|
|
|
QCOMPARE(outerRawFont.familyName(), rawFontFamilyName);
|
|
|
|
QCOMPARE(outerRawFont.hintingPreference(), hintingPreference);
|
|
|
|
QCOMPARE(outerRawFont.ascent(), rawFontAscent);
|
|
|
|
QCOMPARE(outerRawFont.descent(), rawFontDescent);
|
|
|
|
QCOMPARE(outerRawFont.fontTable("glyf").size(), rawFontTableSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::unsupportedWritingSystem_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::unsupportedWritingSystem()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
int id = QFontDatabase::addApplicationFont(testFont);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QFont font("QtBidiTestFont");
|
|
|
|
font.setHintingPreference(hintingPreference);
|
2011-05-02 08:06:44 +00:00
|
|
|
font.setPixelSize(12.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QRawFont rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
|
|
|
|
QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont"));
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 12.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
rawFont = QRawFont::fromFont(font, QFontDatabase::Hebrew);
|
|
|
|
QCOMPARE(rawFont.familyName(), QString::fromLatin1("QtBidiTestFont"));
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 12.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
Fix fallback fonts for non-common writing system
When we request fallback fonts, we cannot discriminate the fonts
based on the writing system support. This is especially important
since common script is now merged with other scripts, meaning that
a common script character will always go through the fallback
mechanism when not supported by the main font. When drawing
for instance a string of Devanagari characters on macOS, we would
get a list of 33 fallback fonts, but almost all of them would be
the default Devanagari font, since none of the other fallbacks
would support that script. Meaning that we would just check the
same font over and over, which makes no sense. The fallback list
has been retrieved specifically for the given script, so we do
not need to consider that when fetching the fonts.
For most of the common set, we will not have noticed the bug,
because at least one of the writing system-specific fallbacks will
have had support for latin characters as well. But when trying to
mix emojis and some non-common script, we would get a box in
place of the emoji, which had been adopted to the main script and
would only be looked for in the fonts supporting this.
Note that this exposed an issue with the QRawFont test on some
systems. When the sample text contained a space, it would
be possible to get a fallback font for this character, since
we now effectively support fallbacks. This is not the correct
behavior, but it is unrelated to this fix, and it was not what
the QRawFont::unsupportedWritingSystem() test was written to
check. I have therefore removed the space from the sample text
to make the test pass, and will make a separate task of fixing
the issue of merging fonts for whitespace characters.
[ChangeLog][QtGui][Text] Fixed a bug where mixing different
writing systems with emojis could lead to missing glyphs.
Task-number: QTBUG-61882
Change-Id: I00f6043bb01af1f2277723ccf643034aebf3e18f
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
2018-01-04 08:02:23 +00:00
|
|
|
QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic).simplified().remove(QLatin1Char(' '));
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
QTextLayout layout;
|
|
|
|
layout.setFont(font);
|
|
|
|
layout.setText(arabicText);
|
2012-05-15 17:02:53 +00:00
|
|
|
layout.setCacheEnabled(true);
|
2011-04-27 10:05:43 +00:00
|
|
|
layout.beginLayout();
|
|
|
|
layout.createLine();
|
|
|
|
layout.endLayout();
|
|
|
|
|
2011-05-10 07:43:00 +00:00
|
|
|
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
|
|
|
QCOMPARE(glyphRuns.size(), 1);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2011-05-10 07:43:00 +00:00
|
|
|
QGlyphRun glyphs = glyphRuns.at(0);
|
|
|
|
QRawFont layoutFont = glyphs.rawFont();
|
2011-04-27 10:05:43 +00:00
|
|
|
QVERIFY(layoutFont.familyName() != QString::fromLatin1("QtBidiTestFont"));
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(layoutFont.pixelSize(), 12.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
rawFont = QRawFont::fromFont(font, QFontDatabase::Arabic);
|
|
|
|
QCOMPARE(rawFont.familyName(), layoutFont.familyName());
|
2011-05-02 08:06:44 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 12.0);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
QFontDatabase::removeApplicationFont(id);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2011-05-06 13:45:37 +00:00
|
|
|
void tst_QRawFont::rawFontSetPixelSize_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QFont::HintingPreference>("hintingPreference");
|
|
|
|
|
|
|
|
QTest::newRow("Default hinting preference") << QFont::PreferDefaultHinting;
|
|
|
|
QTest::newRow("No hinting preference") << QFont::PreferNoHinting;
|
|
|
|
QTest::newRow("Vertical hinting preference") << QFont::PreferVerticalHinting;
|
|
|
|
QTest::newRow("Full hinting preference") << QFont::PreferFullHinting;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::rawFontSetPixelSize()
|
|
|
|
{
|
|
|
|
QFETCH(QFont::HintingPreference, hintingPreference);
|
|
|
|
|
|
|
|
QTextLayout layout("Foobar");
|
|
|
|
|
|
|
|
QFont font = layout.font();
|
|
|
|
font.setHintingPreference(hintingPreference);
|
|
|
|
font.setPixelSize(12);
|
|
|
|
layout.setFont(font);
|
|
|
|
|
2012-05-15 17:02:53 +00:00
|
|
|
layout.setCacheEnabled(true);
|
2011-05-06 13:45:37 +00:00
|
|
|
layout.beginLayout();
|
|
|
|
layout.createLine();
|
|
|
|
layout.endLayout();
|
|
|
|
|
2011-05-10 23:53:54 +00:00
|
|
|
QGlyphRun glyphs = layout.glyphRuns().at(0);
|
|
|
|
QRawFont rawFont = glyphs.rawFont();
|
2011-05-06 13:45:37 +00:00
|
|
|
QCOMPARE(rawFont.pixelSize(), 12.0);
|
|
|
|
|
|
|
|
rawFont.setPixelSize(24);
|
|
|
|
QCOMPARE(rawFont.pixelSize(), 24.0);
|
|
|
|
}
|
|
|
|
|
2011-07-19 16:36:05 +00:00
|
|
|
void tst_QRawFont::multipleRawFontsFromData()
|
|
|
|
{
|
2012-01-13 03:05:50 +00:00
|
|
|
QFile file(testFont);
|
2011-07-19 16:36:05 +00:00
|
|
|
QRawFont testFont;
|
|
|
|
if (file.open(QIODevice::ReadOnly)) {
|
|
|
|
testFont.loadFromData(file.readAll(), 11, QFont::PreferDefaultHinting);
|
|
|
|
file.close();
|
|
|
|
}
|
2012-01-13 03:05:50 +00:00
|
|
|
file.setFileName(testFontBoldItalic);
|
2011-07-19 16:36:05 +00:00
|
|
|
QRawFont testFontBoldItalic;
|
|
|
|
if (file.open(QIODevice::ReadOnly))
|
|
|
|
testFontBoldItalic.loadFromData(file.readAll(), 11, QFont::PreferDefaultHinting);
|
|
|
|
|
|
|
|
QVERIFY(testFont.familyName() != (testFontBoldItalic.familyName())
|
2012-04-24 10:06:33 +00:00
|
|
|
|| testFont.style() != (testFontBoldItalic.style()));
|
2011-07-19 16:36:05 +00:00
|
|
|
}
|
|
|
|
|
2014-05-12 07:09:24 +00:00
|
|
|
void tst_QRawFont::rawFontFromInvalidData()
|
|
|
|
{
|
|
|
|
QByteArray invalidData("foobar");
|
|
|
|
QRawFont font;
|
|
|
|
font.loadFromData(invalidData, 10, QFont::PreferDefaultHinting);
|
|
|
|
|
|
|
|
QVERIFY(!font.isValid());
|
2014-05-15 11:32:27 +00:00
|
|
|
|
2015-01-15 13:00:19 +00:00
|
|
|
invalidData.fill(char(255), 1024);
|
2014-05-15 11:32:27 +00:00
|
|
|
font.loadFromData(invalidData, 10, QFont::PreferDefaultHinting);
|
|
|
|
|
|
|
|
QVERIFY(!font.isValid());
|
2014-05-12 07:09:24 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 12:47:27 +00:00
|
|
|
#define FUZZY_LTEQ(X, Y) (X < Y || qFuzzyCompare(X, Y))
|
|
|
|
|
|
|
|
void tst_QRawFont::kernedAdvances()
|
|
|
|
{
|
|
|
|
const int emSquareSize = 1000;
|
|
|
|
const qreal pixelSize = 16.0;
|
|
|
|
const int underScoreAW = 500;
|
|
|
|
const int underscoreTwoKerning = -500;
|
|
|
|
const qreal errorMargin = 1.0 / 16.0; // Fixed point error margin
|
|
|
|
|
|
|
|
QRawFont font(testFont, pixelSize);
|
|
|
|
QVERIFY(font.isValid());
|
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<quint32> glyphIndexes = font.glyphIndexesForString(QStringLiteral("__"));
|
2015-11-25 12:47:27 +00:00
|
|
|
QCOMPARE(glyphIndexes.size(), 2);
|
|
|
|
|
2020-06-23 08:04:16 +00:00
|
|
|
QList<QPointF> advances = font.advancesForGlyphIndexes(glyphIndexes, QRawFont::KernedAdvances);
|
2015-11-25 12:47:27 +00:00
|
|
|
QCOMPARE(advances.size(), 2);
|
|
|
|
|
|
|
|
qreal expectedAdvanceWidth = pixelSize * underScoreAW / emSquareSize;
|
|
|
|
QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin));
|
|
|
|
|
|
|
|
glyphIndexes = font.glyphIndexesForString(QStringLiteral("_2"));
|
|
|
|
QCOMPARE(glyphIndexes.size(), 2);
|
|
|
|
|
|
|
|
advances = font.advancesForGlyphIndexes(glyphIndexes, QRawFont::KernedAdvances);
|
|
|
|
QCOMPARE(advances.size(), 2);
|
|
|
|
|
|
|
|
expectedAdvanceWidth = pixelSize * (underScoreAW + underscoreTwoKerning) / emSquareSize;
|
|
|
|
QVERIFY(FUZZY_LTEQ(qAbs(advances.at(0).x() - expectedAdvanceWidth), errorMargin));
|
|
|
|
}
|
|
|
|
|
2018-01-08 12:29:38 +00:00
|
|
|
void tst_QRawFont::fallbackFontsOrder()
|
|
|
|
{
|
2020-11-02 18:48:25 +00:00
|
|
|
int id = QFontDatabase::addApplicationFont(testFont);
|
2018-01-08 12:29:38 +00:00
|
|
|
|
|
|
|
QFont font("QtBidiTestFont");
|
|
|
|
font.setPixelSize(12.0);
|
|
|
|
|
|
|
|
QString arabicText = QFontDatabase::writingSystemSample(QFontDatabase::Arabic);
|
|
|
|
|
|
|
|
// If this fails, then the writing system sample has changed and we need to create
|
|
|
|
// a new text containing both a space and Arabic characters.
|
|
|
|
QVERIFY(arabicText.contains(QLatin1Char(' ')));
|
|
|
|
|
|
|
|
QTextLayout layout;
|
|
|
|
layout.setFont(font);
|
|
|
|
layout.setText(arabicText);
|
|
|
|
layout.setCacheEnabled(true);
|
|
|
|
layout.beginLayout();
|
|
|
|
layout.createLine();
|
|
|
|
layout.endLayout();
|
|
|
|
|
|
|
|
QList<QGlyphRun> glyphRuns = layout.glyphRuns();
|
|
|
|
|
2018-06-29 13:29:55 +00:00
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
QEXPECT_FAIL("", "QTBUG-69217", Continue);
|
|
|
|
#endif
|
2018-01-08 12:29:38 +00:00
|
|
|
// Since QtBidiTestFont does not support Arabic nor the space, both should map to
|
|
|
|
// the same font. If this fails, it is an indication that the list of fallbacks fonts
|
|
|
|
// is not sorted by writing system support.
|
|
|
|
QCOMPARE(glyphRuns.size(), 1);
|
|
|
|
|
2020-11-02 18:48:25 +00:00
|
|
|
QFontDatabase::removeApplicationFont(id);
|
2018-01-08 12:29:38 +00:00
|
|
|
}
|
|
|
|
|
2018-02-05 12:41:37 +00:00
|
|
|
void tst_QRawFont::qtbug65923_partal_clone_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<bool>("shouldClone");
|
|
|
|
|
|
|
|
QTest::newRow("Without cloning font engine") << false;
|
|
|
|
QTest::newRow("Cloning font engine") << true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_QRawFont::qtbug65923_partal_clone()
|
|
|
|
{
|
|
|
|
QFile file(testFont);
|
|
|
|
file.open(QIODevice::ReadOnly);
|
|
|
|
QByteArray fontData = file.readAll();
|
|
|
|
|
|
|
|
QRawFont outerFont;
|
|
|
|
|
|
|
|
{
|
|
|
|
QRawFont innerFont(fontData, 16, QFont::PreferDefaultHinting);
|
|
|
|
|
|
|
|
QFETCH(bool, shouldClone);
|
|
|
|
if (shouldClone) {
|
|
|
|
// This will trigger QFontEngine::cloneWithSize
|
|
|
|
innerFont.setPixelSize(innerFont.pixelSize() + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
outerFont = innerFont;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will detach if data is shared with the raw font. If the raw font has
|
|
|
|
// a naked reference to the data, without informing Qt of it via the ref count
|
|
|
|
// of the byte array, this will result in clearing 'live' data.
|
|
|
|
fontData.fill('\0');
|
|
|
|
|
|
|
|
QVERIFY(!outerFont.boundingRect(42).isEmpty());
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
#endif // QT_NO_RAWFONT
|
|
|
|
|
|
|
|
QTEST_MAIN(tst_QRawFont)
|
|
|
|
#include "tst_qrawfont.moc"
|
|
|
|
|