summaryrefslogtreecommitdiffstats
path: root/tests/manual/textrendering
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-11-28 16:56:44 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-12-08 15:27:06 +0000
commite12aad05f039ddaefd444f80246845090ef9ce13 (patch)
tree69000ca743a2d5b78d5a2ba3806d4176dddfd597 /tests/manual/textrendering
parenta71f50edc6431a7d5a8b4a4836e98ca59e6ad7ae (diff)
Add manual test case for verifying our text rendering
Allows comparing Qt's text rendering to the native rendering. Change-Id: I56f015fb64df3f70c33db58891876c325cbbc55d Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'tests/manual/textrendering')
-rw-r--r--tests/manual/textrendering/nativetext/main.cpp310
-rw-r--r--tests/manual/textrendering/nativetext/nativetext.pro7
-rw-r--r--tests/manual/textrendering/textrendering.pro3
3 files changed, 319 insertions, 1 deletions
diff --git a/tests/manual/textrendering/nativetext/main.cpp b/tests/manual/textrendering/nativetext/main.cpp
new file mode 100644
index 0000000000..5c7621e61f
--- /dev/null
+++ b/tests/manual/textrendering/nativetext/main.cpp
@@ -0,0 +1,310 @@
+/****************************************************************************
+**
+** 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 <QtWidgets>
+
+#ifdef Q_OS_DARWIN
+#include <private/qcoregraphics_p.h>
+#include <private/qcore_mac_p.h>
+#include <Foundation/Foundation.h>
+#include <private/qfont_p.h>
+#include <private/qfontengine_p.h>
+#endif
+
+static int s_mode;
+static QString s_text = QString::fromUtf8("The quick brown \xF0\x9F\xA6\x8A jumps over the lazy \xF0\x9F\x90\xB6");
+
+class TextRenderer : public QWidget
+{
+ Q_OBJECT
+public:
+ enum RenderingMode { QtRendering, NativeRendering };
+ Q_ENUM(RenderingMode);
+
+ TextRenderer(qreal pointSize, const QString &text, const QColor &textColor = QColor(), const QColor &bgColor = QColor())
+ : m_text(text)
+ {
+ if (pointSize) {
+ QFont f = font();
+ f.setPointSize(pointSize);
+ setFont(f);
+ }
+
+ if (textColor.isValid()) {
+ QPalette p = palette();
+ p.setColor(QPalette::Text, textColor);
+ setPalette(p);
+ }
+
+ if (bgColor.isValid()) {
+ QPalette p = palette();
+ p.setColor(QPalette::Window, bgColor);
+ setPalette(p);
+ }
+ }
+
+ QString text() const
+ {
+ return !m_text.isNull() ? m_text : s_text;
+ }
+
+ QSize sizeHint() const override
+ {
+ QFontMetrics fm = fontMetrics();
+ return QSize(fm.boundingRect(text()).width(), fm.height());
+ }
+
+ bool event(QEvent * event) override
+ {
+ if (event->type() == QEvent::ToolTip) {
+ QString toolTip;
+ QDebug debug(&toolTip);
+ debug << "textColor =" << palette().color(QPalette::Text) << "bgColor =" << palette().color(QPalette::Window);
+ setToolTip(toolTip);
+ }
+
+ return QWidget::event(event);
+ }
+
+ void paintEvent(QPaintEvent *) override
+ {
+ QImage image(size() * devicePixelRatio(), QImage::Format_ARGB32_Premultiplied);
+ image.setDevicePixelRatio(devicePixelRatio());
+
+ QPainter p(&image);
+ p.fillRect(QRect(0, 0, image.width(), image.height()), palette().window().color());
+
+ const int ascent = fontMetrics().ascent();
+
+ p.setPen(Qt::magenta);
+ p.drawLine(QPoint(0, ascent), QPoint(width(), ascent));
+ p.end();
+
+ if (s_mode == QtRendering)
+ renderQtText(image);
+ else
+ renderNativeText(image);
+
+ QPainter wp(this);
+ wp.drawImage(QPoint(0, 0), image);
+ }
+
+ void renderQtText(QImage &image)
+ {
+ QPainter p(&image);
+
+ const int ascent = fontMetrics().ascent();
+
+ p.setPen(palette().text().color());
+
+ QFont f = font();
+ f.resolve(-1);
+ p.setFont(f);
+
+ p.drawText(QPoint(0, ascent), text());
+ }
+
+ void renderNativeText(QImage &image)
+ {
+#ifdef Q_OS_DARWIN
+ QMacAutoReleasePool pool;
+ QMacCGContext ctx(&image);
+
+ const auto *fontEngine = QFontPrivate::get(font())->engineForScript(QChar::Script_Common);
+ Q_ASSERT(fontEngine);
+ if (fontEngine->type() == QFontEngine::Multi) {
+ fontEngine = static_cast<const QFontEngineMulti *>(fontEngine)->engine(0);
+ Q_ASSERT(fontEngine);
+ }
+ Q_ASSERT(fontEngine->type() == QFontEngine::Mac);
+
+ QColor textColor = palette().text().color();
+ auto nsColor = [NSColor colorWithSRGBRed:textColor.redF()
+ green:textColor.greenF()
+ blue:textColor.blueF()
+ alpha:textColor.alphaF()];
+
+ if (font().styleStrategy() & QFont::NoAntialias)
+ CGContextSetShouldAntialias(ctx, false);
+
+ // Retain count already tracked by QMacCGContext above
+ NSGraphicsContext.currentContext = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:YES];
+ [text().toNSString() drawAtPoint:CGPointZero withAttributes:@{
+ NSFontAttributeName : (NSFont *)fontEngine->handle(),
+ NSForegroundColorAttributeName : nsColor
+ }];
+ NSGraphicsContext.currentContext = nil;
+#endif
+ }
+
+public:
+
+ RenderingMode m_mode = QtRendering;
+ QString m_text;
+};
+
+class TestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ TestWidget()
+ {
+ auto *mainLayout = new QVBoxLayout;
+
+ m_previews = new QWidget;
+ m_previews->setLayout(new QHBoxLayout);
+
+ for (int i = 0; i < 6; ++i) {
+ auto *layout = new QVBoxLayout;
+ QString text;
+ if (i > 0)
+ text = "ABC";
+
+ QPair<QColor, QColor> color = [i] {
+ switch (i) {
+ case 0: return qMakePair(QColor(), QColor());
+ case 1: return qMakePair(QColor(Qt::black), QColor(Qt::white));
+ case 2: return qMakePair(QColor(Qt::white), QColor(Qt::black));
+ case 3: return qMakePair(QColor(Qt::green), QColor(Qt::red));
+ case 4: return qMakePair(QColor(0, 0, 0, 128), QColor(Qt::white));
+ case 5: return qMakePair(QColor(255, 255, 255, 128), QColor(Qt::black));
+ default: return qMakePair(QColor(), QColor());
+ }
+ }();
+
+ layout->addWidget(new TextRenderer(12, text, color.first, color.second));
+ layout->addWidget(new TextRenderer(24, text, color.first, color.second));
+ layout->addWidget(new TextRenderer(36, text, color.first, color.second));
+ layout->addWidget(new TextRenderer(48, text, color.first, color.second));
+ static_cast<QHBoxLayout*>(m_previews->layout())->addLayout(layout);
+ }
+
+ mainLayout->addWidget(m_previews);
+
+ auto *controls = new QHBoxLayout;
+ auto *lineEdit = new QLineEdit(s_text);
+ connect(lineEdit, &QLineEdit::textChanged, [&](const QString &text) {
+ s_text = text;
+ for (TextRenderer *renderer : m_previews->findChildren<TextRenderer *>())
+ renderer->updateGeometry();
+ });
+ controls->addWidget(lineEdit);
+
+ auto *colorButton = new QPushButton("Color...");
+ connect(colorButton, &QPushButton::clicked, [&] {
+ auto *colorDialog = new QColorDialog(this);
+ colorDialog->setOptions(QColorDialog::NoButtons | QColorDialog::ShowAlphaChannel);
+ colorDialog->setModal(false);
+ connect(colorDialog, &QColorDialog::currentColorChanged, [&](const QColor &color) {
+ QPalette p = palette();
+ p.setColor(QPalette::Text, color);
+ setPalette(p);
+ });
+ colorDialog->setCurrentColor(palette().text().color());
+ colorDialog->setVisible(true);
+ });
+ controls->addWidget(colorButton);
+ auto *fontButton = new QPushButton("Font...");
+ connect(fontButton, &QPushButton::clicked, [&] {
+ auto *fontDialog = new QFontDialog(this);
+ fontDialog->setOptions(QFontDialog::NoButtons);
+ fontDialog->setModal(false);
+ fontDialog->setCurrentFont(m_previews->font());
+ connect(fontDialog, &QFontDialog::currentFontChanged, [&](const QFont &font) {
+ m_previews->setFont(font);
+ });
+ fontDialog->setVisible(true);
+ });
+ controls->addWidget(fontButton);
+
+ auto *aaButton = new QCheckBox("NoAntialias");
+ connect(aaButton, &QCheckBox::stateChanged, [&] {
+ for (TextRenderer *renderer : m_previews->findChildren<TextRenderer *>()) {
+ QFont font = renderer->font();
+ font.setStyleStrategy(QFont::StyleStrategy(font.styleStrategy() ^ QFont::NoAntialias));
+ renderer->setFont(font);
+ }
+ });
+ controls->addWidget(aaButton);
+
+ auto *subpixelAAButton = new QCheckBox("NoSubpixelAntialias");
+ connect(subpixelAAButton, &QCheckBox::stateChanged, [&] {
+ for (TextRenderer *renderer : m_previews->findChildren<TextRenderer *>()) {
+ QFont font = renderer->font();
+ font.setStyleStrategy(QFont::StyleStrategy(font.styleStrategy() ^ QFont::NoSubpixelAntialias));
+ renderer->setFont(font);
+ }
+ });
+ controls->addWidget(subpixelAAButton);
+ controls->addStretch();
+
+ mainLayout->addLayout(controls);
+
+ mainLayout->setSizeConstraint(QLayout::SetFixedSize);
+ setLayout(mainLayout);
+
+ setMode(TextRenderer::QtRendering);
+ setFocusPolicy(Qt::StrongFocus);
+ setFocus();
+ }
+
+ void setMode(TextRenderer::RenderingMode mode)
+ {
+ s_mode = mode;
+ setWindowTitle(s_mode == TextRenderer::QtRendering ? "Qt" : "Native");
+
+ for (TextRenderer *renderer : m_previews->findChildren<TextRenderer *>())
+ renderer->update();
+ }
+
+ void mousePressEvent(QMouseEvent *) override
+ {
+ setMode(TextRenderer::RenderingMode(!s_mode));
+ }
+
+ void keyPressEvent(QKeyEvent *e) override
+ {
+ if (e->key() == Qt::Key_Space)
+ setMode(TextRenderer::RenderingMode(!s_mode));
+ }
+
+ QWidget *m_previews;
+};
+
+int main(int argc, char **argv)
+{
+ qputenv("QT_MAX_CACHED_GLYPH_SIZE", "97");
+ QApplication app(argc, argv);
+
+ TestWidget widget;
+ widget.show();
+ return app.exec();
+}
+
+#include "main.moc"
+
diff --git a/tests/manual/textrendering/nativetext/nativetext.pro b/tests/manual/textrendering/nativetext/nativetext.pro
new file mode 100644
index 0000000000..fb3e3799e7
--- /dev/null
+++ b/tests/manual/textrendering/nativetext/nativetext.pro
@@ -0,0 +1,7 @@
+QT += widgets core-private gui-private
+SOURCES += main.cpp
+CONFIG -= app_bundle
+darwin {
+ QMAKE_CXXFLAGS += -x objective-c++
+ LIBS += -framework Foundation -framework CoreGraphics -framework AppKit
+}
diff --git a/tests/manual/textrendering/textrendering.pro b/tests/manual/textrendering/textrendering.pro
index 92f0741bf3..14806e416c 100644
--- a/tests/manual/textrendering/textrendering.pro
+++ b/tests/manual/textrendering/textrendering.pro
@@ -1,4 +1,5 @@
TEMPLATE=subdirs
SUBDIRS = glyphshaping \
- textperformance
+ textperformance \
+ nativetext