From 938df790810ddd9ec405e8a5ce8e8c7d90d6dd03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 2 Oct 2024 11:43:27 +0200 Subject: [PATCH] Add manual test for QtGui color management The example presents three windows. One that does no attempt at color management, one that color matches from sRGB to whatever the window (or screen) color space is, and one that explicitly requests an sRGB color space for the window. Task-number: QTBUG-129499 Change-Id: Id2bfc244f28acc2c31c48b06584de6cb3ed212e3 Reviewed-by: Allan Sandfeld Jensen --- tests/manual/colormanagement/CMakeLists.txt | 10 ++ tests/manual/colormanagement/main.cpp | 117 ++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 tests/manual/colormanagement/CMakeLists.txt create mode 100644 tests/manual/colormanagement/main.cpp diff --git a/tests/manual/colormanagement/CMakeLists.txt b/tests/manual/colormanagement/CMakeLists.txt new file mode 100644 index 00000000000..cc0dd8efe34 --- /dev/null +++ b/tests/manual/colormanagement/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_manual_test(colormanagement + SOURCES + main.cpp + LIBRARIES + Qt::Gui + Qt::GuiPrivate +) diff --git a/tests/manual/colormanagement/main.cpp b/tests/manual/colormanagement/main.cpp new file mode 100644 index 00000000000..e0c1e41f77f --- /dev/null +++ b/tests/manual/colormanagement/main.cpp @@ -0,0 +1,117 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include +#include + +QString debugDescription(const QColorSpace &colorSpace) +{ + QString str; + QDebug dbg(&str); + dbg << colorSpace; + return str; +} + +// The color space of our assets that we need to color match from. +// In real world apps this could be different for each QImage etc. +static const QColorSpace assetColorSpace = QColorSpace::AdobeRgb; + +class TestWindow : public QRasterWindow +{ +public: + using QRasterWindow::QRasterWindow; + TestWindow() + { + resize(900, 300); + setFlag(Qt::NoDropShadowWindowHint); + + // Moving a window to a different screen may not result + // in an automatic expose/paint event, as the window's + // content might still be valid on the new screen. In + // our case we know it's not, as we need to update the + // screen information we reflect in the paintEvent below. + QObject::connect(this, &QWindow::screenChanged, + this, qOverload<>(&QRasterWindow::update)); + } + + bool colorManaged = false; + +protected: + void paintEvent(QPaintEvent *) override + { + QPainter painter(this); + + auto requestedColorSpace = requestedFormat().colorSpace(); + auto windowColorSpace = format().colorSpace(); + auto screenColorSpace = screen()->handle()->colorSpace(); + + auto targetColorSpace = windowColorSpace; + if (!targetColorSpace.isValid()) { + qWarning("Window does not report color space! Using screen color space as target"); + targetColorSpace = screenColorSpace; + } + auto colorTransform = assetColorSpace.transformationToColorSpace(targetColorSpace); + + if (!colorManaged && requestedColorSpace.isValid() && !colorTransform.isIdentity()) { + qWarning() << "Requested" << requestedColorSpace << "but got" + << targetColorSpace << "and not prepared to do color matching"; + } + + QColor colors[] = { + QColor(Qt::red), + QColor(Qt::green), + QColor(Qt::blue), + QColor(Qt::cyan), + QColor(Qt::magenta), + QColor(Qt::yellow) + }; + qreal colorWidth = width() / qreal(std::size(colors)); + for (size_t i = 0; i < std::size(colors); ++i) { + QColor color = colors[i]; + if (colorManaged) + color = colorTransform.map(color); + + painter.fillRect(QRectF(colorWidth * i, 0, colorWidth, height()), color); + } + + QRect rect(0, 0, width(), height()); + painter.fillRect(rect.adjusted(20, 100, -20, -100), Qt::white); + painter.drawText(rect, Qt::AlignCenter, + QString("Assets: %1\nRequested: %2\nWindow: %3\nScreen: %4").arg( + debugDescription(assetColorSpace) + ).arg( + debugDescription(windowColorSpace) + ).arg( + debugDescription(windowColorSpace) + ).arg( + debugDescription(screenColorSpace) + )); + } +}; + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + TestWindow defaultColorSpaceWindow; + defaultColorSpaceWindow.setTitle(QString( + "Color-space unaware (pass-through, assuming surface/screen is %1)").arg( + assetColorSpace.description())); + defaultColorSpaceWindow.show(); + + TestWindow colorSpaceAwareWindow; + colorSpaceAwareWindow.setTitle(QString( + "Color-space aware (match %1 to surface)").arg(assetColorSpace.description())); + colorSpaceAwareWindow.colorManaged = true; + colorSpaceAwareWindow.show(); + + TestWindow explicitColorSpaceWindow; + explicitColorSpaceWindow.setTitle(QString( + "Explicit %1 surface").arg(assetColorSpace.description())); + auto format = explicitColorSpaceWindow.format(); + format.setColorSpace(assetColorSpace); + explicitColorSpaceWindow.setFormat(format); + explicitColorSpaceWindow.show(); + + return app.exec(); +}