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<HistoryDocumentNamed>()) { 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<HistoryDocumentCaptioned>()) { - 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<HistoryMessageForwarded>(); 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;