Fix spoiler rounding.

This commit is contained in:
John Preston 2021-12-30 15:56:55 +03:00
parent 541c8d258b
commit 9da4e1e731

View file

@ -1765,33 +1765,23 @@ private:
} }
} }
} }
if (_background.color) { const auto hasSpoiler = _background.color &&
const auto from = currentBlock->from(); (_background.inFront || _background.startMs);
const auto to = (nextBlock ? nextBlock->from() : _t->_text.size()); if (hasSpoiler) {
if (_localFrom + si.position < to) {
auto chFrom = _str + currentBlock->from();
auto chTo = chFrom + ((nextBlock ? nextBlock->from() : _t->_text.size()) - currentBlock->from());
if (_localFrom + si.position >= from) { // could be without space
if (chTo == chFrom || (chTo - 1)->unicode() != QChar::Space || to >= (chTo - _str)) {
fillSpoiler = { x, si.width }; fillSpoiler = { x, si.width };
} else { // or with space
fillSpoiler = { glyphX, currentBlock->f_width() };
} }
} else if (chTo > chFrom && (chTo - 1)->unicode() == QChar::Space && (chTo - 1 - _str) >= from) { const auto spoilerOpacity = hasSpoiler
if (rtl) { // rtl space only ? fillSpoilerOpacity()
fillSpoiler = { x, glyphX - x }; : 0.;
} else { // ltr space only
fillSpoiler = { x + currentBlock->f_width(), si.width - currentBlock->f_width() };
}
}
}
}
const auto hasSpoiler = fillSpoiler.width != QFixed();
const auto hasSelect = fillSelect.to != QFixed(); const auto hasSelect = fillSelect.to != QFixed();
if (hasSelect) { if (hasSelect) {
fillSelectRange(fillSelect.from, fillSelect.to); fillSelectRange(fillSelect.from, fillSelect.to);
} }
if (!_background.inFront) { const auto opacity = _p->opacity();
if (spoilerOpacity < 1.) {
if (hasSpoiler) {
_p->setOpacity(opacity * (1. - spoilerOpacity));
}
Emoji::Draw( Emoji::Draw(
*_p, *_p,
static_cast<const EmojiBlock*>(currentBlock)->_emoji, static_cast<const EmojiBlock*>(currentBlock)->_emoji,
@ -1799,14 +1789,14 @@ private:
(glyphX + st::emojiPadding).toInt(), (glyphX + st::emojiPadding).toInt(),
_y + _yDelta + emojiY); _y + _yDelta + emojiY);
} }
if ((hasSpoiler && _background.inFront) if (hasSpoiler) {
|| _background.startMs) { _p->setOpacity(opacity * spoilerOpacity);
const auto opacity = _p->opacity(); fillSpoilerRange(
const auto fillOpacity = fillSpoilerOpacity(); fillSpoiler.from,
if (fillOpacity != opacity) { fillSpoiler.width,
_p->setOpacity(fillOpacity); blockIndex,
} currentBlock->from(),
fillSpoilerRange(fillSpoiler.from, fillSpoiler.width, blockIndex); (nextBlock ? nextBlock->from() : _t->_text.size()));
_p->setOpacity(opacity); _p->setOpacity(opacity);
} }
// } else if (_p && currentBlock->type() == TextBlockSkip) { // debug // } else if (_p && currentBlock->type() == TextBlockSkip) { // debug
@ -1944,7 +1934,15 @@ private:
selectedRect = QRect(selX.toInt(), _y + _yDelta, (selX + selWidth).toInt() - selX.toInt(), _fontHeight); selectedRect = QRect(selX.toInt(), _y + _yDelta, (selX + selWidth).toInt() - selX.toInt(), _fontHeight);
fillSelectRange(selX, selX + selWidth); fillSelectRange(selX, selX + selWidth);
} }
if (!_background.inFront || _background.startMs) { const auto hasSpoiler = (_background.inFront || _background.startMs);
const auto spoilerOpacity = hasSpoiler
? fillSpoilerOpacity()
: 0.;
const auto opacity = _p->opacity();
if (spoilerOpacity < 1.) {
if (hasSpoiler) {
_p->setOpacity(opacity * (1. - spoilerOpacity));
}
if (Q_UNLIKELY(hasSelected)) { if (Q_UNLIKELY(hasSelected)) {
if (Q_UNLIKELY(hasNotSelected)) { if (Q_UNLIKELY(hasNotSelected)) {
auto clippingEnabled = _p->hasClipping(); auto clippingEnabled = _p->hasClipping();
@ -1971,13 +1969,14 @@ private:
} }
} }
if (_background.inFront || _background.startMs) { if (hasSpoiler) {
const auto opacity = _p->opacity(); _p->setOpacity(opacity * spoilerOpacity);
const auto fillOpacity = fillSpoilerOpacity(); fillSpoilerRange(
if (fillOpacity != opacity) { x,
_p->setOpacity(fillOpacity); itemWidth,
} blockIndex,
fillSpoilerRange(x, itemWidth, blockIndex); _localFrom + itemStart,
_localFrom + itemEnd);
_p->setOpacity(opacity); _p->setOpacity(opacity);
} }
} }
@ -2007,7 +2006,12 @@ private:
return (1. - std::min(progress, 1.)); return (1. - std::min(progress, 1.));
} }
void fillSpoilerRange(QFixed x, QFixed width, int currentBlockIndex) { void fillSpoilerRange(
QFixed x,
QFixed width,
int currentBlockIndex,
int positionFrom,
int positionTill) {
if (!_background.color) { if (!_background.color) {
return; return;
} }
@ -2019,10 +2023,11 @@ private:
: _t->_spoilerShownCache; : _t->_spoilerShownCache;
const auto cornerWidth = cache.corners[0].width() const auto cornerWidth = cache.corners[0].width()
/ style::DevicePixelRatio(); / style::DevicePixelRatio();
const auto useWidth = (x + width).toInt() - x.toInt();
const auto rect = QRect( const auto rect = QRect(
x.toInt(), x.toInt(),
_y + _yDelta, _y + _yDelta,
std::max(width.toInt() - elideOffset, cornerWidth * 2), std::max(useWidth - elideOffset, cornerWidth * 2),
_fontHeight); _fontHeight);
if (!rect.isValid()) { if (!rect.isValid()) {
return; return;
@ -2030,12 +2035,21 @@ private:
const auto parts = [&] { const auto parts = [&] {
const auto blockIndex = currentBlockIndex - 1; const auto blockIndex = currentBlockIndex - 1;
const auto now = _t->_blocks[blockIndex]->spoilerIndex(); const auto block = _t->_blocks[blockIndex].get();
const auto was = (blockIndex > 0) const auto nextBlock = (blockIndex + 1 < _t->_blocks.size())
? _t->_blocks[blockIndex + 1].get()
: nullptr;
const auto blockEnd = nextBlock ? nextBlock->from() : _t->_text.size();
const auto now = block->spoilerIndex();
const auto was = (positionFrom > block->from())
? now
: (blockIndex > 0)
? _t->_blocks[blockIndex - 1]->spoilerIndex() ? _t->_blocks[blockIndex - 1]->spoilerIndex()
: 0; : 0;
const auto will = (blockIndex < _t->_blocks.size() - 1) const auto will = (positionTill < blockEnd)
? _t->_blocks[blockIndex + 1]->spoilerIndex() ? now
: nextBlock
? nextBlock->spoilerIndex()
: 0; : 0;
return RectPart::None return RectPart::None
| ((now != was) ? (RectPart::FullLeft) : RectPart::None) | ((now != was) ? (RectPart::FullLeft) : RectPart::None)