Moved out all block implementations from header file.

This commit is contained in:
23rd 2022-01-06 19:38:41 +03:00
parent c9a9751472
commit 8e999fe8fb
2 changed files with 306 additions and 197 deletions

View file

@ -446,6 +446,10 @@ TextBlock::TextBlock(
} }
} }
QFixed TextBlock::real_f_rbearing() const {
return _words.isEmpty() ? 0 : _words.back().f_rbearing();
}
EmojiBlock::EmojiBlock( EmojiBlock::EmojiBlock(
const style::font &font, const style::font &font,
const QString &str, 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<NewlineBlock>(other.unsafe<NewlineBlock>());
break;
case TextBlockTText:
emplace<TextBlock>(other.unsafe<TextBlock>());
break;
case TextBlockTEmoji:
emplace<EmojiBlock>(other.unsafe<EmojiBlock>());
break;
case TextBlockTSkip:
emplace<SkipBlock>(other.unsafe<SkipBlock>());
break;
default:
Unexpected("Bad text block type in Block(const Block&).");
}
}
Block::Block(Block &&other) {
switch (other->type()) {
case TextBlockTNewline:
emplace<NewlineBlock>(std::move(other.unsafe<NewlineBlock>()));
break;
case TextBlockTText:
emplace<TextBlock>(std::move(other.unsafe<TextBlock>()));
break;
case TextBlockTEmoji:
emplace<EmojiBlock>(std::move(other.unsafe<EmojiBlock>()));
break;
case TextBlockTSkip:
emplace<SkipBlock>(std::move(other.unsafe<SkipBlock>()));
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<NewlineBlock>(other.unsafe<NewlineBlock>());
break;
case TextBlockTText:
emplace<TextBlock>(other.unsafe<TextBlock>());
break;
case TextBlockTEmoji:
emplace<EmojiBlock>(other.unsafe<EmojiBlock>());
break;
case TextBlockTSkip:
emplace<SkipBlock>(other.unsafe<SkipBlock>());
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<NewlineBlock>(std::move(other.unsafe<NewlineBlock>()));
break;
case TextBlockTText:
emplace<TextBlock>(std::move(other.unsafe<TextBlock>()));
break;
case TextBlockTEmoji:
emplace<EmojiBlock>(std::move(other.unsafe<EmojiBlock>()));
break;
case TextBlockTSkip:
emplace<SkipBlock>(std::move(other.unsafe<SkipBlock>()));
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<NewlineBlock>(
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<TextBlock>(
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<EmojiBlock>(
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<SkipBlock>(font, str, from, w, h, lnkIndex, spoilerIndex);
}
AbstractBlock *Block::get() {
return &unsafe<AbstractBlock>();
}
const AbstractBlock *Block::get() const {
return &unsafe<AbstractBlock>();
}
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>().~NewlineBlock();
break;
case TextBlockTText:
unsafe<TextBlock>().~TextBlock();
break;
case TextBlockTEmoji:
unsafe<EmojiBlock>().~EmojiBlock();
break;
case TextBlockTSkip:
unsafe<SkipBlock>().~SkipBlock();
break;
default:
Unexpected("Bad text block type in Block(Block&&).");
}
}
} // namespace Text } // namespace Text
} // namespace Ui } // namespace Ui

View file

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