From 4a5abfcea4ec2e494efd117d278a929f020816c0 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 7 Dec 2022 15:31:05 +0100 Subject: [PATCH] wiggly example: add support for emojis etc. (utf16 surrogate pairs) The venerable wiggly example was created before unicode support was added to Qt. Hence, when extracting the individual characters from the string for painting, the code was not prepared to handle that some characters, like emojis, are composed of two QChar elements. Fixes: QTBUG-28853 Change-Id: I9804415f92775e2b78fa9fcaf7a2d112153cdce0 Reviewed-by: Eskil Abrahamsen Blomfeldt --- examples/widgets/doc/src/wiggly.qdoc | 13 ++++++++----- examples/widgets/widgets/wiggly/dialog.cpp | 2 +- examples/widgets/widgets/wiggly/wigglywidget.cpp | 11 ++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/examples/widgets/doc/src/wiggly.qdoc b/examples/widgets/doc/src/wiggly.qdoc index 2c7ea5db9e0..30a2a34f1b3 100644 --- a/examples/widgets/doc/src/wiggly.qdoc +++ b/examples/widgets/doc/src/wiggly.qdoc @@ -52,7 +52,7 @@ {QLineEdit::textChanged()}{textChanged()} signal to the wiggly widget's \c setText() slot to obtain the real time interaction with the wiggly widget. The widget's default text is "Hello - world!". + world!", with an emoji thrown in for fun. \section1 WigglyWidget Class Definition @@ -115,13 +115,16 @@ Each time the \c paintEvent() function is called, we create a QPainter object \c painter to draw the contents of the widget. - For each character in \c text, we determine the color and the - position on the wiggly line based on \c step. In addition, \c x - is incremented by the character's width. + Since we are going to paint the character symbols individually, we + extract the unique unicode code point for each character from \c + text, and convert it to a string \c symbol. For each \c symbol, we + determine the color and the position on the wiggly line based on + \c step and its \c offset from the start of the text. In addition, + \c x is incremented by the symbol's width. For simplicity, we assume that QFontMetrics::horizontalAdvance(\c text) returns the sum of the individual character advances - (QFontMetrics::horizontalAdvance(\c text[i])). In practice, this is not + (QFontMetrics::horizontalAdvance(\c symbol)). In practice, this is not always the case because QFontMetrics::horizontalAdvance(\c text) also takes into account the kerning between certain letters (e.g., 'A' and 'V'). The result is that the text isn't perfectly centered. You diff --git a/examples/widgets/widgets/wiggly/dialog.cpp b/examples/widgets/widgets/wiggly/dialog.cpp index 08a240af56e..0f3aa84fd86 100644 --- a/examples/widgets/widgets/wiggly/dialog.cpp +++ b/examples/widgets/widgets/wiggly/dialog.cpp @@ -19,7 +19,7 @@ Dialog::Dialog(QWidget *parent) layout->addWidget(lineEdit); connect(lineEdit, &QLineEdit::textChanged, wigglyWidget, &WigglyWidget::setText); - lineEdit->setText(tr("Hello world!")); + lineEdit->setText(u8"🖖 " + tr("Hello world!")); setWindowTitle(tr("Wiggly")); resize(360, 145); diff --git a/examples/widgets/widgets/wiggly/wigglywidget.cpp b/examples/widgets/widgets/wiggly/wigglywidget.cpp index d7890ef2b7c..3e686a67cf2 100644 --- a/examples/widgets/widgets/wiggly/wigglywidget.cpp +++ b/examples/widgets/widgets/wiggly/wigglywidget.cpp @@ -39,13 +39,14 @@ void WigglyWidget::paintEvent(QPaintEvent * /* event */) //! [3] QPainter painter(this); //! [3] //! [4] - for (int i = 0; i < text.size(); ++i) { - int index = (step + i) % 16; + int offset = 0; + for (char32_t codePoint : text.toUcs4()) { + int index = (step + offset++) % 16; color.setHsv((15 - index) * 16, 255, 191); painter.setPen(color); - painter.drawText(x, y - ((sineTable[index] * metrics.height()) / 400), - QString(text[i])); - x += metrics.horizontalAdvance(text[i]); + QString symbol = QString::fromUcs4(&codePoint, 1); + painter.drawText(x, y - ((sineTable[index] * metrics.height()) / 400), symbol); + x += metrics.horizontalAdvance(symbol); } } //! [4]