LMMS
Loading...
Searching...
No Matches
juce_RenderingHelpers.h
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
32{
33
34//==============================================================================
40{
41public:
44
46
52
53 AffineTransform getTransformWith (const AffineTransform& userTransform) const noexcept
54 {
55 return isOnlyTranslated ? userTransform.translated (offset)
56 : userTransform.followedBy (complexTransform);
57 }
58
60 {
61 return isOnlyTranslated && offset.isOrigin();
62 }
63
64 void setOrigin (Point<int> delta) noexcept
65 {
67 offset += delta;
68 else
70 .followedBy (complexTransform);
71 }
72
73 void addTransform (const AffineTransform& t) noexcept
74 {
75 if (isOnlyTranslated && t.isOnlyTranslation())
76 {
77 auto tx = (int) (t.getTranslationX() * 256.0f);
78 auto ty = (int) (t.getTranslationY() * 256.0f);
79
80 if (((tx | ty) & 0xf8) == 0)
81 {
82 offset += Point<int> (tx >> 8, ty >> 8);
83 return;
84 }
85 }
86
88 isOnlyTranslated = false;
89 isRotated = (complexTransform.mat01 != 0.0f || complexTransform.mat10 != 0.0f
90 || complexTransform.mat00 < 0 || complexTransform.mat11 < 0);
91 }
92
94 {
95 return isOnlyTranslated ? 1.0f : std::sqrt (std::abs (complexTransform.getDeterminant()));
96 }
97
98 void moveOriginInDeviceSpace (Point<int> delta) noexcept
99 {
101 offset += delta;
102 else
103 complexTransform = complexTransform.translated (delta);
104 }
105
107 {
109 return r + offset;
110 }
111
113 {
115 return r + offset.toFloat();
116 }
117
118 template <typename RectangleOrPoint>
119 RectangleOrPoint transformed (RectangleOrPoint r) const noexcept
120 {
122 return r.transformedBy (complexTransform);
123 }
124
125 template <typename Type>
127 {
128 return isOnlyTranslated ? r - offset
129 : r.transformedBy (complexTransform.inverted());
130 }
131
134 bool isOnlyTranslated = true, isRotated = false;
135};
136
137//==============================================================================
142template <class CachedGlyphType, class RenderTargetType>
144{
145public:
147 {
148 reset();
149 }
150
151 ~GlyphCache() override
152 {
153 getSingletonPointer() = nullptr;
154 }
155
157 {
158 auto& g = getSingletonPointer();
159
160 if (g == nullptr)
161 g = new GlyphCache();
162
163 return *g;
164 }
165
166 //==============================================================================
167 void reset()
168 {
169 const ScopedLock sl (lock);
170 glyphs.clear();
171 addNewGlyphSlots (120);
172 hits = 0;
173 misses = 0;
174 }
175
176 void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point<float> pos)
177 {
178 if (auto glyph = findOrCreateGlyph (font, glyphNumber))
179 {
180 glyph->lastAccessCount = ++accessCounter;
181 glyph->draw (target, pos);
182 }
183 }
184
186 {
187 const ScopedLock sl (lock);
188
189 if (auto g = findExistingGlyph (font, glyphNumber))
190 {
191 ++hits;
192 return g;
193 }
194
195 ++misses;
196 auto g = getGlyphForReuse();
197 jassert (g != nullptr);
198 g->generate (font, glyphNumber);
199 return g;
200 }
201
202private:
206
207 ReferenceCountedObjectPtr<CachedGlyphType> findExistingGlyph (const Font& font, int glyphNumber) const noexcept
208 {
209 for (auto g : glyphs)
210 if (g->glyph == glyphNumber && g->font == font)
211 return *g;
212
213 return {};
214 }
215
217 {
218 if (hits.get() + misses.get() > glyphs.size() * 16)
219 {
220 if (misses.get() * 2 > hits.get())
221 addNewGlyphSlots (32);
222
223 hits = 0;
224 misses = 0;
225 }
226
227 if (auto g = findLeastRecentlyUsedGlyph())
228 return *g;
229
230 addNewGlyphSlots (32);
231 return glyphs.getLast();
232 }
233
234 void addNewGlyphSlots (int num)
235 {
236 glyphs.ensureStorageAllocated (glyphs.size() + num);
237
238 while (--num >= 0)
239 glyphs.add (new CachedGlyphType());
240 }
241
243 {
244 CachedGlyphType* oldest = nullptr;
245 auto oldestCounter = std::numeric_limits<int>::max();
246
247 for (auto* g : glyphs)
248 {
249 if (g->lastAccessCount <= oldestCounter
250 && g->getReferenceCount() == 1)
251 {
252 oldestCounter = g->lastAccessCount;
253 oldest = g;
254 }
255 }
256
257 return oldest;
258 }
259
261 {
262 static GlyphCache* g = nullptr;
263 return g;
264 }
265
267};
268
269//==============================================================================
274template <class RendererType>
276{
277public:
279
280 void draw (RendererType& state, Point<float> pos) const
281 {
283 pos.x = std::floor (pos.x + 0.5f);
284
285 if (edgeTable != nullptr)
286 state.fillEdgeTable (*edgeTable, pos.x, roundToInt (pos.y));
287 }
288
289 void generate (const Font& newFont, int glyphNumber)
290 {
291 font = newFont;
292 auto typeface = newFont.getTypefacePtr();
293 snapToIntegerCoordinate = typeface->isHinted();
294 glyph = glyphNumber;
295
296 auto fontHeight = font.getHeight();
297 edgeTable.reset (typeface->getEdgeTableForGlyph (glyphNumber,
298 AffineTransform::scale (fontHeight * font.getHorizontalScale(),
299 fontHeight), fontHeight));
300 }
301
303 std::unique_ptr<EdgeTable> edgeTable;
304 int glyph = 0, lastAccessCount = 0;
306
308};
309
310//==============================================================================
317{
319 : left (roundToInt (256.0f * area.getX())),
320 top (roundToInt (256.0f * area.getY())),
321 right (roundToInt (256.0f * area.getRight())),
322 bottom (roundToInt (256.0f * area.getBottom()))
323 {
324 if ((top >> 8) == (bottom >> 8))
325 {
326 topAlpha = bottom - top;
327 bottomAlpha = 0;
328 totalTop = top >> 8;
329 totalBottom = bottom = top = totalTop + 1;
330 }
331 else
332 {
333 if ((top & 255) == 0)
334 {
335 topAlpha = 0;
336 top = totalTop = (top >> 8);
337 }
338 else
339 {
340 topAlpha = 255 - (top & 255);
341 totalTop = (top >> 8);
342 top = totalTop + 1;
343 }
344
345 bottomAlpha = bottom & 255;
346 bottom >>= 8;
347 totalBottom = bottom + (bottomAlpha != 0 ? 1 : 0);
348 }
349
350 if ((left >> 8) == (right >> 8))
351 {
352 leftAlpha = right - left;
353 rightAlpha = 0;
354 totalLeft = (left >> 8);
355 totalRight = right = left = totalLeft + 1;
356 }
357 else
358 {
359 if ((left & 255) == 0)
360 {
361 leftAlpha = 0;
362 left = totalLeft = (left >> 8);
363 }
364 else
365 {
366 leftAlpha = 255 - (left & 255);
367 totalLeft = (left >> 8);
368 left = totalLeft + 1;
369 }
370
371 rightAlpha = right & 255;
372 right >>= 8;
373 totalRight = right + (rightAlpha != 0 ? 1 : 0);
374 }
375 }
376
377 template <class Callback>
387
388 inline bool isOnePixelWide() const noexcept { return right - left == 1 && leftAlpha + rightAlpha == 0; }
389
390 inline int getTopLeftCornerAlpha() const noexcept { return (topAlpha * leftAlpha) >> 8; }
391 inline int getTopRightCornerAlpha() const noexcept { return (topAlpha * rightAlpha) >> 8; }
394
395 //==============================================================================
396 int left, top, right, bottom; // bounds of the solid central area, excluding anti-aliased edges
397 int totalTop, totalLeft, totalBottom, totalRight; // bounds of the total area, including edges
398 int topAlpha, leftAlpha, bottomAlpha, rightAlpha; // alpha of each anti-aliased edge
399};
400
401//==============================================================================
404{
406 struct Linear
407 {
408 Linear (const ColourGradient& gradient, const AffineTransform& transform,
409 const PixelARGB* colours, int numColours)
410 : lookupTable (colours),
411 numEntries (numColours)
412 {
413 jassert (numColours >= 0);
414 auto p1 = gradient.point1;
415 auto p2 = gradient.point2;
416
417 if (! transform.isIdentity())
418 {
419 auto p3 = Line<float> (p2, p1).getPointAlongLine (0.0f, 100.0f);
420
421 p1.applyTransform (transform);
422 p2.applyTransform (transform);
423 p3.applyTransform (transform);
424
425 p2 = Line<float> (p2, p3).findNearestPointTo (p1);
426 }
427
428 vertical = std::abs (p1.x - p2.x) < 0.001f;
429 horizontal = std::abs (p1.y - p2.y) < 0.001f;
430
431 if (vertical)
432 {
433 scale = roundToInt ((double) ((int64_t) numEntries << (int) numScaleBits) / (double) (p2.y - p1.y));
434 start = roundToInt (p1.y * (float) scale);
435 }
436 else if (horizontal)
437 {
438 scale = roundToInt ((double) ((int64_t) numEntries << (int) numScaleBits) / (double) (p2.x - p1.x));
439 start = roundToInt (p1.x * (float) scale);
440 }
441 else
442 {
443 grad = (p2.getY() - p1.y) / (double) (p1.x - p2.x);
444 yTerm = p1.getY() - p1.x / grad;
445 scale = roundToInt ((double) ((int64_t) numEntries << (int) numScaleBits) / (yTerm * grad - (p2.y * grad - p2.x)));
446 grad *= scale;
447 }
448 }
449
450 forcedinline void setY (int y) noexcept
451 {
452 if (vertical)
454 else if (! horizontal)
455 start = roundToInt ((y - yTerm) * grad);
456 }
457
458 inline PixelARGB getPixel (int x) const noexcept
459 {
460 return vertical ? linePix
461 : lookupTable[jlimit (0, numEntries, (x * scale - start) >> (int) numScaleBits)];
462 }
463
464 const PixelARGB* const lookupTable;
465 const int numEntries;
468 double grad, yTerm;
470 enum { numScaleBits = 12 };
471
473 };
474
475 //==============================================================================
477 struct Radial
478 {
479 Radial (const ColourGradient& gradient, const AffineTransform&,
480 const PixelARGB* colours, int numColours)
481 : lookupTable (colours),
482 numEntries (numColours),
483 gx1 (gradient.point1.x),
484 gy1 (gradient.point1.y)
485 {
486 jassert (numColours >= 0);
487 auto diff = gradient.point1 - gradient.point2;
488 maxDist = diff.x * diff.x + diff.y * diff.y;
489 invScale = numEntries / std::sqrt (maxDist);
490 jassert (roundToInt (std::sqrt (maxDist) * invScale) <= numEntries);
491 }
492
493 forcedinline void setY (int y) noexcept
494 {
495 dy = y - gy1;
496 dy *= dy;
497 }
498
499 inline PixelARGB getPixel (int px) const noexcept
500 {
501 auto x = px - gx1;
502 x *= x;
503 x += dy;
504
505 return lookupTable[x >= maxDist ? numEntries : roundToInt (std::sqrt (x) * invScale)];
506 }
507
508 const PixelARGB* const lookupTable;
509 const int numEntries;
510 const double gx1, gy1;
512
514 };
515
516 //==============================================================================
518 struct TransformedRadial : public Radial
519 {
520 TransformedRadial (const ColourGradient& gradient, const AffineTransform& transform,
521 const PixelARGB* colours, int numColours)
522 : Radial (gradient, transform, colours, numColours),
523 inverseTransform (transform.inverted())
524 {
525 tM10 = inverseTransform.mat10;
526 tM00 = inverseTransform.mat00;
527 }
528
529 forcedinline void setY (int y) noexcept
530 {
531 auto floatY = (float) y;
532 lineYM01 = inverseTransform.mat01 * floatY + inverseTransform.mat02 - gx1;
533 lineYM11 = inverseTransform.mat11 * floatY + inverseTransform.mat12 - gy1;
534 }
535
536 inline PixelARGB getPixel (int px) const noexcept
537 {
538 double x = px;
539 auto y = tM10 * x + lineYM11;
540 x = tM00 * x + lineYM01;
541 x *= x;
542 x += y * y;
543
544 if (x >= maxDist)
545 return lookupTable[numEntries];
546
547 return lookupTable[jmin (numEntries, roundToInt (std::sqrt (x) * invScale))];
548 }
549
550 private:
553
555 };
556}
557
558#define JUCE_PERFORM_PIXEL_OP_LOOP(op) \
559{ \
560 const int destStride = destData.pixelStride; \
561 do { dest->op; dest = addBytesToPointer (dest, destStride); } while (--width > 0); \
562}
563
564//==============================================================================
567{
569 template <class PixelType, bool replaceExisting = false>
571 {
573 : destData (image), sourceColour (colour)
574 {
575 if (sizeof (PixelType) == 3 && (size_t) destData.pixelStride == sizeof (PixelType))
576 areRGBComponentsEqual = sourceColour.getRed() == sourceColour.getGreen()
577 && sourceColour.getGreen() == sourceColour.getBlue();
578 else
579 areRGBComponentsEqual = false;
580 }
581
582 forcedinline void setEdgeTableYPos (int y) noexcept
583 {
584 linePixels = (PixelType*) destData.getLinePointer (y);
585 }
586
587 forcedinline void handleEdgeTablePixel (int x, int alphaLevel) const noexcept
588 {
589 if (replaceExisting)
590 getPixel (x)->set (sourceColour);
591 else
592 getPixel (x)->blend (sourceColour, (uint32) alphaLevel);
593 }
594
595 forcedinline void handleEdgeTablePixelFull (int x) const noexcept
596 {
597 if (replaceExisting)
598 getPixel (x)->set (sourceColour);
599 else
600 getPixel (x)->blend (sourceColour);
601 }
602
603 forcedinline void handleEdgeTableLine (int x, int width, int alphaLevel) const noexcept
604 {
605 auto p = sourceColour;
606 p.multiplyAlpha (alphaLevel);
607
608 auto* dest = getPixel (x);
609
610 if (replaceExisting || p.getAlpha() >= 0xff)
611 replaceLine (dest, p, width);
612 else
613 blendLine (dest, p, width);
614 }
615
616 forcedinline void handleEdgeTableLineFull (int x, int width) const noexcept
617 {
618 auto* dest = getPixel (x);
619
620 if (replaceExisting || sourceColour.getAlpha() >= 0xff)
622 else
624 }
625
626 void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
627 {
628 auto p = sourceColour;
629 p.multiplyAlpha (alphaLevel);
630
632 auto* dest = getPixel (x);
633
634 if (replaceExisting || p.getAlpha() >= 0xff)
635 {
636 while (--height >= 0)
637 {
638 replaceLine (dest, p, width);
639 dest = addBytesToPointer (dest, destData.lineStride);
640 }
641 }
642 else
643 {
644 while (--height >= 0)
645 {
646 blendLine (dest, p, width);
647 dest = addBytesToPointer (dest, destData.lineStride);
648 }
649 }
650 }
651
652 void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
653 {
655 }
656
657 private:
659 PixelType* linePixels;
662
663 forcedinline PixelType* getPixel (int x) const noexcept
664 {
665 return addBytesToPointer (linePixels, x * destData.pixelStride);
666 }
667
668 inline void blendLine (PixelType* dest, PixelARGB colour, int width) const noexcept
669 {
670 JUCE_PERFORM_PIXEL_OP_LOOP (blend (colour))
671 }
672
673 forcedinline void replaceLine (PixelRGB* dest, PixelARGB colour, int width) const noexcept
674 {
675 if ((size_t) destData.pixelStride == sizeof (*dest) && areRGBComponentsEqual)
676 memset ((void*) dest, colour.getRed(), (size_t) width * 3); // if all the component values are the same, we can cheat..
677 else
678 JUCE_PERFORM_PIXEL_OP_LOOP (set (colour));
679 }
680
681 forcedinline void replaceLine (PixelAlpha* dest, const PixelARGB colour, int width) const noexcept
682 {
683 if ((size_t) destData.pixelStride == sizeof (*dest))
684 memset ((void*) dest, colour.getAlpha(), (size_t) width);
685 else
686 JUCE_PERFORM_PIXEL_OP_LOOP (setAlpha (colour.getAlpha()))
687 }
688
689 forcedinline void replaceLine (PixelARGB* dest, const PixelARGB colour, int width) const noexcept
690 {
691 JUCE_PERFORM_PIXEL_OP_LOOP (set (colour))
692 }
693
695 };
696
697 //==============================================================================
699 template <class PixelType, class GradientType>
700 struct Gradient : public GradientType
701 {
702 Gradient (const Image::BitmapData& dest, const ColourGradient& gradient, const AffineTransform& transform,
703 const PixelARGB* colours, int numColours)
704 : GradientType (gradient, transform, colours, numColours - 1),
705 destData (dest)
706 {
707 }
708
709 forcedinline void setEdgeTableYPos (int y) noexcept
710 {
711 linePixels = (PixelType*) destData.getLinePointer (y);
712 GradientType::setY (y);
713 }
714
715 forcedinline void handleEdgeTablePixel (int x, int alphaLevel) const noexcept
716 {
717 getPixel (x)->blend (GradientType::getPixel (x), (uint32) alphaLevel);
718 }
719
720 forcedinline void handleEdgeTablePixelFull (int x) const noexcept
721 {
722 getPixel (x)->blend (GradientType::getPixel (x));
723 }
724
725 void handleEdgeTableLine (int x, int width, int alphaLevel) const noexcept
726 {
727 auto* dest = getPixel (x);
728
729 if (alphaLevel < 0xff)
730 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++), (uint32) alphaLevel))
731 else
732 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++)))
733 }
734
735 void handleEdgeTableLineFull (int x, int width) const noexcept
736 {
737 auto* dest = getPixel (x);
738 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++)))
739 }
740
741 void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
742 {
743 while (--height >= 0)
744 {
746 handleEdgeTableLine (x, width, alphaLevel);
747 }
748 }
749
750 void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
751 {
752 while (--height >= 0)
753 {
756 }
757 }
758
759 private:
761 PixelType* linePixels;
762
763 forcedinline PixelType* getPixel (int x) const noexcept
764 {
765 return addBytesToPointer (linePixels, x * destData.pixelStride);
766 }
767
769 };
770
771 //==============================================================================
773 template <class DestPixelType, class SrcPixelType, bool repeatPattern>
775 {
776 ImageFill (const Image::BitmapData& dest, const Image::BitmapData& src, int alpha, int x, int y)
777 : destData (dest),
778 srcData (src),
779 extraAlpha (alpha + 1),
780 xOffset (repeatPattern ? negativeAwareModulo (x, src.width) - src.width : x),
781 yOffset (repeatPattern ? negativeAwareModulo (y, src.height) - src.height : y)
782 {
783 }
784
785 forcedinline void setEdgeTableYPos (int y) noexcept
786 {
787 linePixels = (DestPixelType*) destData.getLinePointer (y);
788 y -= yOffset;
789
790 if (repeatPattern)
791 {
792 jassert (y >= 0);
793 y %= srcData.height;
794 }
795
796 sourceLineStart = (SrcPixelType*) srcData.getLinePointer (y);
797 }
798
799 forcedinline void handleEdgeTablePixel (int x, int alphaLevel) const noexcept
800 {
801 alphaLevel = (alphaLevel * extraAlpha) >> 8;
802
803 getDestPixel (x)->blend (*getSrcPixel (repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)), (uint32) alphaLevel);
804 }
805
806 forcedinline void handleEdgeTablePixelFull (int x) const noexcept
807 {
808 getDestPixel (x)->blend (*getSrcPixel (repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)), (uint32) extraAlpha);
809 }
810
811 void handleEdgeTableLine (int x, int width, int alphaLevel) const noexcept
812 {
813 auto* dest = getDestPixel (x);
814 alphaLevel = (alphaLevel * extraAlpha) >> 8;
815 x -= xOffset;
816
817 if (repeatPattern)
818 {
819 if (alphaLevel < 0xfe)
820 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width), (uint32) alphaLevel))
821 else
822 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width)))
823 }
824 else
825 {
826 jassert (x >= 0 && x + width <= srcData.width);
827
828 if (alphaLevel < 0xfe)
829 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++), (uint32) alphaLevel))
830 else
831 copyRow (dest, getSrcPixel (x), width);
832 }
833 }
834
835 void handleEdgeTableLineFull (int x, int width) const noexcept
836 {
837 auto* dest = getDestPixel (x);
838 x -= xOffset;
839
840 if (repeatPattern)
841 {
842 if (extraAlpha < 0xfe)
844 else
845 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width)))
846 }
847 else
848 {
849 jassert (x >= 0 && x + width <= srcData.width);
850
851 if (extraAlpha < 0xfe)
853 else
854 copyRow (dest, getSrcPixel (x), width);
855 }
856 }
857
858 void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
859 {
860 while (--height >= 0)
861 {
863 handleEdgeTableLine (x, width, alphaLevel);
864 }
865 }
866
867 void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
868 {
869 while (--height >= 0)
870 {
873 }
874 }
875
876 void clipEdgeTableLine (EdgeTable& et, int x, int y, int width)
877 {
878 jassert (x - xOffset >= 0 && x + width - xOffset <= srcData.width);
879 auto* s = (SrcPixelType*) srcData.getLinePointer (y - yOffset);
880 auto* mask = (uint8*) (s + x - xOffset);
881
882 if (sizeof (SrcPixelType) == sizeof (PixelARGB))
884
885 et.clipLineToMask (x, y, mask, sizeof (SrcPixelType), width);
886 }
887
888 private:
892 DestPixelType* linePixels;
893 SrcPixelType* sourceLineStart;
894
895 forcedinline DestPixelType* getDestPixel (int x) const noexcept
896 {
897 return addBytesToPointer (linePixels, x * destData.pixelStride);
898 }
899
900 forcedinline SrcPixelType const* getSrcPixel (int x) const noexcept
901 {
902 return addBytesToPointer (sourceLineStart, x * srcData.pixelStride);
903 }
904
905 forcedinline void copyRow (DestPixelType* dest, SrcPixelType const* src, int width) const noexcept
906 {
907 auto destStride = destData.pixelStride;
908 auto srcStride = srcData.pixelStride;
909
910 if (destStride == srcStride
911 && srcData.pixelFormat == Image::RGB
912 && destData.pixelFormat == Image::RGB)
913 {
914 memcpy ((void*) dest, src, (size_t) (width * srcStride));
915 }
916 else
917 {
918 do
919 {
920 dest->blend (*src);
921 dest = addBytesToPointer (dest, destStride);
922 src = addBytesToPointer (src, srcStride);
923 } while (--width > 0);
924 }
925 }
926
928 };
929
930 //==============================================================================
932 template <class DestPixelType, class SrcPixelType, bool repeatPattern>
934 {
936 const AffineTransform& transform, int alpha, Graphics::ResamplingQuality q)
937 : interpolator (transform,
938 q != Graphics::lowResamplingQuality ? 0.5f : 0.0f,
939 q != Graphics::lowResamplingQuality ? -128 : 0),
940 destData (dest),
941 srcData (src),
942 extraAlpha (alpha + 1),
943 quality (q),
944 maxX (src.width - 1),
945 maxY (src.height - 1)
946 {
947 scratchBuffer.malloc (scratchSize);
948 }
949
950 forcedinline void setEdgeTableYPos (int newY) noexcept
951 {
952 currentY = newY;
953 linePixels = (DestPixelType*) destData.getLinePointer (newY);
954 }
955
956 forcedinline void handleEdgeTablePixel (int x, int alphaLevel) noexcept
957 {
958 SrcPixelType p;
959 generate (&p, x, 1);
960
961 getDestPixel (x)->blend (p, (uint32) (alphaLevel * extraAlpha) >> 8);
962 }
963
965 {
966 SrcPixelType p;
967 generate (&p, x, 1);
968
969 getDestPixel (x)->blend (p, (uint32) extraAlpha);
970 }
971
972 void handleEdgeTableLine (int x, int width, int alphaLevel) noexcept
973 {
974 if (width > (int) scratchSize)
975 {
976 scratchSize = (size_t) width;
977 scratchBuffer.malloc (scratchSize);
978 }
979
980 SrcPixelType* span = scratchBuffer;
981 generate (span, x, width);
982
983 auto* dest = getDestPixel (x);
984 alphaLevel *= extraAlpha;
985 alphaLevel >>= 8;
986
987 if (alphaLevel < 0xfe)
988 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*span++, (uint32) alphaLevel))
989 else
990 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*span++))
991 }
992
994 {
996 }
997
998 void handleEdgeTableRectangle (int x, int y, int width, int height, int alphaLevel) noexcept
999 {
1000 while (--height >= 0)
1001 {
1002 setEdgeTableYPos (y++);
1003 handleEdgeTableLine (x, width, alphaLevel);
1004 }
1005 }
1006
1007 void handleEdgeTableRectangleFull (int x, int y, int width, int height) noexcept
1008 {
1009 while (--height >= 0)
1010 {
1011 setEdgeTableYPos (y++);
1013 }
1014 }
1015
1016 void clipEdgeTableLine (EdgeTable& et, int x, int y, int width)
1017 {
1018 if (width > (int) scratchSize)
1019 {
1020 scratchSize = (size_t) width;
1021 scratchBuffer.malloc (scratchSize);
1022 }
1023
1024 currentY = y;
1025 generate (scratchBuffer.get(), x, width);
1026
1027 et.clipLineToMask (x, y,
1028 reinterpret_cast<uint8*> (scratchBuffer.get()) + SrcPixelType::indexA,
1029 sizeof (SrcPixelType), width);
1030 }
1031
1032 private:
1033 forcedinline DestPixelType* getDestPixel (int x) const noexcept
1034 {
1035 return addBytesToPointer (linePixels, x * destData.pixelStride);
1036 }
1037
1038 //==============================================================================
1039 template <class PixelType>
1040 void generate (PixelType* dest, int x, int numPixels) noexcept
1041 {
1042 this->interpolator.setStartOfLine ((float) x, (float) currentY, numPixels);
1043
1044 do
1045 {
1046 int hiResX, hiResY;
1047 this->interpolator.next (hiResX, hiResY);
1048
1049 int loResX = hiResX >> 8;
1050 int loResY = hiResY >> 8;
1051
1052 if (repeatPattern)
1053 {
1054 loResX = negativeAwareModulo (loResX, srcData.width);
1055 loResY = negativeAwareModulo (loResY, srcData.height);
1056 }
1057
1059 {
1060 if (isPositiveAndBelow (loResX, maxX))
1061 {
1062 if (isPositiveAndBelow (loResY, maxY))
1063 {
1064 // In the centre of the image..
1065 render4PixelAverage (dest, this->srcData.getPixelPointer (loResX, loResY),
1066 hiResX & 255, hiResY & 255);
1067 ++dest;
1068 continue;
1069 }
1070
1071 if (! repeatPattern)
1072 {
1073 // At a top or bottom edge..
1074 if (loResY < 0)
1075 render2PixelAverageX (dest, this->srcData.getPixelPointer (loResX, 0), hiResX & 255);
1076 else
1077 render2PixelAverageX (dest, this->srcData.getPixelPointer (loResX, maxY), hiResX & 255);
1078
1079 ++dest;
1080 continue;
1081 }
1082 }
1083 else
1084 {
1085 if (isPositiveAndBelow (loResY, maxY) && ! repeatPattern)
1086 {
1087 // At a left or right hand edge..
1088 if (loResX < 0)
1089 render2PixelAverageY (dest, this->srcData.getPixelPointer (0, loResY), hiResY & 255);
1090 else
1091 render2PixelAverageY (dest, this->srcData.getPixelPointer (maxX, loResY), hiResY & 255);
1092
1093 ++dest;
1094 continue;
1095 }
1096 }
1097 }
1098
1099 if (! repeatPattern)
1100 {
1101 if (loResX < 0) loResX = 0;
1102 if (loResY < 0) loResY = 0;
1103 if (loResX > maxX) loResX = maxX;
1104 if (loResY > maxY) loResY = maxY;
1105 }
1106
1107 dest->set (*(const PixelType*) this->srcData.getPixelPointer (loResX, loResY));
1108 ++dest;
1109
1110 } while (--numPixels > 0);
1111 }
1112
1113 //==============================================================================
1114 void render4PixelAverage (PixelARGB* dest, const uint8* src, int subPixelX, int subPixelY) noexcept
1115 {
1116 uint32 c[4] = { 256 * 128, 256 * 128, 256 * 128, 256 * 128 };
1117
1118 auto weight = (uint32) ((256 - subPixelX) * (256 - subPixelY));
1119 c[0] += weight * src[0];
1120 c[1] += weight * src[1];
1121 c[2] += weight * src[2];
1122 c[3] += weight * src[3];
1123
1124 src += this->srcData.pixelStride;
1125
1126 weight = (uint32) (subPixelX * (256 - subPixelY));
1127 c[0] += weight * src[0];
1128 c[1] += weight * src[1];
1129 c[2] += weight * src[2];
1130 c[3] += weight * src[3];
1131
1132 src += this->srcData.lineStride;
1133
1134 weight = (uint32) (subPixelX * subPixelY);
1135 c[0] += weight * src[0];
1136 c[1] += weight * src[1];
1137 c[2] += weight * src[2];
1138 c[3] += weight * src[3];
1139
1140 src -= this->srcData.pixelStride;
1141
1142 weight = (uint32) ((256 - subPixelX) * subPixelY);
1143 c[0] += weight * src[0];
1144 c[1] += weight * src[1];
1145 c[2] += weight * src[2];
1146 c[3] += weight * src[3];
1147
1148 dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 16),
1149 (uint8) (c[PixelARGB::indexR] >> 16),
1150 (uint8) (c[PixelARGB::indexG] >> 16),
1151 (uint8) (c[PixelARGB::indexB] >> 16));
1152 }
1153
1154 void render2PixelAverageX (PixelARGB* dest, const uint8* src, uint32 subPixelX) noexcept
1155 {
1156 uint32 c[4] = { 128, 128, 128, 128 };
1157
1158 uint32 weight = 256 - subPixelX;
1159 c[0] += weight * src[0];
1160 c[1] += weight * src[1];
1161 c[2] += weight * src[2];
1162 c[3] += weight * src[3];
1163
1164 src += this->srcData.pixelStride;
1165
1166 weight = subPixelX;
1167 c[0] += weight * src[0];
1168 c[1] += weight * src[1];
1169 c[2] += weight * src[2];
1170 c[3] += weight * src[3];
1171
1172 dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 8),
1173 (uint8) (c[PixelARGB::indexR] >> 8),
1174 (uint8) (c[PixelARGB::indexG] >> 8),
1175 (uint8) (c[PixelARGB::indexB] >> 8));
1176 }
1177
1178 void render2PixelAverageY (PixelARGB* dest, const uint8* src, uint32 subPixelY) noexcept
1179 {
1180 uint32 c[4] = { 128, 128, 128, 128 };
1181
1182 uint32 weight = 256 - subPixelY;
1183 c[0] += weight * src[0];
1184 c[1] += weight * src[1];
1185 c[2] += weight * src[2];
1186 c[3] += weight * src[3];
1187
1188 src += this->srcData.lineStride;
1189
1190 weight = subPixelY;
1191 c[0] += weight * src[0];
1192 c[1] += weight * src[1];
1193 c[2] += weight * src[2];
1194 c[3] += weight * src[3];
1195
1196 dest->setARGB ((uint8) (c[PixelARGB::indexA] >> 8),
1197 (uint8) (c[PixelARGB::indexR] >> 8),
1198 (uint8) (c[PixelARGB::indexG] >> 8),
1199 (uint8) (c[PixelARGB::indexB] >> 8));
1200 }
1201
1202 //==============================================================================
1203 void render4PixelAverage (PixelRGB* dest, const uint8* src, uint32 subPixelX, uint32 subPixelY) noexcept
1204 {
1205 uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 };
1206
1207 uint32 weight = (256 - subPixelX) * (256 - subPixelY);
1208 c[0] += weight * src[0];
1209 c[1] += weight * src[1];
1210 c[2] += weight * src[2];
1211
1212 src += this->srcData.pixelStride;
1213
1214 weight = subPixelX * (256 - subPixelY);
1215 c[0] += weight * src[0];
1216 c[1] += weight * src[1];
1217 c[2] += weight * src[2];
1218
1219 src += this->srcData.lineStride;
1220
1221 weight = subPixelX * subPixelY;
1222 c[0] += weight * src[0];
1223 c[1] += weight * src[1];
1224 c[2] += weight * src[2];
1225
1226 src -= this->srcData.pixelStride;
1227
1228 weight = (256 - subPixelX) * subPixelY;
1229 c[0] += weight * src[0];
1230 c[1] += weight * src[1];
1231 c[2] += weight * src[2];
1232
1233 dest->setARGB ((uint8) 255,
1234 (uint8) (c[PixelRGB::indexR] >> 16),
1235 (uint8) (c[PixelRGB::indexG] >> 16),
1236 (uint8) (c[PixelRGB::indexB] >> 16));
1237 }
1238
1239 void render2PixelAverageX (PixelRGB* dest, const uint8* src, uint32 subPixelX) noexcept
1240 {
1241 uint32 c[3] = { 128, 128, 128 };
1242
1243 const uint32 weight = 256 - subPixelX;
1244 c[0] += weight * src[0];
1245 c[1] += weight * src[1];
1246 c[2] += weight * src[2];
1247
1248 src += this->srcData.pixelStride;
1249
1250 c[0] += subPixelX * src[0];
1251 c[1] += subPixelX * src[1];
1252 c[2] += subPixelX * src[2];
1253
1254 dest->setARGB ((uint8) 255,
1255 (uint8) (c[PixelRGB::indexR] >> 8),
1256 (uint8) (c[PixelRGB::indexG] >> 8),
1257 (uint8) (c[PixelRGB::indexB] >> 8));
1258 }
1259
1260 void render2PixelAverageY (PixelRGB* dest, const uint8* src, uint32 subPixelY) noexcept
1261 {
1262 uint32 c[3] = { 128, 128, 128 };
1263
1264 const uint32 weight = 256 - subPixelY;
1265 c[0] += weight * src[0];
1266 c[1] += weight * src[1];
1267 c[2] += weight * src[2];
1268
1269 src += this->srcData.lineStride;
1270
1271 c[0] += subPixelY * src[0];
1272 c[1] += subPixelY * src[1];
1273 c[2] += subPixelY * src[2];
1274
1275 dest->setARGB ((uint8) 255,
1276 (uint8) (c[PixelRGB::indexR] >> 8),
1277 (uint8) (c[PixelRGB::indexG] >> 8),
1278 (uint8) (c[PixelRGB::indexB] >> 8));
1279 }
1280
1281 //==============================================================================
1282 void render4PixelAverage (PixelAlpha* dest, const uint8* src, uint32 subPixelX, uint32 subPixelY) noexcept
1283 {
1284 uint32 c = 256 * 128;
1285 c += src[0] * ((256 - subPixelX) * (256 - subPixelY));
1286 src += this->srcData.pixelStride;
1287 c += src[0] * (subPixelX * (256 - subPixelY));
1288 src += this->srcData.lineStride;
1289 c += src[0] * (subPixelX * subPixelY);
1290 src -= this->srcData.pixelStride;
1291
1292 c += src[0] * ((256 - subPixelX) * subPixelY);
1293
1294 *((uint8*) dest) = (uint8) (c >> 16);
1295 }
1296
1297 void render2PixelAverageX (PixelAlpha* dest, const uint8* src, uint32 subPixelX) noexcept
1298 {
1299 uint32 c = 128;
1300 c += src[0] * (256 - subPixelX);
1301 src += this->srcData.pixelStride;
1302 c += src[0] * subPixelX;
1303 *((uint8*) dest) = (uint8) (c >> 8);
1304 }
1305
1306 void render2PixelAverageY (PixelAlpha* dest, const uint8* src, uint32 subPixelY) noexcept
1307 {
1308 uint32 c = 128;
1309 c += src[0] * (256 - subPixelY);
1310 src += this->srcData.lineStride;
1311 c += src[0] * subPixelY;
1312 *((uint8*) dest) = (uint8) (c >> 8);
1313 }
1314
1315 //==============================================================================
1317 {
1318 TransformedImageSpanInterpolator (const AffineTransform& transform, float offsetFloat, int offsetInt) noexcept
1319 : inverseTransform (transform.inverted()),
1320 pixelOffset (offsetFloat), pixelOffsetInt (offsetInt)
1321 {}
1322
1323 void setStartOfLine (float sx, float sy, int numPixels) noexcept
1324 {
1325 jassert (numPixels > 0);
1326
1327 sx += pixelOffset;
1328 sy += pixelOffset;
1329 auto x1 = sx, y1 = sy;
1330 sx += (float) numPixels;
1331 inverseTransform.transformPoints (x1, y1, sx, sy);
1332
1333 xBresenham.set ((int) (x1 * 256.0f), (int) (sx * 256.0f), numPixels, pixelOffsetInt);
1334 yBresenham.set ((int) (y1 * 256.0f), (int) (sy * 256.0f), numPixels, pixelOffsetInt);
1335 }
1336
1337 void next (int& px, int& py) noexcept
1338 {
1339 px = xBresenham.n; xBresenham.stepToNext();
1340 py = yBresenham.n; yBresenham.stepToNext();
1341 }
1342
1343 private:
1345 {
1347
1348 void set (int n1, int n2, int steps, int offsetInt) noexcept
1349 {
1350 numSteps = steps;
1351 step = (n2 - n1) / numSteps;
1352 remainder = modulo = (n2 - n1) % numSteps;
1353 n = n1 + offsetInt;
1354
1355 if (modulo <= 0)
1356 {
1357 modulo += numSteps;
1359 --step;
1360 }
1361
1362 modulo -= numSteps;
1363 }
1364
1366 {
1367 modulo += remainder;
1368 n += step;
1369
1370 if (modulo > 0)
1371 {
1372 modulo -= numSteps;
1373 ++n;
1374 }
1375 }
1376
1377 int n;
1378
1379 private:
1381 };
1382
1385 const float pixelOffset;
1387
1389 };
1390
1391 //==============================================================================
1395 const int extraAlpha;
1397 const int maxX, maxY;
1399 DestPixelType* linePixels;
1401 size_t scratchSize = 2048;
1402
1404 };
1405
1406
1407 //==============================================================================
1408 template <class Iterator>
1409 void renderImageTransformed (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData,
1410 int alpha, const AffineTransform& transform, Graphics::ResamplingQuality quality, bool tiledFill)
1411 {
1412 switch (destData.pixelFormat)
1413 {
1414 case Image::ARGB:
1415 switch (srcData.pixelFormat)
1416 {
1417 case Image::ARGB:
1418 if (tiledFill) { TransformedImageFill<PixelARGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1419 else { TransformedImageFill<PixelARGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1420 break;
1421 case Image::RGB:
1422 if (tiledFill) { TransformedImageFill<PixelARGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1423 else { TransformedImageFill<PixelARGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1424 break;
1427 default:
1428 if (tiledFill) { TransformedImageFill<PixelARGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1429 else { TransformedImageFill<PixelARGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1430 break;
1431 }
1432 break;
1433
1434 case Image::RGB:
1435 {
1436 switch (srcData.pixelFormat)
1437 {
1438 case Image::ARGB:
1439 if (tiledFill) { TransformedImageFill<PixelRGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1440 else { TransformedImageFill<PixelRGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1441 break;
1442 case Image::RGB:
1443 if (tiledFill) { TransformedImageFill<PixelRGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1444 else { TransformedImageFill<PixelRGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1445 break;
1448 default:
1449 if (tiledFill) { TransformedImageFill<PixelRGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1450 else { TransformedImageFill<PixelRGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1451 break;
1452 }
1453 break;
1454 }
1455
1458 default:
1459 switch (srcData.pixelFormat)
1460 {
1461 case Image::ARGB:
1462 if (tiledFill) { TransformedImageFill<PixelAlpha, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1463 else { TransformedImageFill<PixelAlpha, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1464 break;
1465 case Image::RGB:
1466 if (tiledFill) { TransformedImageFill<PixelAlpha, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1467 else { TransformedImageFill<PixelAlpha, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1468 break;
1471 default:
1472 if (tiledFill) { TransformedImageFill<PixelAlpha, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1473 else { TransformedImageFill<PixelAlpha, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
1474 break;
1475 }
1476 break;
1477 }
1478 }
1479
1480 template <class Iterator>
1481 void renderImageUntransformed (Iterator& iter, const Image::BitmapData& destData, const Image::BitmapData& srcData, int alpha, int x, int y, bool tiledFill)
1482 {
1483 switch (destData.pixelFormat)
1484 {
1485 case Image::ARGB:
1486 switch (srcData.pixelFormat)
1487 {
1488 case Image::ARGB:
1489 if (tiledFill) { ImageFill<PixelARGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1490 else { ImageFill<PixelARGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1491 break;
1492 case Image::RGB:
1493 if (tiledFill) { ImageFill<PixelARGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1494 else { ImageFill<PixelARGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1495 break;
1498 default:
1499 if (tiledFill) { ImageFill<PixelARGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1500 else { ImageFill<PixelARGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1501 break;
1502 }
1503 break;
1504
1505 case Image::RGB:
1506 switch (srcData.pixelFormat)
1507 {
1508 case Image::ARGB:
1509 if (tiledFill) { ImageFill<PixelRGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1510 else { ImageFill<PixelRGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1511 break;
1512 case Image::RGB:
1513 if (tiledFill) { ImageFill<PixelRGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1514 else { ImageFill<PixelRGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1515 break;
1518 default:
1519 if (tiledFill) { ImageFill<PixelRGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1520 else { ImageFill<PixelRGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1521 break;
1522 }
1523 break;
1524
1527 default:
1528 switch (srcData.pixelFormat)
1529 {
1530 case Image::ARGB:
1531 if (tiledFill) { ImageFill<PixelAlpha, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1532 else { ImageFill<PixelAlpha, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1533 break;
1534 case Image::RGB:
1535 if (tiledFill) { ImageFill<PixelAlpha, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1536 else { ImageFill<PixelAlpha, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1537 break;
1540 default:
1541 if (tiledFill) { ImageFill<PixelAlpha, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1542 else { ImageFill<PixelAlpha, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
1543 break;
1544 }
1545 break;
1546 }
1547 }
1548
1549 template <class Iterator, class DestPixelType>
1550 void renderSolidFill (Iterator& iter, const Image::BitmapData& destData, PixelARGB fillColour, bool replaceContents, DestPixelType*)
1551 {
1552 if (replaceContents)
1553 {
1555 iter.iterate (r);
1556 }
1557 else
1558 {
1560 iter.iterate (r);
1561 }
1562 }
1563
1564 template <class Iterator, class DestPixelType>
1565 void renderGradient (Iterator& iter, const Image::BitmapData& destData, const ColourGradient& g, const AffineTransform& transform,
1566 const PixelARGB* lookupTable, int numLookupEntries, bool isIdentity, DestPixelType*)
1567 {
1568 if (g.isRadial)
1569 {
1570 if (isIdentity)
1571 {
1572 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Radial> renderer (destData, g, transform, lookupTable, numLookupEntries);
1573 iter.iterate (renderer);
1574 }
1575 else
1576 {
1577 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::TransformedRadial> renderer (destData, g, transform, lookupTable, numLookupEntries);
1578 iter.iterate (renderer);
1579 }
1580 }
1581 else
1582 {
1583 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Linear> renderer (destData, g, transform, lookupTable, numLookupEntries);
1584 iter.iterate (renderer);
1585 }
1586 }
1587}
1588
1589//==============================================================================
1590template <class SavedStateType>
1592{
1594 {
1595 Base() = default;
1596 ~Base() override = default;
1597
1599
1600 virtual Ptr clone() const = 0;
1601 virtual Ptr applyClipTo (const Ptr& target) const = 0;
1602
1606 virtual Ptr clipToPath (const Path&, const AffineTransform&) = 0;
1607 virtual Ptr clipToEdgeTable (const EdgeTable&) = 0;
1609 virtual void translate (Point<int> delta) = 0;
1610
1611 virtual bool clipRegionIntersects (Rectangle<int>) const = 0;
1612 virtual Rectangle<int> getClipBounds() const = 0;
1613
1614 virtual void fillRectWithColour (SavedStateType&, Rectangle<int>, PixelARGB colour, bool replaceContents) const = 0;
1615 virtual void fillRectWithColour (SavedStateType&, Rectangle<float>, PixelARGB colour) const = 0;
1616 virtual void fillAllWithColour (SavedStateType&, PixelARGB colour, bool replaceContents) const = 0;
1617 virtual void fillAllWithGradient (SavedStateType&, ColourGradient&, const AffineTransform&, bool isIdentity) const = 0;
1618 virtual void renderImageTransformed (SavedStateType&, const Image&, int alpha, const AffineTransform&, Graphics::ResamplingQuality, bool tiledFill) const = 0;
1619 virtual void renderImageUntransformed (SavedStateType&, const Image&, int alpha, int x, int y, bool tiledFill) const = 0;
1620 };
1621
1622 //==============================================================================
1623 struct EdgeTableRegion : public Base
1624 {
1630 EdgeTableRegion (Rectangle<int> bounds, const Path& p, const AffineTransform& t) : edgeTable (bounds, p, t) {}
1631
1633 EdgeTableRegion& operator= (const EdgeTableRegion&) = delete;
1634
1635 using Ptr = typename Base::Ptr;
1636
1637 Ptr clone() const override { return *new EdgeTableRegion (*this); }
1638 Ptr applyClipTo (const Ptr& target) const override { return target->clipToEdgeTable (edgeTable); }
1639
1641 {
1642 edgeTable.clipToRectangle (r);
1643 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1644 }
1645
1647 {
1648 RectangleList<int> inverse (edgeTable.getMaximumBounds());
1649
1650 if (inverse.subtract (r))
1651 for (auto& i : inverse)
1652 edgeTable.excludeRectangle (i);
1653
1654 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1655 }
1656
1658 {
1659 edgeTable.excludeRectangle (r);
1660 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1661 }
1662
1663 Ptr clipToPath (const Path& p, const AffineTransform& transform) override
1664 {
1665 EdgeTable et (edgeTable.getMaximumBounds(), p, transform);
1666 edgeTable.clipToEdgeTable (et);
1667 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1668 }
1669
1670 Ptr clipToEdgeTable (const EdgeTable& et) override
1671 {
1672 edgeTable.clipToEdgeTable (et);
1673 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1674 }
1675
1677 {
1679
1680 if (transform.isOnlyTranslation())
1681 {
1682 // If our translation doesn't involve any distortion, just use a simple blit..
1683 auto tx = (int) (transform.getTranslationX() * 256.0f);
1684 auto ty = (int) (transform.getTranslationY() * 256.0f);
1685
1686 if (quality == Graphics::lowResamplingQuality || ((tx | ty) & 224) == 0)
1687 {
1688 auto imageX = ((tx + 128) >> 8);
1689 auto imageY = ((ty + 128) >> 8);
1690
1691 if (image.getFormat() == Image::ARGB)
1692 straightClipImage (srcData, imageX, imageY, (PixelARGB*) nullptr);
1693 else
1694 straightClipImage (srcData, imageX, imageY, (PixelAlpha*) nullptr);
1695
1696 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1697 }
1698 }
1699
1700 if (transform.isSingularity())
1701 return Ptr();
1702
1703 {
1704 Path p;
1705 p.addRectangle (0, 0, (float) srcData.width, (float) srcData.height);
1706 EdgeTable et2 (edgeTable.getMaximumBounds(), p, transform);
1707 edgeTable.clipToEdgeTable (et2);
1708 }
1709
1710 if (! edgeTable.isEmpty())
1711 {
1712 if (image.getFormat() == Image::ARGB)
1713 transformedClipImage (srcData, transform, quality, (PixelARGB*) nullptr);
1714 else
1715 transformedClipImage (srcData, transform, quality, (PixelAlpha*) nullptr);
1716 }
1717
1718 return edgeTable.isEmpty() ? Ptr() : Ptr (*this);
1719 }
1720
1721 void translate (Point<int> delta) override
1722 {
1723 edgeTable.translate ((float) delta.x, delta.y);
1724 }
1725
1727 {
1728 return edgeTable.getMaximumBounds().intersects (r);
1729 }
1730
1732 {
1733 return edgeTable.getMaximumBounds();
1734 }
1735
1736 void fillRectWithColour (SavedStateType& state, Rectangle<int> area, PixelARGB colour, bool replaceContents) const override
1737 {
1738 auto totalClip = edgeTable.getMaximumBounds();
1739 auto clipped = totalClip.getIntersection (area);
1740
1741 if (! clipped.isEmpty())
1742 {
1743 EdgeTableRegion et (clipped);
1745 state.fillWithSolidColour (et.edgeTable, colour, replaceContents);
1746 }
1747 }
1748
1749 void fillRectWithColour (SavedStateType& state, Rectangle<float> area, PixelARGB colour) const override
1750 {
1751 auto totalClip = edgeTable.getMaximumBounds().toFloat();
1752 auto clipped = totalClip.getIntersection (area);
1753
1754 if (! clipped.isEmpty())
1755 {
1756 EdgeTableRegion et (clipped);
1758 state.fillWithSolidColour (et.edgeTable, colour, false);
1759 }
1760 }
1761
1762 void fillAllWithColour (SavedStateType& state, PixelARGB colour, bool replaceContents) const override
1763 {
1764 state.fillWithSolidColour (edgeTable, colour, replaceContents);
1765 }
1766
1767 void fillAllWithGradient (SavedStateType& state, ColourGradient& gradient, const AffineTransform& transform, bool isIdentity) const override
1768 {
1769 state.fillWithGradient (edgeTable, gradient, transform, isIdentity);
1770 }
1771
1772 void renderImageTransformed (SavedStateType& state, const Image& src, int alpha, const AffineTransform& transform, Graphics::ResamplingQuality quality, bool tiledFill) const override
1773 {
1774 state.renderImageTransformed (edgeTable, src, alpha, transform, quality, tiledFill);
1775 }
1776
1777 void renderImageUntransformed (SavedStateType& state, const Image& src, int alpha, int x, int y, bool tiledFill) const override
1778 {
1779 state.renderImageUntransformed (edgeTable, src, alpha, x, y, tiledFill);
1780 }
1781
1783
1784 private:
1785 template <class SrcPixelType>
1786 void transformedClipImage (const Image::BitmapData& srcData, const AffineTransform& transform, Graphics::ResamplingQuality quality, const SrcPixelType*)
1787 {
1789
1790 for (int y = 0; y < edgeTable.getMaximumBounds().getHeight(); ++y)
1791 renderer.clipEdgeTableLine (edgeTable, edgeTable.getMaximumBounds().getX(), y + edgeTable.getMaximumBounds().getY(),
1792 edgeTable.getMaximumBounds().getWidth());
1793 }
1794
1795 template <class SrcPixelType>
1796 void straightClipImage (const Image::BitmapData& srcData, int imageX, int imageY, const SrcPixelType*)
1797 {
1798 Rectangle<int> r (imageX, imageY, srcData.width, srcData.height);
1799 edgeTable.clipToRectangle (r);
1800
1801 EdgeTableFillers::ImageFill<SrcPixelType, SrcPixelType, false> renderer (srcData, srcData, 255, imageX, imageY);
1802
1803 for (int y = 0; y < r.getHeight(); ++y)
1804 renderer.clipEdgeTableLine (edgeTable, r.getX(), y + r.getY(), r.getWidth());
1805 }
1806 };
1807
1808 //==============================================================================
1810 {
1811 public:
1815
1816 using Ptr = typename Base::Ptr;
1817
1818 Ptr clone() const override { return *new RectangleListRegion (*this); }
1819 Ptr applyClipTo (const Ptr& target) const override { return target->clipToRectangleList (clip); }
1820
1822 {
1823 clip.clipTo (r);
1824 return clip.isEmpty() ? Ptr() : Ptr (*this);
1825 }
1826
1828 {
1829 clip.clipTo (r);
1830 return clip.isEmpty() ? Ptr() : Ptr (*this);
1831 }
1832
1834 {
1835 clip.subtract (r);
1836 return clip.isEmpty() ? Ptr() : Ptr (*this);
1837 }
1838
1839 Ptr clipToPath (const Path& p, const AffineTransform& transform) override { return toEdgeTable()->clipToPath (p, transform); }
1840 Ptr clipToEdgeTable (const EdgeTable& et) override { return toEdgeTable()->clipToEdgeTable (et); }
1841
1843 {
1844 return toEdgeTable()->clipToImageAlpha (image, transform, quality);
1845 }
1846
1847 void translate (Point<int> delta) override { clip.offsetAll (delta); }
1848 bool clipRegionIntersects (Rectangle<int> r) const override { return clip.intersects (r); }
1849 Rectangle<int> getClipBounds() const override { return clip.getBounds(); }
1850
1851 void fillRectWithColour (SavedStateType& state, Rectangle<int> area, PixelARGB colour, bool replaceContents) const override
1852 {
1853 SubRectangleIterator iter (clip, area);
1854 state.fillWithSolidColour (iter, colour, replaceContents);
1855 }
1856
1857 void fillRectWithColour (SavedStateType& state, Rectangle<float> area, PixelARGB colour) const override
1858 {
1859 SubRectangleIteratorFloat iter (clip, area);
1860 state.fillWithSolidColour (iter, colour, false);
1861 }
1862
1863 void fillAllWithColour (SavedStateType& state, PixelARGB colour, bool replaceContents) const override
1864 {
1865 state.fillWithSolidColour (*this, colour, replaceContents);
1866 }
1867
1868 void fillAllWithGradient (SavedStateType& state, ColourGradient& gradient, const AffineTransform& transform, bool isIdentity) const override
1869 {
1870 state.fillWithGradient (*this, gradient, transform, isIdentity);
1871 }
1872
1873 void renderImageTransformed (SavedStateType& state, const Image& src, int alpha, const AffineTransform& transform, Graphics::ResamplingQuality quality, bool tiledFill) const override
1874 {
1875 state.renderImageTransformed (*this, src, alpha, transform, quality, tiledFill);
1876 }
1877
1878 void renderImageUntransformed (SavedStateType& state, const Image& src, int alpha, int x, int y, bool tiledFill) const override
1879 {
1880 state.renderImageUntransformed (*this, src, alpha, x, y, tiledFill);
1881 }
1882
1884
1885 //==============================================================================
1886 template <class Renderer>
1887 void iterate (Renderer& r) const noexcept
1888 {
1889 for (auto& i : clip)
1890 {
1891 auto x = i.getX();
1892 auto w = i.getWidth();
1893 jassert (w > 0);
1894 auto bottom = i.getBottom();
1895
1896 for (int y = i.getY(); y < bottom; ++y)
1897 {
1898 r.setEdgeTableYPos (y);
1899 r.handleEdgeTableLineFull (x, w);
1900 }
1901 }
1902 }
1903
1904 private:
1905 //==============================================================================
1907 {
1908 public:
1910 : clip (clipList), area (clipBounds)
1911 {}
1912
1913 template <class Renderer>
1914 void iterate (Renderer& r) const noexcept
1915 {
1916 for (auto& i : clip)
1917 {
1918 auto rect = i.getIntersection (area);
1919
1920 if (! rect.isEmpty())
1921 r.handleEdgeTableRectangleFull (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
1922 }
1923 }
1924
1925 private:
1928
1930 };
1931
1932 //==============================================================================
1934 {
1935 public:
1937 : clip (clipList), area (clipBounds)
1938 {
1939 }
1940
1941 template <class Renderer>
1942 void iterate (Renderer& r) const noexcept
1943 {
1945
1946 for (auto& i : clip)
1947 {
1948 auto clipLeft = i.getX();
1949 auto clipRight = i.getRight();
1950 auto clipTop = i.getY();
1951 auto clipBottom = i.getBottom();
1952
1953 if (f.totalBottom > clipTop && f.totalTop < clipBottom
1954 && f.totalRight > clipLeft && f.totalLeft < clipRight)
1955 {
1956 if (f.isOnePixelWide())
1957 {
1958 if (f.topAlpha != 0 && f.totalTop >= clipTop)
1959 {
1960 r.setEdgeTableYPos (f.totalTop);
1961 r.handleEdgeTablePixel (f.left, f.topAlpha);
1962 }
1963
1964 auto y1 = jmax (clipTop, f.top);
1965 auto y2 = jmin (f.bottom, clipBottom);
1966 auto h = y2 - y1;
1967
1968 if (h > 0)
1969 r.handleEdgeTableRectangleFull (f.left, y1, 1, h);
1970
1971 if (f.bottomAlpha != 0 && f.bottom < clipBottom)
1972 {
1973 r.setEdgeTableYPos (f.bottom);
1974 r.handleEdgeTablePixel (f.left, f.bottomAlpha);
1975 }
1976 }
1977 else
1978 {
1979 auto clippedLeft = jmax (f.left, clipLeft);
1980 auto clippedWidth = jmin (f.right, clipRight) - clippedLeft;
1981 bool doLeftAlpha = f.leftAlpha != 0 && f.totalLeft >= clipLeft;
1982 bool doRightAlpha = f.rightAlpha != 0 && f.right < clipRight;
1983
1984 if (f.topAlpha != 0 && f.totalTop >= clipTop)
1985 {
1986 r.setEdgeTableYPos (f.totalTop);
1987
1988 if (doLeftAlpha) r.handleEdgeTablePixel (f.totalLeft, f.getTopLeftCornerAlpha());
1989 if (clippedWidth > 0) r.handleEdgeTableLine (clippedLeft, clippedWidth, f.topAlpha);
1990 if (doRightAlpha) r.handleEdgeTablePixel (f.right, f.getTopRightCornerAlpha());
1991 }
1992
1993 auto y1 = jmax (clipTop, f.top);
1994 auto y2 = jmin (f.bottom, clipBottom);
1995 auto h = y2 - y1;
1996
1997 if (h > 0)
1998 {
1999 if (h == 1)
2000 {
2001 r.setEdgeTableYPos (y1);
2002
2003 if (doLeftAlpha) r.handleEdgeTablePixel (f.totalLeft, f.leftAlpha);
2004 if (clippedWidth > 0) r.handleEdgeTableLineFull (clippedLeft, clippedWidth);
2005 if (doRightAlpha) r.handleEdgeTablePixel (f.right, f.rightAlpha);
2006 }
2007 else
2008 {
2009 if (doLeftAlpha) r.handleEdgeTableRectangle (f.totalLeft, y1, 1, h, f.leftAlpha);
2010 if (clippedWidth > 0) r.handleEdgeTableRectangleFull (clippedLeft, y1, clippedWidth, h);
2011 if (doRightAlpha) r.handleEdgeTableRectangle (f.right, y1, 1, h, f.rightAlpha);
2012 }
2013 }
2014
2015 if (f.bottomAlpha != 0 && f.bottom < clipBottom)
2016 {
2017 r.setEdgeTableYPos (f.bottom);
2018
2019 if (doLeftAlpha) r.handleEdgeTablePixel (f.totalLeft, f.getBottomLeftCornerAlpha());
2020 if (clippedWidth > 0) r.handleEdgeTableLine (clippedLeft, clippedWidth, f.bottomAlpha);
2021 if (doRightAlpha) r.handleEdgeTablePixel (f.right, f.getBottomRightCornerAlpha());
2022 }
2023 }
2024 }
2025 }
2026 }
2027
2028 private:
2031
2033 };
2034
2035 Ptr toEdgeTable() const { return *new EdgeTableRegion (clip); }
2036
2037 RectangleListRegion& operator= (const RectangleListRegion&) = delete;
2038 };
2039};
2040
2041//==============================================================================
2042template <class SavedStateType>
2044{
2045public:
2049
2051 : clip (new RectangleListRegionType (initialClip)),
2052 interpolationQuality (Graphics::mediumResamplingQuality), transparencyLayerAlpha (1.0f)
2053 {
2054 }
2055
2057 : clip (new RectangleListRegionType (clipList)), transform (origin),
2058 interpolationQuality (Graphics::mediumResamplingQuality), transparencyLayerAlpha (1.0f)
2059 {
2060 }
2061
2068
2069 SavedStateType& getThis() noexcept { return *static_cast<SavedStateType*> (this); }
2070
2072 {
2073 if (clip != nullptr)
2074 {
2075 if (transform.isOnlyTranslated)
2076 {
2078 clip = clip->clipToRectangle (transform.translated (r));
2079 }
2080 else if (! transform.isRotated)
2081 {
2083 clip = clip->clipToRectangle (transform.transformed (r));
2084 }
2085 else
2086 {
2087 Path p;
2088 p.addRectangle (r);
2089 clipToPath (p, {});
2090 }
2091 }
2092
2093 return clip != nullptr;
2094 }
2095
2097 {
2098 if (clip != nullptr)
2099 {
2100 if (transform.isOnlyTranslated)
2101 {
2103
2104 if (transform.isIdentity())
2105 {
2106 clip = clip->clipToRectangleList (r);
2107 }
2108 else
2109 {
2110 RectangleList<int> offsetList (r);
2111 offsetList.offsetAll (transform.offset);
2112 clip = clip->clipToRectangleList (offsetList);
2113 }
2114 }
2115 else if (! transform.isRotated)
2116 {
2118 RectangleList<int> scaledList;
2119
2120 for (auto& i : r)
2121 scaledList.add (transform.transformed (i));
2122
2123 clip = clip->clipToRectangleList (scaledList);
2124 }
2125 else
2126 {
2127 clipToPath (r.toPath(), {});
2128 }
2129 }
2130
2131 return clip != nullptr;
2132 }
2133
2135 {
2136 auto x1 = (int) std::ceil (r.getX());
2137 auto y1 = (int) std::ceil (r.getY());
2138 auto x2 = (int) std::floor (r.getRight());
2139 auto y2 = (int) std::floor (r.getBottom());
2140
2141 return { x1, y1, x2 - x1, y2 - y1 };
2142 }
2143
2145 {
2146 if (clip != nullptr)
2147 {
2149
2150 if (transform.isOnlyTranslated)
2151 {
2152 clip = clip->excludeClipRectangle (getLargestIntegerWithin (transform.translated (r.toFloat())));
2153 }
2154 else if (! transform.isRotated)
2155 {
2156 clip = clip->excludeClipRectangle (getLargestIntegerWithin (transform.transformed (r.toFloat())));
2157 }
2158 else
2159 {
2160 Path p;
2161 p.addRectangle (r.toFloat());
2162 p.applyTransform (transform.complexTransform);
2163 p.addRectangle (clip->getClipBounds().toFloat());
2164 p.setUsingNonZeroWinding (false);
2165 clip = clip->clipToPath (p, {});
2166 }
2167 }
2168
2169 return clip != nullptr;
2170 }
2171
2172 void clipToPath (const Path& p, const AffineTransform& t)
2173 {
2174 if (clip != nullptr)
2175 {
2177 clip = clip->clipToPath (p, transform.getTransformWith (t));
2178 }
2179 }
2180
2181 void clipToImageAlpha (const Image& sourceImage, const AffineTransform& t)
2182 {
2183 if (clip != nullptr)
2184 {
2185 if (sourceImage.hasAlphaChannel())
2186 {
2188 clip = clip->clipToImageAlpha (sourceImage, transform.getTransformWith (t), interpolationQuality);
2189 }
2190 else
2191 {
2192 Path p;
2193 p.addRectangle (sourceImage.getBounds());
2194 clipToPath (p, t);
2195 }
2196 }
2197 }
2198
2200 {
2201 if (clip != nullptr)
2202 {
2203 if (transform.isOnlyTranslated)
2204 return clip->clipRegionIntersects (transform.translated (r));
2205
2206 return getClipBounds().intersects (r);
2207 }
2208
2209 return false;
2210 }
2211
2213 {
2214 return clip != nullptr ? transform.deviceSpaceToUserSpace (clip->getClipBounds())
2215 : Rectangle<int>();
2216 }
2217
2218 void setFillType (const FillType& newFill)
2219 {
2220 fillType = newFill;
2221 }
2222
2223 void fillTargetRect (Rectangle<int> r, bool replaceContents)
2224 {
2225 if (fillType.isColour())
2226 {
2227 clip->fillRectWithColour (getThis(), r, fillType.colour.getPixelARGB(), replaceContents);
2228 }
2229 else
2230 {
2231 auto clipped = clip->getClipBounds().getIntersection (r);
2232
2233 if (! clipped.isEmpty())
2234 fillShape (*new RectangleListRegionType (clipped), false);
2235 }
2236 }
2237
2239 {
2240 if (fillType.isColour())
2241 {
2242 clip->fillRectWithColour (getThis(), r, fillType.colour.getPixelARGB());
2243 }
2244 else
2245 {
2246 auto clipped = clip->getClipBounds().toFloat().getIntersection (r);
2247
2248 if (! clipped.isEmpty())
2249 fillShape (*new EdgeTableRegionType (clipped), false);
2250 }
2251 }
2252
2253 template <typename CoordType>
2255 {
2256 Path p;
2257 p.addRectangle (r);
2258 fillPath (p, {});
2259 }
2260
2261 void fillRect (Rectangle<int> r, bool replaceContents)
2262 {
2263 if (clip != nullptr)
2264 {
2265 if (transform.isOnlyTranslated)
2266 {
2267 fillTargetRect (transform.translated (r), replaceContents);
2268 }
2269 else if (! transform.isRotated)
2270 {
2271 fillTargetRect (transform.transformed (r), replaceContents);
2272 }
2273 else
2274 {
2275 jassert (! replaceContents); // not implemented..
2276 fillRectAsPath (r);
2277 }
2278 }
2279 }
2280
2282 {
2283 if (clip != nullptr)
2284 {
2285 if (transform.isOnlyTranslated)
2286 fillTargetRect (transform.translated (r));
2287 else if (! transform.isRotated)
2288 fillTargetRect (transform.transformed (r));
2289 else
2290 fillRectAsPath (r);
2291 }
2292 }
2293
2295 {
2296 if (clip != nullptr)
2297 {
2298 if (list.getNumRectangles() == 1)
2299 return fillRect (*list.begin());
2300
2301 if (transform.isIdentity())
2302 {
2303 fillShape (*new EdgeTableRegionType (list), false);
2304 }
2305 else if (! transform.isRotated)
2306 {
2307 RectangleList<float> transformed (list);
2308
2309 if (transform.isOnlyTranslated)
2310 transformed.offsetAll (transform.offset.toFloat());
2311 else
2312 transformed.transformAll (transform.getTransform());
2313
2314 fillShape (*new EdgeTableRegionType (transformed), false);
2315 }
2316 else
2317 {
2318 fillPath (list.toPath(), {});
2319 }
2320 }
2321 }
2322
2323 void fillPath (const Path& path, const AffineTransform& t)
2324 {
2325 if (clip != nullptr)
2326 {
2327 auto trans = transform.getTransformWith (t);
2328 auto clipRect = clip->getClipBounds();
2329
2330 if (path.getBoundsTransformed (trans).getSmallestIntegerContainer().intersects (clipRect))
2331 fillShape (*new EdgeTableRegionType (clipRect, path, trans), false);
2332 }
2333 }
2334
2335 void fillEdgeTable (const EdgeTable& edgeTable, float x, int y)
2336 {
2337 if (clip != nullptr)
2338 {
2339 auto* edgeTableClip = new EdgeTableRegionType (edgeTable);
2340 edgeTableClip->edgeTable.translate (x, y);
2341
2342 if (fillType.isColour())
2343 {
2344 auto brightness = fillType.colour.getBrightness() - 0.5f;
2345
2346 if (brightness > 0.0f)
2347 edgeTableClip->edgeTable.multiplyLevels (1.0f + 1.6f * brightness);
2348 }
2349
2350 fillShape (*edgeTableClip, false);
2351 }
2352 }
2353
2355 {
2356 Path p;
2357 p.addLineSegment (line, 1.0f);
2358 fillPath (p, {});
2359 }
2360
2361 void drawImage (const Image& sourceImage, const AffineTransform& trans)
2362 {
2363 if (clip != nullptr && ! fillType.colour.isTransparent())
2364 renderImage (sourceImage, trans, {});
2365 }
2366
2367 static bool isOnlyTranslationAllowingError (const AffineTransform& t, float tolerance) noexcept
2368 {
2369 return std::abs (t.mat01) < tolerance
2370 && std::abs (t.mat10) < tolerance
2371 && std::abs (t.mat00 - 1.0f) < tolerance
2372 && std::abs (t.mat11 - 1.0f) < tolerance;
2373 }
2374
2375 void renderImage (const Image& sourceImage, const AffineTransform& trans, const BaseRegionType* tiledFillClipRegion)
2376 {
2377 auto t = transform.getTransformWith (trans);
2378 auto alpha = fillType.colour.getAlpha();
2379
2380 if (isOnlyTranslationAllowingError (t, 0.002f))
2381 {
2382 // If our translation doesn't involve any distortion, just use a simple blit..
2383 auto tx = (int) (t.getTranslationX() * 256.0f);
2384 auto ty = (int) (t.getTranslationY() * 256.0f);
2385
2386 if (interpolationQuality == Graphics::lowResamplingQuality || ((tx | ty) & 224) == 0)
2387 {
2388 tx = ((tx + 128) >> 8);
2389 ty = ((ty + 128) >> 8);
2390
2391 if (tiledFillClipRegion != nullptr)
2392 {
2393 tiledFillClipRegion->renderImageUntransformed (getThis(), sourceImage, alpha, tx, ty, true);
2394 }
2395 else
2396 {
2397 Rectangle<int> area (tx, ty, sourceImage.getWidth(), sourceImage.getHeight());
2398 area = area.getIntersection (getThis().getMaximumBounds());
2399
2400 if (! area.isEmpty())
2401 if (auto c = clip->applyClipTo (*new EdgeTableRegionType (area)))
2402 c->renderImageUntransformed (getThis(), sourceImage, alpha, tx, ty, false);
2403 }
2404
2405 return;
2406 }
2407 }
2408
2409 if (! t.isSingularity())
2410 {
2411 if (tiledFillClipRegion != nullptr)
2412 {
2413 tiledFillClipRegion->renderImageTransformed (getThis(), sourceImage, alpha,
2414 t, interpolationQuality, true);
2415 }
2416 else
2417 {
2418 Path p;
2419 p.addRectangle (sourceImage.getBounds());
2420
2421 if (auto c = clip->clone()->clipToPath (p, t))
2422 c->renderImageTransformed (getThis(), sourceImage, alpha,
2423 t, interpolationQuality, false);
2424 }
2425 }
2426 }
2427
2428 void fillShape (typename BaseRegionType::Ptr shapeToFill, bool replaceContents)
2429 {
2430 jassert (clip != nullptr);
2431 shapeToFill = clip->applyClipTo (shapeToFill);
2432
2433 if (shapeToFill != nullptr)
2434 {
2435 if (fillType.isGradient())
2436 {
2437 jassert (! replaceContents); // that option is just for solid colours
2438
2439 auto g2 = *(fillType.gradient);
2440 g2.multiplyOpacity (fillType.getOpacity());
2441 auto t = transform.getTransformWith (fillType.transform).translated (-0.5f, -0.5f);
2442
2443 bool isIdentity = t.isOnlyTranslation();
2444
2445 if (isIdentity)
2446 {
2447 // If our translation doesn't involve any distortion, we can speed it up..
2448 g2.point1.applyTransform (t);
2449 g2.point2.applyTransform (t);
2450 t = {};
2451 }
2452
2453 shapeToFill->fillAllWithGradient (getThis(), g2, t, isIdentity);
2454 }
2455 else if (fillType.isTiledImage())
2456 {
2457 renderImage (fillType.image, fillType.transform, shapeToFill.get());
2458 }
2459 else
2460 {
2461 shapeToFill->fillAllWithColour (getThis(), fillType.colour.getPixelARGB(), replaceContents);
2462 }
2463 }
2464 }
2465
2467 {
2468 if (clip->getReferenceCount() > 1)
2469 clip = clip->clone();
2470 }
2471
2472 typename BaseRegionType::Ptr clip;
2477};
2478
2479//==============================================================================
2480class SoftwareRendererSavedState : public SavedStateBase<SoftwareRendererSavedState>
2481{
2483
2484public:
2486 : BaseClass (clipBounds), image (im)
2487 {
2488 }
2489
2491 : BaseClass (clipList, origin), image (im)
2492 {
2493 }
2494
2496
2498 {
2499 auto* s = new SoftwareRendererSavedState (*this);
2500
2501 if (clip != nullptr)
2502 {
2503 auto layerBounds = clip->getClipBounds();
2504
2505 s->image = Image (Image::ARGB, layerBounds.getWidth(), layerBounds.getHeight(), true);
2506 s->transparencyLayerAlpha = opacity;
2507 s->transform.moveOriginInDeviceSpace (-layerBounds.getPosition());
2508 s->cloneClipIfMultiplyReferenced();
2509 s->clip->translate (-layerBounds.getPosition());
2510 }
2511
2512 return s;
2513 }
2514
2516 {
2517 if (clip != nullptr)
2518 {
2519 auto layerBounds = clip->getClipBounds();
2520
2521 auto g = image.createLowLevelContext();
2522 g->setOpacity (finishedLayerState.transparencyLayerAlpha);
2523 g->drawImage (finishedLayerState.image, AffineTransform::translation (layerBounds.getPosition()));
2524 }
2525 }
2526
2528
2529 static void clearGlyphCache()
2530 {
2532 }
2533
2534 //==============================================================================
2535 void drawGlyph (int glyphNumber, const AffineTransform& trans)
2536 {
2537 if (clip != nullptr)
2538 {
2539 if (trans.isOnlyTranslation() && ! transform.isRotated)
2540 {
2541 auto& cache = GlyphCacheType::getInstance();
2542 Point<float> pos (trans.getTranslationX(), trans.getTranslationY());
2543
2544 if (transform.isOnlyTranslated)
2545 {
2546 cache.drawGlyph (*this, font, glyphNumber, pos + transform.offset.toFloat());
2547 }
2548 else
2549 {
2550 pos = transform.transformed (pos);
2551
2552 Font f (font);
2553 f.setHeight (font.getHeight() * transform.complexTransform.mat11);
2554
2555 auto xScale = transform.complexTransform.mat00 / transform.complexTransform.mat11;
2556
2557 if (std::abs (xScale - 1.0f) > 0.01f)
2558 f.setHorizontalScale (xScale);
2559
2560 cache.drawGlyph (*this, f, glyphNumber, pos);
2561 }
2562 }
2563 else
2564 {
2565 auto fontHeight = font.getHeight();
2566
2567 auto t = transform.getTransformWith (AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
2568 .followedBy (trans));
2569
2570 std::unique_ptr<EdgeTable> et (font.getTypefacePtr()->getEdgeTableForGlyph (glyphNumber, t, fontHeight));
2571
2572 if (et != nullptr)
2573 fillShape (*new EdgeTableRegionType (*et), false);
2574 }
2575 }
2576 }
2577
2578 Rectangle<int> getMaximumBounds() const { return image.getBounds(); }
2579
2580 //==============================================================================
2581 template <typename IteratorType>
2582 void renderImageTransformed (IteratorType& iter, const Image& src, int alpha, const AffineTransform& trans, Graphics::ResamplingQuality quality, bool tiledFill) const
2583 {
2586 EdgeTableFillers::renderImageTransformed (iter, destData, srcData, alpha, trans, quality, tiledFill);
2587 }
2588
2589 template <typename IteratorType>
2590 void renderImageUntransformed (IteratorType& iter, const Image& src, int alpha, int x, int y, bool tiledFill) const
2591 {
2594 EdgeTableFillers::renderImageUntransformed (iter, destData, srcData, alpha, x, y, tiledFill);
2595 }
2596
2597 template <typename IteratorType>
2598 void fillWithSolidColour (IteratorType& iter, PixelARGB colour, bool replaceContents) const
2599 {
2601
2602 switch (destData.pixelFormat)
2603 {
2604 case Image::ARGB: EdgeTableFillers::renderSolidFill (iter, destData, colour, replaceContents, (PixelARGB*) nullptr); break;
2605 case Image::RGB: EdgeTableFillers::renderSolidFill (iter, destData, colour, replaceContents, (PixelRGB*) nullptr); break;
2608 default: EdgeTableFillers::renderSolidFill (iter, destData, colour, replaceContents, (PixelAlpha*) nullptr); break;
2609 }
2610 }
2611
2612 template <typename IteratorType>
2613 void fillWithGradient (IteratorType& iter, ColourGradient& gradient, const AffineTransform& trans, bool isIdentity) const
2614 {
2615 HeapBlock<PixelARGB> lookupTable;
2616 auto numLookupEntries = gradient.createLookupTable (trans, lookupTable);
2617 jassert (numLookupEntries > 0);
2618
2620
2621 switch (destData.pixelFormat)
2622 {
2623 case Image::ARGB: EdgeTableFillers::renderGradient (iter, destData, gradient, trans, lookupTable, numLookupEntries, isIdentity, (PixelARGB*) nullptr); break;
2624 case Image::RGB: EdgeTableFillers::renderGradient (iter, destData, gradient, trans, lookupTable, numLookupEntries, isIdentity, (PixelRGB*) nullptr); break;
2627 default: EdgeTableFillers::renderGradient (iter, destData, gradient, trans, lookupTable, numLookupEntries, isIdentity, (PixelAlpha*) nullptr); break;
2628 }
2629 }
2630
2631 //==============================================================================
2634
2635private:
2637};
2638
2639//==============================================================================
2640template <class StateObjectType>
2642{
2643public:
2644 SavedStateStack (StateObjectType* initialState) noexcept
2645 : currentState (initialState)
2646 {}
2647
2648 SavedStateStack() = default;
2649
2650 void initialise (StateObjectType* state)
2651 {
2652 currentState.reset (state);
2653 }
2654
2655 inline StateObjectType* operator->() const noexcept { return currentState.get(); }
2656 inline StateObjectType& operator*() const noexcept { return *currentState; }
2657
2658 void save()
2659 {
2660 stack.add (new StateObjectType (*currentState));
2661 }
2662
2663 void restore()
2664 {
2665 if (auto* top = stack.getLast())
2666 {
2667 currentState.reset (top);
2668 stack.removeLast (1, false);
2669 }
2670 else
2671 {
2672 jassertfalse; // trying to pop with an empty stack!
2673 }
2674 }
2675
2676 void beginTransparencyLayer (float opacity)
2677 {
2678 save();
2679 currentState.reset (currentState->beginTransparencyLayer (opacity));
2680 }
2681
2683 {
2684 std::unique_ptr<StateObjectType> finishedTransparencyLayer (currentState.release());
2685 restore();
2686 currentState->endTransparencyLayer (*finishedTransparencyLayer);
2687 }
2688
2689private:
2690 std::unique_ptr<StateObjectType> currentState;
2692
2694};
2695
2696//==============================================================================
2697template <class SavedStateType>
2699{
2700public:
2701 bool isVectorDevice() const override { return false; }
2702 void setOrigin (Point<int> o) override { stack->transform.setOrigin (o); }
2703 void addTransform (const AffineTransform& t) override { stack->transform.addTransform (t); }
2704 float getPhysicalPixelScaleFactor() override { return stack->transform.getPhysicalPixelScaleFactor(); }
2705 Rectangle<int> getClipBounds() const override { return stack->getClipBounds(); }
2706 bool isClipEmpty() const override { return stack->clip == nullptr; }
2707 bool clipRegionIntersects (const Rectangle<int>& r) override { return stack->clipRegionIntersects (r); }
2708 bool clipToRectangle (const Rectangle<int>& r) override { return stack->clipToRectangle (r); }
2709 bool clipToRectangleList (const RectangleList<int>& r) override { return stack->clipToRectangleList (r); }
2710 void excludeClipRectangle (const Rectangle<int>& r) override { stack->excludeClipRectangle (r); }
2711 void clipToPath (const Path& path, const AffineTransform& t) override { stack->clipToPath (path, t); }
2712 void clipToImageAlpha (const Image& im, const AffineTransform& t) override { stack->clipToImageAlpha (im, t); }
2713 void saveState() override { stack.save(); }
2714 void restoreState() override { stack.restore(); }
2715 void beginTransparencyLayer (float opacity) override { stack.beginTransparencyLayer (opacity); }
2716 void endTransparencyLayer() override { stack.endTransparencyLayer(); }
2717 void setFill (const FillType& fillType) override { stack->setFillType (fillType); }
2718 void setOpacity (float newOpacity) override { stack->fillType.setOpacity (newOpacity); }
2719 void setInterpolationQuality (Graphics::ResamplingQuality quality) override { stack->interpolationQuality = quality; }
2720 void fillRect (const Rectangle<int>& r, bool replace) override { stack->fillRect (r, replace); }
2721 void fillRect (const Rectangle<float>& r) override { stack->fillRect (r); }
2722 void fillRectList (const RectangleList<float>& list) override { stack->fillRectList (list); }
2723 void fillPath (const Path& path, const AffineTransform& t) override { stack->fillPath (path, t); }
2724 void drawImage (const Image& im, const AffineTransform& t) override { stack->drawImage (im, t); }
2725 void drawGlyph (int glyphNumber, const AffineTransform& t) override { stack->drawGlyph (glyphNumber, t); }
2726 void drawLine (const Line<float>& line) override { stack->drawLine (line); }
2727 void setFont (const Font& newFont) override { stack->font = newFont; }
2728 const Font& getFont() override { return stack->font; }
2729
2730protected:
2731 StackBasedLowLevelGraphicsContext (SavedStateType* initialState) : stack (initialState) {}
2733
2735};
2736
2737}
2738
2740
2741} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
static const unsigned long mask[]
Definition bitwise.c:31
Definition juce_AffineTransform.h:43
bool isSingularity() const noexcept
Definition juce_AffineTransform.cpp:208
static AffineTransform scale(float factorX, float factorY) noexcept
Definition juce_AffineTransform.cpp:141
bool isOnlyTranslation() const noexcept
Definition juce_AffineTransform.cpp:230
float getTranslationY() const noexcept
Definition juce_AffineTransform.h:264
bool isIdentity() const noexcept
Definition juce_AffineTransform.cpp:52
static AffineTransform translation(float deltaX, float deltaY) noexcept
Definition juce_AffineTransform.cpp:81
float getTranslationX() const noexcept
Definition juce_AffineTransform.h:259
Definition juce_ColourGradient.h:38
int createLookupTable(const AffineTransform &transform, HeapBlock< PixelARGB > &resultLookupTable) const
Definition juce_ColourGradient.cpp:229
Point< float > point2
Definition juce_ColourGradient.h:195
Point< float > point1
Definition juce_ColourGradient.h:195
Definition juce_CriticalSection.h:43
DeletedAtShutdown()
Definition juce_DeletedAtShutdown.cpp:34
Definition juce_EdgeTable.h:38
void clipToEdgeTable(const EdgeTable &)
Definition juce_EdgeTable.cpp:740
void clipLineToMask(int x, int y, const uint8 *mask, int maskStride, int numPixels)
Definition juce_EdgeTable.cpp:775
Definition juce_FillType.h:41
Definition juce_Font.h:42
Typeface::Ptr getTypefacePtr() const
Definition juce_Font.cpp:509
Definition juce_GraphicsContext.h:45
ResamplingQuality
Definition juce_GraphicsContext.h:462
@ lowResamplingQuality
Definition juce_GraphicsContext.h:463
Definition juce_HeapBlock.h:87
Definition juce_Image.h:310
int height
Definition juce_Image.h:356
@ readOnly
Definition juce_Image.h:314
@ readWrite
Definition juce_Image.h:316
int width
Definition juce_Image.h:356
PixelFormat pixelFormat
Definition juce_Image.h:353
Definition juce_Image.h:58
int getWidth() const noexcept
Definition juce_Image.cpp:271
bool hasAlphaChannel() const noexcept
Definition juce_Image.cpp:278
int getHeight() const noexcept
Definition juce_Image.cpp:272
Rectangle< int > getBounds() const noexcept
Definition juce_Image.cpp:273
@ SingleChannel
Definition juce_Image.h:68
@ UnknownFormat
Definition juce_Image.h:65
@ ARGB
Definition juce_Image.h:67
@ RGB
Definition juce_Image.h:66
Definition juce_Line.h:47
Point< ValueType > getPointAlongLine(ValueType distanceFromStart) const noexcept
Definition juce_Line.h:204
Point< ValueType > findNearestPointTo(Point< ValueType > point) const noexcept
Definition juce_Line.h:315
Definition juce_OwnedArray.h:51
Definition juce_Path.h:65
Rectangle< float > getBoundsTransformed(const AffineTransform &transform) const noexcept
Definition juce_Path.cpp:205
Definition juce_PixelFormats.h:59
@ indexG
Definition juce_PixelFormats.h:302
@ indexA
Definition juce_PixelFormats.h:302
@ indexR
Definition juce_PixelFormats.h:302
@ indexB
Definition juce_PixelFormats.h:302
Definition juce_PixelFormats.h:600
Definition juce_PixelFormats.h:354
@ indexG
Definition juce_PixelFormats.h:553
@ indexR
Definition juce_PixelFormats.h:553
@ indexB
Definition juce_PixelFormats.h:553
Definition juce_Point.h:42
ValueType y
Definition juce_Point.h:247
ValueType x
Definition juce_Point.h:246
Definition juce_Rectangle.h:67
bool intersects(Rectangle other) const noexcept
Definition juce_Rectangle.h:641
Rectangle< int > getSmallestIntegerContainer() const noexcept
Definition juce_Rectangle.h:840
Rectangle getIntersection(Rectangle other) const noexcept
Definition juce_Rectangle.h:664
bool isEmpty() const noexcept
Definition juce_Rectangle.h:121
Definition juce_RectangleList.h:43
void subtract(RectangleType rect)
Definition juce_RectangleList.h:204
void offsetAll(Point< ValueType > offset) noexcept
Definition juce_RectangleList.h:589
void add(RectangleType rect)
Definition juce_RectangleList.h:110
void transformAll(const AffineTransform &transform) noexcept
Definition juce_RectangleList.h:613
Definition juce_ReferenceCountedArray.h:51
Definition juce_ReferenceCountedObject.h:247
Font font
Definition juce_RenderingHelpers.h:302
int glyph
Definition juce_RenderingHelpers.h:304
bool snapToIntegerCoordinate
Definition juce_RenderingHelpers.h:305
void draw(RendererType &state, Point< float > pos) const
Definition juce_RenderingHelpers.h:280
int lastAccessCount
Definition juce_RenderingHelpers.h:304
std::unique_ptr< EdgeTable > edgeTable
Definition juce_RenderingHelpers.h:303
void generate(const Font &newFont, int glyphNumber)
Definition juce_RenderingHelpers.h:289
void iterate(Renderer &r) const noexcept
Definition juce_RenderingHelpers.h:1942
SubRectangleIteratorFloat(const RectangleList< int > &clipList, Rectangle< float > clipBounds) noexcept
Definition juce_RenderingHelpers.h:1936
Rectangle< float > area
Definition juce_RenderingHelpers.h:2030
const RectangleList< int > & clip
Definition juce_RenderingHelpers.h:2029
const RectangleList< int > & clip
Definition juce_RenderingHelpers.h:1926
SubRectangleIterator(const RectangleList< int > &clipList, Rectangle< int > clipBounds)
Definition juce_RenderingHelpers.h:1909
void iterate(Renderer &r) const noexcept
Definition juce_RenderingHelpers.h:1914
const Rectangle< int > area
Definition juce_RenderingHelpers.h:1927
Definition juce_RenderingHelpers.h:1810
Ptr clipToRectangle(Rectangle< int > r) override
Definition juce_RenderingHelpers.h:1821
void translate(Point< int > delta) override
Definition juce_RenderingHelpers.h:1847
RectangleListRegion(const RectangleListRegion &other)
Definition juce_RenderingHelpers.h:1814
Ptr clone() const override
Definition juce_RenderingHelpers.h:1818
Ptr toEdgeTable() const
Definition juce_RenderingHelpers.h:2035
RectangleListRegion(const RectangleList< int > &r)
Definition juce_RenderingHelpers.h:1813
void fillAllWithGradient(SavedStateType &state, ColourGradient &gradient, const AffineTransform &transform, bool isIdentity) const override
Definition juce_RenderingHelpers.h:1868
void fillAllWithColour(SavedStateType &state, PixelARGB colour, bool replaceContents) const override
Definition juce_RenderingHelpers.h:1863
RectangleListRegion(Rectangle< int > r)
Definition juce_RenderingHelpers.h:1812
Ptr clipToImageAlpha(const Image &image, const AffineTransform &transform, Graphics::ResamplingQuality quality) override
Definition juce_RenderingHelpers.h:1842
void fillRectWithColour(SavedStateType &state, Rectangle< float > area, PixelARGB colour) const override
Definition juce_RenderingHelpers.h:1857
Ptr excludeClipRectangle(Rectangle< int > r) override
Definition juce_RenderingHelpers.h:1833
Rectangle< int > getClipBounds() const override
Definition juce_RenderingHelpers.h:1849
Ptr clipToRectangleList(const RectangleList< int > &r) override
Definition juce_RenderingHelpers.h:1827
void renderImageTransformed(SavedStateType &state, const Image &src, int alpha, const AffineTransform &transform, Graphics::ResamplingQuality quality, bool tiledFill) const override
Definition juce_RenderingHelpers.h:1873
void iterate(Renderer &r) const noexcept
Definition juce_RenderingHelpers.h:1887
Ptr clipToPath(const Path &p, const AffineTransform &transform) override
Definition juce_RenderingHelpers.h:1839
bool clipRegionIntersects(Rectangle< int > r) const override
Definition juce_RenderingHelpers.h:1848
Ptr applyClipTo(const Ptr &target) const override
Definition juce_RenderingHelpers.h:1819
void fillRectWithColour(SavedStateType &state, Rectangle< int > area, PixelARGB colour, bool replaceContents) const override
Definition juce_RenderingHelpers.h:1851
typename Base::Ptr Ptr
Definition juce_RenderingHelpers.h:1816
void renderImageUntransformed(SavedStateType &state, const Image &src, int alpha, int x, int y, bool tiledFill) const override
Definition juce_RenderingHelpers.h:1878
Ptr clipToEdgeTable(const EdgeTable &et) override
Definition juce_RenderingHelpers.h:1840
RectangleList< int > clip
Definition juce_RenderingHelpers.h:1883
Definition juce_RenderingHelpers.h:144
void drawGlyph(RenderTargetType &target, const Font &font, const int glyphNumber, Point< float > pos)
Definition juce_RenderingHelpers.h:176
ReferenceCountedObjectPtr< CachedGlyphEdgeTable< SoftwareRendererSavedState > > findExistingGlyph(const Font &font, int glyphNumber) const noexcept
Definition juce_RenderingHelpers.h:207
ReferenceCountedArray< CachedGlyphEdgeTable< SoftwareRendererSavedState > > glyphs
Definition juce_RenderingHelpers.h:203
~GlyphCache() override
Definition juce_RenderingHelpers.h:151
static GlyphCache & getInstance()
Definition juce_RenderingHelpers.h:156
ReferenceCountedObjectPtr< CachedGlyphEdgeTable< SoftwareRendererSavedState > > findOrCreateGlyph(const Font &font, int glyphNumber)
Definition juce_RenderingHelpers.h:185
ReferenceCountedObjectPtr< CachedGlyphEdgeTable< SoftwareRendererSavedState > > getGlyphForReuse()
Definition juce_RenderingHelpers.h:216
CachedGlyphEdgeTable< SoftwareRendererSavedState > * findLeastRecentlyUsedGlyph() const noexcept
Definition juce_RenderingHelpers.h:242
GlyphCache()
Definition juce_RenderingHelpers.h:146
void fillPath(const Path &path, const AffineTransform &t)
Definition juce_RenderingHelpers.h:2323
Graphics::ResamplingQuality interpolationQuality
Definition juce_RenderingHelpers.h:2475
void setFillType(const FillType &newFill)
Definition juce_RenderingHelpers.h:2218
RenderingHelpers::TranslationOrTransform transform
Definition juce_RenderingHelpers.h:2473
static bool isOnlyTranslationAllowingError(const AffineTransform &t, float tolerance) noexcept
Definition juce_RenderingHelpers.h:2367
SavedStateBase(const RectangleList< int > &clipList, Point< int > origin)
Definition juce_RenderingHelpers.h:2056
void clipToImageAlpha(const Image &sourceImage, const AffineTransform &t)
Definition juce_RenderingHelpers.h:2181
void renderImage(const Image &sourceImage, const AffineTransform &trans, const BaseRegionType *tiledFillClipRegion)
Definition juce_RenderingHelpers.h:2375
bool clipToRectangleList(const RectangleList< int > &r)
Definition juce_RenderingHelpers.h:2096
SavedStateBase(const SavedStateBase &other)
Definition juce_RenderingHelpers.h:2062
void cloneClipIfMultiplyReferenced()
Definition juce_RenderingHelpers.h:2466
SavedStateType & getThis() noexcept
Definition juce_RenderingHelpers.h:2069
void fillEdgeTable(const EdgeTable &edgeTable, float x, int y)
Definition juce_RenderingHelpers.h:2335
typename ClipRegions< SavedStateType >::RectangleListRegion RectangleListRegionType
Definition juce_RenderingHelpers.h:2048
BaseRegionType::Ptr clip
Definition juce_RenderingHelpers.h:2472
void fillRectAsPath(Rectangle< CoordType > r)
Definition juce_RenderingHelpers.h:2254
void fillRectList(const RectangleList< float > &list)
Definition juce_RenderingHelpers.h:2294
void clipToPath(const Path &p, const AffineTransform &t)
Definition juce_RenderingHelpers.h:2172
bool clipRegionIntersects(Rectangle< int > r) const
Definition juce_RenderingHelpers.h:2199
void fillTargetRect(Rectangle< float > r)
Definition juce_RenderingHelpers.h:2238
void drawLine(Line< float > line)
Definition juce_RenderingHelpers.h:2354
typename ClipRegions< SavedStateType >::EdgeTableRegion EdgeTableRegionType
Definition juce_RenderingHelpers.h:2047
bool clipToRectangle(Rectangle< int > r)
Definition juce_RenderingHelpers.h:2071
void fillRect(Rectangle< float > r)
Definition juce_RenderingHelpers.h:2281
float transparencyLayerAlpha
Definition juce_RenderingHelpers.h:2476
void drawImage(const Image &sourceImage, const AffineTransform &trans)
Definition juce_RenderingHelpers.h:2361
void fillRect(Rectangle< int > r, bool replaceContents)
Definition juce_RenderingHelpers.h:2261
typename ClipRegions< SavedStateType >::Base BaseRegionType
Definition juce_RenderingHelpers.h:2046
void fillShape(typename BaseRegionType::Ptr shapeToFill, bool replaceContents)
Definition juce_RenderingHelpers.h:2428
bool excludeClipRectangle(Rectangle< int > r)
Definition juce_RenderingHelpers.h:2144
void fillTargetRect(Rectangle< int > r, bool replaceContents)
Definition juce_RenderingHelpers.h:2223
SavedStateBase(Rectangle< int > initialClip)
Definition juce_RenderingHelpers.h:2050
Rectangle< int > getClipBounds() const
Definition juce_RenderingHelpers.h:2212
static Rectangle< int > getLargestIntegerWithin(Rectangle< float > r)
Definition juce_RenderingHelpers.h:2134
FillType fillType
Definition juce_RenderingHelpers.h:2474
Definition juce_RenderingHelpers.h:2642
void save()
Definition juce_RenderingHelpers.h:2658
StateObjectType & operator*() const noexcept
Definition juce_RenderingHelpers.h:2656
void beginTransparencyLayer(float opacity)
Definition juce_RenderingHelpers.h:2676
void endTransparencyLayer()
Definition juce_RenderingHelpers.h:2682
SavedStateStack(StateObjectType *initialState) noexcept
Definition juce_RenderingHelpers.h:2644
void restore()
Definition juce_RenderingHelpers.h:2663
StateObjectType * operator->() const noexcept
Definition juce_RenderingHelpers.h:2655
OwnedArray< StateObjectType > stack
Definition juce_RenderingHelpers.h:2691
std::unique_ptr< StateObjectType > currentState
Definition juce_RenderingHelpers.h:2690
void initialise(StateObjectType *state)
Definition juce_RenderingHelpers.h:2650
void renderImageTransformed(IteratorType &iter, const Image &src, int alpha, const AffineTransform &trans, Graphics::ResamplingQuality quality, bool tiledFill) const
Definition juce_RenderingHelpers.h:2582
SavedStateBase< SoftwareRendererSavedState > BaseClass
Definition juce_RenderingHelpers.h:2482
static void clearGlyphCache()
Definition juce_RenderingHelpers.h:2529
Image image
Definition juce_RenderingHelpers.h:2632
void fillWithGradient(IteratorType &iter, ColourGradient &gradient, const AffineTransform &trans, bool isIdentity) const
Definition juce_RenderingHelpers.h:2613
void drawGlyph(int glyphNumber, const AffineTransform &trans)
Definition juce_RenderingHelpers.h:2535
void fillWithSolidColour(IteratorType &iter, PixelARGB colour, bool replaceContents) const
Definition juce_RenderingHelpers.h:2598
SoftwareRendererSavedState(const SoftwareRendererSavedState &other)=default
GlyphCache< CachedGlyphEdgeTable< SoftwareRendererSavedState >, SoftwareRendererSavedState > GlyphCacheType
Definition juce_RenderingHelpers.h:2527
SoftwareRendererSavedState(const Image &im, Rectangle< int > clipBounds)
Definition juce_RenderingHelpers.h:2485
SoftwareRendererSavedState * beginTransparencyLayer(float opacity)
Definition juce_RenderingHelpers.h:2497
void endTransparencyLayer(SoftwareRendererSavedState &finishedLayerState)
Definition juce_RenderingHelpers.h:2515
Font font
Definition juce_RenderingHelpers.h:2633
SoftwareRendererSavedState(const Image &im, const RectangleList< int > &clipList, Point< int > origin)
Definition juce_RenderingHelpers.h:2490
void renderImageUntransformed(IteratorType &iter, const Image &src, int alpha, int x, int y, bool tiledFill) const
Definition juce_RenderingHelpers.h:2590
Rectangle< int > getMaximumBounds() const
Definition juce_RenderingHelpers.h:2578
void setOrigin(Point< int > o) override
Definition juce_RenderingHelpers.h:2702
void fillRectList(const RectangleList< float > &list) override
Definition juce_RenderingHelpers.h:2722
float getPhysicalPixelScaleFactor() override
Definition juce_RenderingHelpers.h:2704
Rectangle< int > getClipBounds() const override
Definition juce_RenderingHelpers.h:2705
bool clipRegionIntersects(const Rectangle< int > &r) override
Definition juce_RenderingHelpers.h:2707
void setFont(const Font &newFont) override
Definition juce_RenderingHelpers.h:2727
void clipToPath(const Path &path, const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2711
void drawImage(const Image &im, const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2724
void fillRect(const Rectangle< float > &r) override
Definition juce_RenderingHelpers.h:2721
void saveState() override
Definition juce_RenderingHelpers.h:2713
RenderingHelpers::SavedStateStack< SavedStateType > stack
Definition juce_RenderingHelpers.h:2734
void drawGlyph(int glyphNumber, const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2725
void drawLine(const Line< float > &line) override
Definition juce_RenderingHelpers.h:2726
void excludeClipRectangle(const Rectangle< int > &r) override
Definition juce_RenderingHelpers.h:2710
void endTransparencyLayer() override
Definition juce_RenderingHelpers.h:2716
bool clipToRectangle(const Rectangle< int > &r) override
Definition juce_RenderingHelpers.h:2708
void fillRect(const Rectangle< int > &r, bool replace) override
Definition juce_RenderingHelpers.h:2720
const Font & getFont() override
Definition juce_RenderingHelpers.h:2728
void fillPath(const Path &path, const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2723
void setInterpolationQuality(Graphics::ResamplingQuality quality) override
Definition juce_RenderingHelpers.h:2719
void setFill(const FillType &fillType) override
Definition juce_RenderingHelpers.h:2717
void beginTransparencyLayer(float opacity) override
Definition juce_RenderingHelpers.h:2715
void clipToImageAlpha(const Image &im, const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2712
void restoreState() override
Definition juce_RenderingHelpers.h:2714
bool isClipEmpty() const override
Definition juce_RenderingHelpers.h:2706
bool clipToRectangleList(const RectangleList< int > &r) override
Definition juce_RenderingHelpers.h:2709
StackBasedLowLevelGraphicsContext(SavedStateType *initialState)
Definition juce_RenderingHelpers.h:2731
void addTransform(const AffineTransform &t) override
Definition juce_RenderingHelpers.h:2703
bool isVectorDevice() const override
Definition juce_RenderingHelpers.h:2701
void setOpacity(float newOpacity) override
Definition juce_RenderingHelpers.h:2718
Definition juce_RenderingHelpers.h:40
Rectangle< int > translated(Rectangle< int > r) const noexcept
Definition juce_RenderingHelpers.h:106
Rectangle< Type > deviceSpaceToUserSpace(Rectangle< Type > r) const noexcept
Definition juce_RenderingHelpers.h:126
RectangleOrPoint transformed(RectangleOrPoint r) const noexcept
Definition juce_RenderingHelpers.h:119
bool isOnlyTranslated
Definition juce_RenderingHelpers.h:134
void addTransform(const AffineTransform &t) noexcept
Definition juce_RenderingHelpers.h:73
TranslationOrTransform(const TranslationOrTransform &other)=default
bool isIdentity() const noexcept
Definition juce_RenderingHelpers.h:59
TranslationOrTransform(Point< int > origin) noexcept
Definition juce_RenderingHelpers.h:43
bool isRotated
Definition juce_RenderingHelpers.h:134
Point< int > offset
Definition juce_RenderingHelpers.h:133
Rectangle< float > translated(Rectangle< float > r) const noexcept
Definition juce_RenderingHelpers.h:112
AffineTransform getTransformWith(const AffineTransform &userTransform) const noexcept
Definition juce_RenderingHelpers.h:53
void moveOriginInDeviceSpace(Point< int > delta) noexcept
Definition juce_RenderingHelpers.h:98
AffineTransform getTransform() const noexcept
Definition juce_RenderingHelpers.h:47
float getPhysicalPixelScaleFactor() const noexcept
Definition juce_RenderingHelpers.h:93
AffineTransform complexTransform
Definition juce_RenderingHelpers.h:132
void setOrigin(Point< int > delta) noexcept
Definition juce_RenderingHelpers.h:64
* e
Definition inflate.c:1404
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 s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
unsigned f
Definition inflate.c:1572
static int int height
Definition pugl.h:1594
static int width
Definition pugl.h:1593
int quality
Definition jpeglib.h:919
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE(className)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define forcedinline
#define jassertfalse
#define JUCE_PERFORM_PIXEL_OP_LOOP(op)
Definition juce_RenderingHelpers.h:558
static int generate(SordWorld *world, SordModel *sord, size_t n_quads, SordNode *graph)
Definition sord_test.c:72
Definition juce_RenderingHelpers.h:567
void renderGradient(Iterator &iter, const Image::BitmapData &destData, const ColourGradient &g, const AffineTransform &transform, const PixelARGB *lookupTable, int numLookupEntries, bool isIdentity, DestPixelType *)
Definition juce_RenderingHelpers.h:1565
void renderImageTransformed(Iterator &iter, const Image::BitmapData &destData, const Image::BitmapData &srcData, int alpha, const AffineTransform &transform, Graphics::ResamplingQuality quality, bool tiledFill)
Definition juce_RenderingHelpers.h:1409
void renderSolidFill(Iterator &iter, const Image::BitmapData &destData, PixelARGB fillColour, bool replaceContents, DestPixelType *)
Definition juce_RenderingHelpers.h:1550
void renderImageUntransformed(Iterator &iter, const Image::BitmapData &destData, const Image::BitmapData &srcData, int alpha, int x, int y, bool tiledFill)
Definition juce_RenderingHelpers.h:1481
Definition juce_RenderingHelpers.h:404
Definition juce_RenderingHelpers.h:32
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
unsigned int uint32
Definition juce_MathsFunctions.h:45
Type jlimit(Type lowerLimit, Type upperLimit, Type valueToConstrain) noexcept
Definition juce_MathsFunctions.h:262
Type * addBytesToPointer(Type *basePointer, IntegerType bytes) noexcept
Definition juce_Memory.h:111
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
IntegerType negativeAwareModulo(IntegerType dividend, const IntegerType divisor) noexcept
Definition juce_MathsFunctions.h:571
unsigned char uint8
Definition juce_MathsFunctions.h:37
int roundToInt(const FloatType value) noexcept
Definition juce_MathsFunctions.h:465
@ list
Definition juce_AccessibilityRole.h:56
@ image
Definition juce_AccessibilityRole.h:42
static bool diff(const std::string fn1, const std::string fn2)
Definition playertest.cpp:161
Definition juce_Atomic.h:42
Definition juce_RenderingHelpers.h:1594
virtual void fillAllWithGradient(SavedStateType &, ColourGradient &, const AffineTransform &, bool isIdentity) const =0
virtual Ptr clipToEdgeTable(const EdgeTable &)=0
virtual void fillRectWithColour(SavedStateType &, Rectangle< int >, PixelARGB colour, bool replaceContents) const =0
virtual Ptr clipToImageAlpha(const Image &, const AffineTransform &, Graphics::ResamplingQuality)=0
virtual bool clipRegionIntersects(Rectangle< int >) const =0
virtual Rectangle< int > getClipBounds() const =0
virtual void fillAllWithColour(SavedStateType &, PixelARGB colour, bool replaceContents) const =0
virtual Ptr clipToRectangleList(const RectangleList< int > &)=0
virtual Ptr clipToPath(const Path &, const AffineTransform &)=0
virtual Ptr clipToRectangle(Rectangle< int >)=0
virtual void translate(Point< int > delta)=0
virtual void renderImageUntransformed(SavedStateType &, const Image &, int alpha, int x, int y, bool tiledFill) const =0
virtual void renderImageTransformed(SavedStateType &, const Image &, int alpha, const AffineTransform &, Graphics::ResamplingQuality, bool tiledFill) const =0
virtual Ptr excludeClipRectangle(Rectangle< int >)=0
ReferenceCountedObjectPtr< Base > Ptr
Definition juce_RenderingHelpers.h:1598
virtual void fillRectWithColour(SavedStateType &, Rectangle< float >, PixelARGB colour) const =0
virtual Ptr applyClipTo(const Ptr &target) const =0
Definition juce_RenderingHelpers.h:1624
void renderImageUntransformed(SavedStateType &state, const Image &src, int alpha, int x, int y, bool tiledFill) const override
Definition juce_RenderingHelpers.h:1777
EdgeTableRegion(const RectangleList< float > &r)
Definition juce_RenderingHelpers.h:1629
Rectangle< int > getClipBounds() const override
Definition juce_RenderingHelpers.h:1731
void translate(Point< int > delta) override
Definition juce_RenderingHelpers.h:1721
Ptr clone() const override
Definition juce_RenderingHelpers.h:1637
bool clipRegionIntersects(Rectangle< int > r) const override
Definition juce_RenderingHelpers.h:1726
Ptr applyClipTo(const Ptr &target) const override
Definition juce_RenderingHelpers.h:1638
void straightClipImage(const Image::BitmapData &srcData, int imageX, int imageY, const SrcPixelType *)
Definition juce_RenderingHelpers.h:1796
void fillAllWithGradient(SavedStateType &state, ColourGradient &gradient, const AffineTransform &transform, bool isIdentity) const override
Definition juce_RenderingHelpers.h:1767
EdgeTableRegion(const EdgeTable &e)
Definition juce_RenderingHelpers.h:1625
Ptr clipToImageAlpha(const Image &image, const AffineTransform &transform, Graphics::ResamplingQuality quality) override
Definition juce_RenderingHelpers.h:1676
EdgeTableRegion(Rectangle< float > r)
Definition juce_RenderingHelpers.h:1627
EdgeTableRegion(Rectangle< int > bounds, const Path &p, const AffineTransform &t)
Definition juce_RenderingHelpers.h:1630
void renderImageTransformed(SavedStateType &state, const Image &src, int alpha, const AffineTransform &transform, Graphics::ResamplingQuality quality, bool tiledFill) const override
Definition juce_RenderingHelpers.h:1772
Ptr clipToEdgeTable(const EdgeTable &et) override
Definition juce_RenderingHelpers.h:1670
void fillRectWithColour(SavedStateType &state, Rectangle< int > area, PixelARGB colour, bool replaceContents) const override
Definition juce_RenderingHelpers.h:1736
void fillRectWithColour(SavedStateType &state, Rectangle< float > area, PixelARGB colour) const override
Definition juce_RenderingHelpers.h:1749
Ptr excludeClipRectangle(Rectangle< int > r) override
Definition juce_RenderingHelpers.h:1657
Ptr clipToPath(const Path &p, const AffineTransform &transform) override
Definition juce_RenderingHelpers.h:1663
EdgeTable edgeTable
Definition juce_RenderingHelpers.h:1782
void transformedClipImage(const Image::BitmapData &srcData, const AffineTransform &transform, Graphics::ResamplingQuality quality, const SrcPixelType *)
Definition juce_RenderingHelpers.h:1786
EdgeTableRegion(const EdgeTableRegion &other)
Definition juce_RenderingHelpers.h:1632
EdgeTableRegion(const RectangleList< int > &r)
Definition juce_RenderingHelpers.h:1628
typename Base::Ptr Ptr
Definition juce_RenderingHelpers.h:1635
Ptr clipToRectangleList(const RectangleList< int > &r) override
Definition juce_RenderingHelpers.h:1646
EdgeTableRegion(Rectangle< int > r)
Definition juce_RenderingHelpers.h:1626
Ptr clipToRectangle(Rectangle< int > r) override
Definition juce_RenderingHelpers.h:1640
void fillAllWithColour(SavedStateType &state, PixelARGB colour, bool replaceContents) const override
Definition juce_RenderingHelpers.h:1762
Definition juce_RenderingHelpers.h:1592
Definition juce_RenderingHelpers.h:701
forcedinline PixelType * getPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:763
void handleEdgeTableRectangle(int x, int y, int width, int height, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:741
void handleEdgeTableRectangleFull(int x, int y, int width, int height) noexcept
Definition juce_RenderingHelpers.h:750
void handleEdgeTableLine(int x, int width, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:725
void handleEdgeTableLineFull(int x, int width) const noexcept
Definition juce_RenderingHelpers.h:735
Gradient(const Image::BitmapData &dest, const ColourGradient &gradient, const AffineTransform &transform, const PixelARGB *colours, int numColours)
Definition juce_RenderingHelpers.h:702
const Image::BitmapData & destData
Definition juce_RenderingHelpers.h:760
forcedinline void handleEdgeTablePixelFull(int x) const noexcept
Definition juce_RenderingHelpers.h:720
forcedinline void setEdgeTableYPos(int y) noexcept
Definition juce_RenderingHelpers.h:709
PixelType * linePixels
Definition juce_RenderingHelpers.h:761
forcedinline void handleEdgeTablePixel(int x, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:715
Definition juce_RenderingHelpers.h:775
void handleEdgeTableRectangle(int x, int y, int width, int height, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:858
SrcPixelType * sourceLineStart
Definition juce_RenderingHelpers.h:893
forcedinline DestPixelType * getDestPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:895
ImageFill(const Image::BitmapData &dest, const Image::BitmapData &src, int alpha, int x, int y)
Definition juce_RenderingHelpers.h:776
DestPixelType * linePixels
Definition juce_RenderingHelpers.h:892
forcedinline void handleEdgeTablePixel(int x, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:799
const Image::BitmapData & destData
Definition juce_RenderingHelpers.h:889
forcedinline SrcPixelType const * getSrcPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:900
const int extraAlpha
Definition juce_RenderingHelpers.h:891
void clipEdgeTableLine(EdgeTable &et, int x, int y, int width)
Definition juce_RenderingHelpers.h:876
forcedinline void setEdgeTableYPos(int y) noexcept
Definition juce_RenderingHelpers.h:785
const int xOffset
Definition juce_RenderingHelpers.h:891
forcedinline void handleEdgeTablePixelFull(int x) const noexcept
Definition juce_RenderingHelpers.h:806
void handleEdgeTableLine(int x, int width, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:811
forcedinline void copyRow(DestPixelType *dest, SrcPixelType const *src, int width) const noexcept
Definition juce_RenderingHelpers.h:905
void handleEdgeTableLineFull(int x, int width) const noexcept
Definition juce_RenderingHelpers.h:835
void handleEdgeTableRectangleFull(int x, int y, int width, int height) noexcept
Definition juce_RenderingHelpers.h:867
const Image::BitmapData & srcData
Definition juce_RenderingHelpers.h:890
const int yOffset
Definition juce_RenderingHelpers.h:891
Definition juce_RenderingHelpers.h:571
void blendLine(PixelType *dest, PixelARGB colour, int width) const noexcept
Definition juce_RenderingHelpers.h:668
forcedinline void replaceLine(PixelRGB *dest, PixelARGB colour, int width) const noexcept
Definition juce_RenderingHelpers.h:673
forcedinline void handleEdgeTablePixelFull(int x) const noexcept
Definition juce_RenderingHelpers.h:595
forcedinline void setEdgeTableYPos(int y) noexcept
Definition juce_RenderingHelpers.h:582
PixelType * linePixels
Definition juce_RenderingHelpers.h:659
bool areRGBComponentsEqual
Definition juce_RenderingHelpers.h:661
SolidColour(const Image::BitmapData &image, PixelARGB colour)
Definition juce_RenderingHelpers.h:572
void handleEdgeTableRectangle(int x, int y, int width, int height, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:626
forcedinline void replaceLine(PixelARGB *dest, const PixelARGB colour, int width) const noexcept
Definition juce_RenderingHelpers.h:689
void handleEdgeTableRectangleFull(int x, int y, int width, int height) noexcept
Definition juce_RenderingHelpers.h:652
forcedinline PixelType * getPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:663
forcedinline void handleEdgeTableLineFull(int x, int width) const noexcept
Definition juce_RenderingHelpers.h:616
forcedinline void handleEdgeTablePixel(int x, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:587
const Image::BitmapData & destData
Definition juce_RenderingHelpers.h:658
forcedinline void replaceLine(PixelAlpha *dest, const PixelARGB colour, int width) const noexcept
Definition juce_RenderingHelpers.h:681
forcedinline void handleEdgeTableLine(int x, int width, int alphaLevel) const noexcept
Definition juce_RenderingHelpers.h:603
PixelARGB sourceColour
Definition juce_RenderingHelpers.h:660
void set(int n1, int n2, int steps, int offsetInt) noexcept
Definition juce_RenderingHelpers.h:1348
const AffineTransform inverseTransform
Definition juce_RenderingHelpers.h:1383
void setStartOfLine(float sx, float sy, int numPixels) noexcept
Definition juce_RenderingHelpers.h:1323
void next(int &px, int &py) noexcept
Definition juce_RenderingHelpers.h:1337
TransformedImageSpanInterpolator(const AffineTransform &transform, float offsetFloat, int offsetInt) noexcept
Definition juce_RenderingHelpers.h:1318
void render2PixelAverageX(PixelARGB *dest, const uint8 *src, uint32 subPixelX) noexcept
Definition juce_RenderingHelpers.h:1154
void render2PixelAverageX(PixelAlpha *dest, const uint8 *src, uint32 subPixelX) noexcept
Definition juce_RenderingHelpers.h:1297
const int maxY
Definition juce_RenderingHelpers.h:1397
void render2PixelAverageY(PixelRGB *dest, const uint8 *src, uint32 subPixelY) noexcept
Definition juce_RenderingHelpers.h:1260
forcedinline DestPixelType * getDestPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:1033
const Graphics::ResamplingQuality quality
Definition juce_RenderingHelpers.h:1396
const int maxX
Definition juce_RenderingHelpers.h:1397
forcedinline void setEdgeTableYPos(int newY) noexcept
Definition juce_RenderingHelpers.h:950
void render2PixelAverageY(PixelAlpha *dest, const uint8 *src, uint32 subPixelY) noexcept
Definition juce_RenderingHelpers.h:1306
void render2PixelAverageX(PixelRGB *dest, const uint8 *src, uint32 subPixelX) noexcept
Definition juce_RenderingHelpers.h:1239
const Image::BitmapData & destData
Definition juce_RenderingHelpers.h:1393
void render4PixelAverage(PixelAlpha *dest, const uint8 *src, uint32 subPixelX, uint32 subPixelY) noexcept
Definition juce_RenderingHelpers.h:1282
void render4PixelAverage(PixelRGB *dest, const uint8 *src, uint32 subPixelX, uint32 subPixelY) noexcept
Definition juce_RenderingHelpers.h:1203
TransformedImageFill(const Image::BitmapData &dest, const Image::BitmapData &src, const AffineTransform &transform, int alpha, Graphics::ResamplingQuality q)
Definition juce_RenderingHelpers.h:935
TransformedImageSpanInterpolator interpolator
Definition juce_RenderingHelpers.h:1392
HeapBlock< SrcPixelType > scratchBuffer
Definition juce_RenderingHelpers.h:1400
void handleEdgeTableLine(int x, int width, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:972
int currentY
Definition juce_RenderingHelpers.h:1398
void render4PixelAverage(PixelARGB *dest, const uint8 *src, int subPixelX, int subPixelY) noexcept
Definition juce_RenderingHelpers.h:1114
DestPixelType * linePixels
Definition juce_RenderingHelpers.h:1399
void clipEdgeTableLine(EdgeTable &et, int x, int y, int width)
Definition juce_RenderingHelpers.h:1016
forcedinline void handleEdgeTablePixel(int x, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:956
size_t scratchSize
Definition juce_RenderingHelpers.h:1401
void handleEdgeTableRectangle(int x, int y, int width, int height, int alphaLevel) noexcept
Definition juce_RenderingHelpers.h:998
const int extraAlpha
Definition juce_RenderingHelpers.h:1395
void generate(PixelType *dest, int x, int numPixels) noexcept
Definition juce_RenderingHelpers.h:1040
const Image::BitmapData & srcData
Definition juce_RenderingHelpers.h:1394
forcedinline void handleEdgeTablePixelFull(int x) noexcept
Definition juce_RenderingHelpers.h:964
void render2PixelAverageY(PixelARGB *dest, const uint8 *src, uint32 subPixelY) noexcept
Definition juce_RenderingHelpers.h:1178
void handleEdgeTableRectangleFull(int x, int y, int width, int height) noexcept
Definition juce_RenderingHelpers.h:1007
forcedinline void handleEdgeTableLineFull(int x, int width) noexcept
Definition juce_RenderingHelpers.h:993
Definition juce_RenderingHelpers.h:317
FloatRectangleRasterisingInfo(Rectangle< float > area)
Definition juce_RenderingHelpers.h:318
int getBottomRightCornerAlpha() const noexcept
Definition juce_RenderingHelpers.h:393
int right
Definition juce_RenderingHelpers.h:396
bool isOnePixelWide() const noexcept
Definition juce_RenderingHelpers.h:388
int totalTop
Definition juce_RenderingHelpers.h:397
void iterate(Callback &callback) const
Definition juce_RenderingHelpers.h:378
int bottom
Definition juce_RenderingHelpers.h:396
int totalRight
Definition juce_RenderingHelpers.h:397
int leftAlpha
Definition juce_RenderingHelpers.h:398
int left
Definition juce_RenderingHelpers.h:396
int totalBottom
Definition juce_RenderingHelpers.h:397
int rightAlpha
Definition juce_RenderingHelpers.h:398
int totalLeft
Definition juce_RenderingHelpers.h:397
int getTopRightCornerAlpha() const noexcept
Definition juce_RenderingHelpers.h:391
int top
Definition juce_RenderingHelpers.h:396
int getBottomLeftCornerAlpha() const noexcept
Definition juce_RenderingHelpers.h:392
int getTopLeftCornerAlpha() const noexcept
Definition juce_RenderingHelpers.h:390
int bottomAlpha
Definition juce_RenderingHelpers.h:398
int topAlpha
Definition juce_RenderingHelpers.h:398
Definition juce_RenderingHelpers.h:407
const int numEntries
Definition juce_RenderingHelpers.h:465
forcedinline void setY(int y) noexcept
Definition juce_RenderingHelpers.h:450
bool vertical
Definition juce_RenderingHelpers.h:469
Linear(const ColourGradient &gradient, const AffineTransform &transform, const PixelARGB *colours, int numColours)
Definition juce_RenderingHelpers.h:408
int start
Definition juce_RenderingHelpers.h:467
@ numScaleBits
Definition juce_RenderingHelpers.h:470
PixelARGB linePix
Definition juce_RenderingHelpers.h:466
double yTerm
Definition juce_RenderingHelpers.h:468
double grad
Definition juce_RenderingHelpers.h:468
int scale
Definition juce_RenderingHelpers.h:467
PixelARGB getPixel(int x) const noexcept
Definition juce_RenderingHelpers.h:458
bool horizontal
Definition juce_RenderingHelpers.h:469
const PixelARGB *const lookupTable
Definition juce_RenderingHelpers.h:464
forcedinline void setY(int y) noexcept
Definition juce_RenderingHelpers.h:493
const PixelARGB *const lookupTable
Definition juce_RenderingHelpers.h:508
double invScale
Definition juce_RenderingHelpers.h:511
PixelARGB getPixel(int px) const noexcept
Definition juce_RenderingHelpers.h:499
double dy
Definition juce_RenderingHelpers.h:511
double maxDist
Definition juce_RenderingHelpers.h:511
const double gx1
Definition juce_RenderingHelpers.h:510
const int numEntries
Definition juce_RenderingHelpers.h:509
const double gy1
Definition juce_RenderingHelpers.h:510
Radial(const ColourGradient &gradient, const AffineTransform &, const PixelARGB *colours, int numColours)
Definition juce_RenderingHelpers.h:479
TransformedRadial(const ColourGradient &gradient, const AffineTransform &transform, const PixelARGB *colours, int numColours)
Definition juce_RenderingHelpers.h:520
const AffineTransform inverseTransform
Definition juce_RenderingHelpers.h:552
forcedinline void setY(int y) noexcept
Definition juce_RenderingHelpers.h:529
double tM10
Definition juce_RenderingHelpers.h:551
double lineYM11
Definition juce_RenderingHelpers.h:551
double lineYM01
Definition juce_RenderingHelpers.h:551
PixelARGB getPixel(int px) const noexcept
Definition juce_RenderingHelpers.h:536
double tM00
Definition juce_RenderingHelpers.h:551
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
static LV2_State_Status save(LV2_Handle instance, LV2_State_Store_Function store, void *callback_data, uint32_t flags, const LV2_Feature *const *features)
Definition test.c:161
static LV2_State_Status restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, void *callback_data, uint32_t flags, const LV2_Feature *const *features)
Definition test.c:292
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
memcpy(hh, h, RAND_HEAD_LEN)
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
register uch * q
Definition fileio.c:817
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137