Support complex dimensions in Ui::Text::String.
This commit is contained in:
parent
607c3909dd
commit
24390ae853
9 changed files with 161 additions and 50 deletions
|
|
@ -819,6 +819,10 @@ Object::~Object() {
|
||||||
unload();
|
unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Object::width() {
|
||||||
|
return st::emojiSize + 2 * st::emojiPadding;
|
||||||
|
}
|
||||||
|
|
||||||
QString Object::entityData() {
|
QString Object::entityData() {
|
||||||
return _instance->entityData();
|
return _instance->entityData();
|
||||||
}
|
}
|
||||||
|
|
@ -864,6 +868,10 @@ Internal::Internal(QString entityData, QImage image, bool colored)
|
||||||
, _colored(colored) {
|
, _colored(colored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Internal::width() {
|
||||||
|
return _image.width() / _image.devicePixelRatio();
|
||||||
|
}
|
||||||
|
|
||||||
QString Internal::entityData() {
|
QString Internal::entityData() {
|
||||||
return _entityData;
|
return _entityData;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,7 @@ public:
|
||||||
Object(not_null<Instance*> instance, Fn<void()> repaint);
|
Object(not_null<Instance*> instance, Fn<void()> repaint);
|
||||||
~Object();
|
~Object();
|
||||||
|
|
||||||
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
void paint(QPainter &p, const Context &context) override;
|
void paint(QPainter &p, const Context &context) override;
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
@ -273,10 +274,11 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Internal final : public Ui::Text::CustomEmoji {
|
class Internal final : public Text::CustomEmoji {
|
||||||
public:
|
public:
|
||||||
Internal(QString entityData, QImage image, bool colored);
|
Internal(QString entityData, QImage image, bool colored);
|
||||||
|
|
||||||
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
void paint(QPainter &p, const Context &context) override;
|
void paint(QPainter &p, const Context &context) override;
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
|
||||||
163
ui/text/text.cpp
163
ui/text/text.cpp
|
|
@ -838,13 +838,37 @@ void String::removeModificationsAfter(int size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String::DimensionsResult String::countDimensions(
|
||||||
|
GeometryDescriptor geometry) const {
|
||||||
|
return countDimensions(std::move(geometry), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
String::DimensionsResult String::countDimensions(
|
||||||
|
GeometryDescriptor geometry,
|
||||||
|
DimensionsRequest request) const {
|
||||||
|
auto result = DimensionsResult();
|
||||||
|
if (request.lineWidths && request.reserve) {
|
||||||
|
result.lineWidths.reserve(request.reserve);
|
||||||
|
}
|
||||||
|
enumerateLines(geometry, [&](QFixed lineWidth, int lineBottom) {
|
||||||
|
const auto width = lineWidth.ceil().toInt();
|
||||||
|
if (request.lineWidths) {
|
||||||
|
result.lineWidths.push_back(width);
|
||||||
|
}
|
||||||
|
result.width = std::max(result.width, width);
|
||||||
|
result.height = lineBottom;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int String::countWidth(int width, bool breakEverywhere) const {
|
int String::countWidth(int width, bool breakEverywhere) const {
|
||||||
if (QFixed(width) >= _maxWidth) {
|
if (QFixed(width) >= _maxWidth) {
|
||||||
return _maxWidth;
|
return _maxWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
QFixed maxLineWidth = 0;
|
QFixed maxLineWidth = 0;
|
||||||
enumerateLines(width, breakEverywhere, [&](QFixed lineWidth, int lineHeight) {
|
enumerateLines(width, breakEverywhere, [&](QFixed lineWidth, int) {
|
||||||
if (lineWidth > maxLineWidth) {
|
if (lineWidth > maxLineWidth) {
|
||||||
maxLineWidth = lineWidth;
|
maxLineWidth = lineWidth;
|
||||||
}
|
}
|
||||||
|
|
@ -857,8 +881,8 @@ int String::countHeight(int width, bool breakEverywhere) const {
|
||||||
return _minHeight;
|
return _minHeight;
|
||||||
}
|
}
|
||||||
int result = 0;
|
int result = 0;
|
||||||
enumerateLines(width, breakEverywhere, [&](QFixed lineWidth, int lineHeight) {
|
enumerateLines(width, breakEverywhere, [&](auto, int lineBottom) {
|
||||||
result += lineHeight;
|
result = lineBottom;
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -874,7 +898,7 @@ std::vector<int> String::countLineWidths(
|
||||||
if (options.reserve) {
|
if (options.reserve) {
|
||||||
result.reserve(options.reserve);
|
result.reserve(options.reserve);
|
||||||
}
|
}
|
||||||
enumerateLines(width, options.breakEverywhere, [&](QFixed lineWidth, int lineHeight) {
|
enumerateLines(width, options.breakEverywhere, [&](QFixed lineWidth, int) {
|
||||||
result.push_back(lineWidth.ceil().toInt());
|
result.push_back(lineWidth.ceil().toInt());
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -884,18 +908,85 @@ template <typename Callback>
|
||||||
void String::enumerateLines(
|
void String::enumerateLines(
|
||||||
int w,
|
int w,
|
||||||
bool breakEverywhere,
|
bool breakEverywhere,
|
||||||
Callback callback) const {
|
Callback &&callback) const {
|
||||||
const auto width = QFixed(std::max(w, _minResizeWidth));
|
if (isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto width = std::max(w, _minResizeWidth);
|
||||||
|
auto g = SimpleGeometry(width, _st->font->height, 0, 0, false, false);
|
||||||
|
g.breakEverywhere = breakEverywhere;
|
||||||
|
enumerateLines(g, std::forward<Callback>(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Callback>
|
||||||
|
void String::enumerateLines(
|
||||||
|
GeometryDescriptor geometry,
|
||||||
|
Callback &&callback) const {
|
||||||
|
auto qindex = 0;
|
||||||
|
auto quote = (QuoteDetails*)nullptr;
|
||||||
|
auto qpadding = QMargins();
|
||||||
|
|
||||||
|
auto top = 0;
|
||||||
|
auto lineLeft = 0;
|
||||||
|
auto lineWidth = 0;
|
||||||
|
auto widthLeft = QFixed(0);
|
||||||
|
auto paragraphWidthRemaining = QFixed();
|
||||||
|
const auto initNextLine = [&] {
|
||||||
|
const auto line = geometry.layout({
|
||||||
|
.left = 0,
|
||||||
|
.top = top,
|
||||||
|
.width = paragraphWidthRemaining.ceil().toInt(),
|
||||||
|
});
|
||||||
|
lineLeft = line.left;
|
||||||
|
lineWidth = line.width;
|
||||||
|
if (quote && quote->maxWidth < lineWidth) {
|
||||||
|
const auto delta = lineWidth - quote->maxWidth;
|
||||||
|
lineWidth = quote->maxWidth;
|
||||||
|
}
|
||||||
|
widthLeft = lineWidth - qpadding.left() - qpadding.right();
|
||||||
|
};
|
||||||
|
const auto initNextParagraph = [&](
|
||||||
|
TextBlocks::const_iterator i,
|
||||||
|
int16 paragraphIndex) {
|
||||||
|
paragraphWidthRemaining = 0;
|
||||||
|
if (qindex != paragraphIndex) {
|
||||||
|
top += qpadding.bottom();
|
||||||
|
qindex = paragraphIndex;
|
||||||
|
quote = quoteByIndex(qindex);
|
||||||
|
qpadding = quotePadding(quote);
|
||||||
|
top += qpadding.top();
|
||||||
|
qpadding.setTop(0);
|
||||||
|
}
|
||||||
|
const auto e = _blocks.cend();
|
||||||
|
if (i != e) {
|
||||||
|
auto last_rPadding = QFixed(0);
|
||||||
|
auto last_rBearing = QFixed(0);
|
||||||
|
for (; i != e; ++i) {
|
||||||
|
if ((*i)->type() == TextBlockType::Newline) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const auto rBearing = (*i)->f_rbearing();
|
||||||
|
paragraphWidthRemaining += last_rBearing
|
||||||
|
+ last_rPadding
|
||||||
|
+ (*i)->f_width()
|
||||||
|
- rBearing;
|
||||||
|
last_rBearing = rBearing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paragraphWidthRemaining += qpadding.left() + qpadding.right();
|
||||||
|
initNextLine();
|
||||||
|
};
|
||||||
|
|
||||||
|
if ((*_blocks.cbegin())->type() != TextBlockType::Newline) {
|
||||||
|
initNextParagraph(_blocks.cbegin(), _startQuoteIndex);
|
||||||
|
}
|
||||||
|
|
||||||
auto qindex = quoteIndex(nullptr);
|
|
||||||
auto quote = quoteByIndex(qindex);
|
|
||||||
auto qpadding = quotePadding(quote);
|
|
||||||
auto widthLeft = width - qpadding.left() - qpadding.right();
|
|
||||||
auto lineHeight = 0;
|
auto lineHeight = 0;
|
||||||
auto last_rBearing = QFixed();
|
auto last_rBearing = QFixed();
|
||||||
auto last_rPadding = QFixed();
|
auto last_rPadding = QFixed();
|
||||||
bool longWordLine = true;
|
bool longWordLine = true;
|
||||||
for (auto &b : _blocks) {
|
for (auto i = _blocks.cbegin(); i != _blocks.cend(); ++i) {
|
||||||
|
const auto &b = *i;
|
||||||
auto _btype = b->type();
|
auto _btype = b->type();
|
||||||
const auto blockHeight = CountBlockHeight(b.get(), _st);
|
const auto blockHeight = CountBlockHeight(b.get(), _st);
|
||||||
|
|
||||||
|
|
@ -903,25 +994,16 @@ void String::enumerateLines(
|
||||||
if (!lineHeight) {
|
if (!lineHeight) {
|
||||||
lineHeight = blockHeight;
|
lineHeight = blockHeight;
|
||||||
}
|
}
|
||||||
lineHeight += qpadding.top();
|
const auto index = b.unsafe<const NewlineBlock>().quoteIndex();
|
||||||
const auto index = quoteIndex(b.get());
|
const auto changed = (qindex != index);
|
||||||
if (qindex != index) {
|
if (changed) {
|
||||||
lineHeight += qpadding.bottom();
|
lineHeight += qpadding.bottom();
|
||||||
qindex = index;
|
|
||||||
quote = quoteByIndex(qindex);
|
|
||||||
qpadding = quotePadding(quote);
|
|
||||||
} else {
|
|
||||||
qpadding.setTop(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(width - widthLeft, lineHeight);
|
callback(lineLeft + lineWidth - widthLeft, top += lineHeight);
|
||||||
|
|
||||||
lineHeight = 0;
|
lineHeight = 0;
|
||||||
last_rBearing = 0;// b->f_rbearing(); (0 for newline)
|
|
||||||
last_rPadding = 0;// b->f_rpadding(); (0 for newline)
|
|
||||||
widthLeft = width - qpadding.left() - qpadding.right();
|
|
||||||
// - (b->f_width() - last_rBearing); (0 for newline)
|
|
||||||
|
|
||||||
|
initNextParagraph(i + 1, index);
|
||||||
longWordLine = true;
|
longWordLine = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -974,23 +1056,23 @@ void String::enumerateLines(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f != j && !breakEverywhere) {
|
if (f != j && !geometry.breakEverywhere) {
|
||||||
j = f;
|
j = f;
|
||||||
widthLeft = f_wLeft;
|
widthLeft = f_wLeft;
|
||||||
lineHeight = f_lineHeight;
|
lineHeight = f_lineHeight;
|
||||||
j_width = (j->f_width() >= 0) ? j->f_width() : -j->f_width();
|
j_width = (j->f_width() >= 0) ? j->f_width() : -j->f_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(width - widthLeft, lineHeight + qpadding.top());
|
callback(lineLeft + lineWidth - widthLeft, top += lineHeight);
|
||||||
qpadding.setTop(0);
|
|
||||||
|
|
||||||
lineHeight = qMax(0, blockHeight);
|
lineHeight = qMax(0, blockHeight);
|
||||||
|
|
||||||
|
paragraphWidthRemaining -= (lineWidth - widthLeft) - last_rPadding + last_rBearing;
|
||||||
|
initNextLine();
|
||||||
|
|
||||||
last_rBearing = j->f_rbearing();
|
last_rBearing = j->f_rbearing();
|
||||||
last_rPadding = j->f_rpadding();
|
last_rPadding = j->f_rpadding();
|
||||||
widthLeft = width
|
widthLeft -= j_width - last_rBearing;
|
||||||
- qpadding.left()
|
|
||||||
- qpadding.right()
|
|
||||||
- (j_width - last_rBearing);
|
|
||||||
|
|
||||||
longWordLine = !wordEndsHere;
|
longWordLine = !wordEndsHere;
|
||||||
f = j + 1;
|
f = j + 1;
|
||||||
|
|
@ -1000,24 +1082,23 @@ void String::enumerateLines(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(width - widthLeft, lineHeight + qpadding.top());
|
callback(lineLeft + lineWidth - widthLeft, top += lineHeight);
|
||||||
qpadding.setTop(0);
|
|
||||||
|
|
||||||
lineHeight = qMax(0, blockHeight);
|
lineHeight = qMax(0, blockHeight);
|
||||||
|
paragraphWidthRemaining -= (lineWidth - widthLeft) - last_rPadding + last_rBearing;
|
||||||
|
initNextLine();
|
||||||
|
|
||||||
last_rBearing = b__f_rbearing;
|
last_rBearing = b__f_rbearing;
|
||||||
last_rPadding = b->f_rpadding();
|
last_rPadding = b->f_rpadding();
|
||||||
widthLeft = width
|
widthLeft -= b->f_width() - last_rBearing;
|
||||||
- qpadding.left()
|
|
||||||
- qpadding.right()
|
|
||||||
- (b->f_width() - last_rBearing);
|
|
||||||
|
|
||||||
longWordLine = true;
|
longWordLine = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (widthLeft < width) {
|
if (widthLeft < lineWidth) {
|
||||||
callback(
|
callback(
|
||||||
width - widthLeft,
|
lineLeft + lineWidth - widthLeft,
|
||||||
lineHeight + qpadding.top() + qpadding.bottom());
|
top + lineHeight + qpadding.bottom());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -275,6 +275,7 @@ public:
|
||||||
std::vector<int> lineWidths;
|
std::vector<int> lineWidths;
|
||||||
};
|
};
|
||||||
struct DimensionsRequest {
|
struct DimensionsRequest {
|
||||||
|
bool breakEverywhere = false;
|
||||||
bool lineWidths = false;
|
bool lineWidths = false;
|
||||||
int reserve = 0;
|
int reserve = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -414,13 +415,17 @@ private:
|
||||||
FlagsChangeCallback flagsChangeCallback) const;
|
FlagsChangeCallback flagsChangeCallback) const;
|
||||||
|
|
||||||
// Template method for countWidth(), countHeight(), countLineWidths().
|
// Template method for countWidth(), countHeight(), countLineWidths().
|
||||||
// callback(lineWidth, lineHeight) will be called for all lines with:
|
// callback(lineWidth, lineBottom) will be called for all lines with:
|
||||||
// QFixed lineWidth, int lineHeight
|
// QFixed lineWidth, int lineBottom
|
||||||
template <typename Callback>
|
template <typename Callback>
|
||||||
void enumerateLines(
|
void enumerateLines(
|
||||||
int w,
|
int w,
|
||||||
bool breakEverywhere,
|
bool breakEverywhere,
|
||||||
Callback callback) const;
|
Callback &&callback) const;
|
||||||
|
template <typename Callback>
|
||||||
|
void enumerateLines(
|
||||||
|
GeometryDescriptor geometry,
|
||||||
|
Callback &&callback) const;
|
||||||
|
|
||||||
void insertModifications(int position, int delta);
|
void insertModifications(int position, int delta);
|
||||||
void removeModificationsAfter(int size);
|
void removeModificationsAfter(int size);
|
||||||
|
|
|
||||||
|
|
@ -551,7 +551,7 @@ CustomEmojiBlock::CustomEmojiBlock(
|
||||||
linkIndex,
|
linkIndex,
|
||||||
colorIndex)
|
colorIndex)
|
||||||
, _custom(std::move(custom)) {
|
, _custom(std::move(custom)) {
|
||||||
_width = int(st::emojiSize + 2 * st::emojiPadding);
|
_width = _custom->width();
|
||||||
_rpadding = 0;
|
_rpadding = 0;
|
||||||
for (auto i = length; i != 0;) {
|
for (auto i = length; i != 0;) {
|
||||||
auto ch = text[_position + (--i)];
|
auto ch = text[_position + (--i)];
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ ShiftedEmoji::ShiftedEmoji(
|
||||||
, _shift(shift) {
|
, _shift(shift) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ShiftedEmoji::width() {
|
||||||
|
return _wrapped->width();
|
||||||
|
}
|
||||||
|
|
||||||
QString ShiftedEmoji::entityData() {
|
QString ShiftedEmoji::entityData() {
|
||||||
return _wrapped->entityData();
|
return _wrapped->entityData();
|
||||||
}
|
}
|
||||||
|
|
@ -45,6 +49,10 @@ FirstFrameEmoji::FirstFrameEmoji(std::unique_ptr<CustomEmoji> wrapped)
|
||||||
: _wrapped(std::move(wrapped)) {
|
: _wrapped(std::move(wrapped)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FirstFrameEmoji::width() {
|
||||||
|
return _wrapped->width();
|
||||||
|
}
|
||||||
|
|
||||||
QString FirstFrameEmoji::entityData() {
|
QString FirstFrameEmoji::entityData() {
|
||||||
return _wrapped->entityData();
|
return _wrapped->entityData();
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +85,10 @@ LimitedLoopsEmoji::LimitedLoopsEmoji(
|
||||||
, _stopOnLast(stopOnLast) {
|
, _stopOnLast(stopOnLast) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LimitedLoopsEmoji::width() {
|
||||||
|
return _wrapped->width();
|
||||||
|
}
|
||||||
|
|
||||||
QString LimitedLoopsEmoji::entityData() {
|
QString LimitedLoopsEmoji::entityData() {
|
||||||
return _wrapped->entityData();
|
return _wrapped->entityData();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class CustomEmoji {
|
||||||
public:
|
public:
|
||||||
virtual ~CustomEmoji() = default;
|
virtual ~CustomEmoji() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual int width() = 0;
|
||||||
[[nodiscard]] virtual QString entityData() = 0;
|
[[nodiscard]] virtual QString entityData() = 0;
|
||||||
|
|
||||||
using Context = CustomEmojiPaintContext;
|
using Context = CustomEmojiPaintContext;
|
||||||
|
|
@ -58,6 +59,7 @@ class ShiftedEmoji final : public CustomEmoji {
|
||||||
public:
|
public:
|
||||||
ShiftedEmoji(std::unique_ptr<CustomEmoji> wrapped, QPoint shift);
|
ShiftedEmoji(std::unique_ptr<CustomEmoji> wrapped, QPoint shift);
|
||||||
|
|
||||||
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
void paint(QPainter &p, const Context &context) override;
|
void paint(QPainter &p, const Context &context) override;
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
@ -74,6 +76,7 @@ class FirstFrameEmoji final : public CustomEmoji {
|
||||||
public:
|
public:
|
||||||
explicit FirstFrameEmoji(std::unique_ptr<CustomEmoji> wrapped);
|
explicit FirstFrameEmoji(std::unique_ptr<CustomEmoji> wrapped);
|
||||||
|
|
||||||
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
void paint(QPainter &p, const Context &context) override;
|
void paint(QPainter &p, const Context &context) override;
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
@ -92,6 +95,7 @@ public:
|
||||||
int limit,
|
int limit,
|
||||||
bool stopOnLast = false);
|
bool stopOnLast = false);
|
||||||
|
|
||||||
|
int width() override;
|
||||||
QString entityData() override;
|
QString entityData() override;
|
||||||
void paint(QPainter &p, const Context &context) override;
|
void paint(QPainter &p, const Context &context) override;
|
||||||
void unload() override;
|
void unload() override;
|
||||||
|
|
|
||||||
|
|
@ -949,14 +949,14 @@ bool Renderer::drawLine(uint16 _lineEnd, const String::TextBlocks::const_iterato
|
||||||
const auto color = (selected
|
const auto color = (selected
|
||||||
? _currentPenSelected
|
? _currentPenSelected
|
||||||
: _currentPen)->color();
|
: _currentPen)->color();
|
||||||
if (!_customEmojiSize) {
|
if (!_customEmojiContext) {
|
||||||
_customEmojiSize = AdjustCustomEmojiSize(st::emojiSize);
|
|
||||||
_customEmojiSkip = (st::emojiSize - _customEmojiSize) / 2;
|
|
||||||
_customEmojiContext = CustomEmoji::Context{
|
_customEmojiContext = CustomEmoji::Context{
|
||||||
.textColor = color,
|
.textColor = color,
|
||||||
.now = now(),
|
.now = now(),
|
||||||
.paused = _pausedEmoji,
|
.paused = _pausedEmoji,
|
||||||
};
|
};
|
||||||
|
_customEmojiSkip = (st::emojiSize
|
||||||
|
- AdjustCustomEmojiSize(st::emojiSize)) / 2;
|
||||||
} else {
|
} else {
|
||||||
_customEmojiContext->textColor = color;
|
_customEmojiContext->textColor = color;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,6 @@ private:
|
||||||
QVarLengthArray<QRect, kSpoilersRectsSize> _highlightRects;
|
QVarLengthArray<QRect, kSpoilersRectsSize> _highlightRects;
|
||||||
|
|
||||||
std::optional<CustomEmoji::Context> _customEmojiContext;
|
std::optional<CustomEmoji::Context> _customEmojiContext;
|
||||||
int _customEmojiSize = 0;
|
|
||||||
int _customEmojiSkip = 0;
|
int _customEmojiSkip = 0;
|
||||||
int _indexOfElidedBlock = -1; // For spoilers.
|
int _indexOfElidedBlock = -1; // For spoilers.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue