text_renderer.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #pragma once
  8. #include "ui/text/text.h"
  9. #include "ui/text/text_block.h"
  10. #include "ui/text/text_custom_emoji.h"
  11. #include <private/qtextengine_p.h>
  12. class QTextItemInt;
  13. struct QScriptAnalysis;
  14. struct QScriptLine;
  15. struct QScriptItem;
  16. namespace Ui::Text {
  17. inline constexpr auto kQuoteCollapsedLines = 3;
  18. class AbstractBlock;
  19. struct FixedRange {
  20. QFixed from;
  21. QFixed till;
  22. [[nodiscard]] bool empty() const {
  23. return (till <= from);
  24. }
  25. };
  26. [[nodiscard]] FixedRange Intersected(FixedRange a, FixedRange b);
  27. [[nodiscard]] bool Intersects(FixedRange a, FixedRange b);
  28. [[nodiscard]] FixedRange United(FixedRange a, FixedRange b);
  29. [[nodiscard]] bool Distinct(FixedRange a, FixedRange b);
  30. class Renderer final {
  31. public:
  32. explicit Renderer(const Ui::Text::String &t);
  33. ~Renderer();
  34. void draw(QPainter &p, const PaintContext &context);
  35. [[nodiscard]] StateResult getState(
  36. QPoint point,
  37. GeometryDescriptor geometry,
  38. StateRequest request);
  39. private:
  40. static constexpr int kSpoilersRectsSize = 512;
  41. struct BidiControl;
  42. void enumerate();
  43. [[nodiscard]] crl::time now() const;
  44. void initNextParagraph(
  45. Blocks::const_iterator i,
  46. int16 paragraphIndex,
  47. Qt::LayoutDirection direction);
  48. void initNextLine();
  49. void initParagraphBidi();
  50. bool drawLine(
  51. uint16 lineEnd,
  52. Blocks::const_iterator blocksEnd);
  53. [[nodiscard]] FixedRange findSelectEmojiRange(
  54. const QScriptItem &si,
  55. std::vector<Block>::const_iterator blockIt,
  56. QFixed x,
  57. TextSelection selection) const;
  58. [[nodiscard]] FixedRange findSelectTextRange(
  59. const QScriptItem &si,
  60. int itemStart,
  61. int itemEnd,
  62. QFixed x,
  63. QFixed itemWidth,
  64. const QTextItemInt &gf,
  65. TextSelection selection) const;
  66. void fillSelectRange(FixedRange range);
  67. void pushHighlightRange(FixedRange range);
  68. void pushSpoilerRange(
  69. FixedRange range,
  70. FixedRange selected,
  71. bool isElidedItem,
  72. bool rtl);
  73. void fillRectsFromRanges();
  74. void fillRectsFromRanges(
  75. QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
  76. QVarLengthArray<FixedRange> &ranges);
  77. void paintSpoilerRects();
  78. void paintSpoilerRects(
  79. const QVarLengthArray<QRect, kSpoilersRectsSize> &rects,
  80. const style::color &color,
  81. int index);
  82. void composeHighlightPath();
  83. [[nodiscard]] const AbstractBlock *markBlockForElisionGetEnd(
  84. int blockIndex);
  85. void setElideBidi(int elideStart);
  86. void prepareElidedLine(
  87. QString &lineText,
  88. int lineStart,
  89. int &lineLength,
  90. const AbstractBlock *&endBlock,
  91. int recursed = 0);
  92. void prepareElisionAt(
  93. QString &lineText,
  94. int &lineLength,
  95. uint16 position);
  96. void restoreAfterElided();
  97. void fillParagraphBg(int paddingBottom);
  98. void applyBlockProperties(
  99. QTextEngine &e,
  100. not_null<const AbstractBlock*> block);
  101. [[nodiscard]] ClickHandlerPtr lookupLink(
  102. const AbstractBlock *block) const;
  103. const String *_t = nullptr;
  104. GeometryDescriptor _geometry;
  105. SpoilerData *_spoiler = nullptr;
  106. SpoilerMessCache *_spoilerCache = nullptr;
  107. QPainter *_p = nullptr;
  108. const style::TextPalette *_palette = nullptr;
  109. std::span<SpecialColor> _colors;
  110. bool _pausedEmoji = false;
  111. bool _pausedSpoiler = false;
  112. style::align _align = style::al_topleft;
  113. QPen _originalPen;
  114. QPen _originalPenSelected;
  115. QPen _quoteLinkPenOverride;
  116. const QPen *_currentPen = nullptr;
  117. const QPen *_currentPenSelected = nullptr;
  118. struct {
  119. bool spoiler = false;
  120. bool selectActiveBlock = false; // For monospace.
  121. } _background;
  122. int _yFrom = 0;
  123. int _yTo = 0;
  124. TextSelection _selection = { 0, 0 };
  125. bool _fullWidthSelection = true;
  126. HighlightInfoRequest *_highlight = nullptr;
  127. const QChar *_str = nullptr;
  128. mutable crl::time _cachedNow = 0;
  129. float64 _spoilerOpacity = 0.;
  130. QVarLengthArray<FixedRange> _spoilerRanges;
  131. QVarLengthArray<FixedRange> _spoilerSelectedRanges;
  132. QVarLengthArray<FixedRange> _highlightRanges;
  133. QVarLengthArray<QRect, kSpoilersRectsSize> _spoilerRects;
  134. QVarLengthArray<QRect, kSpoilersRectsSize> _spoilerSelectedRects;
  135. QVarLengthArray<QRect, kSpoilersRectsSize> _highlightRects;
  136. std::optional<CustomEmoji::Context> _customEmojiContext;
  137. int _customEmojiSkip = 0;
  138. int _indexOfElidedBlock = -1; // For spoilers.
  139. // current paragraph data
  140. Blocks::const_iterator _paragraphStartBlock;
  141. Qt::LayoutDirection _paragraphDirection = Qt::LayoutDirectionAuto;
  142. int _paragraphStart = 0;
  143. int _paragraphLength = 0;
  144. QVarLengthArray<QScriptAnalysis, 4096> _paragraphAnalysis;
  145. // current quote data
  146. QuoteDetails *_quote = nullptr;
  147. Qt::LayoutDirection _quoteDirection = Qt::LayoutDirectionAuto;
  148. int _quoteShift = 0;
  149. int _quoteIndex = 0;
  150. QMargins _quotePadding;
  151. int _quoteLinesLeft = -1;
  152. int _quoteTop = 0;
  153. int _quoteLineTop = 0;
  154. QuotePaintCache *_quotePreCache = nullptr;
  155. QuotePaintCache *_quoteBlockquoteCache = nullptr;
  156. bool _quotePreValid = false;
  157. bool _quoteBlockquoteValid = false;
  158. ClickHandlerPtr _quoteExpandLink;
  159. bool _quoteExpandLinkLookup = false;
  160. // current line data
  161. style::font _f;
  162. int _startLeft = 0;
  163. int _startTop = 0;
  164. int _startLineWidth = 0;
  165. QFixed _x, _wLeft, _last_rPadding;
  166. int _y = 0;
  167. int _yDelta = 0;
  168. int _lineIndex = 0;
  169. int _lineHeight = 0;
  170. int _fontHeight = 0;
  171. bool _breakEverywhere = false;
  172. bool _elidedLine = false;
  173. // elided hack support
  174. int _blocksSize = 0;
  175. int _elideSavedIndex = 0;
  176. std::optional<Block> _elideSavedBlock;
  177. int _lineStart = 0;
  178. int _localFrom = 0;
  179. int _lineStartBlock = 0;
  180. QFixed _lineStartPadding = 0;
  181. QFixed _lineWidth = 0;
  182. // link and symbol resolve
  183. QFixed _lookupX = 0;
  184. int _lookupY = 0;
  185. bool _lookupSymbol = false;
  186. bool _lookupLink = false;
  187. StateRequest _lookupRequest;
  188. StateResult _lookupResult;
  189. bool _elisionMiddle = false;
  190. };
  191. } // namespace Ui::Text