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