Use std::unique_ptrs for ITextBlocks.

This commit is contained in:
John Preston 2017-07-06 18:58:05 +03:00
parent 8550099110
commit 8d43bdb084
3 changed files with 97 additions and 99 deletions

View file

@ -178,13 +178,13 @@ public:
} }
lastSkipped = false; lastSkipped = false;
if (emoji) { if (emoji) {
_t->_blocks.push_back(new EmojiBlock(_t->_st->font, _t->_text, blockStart, len, flags, lnkIndex, emoji)); _t->_blocks.push_back(std::make_unique<EmojiBlock>(_t->_st->font, _t->_text, blockStart, len, flags, lnkIndex, emoji));
emoji = 0; emoji = 0;
lastSkipped = true; lastSkipped = true;
} else if (newline) { } else if (newline) {
_t->_blocks.push_back(new NewlineBlock(_t->_st->font, _t->_text, blockStart, len, flags, lnkIndex)); _t->_blocks.push_back(std::make_unique<NewlineBlock>(_t->_st->font, _t->_text, blockStart, len, flags, lnkIndex));
} else { } else {
_t->_blocks.push_back(new TextBlock(_t->_st->font, _t->_text, _t->_minResizeWidth, blockStart, len, flags, lnkIndex)); _t->_blocks.push_back(std::make_unique<TextBlock>(_t->_st->font, _t->_text, _t->_minResizeWidth, blockStart, len, flags, lnkIndex));
} }
blockStart += len; blockStart += len;
blockCreated(); blockCreated();
@ -194,7 +194,7 @@ public:
void createSkipBlock(int32 w, int32 h) { void createSkipBlock(int32 w, int32 h) {
createBlock(); createBlock();
_t->_text.push_back('_'); _t->_text.push_back('_');
_t->_blocks.push_back(new SkipBlock(_t->_st->font, _t->_text, blockStart++, w, h, lnkIndex)); _t->_blocks.push_back(std::make_unique<SkipBlock>(_t->_st->font, _t->_text, blockStart++, w, h, lnkIndex));
blockCreated(); blockCreated();
} }
@ -251,7 +251,7 @@ public:
} else if (type == EntityInTextPre) { } else if (type == EntityInTextPre) {
startFlags = TextBlockFPre; startFlags = TextBlockFPre;
createBlock(); createBlock();
if (!_t->_blocks.isEmpty() && _t->_blocks.back()->type() != TextBlockTNewline) { if (!_t->_blocks.empty() && _t->_blocks.back()->type() != TextBlockTNewline) {
createNewlineBlock(); createNewlineBlock();
} }
} else if (type == EntityInTextUrl } else if (type == EntityInTextUrl
@ -587,7 +587,7 @@ public:
_t->_links.resize(maxLnkIndex); _t->_links.resize(maxLnkIndex);
for (auto i = _t->_blocks.cbegin(), e = _t->_blocks.cend(); i != e; ++i) { for (auto i = _t->_blocks.cbegin(), e = _t->_blocks.cend(); i != e; ++i) {
auto b = *i; auto b = i->get();
if (b->lnkIndex() > 0x8000) { if (b->lnkIndex() > 0x8000) {
lnkIndex = maxLnkIndex + (b->lnkIndex() - 0x8000); lnkIndex = maxLnkIndex + (b->lnkIndex() - 0x8000);
if (_t->_links.size() < lnkIndex) { if (_t->_links.size() < lnkIndex) {
@ -635,7 +635,7 @@ public:
} }
} }
_t->_links.squeeze(); _t->_links.squeeze();
_t->_blocks.squeeze(); _t->_blocks.shrink_to_fit();
_t->_text.squeeze(); _t->_text.squeeze();
} }
@ -823,8 +823,8 @@ public:
_wLeft = _w = w; _wLeft = _w = w;
if (_elideLast) { if (_elideLast) {
_yToElide = _yTo; _yToElide = _yTo;
if (_elideRemoveFromEnd > 0 && !_t->_blocks.isEmpty()) { if (_elideRemoveFromEnd > 0 && !_t->_blocks.empty()) {
int firstBlockHeight = countBlockHeight(_t->_blocks.front(), _t->_st); int firstBlockHeight = countBlockHeight(_t->_blocks.front().get(), _t->_st);
if (_y + firstBlockHeight >= _yToElide) { if (_y + firstBlockHeight >= _yToElide) {
_wLeft -= _elideRemoveFromEnd; _wLeft -= _elideRemoveFromEnd;
} }
@ -860,7 +860,7 @@ public:
bool longWordLine = true; bool longWordLine = true;
auto e = _t->_blocks.cend(); auto e = _t->_blocks.cend();
for (auto i = _t->_blocks.cbegin(); i != e; ++i, ++blockIndex) { for (auto i = _t->_blocks.cbegin(); i != e; ++i, ++blockIndex) {
auto b = *i; auto b = i->get();
auto _btype = b->type(); auto _btype = b->type();
auto blockHeight = countBlockHeight(b, _t->_st); auto blockHeight = countBlockHeight(b, _t->_st);
@ -1139,7 +1139,7 @@ private:
} }
} }
auto _endBlock = (_endBlockIter == _end) ? nullptr : (*_endBlockIter); auto _endBlock = (_endBlockIter == _end) ? nullptr : _endBlockIter->get();
auto elidedLine = _elideLast && (_y + _lineHeight >= _yToElide); auto elidedLine = _elideLast && (_y + _lineHeight >= _yToElide);
if (elidedLine) { if (elidedLine) {
// If we decided to draw the last line elided only because of the skip block // If we decided to draw the last line elided only because of the skip block
@ -1154,8 +1154,8 @@ private:
} }
auto blockIndex = _lineStartBlock; auto blockIndex = _lineStartBlock;
auto currentBlock = _t->_blocks[blockIndex]; auto currentBlock = _t->_blocks[blockIndex].get();
auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : nullptr; auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
int32 delta = (currentBlock->from() < _lineStart ? qMin(_lineStart - currentBlock->from(), 2) : 0); int32 delta = (currentBlock->from() < _lineStart ? qMin(_lineStart - currentBlock->from(), 2) : 0);
_localFrom = _lineStart - delta; _localFrom = _lineStart - delta;
@ -1254,12 +1254,12 @@ private:
QVarLengthArray<int> visualOrder(nItems); QVarLengthArray<int> visualOrder(nItems);
QVarLengthArray<uchar> levels(nItems); QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i) { for (int i = 0; i < nItems; ++i) {
QScriptItem &si(engine.layoutData->items[firstItem + i]); auto &si = engine.layoutData->items[firstItem + i];
while (nextBlock && nextBlock->from() <= _localFrom + si.position) { while (nextBlock && nextBlock->from() <= _localFrom + si.position) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
} }
TextBlockType _type = currentBlock->type(); auto _type = currentBlock->type();
if (_type == TextBlockTSkip) { if (_type == TextBlockTSkip) {
levels[i] = si.analysis.bidiLevel = 0; levels[i] = si.analysis.bidiLevel = 0;
skipIndex = i; skipIndex = i;
@ -1282,8 +1282,8 @@ private:
} }
blockIndex = _lineStartBlock; blockIndex = _lineStartBlock;
currentBlock = _t->_blocks[blockIndex]; currentBlock = _t->_blocks[blockIndex].get();
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
int32 textY = _y + _yDelta + _t->_st->font->ascent, emojiY = (_t->_st->font->height - st::emojiSize) / 2; int32 textY = _y + _yDelta + _t->_st->font->ascent, emojiY = (_t->_st->font->height - st::emojiSize) / 2;
@ -1295,12 +1295,12 @@ private:
while (blockIndex > _lineStartBlock + 1 && _t->_blocks[blockIndex - 1]->from() > _localFrom + si.position) { while (blockIndex > _lineStartBlock + 1 && _t->_blocks[blockIndex - 1]->from() > _localFrom + si.position) {
nextBlock = currentBlock; nextBlock = currentBlock;
currentBlock = _t->_blocks[--blockIndex - 1]; currentBlock = _t->_blocks[--blockIndex - 1].get();
applyBlockProperties(currentBlock); applyBlockProperties(currentBlock);
} }
while (nextBlock && nextBlock->from() <= _localFrom + si.position) { while (nextBlock && nextBlock->from() <= _localFrom + si.position) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
applyBlockProperties(currentBlock); applyBlockProperties(currentBlock);
} }
if (si.analysis.flags >= QScriptAnalysis::TabOrObject) { if (si.analysis.flags >= QScriptAnalysis::TabOrObject) {
@ -1551,10 +1551,11 @@ private:
} }
_elideSavedIndex = blockIndex; _elideSavedIndex = blockIndex;
_elideSavedBlock = _t->_blocks[blockIndex]; auto mutableText = const_cast<Text*>(_t);
const_cast<Text*>(_t)->_blocks[blockIndex] = new TextBlock(_t->_st->font, _t->_text, QFIXED_MAX, elideStart, 0, _elideSavedBlock->flags(), _elideSavedBlock->lnkIndex()); _elideSavedBlock = std::move(mutableText->_blocks[blockIndex]);
mutableText->_blocks[blockIndex] = std::make_unique<TextBlock>(_t->_st->font, _t->_text, QFIXED_MAX, elideStart, 0, _elideSavedBlock->flags(), _elideSavedBlock->lnkIndex());
_blocksSize = blockIndex + 1; _blocksSize = blockIndex + 1;
_endBlock = (blockIndex + 1 < _t->_blocks.size() ? _t->_blocks[blockIndex + 1] : 0); _endBlock = (blockIndex + 1 < _t->_blocks.size() ? _t->_blocks[blockIndex + 1].get() : nullptr);
} }
void setElideBidi(int32 elideStart, int32 elideLen) { void setElideBidi(int32 elideStart, int32 elideLen) {
@ -1577,9 +1578,9 @@ private:
eItemize(); eItemize();
int blockIndex = _lineStartBlock; auto blockIndex = _lineStartBlock;
ITextBlock *currentBlock = _t->_blocks[blockIndex]; auto currentBlock = _t->_blocks[blockIndex].get();
ITextBlock *nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
QScriptLine line; QScriptLine line;
line.from = lineStart; line.from = lineStart;
@ -1596,7 +1597,7 @@ private:
QScriptItem &si(engine.layoutData->items[firstItem + i]); QScriptItem &si(engine.layoutData->items[firstItem + i]);
while (nextBlock && nextBlock->from() <= _localFrom + si.position) { while (nextBlock && nextBlock->from() <= _localFrom + si.position) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
} }
TextBlockType _type = currentBlock->type(); TextBlockType _type = currentBlock->type();
if (si.analysis.flags == QScriptAnalysis::Object) { if (si.analysis.flags == QScriptAnalysis::Object) {
@ -1667,7 +1668,7 @@ private:
lineLength += _Elide.size(); lineLength += _Elide.size();
if (!repeat) { if (!repeat) {
for (; blockIndex < _blocksSize && _t->_blocks[blockIndex] != _endBlock && _t->_blocks[blockIndex]->from() < elideStart; ++blockIndex) { for (; blockIndex < _blocksSize && _t->_blocks[blockIndex].get() != _endBlock && _t->_blocks[blockIndex]->from() < elideStart; ++blockIndex) {
} }
if (blockIndex < _blocksSize) { if (blockIndex < _blocksSize) {
elideSaveBlock(blockIndex, _endBlock, elideStart, elideWidth); elideSaveBlock(blockIndex, _endBlock, elideStart, elideWidth);
@ -1677,9 +1678,7 @@ private:
void restoreAfterElided() { void restoreAfterElided() {
if (_elideSavedBlock) { if (_elideSavedBlock) {
delete _t->_blocks[_elideSavedIndex]; const_cast<Text*>(_t)->_blocks[_elideSavedIndex] = std::move(_elideSavedBlock);
const_cast<Text*>(_t)->_blocks[_elideSavedIndex] = _elideSavedBlock;
_elideSavedBlock = nullptr;
} }
} }
@ -1695,15 +1694,15 @@ private:
auto end = _e->findItem(line.from + line.length - 1, item); auto end = _e->findItem(line.from + line.length - 1, item);
#endif // OS_MAC_OLD #endif // OS_MAC_OLD
int blockIndex = _lineStartBlock; auto blockIndex = _lineStartBlock;
ITextBlock *currentBlock = _t->_blocks[blockIndex]; auto currentBlock = _t->_blocks[blockIndex].get();
ITextBlock *nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
eSetFont(currentBlock); eSetFont(currentBlock);
for (; item <= end; ++item) { for (; item <= end; ++item) {
QScriptItem &si = _e->layoutData->items[item]; QScriptItem &si = _e->layoutData->items[item];
while (nextBlock && nextBlock->from() <= _localFrom + si.position) { while (nextBlock && nextBlock->from() <= _localFrom + si.position) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
eSetFont(currentBlock); eSetFont(currentBlock);
} }
_e->shape(item); _e->shape(item);
@ -1773,12 +1772,12 @@ private:
const ushort *string = reinterpret_cast<const ushort*>(_e->layoutData->string.unicode()); const ushort *string = reinterpret_cast<const ushort*>(_e->layoutData->string.unicode());
int blockIndex = _lineStartBlock; auto blockIndex = _lineStartBlock;
ITextBlock *currentBlock = _t->_blocks[blockIndex]; auto currentBlock = _t->_blocks[blockIndex].get();
ITextBlock *nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; auto nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
_e->layoutData->hasBidi = _parHasBidi; _e->layoutData->hasBidi = _parHasBidi;
QScriptAnalysis *analysis = _parAnalysis.data() + (_localFrom - _parStart); auto analysis = _parAnalysis.data() + (_localFrom - _parStart);
{ {
QVarLengthArray<uchar> scripts(length); QVarLengthArray<uchar> scripts(length);
@ -1788,17 +1787,17 @@ private:
} }
blockIndex = _lineStartBlock; blockIndex = _lineStartBlock;
currentBlock = _t->_blocks[blockIndex]; currentBlock = _t->_blocks[blockIndex].get();
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
const ushort *start = string; auto start = string;
const ushort *end = start + length; auto end = start + length;
while (start < end) { while (start < end) {
while (nextBlock && nextBlock->from() <= _localFrom + (start - string)) { while (nextBlock && nextBlock->from() <= _localFrom + (start - string)) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
} }
TextBlockType _type = currentBlock->type(); auto _type = currentBlock->type();
if (_type == TextBlockTEmoji || _type == TextBlockTSkip) { if (_type == TextBlockTEmoji || _type == TextBlockTSkip) {
analysis->script = QChar::Script_Common; analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Object; analysis->flags = QScriptAnalysis::Object;
@ -1811,22 +1810,24 @@ private:
} }
{ {
const QString *i_string = &_e->layoutData->string; auto i_string = &_e->layoutData->string;
const QScriptAnalysis *i_analysis = _parAnalysis.data() + (_localFrom - _parStart); auto i_analysis = _parAnalysis.data() + (_localFrom - _parStart);
QScriptItemArray *i_items = &_e->layoutData->items; auto i_items = &_e->layoutData->items;
blockIndex = _lineStartBlock; blockIndex = _lineStartBlock;
currentBlock = _t->_blocks[blockIndex]; currentBlock = _t->_blocks[blockIndex].get();
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
ITextBlock *startBlock = currentBlock; auto startBlock = currentBlock;
if (!length) if (!length) {
return; return;
int start = 0, end = start + length; }
auto start = 0;
auto end = start + length;
for (int i = start + 1; i < end; ++i) { for (int i = start + 1; i < end; ++i) {
while (nextBlock && nextBlock->from() <= _localFrom + i) { while (nextBlock && nextBlock->from() <= _localFrom + i) {
currentBlock = nextBlock; currentBlock = nextBlock;
nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex] : 0; nextBlock = (++blockIndex < _blocksSize) ? _t->_blocks[blockIndex].get() : nullptr;
} }
// According to the unicode spec we should be treating characters in the Common script // According to the unicode spec we should be treating characters in the Common script
// (punctuation, spaces, etc) as being the same script as the surrounding text for the // (punctuation, spaces, etc) as being the same script as the surrounding text for the
@ -2359,7 +2360,7 @@ private:
// elided hack support // elided hack support
int _blocksSize = 0; int _blocksSize = 0;
int _elideSavedIndex = 0; int _elideSavedIndex = 0;
ITextBlock *_elideSavedBlock = nullptr; std::unique_ptr<ITextBlock> _elideSavedBlock;
int _lineStart = 0; int _lineStart = 0;
int _localFrom = 0; int _localFrom = 0;
@ -2406,11 +2407,11 @@ Text::Text(const Text &other)
, _minHeight(other._minHeight) , _minHeight(other._minHeight)
, _text(other._text) , _text(other._text)
, _st(other._st) , _st(other._st)
, _blocks(other._blocks.size())
, _links(other._links) , _links(other._links)
, _startDir(other._startDir) { , _startDir(other._startDir) {
for (int32 i = 0, l = _blocks.size(); i < l; ++i) { _blocks.reserve(other._blocks.size());
_blocks[i] = other._blocks.at(i)->clone(); for (auto &block : other._blocks) {
_blocks.push_back(block->clone());
} }
} }
@ -2420,7 +2421,7 @@ Text::Text(Text &&other)
, _minHeight(other._minHeight) , _minHeight(other._minHeight)
, _text(other._text) , _text(other._text)
, _st(other._st) , _st(other._st)
, _blocks(other._blocks) , _blocks(std::move(other._blocks))
, _links(other._links) , _links(other._links)
, _startDir(other._startDir) { , _startDir(other._startDir) {
other.clearFields(); other.clearFields();
@ -2447,7 +2448,7 @@ Text &Text::operator=(Text &&other) {
_minHeight = other._minHeight; _minHeight = other._minHeight;
_text = other._text; _text = other._text;
_st = other._st; _st = other._st;
_blocks = other._blocks; _blocks = std::move(other._blocks);
_links = other._links; _links = other._links;
_startDir = other._startDir; _startDir = other._startDir;
other.clearFields(); other.clearFields();
@ -2471,7 +2472,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
int32 result = 0, lastNewlineStart = 0; int32 result = 0, lastNewlineStart = 0;
QFixed _width = 0, last_rBearing = 0, last_rPadding = 0; QFixed _width = 0, last_rBearing = 0, last_rPadding = 0;
for (auto i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) { for (auto i = _blocks.cbegin(), e = _blocks.cend(); i != e; ++i) {
auto b = *i; auto b = i->get();
auto _btype = b->type(); auto _btype = b->type();
auto blockHeight = countBlockHeight(b, _st); auto blockHeight = countBlockHeight(b, _st);
if (_btype == TextBlockTNewline) { if (_btype == TextBlockTNewline) {
@ -2530,7 +2531,7 @@ void Text::recountNaturalSize(bool initial, Qt::LayoutDirection optionsDir) {
} }
} }
if (_width > 0) { if (_width > 0) {
if (!lineHeight) lineHeight = countBlockHeight(_blocks.back(), _st); if (!lineHeight) lineHeight = countBlockHeight(_blocks.back().get(), _st);
_minHeight += lineHeight; _minHeight += lineHeight;
accumulate_max(_maxWidth, _width); accumulate_max(_maxWidth, _width);
} }
@ -2659,23 +2660,23 @@ bool Text::hasLinks() const {
} }
bool Text::hasSkipBlock() const { bool Text::hasSkipBlock() const {
return _blocks.isEmpty() ? false : _blocks.back()->type() == TextBlockTSkip; return _blocks.empty() ? false : _blocks.back()->type() == TextBlockTSkip;
} }
void Text::setSkipBlock(int32 width, int32 height) { void Text::setSkipBlock(int32 width, int32 height) {
if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockTSkip) { if (!_blocks.empty() && _blocks.back()->type() == TextBlockTSkip) {
SkipBlock *block = static_cast<SkipBlock*>(_blocks.back()); auto block = static_cast<SkipBlock*>(_blocks.back().get());
if (block->width() == width && block->height() == height) return; if (block->width() == width && block->height() == height) return;
_text.resize(block->from()); _text.resize(block->from());
_blocks.pop_back(); _blocks.pop_back();
} }
_text.push_back('_'); _text.push_back('_');
_blocks.push_back(new SkipBlock(_st->font, _text, _text.size() - 1, width, height, 0)); _blocks.push_back(std::make_unique<SkipBlock>(_st->font, _text, _text.size() - 1, width, height, 0));
recountNaturalSize(false); recountNaturalSize(false);
} }
void Text::removeSkipBlock() { void Text::removeSkipBlock() {
if (!_blocks.isEmpty() && _blocks.back()->type() == TextBlockTSkip) { if (!_blocks.empty() && _blocks.back()->type() == TextBlockTSkip) {
_text.resize(_blocks.back()->from()); _text.resize(_blocks.back()->from());
_blocks.pop_back(); _blocks.pop_back();
recountNaturalSize(false); recountNaturalSize(false);
@ -2721,9 +2722,9 @@ void Text::enumerateLines(int w, Callback callback) const {
int lineHeight = 0; int lineHeight = 0;
QFixed widthLeft = width, last_rBearing = 0, last_rPadding = 0; QFixed widthLeft = width, last_rBearing = 0, last_rPadding = 0;
bool longWordLine = true; bool longWordLine = true;
for_const (auto b, _blocks) { for (auto &b : _blocks) {
auto _btype = b->type(); auto _btype = b->type();
int blockHeight = countBlockHeight(b, _st); int blockHeight = countBlockHeight(b.get(), _st);
if (_btype == TextBlockTNewline) { if (_btype == TextBlockTNewline) {
if (!lineHeight) lineHeight = blockHeight; if (!lineHeight) lineHeight = blockHeight;
@ -2751,7 +2752,7 @@ void Text::enumerateLines(int w, Callback callback) const {
} }
if (_btype == TextBlockTText) { if (_btype == TextBlockTText) {
auto t = static_cast<TextBlock*>(b); auto t = static_cast<TextBlock*>(b.get());
if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line if (t->_words.isEmpty()) { // no words in this block, spaces only => layout this block in the same line
last_rPadding += b->f_rpadding(); last_rPadding += b->f_rpadding();
@ -3027,9 +3028,6 @@ QString Text::originalText(TextSelection selection, ExpandLinksMode mode) const
} }
void Text::clear() { void Text::clear() {
for (TextBlocks::iterator i = _blocks.begin(), e = _blocks.end(); i != e; ++i) {
delete *i;
}
clearFields(); clearFields();
_text.clear(); _text.clear();
} }
@ -3041,6 +3039,8 @@ void Text::clearFields() {
_startDir = Qt::LayoutDirectionAuto; _startDir = Qt::LayoutDirectionAuto;
} }
Text::~Text() = default;
void emojiDraw(QPainter &p, EmojiPtr e, int x, int y) { void emojiDraw(QPainter &p, EmojiPtr e, int x, int y) {
auto size = Ui::Emoji::Size(); auto size = Ui::Emoji::Size();
p.drawPixmap(QPoint(x, y), App::emoji(), QRect(e->x() * size, e->y() * size, size, size)); p.drawPixmap(QPoint(x, y), App::emoji(), QRect(e->x() * size, e->y() * size, size, size));

View file

@ -199,12 +199,10 @@ public:
} }
void clear(); void clear();
~Text() { ~Text();
clear();
}
private: private:
using TextBlocks = QVector<ITextBlock*>; using TextBlocks = std::vector<std::unique_ptr<ITextBlock>>;
using TextLinks = QVector<ClickHandlerPtr>; using TextLinks = QVector<ClickHandlerPtr>;
uint16 countBlockEnd(const TextBlocks::const_iterator &i, const TextBlocks::const_iterator &e) const; uint16 countBlockEnd(const TextBlocks::const_iterator &i, const TextBlocks::const_iterator &e) const;

View file

@ -77,7 +77,7 @@ public:
return (_flags & 0xFF); return (_flags & 0xFF);
} }
virtual ITextBlock *clone() const = 0; virtual std::unique_ptr<ITextBlock> clone() const = 0;
virtual ~ITextBlock() { virtual ~ITextBlock() {
} }
@ -99,19 +99,19 @@ protected:
class NewlineBlock : public ITextBlock { class NewlineBlock : public ITextBlock {
public: public:
Qt::LayoutDirection nextDirection() const {
return _nextDir;
}
ITextBlock *clone() const {
return new NewlineBlock(*this);
}
private:
NewlineBlock(const style::font &font, const QString &str, uint16 from, uint16 length, uchar flags, uint16 lnkIndex) : ITextBlock(font, str, from, length, flags, lnkIndex), _nextDir(Qt::LayoutDirectionAuto) { NewlineBlock(const style::font &font, const QString &str, uint16 from, uint16 length, uchar flags, uint16 lnkIndex) : ITextBlock(font, str, from, length, flags, lnkIndex), _nextDir(Qt::LayoutDirectionAuto) {
_flags |= ((TextBlockTNewline & 0x0F) << 8); _flags |= ((TextBlockTNewline & 0x0F) << 8);
} }
Qt::LayoutDirection nextDirection() const {
return _nextDir;
}
std::unique_ptr<ITextBlock> clone() const override {
return std::make_unique<NewlineBlock>(*this);
}
private:
Qt::LayoutDirection _nextDir; Qt::LayoutDirection _nextDir;
friend class Text; friend class Text;
@ -155,13 +155,13 @@ private:
class TextBlock : public ITextBlock { class TextBlock : public ITextBlock {
public: public:
ITextBlock *clone() const { TextBlock(const style::font &font, const QString &str, QFixed minResizeWidth, uint16 from, uint16 length, uchar flags, uint16 lnkIndex);
return new TextBlock(*this);
std::unique_ptr<ITextBlock> clone() const override {
return std::make_unique<TextBlock>(*this);
} }
private: private:
TextBlock(const style::font &font, const QString &str, QFixed minResizeWidth, uint16 from, uint16 length, uchar flags, uint16 lnkIndex);
friend class ITextBlock; friend class ITextBlock;
QFixed real_f_rbearing() const { QFixed real_f_rbearing() const {
return _words.isEmpty() ? 0 : _words.back().f_rbearing(); return _words.isEmpty() ? 0 : _words.back().f_rbearing();
@ -180,13 +180,13 @@ private:
class EmojiBlock : public ITextBlock { class EmojiBlock : public ITextBlock {
public: public:
ITextBlock *clone() const { EmojiBlock(const style::font &font, const QString &str, uint16 from, uint16 length, uchar flags, uint16 lnkIndex, EmojiPtr emoji);
return new EmojiBlock(*this);
std::unique_ptr<ITextBlock> clone() const {
return std::make_unique<EmojiBlock>(*this);
} }
private: private:
EmojiBlock(const style::font &font, const QString &str, uint16 from, uint16 length, uchar flags, uint16 lnkIndex, EmojiPtr emoji);
EmojiPtr emoji = nullptr; EmojiPtr emoji = nullptr;
friend class Text; friend class Text;
@ -198,17 +198,17 @@ private:
class SkipBlock : public ITextBlock { class SkipBlock : public ITextBlock {
public: public:
SkipBlock(const style::font &font, const QString &str, uint16 from, int32 w, int32 h, uint16 lnkIndex);
int32 height() const { int32 height() const {
return _height; return _height;
} }
ITextBlock *clone() const { std::unique_ptr<ITextBlock> clone() const override {
return new SkipBlock(*this); return std::make_unique<SkipBlock>(*this);
} }
private: private:
SkipBlock(const style::font &font, const QString &str, uint16 from, int32 w, int32 h, uint16 lnkIndex);
int32 _height; int32 _height;
friend class Text; friend class Text;