text_block.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "ui/text/text_block.h"
  8. #include "styles/style_basic.h"
  9. #include <private/qfontengine_p.h>
  10. namespace Ui {
  11. namespace Text {
  12. style::font WithFlags(
  13. const style::font &font,
  14. TextBlockFlags flags,
  15. style::FontFlags fontFlags) {
  16. using namespace style::internal;
  17. using Flag = style::FontFlag;
  18. if (!flags && !fontFlags) {
  19. return font;
  20. } else if (IsMono(flags) || (fontFlags & Flag::Monospace)) {
  21. return font->monospace();
  22. }
  23. auto result = font;
  24. if ((flags & TextBlockFlag::Bold) || (fontFlags & Flag::Bold)) {
  25. result = result->bold();
  26. } else if ((flags & TextBlockFlag::Semibold)
  27. || (fontFlags & Flag::Semibold)) {
  28. result = result->semibold();
  29. }
  30. if ((flags & TextBlockFlag::Italic) || (fontFlags & Flag::Italic)) {
  31. result = result->italic();
  32. }
  33. if ((flags & TextBlockFlag::Underline)
  34. || (fontFlags & Flag::Underline)) {
  35. result = result->underline();
  36. }
  37. if ((flags & TextBlockFlag::StrikeOut)
  38. || (fontFlags & Flag::StrikeOut)) {
  39. result = result->strikeout();
  40. }
  41. if (flags & TextBlockFlag::Tilde) { // Tilde fix in OpenSans.
  42. result = result->semibold();
  43. }
  44. return result;
  45. }
  46. Qt::LayoutDirection UnpackParagraphDirection(bool ltr, bool rtl) {
  47. return ltr
  48. ? Qt::LeftToRight
  49. : rtl
  50. ? Qt::RightToLeft
  51. : Qt::LayoutDirectionAuto;
  52. }
  53. AbstractBlock::AbstractBlock(TextBlockType type, BlockDescriptor descriptor)
  54. : _position(descriptor.position)
  55. , _type(static_cast<uint16>(type))
  56. , _flags(descriptor.flags)
  57. , _linkIndex(descriptor.linkIndex)
  58. , _colorIndex(descriptor.colorIndex) {
  59. }
  60. uint16 AbstractBlock::position() const {
  61. return _position;
  62. }
  63. TextBlockType AbstractBlock::type() const {
  64. return static_cast<TextBlockType>(_type);
  65. }
  66. TextBlockFlags AbstractBlock::flags() const {
  67. return TextBlockFlags::from_raw(_flags);
  68. }
  69. int AbstractBlock::objectWidth() const {
  70. switch (type()) {
  71. case TextBlockType::Emoji: return st::emojiSize + 2 * st::emojiPadding;
  72. case TextBlockType::CustomEmoji:
  73. return static_cast<const CustomEmojiBlock*>(this)->custom()->width();
  74. case TextBlockType::Skip:
  75. return static_cast<const SkipBlock*>(this)->width();
  76. }
  77. Unexpected("Type in AbstractBlock::objectWidth.");
  78. }
  79. uint16 AbstractBlock::linkIndex() const {
  80. return _linkIndex;
  81. }
  82. uint16 AbstractBlock::colorIndex() const {
  83. return _colorIndex;
  84. }
  85. void AbstractBlock::setLinkIndex(uint16 index) {
  86. _linkIndex = index;
  87. }
  88. TextBlock::TextBlock(BlockDescriptor descriptor)
  89. : AbstractBlock(TextBlockType::Text, descriptor) {
  90. }
  91. EmojiBlock::EmojiBlock(BlockDescriptor descriptor, EmojiPtr emoji)
  92. : AbstractBlock(TextBlockType::Emoji, descriptor)
  93. , _emoji(emoji) {
  94. }
  95. CustomEmojiBlock::CustomEmojiBlock(
  96. BlockDescriptor descriptor,
  97. std::unique_ptr<CustomEmoji> custom)
  98. : AbstractBlock(TextBlockType::CustomEmoji, descriptor)
  99. , _custom(std::move(custom)) {
  100. }
  101. NewlineBlock::NewlineBlock(BlockDescriptor descriptor, uint16 quoteIndex)
  102. : AbstractBlock(TextBlockType::Newline, descriptor)
  103. , _quoteIndex(quoteIndex) {
  104. }
  105. SkipBlock::SkipBlock(BlockDescriptor descriptor, int width, int height)
  106. : AbstractBlock(TextBlockType::Skip, descriptor)
  107. , _width(width)
  108. , _height(height) {
  109. }
  110. int SkipBlock::width() const {
  111. return _width;
  112. }
  113. int SkipBlock::height() const {
  114. return _height;
  115. }
  116. Block::Block() {
  117. Unexpected("Should not be called.");
  118. }
  119. Block::Block(Block &&other) {
  120. switch (other->type()) {
  121. case TextBlockType::Newline:
  122. emplace<NewlineBlock>(std::move(other.unsafe<NewlineBlock>()));
  123. break;
  124. case TextBlockType::Text:
  125. emplace<TextBlock>(std::move(other.unsafe<TextBlock>()));
  126. break;
  127. case TextBlockType::Emoji:
  128. emplace<EmojiBlock>(std::move(other.unsafe<EmojiBlock>()));
  129. break;
  130. case TextBlockType::CustomEmoji:
  131. emplace<CustomEmojiBlock>(
  132. std::move(other.unsafe<CustomEmojiBlock>()));
  133. break;
  134. case TextBlockType::Skip:
  135. emplace<SkipBlock>(std::move(other.unsafe<SkipBlock>()));
  136. break;
  137. default:
  138. Unexpected("Bad text block type in Block(Block&&).");
  139. }
  140. }
  141. Block &Block::operator=(Block &&other) {
  142. if (&other == this) {
  143. return *this;
  144. }
  145. destroy();
  146. switch (other->type()) {
  147. case TextBlockType::Newline:
  148. emplace<NewlineBlock>(std::move(other.unsafe<NewlineBlock>()));
  149. break;
  150. case TextBlockType::Text:
  151. emplace<TextBlock>(std::move(other.unsafe<TextBlock>()));
  152. break;
  153. case TextBlockType::Emoji:
  154. emplace<EmojiBlock>(std::move(other.unsafe<EmojiBlock>()));
  155. break;
  156. case TextBlockType::CustomEmoji:
  157. emplace<CustomEmojiBlock>(
  158. std::move(other.unsafe<CustomEmojiBlock>()));
  159. break;
  160. case TextBlockType::Skip:
  161. emplace<SkipBlock>(std::move(other.unsafe<SkipBlock>()));
  162. break;
  163. default:
  164. Unexpected("Bad text block type in operator=(Block&&).");
  165. }
  166. return *this;
  167. }
  168. Block::~Block() {
  169. destroy();
  170. }
  171. Block Block::Newline(BlockDescriptor descriptor, uint16 quoteIndex) {
  172. return New<NewlineBlock>(descriptor, quoteIndex);
  173. }
  174. Block Block::Text(BlockDescriptor descriptor) {
  175. return New<TextBlock>(descriptor);
  176. }
  177. Block Block::Emoji(BlockDescriptor descriptor, EmojiPtr emoji) {
  178. return New<EmojiBlock>(descriptor, emoji);
  179. }
  180. Block Block::CustomEmoji(
  181. BlockDescriptor descriptor,
  182. std::unique_ptr<Text::CustomEmoji> custom) {
  183. return New<CustomEmojiBlock>(descriptor, std::move(custom));
  184. }
  185. Block Block::Skip(BlockDescriptor descriptor, int width, int height) {
  186. return New<SkipBlock>(descriptor, width, height);
  187. }
  188. AbstractBlock *Block::get() {
  189. return &unsafe<AbstractBlock>();
  190. }
  191. const AbstractBlock *Block::get() const {
  192. return &unsafe<AbstractBlock>();
  193. }
  194. AbstractBlock *Block::operator->() {
  195. return get();
  196. }
  197. const AbstractBlock *Block::operator->() const {
  198. return get();
  199. }
  200. AbstractBlock &Block::operator*() {
  201. return *get();
  202. }
  203. const AbstractBlock &Block::operator*() const {
  204. return *get();
  205. }
  206. void Block::destroy() {
  207. switch (get()->type()) {
  208. case TextBlockType::Newline:
  209. unsafe<NewlineBlock>().~NewlineBlock();
  210. break;
  211. case TextBlockType::Text:
  212. unsafe<TextBlock>().~TextBlock();
  213. break;
  214. case TextBlockType::Emoji:
  215. unsafe<EmojiBlock>().~EmojiBlock();
  216. break;
  217. case TextBlockType::CustomEmoji:
  218. unsafe<CustomEmojiBlock>().~CustomEmojiBlock();
  219. break;
  220. case TextBlockType::Skip:
  221. unsafe<SkipBlock>().~SkipBlock();
  222. break;
  223. default:
  224. Unexpected("Bad text block type in Block(Block&&).");
  225. }
  226. }
  227. int CountBlockHeight(
  228. const AbstractBlock *block,
  229. const style::TextStyle *st) {
  230. return (block->type() == TextBlockType::Skip)
  231. ? static_cast<const SkipBlock*>(block)->height()
  232. : st->lineHeight
  233. ? st->lineHeight
  234. : st->font->height;
  235. }
  236. } // namespace Text
  237. } // namespace Ui