Render correct spoiler selections.
This commit is contained in:
parent
4ff5bc5773
commit
a60fe582ad
4 changed files with 190 additions and 85 deletions
|
|
@ -95,24 +95,13 @@ SpoilerMessCache::SpoilerMessCache(int capacity) : _capacity(capacity) {
|
||||||
not_null<SpoilerMessCached*> SpoilerMessCache::lookup(QColor color) {
|
not_null<SpoilerMessCached*> SpoilerMessCache::lookup(QColor color) {
|
||||||
for (auto &entry : _cache) {
|
for (auto &entry : _cache) {
|
||||||
if (entry.color == color) {
|
if (entry.color == color) {
|
||||||
entry.generation = ++_generation;
|
|
||||||
return &entry.mess;
|
return &entry.mess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_cache.size() == _capacity) {
|
Assert(_cache.size() < _capacity);
|
||||||
const auto i = ranges::min_element(
|
|
||||||
_cache,
|
|
||||||
ranges::less(),
|
|
||||||
&Entry::generation);
|
|
||||||
i->generation = ++_generation;
|
|
||||||
i->color = color;
|
|
||||||
i->mess = Ui::SpoilerMessCached(DefaultTextSpoilerMask(), color);
|
|
||||||
return &i->mess;
|
|
||||||
}
|
|
||||||
_cache.push_back({
|
_cache.push_back({
|
||||||
.mess = Ui::SpoilerMessCached(DefaultTextSpoilerMask(), color),
|
.mess = Ui::SpoilerMessCached(DefaultTextSpoilerMask(), color),
|
||||||
.color = color,
|
.color = color,
|
||||||
.generation = ++_generation,
|
|
||||||
});
|
});
|
||||||
return &_cache.back().mess;
|
return &_cache.back().mess;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,12 +115,10 @@ private:
|
||||||
struct Entry {
|
struct Entry {
|
||||||
SpoilerMessCached mess;
|
SpoilerMessCached mess;
|
||||||
QColor color;
|
QColor color;
|
||||||
int generation = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Entry> _cache;
|
std::vector<Entry> _cache;
|
||||||
const int _capacity = 0;
|
const int _capacity = 0;
|
||||||
int _generation = 0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,31 @@ void InitTextItemWithScriptItem(QTextItemInt &ti, const QScriptItem &si) {
|
||||||
ti.flags |= QTextItem::StrikeOut;
|
ti.flags |= QTextItem::StrikeOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
void AppendRange(
|
||||||
|
QVarLengthArray<FixedRange> &ranges,
|
||||||
|
FixedRange range) {
|
||||||
|
for (auto i = ranges.begin(); i != ranges.end(); ++i) {
|
||||||
|
if (range.till < i->from) {
|
||||||
|
ranges.insert(i, range);
|
||||||
|
return;
|
||||||
|
} else if (!Distinct(range, *i)) {
|
||||||
|
*i = United(*i, range);
|
||||||
|
for (auto j = i + 1; j != ranges.end(); ++j) {
|
||||||
|
if (j->from > i->till) {
|
||||||
|
ranges.erase(i + 1, j);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
*i = United(*i, *j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranges.erase(i + 1, ranges.end());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ranges.push_back(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
struct Renderer::BidiControl {
|
struct Renderer::BidiControl {
|
||||||
inline BidiControl(bool rtl)
|
inline BidiControl(bool rtl)
|
||||||
|
|
@ -109,6 +132,28 @@ struct Renderer::BidiControl {
|
||||||
bool override = false;
|
bool override = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FixedRange Intersected(FixedRange a, FixedRange b) {
|
||||||
|
return {
|
||||||
|
.from = std::max(a.from, b.from),
|
||||||
|
.till = std::min(a.till, b.till),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Intersects(FixedRange a, FixedRange b) {
|
||||||
|
return (a.till > b.from) && (b.till > a.from);
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedRange United(FixedRange a, FixedRange b) {
|
||||||
|
return {
|
||||||
|
.from = std::min(a.from, b.from),
|
||||||
|
.till = std::max(a.till, b.till),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Distinct(FixedRange a, FixedRange b) {
|
||||||
|
return (a.till < b.from) || (b.till < a.from);
|
||||||
|
}
|
||||||
|
|
||||||
Renderer::Renderer(const Ui::Text::String &t)
|
Renderer::Renderer(const Ui::Text::String &t)
|
||||||
: _t(&t) {
|
: _t(&t) {
|
||||||
}
|
}
|
||||||
|
|
@ -194,6 +239,12 @@ void Renderer::enumerate() {
|
||||||
auto last_rBearing = QFixed(0);
|
auto last_rBearing = QFixed(0);
|
||||||
_last_rPadding = QFixed(0);
|
_last_rPadding = QFixed(0);
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] {
|
||||||
|
if (_p) {
|
||||||
|
paintSpoilerRects();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
auto blockIndex = 0;
|
auto blockIndex = 0;
|
||||||
bool longWordLine = true;
|
bool longWordLine = true;
|
||||||
auto e = _t->_blocks.cend();
|
auto e = _t->_blocks.cend();
|
||||||
|
|
@ -572,13 +623,13 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
if ((selectFromStart && _parDirection == Qt::LeftToRight)
|
if ((selectFromStart && _parDirection == Qt::LeftToRight)
|
||||||
|| (selectTillEnd && _parDirection == Qt::RightToLeft)) {
|
|| (selectTillEnd && _parDirection == Qt::RightToLeft)) {
|
||||||
if (x > _x) {
|
if (x > _x) {
|
||||||
fillSelectRange(_x, x);
|
fillSelectRange({ _x, x });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((selectTillEnd && _parDirection == Qt::LeftToRight)
|
if ((selectTillEnd && _parDirection == Qt::LeftToRight)
|
||||||
|| (selectFromStart && _parDirection == Qt::RightToLeft)) {
|
|| (selectFromStart && _parDirection == Qt::RightToLeft)) {
|
||||||
if (x < _x + _wLeft) {
|
if (x < _x + _wLeft) {
|
||||||
fillSelectRange(x + _w - _wLeft, _x + _w);
|
fillSelectRange({ x + _w - _wLeft, _x + _w });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -730,14 +781,8 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
if (rtl) {
|
if (rtl) {
|
||||||
glyphX += spacesWidth;
|
glyphX += spacesWidth;
|
||||||
}
|
}
|
||||||
struct {
|
FixedRange fillSelect;
|
||||||
QFixed from;
|
FixedRange fillSpoiler;
|
||||||
QFixed to;
|
|
||||||
} fillSelect;
|
|
||||||
struct {
|
|
||||||
QFixed from;
|
|
||||||
QFixed width;
|
|
||||||
} fillSpoiler;
|
|
||||||
if (_background.selectActiveBlock) {
|
if (_background.selectActiveBlock) {
|
||||||
fillSelect = { x, x + si.width };
|
fillSelect = { x, x + si.width };
|
||||||
} else if (_localFrom + si.position < _selection.to) {
|
} else if (_localFrom + si.position < _selection.to) {
|
||||||
|
|
@ -757,18 +802,15 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto hasSpoiler = _background.spoiler &&
|
const auto hasSpoiler = _background.inFront
|
||||||
(_background.inFront || _background.startMs);
|
|| _background.startMs;
|
||||||
if (hasSpoiler) {
|
if (hasSpoiler) {
|
||||||
fillSpoiler = { x, si.width };
|
fillSpoiler = { x, x + si.width };
|
||||||
}
|
}
|
||||||
const auto spoilerOpacity = hasSpoiler
|
const auto spoilerOpacity = hasSpoiler
|
||||||
? fillSpoilerOpacity()
|
? fillSpoilerOpacity()
|
||||||
: 0.;
|
: 0.;
|
||||||
const auto hasSelect = fillSelect.to != QFixed();
|
fillSelectRange(fillSelect);
|
||||||
if (hasSelect) {
|
|
||||||
fillSelectRange(fillSelect.from, fillSelect.to);
|
|
||||||
}
|
|
||||||
const auto opacity = _p->opacity();
|
const auto opacity = _p->opacity();
|
||||||
if (spoilerOpacity < 1.) {
|
if (spoilerOpacity < 1.) {
|
||||||
if (hasSpoiler) {
|
if (hasSpoiler) {
|
||||||
|
|
@ -795,16 +837,12 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
.paused = _paused,
|
.paused = _paused,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (hasSpoiler) {
|
||||||
|
_p->setOpacity(opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hasSpoiler) {
|
if (hasSpoiler) {
|
||||||
_p->setOpacity(opacity * spoilerOpacity);
|
pushSpoilerRange(fillSpoiler, fillSelect, blockIndex);
|
||||||
fillSpoilerRange(
|
|
||||||
fillSpoiler.from,
|
|
||||||
fillSpoiler.width,
|
|
||||||
blockIndex,
|
|
||||||
currentBlock->from(),
|
|
||||||
(nextBlock ? nextBlock->from() : _t->_text.size()));
|
|
||||||
_p->setOpacity(opacity);
|
|
||||||
}
|
}
|
||||||
//} else if (_p && currentBlock->type() == TextBlockSkip) { // debug
|
//} else if (_p && currentBlock->type() == TextBlockSkip) { // debug
|
||||||
// _p->fillRect(QRect(x.toInt(), _y, currentBlock->width(), static_cast<SkipBlock*>(currentBlock)->height()), QColor(0, 0, 0, 32));
|
// _p->fillRect(QRect(x.toInt(), _y, currentBlock->width(), static_cast<SkipBlock*>(currentBlock)->height()), QColor(0, 0, 0, 32));
|
||||||
|
|
@ -896,11 +934,14 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
gf.justified = false;
|
gf.justified = false;
|
||||||
InitTextItemWithScriptItem(gf, si);
|
InitTextItemWithScriptItem(gf, si);
|
||||||
|
|
||||||
|
auto itemRange = FixedRange{ x, x + itemWidth };
|
||||||
|
auto fillSelect = FixedRange();
|
||||||
auto hasSelected = false;
|
auto hasSelected = false;
|
||||||
auto hasNotSelected = true;
|
auto hasNotSelected = true;
|
||||||
auto selectedRect = QRect();
|
auto selectedRect = QRect();
|
||||||
if (_background.selectActiveBlock) {
|
if (_background.selectActiveBlock) {
|
||||||
fillSelectRange(x, x + itemWidth);
|
fillSelect = itemRange;
|
||||||
|
fillSelectRange(fillSelect);
|
||||||
} else if (_localFrom + itemStart < _selection.to && _localFrom + itemEnd > _selection.from) {
|
} else if (_localFrom + itemStart < _selection.to && _localFrom + itemEnd > _selection.from) {
|
||||||
hasSelected = true;
|
hasSelected = true;
|
||||||
auto selX = x;
|
auto selX = x;
|
||||||
|
|
@ -943,7 +984,8 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
}
|
}
|
||||||
if (rtl) selX = x + itemWidth - (selX - x) - selWidth;
|
if (rtl) selX = x + itemWidth - (selX - x) - selWidth;
|
||||||
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);
|
fillSelect = { selX, selX + selWidth };
|
||||||
|
fillSelectRange(fillSelect);
|
||||||
}
|
}
|
||||||
const auto hasSpoiler = (_background.inFront || _background.startMs);
|
const auto hasSpoiler = (_background.inFront || _background.startMs);
|
||||||
const auto spoilerOpacity = hasSpoiler
|
const auto spoilerOpacity = hasSpoiler
|
||||||
|
|
@ -1024,29 +1066,28 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
} else {
|
} else {
|
||||||
_p->setClipping(false);
|
_p->setClipping(false);
|
||||||
}
|
}
|
||||||
|
} else if (hasSpoiler && !isElidedBlock) {
|
||||||
|
_p->setOpacity(opacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSpoiler) {
|
if (hasSpoiler) {
|
||||||
_p->setOpacity(opacity * spoilerOpacity);
|
pushSpoilerRange(itemRange, fillSelect, blockIndex);
|
||||||
fillSpoilerRange(
|
|
||||||
x,
|
|
||||||
itemWidth,
|
|
||||||
blockIndex,
|
|
||||||
_localFrom + itemStart,
|
|
||||||
_localFrom + itemEnd);
|
|
||||||
_p->setOpacity(opacity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x += itemWidth;
|
x += itemWidth;
|
||||||
}
|
}
|
||||||
|
fillSpoilerRects();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::fillSelectRange(QFixed from, QFixed to) {
|
void Renderer::fillSelectRange(FixedRange range) {
|
||||||
auto left = from.toInt();
|
if (range.empty()) {
|
||||||
auto width = to.toInt() - left;
|
return;
|
||||||
|
}
|
||||||
|
const auto left = range.from.toInt();
|
||||||
|
const auto width = range.till.toInt() - left;
|
||||||
_p->fillRect(left, _y + _yDelta, width, _fontHeight, _palette->selectBg);
|
_p->fillRect(left, _y + _yDelta, width, _fontHeight, _palette->selectBg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1066,39 +1107,91 @@ float64 Renderer::fillSpoilerOpacity() {
|
||||||
return (1. - std::min(progress, 1.));
|
return (1. - std::min(progress, 1.));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::fillSpoilerRange(
|
void Renderer::pushSpoilerRange(
|
||||||
QFixed x,
|
FixedRange range,
|
||||||
QFixed width,
|
FixedRange selected,
|
||||||
int currentBlockIndex,
|
int currentBlockIndex) {
|
||||||
int positionFrom,
|
|
||||||
int positionTill) {
|
|
||||||
if (!_background.spoiler || !_t->_spoiler) {
|
if (!_background.spoiler || !_t->_spoiler) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto elided = (_indexOfElidedBlock == currentBlockIndex)
|
const auto elided = (_indexOfElidedBlock == currentBlockIndex)
|
||||||
? (_elideRemoveFromEnd + _f->elidew)
|
? (_elideRemoveFromEnd + _f->elidew)
|
||||||
: 0;
|
: 0;
|
||||||
const auto left = x.toInt();
|
range.till -= elided;
|
||||||
const auto useWidth = ((x + width).toInt() - left) - elided;
|
if (range.empty()) {
|
||||||
if (useWidth <= 0) {
|
return;
|
||||||
|
} else if (selected.empty() || !Intersects(range, selected)) {
|
||||||
|
AppendRange(_spoilerRanges, range);
|
||||||
|
} else {
|
||||||
|
AppendRange(_spoilerRanges, { range.from, selected.from });
|
||||||
|
AppendRange(_spoilerSelectedRanges, Intersected(range, selected));
|
||||||
|
AppendRange(_spoilerRanges, { selected.till, range.till });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::fillSpoilerRects() {
|
||||||
|
fillSpoilerRects(_spoilerRects, _spoilerRanges);
|
||||||
|
fillSpoilerRects(_spoilerSelectedRects, _spoilerSelectedRanges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::fillSpoilerRects(
|
||||||
|
QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
|
||||||
|
QVarLengthArray<FixedRange> &ranges) {
|
||||||
|
if (ranges.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto rect = QRect(
|
auto lastTill = ranges.front().from.toInt() - 1;
|
||||||
left,
|
const auto y = _y + _yDelta;
|
||||||
_y + _yDelta,
|
for (const auto &range : ranges) {
|
||||||
useWidth,
|
auto from = range.from.toInt();
|
||||||
_fontHeight);
|
auto till = range.till.toInt();
|
||||||
|
if (from <= lastTill) {
|
||||||
|
auto &last = rects.back();
|
||||||
|
from = std::min(from, last.x());
|
||||||
|
till = std::max(till, last.x() + last.width());
|
||||||
|
last = { from, y, till - from, _fontHeight };
|
||||||
|
} else {
|
||||||
|
rects.push_back({ from, y, till - from, _fontHeight });
|
||||||
|
}
|
||||||
|
lastTill = till;
|
||||||
|
}
|
||||||
|
ranges.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::paintSpoilerRects() {
|
||||||
|
if (!_t->_spoiler) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto index = _t->_spoiler->animation.index(now(), _paused);
|
||||||
|
paintSpoilerRects(
|
||||||
|
_spoilerRects,
|
||||||
|
_palette->spoilerFg,
|
||||||
|
index);
|
||||||
|
paintSpoilerRects(
|
||||||
|
_spoilerSelectedRects,
|
||||||
|
_palette->selectSpoilerFg,
|
||||||
|
index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::paintSpoilerRects(
|
||||||
|
const QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
|
||||||
|
const style::color &color,
|
||||||
|
int index) {
|
||||||
|
if (rects.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto frame = _spoilerCache->lookup(color->c)->frame(index);
|
||||||
if (_spoilerCache) {
|
if (_spoilerCache) {
|
||||||
const auto mess = _spoilerCache->lookup((*_background.spoiler)->c);
|
for (const auto &rect : rects) {
|
||||||
const auto spoiler = _t->_spoiler.get();
|
|
||||||
const auto frame = mess->frame(
|
|
||||||
spoiler->animation.index(now(), _paused));
|
|
||||||
Ui::FillSpoilerRect(*_p, rect, frame, -rect.topLeft());
|
Ui::FillSpoilerRect(*_p, rect, frame, -rect.topLeft());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Show forgotten spoiler context part.
|
// Show forgotten spoiler context part.
|
||||||
|
for (const auto &rect : rects) {
|
||||||
_p->fillRect(rect, Qt::red);
|
_p->fillRect(rect, Qt::red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::elideSaveBlock(int32 blockIndex, const AbstractBlock *&_endBlock, int32 elideStart, int32 elideWidth) {
|
void Renderer::elideSaveBlock(int32 blockIndex, const AbstractBlock *&_endBlock, int32 elideStart, int32 elideWidth) {
|
||||||
if (_elideSavedBlock) {
|
if (_elideSavedBlock) {
|
||||||
|
|
@ -1920,8 +2013,7 @@ void Renderer::applyBlockProperties(const AbstractBlock *block) {
|
||||||
= _t->_spoiler->links.at(block->spoilerIndex() - 1);
|
= _t->_spoiler->links.at(block->spoilerIndex() - 1);
|
||||||
const auto inBack = (handler && handler->shown());
|
const auto inBack = (handler && handler->shown());
|
||||||
_background.inFront = !inBack;
|
_background.inFront = !inBack;
|
||||||
_background.spoiler = &_palette->spoilerFg;
|
_background.spoiler = true;
|
||||||
_background.spoilerSelected = &_palette->selectSpoilerFg;
|
|
||||||
_background.startMs = handler ? handler->startMs() : 0;
|
_background.startMs = handler ? handler->startMs() : 0;
|
||||||
_background.spoilerIndex = block->spoilerIndex();
|
_background.spoilerIndex = block->spoilerIndex();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,20 @@ struct QScriptLine;
|
||||||
|
|
||||||
namespace Ui::Text {
|
namespace Ui::Text {
|
||||||
|
|
||||||
|
struct FixedRange {
|
||||||
|
QFixed from;
|
||||||
|
QFixed till;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return (till <= from);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] FixedRange Intersected(FixedRange a, FixedRange b);
|
||||||
|
[[nodiscard]] bool Intersects(FixedRange a, FixedRange b);
|
||||||
|
[[nodiscard]] FixedRange United(FixedRange a, FixedRange b);
|
||||||
|
[[nodiscard]] bool Distinct(FixedRange a, FixedRange b);
|
||||||
|
|
||||||
class Renderer final {
|
class Renderer final {
|
||||||
public:
|
public:
|
||||||
explicit Renderer(const Ui::Text::String &t);
|
explicit Renderer(const Ui::Text::String &t);
|
||||||
|
|
@ -31,6 +45,8 @@ public:
|
||||||
StateRequestElided request);
|
StateRequestElided request);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr int kSpoilersRectsSize = 512;
|
||||||
|
|
||||||
struct BidiControl;
|
struct BidiControl;
|
||||||
|
|
||||||
void enumerate();
|
void enumerate();
|
||||||
|
|
@ -42,14 +58,21 @@ private:
|
||||||
uint16 _lineEnd,
|
uint16 _lineEnd,
|
||||||
const String::TextBlocks::const_iterator &_endBlockIter,
|
const String::TextBlocks::const_iterator &_endBlockIter,
|
||||||
const String::TextBlocks::const_iterator &_end);
|
const String::TextBlocks::const_iterator &_end);
|
||||||
void fillSelectRange(QFixed from, QFixed to);
|
void fillSelectRange(FixedRange range);
|
||||||
[[nodiscard]] float64 fillSpoilerOpacity();
|
[[nodiscard]] float64 fillSpoilerOpacity();
|
||||||
void fillSpoilerRange(
|
void pushSpoilerRange(
|
||||||
QFixed x,
|
FixedRange range,
|
||||||
QFixed width,
|
FixedRange selected,
|
||||||
int currentBlockIndex,
|
int currentBlockIndex);
|
||||||
int positionFrom,
|
void fillSpoilerRects();
|
||||||
int positionTill);
|
void fillSpoilerRects(
|
||||||
|
QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
|
||||||
|
QVarLengthArray<FixedRange> &ranges);
|
||||||
|
void paintSpoilerRects();
|
||||||
|
void paintSpoilerRects(
|
||||||
|
const QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
|
||||||
|
const style::color &color,
|
||||||
|
int index);
|
||||||
void elideSaveBlock(
|
void elideSaveBlock(
|
||||||
int32 blockIndex,
|
int32 blockIndex,
|
||||||
const AbstractBlock *&_endBlock,
|
const AbstractBlock *&_endBlock,
|
||||||
|
|
@ -100,9 +123,8 @@ private:
|
||||||
const QPen *_currentPen = nullptr;
|
const QPen *_currentPen = nullptr;
|
||||||
const QPen *_currentPenSelected = nullptr;
|
const QPen *_currentPenSelected = nullptr;
|
||||||
struct {
|
struct {
|
||||||
const style::color *spoiler = nullptr;
|
|
||||||
const style::color *spoilerSelected = nullptr;
|
|
||||||
bool inFront = false;
|
bool inFront = false;
|
||||||
|
bool spoiler = true;
|
||||||
crl::time startMs = 0;
|
crl::time startMs = 0;
|
||||||
uint16 spoilerIndex = 0;
|
uint16 spoilerIndex = 0;
|
||||||
|
|
||||||
|
|
@ -115,6 +137,10 @@ private:
|
||||||
bool _fullWidthSelection = true;
|
bool _fullWidthSelection = true;
|
||||||
const QChar *_str = nullptr;
|
const QChar *_str = nullptr;
|
||||||
mutable crl::time _cachedNow = 0;
|
mutable crl::time _cachedNow = 0;
|
||||||
|
QVarLengthArray<FixedRange> _spoilerRanges;
|
||||||
|
QVarLengthArray<FixedRange> _spoilerSelectedRanges;
|
||||||
|
QVarLengthArray<QRect, kSpoilersRectsSize> _spoilerRects;
|
||||||
|
QVarLengthArray<QRect, kSpoilersRectsSize> _spoilerSelectedRects;
|
||||||
|
|
||||||
int _customEmojiSize = 0;
|
int _customEmojiSize = 0;
|
||||||
int _customEmojiSkip = 0;
|
int _customEmojiSkip = 0;
|
||||||
|
|
@ -122,7 +148,7 @@ private:
|
||||||
|
|
||||||
// current paragraph data
|
// current paragraph data
|
||||||
String::TextBlocks::const_iterator _parStartBlock;
|
String::TextBlocks::const_iterator _parStartBlock;
|
||||||
Qt::LayoutDirection _parDirection;
|
Qt::LayoutDirection _parDirection = Qt::LayoutDirectionAuto;
|
||||||
int _parStart = 0;
|
int _parStart = 0;
|
||||||
int _parLength = 0;
|
int _parLength = 0;
|
||||||
bool _parHasBidi = false;
|
bool _parHasBidi = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue