JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_GraphicsContext.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - 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 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-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
26namespace juce
27{
28
30{
31 static auto compareFont (const Font& a, const Font& b) { return Font::compare (a, b); }
32};
33
34static auto operator< (const Font& a, const Font& b)
35{
36 return GraphicsFontHelpers::compareFont (a, b);
37}
38
39template <typename T>
40static auto operator< (const Rectangle<T>& a, const Rectangle<T>& b)
41{
42 const auto tie = [] (auto& t) { return std::make_tuple (t.getX(), t.getY(), t.getWidth(), t.getHeight()); };
43 return tie (a) < tie (b);
44}
45
46static auto operator< (const Justification& a, const Justification& b)
47{
48 return a.getFlags() < b.getFlags();
49}
50
51//==============================================================================
52namespace
53{
54 struct ConfiguredArrangement
55 {
56 void draw (const Graphics& g) const { arrangement.draw (g, transform); }
57
58 GlyphArrangement arrangement;
59 AffineTransform transform;
60 };
61
62 template <typename ArrangementArgs>
63 class GlyphArrangementCache final : public DeletedAtShutdown
64 {
65 public:
66 GlyphArrangementCache() = default;
67
68 ~GlyphArrangementCache() override
69 {
71 }
72
73 template <typename ConfigureArrangement>
74 void draw (const Graphics& g, ArrangementArgs&& args, ConfigureArrangement&& configureArrangement)
75 {
76 const ScopedTryLock stl (lock);
77
78 if (! stl.isLocked())
79 {
80 configureArrangement (args).draw (g);
81 return;
82 }
83
84 const auto cached = [&]
85 {
86 const auto iter = cache.find (args);
87
88 if (iter != cache.end())
89 {
90 if (iter->second.cachePosition != cacheOrder.begin())
91 cacheOrder.splice (cacheOrder.begin(), cacheOrder, iter->second.cachePosition);
92
93 return iter;
94 }
95
96 auto result = cache.emplace (std::move (args), CachedGlyphArrangement { configureArrangement (args), {} }).first;
97 cacheOrder.push_front (result);
98 return result;
99 }();
100
101 cached->second.cachePosition = cacheOrder.begin();
102 cached->second.configured.draw (g);
103
104 while (cache.size() > cacheSize)
105 {
106 cache.erase (cacheOrder.back());
107 cacheOrder.pop_back();
108 }
109 }
110
112
113 private:
114 struct CachedGlyphArrangement
115 {
117 ConfiguredArrangement configured;
118 typename std::list<CachePtr>::const_iterator cachePosition;
119 };
120
121 static constexpr size_t cacheSize = 128;
124 CriticalSection lock;
125 };
126
127 template <typename ArrangementArgs>
128 juce::SingletonHolder<GlyphArrangementCache<ArrangementArgs>, juce::CriticalSection, false> GlyphArrangementCache<ArrangementArgs>::singletonHolder;
129
130 //==============================================================================
131 template <typename Type>
132 Rectangle<Type> coordsToRectangle (Type x, Type y, Type w, Type h) noexcept
133 {
134 #if JUCE_DEBUG
135 const int maxVal = 0x3fffffff;
136
137 jassert ((int) x >= -maxVal && (int) x <= maxVal
138 && (int) y >= -maxVal && (int) y <= maxVal
139 && (int) w >= 0 && (int) w <= maxVal
140 && (int) h >= 0 && (int) h <= maxVal);
141 #endif
142
143 return { x, y, w, h };
144 }
145}
146
147//==============================================================================
149 : contextHolder (imageToDrawOnto.createLowLevelContext()),
150 context (*contextHolder)
151{
152 jassert (imageToDrawOnto.isValid()); // Can't draw into a null image!
153}
154
159
160//==============================================================================
162{
163 saveStateIfPending();
164 context.setFill (FillType());
165 context.setFont (Font());
166 context.setInterpolationQuality (Graphics::mediumResamplingQuality);
167}
168
170{
171 return context.isVectorDevice();
172}
173
175{
176 saveStateIfPending();
177 return context.clipToRectangle (area);
178}
179
180bool Graphics::reduceClipRegion (int x, int y, int w, int h)
181{
182 return reduceClipRegion (coordsToRectangle (x, y, w, h));
183}
184
186{
187 saveStateIfPending();
188 return context.clipToRectangleList (clipRegion);
189}
190
191bool Graphics::reduceClipRegion (const Path& path, const AffineTransform& transform)
192{
193 saveStateIfPending();
194 context.clipToPath (path, transform);
195 return ! context.isClipEmpty();
196}
197
198bool Graphics::reduceClipRegion (const Image& image, const AffineTransform& transform)
199{
200 saveStateIfPending();
201 context.clipToImageAlpha (image, transform);
202 return ! context.isClipEmpty();
203}
204
206{
207 saveStateIfPending();
208 context.excludeClipRectangle (rectangleToExclude);
209}
210
212{
213 return context.isClipEmpty();
214}
215
217{
218 return context.getClipBounds();
219}
220
222{
223 saveStateIfPending();
224 saveStatePending = true;
225}
226
228{
229 if (saveStatePending)
230 saveStatePending = false;
231 else
232 context.restoreState();
233}
234
235void Graphics::saveStateIfPending()
236{
237 if (saveStatePending)
238 {
239 saveStatePending = false;
240 context.saveState();
241 }
242}
243
245{
246 saveStateIfPending();
247 context.setOrigin (newOrigin);
248}
249
250void Graphics::setOrigin (int x, int y)
251{
252 setOrigin ({ x, y });
253}
254
256{
257 saveStateIfPending();
258 context.addTransform (transform);
259}
260
262{
263 return context.clipRegionIntersects (area);
264}
265
267{
268 saveStateIfPending();
269 context.beginTransparencyLayer (layerOpacity);
270}
271
273{
274 context.endTransparencyLayer();
275}
276
277//==============================================================================
279{
280 saveStateIfPending();
281 context.setFill (newColour);
282}
283
285{
286 saveStateIfPending();
287 context.setOpacity (newOpacity);
288}
289
291{
292 setFillType (gradient);
293}
294
296{
297 setFillType (std::move (gradient));
298}
299
300void Graphics::setTiledImageFill (const Image& imageToUse, const int anchorX, const int anchorY, const float opacity)
301{
302 saveStateIfPending();
303 context.setFill (FillType (imageToUse, AffineTransform::translation ((float) anchorX, (float) anchorY)));
304 context.setOpacity (opacity);
305}
306
308{
309 saveStateIfPending();
310 context.setFill (newFill);
311}
312
313//==============================================================================
315{
316 saveStateIfPending();
317 context.setFont (newFont);
318}
319
321{
322 setFont (context.getFont().withHeight (newFontHeight));
323}
324
326{
327 return context.getFont();
328}
329
330//==============================================================================
331void Graphics::drawSingleLineText (const String& text, const int startX, const int baselineY,
332 Justification justification) const
333{
334 if (text.isEmpty())
335 return;
336
337 // Don't pass any vertical placement flags to this method - they'll be ignored.
338 jassert (justification.getOnlyVerticalFlags() == 0);
339
340 auto flags = justification.getOnlyHorizontalFlags();
341
342 if (flags == Justification::right && startX < context.getClipBounds().getX())
343 return;
344
345 if (flags == Justification::left && startX > context.getClipBounds().getRight())
346 return;
347
348 struct ArrangementArgs
349 {
350 auto tie() const noexcept { return std::tie (font, text, startX, baselineY); }
351 bool operator< (const ArrangementArgs& other) const { return tie() < other.tie(); }
352
353 const Font font;
354 const String text;
355 const int startX, baselineY, flags;
356 };
357
358 auto configureArrangement = [] (const ArrangementArgs& args)
359 {
360 AffineTransform transform;
361 GlyphArrangement arrangement;
362 arrangement.addLineOfText (args.font, args.text, (float) args.startX, (float) args.baselineY);
363
364 if (args.flags != Justification::left)
365 {
366 auto w = arrangement.getBoundingBox (0, -1, true).getWidth();
367
369 w /= 2.0f;
370
371 transform = AffineTransform::translation (-w, 0);
372 }
373
374 return ConfiguredArrangement { std::move (arrangement), std::move (transform) };
375 };
376
377 GlyphArrangementCache<ArrangementArgs>::getInstance()->draw (*this,
378 { context.getFont(), text, startX, baselineY, flags },
379 std::move (configureArrangement));
380}
381
382void Graphics::drawMultiLineText (const String& text, const int startX,
383 const int baselineY, const int maximumLineWidth,
384 Justification justification, const float leading) const
385{
386 if (text.isEmpty() || startX >= context.getClipBounds().getRight())
387 return;
388
389 struct ArrangementArgs
390 {
391 auto tie() const noexcept { return std::tie (font, text, startX, baselineY, maximumLineWidth, justification, leading); }
392 bool operator< (const ArrangementArgs& other) const { return tie() < other.tie(); }
393
394 const Font font;
395 const String text;
396 const int startX, baselineY, maximumLineWidth;
397 const Justification justification;
398 const float leading;
399 };
400
401 auto configureArrangement = [] (const ArrangementArgs& args)
402 {
403 GlyphArrangement arrangement;
404 arrangement.addJustifiedText (args.font, args.text,
405 (float) args.startX, (float) args.baselineY, (float) args.maximumLineWidth,
406 args.justification, args.leading);
407 return ConfiguredArrangement { std::move (arrangement), {} };
408 };
409
410 GlyphArrangementCache<ArrangementArgs>::getInstance()->draw (*this,
411 { context.getFont(), text, startX, baselineY, maximumLineWidth, justification, leading },
412 std::move (configureArrangement));
413}
414
417{
418 if (text.isEmpty() || ! context.clipRegionIntersects (area.getSmallestIntegerContainer()))
419 return;
420
421 struct ArrangementArgs
422 {
423 auto tie() const noexcept { return std::tie (font, text, area, justificationType, useEllipsesIfTooBig); }
424 bool operator< (const ArrangementArgs& other) const { return tie() < other.tie(); }
425
426 const Font font;
427 const String text;
428 const Rectangle<float> area;
429 const Justification justificationType;
430 const bool useEllipsesIfTooBig;
431 };
432
433 auto configureArrangement = [] (const ArrangementArgs& args)
434 {
435 GlyphArrangement arrangement;
436 arrangement.addCurtailedLineOfText (args.font, args.text, 0.0f, 0.0f,
437 args.area.getWidth(), args.useEllipsesIfTooBig);
438
439 arrangement.justifyGlyphs (0, arrangement.getNumGlyphs(),
440 args.area.getX(), args.area.getY(), args.area.getWidth(), args.area.getHeight(),
441 args.justificationType);
442 return ConfiguredArrangement { std::move (arrangement), {} };
443 };
444
445 GlyphArrangementCache<ArrangementArgs>::getInstance()->draw (*this,
446 { context.getFont(), text, area, justificationType, useEllipsesIfTooBig },
447 std::move (configureArrangement));
448}
449
455
456void Graphics::drawText (const String& text, int x, int y, int width, int height,
458{
459 drawText (text, coordsToRectangle (x, y, width, height), justificationType, useEllipsesIfTooBig);
460}
461
463 Justification justification,
464 const int maximumNumberOfLines,
465 const float minimumHorizontalScale) const
466{
467 if (text.isEmpty() || area.isEmpty() || ! context.clipRegionIntersects (area))
468 return;
469
470 struct ArrangementArgs
471 {
472 auto tie() const noexcept { return std::tie (font, text, area, justification, maximumNumberOfLines, minimumHorizontalScale); }
473 bool operator< (const ArrangementArgs& other) const noexcept { return tie() < other.tie(); }
474
475 const Font font;
476 const String text;
477 const Rectangle<float> area;
478 const Justification justification;
479 const int maximumNumberOfLines;
480 const float minimumHorizontalScale;
481 };
482
483 auto configureArrangement = [] (const ArrangementArgs& args)
484 {
485 GlyphArrangement arrangement;
486 arrangement.addFittedText (args.font, args.text,
487 args.area.getX(), args.area.getY(),
488 args.area.getWidth(), args.area.getHeight(),
489 args.justification,
490 args.maximumNumberOfLines,
491 args.minimumHorizontalScale);
492 return ConfiguredArrangement { std::move (arrangement), {} };
493 };
494
495 GlyphArrangementCache<ArrangementArgs>::getInstance()->draw (*this,
496 { context.getFont(), text, area.toFloat(), justification, maximumNumberOfLines, minimumHorizontalScale },
497 std::move (configureArrangement));
498}
499
500void Graphics::drawFittedText (const String& text, int x, int y, int width, int height,
501 Justification justification,
502 const int maximumNumberOfLines,
503 const float minimumHorizontalScale) const
504{
505 drawFittedText (text, coordsToRectangle (x, y, width, height),
506 justification, maximumNumberOfLines, minimumHorizontalScale);
507}
508
509//==============================================================================
511{
512 context.fillRect (r, false);
513}
514
516{
517 context.fillRect (r);
518}
519
520void Graphics::fillRect (int x, int y, int width, int height) const
521{
522 context.fillRect (coordsToRectangle (x, y, width, height), false);
523}
524
525void Graphics::fillRect (float x, float y, float width, float height) const
526{
527 fillRect (coordsToRectangle (x, y, width, height));
528}
529
531{
532 context.fillRectList (rectangles);
533}
534
536{
537 for (auto& r : rects)
538 context.fillRect (r, false);
539}
540
542{
543 context.fillAll();
544}
545
547{
548 if (! colourToUse.isTransparent())
549 {
550 context.saveState();
551 context.setFill (colourToUse);
552 context.fillAll();
553 context.restoreState();
554 }
555}
556
557
558//==============================================================================
559void Graphics::fillPath (const Path& path) const
560{
561 if (! (context.isClipEmpty() || path.isEmpty()))
562 context.fillPath (path, AffineTransform());
563}
564
565void Graphics::fillPath (const Path& path, const AffineTransform& transform) const
566{
567 if (! (context.isClipEmpty() || path.isEmpty()))
568 context.fillPath (path, transform);
569}
570
571void Graphics::strokePath (const Path& path,
572 const PathStrokeType& strokeType,
573 const AffineTransform& transform) const
574{
575 Path stroke;
576 strokeType.createStrokedPath (stroke, path, transform, context.getPhysicalPixelScaleFactor());
578}
579
580//==============================================================================
581void Graphics::drawRect (float x, float y, float width, float height, float lineThickness) const
582{
583 drawRect (coordsToRectangle (x, y, width, height), lineThickness);
584}
585
586void Graphics::drawRect (int x, int y, int width, int height, int lineThickness) const
587{
588 drawRect (coordsToRectangle (x, y, width, height), lineThickness);
589}
590
592{
593 drawRect (r.toFloat(), (float) lineThickness);
594}
595
597{
598 jassert (r.getWidth() >= 0.0f && r.getHeight() >= 0.0f);
599
605 context.fillRectList (rects);
606}
607
608//==============================================================================
610{
611 Path p;
612 p.addEllipse (area);
613 fillPath (p);
614}
615
616void Graphics::fillEllipse (float x, float y, float w, float h) const
617{
618 fillEllipse (coordsToRectangle (x, y, w, h));
619}
620
621void Graphics::drawEllipse (float x, float y, float width, float height, float lineThickness) const
622{
623 drawEllipse (coordsToRectangle (x, y, width, height), lineThickness);
624}
625
627{
628 Path p;
629
630 if (approximatelyEqual (area.getWidth(), area.getHeight()))
631 {
632 // For a circle, we can avoid having to generate a stroke
633 p.addEllipse (area.expanded (lineThickness * 0.5f));
634 p.addEllipse (area.reduced (lineThickness * 0.5f));
635 p.setUsingNonZeroWinding (false);
636 fillPath (p);
637 }
638 else
639 {
640 p.addEllipse (area);
642 }
643}
644
645void Graphics::fillRoundedRectangle (float x, float y, float width, float height, float cornerSize) const
646{
647 fillRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize);
648}
649
650void Graphics::fillRoundedRectangle (Rectangle<float> r, const float cornerSize) const
651{
652 Path p;
653 p.addRoundedRectangle (r, cornerSize);
654 fillPath (p);
655}
656
657void Graphics::drawRoundedRectangle (float x, float y, float width, float height,
658 float cornerSize, float lineThickness) const
659{
660 drawRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize, lineThickness);
661}
662
663void Graphics::drawRoundedRectangle (Rectangle<float> r, float cornerSize, float lineThickness) const
664{
665 Path p;
666 p.addRoundedRectangle (r, cornerSize);
668}
669
671{
672 Path p;
674 fillPath (p);
675}
676
679{
680 jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less!
681
682 if (checkWidth > 0 && checkHeight > 0)
683 {
684 context.saveState();
685
686 if (colour1 == colour2)
687 {
688 context.setFill (colour1);
689 context.fillRect (area);
690 }
691 else
692 {
693 auto clipped = context.getClipBounds().getIntersection (area.getSmallestIntegerContainer());
694
695 if (! clipped.isEmpty())
696 {
697 const int checkNumX = (int) (((float) clipped.getX() - area.getX()) / checkWidth);
698 const int checkNumY = (int) (((float) clipped.getY() - area.getY()) / checkHeight);
699 const float startX = area.getX() + (float) checkNumX * checkWidth;
700 const float startY = area.getY() + (float) checkNumY * checkHeight;
701 const float right = (float) clipped.getRight();
702 const float bottom = (float) clipped.getBottom();
703
704 for (int i = 0; i < 2; ++i)
705 {
706 int cy = i;
708
709 for (float y = startY; y < bottom; y += checkHeight)
710 for (float x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2.0f)
712
713 checks.clipTo (area);
714 context.setFill (i == ((checkNumX ^ checkNumY) & 1) ? colour1 : colour2);
715 context.fillRectList (checks);
716 }
717 }
718 }
719
720 context.restoreState();
721 }
722}
723
724//==============================================================================
725void Graphics::drawVerticalLine (const int x, float top, float bottom) const
726{
727 if (top < bottom)
728 context.fillRect (Rectangle<float> ((float) x, top, 1.0f, bottom - top));
729}
730
731void Graphics::drawHorizontalLine (const int y, float left, float right) const
732{
733 if (left < right)
734 context.fillRect (Rectangle<float> (left, (float) y, right - left, 1.0f));
735}
736
737void Graphics::drawLine (Line<float> line) const
738{
739 context.drawLine (line);
740}
741
742void Graphics::drawLine (float x1, float y1, float x2, float y2) const
743{
744 context.drawLine (Line<float> (x1, y1, x2, y2));
745}
746
747void Graphics::drawLine (float x1, float y1, float x2, float y2, float lineThickness) const
748{
749 drawLine (Line<float> (x1, y1, x2, y2), lineThickness);
750}
751
752void Graphics::drawLine (Line<float> line, const float lineThickness) const
753{
754 Path p;
755 p.addLineSegment (line, lineThickness);
756 fillPath (p);
757}
758
759void Graphics::drawDashedLine (Line<float> line, const float* dashLengths,
760 int numDashLengths, float lineThickness, int n) const
761{
762 jassert (n >= 0 && n < numDashLengths); // your start index must be valid!
763
764 const Point<double> delta ((line.getEnd() - line.getStart()).toDouble());
765 const double totalLen = delta.getDistanceFromOrigin();
766
767 if (totalLen >= 0.1)
768 {
769 const double onePixAlpha = 1.0 / totalLen;
770
771 for (double alpha = 0.0; alpha < 1.0;)
772 {
773 jassert (dashLengths[n] > 0); // can't have zero-length dashes!
774
775 const double lastAlpha = alpha;
776 alpha += dashLengths [n] * onePixAlpha;
777 n = (n + 1) % numDashLengths;
778
779 if ((n & 1) != 0)
780 {
781 const Line<float> segment (line.getStart() + (delta * lastAlpha).toFloat(),
782 line.getStart() + (delta * jmin (1.0, alpha)).toFloat());
783
784 if (! approximatelyEqual (lineThickness, 1.0f))
785 drawLine (segment, lineThickness);
786 else
787 context.drawLine (segment);
788 }
789 }
790 }
791}
792
793//==============================================================================
794void Graphics::setImageResamplingQuality (const Graphics::ResamplingQuality newQuality)
795{
796 saveStateIfPending();
797 context.setInterpolationQuality (newQuality);
798}
799
800//==============================================================================
801void Graphics::drawImageAt (const Image& imageToDraw, int x, int y, bool fillAlphaChannel) const
802{
803 drawImageTransformed (imageToDraw,
804 AffineTransform::translation ((float) x, (float) y),
805 fillAlphaChannel);
806}
807
808void Graphics::drawImage (const Image& imageToDraw, Rectangle<float> targetArea,
809 RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
810{
811 if (imageToDraw.isValid())
812 drawImageTransformed (imageToDraw,
813 placementWithinTarget.getTransformToFit (imageToDraw.getBounds().toFloat(), targetArea),
814 fillAlphaChannelWithCurrentBrush);
815}
816
817void Graphics::drawImageWithin (const Image& imageToDraw, int dx, int dy, int dw, int dh,
818 RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
819{
820 drawImage (imageToDraw, coordsToRectangle (dx, dy, dw, dh).toFloat(),
821 placementWithinTarget, fillAlphaChannelWithCurrentBrush);
822}
823
824void Graphics::drawImage (const Image& imageToDraw,
825 int dx, int dy, int dw, int dh,
826 int sx, int sy, int sw, int sh,
827 const bool fillAlphaChannelWithCurrentBrush) const
828{
829 if (imageToDraw.isValid() && context.clipRegionIntersects (coordsToRectangle (dx, dy, dw, dh)))
830 drawImageTransformed (imageToDraw.getClippedImage (coordsToRectangle (sx, sy, sw, sh)),
831 AffineTransform::scale ((float) dw / (float) sw, (float) dh / (float) sh)
832 .translated ((float) dx, (float) dy),
833 fillAlphaChannelWithCurrentBrush);
834}
835
836void Graphics::drawImageTransformed (const Image& imageToDraw,
837 const AffineTransform& transform,
838 const bool fillAlphaChannelWithCurrentBrush) const
839{
840 if (imageToDraw.isValid() && ! context.isClipEmpty())
841 {
842 if (fillAlphaChannelWithCurrentBrush)
843 {
844 context.saveState();
845 context.clipToImageAlpha (imageToDraw, transform);
846 fillAll();
847 context.restoreState();
848 }
849 else
850 {
851 context.drawImage (imageToDraw, transform);
852 }
853 }
854}
855
856//==============================================================================
857Graphics::ScopedSaveState::ScopedSaveState (Graphics& g) : context (g)
858{
859 context.saveState();
860}
861
862Graphics::ScopedSaveState::~ScopedSaveState()
863{
864 context.restoreState();
865}
866
867} // namespace juce
Represents a 2D affine-transformation matrix.
static AffineTransform translation(float deltaX, float deltaY) noexcept
Returns a new transform which is a translation.
Describes the layout and colours that should be used to paint a colour gradient.
Represents a colour, also including a transparency value.
Definition juce_Colour.h:38
Represents a colour or fill pattern to use for rendering paths.
Represents a particular font, including its size, style, etc.
Definition juce_Font.h:42
Font withHeight(float height) const
Returns a copy of this font with a new height.
A set of glyphs, each with a position.
void addLineOfText(const Font &font, const String &text, float x, float y)
Appends a line of text to the arrangement.
Rectangle< float > getBoundingBox(int startIndex, int numGlyphs, bool includeWhitespace) const
Finds the smallest rectangle that will enclose a subset of the glyphs.
int getNumGlyphs() const noexcept
Returns the total number of glyphs in the arrangement.
void addFittedText(const Font &font, const String &text, float x, float y, float width, float height, Justification layout, int maximumLinesToUse, float minimumHorizontalScale=0.0f)
Tries to fit some text within a given space.
void addCurtailedLineOfText(const Font &font, const String &text, float x, float y, float maxWidthPixels, bool useEllipsis)
Adds a line of text, truncating it if it's wider than a specified size.
void addJustifiedText(const Font &font, const String &text, float x, float y, float maxLineWidth, Justification horizontalLayout, float leading=0.0f)
Adds some multi-line text, breaking lines at word-boundaries if they are too wide.
void justifyGlyphs(int startIndex, int numGlyphs, float x, float y, float width, float height, Justification justification)
Justifies a set of glyphs within a given space.
A graphics context, used for drawing a component or image.
void saveState()
Saves the current graphics state on an internal stack.
void setOpacity(float newOpacity)
Changes the opacity to use with the current colour.
void drawText(const String &text, int x, int y, int width, int height, Justification justificationType, bool useEllipsesIfTooBig=true) const
Draws a line of text within a specified rectangle.
void drawFittedText(const String &text, int x, int y, int width, int height, Justification justificationFlags, int maximumNumberOfLines, float minimumHorizontalScale=0.0f) const
Tries to draw a text string inside a given space.
Font getCurrentFont() const
Returns the currently selected font.
void setFont(const Font &newFont)
Changes the font to use for subsequent text-drawing functions.
void fillRectList(const RectangleList< float > &rectangles) const
Fills a set of rectangles using the current colour or brush.
void restoreState()
Restores a graphics state that was previously saved with saveState().
ResamplingQuality
Types of rendering quality that can be specified when drawing images.
@ mediumResamplingQuality
Uses bilinear interpolation for upsampling and area-averaging for downsampling.
bool isClipEmpty() const
Returns true if no drawing can be done because the clip region is zero.
void setFillType(const FillType &newFill)
Changes the current fill settings.
void drawArrow(Line< float > line, float lineThickness, float arrowheadWidth, float arrowheadLength) const
Draws a line with an arrowhead at its end.
void setGradientFill(const ColourGradient &gradient)
Sets the context to use a gradient for its fill pattern.
void fillRoundedRectangle(float x, float y, float width, float height, float cornerSize) const
Uses the current colour or brush to fill a rectangle with rounded corners.
void excludeClipRegion(Rectangle< int > rectangleToExclude)
Excludes a rectangle to stop it being drawn into.
void drawRect(int x, int y, int width, int height, int lineThickness=1) const
Draws a rectangular outline, using the current colour or brush.
void endTransparencyLayer()
Completes a drawing operation to a temporary semi-transparent buffer.
void setTiledImageFill(const Image &imageToUse, int anchorX, int anchorY, float opacity)
Sets the context to use a tiled image pattern for filling.
void addTransform(const AffineTransform &transform)
Adds a transformation which will be performed on all the graphics operations that the context subsequ...
bool clipRegionIntersects(Rectangle< int > area) const
Checks whether a rectangle overlaps the context's clipping region.
void fillRect(Rectangle< int > rectangle) const
Fills a rectangle with the current colour or brush.
void beginTransparencyLayer(float layerOpacity)
Begins rendering to an off-screen bitmap which will later be flattened onto the current context with ...
void drawMultiLineText(const String &text, int startX, int baselineY, int maximumLineWidth, Justification justification=Justification::left, float leading=0.0f) const
Draws text across multiple lines.
void fillPath(const Path &path) const
Fills a path using the currently selected colour or brush.
Graphics(const Image &imageToDrawOnto)
Creates a Graphics object to draw directly onto the given image.
void resetToDefaultState()
Resets the current colour, brush, and font to default settings.
void drawEllipse(float x, float y, float width, float height, float lineThickness) const
Draws an elliptical stroke using the current colour or brush.
void drawSingleLineText(const String &text, int startX, int baselineY, Justification justification=Justification::left) const
Draws a one-line text string.
bool reduceClipRegion(int x, int y, int width, int height)
Intersects the current clipping region with another region.
void fillCheckerBoard(Rectangle< float > area, float checkWidth, float checkHeight, Colour colour1, Colour colour2) const
Fills a rectangle with a checkerboard pattern, alternating between two colours.
Rectangle< int > getClipBounds() const
Returns the position of the bounding box for the current clipping region.
bool isVectorDevice() const
Returns true if this context is drawing to a vector-based device, such as a printer.
void setColour(Colour newColour)
Changes the current drawing colour.
void strokePath(const Path &path, const PathStrokeType &strokeType, const AffineTransform &transform={}) const
Draws a path's outline using the currently selected colour or brush.
void fillAll() const
Fills the context's entire clip region with the current colour or brush.
void setOrigin(Point< int > newOrigin)
Moves the position of the context's origin.
void drawRoundedRectangle(float x, float y, float width, float height, float cornerSize, float lineThickness) const
Uses the current colour or brush to draw the outline of a rectangle with rounded corners.
void fillEllipse(float x, float y, float width, float height) const
Fills an ellipse with the current colour or brush.
Holds a fixed-size bitmap.
Definition juce_Image.h:58
Image getClippedImage(const Rectangle< int > &area) const
Returns an image which refers to a subsection of this image.
Rectangle< int > getBounds() const noexcept
Returns a rectangle with the same size as this image.
bool isValid() const noexcept
Returns true if this image isn't null.
Definition juce_Image.h:147
Represents a type of justification to be used when positioning graphical items.
@ horizontallyJustified
Indicates that lines of text should be spread out to fill the maximum width available,...
@ left
Indicates that the item should be aligned against the left edge of the available space.
@ horizontallyCentred
Indicates that the item should be placed in the centre between the left and right sides of the availa...
@ right
Indicates that the item should be aligned against the right edge of the available space.
int getOnlyVerticalFlags() const noexcept
Returns just the flags from this object that deal with vertical layout.
int getOnlyHorizontalFlags() const noexcept
Returns just the flags from this object that deal with horizontal layout.
Represents a line.
Definition juce_Line.h:47
Point< ValueType > getEnd() const noexcept
Returns the line's end point.
Definition juce_Line.h:91
Point< ValueType > getStart() const noexcept
Returns the line's start point.
Definition juce_Line.h:88
Interface class for graphics context objects, used internally by the Graphics class.
virtual bool isVectorDevice() const =0
Returns true if this device is vector-based, e.g.
virtual void setOrigin(Point< int >)=0
Moves the origin to a new position.
Describes a type of stroke used to render a solid outline along a path.
void createStrokedPath(Path &destPath, const Path &sourcePath, const AffineTransform &transform=AffineTransform(), float extraAccuracy=1.0f) const
Applies this stroke type to a path and returns the resultant stroke as another Path.
A path is a sequence of lines and curves that may either form a closed shape or be open-ended.
Definition juce_Path.h:65
void addRoundedRectangle(float x, float y, float width, float height, float cornerSize)
Adds a rectangle with rounded corners to the path.
void addEllipse(float x, float y, float width, float height)
Adds an ellipse to the path.
void addLineSegment(Line< float > line, float lineThickness)
Adds a line with a specified thickness.
void addArrow(Line< float > line, float lineThickness, float arrowheadWidth, float arrowheadLength)
Adds a line with an arrowhead on the end.
void setUsingNonZeroWinding(bool isNonZeroWinding) noexcept
Changes the winding-rule to be used when filling the path.
bool isEmpty() const noexcept
Returns true if the path doesn't contain any lines or curves.
A pair of (x, y) coordinates.
Definition juce_Point.h:42
ValueType getDistanceFromOrigin() const noexcept
Returns the straight-line distance between this point and the origin.
Definition juce_Point.h:162
Maintains a set of rectangles as a complex region.
void addWithoutMerging(RectangleType rect)
Dumbly adds a rectangle to the list without checking for overlaps.
Defines the method used to position some kind of rectangular object within a rectangular viewport.
AffineTransform getTransformToFit(const Rectangle< float > &source, const Rectangle< float > &destination) const noexcept
Returns the transform that should be applied to these source coordinates to fit them into the destina...
Manages a rectangle and allows geometric operations to be performed on it.
ValueType getRight() const noexcept
Returns the x coordinate of the rectangle's right-hand-side.
Rectangle< float > toFloat() const noexcept
Casts this rectangle to a Rectangle<float>.
Rectangle removeFromRight(ValueType amountToRemove) noexcept
Removes a strip from the right-hand edge of this rectangle, reducing this rectangle by the specified ...
ValueType getX() const noexcept
Returns the x coordinate of the rectangle's left-hand-side.
Rectangle< int > getSmallestIntegerContainer() const noexcept
Returns the smallest integer-aligned rectangle that completely contains this one.
Rectangle removeFromBottom(ValueType amountToRemove) noexcept
Removes a strip from the bottom of this rectangle, reducing this rectangle by the specified amount an...
Rectangle getIntersection(Rectangle other) const noexcept
Returns the region that is the overlap between this and another rectangle.
ValueType getWidth() const noexcept
Returns the width of the rectangle.
Rectangle removeFromTop(ValueType amountToRemove) noexcept
Removes a strip from the top of this rectangle, reducing this rectangle by the specified amount and r...
Rectangle reduced(ValueType deltaX, ValueType deltaY) const noexcept
Returns a rectangle that is smaller than this one by a given amount.
Rectangle removeFromLeft(ValueType amountToRemove) noexcept
Removes a strip from the left-hand edge of this rectangle, reducing this rectangle by the specified a...
ValueType getY() const noexcept
Returns the y coordinate of the rectangle's top edge.
bool isEmpty() const noexcept
Returns true if the rectangle's width or height are zero or less.
ValueType getHeight() const noexcept
Returns the height of the rectangle.
Rectangle expanded(ValueType deltaX, ValueType deltaY) const noexcept
Returns a rectangle that is larger than this one by a given amount.
The JUCE String class!
Definition juce_String.h:53
bool isEmpty() const noexcept
Returns true if the string contains no characters.
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_SINGLETON(Classname, doNotRecreateAfterDeletion)
Macro to generate the appropriate methods and boilerplate for a singleton class.
typedef int
T lock(T... args)
T make_tuple(T... args)
typedef float
JUCE Namespace.
constexpr bool approximatelyEqual(Type a, Type b, Tolerance< Type > tolerance=Tolerance< Type >{} .withAbsolute(std::numeric_limits< Type >::min()) .withRelative(std::numeric_limits< Type >::epsilon()))
Returns true if the two floating-point numbers are approximately equal.
constexpr Type jmin(Type a, Type b)
Returns the smaller of two values.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
CriticalSection::ScopedTryLockType ScopedTryLock
Automatically tries to lock and unlock a CriticalSection object.
Used by the JUCE_DECLARE_SINGLETON macros to manage a static pointer to a singleton instance.
T tie(T... args)
T transform(T... args)
y1