diff --git a/modules/juce_graphics/images/juce_Image.cpp b/modules/juce_graphics/images/juce_Image.cpp index 28f5b59cab..6af4ae1487 100644 --- a/modules/juce_graphics/images/juce_Image.cpp +++ b/modules/juce_graphics/images/juce_Image.cpp @@ -262,9 +262,49 @@ namespace BitmapDataDetail } } +//============================================================================== +/* Allows access to ImagePixelData implementation details by LowLevelGraphicsContext instances. + The internal templating is mainly to facilitate returning a type with dynamic implementation by value. +*/ +class ImagePixelDataNativeExtensions +{ +public: + template + explicit ImagePixelDataNativeExtensions (Impl x) + : impl (std::make_unique> (std::move (x))) {} + + /* For subsection images, this returns the top-left pixel inside the root image */ + Point getTopLeft() const { return impl->getTopLeft(); } + +private: + struct Base + { + virtual ~Base() = default; + virtual Point getTopLeft() const = 0; + }; + + template + class Concrete : public Base + { + public: + explicit Concrete (Impl x) + : impl (std::move (x)) {} + + Point getTopLeft() const override { return impl.getTopLeft(); } + + private: + Impl impl; + }; + + std::unique_ptr impl; +}; + +//============================================================================== class SubsectionPixelData : public ImagePixelData { public: + using Ptr = ReferenceCountedObjectPtr; + SubsectionPixelData (ImagePixelData::Ptr source, Rectangle r) : ImagePixelData (source->pixelFormat, r.getWidth(), r.getHeight()), sourceImage (std::move (source)), @@ -330,6 +370,24 @@ public: /* as we always hold a reference to image, don't double count */ int getSharedCount() const noexcept override { return getReferenceCount() + sourceImage->getSharedCount() - 1; } + NativeExtensions getNativeExtensions() override + { + struct Wrapped + { + explicit Wrapped (Ptr selfIn) + : self (selfIn) {} + + Point getTopLeft() const + { + return self->sourceImage->getNativeExtensions().getTopLeft() + self->area.getTopLeft(); + } + + Ptr self; + }; + + return NativeExtensions { Wrapped { this } }; + } + private: Rectangle getIntersection (Rectangle b) const { @@ -402,6 +460,16 @@ void ImagePixelData::desaturateInArea (Rectangle b) } } +auto ImagePixelData::getNativeExtensions() -> NativeExtensions +{ + struct Wrapped + { + Point getTopLeft() const { return {}; } + }; + + return NativeExtensions { Wrapped{} }; +} + //============================================================================== ImageType::ImageType() = default; ImageType::~ImageType() = default; diff --git a/modules/juce_graphics/images/juce_Image.h b/modules/juce_graphics/images/juce_Image.h index 59ff52c781..b1623c9437 100644 --- a/modules/juce_graphics/images/juce_Image.h +++ b/modules/juce_graphics/images/juce_Image.h @@ -555,6 +555,11 @@ protected: ~ImagePixelDataBackupExtensions() = default; }; +/** @internal + @tags{Graphics} + */ +class ImagePixelDataNativeExtensions; + //============================================================================== /** This is a base class for holding image data in implementation-specific ways. @@ -572,6 +577,7 @@ class JUCE_API ImagePixelData : public ReferenceCountedObject { public: using BackupExtensions = ImagePixelDataBackupExtensions; + using NativeExtensions = ImagePixelDataNativeExtensions; ImagePixelData (Image::PixelFormat, int width, int height); ~ImagePixelData() override; @@ -679,6 +685,9 @@ public: void sendDataChangeMessage(); + /** @internal intentionally not callable from user code */ + virtual NativeExtensions getNativeExtensions(); + private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ImagePixelData) };