VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_graphics / fonts / juce_GlyphArrangement.h
blob3ec14752cd93ee83464e9e4b1b8c13d0d63e36be
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
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.
23 ==============================================================================
26 namespace juce
29 //==============================================================================
30 /**
31 A glyph from a particular font, with a particular size, style,
32 typeface and position.
34 You should rarely need to use this class directly - for most purposes, the
35 GlyphArrangement class will do what you need for text layout.
37 @see GlyphArrangement, Font
39 @tags{Graphics}
41 class JUCE_API PositionedGlyph final
43 public:
44 //==============================================================================
45 PositionedGlyph() noexcept;
47 PositionedGlyph (const Font& font, juce_wchar character, int glyphNumber,
48 float anchorX, float baselineY, float width, bool isWhitespace);
50 /** Returns the character the glyph represents. */
51 juce_wchar getCharacter() const noexcept { return character; }
52 /** Checks whether the glyph is actually empty. */
53 bool isWhitespace() const noexcept { return whitespace; }
55 /** Returns the position of the glyph's left-hand edge. */
56 float getLeft() const noexcept { return x; }
57 /** Returns the position of the glyph's right-hand edge. */
58 float getRight() const noexcept { return x + w; }
59 /** Returns the y position of the glyph's baseline. */
60 float getBaselineY() const noexcept { return y; }
61 /** Returns the y position of the top of the glyph. */
62 float getTop() const { return y - font.getAscent(); }
63 /** Returns the y position of the bottom of the glyph. */
64 float getBottom() const { return y + font.getDescent(); }
65 /** Returns the bounds of the glyph. */
66 Rectangle<float> getBounds() const { return { x, getTop(), w, font.getHeight() }; }
68 //==============================================================================
69 /** Shifts the glyph's position by a relative amount. */
70 void moveBy (float deltaX, float deltaY);
72 //==============================================================================
73 /** Draws the glyph into a graphics context.
74 (Note that this may change the context's currently selected font).
76 void draw (Graphics& g) const;
78 /** Draws the glyph into a graphics context, with an extra transform applied to it.
79 (Note that this may change the context's currently selected font).
81 void draw (Graphics& g, AffineTransform transform) const;
83 /** Returns the path for this glyph.
84 @param path the glyph's outline will be appended to this path
86 void createPath (Path& path) const;
88 /** Checks to see if a point lies within this glyph. */
89 bool hitTest (float x, float y) const;
91 private:
92 //==============================================================================
93 friend class GlyphArrangement;
94 Font font;
95 juce_wchar character;
96 int glyph;
97 float x, y, w;
98 bool whitespace;
100 JUCE_LEAK_DETECTOR (PositionedGlyph)
104 //==============================================================================
106 A set of glyphs, each with a position.
108 You can create a GlyphArrangement, text to it and then draw it onto a
109 graphics context. It's used internally by the text methods in the
110 Graphics class, but can be used directly if more control is needed.
112 @see Font, PositionedGlyph
114 @tags{Graphics}
116 class JUCE_API GlyphArrangement final
118 public:
119 //==============================================================================
120 /** Creates an empty arrangement. */
121 GlyphArrangement();
123 GlyphArrangement (const GlyphArrangement&) = default;
124 GlyphArrangement& operator= (const GlyphArrangement&) = default;
125 GlyphArrangement (GlyphArrangement&&) = default;
126 GlyphArrangement& operator= (GlyphArrangement&&) = default;
128 /** Destructor. */
129 ~GlyphArrangement() = default;
131 //==============================================================================
132 /** Returns the total number of glyphs in the arrangement. */
133 int getNumGlyphs() const noexcept { return glyphs.size(); }
135 /** Returns one of the glyphs from the arrangement.
137 @param index the glyph's index, from 0 to (getNumGlyphs() - 1). Be
138 careful not to pass an out-of-range index here, as it
139 doesn't do any bounds-checking.
141 PositionedGlyph& getGlyph (int index) noexcept;
143 const PositionedGlyph* begin() const { return glyphs.begin(); }
144 const PositionedGlyph* end() const { return glyphs.end(); }
146 //==============================================================================
147 /** Clears all text from the arrangement and resets it. */
148 void clear();
150 /** Appends a line of text to the arrangement.
152 This will add the text as a single line, where x is the left-hand edge of the
153 first character, and y is the position for the text's baseline.
155 If the text contains new-lines or carriage-returns, this will ignore them - use
156 addJustifiedText() to add multi-line arrangements.
158 void addLineOfText (const Font& font,
159 const String& text,
160 float x, float y);
162 /** Adds a line of text, truncating it if it's wider than a specified size.
164 This is the same as addLineOfText(), but if the line's width exceeds the value
165 specified in maxWidthPixels, it will be truncated using either ellipsis (i.e. dots: "..."),
166 if useEllipsis is true, or if this is false, it will just drop any subsequent characters.
168 void addCurtailedLineOfText (const Font& font,
169 const String& text,
170 float x, float y,
171 float maxWidthPixels,
172 bool useEllipsis);
174 /** Adds some multi-line text, breaking lines at word-boundaries if they are too wide.
176 This will add text to the arrangement, breaking it into new lines either where there
177 is a new-line or carriage-return character in the text, or where a line's width
178 exceeds the value set in maxLineWidth.
180 Each line that is added will be laid out using the flags set in horizontalLayout, so
181 the lines can be left- or right-justified, or centred horizontally in the space
182 between x and (x + maxLineWidth).
184 The y coordinate is the position of the baseline of the first line of text - subsequent
185 lines will be placed below it, separated by a distance of font.getHeight() + leading.
187 void addJustifiedText (const Font& font,
188 const String& text,
189 float x, float y,
190 float maxLineWidth,
191 Justification horizontalLayout,
192 float leading = 0.0f);
194 /** Tries to fit some text within a given space.
196 This does its best to make the given text readable within the specified rectangle,
197 so it's useful for labelling things.
199 If the text is too big, it'll be squashed horizontally or broken over multiple lines
200 if the maximumLinesToUse value allows this. If the text just won't fit into the space,
201 it'll cram as much as possible in there, and put some ellipsis at the end to show that
202 it's been truncated.
204 A Justification parameter lets you specify how the text is laid out within the rectangle,
205 both horizontally and vertically.
207 The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally
208 to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you
209 can set this value to 1.0f. Pass 0 if you want it to use the default value.
211 @see Graphics::drawFittedText
213 void addFittedText (const Font& font,
214 const String& text,
215 float x, float y, float width, float height,
216 Justification layout,
217 int maximumLinesToUse,
218 float minimumHorizontalScale = 0.0f);
220 /** Appends another glyph arrangement to this one. */
221 void addGlyphArrangement (const GlyphArrangement&);
223 /** Appends a custom glyph to the arrangement. */
224 void addGlyph (const PositionedGlyph&);
226 //==============================================================================
227 /** Draws this glyph arrangement to a graphics context.
229 This uses cached bitmaps so is much faster than the draw (Graphics&, AffineTransform)
230 method, which renders the glyphs as filled vectors.
232 void draw (const Graphics&) const;
234 /** Draws this glyph arrangement to a graphics context.
236 This renders the paths as filled vectors, so is far slower than the draw (Graphics&)
237 method for non-transformed arrangements.
239 void draw (const Graphics&, AffineTransform) const;
241 /** Converts the set of glyphs into a path.
242 @param path the glyphs' outlines will be appended to this path
244 void createPath (Path& path) const;
246 /** Looks for a glyph that contains the given coordinate.
247 @returns the index of the glyph, or -1 if none were found.
249 int findGlyphIndexAt (float x, float y) const;
251 //==============================================================================
252 /** Finds the smallest rectangle that will enclose a subset of the glyphs.
255 @param startIndex the first glyph to test
256 @param numGlyphs the number of glyphs to include; if this is < 0, all glyphs after
257 startIndex will be included
258 @param includeWhitespace if true, the extent of any whitespace characters will also
259 be taken into account
261 Rectangle<float> getBoundingBox (int startIndex, int numGlyphs, bool includeWhitespace) const;
263 /** Shifts a set of glyphs by a given amount.
265 @param startIndex the first glyph to transform
266 @param numGlyphs the number of glyphs to move; if this is < 0, all glyphs after
267 startIndex will be used
268 @param deltaX the amount to add to their x-positions
269 @param deltaY the amount to add to their y-positions
271 void moveRangeOfGlyphs (int startIndex, int numGlyphs,
272 float deltaX, float deltaY);
274 /** Removes a set of glyphs from the arrangement.
276 @param startIndex the first glyph to remove
277 @param numGlyphs the number of glyphs to remove; if this is < 0, all glyphs after
278 startIndex will be deleted
280 void removeRangeOfGlyphs (int startIndex, int numGlyphs);
282 /** Expands or compresses a set of glyphs horizontally.
284 @param startIndex the first glyph to transform
285 @param numGlyphs the number of glyphs to stretch; if this is < 0, all glyphs after
286 startIndex will be used
287 @param horizontalScaleFactor how much to scale their horizontal width by
289 void stretchRangeOfGlyphs (int startIndex, int numGlyphs,
290 float horizontalScaleFactor);
292 /** Justifies a set of glyphs within a given space.
294 This moves the glyphs as a block so that the whole thing is located within the
295 given rectangle with the specified layout.
297 If the Justification::horizontallyJustified flag is specified, each line will
298 be stretched out to fill the specified width.
300 void justifyGlyphs (int startIndex, int numGlyphs,
301 float x, float y, float width, float height,
302 Justification justification);
305 private:
306 //==============================================================================
307 Array<PositionedGlyph> glyphs;
309 int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex);
310 int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&,
311 Justification, float minimumHorizontalScale);
312 void spreadOutLine (int start, int numGlyphs, float targetWidth);
313 void splitLines (const String&, Font, int start, float x, float y, float w, float h, int maxLines,
314 float lineWidth, Justification, float minimumHorizontalScale);
315 void addLinesWithLineBreaks (const String&, const Font&, float x, float y, float width, float height, Justification);
316 void drawGlyphUnderline (const Graphics&, const PositionedGlyph&, int, AffineTransform) const;
318 JUCE_LEAK_DETECTOR (GlyphArrangement)
321 } // namespace juce