LMMS
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{
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 {
70 clearSingletonInstance();
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
111 JUCE_DECLARE_SINGLETON (GlyphArrangementCache<ArrangementArgs>, false)
112
113 private:
114 struct CachedGlyphArrangement
115 {
116 using CachePtr = typename std::map<ArrangementArgs, CachedGlyphArrangement>::const_iterator;
117 ConfiguredArrangement configured;
118 typename std::list<CachePtr>::const_iterator cachePosition;
119 };
120
121 static constexpr size_t cacheSize = 128;
122 std::map<ArrangementArgs, CachedGlyphArrangement> cache;
123 std::list<typename CachedGlyphArrangement::CachePtr> cacheOrder;
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 jassertquiet ((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//==============================================================================
148Graphics::Graphics (const Image& imageToDrawOnto)
149 : contextHolder (imageToDrawOnto.createLowLevelContext()),
151{
152 jassert (imageToDrawOnto.isValid()); // Can't draw into a null image!
153}
154
156 : context (internalContext)
157{
158}
159
160//==============================================================================
162{
164 context.setFill (FillType());
165 context.setFont (Font());
166 context.setInterpolationQuality (Graphics::mediumResamplingQuality);
167}
168
170{
171 return context.isVectorDevice();
172}
173
175{
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{
188 return context.clipToRectangleList (clipRegion);
189}
190
191bool Graphics::reduceClipRegion (const Path& path, const AffineTransform& transform)
192{
194 context.clipToPath (path, transform);
195 return ! context.isClipEmpty();
196}
197
198bool Graphics::reduceClipRegion (const Image& image, const AffineTransform& transform)
199{
201 context.clipToImageAlpha (image, transform);
202 return ! context.isClipEmpty();
203}
204
206{
208 context.excludeClipRectangle (rectangleToExclude);
209}
210
212{
213 return context.isClipEmpty();
214}
215
217{
218 return context.getClipBounds();
219}
220
222{
224 saveStatePending = true;
225}
226
228{
230 saveStatePending = false;
231 else
232 context.restoreState();
233}
234
236{
238 {
239 saveStatePending = false;
240 context.saveState();
241 }
242}
243
245{
247 context.setOrigin (newOrigin);
248}
249
250void Graphics::setOrigin (int x, int y)
251{
252 setOrigin ({ x, y });
253}
254
256{
258 context.addTransform (transform);
259}
260
262{
263 return context.clipRegionIntersects (area);
264}
265
266void Graphics::beginTransparencyLayer (float layerOpacity)
267{
269 context.beginTransparencyLayer (layerOpacity);
270}
271
273{
274 context.endTransparencyLayer();
275}
276
277//==============================================================================
279{
281 context.setFill (newColour);
282}
283
284void Graphics::setOpacity (float newOpacity)
285{
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{
303 context.setFill (FillType (imageToUse, AffineTransform::translation ((float) anchorX, (float) anchorY)));
304 context.setOpacity (opacity);
305}
306
307void Graphics::setFillType (const FillType& newFill)
308{
310 context.setFill (newFill);
311}
312
313//==============================================================================
314void Graphics::setFont (const Font& newFont)
315{
317 context.setFont (newFont);
318}
319
320void Graphics::setFont (const float newFontHeight)
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
416 Justification justificationType, bool useEllipsesIfTooBig) const
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
451 Justification justificationType, bool useEllipsesIfTooBig) const
452{
453 drawText (text, area.toFloat(), justificationType, useEllipsesIfTooBig);
454}
455
456void Graphics::drawText (const String& text, int x, int y, int width, int height,
457 Justification justificationType, const bool useEllipsesIfTooBig) const
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
530void Graphics::fillRectList (const RectangleList<float>& rectangles) const
531{
532 context.fillRectList (rectangles);
533}
534
536{
537 for (auto& r : rects)
538 context.fillRect (r, false);
539}
540
542{
543 fillRect (context.getClipBounds());
544}
545
546void Graphics::fillAll (Colour colourToUse) const
547{
548 if (! colourToUse.isTransparent())
549 {
550 auto clip = context.getClipBounds();
551
552 context.saveState();
553 context.setFill (colourToUse);
554 context.fillRect (clip, false);
555 context.restoreState();
556 }
557}
558
559
560//==============================================================================
561void Graphics::fillPath (const Path& path) const
562{
563 if (! (context.isClipEmpty() || path.isEmpty()))
564 context.fillPath (path, AffineTransform());
565}
566
567void Graphics::fillPath (const Path& path, const AffineTransform& transform) const
568{
569 if (! (context.isClipEmpty() || path.isEmpty()))
570 context.fillPath (path, transform);
571}
572
573void Graphics::strokePath (const Path& path,
574 const PathStrokeType& strokeType,
575 const AffineTransform& transform) const
576{
577 Path stroke;
578 strokeType.createStrokedPath (stroke, path, transform, context.getPhysicalPixelScaleFactor());
579 fillPath (stroke);
580}
581
582//==============================================================================
583void Graphics::drawRect (float x, float y, float width, float height, float lineThickness) const
584{
585 drawRect (coordsToRectangle (x, y, width, height), lineThickness);
586}
587
588void Graphics::drawRect (int x, int y, int width, int height, int lineThickness) const
589{
590 drawRect (coordsToRectangle (x, y, width, height), lineThickness);
591}
592
593void Graphics::drawRect (Rectangle<int> r, int lineThickness) const
594{
595 drawRect (r.toFloat(), (float) lineThickness);
596}
597
598void Graphics::drawRect (Rectangle<float> r, const float lineThickness) const
599{
600 jassert (r.getWidth() >= 0.0f && r.getHeight() >= 0.0f);
601
603 rects.addWithoutMerging (r.removeFromTop (lineThickness));
604 rects.addWithoutMerging (r.removeFromBottom (lineThickness));
605 rects.addWithoutMerging (r.removeFromLeft (lineThickness));
606 rects.addWithoutMerging (r.removeFromRight (lineThickness));
607 context.fillRectList (rects);
608}
609
610//==============================================================================
612{
613 Path p;
614 p.addEllipse (area);
615 fillPath (p);
616}
617
618void Graphics::fillEllipse (float x, float y, float w, float h) const
619{
620 fillEllipse (coordsToRectangle (x, y, w, h));
621}
622
623void Graphics::drawEllipse (float x, float y, float width, float height, float lineThickness) const
624{
625 drawEllipse (coordsToRectangle (x, y, width, height), lineThickness);
626}
627
628void Graphics::drawEllipse (Rectangle<float> area, float lineThickness) const
629{
630 Path p;
631
632 if (area.getWidth() == area.getHeight())
633 {
634 // For a circle, we can avoid having to generate a stroke
635 p.addEllipse (area.expanded (lineThickness * 0.5f));
636 p.addEllipse (area.reduced (lineThickness * 0.5f));
637 p.setUsingNonZeroWinding (false);
638 fillPath (p);
639 }
640 else
641 {
642 p.addEllipse (area);
643 strokePath (p, PathStrokeType (lineThickness));
644 }
645}
646
647void Graphics::fillRoundedRectangle (float x, float y, float width, float height, float cornerSize) const
648{
649 fillRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize);
650}
651
652void Graphics::fillRoundedRectangle (Rectangle<float> r, const float cornerSize) const
653{
654 Path p;
655 p.addRoundedRectangle (r, cornerSize);
656 fillPath (p);
657}
658
659void Graphics::drawRoundedRectangle (float x, float y, float width, float height,
660 float cornerSize, float lineThickness) const
661{
662 drawRoundedRectangle (coordsToRectangle (x, y, width, height), cornerSize, lineThickness);
663}
664
665void Graphics::drawRoundedRectangle (Rectangle<float> r, float cornerSize, float lineThickness) const
666{
667 Path p;
668 p.addRoundedRectangle (r, cornerSize);
669 strokePath (p, PathStrokeType (lineThickness));
670}
671
672void Graphics::drawArrow (Line<float> line, float lineThickness, float arrowheadWidth, float arrowheadLength) const
673{
674 Path p;
675 p.addArrow (line, lineThickness, arrowheadWidth, arrowheadLength);
676 fillPath (p);
677}
678
679void Graphics::fillCheckerBoard (Rectangle<float> area, float checkWidth, float checkHeight,
680 Colour colour1, Colour colour2) const
681{
682 jassert (checkWidth > 0 && checkHeight > 0); // can't be zero or less!
683
684 if (checkWidth > 0 && checkHeight > 0)
685 {
686 context.saveState();
687
688 if (colour1 == colour2)
689 {
690 context.setFill (colour1);
691 context.fillRect (area);
692 }
693 else
694 {
695 auto clipped = context.getClipBounds().getIntersection (area.getSmallestIntegerContainer());
696
697 if (! clipped.isEmpty())
698 {
699 const int checkNumX = (int) (((float) clipped.getX() - area.getX()) / checkWidth);
700 const int checkNumY = (int) (((float) clipped.getY() - area.getY()) / checkHeight);
701 const float startX = area.getX() + (float) checkNumX * checkWidth;
702 const float startY = area.getY() + (float) checkNumY * checkHeight;
703 const float right = (float) clipped.getRight();
704 const float bottom = (float) clipped.getBottom();
705
706 for (int i = 0; i < 2; ++i)
707 {
708 int cy = i;
710
711 for (float y = startY; y < bottom; y += checkHeight)
712 for (float x = startX + (cy++ & 1) * checkWidth; x < right; x += checkWidth * 2.0f)
713 checks.addWithoutMerging ({ x, y, checkWidth, checkHeight });
714
715 checks.clipTo (area);
716 context.setFill (i == ((checkNumX ^ checkNumY) & 1) ? colour1 : colour2);
717 context.fillRectList (checks);
718 }
719 }
720 }
721
722 context.restoreState();
723 }
724}
725
726//==============================================================================
727void Graphics::drawVerticalLine (const int x, float top, float bottom) const
728{
729 if (top < bottom)
730 context.fillRect (Rectangle<float> ((float) x, top, 1.0f, bottom - top));
731}
732
733void Graphics::drawHorizontalLine (const int y, float left, float right) const
734{
735 if (left < right)
736 context.fillRect (Rectangle<float> (left, (float) y, right - left, 1.0f));
737}
738
740{
741 context.drawLine (line);
742}
743
744void Graphics::drawLine (float x1, float y1, float x2, float y2) const
745{
746 context.drawLine (Line<float> (x1, y1, x2, y2));
747}
748
749void Graphics::drawLine (float x1, float y1, float x2, float y2, float lineThickness) const
750{
751 drawLine (Line<float> (x1, y1, x2, y2), lineThickness);
752}
753
754void Graphics::drawLine (Line<float> line, const float lineThickness) const
755{
756 Path p;
757 p.addLineSegment (line, lineThickness);
758 fillPath (p);
759}
760
761void Graphics::drawDashedLine (Line<float> line, const float* dashLengths,
762 int numDashLengths, float lineThickness, int n) const
763{
764 jassert (n >= 0 && n < numDashLengths); // your start index must be valid!
765
766 const Point<double> delta ((line.getEnd() - line.getStart()).toDouble());
767 const double totalLen = delta.getDistanceFromOrigin();
768
769 if (totalLen >= 0.1)
770 {
771 const double onePixAlpha = 1.0 / totalLen;
772
773 for (double alpha = 0.0; alpha < 1.0;)
774 {
775 jassert (dashLengths[n] > 0); // can't have zero-length dashes!
776
777 const double lastAlpha = alpha;
778 alpha += dashLengths [n] * onePixAlpha;
779 n = (n + 1) % numDashLengths;
780
781 if ((n & 1) != 0)
782 {
783 const Line<float> segment (line.getStart() + (delta * lastAlpha).toFloat(),
784 line.getStart() + (delta * jmin (1.0, alpha)).toFloat());
785
786 if (lineThickness != 1.0f)
787 drawLine (segment, lineThickness);
788 else
789 context.drawLine (segment);
790 }
791 }
792 }
793}
794
795//==============================================================================
797{
799 context.setInterpolationQuality (newQuality);
800}
801
802//==============================================================================
803void Graphics::drawImageAt (const Image& imageToDraw, int x, int y, bool fillAlphaChannel) const
804{
805 drawImageTransformed (imageToDraw,
806 AffineTransform::translation ((float) x, (float) y),
807 fillAlphaChannel);
808}
809
810void Graphics::drawImage (const Image& imageToDraw, Rectangle<float> targetArea,
811 RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
812{
813 if (imageToDraw.isValid())
814 drawImageTransformed (imageToDraw,
815 placementWithinTarget.getTransformToFit (imageToDraw.getBounds().toFloat(), targetArea),
816 fillAlphaChannelWithCurrentBrush);
817}
818
819void Graphics::drawImageWithin (const Image& imageToDraw, int dx, int dy, int dw, int dh,
820 RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush) const
821{
822 drawImage (imageToDraw, coordsToRectangle (dx, dy, dw, dh).toFloat(),
823 placementWithinTarget, fillAlphaChannelWithCurrentBrush);
824}
825
826void Graphics::drawImage (const Image& imageToDraw,
827 int dx, int dy, int dw, int dh,
828 int sx, int sy, int sw, int sh,
829 const bool fillAlphaChannelWithCurrentBrush) const
830{
831 if (imageToDraw.isValid() && context.clipRegionIntersects (coordsToRectangle (dx, dy, dw, dh)))
832 drawImageTransformed (imageToDraw.getClippedImage (coordsToRectangle (sx, sy, sw, sh)),
833 AffineTransform::scale ((float) dw / (float) sw, (float) dh / (float) sh)
834 .translated ((float) dx, (float) dy),
835 fillAlphaChannelWithCurrentBrush);
836}
837
838void Graphics::drawImageTransformed (const Image& imageToDraw,
839 const AffineTransform& transform,
840 const bool fillAlphaChannelWithCurrentBrush) const
841{
842 if (imageToDraw.isValid() && ! context.isClipEmpty())
843 {
844 if (fillAlphaChannelWithCurrentBrush)
845 {
846 context.saveState();
847 context.clipToImageAlpha (imageToDraw, transform);
848 fillAll();
849 context.restoreState();
850 }
851 else
852 {
853 context.drawImage (imageToDraw, transform);
854 }
855 }
856}
857
858//==============================================================================
863
868
869} // namespace juce
#define noexcept
Definition DistrhoDefines.h:72
#define final
Definition DistrhoDefines.h:74
static void drawLine(const Point< T > &posStart, const Point< T > &posEnd)
Definition OpenGL.cpp:79
uint8_t a
Definition Spc_Cpu.h:141
Definition juce_AffineTransform.h:43
static AffineTransform scale(float factorX, float factorY) noexcept
Definition juce_AffineTransform.cpp:141
static AffineTransform translation(float deltaX, float deltaY) noexcept
Definition juce_AffineTransform.cpp:81
Definition juce_ColourGradient.h:38
Definition juce_Colour.h:38
bool isTransparent() const noexcept
Definition juce_Colour.cpp:307
Definition juce_FillType.h:41
Definition juce_Font.h:42
static bool compare(const Font &, const Font &) noexcept
Definition juce_Font.cpp:426
Definition juce_GlyphArrangement.h:117
void addLineOfText(const Font &font, const String &text, float x, float y)
Definition juce_GlyphArrangement.cpp:144
Rectangle< float > getBoundingBox(int startIndex, int numGlyphs, bool includeWhitespace) const
Definition juce_GlyphArrangement.cpp:441
int getNumGlyphs() const noexcept
Definition juce_GlyphArrangement.h:133
void addFittedText(const Font &font, const String &text, float x, float y, float width, float height, Justification layout, int maximumLinesToUse, float minimumHorizontalScale=0.0f)
Definition juce_GlyphArrangement.cpp:310
void addCurtailedLineOfText(const Font &font, const String &text, float x, float y, float maxWidthPixels, bool useEllipsis)
Definition juce_GlyphArrangement.cpp:149
void addJustifiedText(const Font &font, const String &text, float x, float y, float maxLineWidth, Justification horizontalLayout, float leading=0.0f)
Definition juce_GlyphArrangement.cpp:228
void justifyGlyphs(int startIndex, int numGlyphs, float x, float y, float width, float height, Justification justification)
Definition juce_GlyphArrangement.cpp:461
~ScopedSaveState()
Definition juce_GraphicsContext.cpp:864
Graphics & context
Definition juce_GraphicsContext.h:666
ScopedSaveState(Graphics &)
Definition juce_GraphicsContext.cpp:859
void saveState()
Definition juce_GraphicsContext.cpp:221
void drawImage(const Image &imageToDraw, int destX, int destY, int destWidth, int destHeight, int sourceX, int sourceY, int sourceWidth, int sourceHeight, bool fillAlphaChannelWithCurrentBrush=false) const
Definition juce_GraphicsContext.cpp:826
void setOpacity(float newOpacity)
Definition juce_GraphicsContext.cpp:284
void drawText(const String &text, int x, int y, int width, int height, Justification justificationType, bool useEllipsesIfTooBig=true) const
Definition juce_GraphicsContext.cpp:456
void saveStateIfPending()
Definition juce_GraphicsContext.cpp:235
void drawFittedText(const String &text, int x, int y, int width, int height, Justification justificationFlags, int maximumNumberOfLines, float minimumHorizontalScale=0.0f) const
Definition juce_GraphicsContext.cpp:500
Font getCurrentFont() const
Definition juce_GraphicsContext.cpp:325
void setFont(const Font &newFont)
Definition juce_GraphicsContext.cpp:314
void fillRectList(const RectangleList< float > &rectangles) const
Definition juce_GraphicsContext.cpp:530
void restoreState()
Definition juce_GraphicsContext.cpp:227
ResamplingQuality
Definition juce_GraphicsContext.h:462
@ mediumResamplingQuality
Definition juce_GraphicsContext.h:464
bool isClipEmpty() const
Definition juce_GraphicsContext.cpp:211
void setFillType(const FillType &newFill)
Definition juce_GraphicsContext.cpp:307
void drawImageAt(const Image &imageToDraw, int topLeftX, int topLeftY, bool fillAlphaChannelWithCurrentBrush=false) const
Definition juce_GraphicsContext.cpp:803
void drawArrow(Line< float > line, float lineThickness, float arrowheadWidth, float arrowheadLength) const
Definition juce_GraphicsContext.cpp:672
void drawImageWithin(const Image &imageToDraw, int destX, int destY, int destWidth, int destHeight, RectanglePlacement placementWithinTarget, bool fillAlphaChannelWithCurrentBrush=false) const
Definition juce_GraphicsContext.cpp:819
void setGradientFill(const ColourGradient &gradient)
Definition juce_GraphicsContext.cpp:290
void setImageResamplingQuality(const ResamplingQuality newQuality)
Definition juce_GraphicsContext.cpp:796
void fillRoundedRectangle(float x, float y, float width, float height, float cornerSize) const
Definition juce_GraphicsContext.cpp:647
void excludeClipRegion(Rectangle< int > rectangleToExclude)
Definition juce_GraphicsContext.cpp:205
void drawRect(int x, int y, int width, int height, int lineThickness=1) const
Definition juce_GraphicsContext.cpp:588
void endTransparencyLayer()
Definition juce_GraphicsContext.cpp:272
void drawImageTransformed(const Image &imageToDraw, const AffineTransform &transform, bool fillAlphaChannelWithCurrentBrush=false) const
Definition juce_GraphicsContext.cpp:838
LowLevelGraphicsContext & context
Definition juce_GraphicsContext.h:741
void setTiledImageFill(const Image &imageToUse, int anchorX, int anchorY, float opacity)
Definition juce_GraphicsContext.cpp:300
void addTransform(const AffineTransform &transform)
Definition juce_GraphicsContext.cpp:255
bool clipRegionIntersects(Rectangle< int > area) const
Definition juce_GraphicsContext.cpp:261
void fillRect(Rectangle< int > rectangle) const
Definition juce_GraphicsContext.cpp:510
void drawVerticalLine(int x, float top, float bottom) const
Definition juce_GraphicsContext.cpp:727
void beginTransparencyLayer(float layerOpacity)
Definition juce_GraphicsContext.cpp:266
void drawMultiLineText(const String &text, int startX, int baselineY, int maximumLineWidth, Justification justification=Justification::left, float leading=0.0f) const
Definition juce_GraphicsContext.cpp:382
void fillPath(const Path &path) const
Definition juce_GraphicsContext.cpp:561
Graphics(const Image &imageToDrawOnto)
Definition juce_GraphicsContext.cpp:148
void resetToDefaultState()
Definition juce_GraphicsContext.cpp:161
void drawEllipse(float x, float y, float width, float height, float lineThickness) const
Definition juce_GraphicsContext.cpp:623
void drawSingleLineText(const String &text, int startX, int baselineY, Justification justification=Justification::left) const
Definition juce_GraphicsContext.cpp:331
bool reduceClipRegion(int x, int y, int width, int height)
Definition juce_GraphicsContext.cpp:180
bool saveStatePending
Definition juce_GraphicsContext.h:743
void fillCheckerBoard(Rectangle< float > area, float checkWidth, float checkHeight, Colour colour1, Colour colour2) const
Definition juce_GraphicsContext.cpp:679
Rectangle< int > getClipBounds() const
Definition juce_GraphicsContext.cpp:216
bool isVectorDevice() const
Definition juce_GraphicsContext.cpp:169
void drawHorizontalLine(int y, float left, float right) const
Definition juce_GraphicsContext.cpp:733
void setColour(Colour newColour)
Definition juce_GraphicsContext.cpp:278
std::unique_ptr< LowLevelGraphicsContext > contextHolder
Definition juce_GraphicsContext.h:740
void drawLine(float startX, float startY, float endX, float endY) const
Definition juce_GraphicsContext.cpp:744
void strokePath(const Path &path, const PathStrokeType &strokeType, const AffineTransform &transform={}) const
Definition juce_GraphicsContext.cpp:573
void fillAll() const
Definition juce_GraphicsContext.cpp:541
void setOrigin(Point< int > newOrigin)
Definition juce_GraphicsContext.cpp:244
void drawRoundedRectangle(float x, float y, float width, float height, float cornerSize, float lineThickness) const
Definition juce_GraphicsContext.cpp:659
void drawDashedLine(Line< float > line, const float *dashLengths, int numDashLengths, float lineThickness=1.0f, int dashIndexToStartFrom=0) const
Definition juce_GraphicsContext.cpp:761
void fillEllipse(float x, float y, float width, float height) const
Definition juce_GraphicsContext.cpp:618
Definition juce_Image.h:58
Image getClippedImage(const Rectangle< int > &area) const
Definition juce_Image.cpp:210
Rectangle< int > getBounds() const noexcept
Definition juce_Image.cpp:273
bool isValid() const noexcept
Definition juce_Image.h:147
Definition juce_Justification.h:41
@ horizontallyJustified
Definition juce_Justification.h:132
@ left
Definition juce_Justification.h:108
@ horizontallyCentred
Definition juce_Justification.h:115
@ right
Definition juce_Justification.h:111
int getOnlyVerticalFlags() const noexcept
Definition juce_Justification.h:66
int getOnlyHorizontalFlags() const noexcept
Definition juce_Justification.h:69
Definition juce_Line.h:47
Point< ValueType > getEnd() const noexcept
Definition juce_Line.h:91
Point< ValueType > getStart() const noexcept
Definition juce_Line.h:88
Definition juce_LowLevelGraphicsContext.h:46
Definition juce_Path.h:65
bool isEmpty() const noexcept
Definition juce_Path.cpp:179
Definition juce_PathStrokeType.h:42
void createStrokedPath(Path &destPath, const Path &sourcePath, const AffineTransform &transform=AffineTransform(), float extraAccuracy=1.0f) const
Definition juce_PathStrokeType.cpp:655
Definition juce_Point.h:42
ValueType getDistanceFromOrigin() const noexcept
Definition juce_Point.h:157
Definition juce_Rectangle.h:67
Rectangle< float > toFloat() const noexcept
Definition juce_Rectangle.h:873
Rectangle< int > getSmallestIntegerContainer() const noexcept
Definition juce_Rectangle.h:840
ValueType getHeight() const noexcept
Definition juce_Rectangle.h:136
ValueType getX() const noexcept
Definition juce_Rectangle.h:127
ValueType getWidth() const noexcept
Definition juce_Rectangle.h:133
Rectangle reduced(ValueType deltaX, ValueType deltaY) const noexcept
Definition juce_Rectangle.h:485
bool isEmpty() const noexcept
Definition juce_Rectangle.h:121
ValueType getY() const noexcept
Definition juce_Rectangle.h:130
Rectangle expanded(ValueType deltaX, ValueType deltaY) const noexcept
Definition juce_Rectangle.h:451
Definition juce_RectangleList.h:43
void addWithoutMerging(RectangleType rect)
Definition juce_RectangleList.h:180
bool clipTo(RectangleType rect)
Definition juce_RectangleList.h:314
Definition juce_RectanglePlacement.h:40
AffineTransform getTransformToFit(const Rectangle< float > &source, const Rectangle< float > &destination) const noexcept
Definition juce_RectanglePlacement.cpp:82
Definition juce_String.h:53
UINT_D64 w
Definition inflate.c:942
struct huft * t
Definition inflate.c:943
int y
Definition inflate.c:1588
int g
Definition inflate.c:1573
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
struct @113205115357366127300225113341150224053346037032::@137033172036070230260373056156374243321245367362 left
struct @113205115357366127300225113341150224053346037032::@137033172036070230260373056156374243321245367362 right
static int int height
Definition pugl.h:1594
static int width
Definition pugl.h:1593
#define jassert(expression)
#define jassertquiet(expression)
#define JUCE_DECLARE_SINGLETON(Classname, doNotRecreateAfterDeletion)
Definition juce_Singleton.h:184
Definition carla_juce.cpp:31
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
CriticalSection::ScopedTryLockType ScopedTryLock
Definition juce_CriticalSection.h:260
static auto tie(const AudioDeviceManager::AudioDeviceSetup &s)
Definition juce_AudioDeviceManager.cpp:41
@ image
Definition juce_AccessibilityRole.h:42
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags
Definition juce_linux_JackAudio.cpp:69
Definition juce_GraphicsContext.cpp:30
static auto compareFont(const Font &a, const Font &b)
Definition juce_GraphicsContext.cpp:31
const char * text
Definition swell-functions.h:167
void Rectangle(HDC ctx, int l, int t, int r, int b)
Definition swell-gdi-generic.cpp:279
int n
Definition crypt.c:458
uch * p
Definition crypt.c:594
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
b
Definition crypt.c:628
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
dy
Definition zipinfo.c:2288