From f4cf464ddb54ef0ebdb5eefa5a7cc8aa73ee64a4 Mon Sep 17 00:00:00 2001 From: fourtf Date: Sun, 21 Oct 2018 13:03:26 +0200 Subject: [PATCH] fixed issues with surrogate pairs in text selection and rendering --- src/messages/MessageElement.cpp | 30 ++++++++++++------- src/messages/layouts/MessageLayoutElement.cpp | 13 ++++++-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/messages/MessageElement.cpp b/src/messages/MessageElement.cpp index 1fd224e64..4412f9de4 100644 --- a/src/messages/MessageElement.cpp +++ b/src/messages/MessageElement.cpp @@ -159,7 +159,7 @@ void TextElement::addToContainer(MessageLayoutContainer &container, for (Word &word : this->words_) { auto getTextLayoutElement = [&](QString text, int width, bool trailingSpace) { - QColor color = this->color_.getColor(*app->themes); + auto color = this->color_.getColor(*app->themes); app->themes->normalizeColor(color); auto e = (new TextLayoutElement( @@ -205,26 +205,34 @@ void TextElement::addToContainer(MessageLayoutContainer &container, QString text = word.text; int textLength = text.length(); int wordStart = 0; - int width = metrics.width(text[0]); + int width = 0; - for (int i = 1; i < textLength; i++) { - int charWidth = metrics.width(text[i]); + // QChar::isHighSurrogate(text[0].unicode()) ? 2 : 1 - if (!container.fitsInLine(width + charWidth)) { + for (int i = 0; i < textLength; i++) // + { + auto isSurrogate = text.size() > i + 1 && + QChar::isHighSurrogate(text[i].unicode()); + + auto charWidth = isSurrogate ? metrics.width(text.mid(i, 2)) + : metrics.width(text[i]); + + if (!container.fitsInLine(width + charWidth)) // + { container.addElementNoLineBreak(getTextLayoutElement( text.mid(wordStart, i - wordStart), width, false)); container.breakLine(); wordStart = i; - width = 0; - if (textLength > i + 2) { - width += metrics.width(text[i]); - width += metrics.width(text[i + 1]); - i += 1; - } + width = charWidth; + + if (isSurrogate) i++; continue; } + width += charWidth; + + if (isSurrogate) i++; } container.addElement(getTextLayoutElement( diff --git a/src/messages/layouts/MessageLayoutElement.cpp b/src/messages/layouts/MessageLayoutElement.cpp index 3b9bfc4e4..b9324aee0 100644 --- a/src/messages/layouts/MessageLayoutElement.cpp +++ b/src/messages/layouts/MessageLayoutElement.cpp @@ -214,13 +214,20 @@ int TextLayoutElement::getMouseOverIndex(const QPoint &abs) const int x = this->getRect().left(); for (int i = 0; i < this->getText().size(); i++) { - int w = metrics.width(this->getText()[i]); + auto &text = this->getText(); + auto width = metrics.width(this->getText()[i]); + + if (x + width > abs.x()) { + if (text.size() > i + 1 && + QChar::isLowSurrogate(text[i].unicode())) // + { + i++; + } - if (x + w > abs.x()) { return i; } - x += w; + x += width; } return this->getSelectionIndexCount();