565namespace EdgeTableFillers
568 template <
class PixelType,
bool replaceExisting = false>
572 : destData (image), sourceColour (colour)
575 areRGBComponentsEqual = sourceColour.getRed() == sourceColour.getGreen()
576 && sourceColour.getGreen() == sourceColour.getBlue();
578 areRGBComponentsEqual =
false;
583 linePixels = (
PixelType*) destData.getLinePointer (y);
589 getPixel (x)->set (sourceColour);
594 forcedinline void handleEdgeTablePixelFull (
int x)
const noexcept
597 getPixel (x)->set (sourceColour);
599 getPixel (x)->blend (sourceColour);
604 auto p = sourceColour;
607 auto* dest = getPixel (x);
610 replaceLine (dest, p, width);
612 blendLine (dest, p, width);
615 forcedinline void handleEdgeTableLineFull (
int x,
int width)
const noexcept
617 auto* dest = getPixel (x);
620 replaceLine (dest, sourceColour, width);
622 blendLine (dest, sourceColour, width);
625 void handleEdgeTableRectangle (
int x,
int y,
int width,
int height,
int alphaLevel)
noexcept
627 auto p = sourceColour;
630 setEdgeTableYPos (y);
631 auto* dest = getPixel (x);
635 while (--height >= 0)
637 replaceLine (dest, p, width);
643 while (--height >= 0)
645 blendLine (dest, p, width);
651 void handleEdgeTableRectangleFull (
int x,
int y,
int width,
int height)
noexcept
653 handleEdgeTableRectangle (x, y, width, height, 255);
660 bool areRGBComponentsEqual;
669 JUCE_PERFORM_PIXEL_OP_LOOP (blend (colour))
675 memset ((
void*) dest, colour.getRed(), (
size_t) width * 3);
677 JUCE_PERFORM_PIXEL_OP_LOOP (set (colour));
683 memset ((
void*) dest, colour.getAlpha(), (
size_t) width);
685 JUCE_PERFORM_PIXEL_OP_LOOP (setAlpha (colour.getAlpha()))
690 JUCE_PERFORM_PIXEL_OP_LOOP (set (colour))
698 template <
class PixelType,
class GradientType>
702 const PixelARGB* colours,
int numColours)
703 :
GradientType (gradient, transform, colours, numColours - 1),
710 linePixels = (
PixelType*) destData.getLinePointer (y);
711 GradientType::setY (y);
719 forcedinline void handleEdgeTablePixelFull (
int x)
const noexcept
721 getPixel (x)->blend (GradientType::getPixel (x));
724 void handleEdgeTableLine (
int x,
int width,
int alphaLevel)
const noexcept
726 auto* dest = getPixel (x);
729 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++), (
uint32)
alphaLevel))
731 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++)))
734 void handleEdgeTableLineFull (
int x,
int width)
const noexcept
736 auto* dest = getPixel (x);
737 JUCE_PERFORM_PIXEL_OP_LOOP (blend (GradientType::getPixel (x++)))
740 void handleEdgeTableRectangle (
int x,
int y,
int width,
int height,
int alphaLevel)
noexcept
742 while (--height >= 0)
744 setEdgeTableYPos (y++);
749 void handleEdgeTableRectangleFull (
int x,
int y,
int width,
int height)
noexcept
751 while (--height >= 0)
753 setEdgeTableYPos (y++);
754 handleEdgeTableLineFull (x, width);
772 template <
class DestPixelType,
class SrcPixelType,
bool repeatPattern>
778 extraAlpha (alpha + 1),
795 sourceLineStart = (
SrcPixelType*) srcData.getLinePointer (y);
805 forcedinline void handleEdgeTablePixelFull (
int x)
const noexcept
807 getDestPixel (x)->blend (*getSrcPixel (
repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)), (
uint32) extraAlpha);
810 void handleEdgeTableLine (
int x,
int width,
int alphaLevel)
const noexcept
812 auto* dest = getDestPixel (x);
819 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width), (
uint32)
alphaLevel))
821 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width)))
825 jassert (x >= 0 && x + width <= srcData.width);
828 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++), (
uint32)
alphaLevel))
830 copyRow (dest, getSrcPixel (x), width);
834 void handleEdgeTableLineFull (
int x,
int width)
const noexcept
836 auto* dest = getDestPixel (x);
841 if (extraAlpha < 0xfe)
842 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width), (
uint32) extraAlpha))
844 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++ % srcData.width)))
848 jassert (x >= 0 && x + width <= srcData.width);
850 if (extraAlpha < 0xfe)
851 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*getSrcPixel (x++), (
uint32) extraAlpha))
853 copyRow (dest, getSrcPixel (x), width);
857 void handleEdgeTableRectangle (
int x,
int y,
int width,
int height,
int alphaLevel)
noexcept
859 while (--height >= 0)
861 setEdgeTableYPos (y++);
866 void handleEdgeTableRectangleFull (
int x,
int y,
int width,
int height)
noexcept
868 while (--height >= 0)
870 setEdgeTableYPos (y++);
871 handleEdgeTableLineFull (x, width);
875 void clipEdgeTableLine (
EdgeTable&
et,
int x,
int y,
int width)
877 jassert (x - xOffset >= 0 && x + width - xOffset <= srcData.width);
878 auto* s = (
SrcPixelType*) srcData.getLinePointer (y - yOffset);
879 auto* mask = (
uint8*) (s + x - xOffset);
882 mask += PixelARGB::indexA;
890 const int extraAlpha, xOffset, yOffset;
922 }
while (--width > 0);
931 template <
class DestPixelType,
class SrcPixelType,
bool repeatPattern>
932 struct TransformedImageFill
936 : interpolator (transform,
941 extraAlpha (alpha + 1),
943 maxX (src.width - 1),
944 maxY (src.height - 1)
946 scratchBuffer.malloc (scratchSize);
963 forcedinline void handleEdgeTablePixelFull (
int x)
noexcept
968 getDestPixel (x)->blend (p, (
uint32) extraAlpha);
971 void handleEdgeTableLine (
int x,
int width,
int alphaLevel)
noexcept
973 if (width > (
int) scratchSize)
975 scratchSize = (
size_t) width;
976 scratchBuffer.malloc (scratchSize);
980 generate (span, x, width);
982 auto* dest = getDestPixel (x);
989 JUCE_PERFORM_PIXEL_OP_LOOP (blend (*span++))
992 forcedinline void handleEdgeTableLineFull (
int x,
int width)
noexcept
994 handleEdgeTableLine (x, width, 255);
997 void handleEdgeTableRectangle (
int x,
int y,
int width,
int height,
int alphaLevel)
noexcept
999 while (--height >= 0)
1001 setEdgeTableYPos (y++);
1006 void handleEdgeTableRectangleFull (
int x,
int y,
int width,
int height)
noexcept
1008 while (--height >= 0)
1010 setEdgeTableYPos (y++);
1011 handleEdgeTableLineFull (x, width);
1015 void clipEdgeTableLine (
EdgeTable&
et,
int x,
int y,
int width)
1017 if (width > (
int) scratchSize)
1019 scratchSize = (
size_t) width;
1020 scratchBuffer.malloc (scratchSize);
1024 generate (scratchBuffer.get(), x, width);
1026 et.clipLineToMask (x, y,
1027 reinterpret_cast<uint8*
> (scratchBuffer.get()) + SrcPixelType::indexA,
1038 template <
class PixelType>
1041 this->interpolator.setStartOfLine ((
float) x, (
float) currentY,
numPixels);
1115 uint32 c[4] = { 256 * 128, 256 * 128, 256 * 128, 256 * 128 };
1131 src += this->srcData.lineStride;
1139 src -= this->srcData.pixelStride;
1147 dest->setARGB ((
uint8) (c[PixelARGB::indexA] >> 16),
1148 (
uint8) (c[PixelARGB::indexR] >> 16),
1149 (
uint8) (c[PixelARGB::indexG] >> 16),
1150 (
uint8) (c[PixelARGB::indexB] >> 16));
1155 uint32 c[4] = { 128, 128, 128, 128 };
1171 dest->setARGB ((
uint8) (c[PixelARGB::indexA] >> 8),
1172 (
uint8) (c[PixelARGB::indexR] >> 8),
1173 (
uint8) (c[PixelARGB::indexG] >> 8),
1174 (
uint8) (c[PixelARGB::indexB] >> 8));
1179 uint32 c[4] = { 128, 128, 128, 128 };
1195 dest->setARGB ((
uint8) (c[PixelARGB::indexA] >> 8),
1196 (
uint8) (c[PixelARGB::indexR] >> 8),
1197 (
uint8) (c[PixelARGB::indexG] >> 8),
1198 (
uint8) (c[PixelARGB::indexB] >> 8));
1204 uint32 c[3] = { 256 * 128, 256 * 128, 256 * 128 };
1218 src += this->srcData.lineStride;
1225 src -= this->srcData.pixelStride;
1232 dest->setARGB ((
uint8) 255,
1233 (
uint8) (c[PixelRGB::indexR] >> 16),
1234 (
uint8) (c[PixelRGB::indexG] >> 16),
1235 (
uint8) (c[PixelRGB::indexB] >> 16));
1240 uint32 c[3] = { 128, 128, 128 };
1253 dest->setARGB ((
uint8) 255,
1254 (
uint8) (c[PixelRGB::indexR] >> 8),
1255 (
uint8) (c[PixelRGB::indexG] >> 8),
1256 (
uint8) (c[PixelRGB::indexB] >> 8));
1261 uint32 c[3] = { 128, 128, 128 };
1274 dest->setARGB ((
uint8) 255,
1275 (
uint8) (c[PixelRGB::indexR] >> 8),
1276 (
uint8) (c[PixelRGB::indexG] >> 8),
1277 (
uint8) (c[PixelRGB::indexB] >> 8));
1287 src += this->srcData.lineStride;
1289 src -= this->srcData.pixelStride;
1315 struct TransformedImageSpanInterpolator
1318 : inverseTransform (transform.inverted()),
1322 void setStartOfLine (
float sx,
float sy,
int numPixels)
noexcept
1330 inverseTransform.transformPoints (x1,
y1,
sx,
sy);
1332 xBresenham.set ((
int) (x1 * 256.0f), (
int) (
sx * 256.0f),
numPixels, pixelOffsetInt);
1333 yBresenham.set ((
int) (
y1 * 256.0f), (
int) (
sy * 256.0f),
numPixels, pixelOffsetInt);
1336 void next (
int&
px,
int&
py)
noexcept
1338 px = xBresenham.n; xBresenham.stepToNext();
1339 py = yBresenham.n; yBresenham.stepToNext();
1343 struct BresenhamInterpolator
1345 BresenhamInterpolator() =
default;
1350 step = (
n2 -
n1) / numSteps;
1383 BresenhamInterpolator xBresenham, yBresenham;
1384 const float pixelOffset;
1385 const int pixelOffsetInt;
1391 TransformedImageSpanInterpolator interpolator;
1394 const int extraAlpha;
1396 const int maxX, maxY;
1400 size_t scratchSize = 2048;
1407 template <
class Iterator>
1425 case Image::UnknownFormat:
1446 case Image::UnknownFormat:
1456 case Image::UnknownFormat:
1469 case Image::UnknownFormat:
1479 template <
class Iterator>
1496 case Image::UnknownFormat:
1516 case Image::UnknownFormat:
1525 case Image::UnknownFormat:
1538 case Image::UnknownFormat:
1548 template <
class Iterator,
class DestPixelType>
1553 EdgeTableFillers::SolidColour<DestPixelType, true> r (destData,
fillColour);
1558 EdgeTableFillers::SolidColour<DestPixelType, false> r (destData,
fillColour);
1563 template <
class Iterator,
class DestPixelType>
1571 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Radial>
renderer (destData, g, transform, lookupTable,
numLookupEntries);
1576 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::TransformedRadial>
renderer (destData, g, transform, lookupTable,
numLookupEntries);
1582 EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Linear>
renderer (destData, g, transform, lookupTable,
numLookupEntries);
2050 : clip (
new RectangleListRegionType (
initialClip)),
2056 : clip (
new RectangleListRegionType (
clipList)), transform (
origin),
2062 : clip (
other.clip), transform (
other.transform), fillType (
other.fillType),
2063 interpolationQuality (
other.interpolationQuality),
2064 transparencyLayerAlpha (
other.transparencyLayerAlpha)
2072 if (clip !=
nullptr)
2074 if (transform.isOnlyTranslated)
2076 cloneClipIfMultiplyReferenced();
2077 clip = clip->clipToRectangle (transform.translated (r));
2079 else if (! transform.isRotated)
2081 cloneClipIfMultiplyReferenced();
2082 clip = clip->clipToRectangle (transform.transformed (r));
2092 return clip !=
nullptr;
2097 if (clip !=
nullptr)
2099 if (transform.isOnlyTranslated)
2101 cloneClipIfMultiplyReferenced();
2103 if (transform.isIdentity())
2105 clip = clip->clipToRectangleList (r);
2111 clip = clip->clipToRectangleList (
offsetList);
2114 else if (! transform.isRotated)
2116 cloneClipIfMultiplyReferenced();
2122 clip = clip->clipToRectangleList (
scaledList);
2126 clipToPath (r.
toPath(), {});
2130 return clip !=
nullptr;
2140 return { x1,
y1, x2 - x1, y2 -
y1 };
2145 if (clip !=
nullptr)
2147 cloneClipIfMultiplyReferenced();
2149 if (transform.isOnlyTranslated)
2151 clip = clip->excludeClipRectangle (getLargestIntegerWithin (transform.translated (r.
toFloat())));
2153 else if (! transform.isRotated)
2155 clip = clip->excludeClipRectangle (getLargestIntegerWithin (transform.transformed (r.
toFloat())));
2164 clip = clip->clipToPath (p, {});
2168 return clip !=
nullptr;
2173 if (clip !=
nullptr)
2175 cloneClipIfMultiplyReferenced();
2176 clip = clip->clipToPath (p, transform.getTransformWith (t));
2182 if (clip !=
nullptr)
2186 cloneClipIfMultiplyReferenced();
2187 clip = clip->clipToImageAlpha (sourceImage, transform.getTransformWith (t), interpolationQuality);
2200 if (clip !=
nullptr)
2202 if (transform.isOnlyTranslated)
2203 return clip->clipRegionIntersects (transform.translated (r));
2213 return clip !=
nullptr ? transform.deviceSpaceToUserSpace (clip->getClipBounds())
2230 auto clipped = clip->getClipBounds().getIntersection (r);
2233 fillShape (*
new RectangleListRegionType (
clipped),
false);
2245 auto clipped = clip->getClipBounds().toFloat().getIntersection (r);
2248 fillShape (*
new EdgeTableRegionType (
clipped),
false);
2252 template <
typename CoordType>
2262 if (clip !=
nullptr)
2264 if (transform.isOnlyTranslated)
2268 else if (! transform.isRotated)
2282 if (clip !=
nullptr)
2284 if (transform.isOnlyTranslated)
2285 fillTargetRect (transform.translated (r));
2286 else if (! transform.isRotated)
2287 fillTargetRect (transform.transformed (r));
2295 if (clip !=
nullptr)
2297 if (list.getNumRectangles() == 1)
2298 return fillRect (*list.begin());
2300 if (transform.isIdentity())
2302 fillShape (*
new EdgeTableRegionType (list),
false);
2304 else if (! transform.isRotated)
2308 if (transform.isOnlyTranslated)
2313 fillShape (*
new EdgeTableRegionType (transformed),
false);
2317 fillPath (list.toPath(), {});
2324 if (clip !=
nullptr)
2326 auto trans = transform.getTransformWith (t);
2327 auto clipRect = clip->getClipBounds();
2330 fillShape (*
new EdgeTableRegionType (
clipRect, path,
trans),
false);
2334 void fillEdgeTable (
const EdgeTable& edgeTable,
float x,
int y)
2336 if (clip !=
nullptr)
2345 if (brightness > 0.0f)
2346 edgeTableClip->edgeTable.multiplyLevels (1.0f + 1.6f * brightness);
2363 renderImage (sourceImage,
trans, {});
2370 && std::abs (t.mat00 - 1.0f) <
tolerance
2371 && std::abs (t.mat11 - 1.0f) <
tolerance;
2376 auto t = transform.getTransformWith (
trans);
2379 if (isOnlyTranslationAllowingError (t, 0.002f))
2387 tx = ((
tx + 128) >> 8);
2388 ty = ((
ty + 128) >> 8);
2400 if (
auto c = clip->applyClipTo (*
new EdgeTableRegionType (area)))
2401 c->renderImageUntransformed (getThis(), sourceImage, alpha,
tx,
ty,
false);
2413 t, interpolationQuality,
true);
2420 if (
auto c = clip->clone()->clipToPath (p, t))
2421 c->renderImageTransformed (getThis(), sourceImage, alpha,
2422 t, interpolationQuality,
false);
2447 g2.point1.applyTransform (t);
2448 g2.point2.applyTransform (t);
2452 shapeToFill->fillAllWithGradient (getThis(),
g2, t, isIdentity);
2465 void cloneClipIfMultiplyReferenced()
2467 if (clip->getReferenceCount() > 1)
2468 clip = clip->clone();
2471 typename BaseRegionType::Ptr clip;
2475 float transparencyLayerAlpha;