qt5base-lts/tests/auto/gui/text/qglyphrun/tst_qglyphrun.cpp
Jiang Jiang 8b4e40f535 Support adding application fonts with QFontconfigDatabase
QFontDatabaseQPA should be able to reinitialize database and
reregister all the fonts when an application font is added, because
it will trigger db->invalidate().

Add cloneWithSize support to QFontEngineBox so that even no usable
font is found in QFontDatabase, QRawFont::setPixelSize can still
work (without making the result rawfont invalid).

Register application fonts with QFontconfigDatabase, the code is
adapted from QFontDatabaseX11.

Reenable QRawFont tests for QPA, these usages are now supported in
QPA.

Fix QStaticText tests, raster in QPA does support transformations.
Translate the text before ZAxix rotation so that it will be visible
in canvas.

Add back fixedPitch support to QPA, and fix QFontDatabase tests.

Fix QGlyphRun tests, ignore non-existence glyphs in alphaMap
locking.

Fix QFontMetrics tests.

Task-number: QTBUG-21415, QTBUG-20754, QTBUG-20977,
             QTBUG-20976, QTBUG-20760, QTBUG-20759
Change-Id: I24aea7d6ec6b2ac6342134d1f2591327c23a692b
Reviewed-on: http://codereview.qt-project.org/5384
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
2011-09-23 10:48:37 +02:00

676 lines
17 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <qglyphrun.h>
#include <qpainter.h>
#include <qtextlayout.h>
#include <qfontdatabase.h>
// #define DEBUG_SAVE_IMAGE
class tst_QGlyphRun: public QObject
{
Q_OBJECT
#if !defined(QT_NO_RAWFONT)
private slots:
void initTestCase();
void init();
void cleanupTestCase();
void constructionAndDestruction();
void copyConstructor();
void assignment();
void equalsOperator_data();
void equalsOperator();
void textLayoutGlyphIndexes();
void drawExistingGlyphs();
void drawNonExistentGlyphs();
void drawMultiScriptText1();
void drawMultiScriptText2();
void drawStruckOutText();
void drawOverlinedText();
void drawUnderlinedText();
void drawRightToLeft();
void detach();
void setRawData();
void setRawDataAndGetAsVector();
private:
int m_testFontId;
QFont m_testFont;
bool m_testFont_ok;
#endif // QT_NO_RAWFONT
};
#if !defined(QT_NO_RAWFONT)
Q_DECLARE_METATYPE(QGlyphRun);
void tst_QGlyphRun::initTestCase()
{
m_testFont_ok = false;
m_testFontId = QFontDatabase::addApplicationFont(SRCDIR "test.ttf");
QVERIFY(m_testFontId >= 0);
m_testFont = QFont("QtsSpecialTestFont");
QCOMPARE(QFontInfo(m_testFont).family(), QString::fromLatin1("QtsSpecialTestFont"));
m_testFont_ok = true;
}
void tst_QGlyphRun::init()
{
if (!m_testFont_ok) {
QSKIP("Test font is not working correctly", SkipAll);
}
}
void tst_QGlyphRun::cleanupTestCase()
{
QFontDatabase::removeApplicationFont(m_testFontId);
}
void tst_QGlyphRun::constructionAndDestruction()
{
QGlyphRun glyphIndexes;
}
static QGlyphRun make_dummy_indexes()
{
QGlyphRun glyphs;
QVector<quint32> glyphIndexes;
QVector<QPointF> positions;
QFont font;
font.setPointSize(18);
glyphIndexes.append(1);
glyphIndexes.append(2);
glyphIndexes.append(3);
positions.append(QPointF(1, 2));
positions.append(QPointF(3, 4));
positions.append(QPointF(5, 6));
glyphs.setRawFont(QRawFont::fromFont(font));
glyphs.setGlyphIndexes(glyphIndexes);
glyphs.setPositions(positions);
return glyphs;
}
void tst_QGlyphRun::copyConstructor()
{
QGlyphRun glyphs;
{
QVector<quint32> glyphIndexes;
QVector<QPointF> positions;
QFont font;
font.setPointSize(18);
glyphIndexes.append(1);
glyphIndexes.append(2);
glyphIndexes.append(3);
positions.append(QPointF(1, 2));
positions.append(QPointF(3, 4));
positions.append(QPointF(5, 6));
glyphs.setRawFont(QRawFont::fromFont(font));
glyphs.setGlyphIndexes(glyphIndexes);
glyphs.setPositions(positions);
}
QGlyphRun otherGlyphs(glyphs);
QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
QCOMPARE(glyphs.positions(), otherGlyphs.positions());
}
void tst_QGlyphRun::assignment()
{
QGlyphRun glyphs(make_dummy_indexes());
QGlyphRun otherGlyphs = glyphs;
QCOMPARE(otherGlyphs.rawFont(), glyphs.rawFont());
QCOMPARE(glyphs.glyphIndexes(), otherGlyphs.glyphIndexes());
QCOMPARE(glyphs.positions(), otherGlyphs.positions());
}
void tst_QGlyphRun::equalsOperator_data()
{
QTest::addColumn<QGlyphRun>("one");
QTest::addColumn<QGlyphRun>("two");
QTest::addColumn<bool>("equals");
QGlyphRun one(make_dummy_indexes());
QGlyphRun two(make_dummy_indexes());
QTest::newRow("Identical") << one << two << true;
{
QGlyphRun busted(two);
QVector<QPointF> positions = busted.positions();
positions[2] += QPointF(1, 1);
busted.setPositions(positions);
QTest::newRow("Different positions") << one << busted << false;
}
{
QGlyphRun busted(two);
QFont font;
font.setPixelSize(busted.rawFont().pixelSize() * 2);
busted.setRawFont(QRawFont::fromFont(font));
QTest::newRow("Different fonts") << one << busted << false;
}
{
QGlyphRun busted(two);
QVector<quint32> glyphIndexes = busted.glyphIndexes();
glyphIndexes[2] += 1;
busted.setGlyphIndexes(glyphIndexes);
QTest::newRow("Different glyph indexes") << one << busted << false;
}
}
void tst_QGlyphRun::equalsOperator()
{
QFETCH(QGlyphRun, one);
QFETCH(QGlyphRun, two);
QFETCH(bool, equals);
QCOMPARE(one == two, equals);
QCOMPARE(one != two, !equals);
}
void tst_QGlyphRun::textLayoutGlyphIndexes()
{
QString s;
s.append(QLatin1Char('A'));
s.append(QChar(0xe000));
QTextLayout layout(s);
layout.setFont(m_testFont);
layout.beginLayout();
layout.createLine();
layout.endLayout();
QList<QGlyphRun> listOfGlyphs = layout.glyphRuns();
QCOMPARE(listOfGlyphs.size(), 1);
QGlyphRun glyphs = listOfGlyphs.at(0);
QCOMPARE(glyphs.glyphIndexes().size(), 2);
QCOMPARE(glyphs.glyphIndexes().at(0), quint32(2));
QCOMPARE(glyphs.glyphIndexes().at(1), quint32(1));
}
void tst_QGlyphRun::drawExistingGlyphs()
{
QPixmap textLayoutDraw(1000, 1000);
QPixmap drawGlyphs(1000, 1000);
textLayoutDraw.fill(Qt::white);
drawGlyphs.fill(Qt::white);
QString s;
s.append(QLatin1Char('A'));
s.append(QChar(0xe000));
QTextLayout layout(s);
layout.setFont(m_testFont);
layout.beginLayout();
layout.createLine();
layout.endLayout();
{
QPainter p(&textLayoutDraw);
layout.draw(&p, QPointF(50, 50));
}
QGlyphRun glyphs = layout.glyphRuns().size() > 0
? layout.glyphRuns().at(0)
: QGlyphRun();
{
QPainter p(&drawGlyphs);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawExistingGlyphs_textLayoutDraw.png");
drawGlyphs.save("drawExistingGlyphs_drawGlyphIndexes.png");
#endif
QCOMPARE(textLayoutDraw, drawGlyphs);
}
void tst_QGlyphRun::setRawData()
{
QGlyphRun glyphRun;
glyphRun.setRawFont(QRawFont::fromFont(m_testFont));
glyphRun.setGlyphIndexes(QVector<quint32>() << 2 << 2 << 2);
glyphRun.setPositions(QVector<QPointF>() << QPointF(2, 3) << QPointF(20, 3) << QPointF(10, 20));
QPixmap baseline(100, 50);
baseline.fill(Qt::white);
{
QPainter p(&baseline);
p.drawGlyphRun(QPointF(3, 2), glyphRun);
}
QGlyphRun baselineCopied = glyphRun;
quint32 glyphIndexArray[3] = { 2, 2, 2 };
QPointF glyphPositionArray[3] = { QPointF(2, 3), QPointF(20, 3), QPointF(10, 20) };
glyphRun.setRawData(glyphIndexArray, glyphPositionArray, 3);
QPixmap rawDataGlyphs(100, 50);
rawDataGlyphs.fill(Qt::white);
{
QPainter p(&rawDataGlyphs);
p.drawGlyphRun(QPointF(3, 2), glyphRun);
}
quint32 otherGlyphIndexArray[1] = { 2 };
QPointF otherGlyphPositionArray[1] = { QPointF(2, 3) };
glyphRun.setRawData(otherGlyphIndexArray, otherGlyphPositionArray, 1);
QPixmap baselineCopiedPixmap(100, 50);
baselineCopiedPixmap.fill(Qt::white);
{
QPainter p(&baselineCopiedPixmap);
p.drawGlyphRun(QPointF(3, 2), baselineCopied);
}
#if defined(DEBUG_SAVE_IMAGE)
baseline.save("setRawData_baseline.png");
rawDataGlyphs.save("setRawData_rawDataGlyphs.png");
baselineCopiedPixmap.save("setRawData_baselineCopiedPixmap.png");
#endif
QCOMPARE(rawDataGlyphs, baseline);
QCOMPARE(baselineCopiedPixmap, baseline);
}
void tst_QGlyphRun::setRawDataAndGetAsVector()
{
QVector<quint32> glyphIndexArray;
glyphIndexArray << 3 << 2 << 1 << 4;
QVector<QPointF> glyphPositionArray;
glyphPositionArray << QPointF(1, 2) << QPointF(3, 4) << QPointF(5, 6) << QPointF(7, 8);
QGlyphRun glyphRun;
glyphRun.setRawData(glyphIndexArray.constData(), glyphPositionArray.constData(), 4);
QVector<quint32> glyphIndexes = glyphRun.glyphIndexes();
QVector<QPointF> glyphPositions = glyphRun.positions();
QCOMPARE(glyphIndexes.size(), 4);
QCOMPARE(glyphPositions.size(), 4);
QCOMPARE(glyphIndexes, glyphIndexArray);
QCOMPARE(glyphPositions, glyphPositionArray);
QGlyphRun otherGlyphRun;
otherGlyphRun.setGlyphIndexes(glyphIndexArray);
otherGlyphRun.setPositions(glyphPositionArray);
QCOMPARE(glyphRun, otherGlyphRun);
}
void tst_QGlyphRun::drawNonExistentGlyphs()
{
QVector<quint32> glyphIndexes;
glyphIndexes.append(3);
QVector<QPointF> glyphPositions;
glyphPositions.append(QPointF(0, 0));
QGlyphRun glyphs;
glyphs.setGlyphIndexes(glyphIndexes);
glyphs.setPositions(glyphPositions);
glyphs.setRawFont(QRawFont::fromFont(m_testFont));
QPixmap image(1000, 1000);
image.fill(Qt::white);
QPixmap imageBefore = image;
{
QPainter p(&image);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
image.save("drawNonExistentGlyphs.png");
#endif
QCOMPARE(image, imageBefore); // Should be unchanged
}
void tst_QGlyphRun::drawMultiScriptText1()
{
QString text;
text += QChar(0x03D0); // Greek, beta
QTextLayout textLayout(text);
textLayout.beginLayout();
textLayout.createLine();
textLayout.endLayout();
QPixmap textLayoutDraw(1000, 1000);
textLayoutDraw.fill(Qt::white);
QPixmap drawGlyphs(1000, 1000);
drawGlyphs.fill(Qt::white);
QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
QCOMPARE(glyphsList.size(), 1);
{
QPainter p(&textLayoutDraw);
textLayout.draw(&p, QPointF(50, 50));
}
{
QPainter p(&drawGlyphs);
foreach (QGlyphRun glyphs, glyphsList)
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawMultiScriptText1_textLayoutDraw.png");
drawGlyphs.save("drawMultiScriptText1_drawGlyphIndexes.png");
#endif
QCOMPARE(drawGlyphs, textLayoutDraw);
}
void tst_QGlyphRun::drawMultiScriptText2()
{
QString text;
text += QChar(0x0621); // Arabic, Hamza
text += QChar(0x03D0); // Greek, beta
QTextLayout textLayout(text);
textLayout.beginLayout();
textLayout.createLine();
textLayout.endLayout();
QPixmap textLayoutDraw(1000, 1000);
textLayoutDraw.fill(Qt::white);
QPixmap drawGlyphs(1000, 1000);
drawGlyphs.fill(Qt::white);
QList<QGlyphRun> glyphsList = textLayout.glyphRuns();
QCOMPARE(glyphsList.size(), 2);
{
QPainter p(&textLayoutDraw);
textLayout.draw(&p, QPointF(50, 50));
}
{
QPainter p(&drawGlyphs);
foreach (QGlyphRun glyphs, glyphsList)
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawMultiScriptText2_textLayoutDraw.png");
drawGlyphs.save("drawMultiScriptText2_drawGlyphIndexes.png");
#endif
QCOMPARE(drawGlyphs, textLayoutDraw);
}
void tst_QGlyphRun::detach()
{
QGlyphRun glyphs;
glyphs.setGlyphIndexes(QVector<quint32>() << 1 << 2 << 3);
QGlyphRun otherGlyphs;
otherGlyphs = glyphs;
QCOMPARE(otherGlyphs.glyphIndexes(), glyphs.glyphIndexes());
otherGlyphs.setGlyphIndexes(QVector<quint32>() << 4 << 5 << 6);
QCOMPARE(otherGlyphs.glyphIndexes(), QVector<quint32>() << 4 << 5 << 6);
QCOMPARE(glyphs.glyphIndexes(), QVector<quint32>() << 1 << 2 << 3);
}
void tst_QGlyphRun::drawStruckOutText()
{
QPixmap textLayoutDraw(1000, 1000);
QPixmap drawGlyphs(1000, 1000);
textLayoutDraw.fill(Qt::white);
drawGlyphs.fill(Qt::white);
QString s = QString::fromLatin1("Foobar");
QFont font;
font.setStrikeOut(true);
QTextLayout layout(s);
layout.setFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
{
QPainter p(&textLayoutDraw);
layout.draw(&p, QPointF(50, 50));
}
QGlyphRun glyphs = layout.glyphRuns().size() > 0
? layout.glyphRuns().at(0)
: QGlyphRun();
{
QPainter p(&drawGlyphs);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawStruckOutText_textLayoutDraw.png");
drawGlyphs.save("drawStruckOutText_drawGlyphIndexes.png");
#endif
QCOMPARE(textLayoutDraw, drawGlyphs);
}
void tst_QGlyphRun::drawOverlinedText()
{
QPixmap textLayoutDraw(1000, 1000);
QPixmap drawGlyphs(1000, 1000);
textLayoutDraw.fill(Qt::white);
drawGlyphs.fill(Qt::white);
QString s = QString::fromLatin1("Foobar");
QFont font;
font.setOverline(true);
QTextLayout layout(s);
layout.setFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
{
QPainter p(&textLayoutDraw);
layout.draw(&p, QPointF(50, 50));
}
QGlyphRun glyphs = layout.glyphRuns().size() > 0
? layout.glyphRuns().at(0)
: QGlyphRun();
{
QPainter p(&drawGlyphs);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawOverlineText_textLayoutDraw.png");
drawGlyphs.save("drawOverlineText_drawGlyphIndexes.png");
#endif
QCOMPARE(textLayoutDraw, drawGlyphs);
}
void tst_QGlyphRun::drawUnderlinedText()
{
QPixmap textLayoutDraw(1000, 1000);
QPixmap drawGlyphs(1000, 1000);
textLayoutDraw.fill(Qt::white);
drawGlyphs.fill(Qt::white);
QString s = QString::fromLatin1("Foobar");
QFont font;
font.setUnderline(true);
QTextLayout layout(s);
layout.setFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
{
QPainter p(&textLayoutDraw);
layout.draw(&p, QPointF(50, 50));
}
QGlyphRun glyphs = layout.glyphRuns().size() > 0
? layout.glyphRuns().at(0)
: QGlyphRun();
{
QPainter p(&drawGlyphs);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawUnderlineText_textLayoutDraw.png");
drawGlyphs.save("drawUnderlineText_drawGlyphIndexes.png");
#endif
QCOMPARE(textLayoutDraw, drawGlyphs);
}
void tst_QGlyphRun::drawRightToLeft()
{
QString s;
s.append(QChar(1575));
s.append(QChar(1578));
QPixmap textLayoutDraw(1000, 1000);
QPixmap drawGlyphs(1000, 1000);
textLayoutDraw.fill(Qt::white);
drawGlyphs.fill(Qt::white);
QFont font;
font.setUnderline(true);
QTextLayout layout(s);
layout.setFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
{
QPainter p(&textLayoutDraw);
layout.draw(&p, QPointF(50, 50));
}
QGlyphRun glyphs = layout.glyphRuns().size() > 0
? layout.glyphRuns().at(0)
: QGlyphRun();
{
QPainter p(&drawGlyphs);
p.drawGlyphRun(QPointF(50, 50), glyphs);
}
#if defined(DEBUG_SAVE_IMAGE)
textLayoutDraw.save("drawRightToLeft_textLayoutDraw.png");
drawGlyphs.save("drawRightToLeft_drawGlyphIndexes.png");
#endif
QCOMPARE(textLayoutDraw, drawGlyphs);
}
#endif // QT_NO_RAWFONT
QTEST_MAIN(tst_QGlyphRun)
#include "tst_qglyphrun.moc"