summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/gui')
-rw-r--r--tests/auto/gui/gui.pro1
-rw-r--r--tests/auto/gui/image/qimage/qimage.pro2
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp6
-rw-r--r--tests/auto/gui/image/qpixmap/qpixmap.pro2
-rw-r--r--tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp10
-rw-r--r--tests/auto/gui/kernel/noqteventloop/noqteventloop.pro2
-rw-r--r--tests/auto/gui/kernel/qguiapplication/qguiapplication.pro1
-rw-r--r--tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp54
-rw-r--r--tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp2
-rw-r--r--tests/auto/gui/kernel/qpalette/tst_qpalette.cpp8
-rw-r--r--tests/auto/gui/kernel/qwindow/qwindow.pro2
-rw-r--r--tests/auto/gui/painting/painting.pro1
-rw-r--r--tests/auto/gui/painting/qbrush/tst_qbrush.cpp6
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp220
-rw-r--r--tests/auto/gui/painting/qcolorspace/qcolorspace.pro9
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpgbin0 -> 30900 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/resources/sRGB2014.iccbin0 -> 3024 bytes
-rw-r--r--tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp361
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp20
-rw-r--r--tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp13
-rw-r--r--tests/auto/gui/painting/qpen/tst_qpen.cpp8
-rw-r--r--tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp6
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.frag12
-rw-r--r--tests/auto/gui/rhi/qrhi/data/texture.vert18
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.pro8
-rw-r--r--tests/auto/gui/rhi/qrhi/qrhi.qrc5
-rw-r--r--tests/auto/gui/rhi/qrhi/tst_qrhi.cpp246
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert18
-rw-r--r--tests/auto/gui/rhi/qshader/data/color.vert.qsbbin0 -> 1847 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/data/color_simple.vert.qsbbin0 -> 813 bytes
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.pro8
-rw-r--r--tests/auto/gui/rhi/qshader/qshader.qrc5
-rw-r--r--tests/auto/gui/rhi/qshader/tst_qshader.cpp233
-rw-r--r--tests/auto/gui/rhi/rhi.pro4
-rw-r--r--tests/auto/gui/text/qfont/tst_qfont.cpp18
-rw-r--r--tests/auto/gui/text/qfontcache/tst_qfontcache.cpp2
-rw-r--r--tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp4
-rw-r--r--tests/auto/gui/text/qstatictext/tst_qstatictext.cpp2
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp5
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp35
-rw-r--r--tests/auto/gui/text/qtextlist/tst_qtextlist.cpp2
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md28
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md17
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp163
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST3
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md62
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/example.md95
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md12
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md13
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro9
-rw-r--r--tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp464
-rw-r--r--tests/auto/gui/text/text.pro4
53 files changed, 2056 insertions, 182 deletions
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
index e0c8123f26..c90fc48251 100644
--- a/tests/auto/gui/gui.pro
+++ b/tests/auto/gui/gui.pro
@@ -13,6 +13,7 @@ SUBDIRS = \
text \
util \
itemmodels \
+ rhi
!qtConfig(opengl)|winrt: SUBDIRS -= qopengl qopenglconfig
diff --git a/tests/auto/gui/image/qimage/qimage.pro b/tests/auto/gui/image/qimage/qimage.pro
index b40866892e..0593cfbc23 100644
--- a/tests/auto/gui/image/qimage/qimage.pro
+++ b/tests/auto/gui/image/qimage/qimage.pro
@@ -7,7 +7,7 @@ qtConfig(c++11): CONFIG += c++11
android:!android-embedded: RESOURCES += qimage.qrc
-win32:!winrt: LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
darwin: LIBS += -framework CoreGraphics
TESTDATA += images/*
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 4d41b5e873..441ec17412 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -1852,7 +1852,9 @@ void tst_QImage::smoothScale4_data()
QTest::addColumn<QImage::Format>("format");
QTest::newRow("RGB32") << QImage::Format_RGB32;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("RGBx64") << QImage::Format_RGBX64;
+#endif
}
void tst_QImage::smoothScale4()
@@ -3403,7 +3405,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb32 -> rgb666 (dithering)") << rgb32 << QImage::Format_RGB666 << int(Qt::PreferDither | Qt::OrderedDither) << 129;
// Test we get the same results for opaque input in the ARGBPM implementation.
- rgb32 = qMove(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ rgb32 = std::move(rgb32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
QTest::newRow("argb32pm -> argb4444pm (no dither)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << 0 << 16;
QTest::newRow("argb32pm -> rgb444 (dithering)") << rgb32 << QImage::Format_RGB444 << int(Qt::PreferDither | Qt::OrderedDither) << 33;
QTest::newRow("argb32pm -> argb4444pm (dithering)") << rgb32 << QImage::Format_ARGB4444_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 33;
@@ -3412,6 +3414,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("argb32pm -> argb6666pm (no dither)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << 0 << 64;
QTest::newRow("argb32pm -> argb6666pm (dithering)") << rgb32 << QImage::Format_ARGB6666_Premultiplied << int(Qt::PreferDither | Qt::OrderedDither) << 129;
+#if QT_CONFIG(raster_64bit)
QImage rgb30(1024, 16, QImage::Format_RGB30);
QLinearGradient gradient30(QRectF(rgb30.rect()).topLeft(), QRectF(rgb30.rect()).topRight());
gradient30.setColorAt(0.0, QColor(0, 0, 0));
@@ -3424,6 +3427,7 @@ void tst_QImage::ditherGradient_data()
QTest::newRow("rgb30 -> rgb32 (dithering)") << rgb30 << QImage::Format_RGB32 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
QTest::newRow("rgb30 -> rgb888 (no dither)") << rgb30 << QImage::Format_RGB888 << 0 << 256;
QTest::newRow("rgb30 -> rgb888 (dithering)") << rgb30 << QImage::Format_RGB888 << int(Qt::PreferDither | Qt::OrderedDither) << 513;
+#endif
}
void tst_QImage::ditherGradient()
diff --git a/tests/auto/gui/image/qpixmap/qpixmap.pro b/tests/auto/gui/image/qpixmap/qpixmap.pro
index e6a020af1a..c9219dad1d 100644
--- a/tests/auto/gui/image/qpixmap/qpixmap.pro
+++ b/tests/auto/gui/image/qpixmap/qpixmap.pro
@@ -5,7 +5,7 @@ QT += core-private gui-private testlib
qtHaveModule(widgets): QT += widgets widgets-private
SOURCES += tst_qpixmap.cpp
-win32:!winrt:LIBS += -lgdi32 -luser32
+win32:!winrt: QMAKE_USE += user32 gdi32
RESOURCES += qpixmap.qrc
TESTDATA += convertFromImage/* convertFromToHICON/* loadFromData/* images/*
diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
index 550f70890e..bc8bc38da6 100644
--- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
+++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp
@@ -734,7 +734,7 @@ void tst_QStandardItemModel::data()
currentRoles.clear();
// bad args
m_model->setData(QModelIndex(), "bla", Qt::DisplayRole);
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
QIcon icon;
for (int r=0; r < m_model->rowCount(); ++r) {
@@ -742,9 +742,9 @@ void tst_QStandardItemModel::data()
m_model->setData(m_model->index(r,c), "initialitem", Qt::DisplayRole);
QCOMPARE(currentRoles, QVector<int>({Qt::DisplayRole, Qt::EditRole}));
m_model->setData(m_model->index(r,c), "tooltip", Qt::ToolTipRole);
- QCOMPARE(currentRoles, {Qt::ToolTipRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::ToolTipRole});
m_model->setData(m_model->index(r,c), icon, Qt::DecorationRole);
- QCOMPARE(currentRoles, {Qt::DecorationRole});
+ QCOMPARE(currentRoles, QVector<int>{Qt::DecorationRole});
}
}
@@ -761,7 +761,7 @@ void tst_QStandardItemModel::clearItemData()
{
currentRoles.clear();
QVERIFY(!m_model->clearItemData(QModelIndex()));
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
const QModelIndex idx = m_model->index(0, 0);
const QMap<int, QVariant> oldData = m_model->itemData(idx);
m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole);
@@ -773,7 +773,7 @@ void tst_QStandardItemModel::clearItemData()
QCOMPARE(idx.data(Qt::ToolTipRole), QVariant());
QCOMPARE(idx.data(Qt::DisplayRole), QVariant());
QCOMPARE(idx.data(Qt::EditRole), QVariant());
- QCOMPARE(currentRoles, {});
+ QCOMPARE(currentRoles, QVector<int>{});
m_model->setItemData(idx, oldData);
currentRoles.clear();
}
diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
index 7e98704aea..293a6a8581 100644
--- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
+++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro
@@ -5,4 +5,4 @@ QT += core-private network gui-private testlib
SOURCES += tst_noqteventloop.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
index 895c2a0307..34b75a8397 100644
--- a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
+++ b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro
@@ -6,6 +6,7 @@ INCLUDEPATH += $$CORE_TEST_PATH
TARGET = tst_qguiapplication
QT += gui-private
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050E00
SOURCES += tst_qguiapplication.cpp
RESOURCES = tst_qguiapplication.qrc
diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
index a304981cd1..5ee25677bf 100644
--- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
+++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
@@ -184,7 +184,7 @@ void tst_QGuiApplication::windowIcon()
class DummyWindow : public QWindow
{
public:
- DummyWindow() : m_focusObject(0) {}
+ DummyWindow() : m_focusObject(nullptr) {}
virtual QObject *focusObject() const
{
@@ -204,7 +204,7 @@ public:
void tst_QGuiApplication::focusObject()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -271,15 +271,15 @@ void tst_QGuiApplication::focusObject()
void tst_QGuiApplication::allWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.allWindows().contains(window1));
QVERIFY(app.allWindows().contains(window2));
QCOMPARE(app.allWindows().count(), 2);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.allWindows().contains(window2));
QVERIFY(!app.allWindows().contains(window1));
QCOMPARE(app.allWindows().count(), 0);
@@ -288,15 +288,15 @@ void tst_QGuiApplication::allWindows()
void tst_QGuiApplication::topLevelWindows()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
QWindow *window1 = new QWindow;
QWindow *window2 = new QWindow(window1);
QVERIFY(app.topLevelWindows().contains(window1));
QVERIFY(!app.topLevelWindows().contains(window2));
QCOMPARE(app.topLevelWindows().count(), 1);
delete window1;
- window1 = 0;
- window2 = 0;
+ window1 = nullptr;
+ window2 = nullptr;
QVERIFY(!app.topLevelWindows().contains(window2));
QVERIFY(!app.topLevelWindows().contains(window1));
QCOMPARE(app.topLevelWindows().count(), 0);
@@ -306,7 +306,7 @@ class ShowCloseShowWindow : public QWindow
{
Q_OBJECT
public:
- ShowCloseShowWindow(bool showAgain, QWindow *parent = 0)
+ ShowCloseShowWindow(bool showAgain, QWindow *parent = nullptr)
: QWindow(parent), showAgain(showAgain)
{
QTimer::singleShot(0, this, SLOT(doClose()));
@@ -331,7 +331,7 @@ private:
void tst_QGuiApplication::abortQuitOnShow()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window1(new ShowCloseShowWindow(false));
@@ -366,7 +366,7 @@ protected:
}
public:
- FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(0), windowDuringFocusOut(0) {}
+ FocusChangeWindow() : QWindow(), windowDuringFocusAboutToChange(nullptr), windowDuringFocusOut(nullptr) {}
QWindow *windowDuringFocusAboutToChange;
QWindow *windowDuringFocusOut;
@@ -378,7 +378,7 @@ void tst_QGuiApplication::changeFocusWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
QSKIP("QWindow::requestActivate() is not supported.");
@@ -430,7 +430,7 @@ void tst_QGuiApplication::changeFocusWindow()
void tst_QGuiApplication::keyboardModifiers()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QScopedPointer<QWindow> window(new QWindow);
@@ -564,7 +564,7 @@ public:
int leaves;
int enters;
- inline explicit BlockableWindow(QWindow *parent = 0)
+ inline explicit BlockableWindow(QWindow *parent = nullptr)
: QWindow(parent), blocked(false), leaves(0), enters(0) {}
bool event(QEvent *e)
@@ -601,7 +601,7 @@ void tst_QGuiApplication::modalWindow()
QSKIP("WinRt does not support multiple native windows.");
#endif
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
int x = screenGeometry.left() + spacing;
@@ -654,7 +654,7 @@ void tst_QGuiApplication::modalWindow()
window2->show();
QVERIFY(QTest::qWaitForWindowExposed(window1.data()));
QVERIFY(QTest::qWaitForWindowExposed(window2.data()));
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0);
QCOMPARE(window2->blocked, 0);
@@ -698,7 +698,7 @@ void tst_QGuiApplication::modalWindow()
// everything is unblocked when applicationModalWindow1 is hidden
applicationModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(childWindow1->blocked, 0); // QTBUG-32242, blocked status needs to be set on children as well.
QCOMPARE(window2->blocked, 0);
@@ -750,7 +750,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow2, windowModalWindow1 and window1 are unblocked
windowModalWindow2->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -815,7 +815,7 @@ void tst_QGuiApplication::modalWindow()
// hide windowModalWindow1, everything is unblocked
windowModalWindow1->hide();
- QCOMPARE(app.modalWindow(), static_cast<QWindow *>(0));
+ QCOMPARE(app.modalWindow(), static_cast<QWindow *>(nullptr));
QCOMPARE(window1->blocked, 0);
QCOMPARE(window2->blocked, 0);
QCOMPARE(windowModalWindow1->blocked, 0);
@@ -829,7 +829,7 @@ void tst_QGuiApplication::modalWindow()
void tst_QGuiApplication::quitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -869,7 +869,7 @@ void tst_QGuiApplication::quitOnLastWindowClosed()
void tst_QGuiApplication::quitOnLastWindowClosedMulti()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry();
QTimer timer;
@@ -909,7 +909,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti()
void tst_QGuiApplication::dontQuitOnLastWindowClosed()
{
int argc = 0;
- QGuiApplication app(argc, 0);
+ QGuiApplication app(argc, nullptr);
app.setQuitOnLastWindowClosed(false);
QTimer timer;
@@ -959,7 +959,7 @@ public:
{
if (key == "testplugin")
return new TestPlugin;
- return 0;
+ return nullptr;
}
};
@@ -989,9 +989,13 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents()
QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User));
QCOMPARE(testReceiver.customEvents, 0);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+ QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata);
+#else
QStaticPlugin testPluginInfo;
testPluginInfo.instance = qt_plugin_instance;
testPluginInfo.rawMetaData = qt_plugin_query_metadata;
+#endif
qRegisterStaticPluginFunction(testPluginInfo);
int argc = 3;
char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") };
@@ -1065,7 +1069,7 @@ void tst_QGuiApplication::testSetPaletteAttribute()
QVERIFY(!QCoreApplication::testAttribute(Qt::AA_SetPalette));
QPalette palette;
- palette.setColor(QPalette::Foreground, Qt::red);
+ palette.setColor(QPalette::WindowText, Qt::red);
QGuiApplication::setPalette(palette);
QVERIFY(QCoreApplication::testAttribute(Qt::AA_SetPalette));
@@ -1122,7 +1126,7 @@ void tst_QGuiApplication::settableStyleHints()
int argc = 0;
QScopedPointer<QGuiApplication> app;
if (appInstance)
- app.reset(new QGuiApplication(argc, 0));
+ app.reset(new QGuiApplication(argc, nullptr));
const int keyboardInputInterval = 555;
QGuiApplication::styleHints()->setKeyboardInputInterval(keyboardInputInterval);
diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
index bad021c3b0..9a4c560a08 100644
--- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
+++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp
@@ -121,7 +121,7 @@ static QByteArray modifiersTestRowName(const QString &keySequence)
if (uc > 32 && uc < 128)
str << '"' << c << '"';
else
- str << "U+" << hex << uc << dec;
+ str << "U+" << Qt::hex << uc << Qt::dec;
if (i < size - 1)
str << ',';
}
diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
index 7f29b1c24e..6ce6422f48 100644
--- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
+++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp
@@ -141,21 +141,20 @@ void tst_QPalette::copySemantics()
void tst_QPalette::moveSemantics()
{
-#ifdef Q_COMPILER_RVALUE_REFS
QPalette src(Qt::red), dst;
const QPalette control = src;
QVERIFY(src != dst);
QCOMPARE(src, control);
QVERIFY(!dst.isCopyOf(src));
QVERIFY(!dst.isCopyOf(control));
- dst = qMove(src); // move assignment
+ dst = std::move(src); // move assignment
QVERIFY(!dst.isCopyOf(src)); // isCopyOf() works on moved-from palettes, too
QVERIFY(dst.isCopyOf(control));
QCOMPARE(dst, control);
src = control; // check moved-from 'src' can still be assigned to (doesn't crash)
QVERIFY(src.isCopyOf(dst));
QVERIFY(src.isCopyOf(control));
- QPalette dst2(qMove(src)); // move construction
+ QPalette dst2(std::move(src)); // move construction
QVERIFY(!src.isCopyOf(dst));
QVERIFY(!src.isCopyOf(dst2));
QVERIFY(!src.isCopyOf(control));
@@ -163,9 +162,6 @@ void tst_QPalette::moveSemantics()
QVERIFY(dst2.isCopyOf(dst));
QVERIFY(dst2.isCopyOf(control));
// check moved-from 'src' can still be destroyed (doesn't crash)
-#else
- QSKIP("Compiler doesn't support C++11 move semantics");
-#endif
}
void tst_QPalette::setBrush()
diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro
index 844b3e8507..e7931ca773 100644
--- a/tests/auto/gui/kernel/qwindow/qwindow.pro
+++ b/tests/auto/gui/kernel/qwindow/qwindow.pro
@@ -5,4 +5,4 @@ QT += core-private gui-private testlib
SOURCES += tst_qwindow.cpp
-qtConfig(dynamicgl):win32:!winrt: LIBS += -luser32
+qtConfig(dynamicgl):win32:!winrt: QMAKE_USE += user32
diff --git a/tests/auto/gui/painting/painting.pro b/tests/auto/gui/painting/painting.pro
index 831fffab30..26e84c1b15 100644
--- a/tests/auto/gui/painting/painting.pro
+++ b/tests/auto/gui/painting/painting.pro
@@ -3,6 +3,7 @@ SUBDIRS=\
qpainterpath \
qpainterpathstroker \
qcolor \
+ qcolorspace \
qbrush \
qregion \
qpagelayout \
diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
index ce6ce15767..f35d4f330b 100644
--- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
+++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp
@@ -338,9 +338,9 @@ void tst_QBrush::gradientPresets()
QCOMPARE(lg->finalStop(), QPointF(1, 0));
QCOMPARE(lg->stops().size(), 3);
- QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e"))));
- QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4"))));
- QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4"))));
+ QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e"))));
+ QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4"))));
+ QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4"))));
QGradient invalidPreset(QGradient::Preset(-1));
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 17289e0b85..90a216e14a 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -33,7 +33,7 @@
#include <qcolor.h>
#include <qdebug.h>
-#include <private/qcolorprofile_p.h>
+#include <private/qcolortrclut_p.h>
#include <private/qdrawingprimitive_sse2_p.h>
#include <qrgba64.h>
@@ -70,6 +70,7 @@ private slots:
void setBlue();
void setRgb();
+ void setRgbF();
void setRgba();
void setHsv();
void setCmyk();
@@ -93,8 +94,8 @@ private slots:
void convertTo();
- void light();
- void dark();
+ void lighter();
+ void darker();
void specConstructor_data();
void specConstructor();
@@ -187,28 +188,28 @@ void tst_QColor::getSetCheck()
// void QColor::setRedF(qreal)
obj1.setRedF(0.0);
QCOMPARE(obj1.redF(), qreal(0.0));
- obj1.setRedF(-0.2);
- QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setRedF(1.1);
- QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setRedF(-0.25);
+ QCOMPARE(obj1.redF(), qreal(-0.25));
+ obj1.setRedF(1.25);
+ QCOMPARE(obj1.redF(), qreal(1.25));
// qreal QColor::greenF()
// void QColor::setGreenF(qreal)
obj1.setGreenF(0.0);
QCOMPARE(obj1.greenF(), qreal(0.0));
- obj1.setGreenF(-0.2);
- QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setGreenF(1.1);
- QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setGreenF(-0.25);
+ QCOMPARE(obj1.greenF(), qreal(-0.25));
+ obj1.setGreenF(1.5);
+ QCOMPARE(obj1.greenF(), qreal(1.5));
// qreal QColor::blueF()
// void QColor::setBlueF(qreal)
obj1.setBlueF(0.0);
QCOMPARE(obj1.blueF(), qreal(0.0));
- obj1.setBlueF(-0.2);
- QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0
- obj1.setBlueF(1.1);
- QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0
+ obj1.setBlueF(-0.5);
+ QCOMPARE(obj1.blueF(), qreal(-0.5));
+ obj1.setBlueF(2.0);
+ QCOMPARE(obj1.blueF(), qreal(2.0));
// QRgb QColor::rgba()
// void QColor::setRgba(QRgb)
@@ -677,30 +678,81 @@ void tst_QColor::setRgb()
{
QColor color;
- for (int A = 0; A <= USHRT_MAX; ++A) {
- {
- // 0-255
- int a = A >> 8;
- QRgb rgb = qRgba(0, 0, 0, a);
+ for (int a = 0; a <= 255; ++a) {
+ QRgb rgb = qRgba(0, 0, 0, a);
- color.setRgb(0, 0, 0, a);
- QCOMPARE(color.alpha(), a);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(0, 0, 0, a);
+ QCOMPARE(color.alpha(), a);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- color.setRgb(rgb);
- QCOMPARE(color.alpha(), 255);
- QCOMPARE(color.rgb(), qRgb(0, 0, 0));
+ color.setRgb(rgb);
+ QCOMPARE(color.alpha(), 255);
+ QCOMPARE(color.rgb(), qRgb(0, 0, 0));
- int r, g, b, a2;
- color.setRgb(0, 0, 0, a);
- color.getRgb(&r, &g, &b, &a2);
- QCOMPARE(a2, a);
+ int r, g, b, a2;
+ color.setRgb(0, 0, 0, a);
+ color.getRgb(&r, &g, &b, &a2);
+ QCOMPARE(a2, a);
- QColor c(0, 0, 0);
- c.setAlpha(a);
- QCOMPARE(c.alpha(), a);
- }
+ QColor c(0, 0, 0);
+ c.setAlpha(a);
+ QCOMPARE(c.alpha(), a);
+ }
+ for (int r = 0; r <= 255; ++r) {
+ QRgb rgb = qRgb(r, 0, 0);
+
+ color.setRgb(r, 0, 0);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.red(), r);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r2, g, b, a;
+ color.getRgb(&r2, &g, &b, &a);
+ QCOMPARE(r2, r);
+ }
+
+ for (int g = 0; g <= 255; ++g) {
+ QRgb rgb = qRgb(0, g, 0);
+
+ color.setRgb(0, g, 0);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.green(), g);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g2, b, a;
+ color.getRgb(&r, &g2, &b, &a);
+ QCOMPARE(g2, g);
+ }
+
+ for (int b = 0; b <= 255; ++b) {
+ QRgb rgb = qRgb(0, 0, b);
+
+ color.setRgb(0, 0, b);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ color.setRgb(rgb);
+ QCOMPARE(color.blue(), b);
+ QCOMPARE(color.rgb(), rgb);
+
+ int r, g, b2, a;
+ color.getRgb(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+}
+
+void tst_QColor::setRgbF()
+{
+ QColor color;
+
+ for (int A = 0; A <= USHRT_MAX; ++A) {
{
// 0.0-1.0
qreal a = A / qreal(USHRT_MAX);
@@ -720,24 +772,6 @@ void tst_QColor::setRgb()
for (int R = 0; R <= USHRT_MAX; ++R) {
{
- // 0-255
- int r = R >> 8;
- QRgb rgb = qRgb(r, 0, 0);
-
- color.setRgb(r, 0, 0);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.red(), r);
- QCOMPARE(color.rgb(), rgb);
-
- int r2, g, b, a;
- color.getRgb(&r2, &g, &b, &a);
- QCOMPARE(r2, r);
- }
-
- {
// 0.0-1.0
qreal r = R / qreal(USHRT_MAX);
color.setRgbF(r, 0.0, 0.0);
@@ -751,24 +785,6 @@ void tst_QColor::setRgb()
for (int G = 0; G <= USHRT_MAX; ++G) {
{
- // 0-255
- int g = G >> 8;
- QRgb rgb = qRgb(0, g, 0);
-
- color.setRgb(0, g, 0);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- color.setRgb(rgb);
- QCOMPARE(color.green(), g);
- QCOMPARE(color.rgb(), rgb);
-
- int r, g2, b, a;
- color.getRgb(&r, &g2, &b, &a);
- QCOMPARE(g2, g);
- }
-
- {
// 0.0-1.0
qreal g = G / qreal(USHRT_MAX);
color.setRgbF(0.0, g, 0.0);
@@ -782,32 +798,53 @@ void tst_QColor::setRgb()
for (int B = 0; B <= USHRT_MAX; ++B) {
{
- // 0-255
- int b = B >> 8;
- QRgb rgb = qRgb(0, 0, b);
+ // 0.0-1.0
+ qreal b = B / qreal(USHRT_MAX);
+ color.setRgbF(0.0, 0.0, b);
+ QCOMPARE(color.blueF(), b);
- color.setRgb(0, 0, b);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ qreal r, g, b2, a;
+ color.getRgbF(&r, &g, &b2, &a);
+ QCOMPARE(b2, b);
+ }
+ }
- color.setRgb(rgb);
- QCOMPARE(color.blue(), b);
- QCOMPARE(color.rgb(), rgb);
+ for (int R = -128; R <= 512; ++R) {
+ {
+ // extended RGB
+ qreal r = R / qreal(256);
+ color.setRgbF(r, 0.0, 0.0);
+ QCOMPARE(qfloat16(color.redF()), qfloat16(r));
- int r, g, b2, a;
- color.getRgb(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ qreal r2, g, b, a;
+ color.getRgbF(&r2, &g, &b, &a);
+ QCOMPARE(qfloat16(r2), qfloat16(r));
}
+ }
+ for (int G = -128; G <= 512; ++G) {
{
- // 0.0-1.0
- qreal b = B / qreal(USHRT_MAX);
+ // extended RGB
+ qreal g = G / qreal(256);
+ color.setRgbF(0.0, g, 0.0);
+ QCOMPARE(qfloat16(color.greenF()), qfloat16(g));
+
+ qreal r, g2, b, a;
+ color.getRgbF(&r, &g2, &b, &a);
+ QCOMPARE(qfloat16(g2), qfloat16(g));
+ }
+ }
+
+ for (int B = -128; B <= 512; ++B) {
+ {
+ // extended RGB
+ qreal b = B / qreal(256);
color.setRgbF(0.0, 0.0, b);
- QCOMPARE(color.blueF(), b);
+ QCOMPARE(qfloat16(color.blueF()), qfloat16(b));
qreal r, g, b2, a;
color.getRgbF(&r, &g, &b2, &a);
- QCOMPARE(b2, b);
+ QCOMPARE(qfloat16(b2), qfloat16(b));
}
}
}
@@ -1382,17 +1419,17 @@ void tst_QColor::convertTo()
QCOMPARE(invalid.spec(), QColor::Invalid);
}
-void tst_QColor::light()
+void tst_QColor::lighter()
{
QColor gray(Qt::gray);
- QColor lighter = gray.light();
+ QColor lighter = gray.lighter();
QVERIFY(lighter.value() > gray.value());
}
-void tst_QColor::dark()
+void tst_QColor::darker()
{
QColor gray(Qt::gray);
- QColor darker = gray.dark();
+ QColor darker = gray.darker();
QVERIFY(darker.value() < gray.value());
}
@@ -1632,14 +1669,13 @@ void tst_QColor::qcolorprofile_data()
QTest::newRow("gamma=1.7") << qreal(1.7) << 2;
QTest::newRow("gamma=2.0") << qreal(2.0) << 8;
QTest::newRow("gamma=2.31") << qreal(2.31) << 33;
- QTest::newRow("SRgb") << qreal(0.0) << 7;
}
void tst_QColor::qcolorprofile()
{
QFETCH(qreal, gammaC);
QFETCH(int, tolerance);
- QColorProfile *cp = (gammaC == 0) ? QColorProfile::fromSRgb(): QColorProfile::fromGamma(gammaC);
+ QColorTrcLut *cp = QColorTrcLut::fromGamma(gammaC);
// Test we are accurate for most values after converting through gamma-correction.
int error = 0;
diff --git a/tests/auto/gui/painting/qcolorspace/qcolorspace.pro b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
new file mode 100644
index 0000000000..14bd699bf7
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/qcolorspace.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+QT += testlib gui-private core-private
+
+TARGET = tst_qcolorspace
+SOURCES += tst_qcolorspace.cpp
+
+RESOURCES += $$files(resources/*)
+
+TESTDATA += resources/*
diff --git a/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
new file mode 100644
index 0000000000..481d35ca8e
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/ProPhoto.jpg
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
new file mode 100644
index 0000000000..49afbfef10
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/resources/sRGB2014.icc
Binary files differ
diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
new file mode 100644
index 0000000000..7a88eb18b2
--- /dev/null
+++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
@@ -0,0 +1,361 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 <QtTest/QtTest>
+
+#include <qcolorspace.h>
+#include <qimage.h>
+#include <qimagereader.h>
+
+#include <private/qcolorspace_p.h>
+
+Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId)
+Q_DECLARE_METATYPE(QColorSpace::Gamut)
+Q_DECLARE_METATYPE(QColorSpace::TransferFunction)
+
+class tst_QColorSpace : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QColorSpace();
+
+private slots:
+ void namedColorSpaces_data();
+ void namedColorSpaces();
+
+ void toIccProfile_data();
+ void toIccProfile();
+
+ void fromIccProfile();
+
+ void imageConversion_data();
+ void imageConversion();
+
+ void loadImage();
+
+ void gamut();
+ void primariesXyz();
+ void primaries2_data();
+ void primaries2();
+ void invalidPrimaries();
+};
+
+tst_QColorSpace::tst_QColorSpace()
+{ }
+
+
+void tst_QColorSpace::namedColorSpaces_data()
+{
+ QTest::addColumn<QColorSpace::ColorSpaceId>("colorSpaceId");
+ QTest::addColumn<QColorSpace::Gamut>("gamutId");
+ QTest::addColumn<QColorSpace::TransferFunction>("transferFunctionId");
+
+ QTest::newRow("sRGB") << QColorSpace::SRgb
+ << QColorSpace::Gamut::SRgb
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("sRGB Linear") << QColorSpace::SRgbLinear
+ << QColorSpace::Gamut::SRgb
+ << QColorSpace::TransferFunction::Linear;
+ QTest::newRow("Adobe RGB") << QColorSpace::AdobeRgb
+ << QColorSpace::Gamut::AdobeRgb
+ << QColorSpace::TransferFunction::Gamma;
+ QTest::newRow("Display-P3") << QColorSpace::DisplayP3
+ << QColorSpace::Gamut::DciP3D65
+ << QColorSpace::TransferFunction::SRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::ProPhotoRgb
+ << QColorSpace::Gamut::ProPhotoRgb
+ << QColorSpace::TransferFunction::ProPhotoRgb;
+ QTest::newRow("BT.2020") << QColorSpace::Bt2020
+ << QColorSpace::Gamut::Bt2020
+ << QColorSpace::TransferFunction::Bt2020;
+}
+
+void tst_QColorSpace::namedColorSpaces()
+{
+ QFETCH(QColorSpace::ColorSpaceId, colorSpaceId);
+ QFETCH(QColorSpace::Gamut, gamutId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ QColorSpace colorSpace = colorSpaceId;
+
+ QVERIFY(colorSpace.isValid());
+
+ QCOMPARE(colorSpace.colorSpaceId(), colorSpaceId);
+ QCOMPARE(colorSpace.gamut(), gamutId);
+ QCOMPARE(colorSpace.transferFunction(), transferFunctionId);
+}
+
+
+void tst_QColorSpace::toIccProfile_data()
+{
+ namedColorSpaces_data();
+}
+
+void tst_QColorSpace::toIccProfile()
+{
+ QFETCH(QColorSpace::ColorSpaceId, colorSpaceId);
+ QFETCH(QColorSpace::Gamut, gamutId);
+ QFETCH(QColorSpace::TransferFunction, transferFunctionId);
+
+ Q_UNUSED(gamutId);
+ Q_UNUSED(transferFunctionId);
+
+ QColorSpace colorSpace = colorSpaceId;
+ QByteArray iccProfile = colorSpace.iccProfile();
+ QVERIFY(!iccProfile.isEmpty());
+
+ QColorSpace colorSpace2 = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(colorSpace2.isValid());
+
+ QCOMPARE(colorSpace2, colorSpace);
+
+ QByteArray iccProfile2 = colorSpace2.iccProfile();
+ QVERIFY(!iccProfile2.isEmpty());
+
+ QCOMPARE(iccProfile2, iccProfile);
+}
+
+void tst_QColorSpace::fromIccProfile()
+{
+ // Read the official sRGB ICCv2 profile:
+ QString prefix = QFINDTESTDATA("resources/");
+ QFile file(prefix + "sRGB2014.icc");
+ file.open(QIODevice::ReadOnly);
+ QByteArray iccProfile = file.readAll();
+ QColorSpace stdSRgb = QColorSpace::fromIccProfile(iccProfile);
+ QVERIFY(stdSRgb.isValid());
+
+ QCOMPARE(stdSRgb.gamut(), QColorSpace::Gamut::SRgb);
+ QCOMPARE(stdSRgb.transferFunction(), QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(stdSRgb.colorSpaceId(), QColorSpace::SRgb);
+
+ QCOMPARE(stdSRgb, QColorSpace(QColorSpace::SRgb));
+}
+
+void tst_QColorSpace::imageConversion_data()
+{
+ QTest::addColumn<QColorSpace::ColorSpaceId>("fromColorSpace");
+ QTest::addColumn<QColorSpace::ColorSpaceId>("toColorSpace");
+ QTest::addColumn<int>("tolerance");
+
+ QTest::newRow("sRGB -> Display-P3") << QColorSpace::SRgb << QColorSpace::DisplayP3 << 0;
+ QTest::newRow("sRGB -> Adobe RGB") << QColorSpace::SRgb << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("Display-P3 -> sRGB") << QColorSpace::DisplayP3 << QColorSpace::SRgb << 0;
+ QTest::newRow("Adobe RGB -> sRGB") << QColorSpace::AdobeRgb << QColorSpace::SRgb << 2;
+ QTest::newRow("Display-P3 -> Adobe RGB") << QColorSpace::DisplayP3 << QColorSpace::AdobeRgb << 2;
+ QTest::newRow("Display-P3 -> BT.2020") << QColorSpace::DisplayP3 << QColorSpace::Bt2020 << 4;
+ QTest::newRow("sRGB -> sRGB Linear") << QColorSpace::SRgb << QColorSpace::SRgbLinear << 0;
+}
+
+void tst_QColorSpace::imageConversion()
+{
+ QFETCH(QColorSpace::ColorSpaceId, fromColorSpace);
+ QFETCH(QColorSpace::ColorSpaceId, toColorSpace);
+ QFETCH(int, tolerance);
+
+ QImage testImage(256, 1, QImage::Format_RGB32);
+
+ for (int i = 0; i < 256; ++i)
+ testImage.setPixel(i, 0, qRgb(i, i, i));
+
+ testImage.setColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+
+ testImage.convertToColorSpace(toColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(toColorSpace));
+
+ int lastRed = 0;
+ int lastGreen = 0;
+ int lastBlue = 0;
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qRed(p) >= lastRed);
+ QVERIFY(qGreen(p) >= lastGreen);
+ QVERIFY(qBlue(p) >= lastBlue);
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+
+ lastRed = 0;
+ lastGreen = 0;
+ lastBlue = 0;
+ testImage.convertToColorSpace(fromColorSpace);
+ QCOMPARE(testImage.colorSpace(), QColorSpace(fromColorSpace));
+ for (int i = 0; i < 256; ++i) {
+ QRgb p = testImage.pixel(i, 0);
+ QVERIFY(qAbs(qRed(p) - qGreen(p)) <= tolerance);
+ QVERIFY(qAbs(qRed(p) - qBlue(p)) <= tolerance);
+ QVERIFY((lastRed - qRed(p)) <= (tolerance / 2));
+ QVERIFY((lastGreen - qGreen(p)) <= (tolerance / 2));
+ QVERIFY((lastBlue - qBlue(p)) <= (tolerance / 2));
+ lastRed = qRed(p);
+ lastGreen = qGreen(p);
+ lastBlue = qBlue(p);
+ }
+}
+
+
+void tst_QColorSpace::loadImage()
+{
+ QString prefix = QFINDTESTDATA("resources/");
+ QImageReader reader(prefix + "ProPhoto.jpg");
+ QImage image = reader.read();
+
+ QVERIFY(!image.isNull());
+ QVERIFY(image.colorSpace().isValid());
+ QCOMPARE(image.colorSpace().colorSpaceId(), QColorSpace::ProPhotoRgb);
+ QVERIFY(!image.colorSpace().iccProfile().isEmpty());
+
+ QColorSpace defaultProPhotoRgb = QColorSpace::ProPhotoRgb;
+ QVERIFY(!defaultProPhotoRgb.iccProfile().isEmpty());
+
+ // Test the iccProfile getter returns the ICC profile from the image
+ // which since we didn't write it, isn't identical to our defaults.
+ QVERIFY(defaultProPhotoRgb.iccProfile() != image.colorSpace().iccProfile());
+
+ QColorTransform transform = image.colorSpace().transformationToColorSpace(QColorSpace::SRgb);
+ qreal maxRed = 0;
+ qreal maxBlue = 0;
+ qreal maxRed2 = 0;
+ qreal maxBlue2 = 0;
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ QColor p = image.pixelColor(x, y);
+ maxRed = std::max(maxRed, p.redF());
+ maxBlue = std::max(maxBlue, p.blueF());
+ p = transform.map(p);
+ maxRed2 = std::max(maxRed2, p.redF());
+ maxBlue2 = std::max(maxBlue2, p.blueF());
+
+ }
+ }
+ // ProPhotoRgb can be a lot more red and blue than SRgb can, so it will have lower values.
+ QVERIFY(maxRed2 > maxRed);
+ QVERIFY(maxBlue2 > maxBlue);
+}
+
+void tst_QColorSpace::gamut()
+{
+ QColor black = QColor::fromRgbF(0.0, 0.0, 0.0);
+ QColor white = QColor::fromRgbF(1.0, 1.0, 1.0);
+ QColor red = QColor::fromRgbF(1.0, 0.0, 0.0);
+ QColor green = QColor::fromRgbF(0.0, 1.0, 0.0);
+ QColor blue = QColor::fromRgbF(0.0, 0.0, 1.0);
+
+ QColorTransform toAdobeRgb = QColorSpace(QColorSpace::SRgb).transformationToColorSpace(QColorSpace::AdobeRgb);
+
+ QColor tblack = toAdobeRgb.map(black);
+ QColor twhite = toAdobeRgb.map(white);
+ QColor tred = toAdobeRgb.map(red);
+ QColor tgreen = toAdobeRgb.map(green);
+ QColor tblue = toAdobeRgb.map(blue);
+
+ // Black is black
+ QCOMPARE(tblack, black);
+
+ // This white hasn't changed
+ QCOMPARE(twhite, white);
+
+ // Adobe's red and blue gamut corners are the same as sRGB's
+ // So, a color in the red corner, will stay in the red corner
+ // the same for blue, but not for green.
+ QVERIFY(tred.greenF() < 0.001);
+ QVERIFY(tred.blueF() < 0.001);
+ QVERIFY(tblue.redF() < 0.001);
+ QVERIFY(tblue.greenF() < 0.001);
+ QVERIFY(tgreen.redF() > 0.2);
+ QVERIFY(tgreen.blueF() > 0.2);
+}
+
+void tst_QColorSpace::primariesXyz()
+{
+ QColorSpace sRgb = QColorSpace::SRgb;
+ QColorSpace adobeRgb = QColorSpace::AdobeRgb;
+ QColorSpace displayP3 = QColorSpace::DisplayP3;
+ QColorSpace proPhotoRgb = QColorSpace::ProPhotoRgb;
+ QColorSpace bt2020 = QColorSpace::Bt2020;
+
+ // Check if our calculated matrices, match the precalculated ones.
+ QCOMPARE(sRgb.d_func()->toXyz, QColorMatrix::toXyzFromSRgb());
+ QCOMPARE(adobeRgb.d_func()->toXyz, QColorMatrix::toXyzFromAdobeRgb());
+ QCOMPARE(displayP3.d_func()->toXyz, QColorMatrix::toXyzFromDciP3D65());
+ QCOMPARE(proPhotoRgb.d_func()->toXyz, QColorMatrix::toXyzFromProPhotoRgb());
+ QCOMPARE(bt2020.d_func()->toXyz, QColorMatrix::toXyzFromBt2020());
+}
+
+void tst_QColorSpace::primaries2_data()
+{
+ QTest::addColumn<QColorSpace::Gamut>("gamut");
+
+ QTest::newRow("sRGB") << QColorSpace::Gamut::SRgb;
+ QTest::newRow("DCI-P3 (D65)") << QColorSpace::Gamut::DciP3D65;
+ QTest::newRow("Adobe RGB (1998)") << QColorSpace::Gamut::AdobeRgb;
+ QTest::newRow("ProPhoto RGB") << QColorSpace::Gamut::ProPhotoRgb;
+ QTest::newRow("BT.2020") << QColorSpace::Gamut::Bt2020;
+}
+
+void tst_QColorSpace::primaries2()
+{
+ QFETCH(QColorSpace::Gamut, gamut);
+ QColorSpacePrimaries primaries(gamut);
+
+ QColorSpace original(gamut, QColorSpace::TransferFunction::Linear);
+ QColorSpace custom1(primaries.whitePoint, primaries.redPoint,
+ primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear);
+ QCOMPARE(original, custom1);
+
+ // A custom color swizzled color-space:
+ QColorSpace custom2(primaries.whitePoint, primaries.bluePoint,
+ primaries.greenPoint, primaries.redPoint, QColorSpace::TransferFunction::Linear);
+
+ QVERIFY(custom1 != custom2);
+ QColor color1(255, 127, 63);
+ QColor color2 = custom1.transformationToColorSpace(custom2).map(color1);
+ QCOMPARE(color2.red(), color1.blue());
+ QCOMPARE(color2.green(), color1.green());
+ QCOMPARE(color2.blue(), color1.red());
+ QCOMPARE(color2.alpha(), color1.alpha());
+ QColor color3 = custom2.transformationToColorSpace(custom1).map(color2);
+ QCOMPARE(color3.red(), color1.red());
+ QCOMPARE(color3.green(), color1.green());
+ QCOMPARE(color3.blue(), color1.blue());
+ QCOMPARE(color3.alpha(), color1.alpha());
+}
+
+void tst_QColorSpace::invalidPrimaries()
+{
+ QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear);
+ QVERIFY(!custom.isValid());
+ QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined);
+}
+
+QTEST_MAIN(tst_QColorSpace)
+#include "tst_qcolorspace.moc"
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index bc0baed15c..2b53169a45 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -185,10 +185,12 @@ private slots:
void gradientPixelFormat_data();
void gradientPixelFormat();
+#if QT_CONFIG(raster_64bit)
void linearGradientRgb30_data();
void linearGradientRgb30();
void radialGradientRgb30_data();
void radialGradientRgb30();
+#endif
void fpe_pixmapTransform();
void fpe_zeroLengthLines();
@@ -368,10 +370,10 @@ void tst_QPainter::getSetCheck()
// bool QPainter::matrixEnabled()
// void QPainter::setMatrixEnabled(bool)
- obj1.setMatrixEnabled(false);
- QCOMPARE(false, obj1.matrixEnabled());
- obj1.setMatrixEnabled(true);
- QCOMPARE(true, obj1.matrixEnabled());
+ obj1.setWorldMatrixEnabled(false);
+ QCOMPARE(false, obj1.worldMatrixEnabled());
+ obj1.setWorldMatrixEnabled(true);
+ QCOMPARE(true, obj1.worldMatrixEnabled());
// bool QPainter::viewTransformEnabled()
// void QPainter::setViewTransformEnabled(bool)
@@ -697,7 +699,7 @@ void tst_QPainter::initFrom()
QCOMPARE(p.font(), font);
QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground));
- QCOMPARE(p.background(), pal.background());
+ QCOMPARE(p.background(), pal.window());
delete widget;
}
@@ -3195,7 +3197,7 @@ void tst_QPainter::largeImagePainting()
p.translate(4, 0);
}
- p.resetMatrix();
+ p.resetTransform();
for (int i = 4; i < img.height(); i += 4) {
p.translate(0, 4);
@@ -3946,6 +3948,7 @@ void tst_QPainter::gradientInterpolation()
}
}
+#if QT_CONFIG(raster_64bit)
void tst_QPainter::linearGradientRgb30_data()
{
QTest::addColumn<QColor>("stop0");
@@ -4004,6 +4007,7 @@ void tst_QPainter::radialGradientRgb30()
QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb()));
}
}
+#endif
void tst_QPainter::drawPolygon()
{
@@ -4884,14 +4888,18 @@ void tst_QPainter::blendARGBonRGB_data()
<< QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM over RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_SourceOver << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_Source << qRgba(255, 0, 0, 120) << 85;
+#endif
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(85, 0, 0, 85) << 85;
+#if QT_CONFIG(raster_64bit)
QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
<< QPainter::CompositionMode_Source << qRgba(180, 0, 0, 180) << 170;
+#endif
QTest::newRow("ARGB source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32
<< QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 85) << 85;
QTest::newRow("ARGB_PM source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied
diff --git a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
index c1a8f7f0de..9e9b0db366 100644
--- a/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
+++ b/tests/auto/gui/painting/qpdfwriter/tst_qpdfwriter.cpp
@@ -154,12 +154,7 @@ void tst_QPdfWriter::testPageMetrics()
if (setMargins) {
// Setup the given margins
- QPdfWriter::Margins margins;
- margins.left = leftMMf;
- margins.right = rightMMf;
- margins.top = topMMf;
- margins.bottom = bottomMMf;
- writer.setMargins(margins);
+ writer.setPageMargins({leftMMf, topMMf, rightMMf, bottomMMf}, QPageLayout::Millimeter);
QCOMPARE(writer.margins().left, leftMMf);
QCOMPARE(writer.margins().right, rightMMf);
QCOMPARE(writer.margins().top, topMMf);
@@ -169,7 +164,7 @@ void tst_QPdfWriter::testPageMetrics()
// Set the given size, in Portrait mode
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -221,7 +216,7 @@ void tst_QPdfWriter::testPageMetrics()
// Now while in Landscape mode, set the size again, results should be the same
if (pageSize < 0) {
- writer.setPageSizeMM(sizeMMf);
+ writer.setPageSize(QPageSize(sizeMMf, QPageSize::Millimeter));
QCOMPARE(writer.pageSize(), QPdfWriter::Custom);
QCOMPARE(writer.pageLayout().pageSize().id(), QPageSize::Custom);
} else {
@@ -255,7 +250,7 @@ void tst_QPdfWriter::qtbug59443()
QTemporaryFile file;
QVERIFY2(file.open(), qPrintable(file.errorString()));
QPdfWriter writer(file.fileName());
- writer.setPageSize(QPdfWriter::A4);
+ writer.setPageSize(QPageSize(QPageSize::A4));
QTextDocument doc;
doc.documentLayout()->setPaintDevice(&writer);
diff --git a/tests/auto/gui/painting/qpen/tst_qpen.cpp b/tests/auto/gui/painting/qpen/tst_qpen.cpp
index ef65d653ce..295ae27d17 100644
--- a/tests/auto/gui/painting/qpen/tst_qpen.cpp
+++ b/tests/auto/gui/painting/qpen/tst_qpen.cpp
@@ -95,7 +95,7 @@ void tst_QPen::move()
QPen p1(Qt::black);
// check that moving does the right thing:
- QPen p2 = qMove(p1); // could be move or copy construction, so don't check p1's state
+ QPen p2 = std::move(p1); // could be move or copy construction, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// this, executed ehre, would crash:
@@ -110,7 +110,7 @@ void tst_QPen::move()
QCOMPARE(p1.color(), QColor(Qt::yellow));
// check that moved-from QPens p2, p3 can still be safely destroyed:
- QPen p5 = qMove(p2);
+ QPen p5 = std::move(p2);
// intentionally no more statements beyond this point
}
@@ -120,7 +120,7 @@ void tst_QPen::move_assign()
QPen p1(Qt::black), p2(Qt::white);
// check that moving does the right thing:
- p2 = qMove(p1); // could be move or copy assignment, so don't check p1's state
+ p2 = std::move(p1); // could be move or copy assignment, so don't check p1's state
QCOMPARE(p2.color(), QColor(Qt::black));
// check that move-assigned-from QPen p1 can still be used, albeit
@@ -137,7 +137,7 @@ void tst_QPen::move_assign()
// check that moved-from QPens p2, p3 can still be safely destroyed:
QPen p5;
- p5 = qMove(p2);
+ p5 = std::move(p2);
// intentionally no more statements beyond this point
}
diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
index f8dfdbd3b0..b82b277781 100644
--- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
+++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp
@@ -200,7 +200,7 @@ static void dumpGlConfiguration(QOpenGLContext &context, QTextStream &str)
<< "\nShading language : " << reinterpret_cast<const char *>(functions.glGetString(GL_SHADING_LANGUAGE_VERSION))
<< "\nFormat : " << context.format();
- QList<QByteArray> extensionList = context.extensions().toList();
+ QList<QByteArray> extensionList = context.extensions().values();
std::sort(extensionList.begin(), extensionList.end());
const int extensionCount = extensionList.size();
str << "\n\nFound " << extensionCount << " extensions:\n";
@@ -233,9 +233,9 @@ void tst_QOpenGlConfig::testGlConfiguration()
static inline QByteArray msgSetMismatch(const QSet<QString> &expected,
const QSet<QString> &actual)
{
- const QString result = QStringList(expected.toList()).join(QLatin1Char(','))
+ const QString result = QStringList(expected.values()).join(QLatin1Char(','))
+ QLatin1String(" != ")
- + QStringList(actual.toList()).join(QLatin1Char(','));
+ + QStringList(actual.values()).join(QLatin1Char(','));
return result.toLatin1();
}
diff --git a/tests/auto/gui/rhi/qrhi/data/texture.frag b/tests/auto/gui/rhi/qrhi/data/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/texture.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ fragColor = texture(tex, v_texcoord);
+}
diff --git a/tests/auto/gui/rhi/qrhi/data/texture.vert b/tests/auto/gui/rhi/qrhi/data/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/data/texture.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = texcoord;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/auto/gui/rhi/qrhi/qrhi.pro b/tests/auto/gui/rhi/qrhi/qrhi.pro
new file mode 100644
index 0000000000..58000ed514
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qrhi
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qrhi.cpp
+
+RESOURCES += qrhi.qrc
diff --git a/tests/auto/gui/rhi/qrhi/qrhi.qrc b/tests/auto/gui/rhi/qrhi/qrhi.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/qrhi.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
new file mode 100644
index 0000000000..897613d525
--- /dev/null
+++ b/tests/auto/gui/rhi/qrhi/tst_qrhi.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QtTest/QtTest>
+#include <QThread>
+#include <QFile>
+#include <QOffscreenSurface>
+#include <QtGui/private/qrhi_p.h>
+#include <QtGui/private/qrhinull_p.h>
+
+#if QT_CONFIG(opengl)
+# include <QtGui/private/qrhigles2_p.h>
+# define TST_GL
+#endif
+
+#if QT_CONFIG(vulkan)
+# include <QVulkanInstance>
+# include <QtGui/private/qrhivulkan_p.h>
+# define TST_VK
+#endif
+
+#ifdef Q_OS_WIN
+#include <QtGui/private/qrhid3d11_p.h>
+# define TST_D3D11
+#endif
+
+#ifdef Q_OS_DARWIN
+# include <QtGui/private/qrhimetal_p.h>
+# define TST_MTL
+#endif
+
+Q_DECLARE_METATYPE(QRhi::Implementation)
+Q_DECLARE_METATYPE(QRhiInitParams *)
+
+class tst_QRhi : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+ void create_data();
+ void create();
+
+private:
+ struct {
+ QRhiNullInitParams null;
+#ifdef TST_GL
+ QRhiGles2InitParams gl;
+#endif
+#ifdef TST_VK
+ QRhiVulkanInitParams vk;
+#endif
+#ifdef TST_D3D11
+ QRhiD3D11InitParams d3d;
+#endif
+#ifdef TST_MTL
+ QRhiMetalInitParams mtl;
+#endif
+ } initParams;
+
+#ifdef TST_VK
+ QVulkanInstance vulkanInstance;
+#endif
+ QOffscreenSurface *fallbackSurface = nullptr;
+};
+
+void tst_QRhi::initTestCase()
+{
+#ifdef TST_GL
+ fallbackSurface = QRhiGles2InitParams::newFallbackSurface();
+ initParams.gl.fallbackSurface = fallbackSurface;
+#endif
+
+#ifdef TST_VK
+ vulkanInstance.create();
+ initParams.vk.inst = &vulkanInstance;
+#endif
+}
+
+void tst_QRhi::cleanupTestCase()
+{
+#ifdef TST_VK
+ vulkanInstance.destroy();
+#endif
+
+ delete fallbackSurface;
+}
+
+void tst_QRhi::create_data()
+{
+ QTest::addColumn<QRhi::Implementation>("impl");
+ QTest::addColumn<QRhiInitParams *>("initParams");
+
+ QTest::newRow("Null") << QRhi::Null << static_cast<QRhiInitParams *>(&initParams.null);
+#ifdef TST_GL
+ QTest::newRow("OpenGL") << QRhi::OpenGLES2 << static_cast<QRhiInitParams *>(&initParams.gl);
+#endif
+#ifdef TST_VK
+ if (vulkanInstance.isValid())
+ QTest::newRow("Vulkan") << QRhi::Vulkan << static_cast<QRhiInitParams *>(&initParams.vk);
+#endif
+#ifdef TST_D3D11
+ QTest::newRow("Direct3D 11") << QRhi::D3D11 << static_cast<QRhiInitParams *>(&initParams.d3d);
+#endif
+#ifdef TST_MTL
+ QTest::newRow("Metal") << QRhi::Metal << static_cast<QRhiInitParams *>(&initParams.mtl);
+#endif
+}
+
+static int aligned(int v, int a)
+{
+ return (v + a - 1) & ~(a - 1);
+}
+
+void tst_QRhi::create()
+{
+ // Merely attempting to create a QRhi should survive, with an error when
+ // not supported. (of course, there is always a chance we encounter a crash
+ // due to some random graphics stack...)
+
+ QFETCH(QRhi::Implementation, impl);
+ QFETCH(QRhiInitParams *, initParams);
+
+ QScopedPointer<QRhi> rhi(QRhi::create(impl, initParams, QRhi::Flags(), nullptr));
+
+ if (rhi) {
+ QCOMPARE(rhi->backend(), impl);
+ QCOMPARE(rhi->thread(), QThread::currentThread());
+
+ int cleanupOk = 0;
+ QRhi *rhiPtr = rhi.data();
+ auto cleanupFunc = [rhiPtr, &cleanupOk](QRhi *dyingRhi) {
+ if (rhiPtr == dyingRhi)
+ cleanupOk += 1;
+ };
+ rhi->addCleanupCallback(cleanupFunc);
+ rhi->runCleanup();
+ QCOMPARE(cleanupOk, 1);
+ cleanupOk = 0;
+ rhi->addCleanupCallback(cleanupFunc);
+
+ QRhiResourceUpdateBatch *resUpd = rhi->nextResourceUpdateBatch();
+ QVERIFY(resUpd);
+ resUpd->release();
+
+ QVERIFY(!rhi->supportedSampleCounts().isEmpty());
+ QVERIFY(rhi->supportedSampleCounts().contains(1));
+
+ QVERIFY(rhi->ubufAlignment() > 0);
+ QCOMPARE(rhi->ubufAligned(123), aligned(123, rhi->ubufAlignment()));
+
+ QCOMPARE(rhi->mipLevelsForSize(QSize(512, 300)), 10);
+ QCOMPARE(rhi->sizeForMipLevel(0, QSize(512, 300)), QSize(512, 300));
+ QCOMPARE(rhi->sizeForMipLevel(1, QSize(512, 300)), QSize(256, 150));
+ QCOMPARE(rhi->sizeForMipLevel(2, QSize(512, 300)), QSize(128, 75));
+ QCOMPARE(rhi->sizeForMipLevel(9, QSize(512, 300)), QSize(1, 1));
+
+ const bool fbUp = rhi->isYUpInFramebuffer();
+ const bool ndcUp = rhi->isYUpInNDC();
+ const bool d0to1 = rhi->isClipDepthZeroToOne();
+ const QMatrix4x4 corrMat = rhi->clipSpaceCorrMatrix();
+ if (impl == QRhi::OpenGLES2) {
+ QVERIFY(fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(!d0to1);
+ QVERIFY(corrMat.isIdentity());
+ } else if (impl == QRhi::Vulkan) {
+ QVERIFY(!fbUp);
+ QVERIFY(!ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::D3D11) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ } else if (impl == QRhi::Metal) {
+ QVERIFY(!fbUp);
+ QVERIFY(ndcUp);
+ QVERIFY(d0to1);
+ QVERIFY(!corrMat.isIdentity());
+ }
+
+ const int texMin = rhi->resourceLimit(QRhi::TextureSizeMin);
+ const int texMax = rhi->resourceLimit(QRhi::TextureSizeMax);
+ const int maxAtt = rhi->resourceLimit(QRhi::MaxColorAttachments);
+ QVERIFY(texMin >= 1);
+ QVERIFY(texMax >= texMin);
+ QVERIFY(maxAtt >= 1);
+
+ QVERIFY(rhi->nativeHandles());
+ QVERIFY(rhi->profiler());
+
+ const QRhi::Feature features[] = {
+ QRhi::MultisampleTexture,
+ QRhi::MultisampleRenderBuffer,
+ QRhi::DebugMarkers,
+ QRhi::Timestamps,
+ QRhi::Instancing,
+ QRhi::CustomInstanceStepRate,
+ QRhi::PrimitiveRestart,
+ QRhi::NonDynamicUniformBuffers,
+ QRhi::NonFourAlignedEffectiveIndexBufferOffset,
+ QRhi::NPOTTextureRepeat,
+ QRhi::RedOrAlpha8IsRed,
+ QRhi::ElementIndexUint
+ };
+ for (size_t i = 0; i <sizeof(features) / sizeof(QRhi::Feature); ++i)
+ rhi->isFeatureSupported(features[i]);
+
+ QVERIFY(rhi->isTextureFormatSupported(QRhiTexture::RGBA8));
+
+ rhi.reset();
+ QCOMPARE(cleanupOk, 1);
+ }
+}
+
+#include <tst_qrhi.moc>
+QTEST_MAIN(tst_QRhi)
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert b/tests/auto/gui/rhi/qshader/data/color.vert
new file mode 100644
index 0000000000..c92f71b9e1
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+ float opacity;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/tests/auto/gui/rhi/qshader/data/color.vert.qsb b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
new file mode 100644
index 0000000000..7d02d823d2
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
new file mode 100644
index 0000000000..c82ba7e8e7
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/data/color_simple.vert.qsb
Binary files differ
diff --git a/tests/auto/gui/rhi/qshader/qshader.pro b/tests/auto/gui/rhi/qshader/qshader.pro
new file mode 100644
index 0000000000..5d9ef8304d
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qshader
+CONFIG += testcase
+
+QT += testlib gui-private
+
+SOURCES += tst_qshader.cpp
+
+RESOURCES += qshader.qrc
diff --git a/tests/auto/gui/rhi/qshader/qshader.qrc b/tests/auto/gui/rhi/qshader/qshader.qrc
new file mode 100644
index 0000000000..f161d8aad6
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/qshader.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>data</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/gui/rhi/qshader/tst_qshader.cpp b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
new file mode 100644
index 0000000000..21f0cc7895
--- /dev/null
+++ b/tests/auto/gui/rhi/qshader/tst_qshader.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QtTest/QtTest>
+#include <QFile>
+#include <QtGui/private/qshaderdescription_p_p.h>
+#include <QtGui/private/qshader_p_p.h>
+
+class tst_QShader : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void simpleCompileCheckResults();
+ void genVariants();
+ void shaderDescImplicitSharing();
+ void bakedShaderImplicitSharing();
+};
+
+static QShader getShader(const QString &name)
+{
+ QFile f(name);
+ if (f.open(QIODevice::ReadOnly))
+ return QShader::fromSerialized(f.readAll());
+
+ return QShader();
+}
+
+void tst_QShader::simpleCompileCheckResults()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+
+ const QShaderCode shader = s.shader(QShaderKey(QShader::SpirvShader,
+ QShaderVersion(100)));
+ QVERIFY(!shader.shader().isEmpty());
+ QCOMPARE(shader.entryPoint(), QByteArrayLiteral("main"));
+
+ const QShaderDescription desc = s.description();
+ QVERIFY(desc.isValid());
+ QCOMPARE(desc.inputVariables().count(), 2);
+ for (const QShaderDescription::InOutVariable &v : desc.inputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("position"));
+ QCOMPARE(v.type, QShaderDescription::Vec4);
+ break;
+ case 1:
+ QCOMPARE(v.name, QLatin1String("color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.outputVariables().count(), 1);
+ for (const QShaderDescription::InOutVariable &v : desc.outputVariables()) {
+ switch (v.location) {
+ case 0:
+ QCOMPARE(v.name, QLatin1String("v_color"));
+ QCOMPARE(v.type, QShaderDescription::Vec3);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+ QCOMPARE(desc.uniformBlocks().count(), 1);
+ const QShaderDescription::UniformBlock blk = desc.uniformBlocks().first();
+ QCOMPARE(blk.blockName, QLatin1String("buf"));
+ QCOMPARE(blk.structName, QLatin1String("ubuf"));
+ QCOMPARE(blk.size, 68);
+ QCOMPARE(blk.binding, 0);
+ QCOMPARE(blk.descriptorSet, 0);
+ QCOMPARE(blk.members.count(), 2);
+ for (int i = 0; i < blk.members.count(); ++i) {
+ const QShaderDescription::BlockVariable v = blk.members[i];
+ switch (i) {
+ case 0:
+ QCOMPARE(v.offset, 0);
+ QCOMPARE(v.size, 64);
+ QCOMPARE(v.name, QLatin1String("mvp"));
+ QCOMPARE(v.type, QShaderDescription::Mat4);
+ QCOMPARE(v.matrixStride, 16);
+ break;
+ case 1:
+ QCOMPARE(v.offset, 64);
+ QCOMPARE(v.size, 4);
+ QCOMPARE(v.name, QLatin1String("opacity"));
+ QCOMPARE(v.type, QShaderDescription::Float);
+ break;
+ default:
+ QVERIFY(false);
+ break;
+ }
+ }
+}
+
+void tst_QShader::genVariants()
+{
+ QShader s = getShader(QLatin1String(":/data/color.vert.qsb"));
+ // spirv, glsl 100, glsl 330, glsl 120, hlsl 50, msl 12
+ // + batchable variants
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 2 * 6);
+
+ int batchableVariantCount = 0;
+ int batchableGlslVariantCount = 0;
+ for (const QShaderKey &key : s.availableShaders()) {
+ if (key.sourceVariant() == QShader::BatchableVertexShader) {
+ ++batchableVariantCount;
+ if (key.source() == QShader::GlslShader) {
+ ++batchableGlslVariantCount;
+ const QByteArray src = s.shader(key).shader();
+ QVERIFY(src.contains(QByteArrayLiteral("_qt_order * ")));
+ }
+ }
+ }
+ QCOMPARE(batchableVariantCount, 6);
+ QCOMPARE(batchableGlslVariantCount, 3);
+}
+
+void tst_QShader::shaderDescImplicitSharing()
+{
+ QShader s = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s.isValid());
+ QCOMPARE(s.availableShaders().count(), 1);
+ QVERIFY(s.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ QShaderDescription d0 = s.description();
+ QVERIFY(d0.isValid());
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+
+ QShaderDescription d1 = d0;
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) == QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+
+ d1.detach();
+ QVERIFY(QShaderDescriptionPrivate::get(&d0) != QShaderDescriptionPrivate::get(&d1));
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+}
+
+void tst_QShader::bakedShaderImplicitSharing()
+{
+ QShader s0 = getShader(QLatin1String(":/data/color_simple.vert.qsb"));
+ QVERIFY(s0.isValid());
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+
+ s1.detach();
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s0.stage(), s1.stage());
+ QCOMPARE(s0, s1);
+ }
+
+ {
+ QShader s1 = s0;
+ QVERIFY(QShaderPrivate::get(&s0) == QShaderPrivate::get(&s1));
+ QCOMPARE(s0.stage(), s1.stage());
+
+ s1.setStage(QShader::FragmentStage); // call a setter to trigger a detach
+ QVERIFY(QShaderPrivate::get(&s0) != QShaderPrivate::get(&s1));
+ QCOMPARE(s0.availableShaders().count(), 1);
+ QVERIFY(s0.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QCOMPARE(s1.availableShaders().count(), 1);
+ QVERIFY(s1.availableShaders().contains(QShaderKey(QShader::SpirvShader, QShaderVersion(100))));
+ QShaderDescription d0 = s0.description();
+ QCOMPARE(d0.inputVariables().count(), 2);
+ QCOMPARE(d0.outputVariables().count(), 1);
+ QCOMPARE(d0.uniformBlocks().count(), 1);
+ QShaderDescription d1 = s1.description();
+ QCOMPARE(d1.inputVariables().count(), 2);
+ QCOMPARE(d1.outputVariables().count(), 1);
+ QCOMPARE(d1.uniformBlocks().count(), 1);
+ QVERIFY(s0 != s1);
+ }
+}
+
+#include <tst_qshader.moc>
+QTEST_MAIN(tst_QShader)
diff --git a/tests/auto/gui/rhi/rhi.pro b/tests/auto/gui/rhi/rhi.pro
new file mode 100644
index 0000000000..cc548b7b8a
--- /dev/null
+++ b/tests/auto/gui/rhi/rhi.pro
@@ -0,0 +1,4 @@
+TEMPLATE=subdirs
+SUBDIRS= \
+ qshader \
+ qrhi
diff --git a/tests/auto/gui/text/qfont/tst_qfont.cpp b/tests/auto/gui/text/qfont/tst_qfont.cpp
index 9acf877790..901284e131 100644
--- a/tests/auto/gui/text/qfont/tst_qfont.cpp
+++ b/tests/auto/gui/text/qfont/tst_qfont.cpp
@@ -609,37 +609,37 @@ void tst_QFont::sharing()
QFont f;
f.setStyleHint(QFont::Serif);
f.exactMatch(); // loads engine
- QCOMPARE(QFontPrivate::get(f)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
QFont f2(f);
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
f2.setKerning(!f.kerning());
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 2 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 2 + refs_by_cache);
f2 = f;
QCOMPARE(QFontPrivate::get(f2), QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 2);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 2);
QVERIFY(QFontPrivate::get(f2)->engineData);
QCOMPARE(QFontPrivate::get(f2)->engineData, QFontPrivate::get(f)->engineData);
- QCOMPARE(QFontPrivate::get(f2)->engineData->ref.load(), 1 + refs_by_cache);
+ QCOMPARE(QFontPrivate::get(f2)->engineData->ref.loadRelaxed(), 1 + refs_by_cache);
if (f.pointSize() > 0)
f2.setPointSize(f.pointSize() * 2 / 3);
else
f2.setPixelSize(f.pixelSize() * 2 / 3);
QVERIFY(QFontPrivate::get(f2) != QFontPrivate::get(f));
- QCOMPARE(QFontPrivate::get(f2)->ref.load(), 1);
+ QCOMPARE(QFontPrivate::get(f2)->ref.loadRelaxed(), 1);
QVERIFY(!QFontPrivate::get(f2)->engineData);
QVERIFY(QFontPrivate::get(f2)->engineData != QFontPrivate::get(f)->engineData);
}
diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
index 785cc3fef2..3d3211c7a2 100644
--- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
+++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp
@@ -217,7 +217,7 @@ void tst_QFontCache::clear()
#ifdef QT_BUILD_INTERNAL
QList<QFontEngine *> leakedEngines = QFontEngine_stopCollectingEngines();
-for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.load();
+for (int i = 0; i < leakedEngines.size(); ++i) qWarning() << i << leakedEngines.at(i) << leakedEngines.at(i)->ref.loadRelaxed();
// and we are not leaking!
QCOMPARE(leakedEngines.size(), 0);
#endif
diff --git a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
index 064e37f73c..2b69801b59 100644
--- a/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
+++ b/tests/auto/gui/text/qfontdatabase/tst_qfontdatabase.cpp
@@ -211,8 +211,8 @@ void tst_QFontDatabase::widthTwoTimes()
f.setPixelSize(pixelSize);
QFontMetrics fm(f);
- int w1 = fm.charWidth(text, 0);
- int w2 = fm.charWidth(text, 0);
+ int w1 = fm.horizontalAdvance(text, 0);
+ int w2 = fm.horizontalAdvance(text, 0);
QCOMPARE(w1, w2);
}
diff --git a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
index d00dc251d8..b091edb64d 100644
--- a/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
+++ b/tests/auto/gui/text/qstatictext/tst_qstatictext.cpp
@@ -681,7 +681,7 @@ static bool checkPixels(const QImage &image,
if (pixel != expectedRgb1 && pixel != expectedRgb2) {
QString message;
QDebug(&message) << "Color mismatch in image" << image
- << "at" << x << ',' << y << ':' << showbase << hex << pixel
+ << "at" << x << ',' << y << ':' << Qt::showbase << Qt::hex << pixel
<< "(expected: " << expectedRgb1 << ',' << expectedRgb2 << ')';
*errorMessage = message.toLocal8Bit();
return false;
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index fe0b6dae49..664ca98a3f 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -34,6 +34,7 @@
#include <qtextdocumentfragment.h>
#include <qtexttable.h>
#include <qtextlist.h>
+#include <qregularexpression.h>
#include <qdebug.h>
#include <private/qtextdocument_p.h>
@@ -944,7 +945,7 @@ void tst_QTextDocumentFragment::namedAnchorFragments3()
QCOMPARE(it.fragment().text(), QString::fromLatin1("T"));
QVERIFY(it.fragment().charFormat().isAnchor());
- QCOMPARE(it.fragment().charFormat().anchorName(), QString("target"));
+ QCOMPARE(it.fragment().charFormat().anchorNames().constFirst(), QLatin1String("target"));
QStringList targets; targets << "target" << "target2";
QCOMPARE(it.fragment().charFormat().anchorNames(), targets);
@@ -1925,7 +1926,7 @@ void tst_QTextDocumentFragment::html_nobr()
QString text = doc->begin().begin().fragment().text();
QString expectedText = input;
- expectedText.replace(QRegExp("\\s+"), QString(QChar::Nbsp));
+ expectedText.replace(QRegularExpression("\\s+"), QString(QChar::Nbsp));
QCOMPARE(text, expectedText);
}
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index 9c477589f9..aee2f970fe 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -138,6 +138,7 @@ private slots:
void noModificationOfInputString();
void superscriptCrash_qtbug53911();
void showLineAndParagraphSeparatorsCrash();
+ void koreanWordWrap();
private:
QFont testFont;
@@ -2227,7 +2228,6 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
for (int j = 0; j < 4; ++j) {
QTextLayout* newTextLayout = new QTextLayout();
newTextLayout->setText(layoutText);
- QList<QTextLayout::FormatRange> formatRanges;
QTextLayout::FormatRange formatRange;
formatRange.format.setFont(QFont());
@@ -2256,8 +2256,7 @@ void tst_QTextLayout::superscriptCrash_qtbug53911()
formatRange.start = 0;
formatRange.length = layoutText.size();
- formatRanges << formatRange;
- newTextLayout->setAdditionalFormats(formatRanges);
+ newTextLayout->setFormats({formatRange});
textLayouts.push_front(newTextLayout);
}
@@ -2288,10 +2287,7 @@ void tst_QTextLayout::nbspWithFormat()
formatRange.length = 1;
formatRange.format.setFontUnderline(true);
- QList<QTextLayout::FormatRange> overrides;
- overrides.append(formatRange);
-
- layout.setAdditionalFormats(overrides);
+ layout.setFormats({formatRange});
layout.beginLayout();
forever {
@@ -2309,5 +2305,30 @@ void tst_QTextLayout::nbspWithFormat()
QCOMPARE(layout.lineAt(1).textLength(), s2.length() + 1 + s3.length());
}
+void tst_QTextLayout::koreanWordWrap()
+{
+ QString s = QString::fromUtf8("안녕하세요 여러분!");
+ QTextLayout layout;
+ QTextOption option = layout.textOption();
+ option.setWrapMode(QTextOption::WordWrap);
+ option.setFlags(QTextOption::Flag(QTextOption::IncludeTrailingSpaces));
+ layout.setTextOption(option);
+ layout.setText(s);
+
+ QFontMetrics metrics(layout.font());
+
+ layout.beginLayout();
+ forever {
+ QTextLine line = layout.createLine();
+ if (!line.isValid())
+ break;
+ line.setLineWidth(metrics.horizontalAdvance(s) * 0.8);
+ }
+ layout.endLayout();
+ QCOMPARE(layout.lineCount(), 2);
+ QCOMPARE(layout.lineAt(0).textLength(), 6);
+ QCOMPARE(layout.lineAt(1).textLength(), 4);
+}
+
QTEST_MAIN(tst_QTextLayout)
#include "tst_qtextlayout.moc"
diff --git a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
index d623ce4044..93e40e7f23 100644
--- a/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
+++ b/tests/auto/gui/text/qtextlist/tst_qtextlist.cpp
@@ -314,7 +314,7 @@ void tst_QTextList::partialRemoval()
selection.deleteChar(); // deletes the second list
QVERIFY(!secondList);
- QVERIFY(!firstList->isEmpty());
+ QVERIFY(firstList->count() > 0);
doc->undo();
}
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
new file mode 100644
index 0000000000..99eb633d17
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/headingBulletsContinuations.md
@@ -0,0 +1,28 @@
+# heading
+- bullet 1
+ continuation line 1, indented via tab
+- bullet 2
+ continuation line 2, indented via 4 spaces
+- bullet 3
+
+ continuation paragraph 3, indented via tab
+
+ - bullet 3.1
+
+ continuation paragraph 3.1, indented via 4 spaces
+
+ - bullet 3.2
+ continuation line, indented via 2 tabs
+- bullet 4
+
+ continuation paragraph 4, indented via 4 spaces
+ and continuing onto another line too
+
+- bullet 5
+
+ continuation paragraph 5, indented via 2 spaces and continuing onto another
+ line too
+
+- bullet 6
+
+plain old paragraph at the end
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
new file mode 100644
index 0000000000..7a0d5388ad
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/data/thematicBreaks.md
@@ -0,0 +1,17 @@
+Heading
+-------
+***
+stars
+- bullet
+ ** not a bullet or a rule, just two stars
+- [ ] unchecked
+
+ --- indented too far, so not a rule
+* * *
+stars with tabs between
+***
+stars with whitespace after
+---
+hyphens with whitespace after
+_____
+underscores with whitespace after
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
new file mode 100644
index 0000000000..7b7fb61244
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/qtextmarkdownimporter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownimporter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownimporter.cpp
+TESTDATA += \
+ data/thematicBreaks.md \
+ data/headingBulletsContinuations.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
new file mode 100644
index 0000000000..8f51a7a474
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownimporter/tst_qtextmarkdownimporter.cpp
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownimporter_p.h>
+
+// #define DEBUG_WRITE_HTML
+
+Q_LOGGING_CATEGORY(lcTests, "qt.text.tests")
+
+static const QChar LineBreak = QChar(0x2028);
+static const QChar Tab = QLatin1Char('\t');
+static const QChar Space = QLatin1Char(' ');
+static const QChar Period = QLatin1Char('.');
+
+class tst_QTextMarkdownImporter : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void headingBulletsContinuations();
+ void thematicBreaks();
+};
+
+void tst_QTextMarkdownImporter::headingBulletsContinuations()
+{
+ const QStringList expectedBlocks = QStringList() <<
+ "" << // we could do without this blank line before the heading, but currently it happens
+ "heading" <<
+ "bullet 1 continuation line 1, indented via tab" <<
+ "bullet 2 continuation line 2, indented via 4 spaces" <<
+ "bullet 3" <<
+ "continuation paragraph 3, indented via tab" <<
+ "bullet 3.1" <<
+ "continuation paragraph 3.1, indented via 4 spaces" <<
+ "bullet 3.2 continuation line, indented via 2 tabs" <<
+ "bullet 4" <<
+ "continuation paragraph 4, indented via 4 spaces and continuing onto another line too" <<
+ "bullet 5" <<
+ // indenting by only 2 spaces is perhaps non-standard but currently is OK
+ "continuation paragraph 5, indented via 2 spaces and continuing onto another line too" <<
+ "bullet 6" <<
+ "plain old paragraph at the end";
+
+ QFile f(QFINDTESTDATA("data/headingBulletsContinuations.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ QStringList::const_iterator expectedIt = expectedBlocks.constBegin();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether we got the right child block
+ QTextBlock block = iterator.currentBlock();
+ QCOMPARE(block.text().contains(LineBreak), false);
+ QCOMPARE(block.text().contains(Tab), false);
+ QVERIFY(!block.text().startsWith(Space));
+ int expectedIndentation = 0;
+ if (block.text().contains(QLatin1String("continuation paragraph")))
+ expectedIndentation = (block.text().contains(Period) ? 2 : 1);
+ qCDebug(lcTests) << i << "child block" << block.text() << "indentation" << block.blockFormat().indent();
+ QVERIFY(expectedIt != expectedBlocks.constEnd());
+ QCOMPARE(block.text(), *expectedIt);
+ if (i > 2)
+ QCOMPARE(block.blockFormat().indent(), expectedIndentation);
+ ++iterator;
+ ++expectedIt;
+ ++i;
+ }
+ QCOMPARE(expectedIt, expectedBlocks.constEnd());
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/headingBulletsContinuations.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+void tst_QTextMarkdownImporter::thematicBreaks()
+{
+ int horizontalRuleCount = 0;
+ int textLinesCount = 0;
+
+ QFile f(QFINDTESTDATA("data/thematicBreaks.md"));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString md = QString::fromUtf8(f.readAll());
+ f.close();
+
+ QTextDocument doc;
+ QTextMarkdownImporter(QTextMarkdownImporter::DialectGitHub).import(&doc, md);
+ QTextFrame::iterator iterator = doc.rootFrame()->begin();
+ QTextFrame *currentFrame = iterator.currentFrame();
+ int i = 0;
+ while (!iterator.atEnd()) {
+ // There are no child frames
+ QCOMPARE(iterator.currentFrame(), currentFrame);
+ // Check whether the block is text or a horizontal rule
+ QTextBlock block = iterator.currentBlock();
+ if (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth))
+ ++horizontalRuleCount;
+ else if (!block.text().isEmpty())
+ ++textLinesCount;
+ qCDebug(lcTests) << i << (block.blockFormat().hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth) ? QLatin1String("- - -") : block.text());
+ ++iterator;
+ ++i;
+ }
+ QCOMPARE(horizontalRuleCount, 5);
+ QCOMPARE(textLinesCount, 9);
+
+#ifdef DEBUG_WRITE_HTML
+ {
+ QFile out("/tmp/thematicBreaks.html");
+ out.open(QFile::WriteOnly);
+ out.write(doc.toHtml().toLatin1());
+ out.close();
+ }
+#endif
+}
+
+QTEST_MAIN(tst_QTextMarkdownImporter)
+#include "tst_qtextmarkdownimporter.moc"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
new file mode 100644
index 0000000000..fc9e5a9efe
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/BLACKLIST
@@ -0,0 +1,3 @@
+[rewriteDocument]
+winrt # QTBUG-54623
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
new file mode 100644
index 0000000000..6336d0219f
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/blockquotes.md
@@ -0,0 +1,62 @@
+In 1958, Mahatma Gandhi was quoted as follows:
+
+> The Earth provides enough to satisfy every man's need but not for every man's
+> greed.
+
+In [The CommonMark Specification](https://spec.commonmark.org/0.29/) John
+MacFarlane writes:
+
+> What distinguishes Markdown from many other lightweight markup syntaxes,
+> which are often easier to write, is its readability. As Gruber writes:
+
+> > The overriding design goal for Markdown's formatting syntax is to make it
+> > as readable as possible. The idea is that a Markdown-formatted document should
+> > be publishable as-is, as plain text, without looking like it's been marked up
+> > with tags or formatting instructions. (
+> > [http://daringfireball.net/projects/markdown/](http://daringfireball.net/projects/markdown/)
+> > )
+
+> The point can be illustrated by comparing a sample of AsciiDoc with an
+> equivalent sample of Markdown. Here is a sample of AsciiDoc from the AsciiDoc
+> manual:
+
+> ``` AsciiDoc
+> 1. List item one.
+> +
+> List item one continued with a second paragraph followed by an
+> Indented block.
+> +
+> .................
+> $ ls *.sh
+> $ mv *.sh ~/tmp
+> .................
+> +
+> List item continued with a third paragraph.
+>
+> 2. List item two continued with an open block.
+> ...
+> ```
+The quotation includes an embedded quotation and a code quotation and ends with
+an ellipsis due to being incomplete.
+
+Now let's have an indented code block:
+
+ #include <stdio.h>
+
+ int main(void)
+ {
+ printf("# hello markdown\n");
+ return 0;
+ }
+
+and end with a fenced code block:
+~~~ pseudocode
+#include <something.h>
+#include <else.h>
+
+a block {
+ a statement;
+ another statement;
+}
+~~~
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/example.md b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
new file mode 100644
index 0000000000..0c3f34e09d
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/example.md
@@ -0,0 +1,95 @@
+# QTextEdit
+
+The QTextEdit widget is an advanced editor that supports formatted rich text.
+It can be used to display HTML and other rich document formats. Internally,
+QTextEdit uses the QTextDocument class to describe both the high-level
+structure of each document and the low-level formatting of paragraphs.
+
+If you are viewing this document in the textedit example, you can edit this
+document to explore Qt's rich text editing features. We have included some
+comments in each of the following sections to encourage you to experiment.
+
+## Font and Paragraph Styles
+
+QTextEdit supports **bold**, *italic*, and ~~strikethrough~~ font styles, and can
+display multicolored text. Font families such as Times New Roman and `Courier`
+can also be used directly. *If you place the cursor in a region of styled text,
+the controls in the tool bars will change to reflect the current style.*
+
+Paragraphs can be formatted so that the text is left-aligned, right-aligned,
+centered, or fully justified.
+
+*Try changing the alignment of some text and resize the editor to see how the
+text layout changes.*
+
+## Lists
+
+Different kinds of lists can be included in rich text documents. Standard
+bullet lists can be nested, using different symbols for each level of the list:
+
+- Disc symbols are typically used for top-level list items.
+ * Circle symbols can be used to distinguish between items in lower-level
+ lists.
+ + Square symbols provide a reasonable alternative to discs and circles.
+
+Ordered lists can be created that can be used for tables of contents. Different
+characters can be used to enumerate items, and we can use both Roman and Arabic
+numerals in the same list structure:
+
+1. Introduction
+2. Qt Tools
+ 1) Qt Assistant
+ 2) Qt Designer
+ 1. Form Editor
+ 2. Component Architecture
+ 3) Qt Linguist
+
+The list will automatically be renumbered if you add or remove items. *Try
+adding new sections to the above list or removing existing item to see the
+numbers change.*
+
+## Images
+
+Inline images are treated like ordinary ranges of characters in the text
+editor, so they flow with the surrounding text. Images can also be selected in
+the same way as text, making it easy to cut, copy, and paste them.
+
+![image](images/logo32.png) *Try to select this image by clicking and dragging
+over it with the mouse, or use the text cursor to select it by holding down
+Shift and using the arrow keys. You can then cut or copy it, and paste it into
+different parts of this document.*
+
+## Tables
+
+QTextEdit can arrange and format tables, supporting features such as row and
+column spans, text formatting within cells, and size constraints for columns.
+
+
+| |Development Tools |Programming Techniques |Graphical User Interfaces|
+|-------------|------------------------------------|---------------------------|-------------------------|
+|9:00 - 11:00 |Introduction to Qt |||
+|11:00 - 13:00|Using qmake |Object-oriented Programming|Layouts in Qt |
+|13:00 - 15:00|Qt Designer Tutorial |Extreme Programming |Writing Custom Styles |
+|15:00 - 17:00|Qt Linguist and Internationalization|  |  |
+
+*Try adding text to the cells in the table and experiment with the alignment of
+the paragraphs.*
+
+## Hyperlinks
+
+QTextEdit is designed to support hyperlinks between documents, and this feature
+is used extensively in
+[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
+automatically created when an HTML file is imported into an editor. Since the
+rich text framework supports hyperlinks natively, they can also be created
+programatically.
+
+## Undo and Redo
+
+Full support for undo and redo operations is built into QTextEdit and the
+underlying rich text framework. Operations on a document can be packaged
+together to make editing a more comfortable experience for the user.
+
+*Try making changes to this document and press `Ctrl+Z` to undo them. You can
+always recover the original contents of the document.*
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
new file mode 100644
index 0000000000..d5d14fb168
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/headingsAndLists.md
@@ -0,0 +1,12 @@
+# heading 1
+
+- list item 1
+- list item 2
+
+## heading 2
+
+1) list item 1
+2) list item 2
+
+the end paragraph
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
new file mode 100644
index 0000000000..dacb0acf77
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/data/wordWrap.md
@@ -0,0 +1,13 @@
+[The CommonMark Specification](https://spec.commonmark.org/0.29/) is the
+conservative formal specification of the Markdown format, while
+[GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
+adds extra features such as task lists and tables.
+
+Qt owes thanks to the authors of the [MD4C parser](https://github.com/mity/md4c)
+for making markdown import possible. The QTextMarkdownWriter class does not
+have such dependencies, and also has not yet been tested as extensively, so we
+do not yet guarantee that we are able to rewrite every Markdown document that
+you are able to read and display with Text or QTextEdit. But you are free to
+write [bugs](https://bugreports.qt.io) about any troublesome cases that you
+encounter.
+
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
new file mode 100644
index 0000000000..6144710b99
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/qtextmarkdownwriter.pro
@@ -0,0 +1,9 @@
+CONFIG += testcase
+TARGET = tst_qtextmarkdownwriter
+QT += core-private gui-private testlib
+SOURCES += tst_qtextmarkdownwriter.cpp
+TESTDATA += \
+ data/example.md \
+ data/blockquotes.md \
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
new file mode 100644
index 0000000000..8d38cbb18a
--- /dev/null
+++ b/tests/auto/gui/text/qtextmarkdownwriter/tst_qtextmarkdownwriter.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 <QtTest/QtTest>
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QTextList>
+#include <QTextTable>
+#include <QBuffer>
+#include <QDebug>
+
+#include <private/qtextmarkdownwriter_p.h>
+
+// #define DEBUG_WRITE_OUTPUT
+
+class tst_QTextMarkdownWriter : public QObject
+{
+ Q_OBJECT
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void testWriteParagraph_data();
+ void testWriteParagraph();
+ void testWriteList();
+ void testWriteNestedBulletLists_data();
+ void testWriteNestedBulletLists();
+ void testWriteNestedNumericLists();
+ void testWriteTable();
+ void rewriteDocument_data();
+ void rewriteDocument();
+ void fromHtml_data();
+ void fromHtml();
+
+private:
+ QString documentToUnixMarkdown();
+
+private:
+ QTextDocument *document;
+};
+
+void tst_QTextMarkdownWriter::init()
+{
+ document = new QTextDocument();
+}
+
+void tst_QTextMarkdownWriter::cleanup()
+{
+ delete document;
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph_data()
+{
+ QTest::addColumn<QString>("input");
+ QTest::addColumn<QString>("output");
+
+ QTest::newRow("empty") << "" <<
+ "";
+ QTest::newRow("spaces") << "foobar word" <<
+ "foobar word\n\n";
+ QTest::newRow("starting spaces") << " starting spaces" <<
+ " starting spaces\n\n";
+ QTest::newRow("trailing spaces") << "trailing spaces " <<
+ "trailing spaces \n\n";
+ QTest::newRow("tab") << "word\ttab x" <<
+ "word\ttab x\n\n";
+ QTest::newRow("tab2") << "word\t\ttab\tx" <<
+ "word\t\ttab\tx\n\n";
+ QTest::newRow("misc") << "foobar word\ttab x" <<
+ "foobar word\ttab x\n\n";
+ QTest::newRow("misc2") << "\t \tFoo" <<
+ "\t \tFoo\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteParagraph()
+{
+ QFETCH(QString, input);
+ QFETCH(QString, output);
+
+ QTextCursor cursor(document);
+ cursor.insertText(input);
+
+ QCOMPARE(documentToUnixMarkdown(), output);
+}
+
+void tst_QTextMarkdownWriter::testWriteList()
+{
+ QTextCursor cursor(document);
+ QTextList *list = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list->add(cursor.block());
+ cursor.insertBlock();
+ cursor.insertText("ListItem 2");
+ list->add(cursor.block());
+
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "- ListItem 1\n- ListItem 2\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists_data()
+{
+ QTest::addColumn<bool>("checkbox");
+ QTest::addColumn<bool>("checked");
+ QTest::addColumn<bool>("continuationLine");
+ QTest::addColumn<bool>("continuationParagraph");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("plain bullets") << false << false << false << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3\n- ListItem 4\n * ListItem 5\n";
+ QTest::newRow("bullets with continuation lines") << false << false << true << false <<
+ "- ListItem 1\n * ListItem 2\n + ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- ListItem 4\n * ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("bullets with continuation paragraphs") << false << false << false << true <<
+ "- ListItem 1\n\n * ListItem 2\n + ListItem 3\n\n continuation\n\n- ListItem 4\n\n * ListItem 5\n\n continuation\n\n";
+ QTest::newRow("unchecked") << true << false << false << false <<
+ "- [ ] ListItem 1\n * [ ] ListItem 2\n + [ ] ListItem 3\n- [ ] ListItem 4\n * [ ] ListItem 5\n";
+ QTest::newRow("checked") << true << true << false << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3\n- [x] ListItem 4\n * [x] ListItem 5\n";
+ QTest::newRow("checked with continuation lines") << true << true << true << false <<
+ "- [x] ListItem 1\n * [x] ListItem 2\n + [x] ListItem 3 with text that won't fit on one line and thus needs a\n continuation\n- [x] ListItem 4\n * [x] ListItem 5 with text that won't fit on one line and thus needs a\n continuation\n";
+ QTest::newRow("checked with continuation paragraphs") << true << true << false << true <<
+ "- [x] ListItem 1\n\n * [x] ListItem 2\n + [x] ListItem 3\n\n continuation\n\n- [x] ListItem 4\n\n * [x] ListItem 5\n\n continuation\n\n";
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedBulletLists()
+{
+ QFETCH(bool, checkbox);
+ QFETCH(bool, checked);
+ QFETCH(bool, continuationParagraph);
+ QFETCH(bool, continuationLine);
+ QFETCH(QString, expectedOutput);
+
+ QTextCursor cursor(document);
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+ if (checkbox) {
+ blockFmt.setMarker(checked ? QTextBlockFormat::Checked : QTextBlockFormat::Unchecked);
+ cursor.setBlockFormat(blockFmt);
+ }
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDisc);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListCircle);
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListSquare);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText(continuationLine ?
+ "ListItem 3 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 3");
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText(continuationLine ?
+ "ListItem 5 with text that won't fit on one line and thus needs a continuation" :
+ "ListItem 5");
+ list2->add(cursor.block());
+ if (continuationParagraph) {
+ QTextBlockFormat blockFmt;
+ blockFmt.setIndent(2);
+ cursor.insertBlock(blockFmt);
+ cursor.insertText("continuation");
+ }
+
+ QString output = documentToUnixMarkdown();
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+ QCOMPARE(documentToUnixMarkdown(), expectedOutput);
+}
+
+void tst_QTextMarkdownWriter::testWriteNestedNumericLists()
+{
+ QTextCursor cursor(document);
+
+ QTextList *list1 = cursor.createList(QTextListFormat::ListDecimal);
+ cursor.insertText("ListItem 1");
+ list1->add(cursor.block());
+
+ QTextListFormat fmt2;
+ fmt2.setStyle(QTextListFormat::ListLowerAlpha);
+ fmt2.setNumberSuffix(QLatin1String(")"));
+ fmt2.setIndent(2);
+ QTextList *list2 = cursor.insertList(fmt2);
+ cursor.insertText("ListItem 2");
+
+ QTextListFormat fmt3;
+ fmt3.setStyle(QTextListFormat::ListDecimal);
+ fmt3.setIndent(3);
+ cursor.insertList(fmt3);
+ cursor.insertText("ListItem 3");
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 4");
+ list1->add(cursor.block());
+
+ cursor.insertBlock();
+ cursor.insertText("ListItem 5");
+ list2->add(cursor.block());
+
+ // There's no QTextList API to set the starting number so we hard-coded all lists to start at 1 (QTBUG-65384)
+ QCOMPARE(documentToUnixMarkdown(), QString::fromLatin1(
+ "1. ListItem 1\n 1) ListItem 2\n 1. ListItem 3\n2. ListItem 4\n 2) ListItem 5\n"));
+}
+
+void tst_QTextMarkdownWriter::testWriteTable()
+{
+ QTextCursor cursor(document);
+ QTextTable * table = cursor.insertTable(4, 3);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ // valid Markdown tables need headers, but QTextTable doesn't make that distinction
+ // so QTextMarkdownWriter assumes the first row of any table is a header
+ cursor.insertText("one");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("two");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("three");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("alice");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("bob");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("carl");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("dennis");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("eric");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("fiona");
+ cursor.movePosition(QTextCursor::NextCell);
+
+ cursor.insertText("gina");
+ /*
+ |one |two |three|
+ |------|----|-----|
+ |alice |bob |carl |
+ |dennis|eric|fiona|
+ |gina | | |
+ */
+
+ QString md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QString expected = QString::fromLatin1(
+ "\n|one |two |three|\n|------|----|-----|\n|alice |bob |carl |\n|dennis|eric|fiona|\n|gina | | |\n\n");
+ QCOMPARE(md, expected);
+
+ // create table with merged cells
+ document->clear();
+ cursor = QTextCursor(document);
+ table = cursor.insertTable(3, 3);
+ table->mergeCells(0, 0, 1, 2);
+ table->mergeCells(1, 1, 1, 2);
+ cursor = table->cellAt(0, 0).firstCursorPosition();
+ cursor.insertText("a");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("b");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("c");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("d");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("e");
+ cursor.movePosition(QTextCursor::NextCell);
+ cursor.insertText("f");
+ /*
+ +---+-+
+ |a |b|
+ +---+-+
+ |c| d|
+ +-+-+-+
+ |e|f| |
+ +-+-+-+
+
+ generates
+
+ |a ||b|
+ |-|-|-|
+ |c|d ||
+ |e|f| |
+
+ */
+
+ md = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/table-merged-cells.md");
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(md, QString::fromLatin1("\n|a ||b|\n|-|-|-|\n|c|d ||\n|e|f| |\n\n"));
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument_data()
+{
+ QTest::addColumn<QString>("inputFile");
+
+ QTest::newRow("block quotes") << "blockquotes.md";
+ QTest::newRow("example") << "example.md";
+ QTest::newRow("list items after headings") << "headingsAndLists.md";
+ QTest::newRow("word wrap") << "wordWrap.md";
+}
+
+void tst_QTextMarkdownWriter::rewriteDocument()
+{
+ QFETCH(QString, inputFile);
+ QTextDocument doc;
+ QFile f(QFINDTESTDATA("data/" + inputFile));
+ QVERIFY(f.open(QFile::ReadOnly | QIODevice::Text));
+ QString orig = QString::fromUtf8(f.readAll());
+ f.close();
+ doc.setMarkdown(orig);
+ QString md = doc.toMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ QFile out("/tmp/rewrite-" + inputFile);
+ out.open(QFile::WriteOnly);
+ out.write(md.toUtf8());
+ out.close();
+#endif
+
+ QCOMPARE(md, orig);
+}
+
+void tst_QTextMarkdownWriter::fromHtml_data()
+{
+ QTest::addColumn<QString>("expectedInput");
+ QTest::addColumn<QString>("expectedOutput");
+
+ QTest::newRow("long URL") <<
+ "<span style=\"font-style:italic;\">https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/</span>" <<
+ "*https://www.example.com/dir/subdir/subsubdir/subsubsubdir/subsubsubsubdir/subsubsubsubsubdir/*\n\n";
+ QTest::newRow("non-emphasis inline asterisk") << "3 * 4" << "3 * 4\n\n";
+ QTest::newRow("arithmetic") << "(2 * a * x + b)^2 = b^2 - 4 * a * c" << "(2 * a * x + b)^2 = b^2 - 4 * a * c\n\n";
+ QTest::newRow("escaped asterisk after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star. * This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a star.\n\\* This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped plus after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus. + This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a plus.\n\\+ This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("escaped hyphen after newline") <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus. - This is wrapped, but is <em>not</em> a bullet point." <<
+ "The first sentence of this paragraph holds 80 characters, then there's a minus.\n\\- This is wrapped, but is *not* a bullet point.\n\n";
+ QTest::newRow("list items with indented continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n";
+ QTest::newRow("nested list items with continuations") <<
+ "<ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li><ul><li>bullet<p>continuation paragraph</p></li><li>another bullet<br/>continuation line</li></ul></ul>" <<
+ "- bullet\n\n continuation paragraph\n\n- another bullet\n continuation line\n\n - bullet\n\n continuation paragraph\n\n - another bullet\n continuation line\n";
+ QTest::newRow("nested ordered list items with continuations") <<
+ "<ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li><ol><li>item<p>continuation paragraph</p></li><li>another item<br/>continuation line</li></ol><li>another</li><li>another</li></ol>" <<
+ "1. item\n\n continuation paragraph\n\n2. another item\n continuation line\n\n 1. item\n\n continuation paragraph\n\n 2. another item\n continuation line\n\n3. another\n4. another\n";
+ QTest::newRow("thematic break") <<
+ "something<hr/>something else" <<
+ "something\n\n- - -\nsomething else\n\n";
+ QTest::newRow("block quote") <<
+ "<p>In 1958, Mahatma Gandhi was quoted as follows:</p><blockquote>The Earth provides enough to satisfy every man's need but not for every man's greed.</blockquote>" <<
+ "In 1958, Mahatma Gandhi was quoted as follows:\n\n> The Earth provides enough to satisfy every man's need but not for every man's\n> greed.\n\n";
+ QTest::newRow("image") <<
+ "<img src=\"/url\" alt=\"foo\" title=\"title\"/>" <<
+ "![foo](/url \"title\")\n\n";
+ QTest::newRow("code") <<
+ "<pre class=\"language-pseudocode\">\n#include \"foo.h\"\n\nblock {\n statement();\n}\n\n</pre>" <<
+ "``` pseudocode\n#include \"foo.h\"\n\nblock {\n statement();\n}\n```\n\n";
+ // TODO
+// QTest::newRow("escaped number and paren after double newline") <<
+// "<p>(The first sentence of this paragraph is a line, the next paragraph has a number</p>13) but that's not part of an ordered list" <<
+// "(The first sentence of this paragraph is a line, the next paragraph has a number\n\n13\\) but that's not part of an ordered list\n\n";
+// QTest::newRow("preformats with embedded backticks") <<
+// "<pre>none `one` ``two``</pre><pre>```three``` ````four````</pre>plain" <<
+// "``` none `one` ``two`` ```\n\n````` ```three``` ````four```` `````\n\nplain\n\n";
+}
+
+void tst_QTextMarkdownWriter::fromHtml()
+{
+ QFETCH(QString, expectedInput);
+ QFETCH(QString, expectedOutput);
+
+ document->setHtml(expectedInput);
+ QString output = documentToUnixMarkdown();
+
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out("/tmp/" + QLatin1String(QTest::currentDataTag()) + ".md");
+ out.open(QFile::WriteOnly);
+ out.write(output.toUtf8());
+ out.close();
+ }
+#endif
+
+ QCOMPARE(output, expectedOutput);
+}
+
+QString tst_QTextMarkdownWriter::documentToUnixMarkdown()
+{
+ QString ret;
+ QTextStream ts(&ret, QIODevice::WriteOnly);
+ QTextMarkdownWriter writer(ts, QTextDocument::MarkdownDialectGitHub);
+ writer.writeAll(document);
+ return ret;
+}
+
+QTEST_MAIN(tst_QTextMarkdownWriter)
+#include "tst_qtextmarkdownwriter.moc"
diff --git a/tests/auto/gui/text/text.pro b/tests/auto/gui/text/text.pro
index 6b033fb506..794d9ea8d3 100644
--- a/tests/auto/gui/text/text.pro
+++ b/tests/auto/gui/text/text.pro
@@ -28,12 +28,16 @@ SUBDIRS=\
win32:SUBDIRS -= qtextpiecetable
+qtConfig(textmarkdownreader): SUBDIRS += qtextmarkdownimporter
+qtConfig(textmarkdownwriter): SUBDIRS += qtextmarkdownwriter
+
!qtConfig(private_tests): SUBDIRS -= \
qfontcache \
qcssparser \
qtextlayout \
qtextpiecetable \
qzip \
+ qtextmarkdownwriter \
qtextodfwriter
!qtHaveModule(xml): SUBDIRS -= \