From 8e3274cd8f7876e70fa249a5bb6aeef1001f0ddc Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 9 Feb 2017 16:46:14 +0300 Subject: [PATCH] Colors added in palette for selected messages. User names in groups, text and links in messages and names in files and shared contacts not can have different colors in plain inbox / outbox messages and in selected messages. Now we can use a separate color for selected parts in Text. --- Telegram/Resources/basic.style | 25 ++++++ Telegram/Resources/colors.palette | 20 ++++- .../history/history_media_types.cpp | 12 +-- .../SourceFiles/history/history_message.cpp | 51 +++++++++--- Telegram/SourceFiles/structs.cpp | 24 +----- Telegram/SourceFiles/structs.h | 10 +-- Telegram/SourceFiles/ui/text/text.cpp | 83 +++++++++++++------ 7 files changed, 158 insertions(+), 67 deletions(-) diff --git a/Telegram/Resources/basic.style b/Telegram/Resources/basic.style index dfe5849ae..a36ee48df 100644 --- a/Telegram/Resources/basic.style +++ b/Telegram/Resources/basic.style @@ -24,6 +24,9 @@ TextPalette { linkFg: color; monoFg: color; selectBg: color; + selectFg: color; + selectLinkFg: color; + selectMonoFg: color; selectOverlay: color; } @@ -52,6 +55,9 @@ defaultTextPalette: TextPalette { linkFg: windowActiveTextFg; monoFg: windowSubTextFg; selectBg: msgInBgSelected; + selectFg: historyTextInFgSelected; + selectLinkFg: historyLinkInFgSelected; + selectMonoFg: msgInMonoFgSelected; selectOverlay: msgSelectOverlay; } defaultTextStyle: TextStyle { @@ -125,6 +131,9 @@ serviceTextPalette: TextPalette(defaultTextPalette) { linkFg: msgServiceFg; monoFg: msgServiceFg; selectBg: msgServiceBgSelected; + selectFg: msgServiceFg; + selectLinkFg: msgServiceFg; + selectMonoFg: msgServiceFg; selectOverlay: msgServiceBgSelected; } serviceTextStyle: TextStyle(defaultTextStyle) { @@ -133,15 +142,31 @@ serviceTextStyle: TextStyle(defaultTextStyle) { linkFontOver: font(fsize semibold underline); } inTextPalette: TextPalette(defaultTextPalette) { + linkFg: historyLinkInFg; monoFg: msgInMonoFg; selectBg: msgInBgSelected; + selectFg: historyTextInFgSelected; + selectLinkFg: historyLinkInFgSelected; + selectMonoFg: msgInMonoFgSelected; selectOverlay: msgSelectOverlay; } +inTextPaletteSelected: TextPalette(inTextPalette) { + linkFg: historyLinkInFgSelected; + monoFg: msgInMonoFgSelected; +} outTextPalette: TextPalette(defaultTextPalette) { + linkFg: historyLinkOutFg; monoFg: msgOutMonoFg; selectBg: msgOutBgSelected; + selectFg: historyTextOutFgSelected; + selectLinkFg: historyLinkOutFgSelected; + selectMonoFg: msgOutMonoFgSelected; selectOverlay: msgSelectOverlay; } +outTextPaletteSelected: TextPalette(outTextPalette) { + linkFg: historyLinkOutFgSelected; + monoFg: msgOutMonoFgSelected; +} fwdTextStyle: TextStyle(semiboldTextStyle) { linkFontOver: semiboldFont; } diff --git a/Telegram/Resources/colors.palette b/Telegram/Resources/colors.palette index a6988edd4..03141b33d 100644 --- a/Telegram/Resources/colors.palette +++ b/Telegram/Resources/colors.palette @@ -247,11 +247,17 @@ stickerPanDeleteFg: windowFgActive; // delete X button icon for custom sent stic stickerPreviewBg: #ffffffb0; // sticker and GIF preview background (when you press and hold on a sticker) historyTextInFg: windowFg; // inbox message text +historyTextInFgSelected: historyTextInFg; // inbox message selected text or text in a selected message historyTextOutFg: windowFg; // outbox message text -historyCaptionInFg: historyTextInFg; // inbox media caption text -historyCaptionOutFg: historyTextOutFg; // outbox media caption text +historyTextOutFgSelected: historyTextOutFg; // outbox message selected text or text in a selected message +historyLinkInFg: windowActiveTextFg; // inbox message link +historyLinkInFgSelected: historyLinkInFg; // inbox message link in a selected text or message +historyLinkOutFg: windowActiveTextFg; // outbox message link +historyLinkOutFgSelected: historyLinkOutFg; // outbox message link in a selected text or message historyFileNameInFg: historyTextInFg; // inbox media filename text +historyFileNameInFgSelected: historyFileNameInFg; // inbox media filename text in a selected message historyFileNameOutFg: historyTextOutFg; // outbox media filename text +historyFileNameOutFgSelected: historyFileNameOutFg; // outbox media filename text in a selected message historyOutIconFg: dialogsSentIconFg; // outbox message tick / double tick icon historyOutIconFgSelected: #4da79f; // outbox message tick / double tick icon in a selected message historyIconFgInverted: windowFgActive; // media message tick / double tick icon (like in sent photo) @@ -267,20 +273,28 @@ historyForwardChooseBg: #0000004c; // forwarding messages in a large window size historyForwardChooseFg: windowFgActive; // forwarding messages in a large window size "choose recipient" text historyPeer1NameFg: #c03d33; // red group member name +historyPeer1NameFgSelected: historyPeer1NameFg; // red group member name in a selected message historyPeer1UserpicBg: #e17076; // red userpic background historyPeer2NameFg: #4fad2d; // green group member name +historyPeer2NameFgSelected: historyPeer2NameFg; // green group member name in a selected message historyPeer2UserpicBg: #7bc862; // green userpic background historyPeer3NameFg: #d09306; // yellow group member name +historyPeer3NameFgSelected: historyPeer3NameFg; // yellow group member name in a selected message historyPeer3UserpicBg: #e5ca77; // yellow userpic background historyPeer4NameFg: windowActiveTextFg; // blue group member name +historyPeer4NameFgSelected: historyPeer4NameFg; // blue group member name in a selected message historyPeer4UserpicBg: #65aadd; // blue userpic background historyPeer5NameFg: #8544d6; // purple group member name +historyPeer5NameFgSelected: historyPeer5NameFg; // purple group member name in a selected message historyPeer5UserpicBg: #a695e7; // purple userpic background historyPeer6NameFg: #cd4073; // pink group member name +historyPeer6NameFgSelected: historyPeer6NameFg; // pink group member name in a selected message historyPeer6UserpicBg: #ee7aae; // pink userpic background historyPeer7NameFg: #2996ad; // sea group member name +historyPeer7NameFgSelected: historyPeer7NameFg; // sea group member name in a selected message historyPeer7UserpicBg: #6ec9cb; // sea userpic background historyPeer8NameFg: #ce671b; // orange group member name +historyPeer8NameFgSelected: historyPeer8NameFg; // orange group member name in a selected message historyPeer8UserpicBg: #faa774; // orange userpic background historyPeerUserpicFg: windowFgActive; // default userpic initials @@ -321,6 +335,8 @@ msgOutReplyBarSelColor: historyOutIconFgSelected; // outbox selected message rep msgImgReplyBarColor: msgServiceFg; // sticker message reply outline msgInMonoFg: #4e7391; // inbox message monospace text (like a message sent with `test` text) msgOutMonoFg: #469165; // outbox message monospace text +msgInMonoFgSelected: msgInMonoFg; // inbox message monospace text in a selected text or message +msgOutMonoFgSelected: msgOutMonoFg; // outbox message monospace text in a selected text or message msgDateImgFg: msgServiceFg; // media message time text (like time text in a sent photo) msgDateImgBg: #00000054; // media message time bubble background (like time bubble in a sent photo) or file with thumbnail download icon circle background msgDateImgBgOver: #00000074; // media message download icon circle background with mouse over (like file with thumbnail download icon) diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index dba7184d8..3c5056fea 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -450,7 +450,7 @@ void HistoryPhoto::draw(Painter &p, const QRect &r, TextSelection selection, Tim _parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage); } } else { - p.setPen(outbg ? st::historyCaptionOutFg : st::historyCaptionInFg); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection); } } @@ -791,7 +791,7 @@ void HistoryVideo::draw(Painter &p, const QRect &r, TextSelection selection, Tim _parent->drawInfo(p, fullRight, fullBottom, 2 * skipx + width, selected, InfoDisplayOverImage); } } else { - p.setPen(outbg ? st::historyCaptionOutFg : st::historyCaptionInFg); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection); } } @@ -1273,7 +1273,7 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, } } else if (auto named = Get()) { p.setFont(st::semiboldFont); - p.setPen(outbg ? st::historyFileNameOutFg : st::historyFileNameInFg); + p.setPen(outbg ? (selected ? st::historyFileNameOutFgSelected : st::historyFileNameOutFg) : (selected ? st::historyFileNameInFgSelected : st::historyFileNameInFg)); if (namewidth < named->_namew) { p.drawTextLeft(nameleft, nametop, _width, st::semiboldFont->elided(named->_name, namewidth, Qt::ElideMiddle)); } else { @@ -1300,7 +1300,7 @@ void HistoryDocument::draw(Painter &p, const QRect &r, TextSelection selection, } if (auto captioned = Get()) { - p.setPen(outbg ? st::historyCaptionOutFg : st::historyCaptionInFg); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); captioned->_caption.draw(p, st::msgPadding.left(), bottom, captionw, style::al_left, 0, -1, selection); } } @@ -1802,7 +1802,7 @@ void HistoryGif::draw(Painter &p, const QRect &r, TextSelection selection, TimeM } if (!_caption.isEmpty()) { - p.setPen(outbg ? st::historyCaptionOutFg : st::historyCaptionInFg); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); _caption.draw(p, st::msgPadding.left(), skipy + height + st::mediaPadding.bottom() + st::mediaCaptionSkip, captionw, style::al_left, 0, -1, selection); } else if (_parent->getMedia() == this && (_data->uploading() || App::hoveredItem() == _parent)) { int32 fullRight = skipx + width, fullBottom = skipy + height; @@ -2337,7 +2337,7 @@ void HistoryContact::draw(Painter &p, const QRect &r, TextSelection selection, T int32 namewidth = width - nameleft - nameright; p.setFont(st::semiboldFont); - p.setPen(outbg ? st::historyFileNameOutFg : st::historyFileNameInFg); + p.setPen(outbg ? (selected ? st::historyFileNameOutFgSelected : st::historyFileNameOutFg) : (selected ? st::historyFileNameInFgSelected : st::historyFileNameInFg)); _name.drawLeftElided(p, nameleft, nametop, namewidth, width); auto &status = outbg ? (selected ? st::mediaOutFgSelected : st::mediaOutFg) : (selected ? st::mediaInFgSelected : st::mediaInFg); diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 3ad0ce77d..1bb585c96 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -77,6 +77,36 @@ ApiWrap::RequestMessageDataCallback historyDependentItemCallback(const FullMsgId constexpr auto kPinnedMessageTextLimit = 16; +style::color fromNameFg(int index) { + t_assert(index >= 0 && index < 8); + style::color colors[] = { + st::historyPeer1NameFg, + st::historyPeer2NameFg, + st::historyPeer3NameFg, + st::historyPeer4NameFg, + st::historyPeer5NameFg, + st::historyPeer6NameFg, + st::historyPeer7NameFg, + st::historyPeer8NameFg, + }; + return colors[index]; +} + +style::color fromNameFgSelected(int index) { + t_assert(index >= 0 && index < 8); + style::color colors[] = { + st::historyPeer1NameFgSelected, + st::historyPeer2NameFgSelected, + st::historyPeer3NameFgSelected, + st::historyPeer4NameFgSelected, + st::historyPeer5NameFgSelected, + st::historyPeer6NameFgSelected, + st::historyPeer7NameFgSelected, + st::historyPeer8NameFgSelected, + }; + return colors[index]; +} + } // namespace void historyInitMessages() { @@ -283,10 +313,9 @@ void HistoryMessageReply::paint(Painter &p, const HistoryItem *holder, int x, in auto replyToAsMsg = replyToMsg->toHistoryMessage(); if (!(flags & PaintInBubble)) { } else if ((replyToAsMsg && replyToAsMsg->emptyText()) || replyToMsg->serviceMsg()) { - auto &date = outbg ? (selected ? st::msgOutDateFgSelected : st::msgOutDateFg) : (selected ? st::msgInDateFgSelected : st::msgInDateFg); - p.setPen(date); + p.setPen(outbg ? (selected ? st::msgOutDateFgSelected : st::msgOutDateFg) : (selected ? st::msgInDateFgSelected : st::msgInDateFg)); } else { - p.setPen(outbg ? st::historyTextOutFg : st::historyTextInFg); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); } replyToText.drawLeftElided(p, x + st::msgReplyBarSkip + previewSkip, y + st::msgReplyPadding.top() + st::msgServiceNameFont->height, w - st::msgReplyBarSkip - previewSkip, w + 2 * x); } @@ -1270,7 +1299,7 @@ void HistoryMessage::draw(Painter &p, const QRect &r, TextSelection selection, T } } - p.setTextPalette(outbg ? st::outTextPalette : st::inTextPalette); + p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette)); auto keyboard = inlineReplyKeyboard(); if (keyboard) { @@ -1353,7 +1382,7 @@ void HistoryMessage::paintFromName(Painter &p, QRect &trect, bool selected) cons if (isPost()) { p.setPen(selected ? st::msgInServiceFgSelected : st::msgInServiceFg); } else { - p.setPen(author()->color); + p.setPen(selected ? fromNameFgSelected(author()->colorIndex()) : fromNameFg(author()->colorIndex())); } author()->nameText.drawElided(p, trect.left(), trect.top(), trect.width()); @@ -1372,14 +1401,15 @@ void HistoryMessage::paintForwardedInfo(Painter &p, QRect &trect, bool selected) if (displayForwardedFrom()) { style::font serviceFont(st::msgServiceFont), serviceName(st::msgServiceNameFont); - p.setPen(selected ? (hasOutLayout() ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (hasOutLayout() ? st::msgOutServiceFg : st::msgInServiceFg)); + auto outbg = hasOutLayout(); + p.setPen(selected ? (outbg ? st::msgOutServiceFgSelected : st::msgInServiceFgSelected) : (outbg ? st::msgOutServiceFg : st::msgInServiceFg)); p.setFont(serviceFont); auto fwd = Get(); bool breakEverywhere = (fwd->_text.countHeight(trect.width()) > 2 * serviceFont->height); - p.setTextPalette(selected ? (hasOutLayout() ? st::outFwdTextPaletteSelected : st::inFwdTextPaletteSelected) : (hasOutLayout() ? st::outFwdTextPalette : st::inFwdTextPalette)); + p.setTextPalette(selected ? (outbg ? st::outFwdTextPaletteSelected : st::inFwdTextPaletteSelected) : (outbg ? st::outFwdTextPalette : st::inFwdTextPalette)); fwd->_text.drawElided(p, trect.x(), trect.y(), trect.width(), 2, style::al_left, 0, -1, 0, breakEverywhere); - p.setTextPalette(hasOutLayout() ? st::outTextPalette : st::inTextPalette); + p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette)); trect.setY(trect.y() + (((fwd->_text.maxWidth() > trect.width()) ? 2 : 1) * serviceFont->height)); } @@ -1411,8 +1441,9 @@ void HistoryMessage::paintViaBotIdInfo(Painter &p, QRect &trect, bool selected) } void HistoryMessage::paintText(Painter &p, QRect &trect, TextSelection selection) const { - bool outbg = out() && !isPost(); - p.setPen(outbg ? st::historyTextOutFg : st::historyTextInFg); + auto outbg = out() && !isPost(); + auto selected = (selection == FullSelection); + p.setPen(outbg ? (selected ? st::historyTextOutFgSelected : st::historyTextOutFg) : (selected ? st::historyTextInFgSelected : st::historyTextInFg)); p.setFont(st::msgFont); _text.draw(p, trect.x(), trect.y(), trect.width(), style::al_left, 0, -1, selection); } diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp index d22275395..86046ea7a 100644 --- a/Telegram/SourceFiles/structs.cpp +++ b/Telegram/SourceFiles/structs.cpp @@ -60,20 +60,6 @@ ImagePtr generateUserpicImage(const style::icon &icon) { } // namespace -style::color peerColor(int index) { - static style::color peerColors[kUserColorsCount] = { - st::historyPeer1NameFg, - st::historyPeer2NameFg, - st::historyPeer3NameFg, - st::historyPeer4NameFg, - st::historyPeer5NameFg, - st::historyPeer6NameFg, - st::historyPeer7NameFg, - st::historyPeer8NameFg, - }; - return peerColors[index]; -} - style::color peerUserpicColor(int index) { static style::color peerColors[kUserColorsCount] = { st::historyPeer1UserpicBg, @@ -248,11 +234,9 @@ using UpdateFlag = Notify::PeerUpdate::Flag; NotifySettings globalNotifyAll, globalNotifyUsers, globalNotifyChats; NotifySettingsPtr globalNotifyAllPtr = UnknownNotifySettings, globalNotifyUsersPtr = UnknownNotifySettings, globalNotifyChatsPtr = UnknownNotifySettings; -PeerData::PeerData(const PeerId &id) : id(id) -, colorIndex(peerColorIndex(id)) -, color(peerColor(colorIndex)) { +PeerData::PeerData(const PeerId &id) : id(id), _colorIndex(peerColorIndex(id)) { nameText.setText(st::msgNameStyle, QString(), _textNameOptions); - _userpicEmpty.set(colorIndex, QString()); + _userpicEmpty.set(_colorIndex, QString()); } void PeerData::updateNameDelayed(const QString &newName, const QString &newNameOrPhone, const QString &newUsername) { @@ -274,7 +258,7 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO name = newName; nameText.setText(st::msgNameStyle, name, _textNameOptions); if (!_userpic) { - _userpicEmpty.set(colorIndex, name); + _userpicEmpty.set(_colorIndex, name); } Notify::PeerUpdate update(this); @@ -309,7 +293,7 @@ void PeerData::updateNameDelayed(const QString &newName, const QString &newNameO void PeerData::setUserpic(ImagePtr userpic) { _userpic = userpic; if (!_userpic || !_userpic->loaded()) { - _userpicEmpty.set(colorIndex, name); + _userpicEmpty.set(_colorIndex, name); } else { _userpicEmpty.clear(); } diff --git a/Telegram/SourceFiles/structs.h b/Telegram/SourceFiles/structs.h index d918320f5..e4751f13d 100644 --- a/Telegram/SourceFiles/structs.h +++ b/Telegram/SourceFiles/structs.h @@ -203,8 +203,6 @@ static constexpr int kUserColorsCount = 8; static constexpr int kChatColorsCount = 4; static constexpr int kChannelColorsCount = 4; -style::color peerColor(int index); - class EmptyUserpic { public: EmptyUserpic(); @@ -311,9 +309,9 @@ public: LoadedStatus loadedStatus = NotLoaded; MTPinputPeer input; - int colorIndex; - style::color color; - + int colorIndex() const { + return _colorIndex; + } void setUserpic(ImagePtr userpic); void paintUserpic(Painter &p, int x, int y, int size) const; void paintUserpicLeft(Painter &p, int x, int y, int w, int size) const { @@ -364,6 +362,8 @@ private: ClickHandlerPtr _openLink; + int _colorIndex = 0; + }; class BotCommand { diff --git a/Telegram/SourceFiles/ui/text/text.cpp b/Telegram/SourceFiles/ui/text/text.cpp index e8c5d3529..4c441a03e 100644 --- a/Telegram/SourceFiles/ui/text/text.cpp +++ b/Telegram/SourceFiles/ui/text/text.cpp @@ -1122,16 +1122,6 @@ public: return _lookupResult; } - const QPen &blockPen(ITextBlock *block) { - if (block->lnkIndex()) { - return _p->textPalette().linkFg->p; - } - if ((block->flags() & TextBlockFCode) || (block->flags() & TextBlockFPre)) { - return _p->textPalette().monoFg->p; - } - return _originalPen; - } - bool drawLine(uint16 _lineEnd, const Text::TextBlocks::const_iterator &_endBlockIter, const Text::TextBlocks::const_iterator &_end) { _yDelta = (_lineHeight - _fontHeight) / 2; if (_yTo >= 0 && (_y + _yDelta >= _yTo || _y >= _yTo)) return false; @@ -1230,12 +1220,12 @@ public: if ((selectFromStart && _parDirection == Qt::LeftToRight) || (selectTillEnd && _parDirection == Qt::RightToLeft)) { if (x > _x) { - _p->fillRect(QRectF(_x.toReal(), _y + _yDelta, (x - _x).toReal(), _fontHeight), _p->textPalette().selectBg->b); + _p->fillRect(QRectF(_x.toReal(), _y + _yDelta, (x - _x).toReal(), _fontHeight), _p->textPalette().selectBg); } } if ((selectTillEnd && _parDirection == Qt::LeftToRight) || (selectFromStart && _parDirection == Qt::RightToLeft)) { if (x < _x + _wLeft) { - _p->fillRect(QRectF((x + _w - _wLeft).toReal(), _y + _yDelta, (_x + _wLeft - x).toReal(), _fontHeight), _p->textPalette().selectBg->b); + _p->fillRect(QRectF((x + _w - _wLeft).toReal(), _y + _yDelta, (_x + _wLeft - x).toReal(), _fontHeight), _p->textPalette().selectBg); } } } @@ -1298,8 +1288,7 @@ public: int32 textY = _y + _yDelta + _t->_st->font->ascent, emojiY = (_t->_st->font->height - st::emojiSize) / 2; - eSetFont(currentBlock); - if (_p) _p->setPen(blockPen(currentBlock)); + applyBlockProperties(currentBlock); for (int i = 0; i < nItems; ++i) { int item = firstItem + visualOrder[i]; const QScriptItem &si = engine.layoutData->items.at(item); @@ -1308,14 +1297,12 @@ public: while (blockIndex > _lineStartBlock + 1 && _t->_blocks[blockIndex - 1]->from() > _localFrom + si.position) { nextBlock = currentBlock; currentBlock = _t->_blocks[--blockIndex - 1]; - if (_p) _p->setPen(blockPen(currentBlock)); - eSetFont(currentBlock); + applyBlockProperties(currentBlock); } while (nextBlock && nextBlock->from() <= _localFrom + si.position) { currentBlock = nextBlock; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; - if (_p) _p->setPen(blockPen(currentBlock)); - eSetFont(currentBlock); + applyBlockProperties(currentBlock); } if (si.analysis.flags >= QScriptAnalysis::TabOrObject) { TextBlockType _type = currentBlock->type(); @@ -1378,7 +1365,7 @@ public: } } else if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space && (chTo - 1 - _str) >= _selection.from) { if (rtl) { // rtl space only - _p->fillRect(QRectF(x.toReal(), _y + _yDelta, (glyphX - x).toReal(), _fontHeight), _p->textPalette().selectBg->b); + _p->fillRect(QRectF(x.toReal(), _y + _yDelta, (glyphX - x).toReal(), _fontHeight), _p->textPalette().selectBg); } else { // ltr space only _p->fillRect(QRectF((x + currentBlock->f_width()).toReal(), _y + _yDelta, (si.width - currentBlock->f_width()).toReal(), _fontHeight), _p->textPalette().selectBg); } @@ -1466,9 +1453,17 @@ public: gf.width = itemWidth; gf.justified = false; gf.initWithScriptItem(si); + + auto hasSelected = false; + auto hasNotSelected = true; + auto selectedRect = QRect(); if (_localFrom + itemStart < _selection.to && _localFrom + itemEnd > _selection.from) { - QFixed selX = x, selWidth = itemWidth; - if (_localFrom + itemEnd > _selection.to || _localFrom + itemStart < _selection.from) { + hasSelected = true; + auto selX = x; + auto selWidth = itemWidth; + if (_localFrom + itemStart >= _selection.from && _localFrom + itemEnd <= _selection.to) { + hasNotSelected = false; + } else { selWidth = 0; int itemL = itemEnd - itemStart; int selStart = _selection.from - (_localFrom + itemStart), selEnd = _selection.to - (_localFrom + itemStart); @@ -1503,10 +1498,32 @@ public: } } if (rtl) selX = x + itemWidth - (selX - x) - selWidth; - _p->fillRect(QRectF(selX.toReal(), _y + _yDelta, selWidth.toReal(), _fontHeight), _p->textPalette().selectBg->b); + selectedRect = QRect(qRound(selX.toReal()), _y + _yDelta, qRound(selWidth.toReal()), _fontHeight); + _p->fillRect(selectedRect, _p->textPalette().selectBg); + } + if (Q_UNLIKELY(hasSelected)) { + if (Q_UNLIKELY(hasNotSelected)) { + auto clippingEnabled = _p->hasClipping(); + auto clippingRegion = _p->clipRegion(); + _p->setClipRect(selectedRect, Qt::IntersectClip); + _p->setPen(*_currentPenSelected); + _p->drawTextItem(QPointF(x.toReal(), textY), gf); + _p->setClipRegion((clippingEnabled ? clippingRegion : QRegion(QRect(0, 0, QFIXED_MAX - 1, QFIXED_MAX - 1))) - selectedRect); + _p->setPen(*_currentPen); + _p->drawTextItem(QPointF(x.toReal(), textY), gf); + if (clippingEnabled) { + _p->setClipRegion(clippingRegion); + } else { + _p->setClipping(false); + } + } else { + _p->setPen(*_currentPenSelected); + _p->drawTextItem(QPointF(x.toReal(), textY), gf); + } + } else { + _p->setPen(*_currentPen); + _p->drawTextItem(QPointF(x.toReal(), textY), gf); } - - _p->drawTextItem(QPointF(x.toReal(), textY), gf); } x += itemWidth; @@ -2277,6 +2294,22 @@ public: } private: + void applyBlockProperties(ITextBlock *block) { + eSetFont(block); + if (_p) { + auto &palette = _p->textPalette(); + if (block->lnkIndex()) { + _currentPen = &palette.linkFg->p; + _currentPenSelected = &palette.selectLinkFg->p; + } else if ((block->flags() & TextBlockFCode) || (block->flags() & TextBlockFPre)) { + _currentPen = &palette.monoFg->p; + _currentPenSelected = &palette.selectMonoFg->p; + } else { + _currentPen = &_originalPen; + _currentPenSelected = &palette.selectFg->p; + } + } + } Painter *_p; const Text *_t; @@ -2285,6 +2318,8 @@ private: int32 _elideRemoveFromEnd = 0; style::align _align; QPen _originalPen; + const QPen *_currentPen = nullptr; + const QPen *_currentPenSelected = nullptr; int32 _yFrom, _yTo, _yToElide; TextSelection _selection = { 0, 0 }; bool _fullWidthSelection = true;