From e60052d4409fa339d98b554a6f83baa4477f0a11 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 4 Nov 2015 18:46:01 -0500 Subject: [PATCH] fixed tilde replacements in input fields and Text --- Telegram/SourceFiles/gui/flatinput.cpp | 210 +++++++++++----------- Telegram/SourceFiles/gui/flattextarea.cpp | 92 +++++----- Telegram/SourceFiles/gui/text.cpp | 12 +- 3 files changed, 163 insertions(+), 151 deletions(-) diff --git a/Telegram/SourceFiles/gui/flatinput.cpp b/Telegram/SourceFiles/gui/flatinput.cpp index 8d5e5731c4..f92a96d0a6 100644 --- a/Telegram/SourceFiles/gui/flatinput.cpp +++ b/Telegram/SourceFiles/gui/flatinput.cpp @@ -917,11 +917,12 @@ QVariant InputArea::InputAreaInner::loadResource(int type, const QUrl &name) { } void InputArea::processDocumentContentsChange(int position, int charsAdded) { - int32 emojiPosition = -1, emojiLen = 0; + int32 replacePosition = -1, replaceLen = 0; const EmojiData *emoji = 0; static QString regular = qsl("Open Sans"), semibold = qsl("Open Sans Semibold"); - bool checkTilde = !cRetina() && (font().pixelSize() == 13) && (font().family() == regular), prevTilde = false; + bool checkTilde = !cRetina() && (_inner.font().pixelSize() == 13) && (_inner.font().family() == regular); + bool wasTildeFragment = false; QTextDocument *doc(_inner.document()); QTextCursor c(_inner.textCursor()); @@ -941,65 +942,66 @@ void InputArea::processDocumentContentsChange(int position, int charsAdded) { continue; } + if (checkTilde) { + wasTildeFragment = (fragment.charFormat().fontFamily() == semibold); + } + QString t(fragment.text()); const QChar *ch = t.constData(), *e = ch + t.size(); for (; ch != e; ++ch, ++fp) { - if (checkTilde && fp >= position) { // tilde fix in OpenSans - bool tilde = (ch->unicode() == '~'); - QString fontfamily; - if (tilde) { - if (fragment.charFormat().fontFamily() != semibold) { - fontfamily = semibold; - } - } else if (prevTilde) { - if (fragment.charFormat().fontFamily() == semibold) { - fontfamily = regular; - } - } - if (!fontfamily.isEmpty()) { - if (!_inner.document()->pageSize().isNull()) { - _inner.document()->setPageSize(QSizeF(0, 0)); - } - emojiPosition = fp; - emojiLen = 1; - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - QTextCharFormat format; - format.setFontFamily(fontfamily); - c.mergeCharFormat(format); - break; - } - prevTilde = tilde; - } - + int32 emojiLen = 0; emoji = emojiFromText(ch, e, emojiLen); if (emoji) { - emojiPosition = fp; + if (replacePosition >= 0) { + emoji = 0; // replace tilde char format first + } else { + replacePosition = fp; + replaceLen = emojiLen; + } break; } + + if (checkTilde && fp >= position) { // tilde fix in OpenSans + bool tilde = (ch->unicode() == '~'); + if ((tilde && !wasTildeFragment) || (!tilde && wasTildeFragment)) { + if (replacePosition < 0) { + replacePosition = fp; + replaceLen = 1; + } else { + ++replaceLen; + } + } else if (replacePosition >= 0) { + break; + } + } + if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) { ++ch; ++fp; } } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; } - if (emojiPosition >= 0) { - if (emoji) { - if (!_inner.document()->pageSize().isNull()) { - _inner.document()->setPageSize(QSizeF(0, 0)); - } - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - insertEmoji(emoji, c); + if (replacePosition >= 0) { + if (!_inner.document()->pageSize().isNull()) { + _inner.document()->setPageSize(QSizeF(0, 0)); } - charsAdded -= emojiPosition + emojiLen - position; - position = emojiPosition + 1; + QTextCursor c(doc->docHandle(), replacePosition); + c.setPosition(replacePosition + replaceLen, QTextCursor::KeepAnchor); + if (emoji) { + insertEmoji(emoji, c); + } else { + QTextCharFormat format; + format.setFontFamily(wasTildeFragment ? regular : semibold); + c.mergeCharFormat(format); + } + charsAdded -= replacePosition + replaceLen - position; + position = replacePosition + (emoji ? 1 : replaceLen); emoji = 0; - emojiPosition = -1; + replacePosition = -1; } else { break; } @@ -1611,11 +1613,13 @@ QVariant InputField::InputFieldInner::loadResource(int type, const QUrl &name) { } void InputField::processDocumentContentsChange(int position, int charsAdded) { - int32 emojiPosition = -1, emojiLen = 0; + int32 replacePosition = -1, replaceLen = 0; const EmojiData *emoji = 0; + bool newlineFound = false; static QString regular = qsl("Open Sans"), semibold = qsl("Open Sans Semibold"), space(' '); - bool checkTilde = !cRetina() && (font().pixelSize() == 13) && (font().family() == regular), prevTilde = false; + bool checkTilde = !cRetina() && (_inner.font().pixelSize() == 13) && (_inner.font().family() == regular); + bool wasTildeFragment = false; QTextDocument *doc(_inner.document()); QTextCursor c(_inner.textCursor()); @@ -1635,87 +1639,91 @@ void InputField::processDocumentContentsChange(int position, int charsAdded) { continue; } + if (checkTilde) { + wasTildeFragment = (fragment.charFormat().fontFamily() == semibold); + } + QString t(fragment.text()); const QChar *ch = t.constData(), *e = ch + t.size(); for (; ch != e; ++ch, ++fp) { - if (checkTilde && fp >= position) { // tilde fix in OpenSans - bool tilde = (ch->unicode() == '~'); - QString fontfamily; - if (tilde) { - if (fragment.charFormat().fontFamily() != semibold) { - fontfamily = semibold; - } - } else if (prevTilde) { - if (fragment.charFormat().fontFamily() == semibold) { - fontfamily = regular; - } - } - if (!fontfamily.isEmpty()) { - if (!_inner.document()->pageSize().isNull()) { - _inner.document()->setPageSize(QSizeF(0, 0)); - } - emojiPosition = fp; - emojiLen = 1; - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - QTextCharFormat format; - format.setFontFamily(fontfamily); - c.mergeCharFormat(format); - break; - } - prevTilde = tilde; - } - // QTextBeginningOfFrame // QTextEndOfFrame - if (ch->unicode() == 0xfdd0 || ch->unicode() == 0xfdd1 || ch->unicode() == QChar::ParagraphSeparator || ch->unicode() == QChar::LineSeparator || ch->unicode() == '\n' || ch->unicode() == '\r') { - if (!_inner.document()->pageSize().isNull()) { - _inner.document()->setPageSize(QSizeF(0, 0)); + newlineFound = (ch->unicode() == 0xfdd0 || ch->unicode() == 0xfdd1 || ch->unicode() == QChar::ParagraphSeparator || ch->unicode() == QChar::LineSeparator || ch->unicode() == '\n' || ch->unicode() == '\r'); + if (newlineFound) { + if (replacePosition >= 0) { + newlineFound = false; // replace tilde char format first + } else { + replacePosition = fp; + replaceLen = 1; } - emojiPosition = fp; - emojiLen = 1; - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - c.insertText(space); break; } + int32 emojiLen = 0; emoji = emojiFromText(ch, e, emojiLen); if (emoji) { - emojiPosition = fp; + if (replacePosition >= 0) { + emoji = 0; // replace tilde char format first + } else { + replacePosition = fp; + replaceLen = emojiLen; + } break; } + + if (checkTilde && fp >= position) { // tilde fix in OpenSans + bool tilde = (ch->unicode() == '~'); + if ((tilde && !wasTildeFragment) || (!tilde && wasTildeFragment)) { + if (replacePosition < 0) { + replacePosition = fp; + replaceLen = 1; + } else { + ++replaceLen; + } + } else if (replacePosition >= 0) { + break; + } + } + if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) { ++ch; ++fp; } } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; if (b.next() != doc->end()) { - emojiPosition = b.next().position() - 1; - emojiLen = 1; - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - c.insertText(space); + newlineFound = true; + replacePosition = b.next().position() - 1; + replaceLen = 1; break; } } - if (emojiPosition >= 0) { - if (emoji) { - if (!_inner.document()->pageSize().isNull()) { - _inner.document()->setPageSize(QSizeF(0, 0)); - } - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - insertEmoji(emoji, c); + if (replacePosition >= 0) { + if (!_inner.document()->pageSize().isNull()) { + _inner.document()->setPageSize(QSizeF(0, 0)); } - charsAdded -= emojiPosition + emojiLen - position; - position = emojiPosition + 1; + QTextCursor c(doc->docHandle(), replacePosition); + c.setPosition(replacePosition + replaceLen, QTextCursor::KeepAnchor); + if (newlineFound) { + QTextCharFormat format; + format.setFontFamily(regular); + c.mergeCharFormat(format); + c.insertText(space); + } else if (emoji) { + insertEmoji(emoji, c); + } else { + QTextCharFormat format; + format.setFontFamily(wasTildeFragment ? regular : semibold); + c.mergeCharFormat(format); + } + charsAdded -= replacePosition + replaceLen - position; + position = replacePosition + ((emoji || newlineFound) ? 1 : replaceLen); + newlineFound = false; emoji = 0; - emojiPosition = -1; + replacePosition = -1; } else { break; } diff --git a/Telegram/SourceFiles/gui/flattextarea.cpp b/Telegram/SourceFiles/gui/flattextarea.cpp index 8cb8103b6d..8d917d475e 100644 --- a/Telegram/SourceFiles/gui/flattextarea.cpp +++ b/Telegram/SourceFiles/gui/flattextarea.cpp @@ -619,11 +619,11 @@ void FlatTextarea::checkContentHeight() { } void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) { - int32 emojiPosition = -1, emojiLen = 0; + int32 replacePosition = -1, replaceLen = 0; const EmojiData *emoji = 0; static QString regular = qsl("Open Sans"), semibold = qsl("Open Sans Semibold"); - bool checkTilde = !cRetina() && (font().pixelSize() == 13) && (font().family() == regular), prevTilde = false; + bool checkTilde = !cRetina() && (font().pixelSize() == 13) && (font().family() == regular), wasTildeFragment = false; QTextDocument *doc(document()); while (true) { @@ -640,66 +640,68 @@ void FlatTextarea::processDocumentContentsChange(int position, int charsAdded) { if (fp >= end || fe <= start) { continue; } + + if (checkTilde) { + wasTildeFragment = (fragment.charFormat().fontFamily() == semibold); + } + QString t(fragment.text()); const QChar *ch = t.constData(), *e = ch + t.size(); for (; ch != e; ++ch, ++fp) { - if (checkTilde && fp >= position) { // tilde fix in OpenSans - bool tilde = (ch->unicode() == '~'); - QString fontfamily; - if (tilde) { - if (fragment.charFormat().fontFamily() != semibold) { - fontfamily = semibold; - } - } else if (prevTilde) { - if (fragment.charFormat().fontFamily() == semibold) { - fontfamily = regular; - } - } - if (!fontfamily.isEmpty()) { - if (!document()->pageSize().isNull()) { - document()->setPageSize(QSizeF(0, 0)); - } - emojiPosition = fp; - emojiLen = 1; - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - QTextCharFormat format; - format.setFontFamily(fontfamily); - c.mergeCharFormat(format); - break; - } - prevTilde = tilde; - } - + int32 emojiLen = 0; emoji = emojiFromText(ch, e, emojiLen); if (emoji) { - emojiPosition = fp; + if (replacePosition >= 0) { + emoji = 0; // replace tilde char format first + } else { + replacePosition = fp; + replaceLen = emojiLen; + } break; } + + if (checkTilde && fp >= position) { // tilde fix in OpenSans + bool tilde = (ch->unicode() == '~'); + if ((tilde && !wasTildeFragment) || (!tilde && wasTildeFragment)) { + if (replacePosition < 0) { + replacePosition = fp; + replaceLen = 1; + } else { + ++replaceLen; + } + } else if (replacePosition >= 0) { + break; + } + } + if (ch + 1 < e && ch->isHighSurrogate() && (ch + 1)->isLowSurrogate()) { ++ch; ++fp; } } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; } - if (emojiPosition >= 0) break; + if (replacePosition >= 0) break; } - if (emojiPosition >= 0) { - if (emoji) { - if (!document()->pageSize().isNull()) { - document()->setPageSize(QSizeF(0, 0)); - } - QTextCursor c(doc->docHandle(), emojiPosition); - c.setPosition(emojiPosition + emojiLen, QTextCursor::KeepAnchor); - insertEmoji(emoji, c); + if (replacePosition >= 0) { + if (!document()->pageSize().isNull()) { + document()->setPageSize(QSizeF(0, 0)); } - charsAdded -= emojiPosition + emojiLen - position; - position = emojiPosition + 1; + QTextCursor c(doc->docHandle(), replacePosition); + c.setPosition(replacePosition + replaceLen, QTextCursor::KeepAnchor); + if (emoji) { + insertEmoji(emoji, c); + } else { + QTextCharFormat format; + format.setFontFamily(wasTildeFragment ? regular : semibold); + c.mergeCharFormat(format); + } + charsAdded -= replacePosition + replaceLen - position; + position = replacePosition + (emoji ? 1 : replaceLen); emoji = 0; - emojiPosition = -1; - } else { + replacePosition = -1; + } else { break; } } diff --git a/Telegram/SourceFiles/gui/text.cpp b/Telegram/SourceFiles/gui/text.cpp index a7fb10ad55..2a6be8b760 100644 --- a/Telegram/SourceFiles/gui/text.cpp +++ b/Telegram/SourceFiles/gui/text.cpp @@ -544,7 +544,7 @@ public: int skipBack = 0; ch = ((ptr < end) ? *ptr : 0); chInt = ch.unicode(); - bool skip = false, isNewLine = multiline && chIsNewline(ch), isSpace = chIsSpace(ch), isDiac = chIsDiac(ch), isTilde = (ch == '~'); + bool skip = false, isNewLine = multiline && chIsNewline(ch), isSpace = chIsSpace(ch), isDiac = chIsDiac(ch), isTilde = checkTilde && (ch == '~'); if (chIsBad(ch) || ch.isLowSurrogate()) { skip = true; } else if (isDiac) { @@ -577,12 +577,12 @@ public: } else { if (isTilde) { // tilde fix in OpenSans if (!(flags & TextBlockFTilde)) { - createBlock(); + createBlock(skipBack); flags |= TextBlockFTilde; } } else { if (flags & TextBlockFTilde) { - createBlock(); + createBlock(skipBack); flags &= ~TextBlockFTilde; } } @@ -688,6 +688,7 @@ public: ch = chInt = 0; lastSkipped = false; + checkTilde = !cRetina() && _t->_font->size() == 13 && _t->_font->flags() == 0; // tilde Open Sans fix entitiesEnd = entities.cend(); waitingEntity = entities.cbegin(); while (waitingEntity != entitiesEnd && waitingEntity->length <= 0) ++waitingEntity; @@ -784,6 +785,7 @@ private: QChar ch; // current char (low surrogate, if current char is surrogate pair) uint32 chInt; // full ch, could be surrogate pair bool lastSkipped; // did we skip current char + bool checkTilde; // do we need a special text block for tilde symbol }; namespace { @@ -1785,7 +1787,7 @@ public: } if (flags & TextBlockFItalic) result = result->italic(); if (flags & TextBlockFUnderline) result = result->underline(); - if ((flags & TextBlockFTilde) && !cRetina() && f->size() == 13 && f->flags() == 0) { // tilde fix in OpenSans + if (flags & TextBlockFTilde) { // tilde fix in OpenSans result = st::semiboldFont; } } @@ -3244,7 +3246,7 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi } if (flags & TextBlockFItalic) blockFont = blockFont->italic(); if (flags & TextBlockFUnderline) blockFont = blockFont->underline(); - if ((flags & TextBlockFTilde) && !cRetina() && font->size() == 13 && font->flags() == 0) { // tilde fix in OpenSans + if (flags & TextBlockFTilde) { // tilde fix in OpenSans blockFont = st::semiboldFont; } }