diff --git a/ui/text/text_block.cpp b/ui/text/text_block.cpp index 1e344e0..f862dfb 100644 --- a/ui/text/text_block.cpp +++ b/ui/text/text_block.cpp @@ -446,6 +446,10 @@ TextBlock::TextBlock( } } +QFixed TextBlock::real_f_rbearing() const { + return _words.isEmpty() ? 0 : _words.back().f_rbearing(); +} + EmojiBlock::EmojiBlock( const style::font &font, const QString &str, @@ -470,5 +474,279 @@ EmojiBlock::EmojiBlock( } } +NewlineBlock::NewlineBlock( + const style::font &font, + const QString &str, + uint16 from, + uint16 length, + uchar flags, + uint16 lnkIndex, + uint16 spoilerIndex) +: AbstractBlock(font, str, from, length, flags, lnkIndex, spoilerIndex) { + _flags |= ((TextBlockTNewline & 0x0F) << 8); +} + +Qt::LayoutDirection NewlineBlock::nextDirection() const { + return _nextDir; +} + +SkipBlock::SkipBlock( + const style::font &font, + const QString &str, + uint16 from, + int32 w, + int32 h, + uint16 lnkIndex, + uint16 spoilerIndex) +: AbstractBlock(font, str, from, 1, 0, lnkIndex, spoilerIndex) +, _height(h) { + _flags |= ((TextBlockTSkip & 0x0F) << 8); + _width = w; +} + +int SkipBlock::height() const { + return _height; +} + + +TextWord::TextWord( + uint16 from, + QFixed width, + QFixed rbearing, + QFixed rpadding) +: _from(from) +, _rbearing((rbearing.value() > 0x7FFF) + ? 0x7FFF + : (rbearing.value() < -0x7FFF ? -0x7FFF : rbearing.value())) +, _width(width) +, _rpadding(rpadding) { +} + +uint16 TextWord::from() const { + return _from; +} + +QFixed TextWord::f_rbearing() const { + return QFixed::fromFixed(_rbearing); +} + +QFixed TextWord::f_width() const { + return _width; +} + +QFixed TextWord::f_rpadding() const { + return _rpadding; +} + +void TextWord::add_rpadding(QFixed padding) { + _rpadding += padding; +} + +Block::Block() { + Unexpected("Should not be called."); +} + +Block::Block(const Block &other) { + switch (other->type()) { + case TextBlockTNewline: + emplace(other.unsafe()); + break; + case TextBlockTText: + emplace(other.unsafe()); + break; + case TextBlockTEmoji: + emplace(other.unsafe()); + break; + case TextBlockTSkip: + emplace(other.unsafe()); + break; + default: + Unexpected("Bad text block type in Block(const Block&)."); + } +} + +Block::Block(Block &&other) { + switch (other->type()) { + case TextBlockTNewline: + emplace(std::move(other.unsafe())); + break; + case TextBlockTText: + emplace(std::move(other.unsafe())); + break; + case TextBlockTEmoji: + emplace(std::move(other.unsafe())); + break; + case TextBlockTSkip: + emplace(std::move(other.unsafe())); + break; + default: + Unexpected("Bad text block type in Block(Block&&)."); + } +} + +Block &Block::operator=(const Block &other) { + if (&other == this) { + return *this; + } + destroy(); + switch (other->type()) { + case TextBlockTNewline: + emplace(other.unsafe()); + break; + case TextBlockTText: + emplace(other.unsafe()); + break; + case TextBlockTEmoji: + emplace(other.unsafe()); + break; + case TextBlockTSkip: + emplace(other.unsafe()); + break; + default: + Unexpected("Bad text block type in operator=(const Block&)."); + } + return *this; +} + +Block &Block::operator=(Block &&other) { + if (&other == this) { + return *this; + } + destroy(); + switch (other->type()) { + case TextBlockTNewline: + emplace(std::move(other.unsafe())); + break; + case TextBlockTText: + emplace(std::move(other.unsafe())); + break; + case TextBlockTEmoji: + emplace(std::move(other.unsafe())); + break; + case TextBlockTSkip: + emplace(std::move(other.unsafe())); + break; + default: + Unexpected("Bad text block type in operator=(Block&&)."); + } + return *this; +} + +Block::~Block() { + destroy(); +} + +Block Block::Newline( + const style::font &font, + const QString &str, + uint16 from, + uint16 length, + uchar flags, + uint16 lnkIndex, + uint16 spoilerIndex) { + return New( + font, + str, + from, + length, + flags, + lnkIndex, + spoilerIndex); +} + +Block Block::Text( + const style::font &font, + const QString &str, + QFixed minResizeWidth, + uint16 from, + uint16 length, + uchar flags, + uint16 lnkIndex, + uint16 spoilerIndex) { + return New( + font, + str, + minResizeWidth, + from, + length, + flags, + lnkIndex, + spoilerIndex); +} + +Block Block::Emoji( + const style::font &font, + const QString &str, + uint16 from, + uint16 length, + uchar flags, + uint16 lnkIndex, + uint16 spoilerIndex, + EmojiPtr emoji) { + return New( + font, + str, + from, + length, + flags, + lnkIndex, + spoilerIndex, + emoji); +} + +Block Block::Skip( + const style::font &font, + const QString &str, + uint16 from, + int32 w, + int32 h, + uint16 lnkIndex, + uint16 spoilerIndex) { + return New(font, str, from, w, h, lnkIndex, spoilerIndex); +} + +AbstractBlock *Block::get() { + return &unsafe(); +} + +const AbstractBlock *Block::get() const { + return &unsafe(); +} + +AbstractBlock *Block::operator->() { + return get(); +} + +const AbstractBlock *Block::operator->() const { + return get(); +} + +AbstractBlock &Block::operator*() { + return *get(); +} + +const AbstractBlock &Block::operator*() const { + return *get(); +} + +void Block::destroy() { + switch (get()->type()) { + case TextBlockTNewline: + unsafe().~NewlineBlock(); + break; + case TextBlockTText: + unsafe().~TextBlock(); + break; + case TextBlockTEmoji: + unsafe().~EmojiBlock(); + break; + case TextBlockTSkip: + unsafe().~SkipBlock(); + break; + default: + Unexpected("Bad text block type in Block(Block&&)."); + } +} + } // namespace Text } // namespace Ui diff --git a/ui/text/text_block.h b/ui/text/text_block.h index e1a6534..b57075b 100644 --- a/ui/text/text_block.h +++ b/ui/text/text_block.h @@ -88,14 +88,9 @@ public: uint16 length, uchar flags, uint16 lnkIndex, - uint16 spoilerIndex) - : AbstractBlock(font, str, from, length, flags, lnkIndex, spoilerIndex) { - _flags |= ((TextBlockTNewline & 0x0F) << 8); - } + uint16 spoilerIndex); - Qt::LayoutDirection nextDirection() const { - return _nextDir; - } + Qt::LayoutDirection nextDirection() const; private: Qt::LayoutDirection _nextDir = Qt::LayoutDirectionAuto; @@ -109,29 +104,12 @@ private: class TextWord final { public: TextWord() = default; - TextWord(uint16 from, QFixed width, QFixed rbearing, QFixed rpadding = 0) - : _from(from) - , _rbearing((rbearing.value() > 0x7FFF) - ? 0x7FFF - : (rbearing.value() < -0x7FFF ? -0x7FFF : rbearing.value())) - , _width(width) - , _rpadding(rpadding) { - } - uint16 from() const { - return _from; - } - QFixed f_rbearing() const { - return QFixed::fromFixed(_rbearing); - } - QFixed f_width() const { - return _width; - } - QFixed f_rpadding() const { - return _rpadding; - } - void add_rpadding(QFixed padding) { - _rpadding += padding; - } + TextWord(uint16 from, QFixed width, QFixed rbearing, QFixed rpadding = 0); + uint16 from() const; + QFixed f_rbearing() const; + QFixed f_width() const; + QFixed f_rpadding() const; + void add_rpadding(QFixed padding); private: uint16 _from = 0; @@ -153,9 +131,7 @@ public: uint16 spoilerIndex); private: - QFixed real_f_rbearing() const { - return _words.isEmpty() ? 0 : _words.back().f_rbearing(); - } + QFixed real_f_rbearing() const; QVector _words; @@ -197,16 +173,9 @@ public: int32 w, int32 h, uint16 lnkIndex, - uint16 spoilerIndex) - : AbstractBlock(font, str, from, 1, 0, lnkIndex, spoilerIndex) - , _height(h) { - _flags |= ((TextBlockTSkip & 0x0F) << 8); - _width = w; - } + uint16 spoilerIndex); - int height() const { - return _height; - } + int height() const; private: int _height = 0; @@ -219,94 +188,12 @@ private: class Block final { public: - Block() { - Unexpected("Should not be called."); - } - Block(const Block &other) { - switch (other->type()) { - case TextBlockTNewline: - emplace(other.unsafe()); - break; - case TextBlockTText: - emplace(other.unsafe()); - break; - case TextBlockTEmoji: - emplace(other.unsafe()); - break; - case TextBlockTSkip: - emplace(other.unsafe()); - break; - default: - Unexpected("Bad text block type in Block(const Block&)."); - } - } - Block(Block &&other) { - switch (other->type()) { - case TextBlockTNewline: - emplace(std::move(other.unsafe())); - break; - case TextBlockTText: - emplace(std::move(other.unsafe())); - break; - case TextBlockTEmoji: - emplace(std::move(other.unsafe())); - break; - case TextBlockTSkip: - emplace(std::move(other.unsafe())); - break; - default: - Unexpected("Bad text block type in Block(Block&&)."); - } - } - Block &operator=(const Block &other) { - if (&other == this) { - return *this; - } - destroy(); - switch (other->type()) { - case TextBlockTNewline: - emplace(other.unsafe()); - break; - case TextBlockTText: - emplace(other.unsafe()); - break; - case TextBlockTEmoji: - emplace(other.unsafe()); - break; - case TextBlockTSkip: - emplace(other.unsafe()); - break; - default: - Unexpected("Bad text block type in operator=(const Block&)."); - } - return *this; - } - Block &operator=(Block &&other) { - if (&other == this) { - return *this; - } - destroy(); - switch (other->type()) { - case TextBlockTNewline: - emplace(std::move(other.unsafe())); - break; - case TextBlockTText: - emplace(std::move(other.unsafe())); - break; - case TextBlockTEmoji: - emplace(std::move(other.unsafe())); - break; - case TextBlockTSkip: - emplace(std::move(other.unsafe())); - break; - default: - Unexpected("Bad text block type in operator=(Block&&)."); - } - return *this; - } - ~Block() { - destroy(); - } + Block(); + Block(const Block &other); + Block(Block &&other); + Block &operator=(const Block &other); + Block &operator=(Block &&other); + ~Block(); [[nodiscard]] static Block Newline( const style::font &font, @@ -315,9 +202,7 @@ public: uint16 length, uchar flags, uint16 lnkIndex, - uint16 spoilerIndex) { - return New(font, str, from, length, flags, lnkIndex, spoilerIndex); - } + uint16 spoilerIndex); [[nodiscard]] static Block Text( const style::font &font, @@ -327,17 +212,7 @@ public: uint16 length, uchar flags, uint16 lnkIndex, - uint16 spoilerIndex) { - return New( - font, - str, - minResizeWidth, - from, - length, - flags, - lnkIndex, - spoilerIndex); - } + uint16 spoilerIndex); [[nodiscard]] static Block Emoji( const style::font &font, @@ -347,17 +222,7 @@ public: uchar flags, uint16 lnkIndex, uint16 spoilerIndex, - EmojiPtr emoji) { - return New( - font, - str, - from, - length, - flags, - lnkIndex, - spoilerIndex, - emoji); - } + EmojiPtr emoji); [[nodiscard]] static Block Skip( const style::font &font, @@ -366,9 +231,7 @@ public: int32 w, int32 h, uint16 lnkIndex, - uint16 spoilerIndex) { - return New(font, str, from, w, h, lnkIndex, spoilerIndex); - } + uint16 spoilerIndex); template [[nodiscard]] FinalBlock &unsafe() { @@ -380,29 +243,14 @@ public: return *reinterpret_cast(&_data); } - [[nodiscard]] AbstractBlock *get() { - return &unsafe(); - } + [[nodiscard]] AbstractBlock *get(); + [[nodiscard]] const AbstractBlock *get() const; - [[nodiscard]] const AbstractBlock *get() const { - return &unsafe(); - } + [[nodiscard]] AbstractBlock *operator->(); + [[nodiscard]] const AbstractBlock *operator->() const; - [[nodiscard]] AbstractBlock *operator->() { - return get(); - } - - [[nodiscard]] const AbstractBlock *operator->() const { - return get(); - } - - [[nodiscard]] AbstractBlock &operator*() { - return *get(); - } - - [[nodiscard]] const AbstractBlock &operator*() const { - return *get(); - } + [[nodiscard]] AbstractBlock &operator*(); + [[nodiscard]] const AbstractBlock &operator*() const; private: struct Tag { @@ -423,24 +271,7 @@ private: new (&_data) FinalType(std::forward(args)...); } - void destroy() { - switch (get()->type()) { - case TextBlockTNewline: - unsafe().~NewlineBlock(); - break; - case TextBlockTText: - unsafe().~TextBlock(); - break; - case TextBlockTEmoji: - unsafe().~EmojiBlock(); - break; - case TextBlockTSkip: - unsafe().~SkipBlock(); - break; - default: - Unexpected("Bad text block type in Block(Block&&)."); - } - } + void destroy(); static_assert(sizeof(NewlineBlock) <= sizeof(TextBlock)); static_assert(alignof(NewlineBlock) <= alignof(void*));