juce_TextLayout.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. namespace juce
  20. {
  21. //==============================================================================
  22. /**
  23. A Pre-formatted piece of text, which may contain multiple fonts and colours.
  24. A TextLayout is created from an AttributedString, and once created can be
  25. quickly drawn into a Graphics context.
  26. @see AttributedString
  27. @tags{Graphics}
  28. */
  29. class JUCE_API TextLayout final
  30. {
  31. private:
  32. template <typename Iterator>
  33. class DereferencingIterator
  34. {
  35. public:
  36. using value_type = typename std::remove_reference<decltype(**std::declval<Iterator>())>::type;
  37. using difference_type = typename std::iterator_traits<Iterator>::difference_type;
  38. using pointer = value_type*;
  39. using reference = value_type&;
  40. using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
  41. explicit DereferencingIterator (Iterator in) : iterator (std::move (in)) {}
  42. DereferencingIterator& operator+= (difference_type distance)
  43. {
  44. iterator += distance;
  45. return *this;
  46. }
  47. friend DereferencingIterator operator+ (DereferencingIterator i, difference_type d) { return i += d; }
  48. friend DereferencingIterator operator+ (difference_type d, DereferencingIterator i) { return i += d; }
  49. DereferencingIterator& operator-= (difference_type distance)
  50. {
  51. iterator -= distance;
  52. return *this;
  53. }
  54. friend DereferencingIterator operator- (DereferencingIterator i, difference_type d) { return i -= d; }
  55. friend difference_type operator- (DereferencingIterator a, DereferencingIterator b) { return a.iterator - b.iterator; }
  56. reference operator[] (difference_type d) const { return *iterator[d]; }
  57. friend bool operator< (DereferencingIterator a, DereferencingIterator b) { return a.iterator < b.iterator; }
  58. friend bool operator<= (DereferencingIterator a, DereferencingIterator b) { return a.iterator <= b.iterator; }
  59. friend bool operator> (DereferencingIterator a, DereferencingIterator b) { return a.iterator > b.iterator; }
  60. friend bool operator>= (DereferencingIterator a, DereferencingIterator b) { return a.iterator >= b.iterator; }
  61. friend bool operator== (DereferencingIterator a, DereferencingIterator b) { return a.iterator == b.iterator; }
  62. friend bool operator!= (DereferencingIterator a, DereferencingIterator b) { return a.iterator != b.iterator; }
  63. DereferencingIterator& operator++() { ++iterator; return *this; }
  64. DereferencingIterator& operator--() { --iterator; return *this; }
  65. DereferencingIterator operator++ (int) const { DereferencingIterator copy (*this); ++(*this); return copy; }
  66. DereferencingIterator operator-- (int) const { DereferencingIterator copy (*this); --(*this); return copy; }
  67. reference operator* () const { return **iterator; }
  68. pointer operator->() const { return *iterator; }
  69. private:
  70. Iterator iterator;
  71. };
  72. public:
  73. /** Creates an empty layout.
  74. Having created a TextLayout, you can populate it using createLayout() or
  75. createLayoutWithBalancedLineLengths().
  76. */
  77. TextLayout();
  78. TextLayout (const TextLayout&);
  79. TextLayout& operator= (const TextLayout&);
  80. TextLayout (TextLayout&&) noexcept;
  81. TextLayout& operator= (TextLayout&&) noexcept;
  82. /** Destructor. */
  83. ~TextLayout();
  84. //==============================================================================
  85. /** Creates a layout from the given attributed string.
  86. This will replace any data that is currently stored in the layout.
  87. */
  88. void createLayout (const AttributedString&, float maxWidth);
  89. /** Creates a layout from the given attributed string, given some size constraints.
  90. This will replace any data that is currently stored in the layout.
  91. */
  92. void createLayout (const AttributedString&, float maxWidth, float maxHeight);
  93. /** Creates a layout, attempting to choose a width which results in lines
  94. of a similar length.
  95. This will be slower than the normal createLayout method, but produces a
  96. tidier result.
  97. */
  98. void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth);
  99. /** Creates a layout, attempting to choose a width which results in lines
  100. of a similar length.
  101. This will be slower than the normal createLayout method, but produces a
  102. tidier result.
  103. */
  104. void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth, float maxHeight);
  105. /** Draws the layout within the specified area.
  106. The position of the text within the rectangle is controlled by the justification
  107. flags set in the original AttributedString that was used to create this layout.
  108. */
  109. void draw (Graphics&, Rectangle<float> area) const;
  110. //==============================================================================
  111. /** A positioned glyph. */
  112. class JUCE_API Glyph
  113. {
  114. public:
  115. Glyph (int glyphCode, Point<float> anchor, float width) noexcept;
  116. Glyph (const Glyph&) noexcept;
  117. Glyph& operator= (const Glyph&) noexcept;
  118. ~Glyph() noexcept;
  119. /** The code number of this glyph. */
  120. int glyphCode;
  121. /** The glyph's anchor point - this is relative to the line's origin.
  122. @see TextLayout::Line::lineOrigin
  123. */
  124. Point<float> anchor;
  125. float width;
  126. private:
  127. JUCE_LEAK_DETECTOR (Glyph)
  128. };
  129. //==============================================================================
  130. /** A sequence of glyphs with a common font and colour. */
  131. class JUCE_API Run
  132. {
  133. public:
  134. Run() noexcept;
  135. Run (const Run&);
  136. Run (Range<int> stringRange, int numGlyphsToPreallocate);
  137. ~Run() noexcept;
  138. /** Returns the X position range which contains all the glyphs in this run. */
  139. Range<float> getRunBoundsX() const noexcept;
  140. Font font; /**< The run's font. */
  141. Colour colour; /**< The run's colour. */
  142. Array<Glyph> glyphs; /**< The glyphs in this run. */
  143. Range<int> stringRange; /**< The character range that this run represents in the
  144. original string that was used to create it. */
  145. private:
  146. Run& operator= (const Run&);
  147. JUCE_LEAK_DETECTOR (Run)
  148. };
  149. //==============================================================================
  150. /** A line containing a sequence of glyph-runs. */
  151. class JUCE_API Line
  152. {
  153. public:
  154. Line() noexcept;
  155. Line (const Line&);
  156. Line (Range<int> stringRange, Point<float> lineOrigin,
  157. float ascent, float descent, float leading, int numRunsToPreallocate);
  158. ~Line() noexcept;
  159. /** Returns the X position range which contains all the glyphs in this line. */
  160. Range<float> getLineBoundsX() const noexcept;
  161. /** Returns the Y position range which contains all the glyphs in this line. */
  162. Range<float> getLineBoundsY() const noexcept;
  163. /** Returns the smallest rectangle which contains all the glyphs in this line. */
  164. Rectangle<float> getLineBounds() const noexcept;
  165. OwnedArray<Run> runs; /**< The glyph-runs in this line. */
  166. Range<int> stringRange; /**< The character range that this line represents in the
  167. original string that was used to create it. */
  168. Point<float> lineOrigin; /**< The line's baseline origin. */
  169. float ascent, descent, leading;
  170. private:
  171. Line& operator= (const Line&);
  172. JUCE_LEAK_DETECTOR (Line)
  173. };
  174. //==============================================================================
  175. /** Returns the maximum width of the content. */
  176. float getWidth() const noexcept { return width; }
  177. /** Returns the maximum height of the content. */
  178. float getHeight() const noexcept { return height; }
  179. /** Returns the number of lines in the layout. */
  180. int getNumLines() const noexcept { return lines.size(); }
  181. /** Returns one of the lines. */
  182. Line& getLine (int index) const noexcept;
  183. /** Adds a line to the layout. The layout will take ownership of this line object
  184. and will delete it when it is no longer needed. */
  185. void addLine (std::unique_ptr<Line>);
  186. /** Pre-allocates space for the specified number of lines. */
  187. void ensureStorageAllocated (int numLinesNeeded);
  188. using iterator = DereferencingIterator< Line* const*>;
  189. using const_iterator = DereferencingIterator<const Line* const*>;
  190. /** Returns an iterator over the lines of content */
  191. iterator begin() { return iterator (lines.begin()); }
  192. const_iterator begin() const { return const_iterator (lines.begin()); }
  193. const_iterator cbegin() const { return const_iterator (lines.begin()); }
  194. /** Returns an iterator over the lines of content */
  195. iterator end() { return iterator (lines.end()); }
  196. const_iterator end() const { return const_iterator (lines.end()); }
  197. const_iterator cend() const { return const_iterator (lines.end()); }
  198. /** If you modify the TextLayout after creating it, call this to compute
  199. the new dimensions of the content.
  200. */
  201. void recalculateSize();
  202. private:
  203. OwnedArray<Line> lines;
  204. float width, height;
  205. Justification justification;
  206. void createStandardLayout (const AttributedString&);
  207. bool createNativeLayout (const AttributedString&);
  208. JUCE_LEAK_DETECTOR (TextLayout)
  209. };
  210. } // namespace juce