diff options
Diffstat (limited to 'tests/manual/qglyphruns')
-rw-r--r-- | tests/manual/qglyphruns/CMakeLists.txt | 17 | ||||
-rw-r--r-- | tests/manual/qglyphruns/controller.cpp | 57 | ||||
-rw-r--r-- | tests/manual/qglyphruns/controller.h | 29 | ||||
-rw-r--r-- | tests/manual/qglyphruns/controller.ui | 200 | ||||
-rw-r--r-- | tests/manual/qglyphruns/glyphruninspector.cpp | 48 | ||||
-rw-r--r-- | tests/manual/qglyphruns/glyphruninspector.h | 31 | ||||
-rw-r--r-- | tests/manual/qglyphruns/main.cpp | 18 | ||||
-rw-r--r-- | tests/manual/qglyphruns/singleglyphrun.cpp | 73 | ||||
-rw-r--r-- | tests/manual/qglyphruns/singleglyphrun.h | 30 | ||||
-rw-r--r-- | tests/manual/qglyphruns/singleglyphrun.ui | 61 | ||||
-rw-r--r-- | tests/manual/qglyphruns/view.cpp | 70 | ||||
-rw-r--r-- | tests/manual/qglyphruns/view.h | 42 |
12 files changed, 676 insertions, 0 deletions
diff --git a/tests/manual/qglyphruns/CMakeLists.txt b/tests/manual/qglyphruns/CMakeLists.txt new file mode 100644 index 0000000000..4af9c3e241 --- /dev/null +++ b/tests/manual/qglyphruns/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +qt_internal_add_manual_test(qglyphrun + GUI + SOURCES + main.cpp + controller.h controller.cpp controller.ui + view.h view.cpp + glyphruninspector.h glyphruninspector.cpp + singleglyphrun.h singleglyphrun.cpp singleglyphrun.ui + LIBRARIES + Qt::Gui + Qt::Widgets + ENABLE_AUTOGEN_TOOLS + uic +) diff --git a/tests/manual/qglyphruns/controller.cpp b/tests/manual/qglyphruns/controller.cpp new file mode 100644 index 0000000000..0037d11b5b --- /dev/null +++ b/tests/manual/qglyphruns/controller.cpp @@ -0,0 +1,57 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "controller.h" +#include "ui_controller.h" + +Controller::Controller(QWidget *parent) : + QWidget(parent), + ui(new Ui::Controller) +{ + ui->setupUi(this); + + connect(ui->cbWrap, &QCheckBox::toggled, this, &Controller::updateViews); + connect(ui->gbRange, &QGroupBox::toggled, this, &Controller::updateViews); + connect(ui->teSourceString, &QPlainTextEdit::textChanged, this, &Controller::updateViews); + connect(ui->hsLineWidth, &QSlider::valueChanged, this, &Controller::updateViews); + connect(ui->inspector, &GlyphRunInspector::updateBounds, ui->view, &View::setVisualizedBounds); + connect(ui->sbFrom, &QSpinBox::valueChanged, this, &Controller::updateViews); + connect(ui->sbTo, &QSpinBox::valueChanged, this, &Controller::updateViews); + connect(ui->teSourceString, &QPlainTextEdit::selectionChanged, this, &Controller::updateRange); + connect(ui->fcbFont, &QFontComboBox::currentFontChanged, this, &Controller::updateViews); +} + +Controller::~Controller() +{ + delete ui; +} + +void Controller::updateRange() +{ + if (ui->gbRange->isChecked()) { + QTextCursor cursor = ui->teSourceString->textCursor(); + if (cursor.hasSelection()) { + ui->sbFrom->setValue(cursor.selectionStart()); + ui->sbTo->setValue(cursor.selectionEnd() - 1); + + updateViews(); + } + } +} + +void Controller::updateViews() +{ + QString s = ui->teSourceString->toPlainText(); + ui->sbFrom->setMaximum(s.length()); + ui->sbTo->setMaximum(s.length()); + + s.replace('\n', QChar::LineSeparator); + ui->view->updateLayout(s, + qreal(ui->hsLineWidth->value()) * ui->hsLineWidth->width() / 100.0f, + ui->cbWrap ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::ManualWrap, + ui->fcbFont->currentFont()); + + int start = ui->gbRange->isChecked() ? ui->sbFrom->value() : -1; + int length = ui->gbRange->isChecked() ? ui->sbTo->value() - start + 1 : -1; + ui->inspector->updateLayout(ui->view->layout(), start, length); +} diff --git a/tests/manual/qglyphruns/controller.h b/tests/manual/qglyphruns/controller.h new file mode 100644 index 0000000000..75289165f8 --- /dev/null +++ b/tests/manual/qglyphruns/controller.h @@ -0,0 +1,29 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include <QWidget> + +namespace Ui { +class Controller; +} + +class Controller : public QWidget +{ + Q_OBJECT + +public: + explicit Controller(QWidget *parent = nullptr); + ~Controller(); + +private slots: + void updateViews(); + void updateRange(); + +private: + Ui::Controller *ui; +}; + +#endif // CONTROLLER_H diff --git a/tests/manual/qglyphruns/controller.ui b/tests/manual/qglyphruns/controller.ui new file mode 100644 index 0000000000..903135a281 --- /dev/null +++ b/tests/manual/qglyphruns/controller.ui @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Controller</class> + <widget class="QWidget" name="Controller"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>549</width> + <height>419</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Source string:</string> + </property> + </widget> + </item> + <item> + <widget class="QPlainTextEdit" name="teSourceString"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QCheckBox" name="cbWrap"> + <property name="text"> + <string>Wrap</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QFontComboBox" name="fcbFont"/> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="gbRange"> + <property name="title"> + <string>Range</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>false</bool> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>From</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sbFrom"/> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>To</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sbTo"/> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Display</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="View" name="view" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Minimum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QSlider" name="hsLineWidth"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="GlyphRunInspector" name="inspector" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pbQuit"> + <property name="text"> + <string>Quit</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>View</class> + <extends>QWidget</extends> + <header>view.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>GlyphRunInspector</class> + <extends>QWidget</extends> + <header>glyphruninspector.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>pbQuit</sender> + <signal>clicked()</signal> + <receiver>Controller</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>517</x> + <y>398</y> + </hint> + <hint type="destinationlabel"> + <x>35</x> + <y>-16</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tests/manual/qglyphruns/glyphruninspector.cpp b/tests/manual/qglyphruns/glyphruninspector.cpp new file mode 100644 index 0000000000..0e35a1f94b --- /dev/null +++ b/tests/manual/qglyphruns/glyphruninspector.cpp @@ -0,0 +1,48 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "glyphruninspector.h" +#include "singleglyphrun.h" + +#include <QTextLayout> +#include <QtWidgets> + +GlyphRunInspector::GlyphRunInspector(QWidget *parent) + : QWidget{parent} +{ + QHBoxLayout *layout = new QHBoxLayout(this); + + m_tabWidget = new QTabWidget; + layout->addWidget(m_tabWidget); + + connect(m_tabWidget, + &QTabWidget::currentChanged, + this, + &GlyphRunInspector::updateVisualizationForTab); +} + +void GlyphRunInspector::updateVisualizationForTab() +{ + int currentTab = m_tabWidget->currentIndex(); + SingleGlyphRun *gr = currentTab >= 0 && currentTab < m_content.size() ? m_content.at(currentTab) : nullptr; + if (gr != nullptr) + emit updateBounds(gr->bounds()); +} + +void GlyphRunInspector::updateLayout(QTextLayout *layout, int start, int length) +{ + QList<QGlyphRun> glyphRuns = layout->glyphRuns(start, length, QTextLayout::RetrieveAll); + + m_tabWidget->clear(); + qDeleteAll(m_content); + m_content.clear(); + for (int i = 0; i < glyphRuns.size(); ++i) { + SingleGlyphRun *w = new SingleGlyphRun(m_tabWidget); + w->updateGlyphRun(glyphRuns.at(i)); + + m_tabWidget->addTab(w, QStringLiteral("%1").arg(glyphRuns.at(i).rawFont().familyName())); + m_content.append(w); + } + + updateVisualizationForTab(); +} diff --git a/tests/manual/qglyphruns/glyphruninspector.h b/tests/manual/qglyphruns/glyphruninspector.h new file mode 100644 index 0000000000..d2aa6033db --- /dev/null +++ b/tests/manual/qglyphruns/glyphruninspector.h @@ -0,0 +1,31 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef GLYPHRUNINSPECTOR_H +#define GLYPHRUNINSPECTOR_H + +#include <QWidget> + +class QTextLayout; +class QTabWidget; +class SingleGlyphRun; +class GlyphRunInspector : public QWidget +{ + Q_OBJECT +public: + explicit GlyphRunInspector(QWidget *parent = nullptr); + + void updateLayout(QTextLayout *layout, int start, int length); + +private slots: + void updateVisualizationForTab(); + +signals: + void updateBounds(const QRegion ®ion); + +private: + QTabWidget *m_tabWidget; + QList<SingleGlyphRun *> m_content; +}; + +#endif // GLYPHRUNINSPECTOR_H diff --git a/tests/manual/qglyphruns/main.cpp b/tests/manual/qglyphruns/main.cpp new file mode 100644 index 0000000000..0f192e051f --- /dev/null +++ b/tests/manual/qglyphruns/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "controller.h" + +#include <QtWidgets> + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + Controller controller; + controller.showMaximized(); + + return app.exec(); +} + +#include "main.moc" diff --git a/tests/manual/qglyphruns/singleglyphrun.cpp b/tests/manual/qglyphruns/singleglyphrun.cpp new file mode 100644 index 0000000000..9a5bd3e139 --- /dev/null +++ b/tests/manual/qglyphruns/singleglyphrun.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "singleglyphrun.h" +#include "ui_singleglyphrun.h" + +SingleGlyphRun::SingleGlyphRun(QWidget *parent) : + QWidget(parent), + ui(new Ui::SingleGlyphRun) +{ + ui->setupUi(this); +} + +SingleGlyphRun::~SingleGlyphRun() +{ + delete ui; +} + +void SingleGlyphRun::updateGlyphRun(const QGlyphRun &glyphRun) +{ + m_bounds = QRegion(); + + QList<quint32> glyphIndexes = glyphRun.glyphIndexes(); + QList<qsizetype> stringIndexes = glyphRun.stringIndexes(); + QList<QPointF> glyphPositions = glyphRun.positions(); + + ui->twGlyphRun->clearContents(); + ui->twGlyphRun->setRowCount(glyphIndexes.size()); + + for (int i = 0; i < glyphIndexes.size(); ++i) { + { + QTableWidgetItem *glyphIndex = new QTableWidgetItem(QString::number(glyphIndexes.at(i))); + ui->twGlyphRun->setItem(i, 0, glyphIndex); + } + + { + QPointF position = glyphPositions.at(i); + QTableWidgetItem *glyphPosition = new QTableWidgetItem(QStringLiteral("(%1, %2)") + .arg(position.x()) + .arg(position.y())); + ui->twGlyphRun->setItem(i, 1, glyphPosition); + } + + { + QTableWidgetItem *stringIndex = new QTableWidgetItem(QString::number(stringIndexes.at(i))); + ui->twGlyphRun->setItem(i, 2, stringIndex); + } + + QChar c = glyphRun.sourceString().at(stringIndexes.at(i)); + + { + QTableWidgetItem *unicode = new QTableWidgetItem(QString::number(c.unicode(), 16)); + ui->twGlyphRun->setItem(i, 3, unicode); + } + + { + QTableWidgetItem *character = new QTableWidgetItem(c); + ui->twGlyphRun->setItem(i, 4, character); + } + + { + QImage image = glyphRun.rawFont().alphaMapForGlyph(glyphIndexes.at(i)); + + QTableWidgetItem *glyphImage = new QTableWidgetItem(QIcon(QPixmap::fromImage(image)), QString{}); + ui->twGlyphRun->setItem(i, 5, glyphImage); + } + + QRectF brect = glyphRun.rawFont().boundingRect(glyphIndexes.at(i)); + brect.adjust(glyphPositions.at(i).x(), glyphPositions.at(i).y(), + glyphPositions.at(i).x(), glyphPositions.at(i).y()); + m_bounds += brect.toAlignedRect(); + } +} diff --git a/tests/manual/qglyphruns/singleglyphrun.h b/tests/manual/qglyphruns/singleglyphrun.h new file mode 100644 index 0000000000..138d820ad4 --- /dev/null +++ b/tests/manual/qglyphruns/singleglyphrun.h @@ -0,0 +1,30 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef SINGLEGLYPHRUN_H +#define SINGLEGLYPHRUN_H + +#include <QWidget> +#include <QGlyphRun> + +namespace Ui { +class SingleGlyphRun; +} + +class SingleGlyphRun : public QWidget +{ + Q_OBJECT + +public: + explicit SingleGlyphRun(QWidget *parent = nullptr); + ~SingleGlyphRun(); + + void updateGlyphRun(const QGlyphRun &glyphRun); + QRegion bounds() const { return m_bounds; } + +private: + Ui::SingleGlyphRun *ui; + QRegion m_bounds; +}; + +#endif // SINGLEGLYPHRUN_H diff --git a/tests/manual/qglyphruns/singleglyphrun.ui b/tests/manual/qglyphruns/singleglyphrun.ui new file mode 100644 index 0000000000..e2c8860de0 --- /dev/null +++ b/tests/manual/qglyphruns/singleglyphrun.ui @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SingleGlyphRun</class> + <widget class="QWidget" name="SingleGlyphRun"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>599</width> + <height>300</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QTableWidget" name="twGlyphRun"> + <column> + <property name="text"> + <string>Glyph index</string> + </property> + </column> + <column> + <property name="text"> + <string>Glyph position</string> + </property> + </column> + <column> + <property name="text"> + <string>String index</string> + </property> + </column> + <column> + <property name="text"> + <string>Unicode</string> + </property> + </column> + <column> + <property name="text"> + <string>Character</string> + </property> + </column> + <column> + <property name="text"> + <string>Font glyph</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/qglyphruns/view.cpp b/tests/manual/qglyphruns/view.cpp new file mode 100644 index 0000000000..0e7d6dd478 --- /dev/null +++ b/tests/manual/qglyphruns/view.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "view.h" +#include <QTextLayout> +#include <QPainter> + +View::View(QWidget *parent) + : QWidget{parent} +{ + setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum)); +} + +View::~View() +{ + delete m_layout; +} + +void View::updateLayout(const QString &sourceString, + float width, + QTextOption::WrapMode mode, + const QFont &font) +{ + if (m_layout == nullptr) + m_layout = new QTextLayout; + + m_layout->setText(sourceString); + QTextOption option; + option.setWrapMode(mode); + m_layout->setTextOption(option); + m_layout->setFont(font); + m_layout->beginLayout(); + float y = 0.0f; + forever { + QTextLine line = m_layout->createLine(); + if (!line.isValid()) + break; + + line.setLineWidth(width); + line.setPosition(QPointF(0, y)); + y += line.height(); + } + m_layout->endLayout(); + + update(); + updateGeometry(); +} + +QSize View::sizeHint() const +{ + if (m_layout != nullptr) + return m_layout->boundingRect().size().toSize(); + else + return QSize(100, 100); +} + +void View::paintEvent(QPaintEvent *) +{ + QPainter p(this); + if (m_layout != nullptr) + m_layout->draw(&p, QPointF(0, 0)); + if (!m_bounds.isEmpty()) { + p.setPen(Qt::NoPen); + p.setBrush(Qt::yellow); + p.setOpacity(0.25); + for (const QRect &r : m_bounds) { + p.drawRect(r); + } + } +} diff --git a/tests/manual/qglyphruns/view.h b/tests/manual/qglyphruns/view.h new file mode 100644 index 0000000000..a8c3c1aed9 --- /dev/null +++ b/tests/manual/qglyphruns/view.h @@ -0,0 +1,42 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef VIEW_H +#define VIEW_H + +#include <QWidget> +#include <QTextOption> + +class QTextLayout; +class View : public QWidget +{ + Q_OBJECT +public: + explicit View(QWidget *parent = nullptr); + ~View() override; + + void updateLayout(const QString &sourceString, + float width, + QTextOption::WrapMode mode, + const QFont &font); + + QSize sizeHint() const override; + + QTextLayout *layout() const { return m_layout; } + +public slots: + void setVisualizedBounds(const QRegion ®ion) + { + m_bounds = region; + update(); + } + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + QTextLayout *m_layout = nullptr; + QRegion m_bounds; +}; + +#endif // VIEW_H |