From cbfbd8cf122f2c73adf00da246505e113e172789 Mon Sep 17 00:00:00 2001 From: reuk Date: Mon, 8 Jun 2020 10:13:13 +0100 Subject: [PATCH] CoreGraphics: Use generic colour spaces, instead of device colour spaces --- .../native/juce_mac_CoreGraphicsContext.h | 42 ++- .../native/juce_mac_CoreGraphicsContext.mm | 279 ++++++++---------- .../juce_graphics/native/juce_mac_Fonts.mm | 2 +- .../native/juce_mac_NSViewComponentPeer.mm | 2 +- 4 files changed, 168 insertions(+), 157 deletions(-) diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h index 55cbecb43e..eefa75f1d5 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h @@ -19,6 +19,41 @@ namespace juce { +namespace detail +{ + struct ColorSpaceDelete + { + void operator() (CGColorSpaceRef ptr) const noexcept { CGColorSpaceRelease (ptr); } + }; + + struct ContextDelete + { + void operator() (CGContextRef ptr) const noexcept { CGContextRelease (ptr); } + }; + + struct DataProviderDelete + { + void operator() (CGDataProviderRef ptr) const noexcept { CGDataProviderRelease (ptr); } + }; + + struct ImageDelete + { + void operator() (CGImageRef ptr) const noexcept { CGImageRelease (ptr); } + }; + + struct GradientDelete + { + void operator() (CGGradientRef ptr) const noexcept { CGGradientRelease (ptr); } + }; + + //============================================================================== + using ColorSpacePtr = std::unique_ptr; + using ContextPtr = std::unique_ptr; + using DataProviderPtr = std::unique_ptr; + using ImagePtr = std::unique_ptr; + using GradientPtr = std::unique_ptr; +} + //============================================================================== class CoreGraphicsContext : public LowLevelGraphicsContext { @@ -67,9 +102,10 @@ public: bool drawTextLayout (const AttributedString&, const Rectangle&) override; private: - CGContextRef context; + //============================================================================== + detail::ContextPtr context; const CGFloat flipHeight; - CGColorSpaceRef rgbColourSpace, greyColourSpace; + detail::ColorSpacePtr rgbColourSpace, greyColourSpace; mutable Rectangle lastClipRect; mutable bool lastClipRectIsValid = false; @@ -86,7 +122,7 @@ private: CGFontRef fontRef = {}; CGAffineTransform textMatrix = CGAffineTransformIdentity, inverseTextMatrix = CGAffineTransformIdentity; - CGGradientRef gradient = {}; + detail::GradientPtr gradient = {}; }; std::unique_ptr state; diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm index 98ae35ec69..7a2ec36481 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm @@ -43,26 +43,23 @@ public: imageDataHolder->data.allocate (numComponents, clearImage); - CGColorSpaceRef colourSpace = (format == Image::SingleChannel) ? CGColorSpaceCreateDeviceGray() - : CGColorSpaceCreateDeviceRGB(); + auto colourSpace = detail::ColorSpacePtr { CGColorSpaceCreateWithName ((format == Image::SingleChannel) ? kCGColorSpaceGenericGrayGamma2_2 + : kCGColorSpaceSRGB) }; - context = CGBitmapContextCreate (imageDataHolder->data, (size_t) width, (size_t) height, 8, (size_t) lineStride, - colourSpace, getCGImageFlags (format)); - - CGColorSpaceRelease (colourSpace); + context = detail::ContextPtr { CGBitmapContextCreate (imageDataHolder->data, (size_t) width, (size_t) height, 8, (size_t) lineStride, + colourSpace.get(), getCGImageFlags (format)) }; } ~CoreGraphicsPixelData() override { freeCachedImageRef(); - CGContextRelease (context); } std::unique_ptr createLowLevelContext() override { freeCachedImageRef(); sendDataChangeMessage(); - return std::make_unique (context, height); + return std::make_unique (context.get(), height); } void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override @@ -95,14 +92,14 @@ public: if (cgim != nullptr && cgim->cachedImageRef != nullptr) { - CGImageRetain (cgim->cachedImageRef); - return cgim->cachedImageRef; + CGImageRetain (cgim->cachedImageRef.get()); + return cgim->cachedImageRef.get(); } CGImageRef ref = createImage (juceImage, colourSpace, false); if (cgim != nullptr) - cgim->cachedImageRef = CGImageRetain (ref); + cgim->cachedImageRef.reset (CGImageRetain (ref)); return ref; } @@ -110,12 +107,12 @@ public: static CGImageRef createImage (const Image& juceImage, CGColorSpaceRef colourSpace, bool mustOutliveSource) { const Image::BitmapData srcData (juceImage, Image::BitmapData::readOnly); - CGDataProviderRef provider; + detail::DataProviderPtr provider; if (mustOutliveSource) { CFDataRef data = CFDataCreate (nullptr, (const UInt8*) srcData.data, (CFIndex) ((size_t) srcData.lineStride * (size_t) srcData.height)); - provider = CGDataProviderCreateWithCFData (data); + provider = detail::DataProviderPtr { CGDataProviderCreateWithCFData (data) }; CFRelease (data); } else @@ -128,10 +125,10 @@ public: return nullptr; } (juceImage); - provider = CGDataProviderCreateWithData (imageDataContainer, - srcData.data, - (size_t) srcData.lineStride * (size_t) srcData.height, - [] (void * __nullable info, const void*, size_t) { delete (HeapBlockContainer::Ptr*) info; }); + provider = detail::DataProviderPtr { CGDataProviderCreateWithData (imageDataContainer, + srcData.data, + (size_t) srcData.lineStride * (size_t) srcData.height, + [] (void * __nullable info, const void*, size_t) { delete (HeapBlockContainer::Ptr*) info; }) }; } CGImageRef imageRef = CGImageCreate ((size_t) srcData.width, @@ -139,16 +136,15 @@ public: 8, (size_t) srcData.pixelStride * 8, (size_t) srcData.lineStride, - colourSpace, getCGImageFlags (juceImage.getFormat()), provider, + colourSpace, getCGImageFlags (juceImage.getFormat()), provider.get(), nullptr, true, kCGRenderingIntentDefault); - CGDataProviderRelease (provider); return imageRef; } //============================================================================== - CGContextRef context; - CGImageRef cachedImageRef = {}; + detail::ContextPtr context; + detail::ImagePtr cachedImageRef; struct HeapBlockContainer : public ReferenceCountedObject { @@ -162,11 +158,7 @@ public: private: void freeCachedImageRef() { - if (cachedImageRef != CGImageRef()) - { - CGImageRelease (cachedImageRef); - cachedImageRef = {}; - } + cachedImageRef.reset(); } static CGBitmapInfo getCGImageFlags (const Image::PixelFormat& format) @@ -192,8 +184,8 @@ CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, float h) flipHeight (h), state (new SavedState()) { - CGContextRetain (context); - CGContextSaveGState (context); + CGContextRetain (context.get()); + CGContextSaveGState (context.get()); bool enableFontSmoothing #if JUCE_DISABLE_COREGRAPHICS_FONT_SMOOTHING @@ -202,27 +194,24 @@ CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, float h) = true; #endif - CGContextSetShouldSmoothFonts (context, enableFontSmoothing); - CGContextSetAllowsFontSmoothing (context, enableFontSmoothing); - CGContextSetShouldAntialias (context, true); - CGContextSetBlendMode (context, kCGBlendModeNormal); - rgbColourSpace = CGColorSpaceCreateDeviceRGB(); - greyColourSpace = CGColorSpaceCreateDeviceGray(); + CGContextSetShouldSmoothFonts (context.get(), enableFontSmoothing); + CGContextSetAllowsFontSmoothing (context.get(), enableFontSmoothing); + CGContextSetShouldAntialias (context.get(), true); + CGContextSetBlendMode (context.get(), kCGBlendModeNormal); + rgbColourSpace.reset (CGColorSpaceCreateWithName (kCGColorSpaceSRGB)); + greyColourSpace.reset (CGColorSpaceCreateWithName (kCGColorSpaceGenericGrayGamma2_2)); setFont (Font()); } CoreGraphicsContext::~CoreGraphicsContext() { - CGContextRestoreGState (context); - CGContextRelease (context); - CGColorSpaceRelease (rgbColourSpace); - CGColorSpaceRelease (greyColourSpace); + CGContextRestoreGState (context.get()); } //============================================================================== void CoreGraphicsContext::setOrigin (Point o) { - CGContextTranslateCTM (context, o.x, -o.y); + CGContextTranslateCTM (context.get(), o.x, -o.y); if (lastClipRectIsValid) lastClipRect.translate (-o.x, -o.y); @@ -241,7 +230,7 @@ void CoreGraphicsContext::addTransform (const AffineTransform& transform) float CoreGraphicsContext::getPhysicalPixelScaleFactor() { - auto t = CGContextGetUserSpaceToDeviceSpaceTransform (context); + auto t = CGContextGetUserSpaceToDeviceSpaceTransform (context.get()); auto determinant = (t.a * t.d) - (t.c * t.b); return (float) std::sqrt (std::abs (determinant)); @@ -249,8 +238,8 @@ float CoreGraphicsContext::getPhysicalPixelScaleFactor() bool CoreGraphicsContext::clipToRectangle (const Rectangle& r) { - CGContextClipToRect (context, CGRectMake (r.getX(), flipHeight - r.getBottom(), - r.getWidth(), r.getHeight())); + CGContextClipToRect (context.get(), CGRectMake (r.getX(), flipHeight - r.getBottom(), + r.getWidth(), r.getHeight())); if (lastClipRectIsValid) { @@ -269,7 +258,7 @@ bool CoreGraphicsContext::clipToRectangleListWithoutTest (const RectangleList(); return false; @@ -282,7 +271,7 @@ bool CoreGraphicsContext::clipToRectangleListWithoutTest (const RectangleList CoreGraphicsContext::getClipBounds() const { if (! lastClipRectIsValid) { - auto bounds = CGRectIntegral (CGContextGetClipBoundingBox (context)); + auto bounds = CGRectIntegral (CGContextGetClipBoundingBox (context.get())); lastClipRectIsValid = true; lastClipRect.setBounds (roundToInt (bounds.origin.x), @@ -366,18 +354,18 @@ bool CoreGraphicsContext::isClipEmpty() const //============================================================================== void CoreGraphicsContext::saveState() { - CGContextSaveGState (context); + CGContextSaveGState (context.get()); stateStack.add (new SavedState (*state)); } void CoreGraphicsContext::restoreState() { - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); if (auto* top = stateStack.getLast()) { state.reset (top); - CGContextSetTextMatrix (context, state->textMatrix); + CGContextSetTextMatrix (context.get(), state->textMatrix); stateStack.removeLast (1, false); lastClipRectIsValid = false; @@ -391,13 +379,13 @@ void CoreGraphicsContext::restoreState() void CoreGraphicsContext::beginTransparencyLayer (float opacity) { saveState(); - CGContextSetAlpha (context, opacity); - CGContextBeginTransparencyLayer (context, nullptr); + CGContextSetAlpha (context.get(), opacity); + CGContextBeginTransparencyLayer (context.get(), nullptr); } void CoreGraphicsContext::endTransparencyLayer() { - CGContextEndTransparencyLayer (context); + CGContextEndTransparencyLayer (context.get()); restoreState(); } @@ -408,9 +396,9 @@ void CoreGraphicsContext::setFill (const FillType& fillType) if (fillType.isColour()) { - CGContextSetRGBFillColor (context, fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), + CGContextSetRGBFillColor (context.get(), fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(), fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha()); - CGContextSetAlpha (context, 1.0f); + CGContextSetAlpha (context.get(), 1.0f); } } @@ -424,9 +412,9 @@ void CoreGraphicsContext::setInterpolationQuality (Graphics::ResamplingQuality q { switch (quality) { - case Graphics::lowResamplingQuality: CGContextSetInterpolationQuality (context, kCGInterpolationNone); return; - case Graphics::mediumResamplingQuality: CGContextSetInterpolationQuality (context, kCGInterpolationMedium); return; - case Graphics::highResamplingQuality: CGContextSetInterpolationQuality (context, kCGInterpolationHigh); return; + case Graphics::lowResamplingQuality: CGContextSetInterpolationQuality (context.get(), kCGInterpolationNone); return; + case Graphics::mediumResamplingQuality: CGContextSetInterpolationQuality (context.get(), kCGInterpolationMedium); return; + case Graphics::highResamplingQuality: CGContextSetInterpolationQuality (context.get(), kCGInterpolationHigh); return; default: return; } } @@ -446,36 +434,36 @@ void CoreGraphicsContext::fillCGRect (const CGRect& cgRect, bool replaceExisting { if (replaceExistingContents) { - CGContextSetBlendMode (context, kCGBlendModeCopy); + CGContextSetBlendMode (context.get(), kCGBlendModeCopy); fillCGRect (cgRect, false); - CGContextSetBlendMode (context, kCGBlendModeNormal); + CGContextSetBlendMode (context.get(), kCGBlendModeNormal); } else { if (state->fillType.isColour()) { - CGContextFillRect (context, cgRect); + CGContextFillRect (context.get(), cgRect); } else if (state->fillType.isGradient()) { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); + CGContextSaveGState (context.get()); + CGContextClipToRect (context.get(), cgRect); drawGradient(); - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } else { - CGContextSaveGState (context); - CGContextClipToRect (context, cgRect); + CGContextSaveGState (context.get()); + CGContextClipToRect (context.get(), cgRect); drawImage (state->fillType.image, state->fillType.transform, true); - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } } } void CoreGraphicsContext::fillPath (const Path& path, const AffineTransform& transform) { - CGContextSaveGState (context); + CGContextSaveGState (context.get()); if (state->fillType.isColour()) { @@ -484,18 +472,18 @@ void CoreGraphicsContext::fillPath (const Path& path, const AffineTransform& tra createPath (path); if (path.isUsingNonZeroWinding()) - CGContextFillPath (context); + CGContextFillPath (context.get()); else - CGContextEOFillPath (context); + CGContextEOFillPath (context.get()); } else { createPath (path, transform); if (path.isUsingNonZeroWinding()) - CGContextClip (context); + CGContextClip (context.get()); else - CGContextEOClip (context); + CGContextEOClip (context.get()); if (state->fillType.isGradient()) drawGradient(); @@ -503,7 +491,7 @@ void CoreGraphicsContext::fillPath (const Path& path, const AffineTransform& tra drawImage (state->fillType.image, state->fillType.transform, true); } - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTransform& transform) @@ -516,12 +504,12 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans auto iw = sourceImage.getWidth(); auto ih = sourceImage.getHeight(); - auto colourSpace = sourceImage.getFormat() == Image::PixelFormat::SingleChannel ? greyColourSpace - : rgbColourSpace; - CGImageRef image = CoreGraphicsPixelData::getCachedImageRef (sourceImage, colourSpace); + auto colourSpace = sourceImage.getFormat() == Image::PixelFormat::SingleChannel ? greyColourSpace.get() + : rgbColourSpace.get(); + auto image = detail::ImagePtr { CoreGraphicsPixelData::getCachedImageRef (sourceImage, colourSpace) }; - CGContextSaveGState (context); - CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextSaveGState (context.get()); + CGContextSetAlpha (context.get(), state->fillType.getOpacity()); flip(); applyTransform (AffineTransform::verticalFlip (ih).followedBy (transform)); @@ -530,18 +518,18 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans if (fillEntireClipAsTiles) { #if JUCE_IOS - CGContextDrawTiledImage (context, imageRect, image); + CGContextDrawTiledImage (context.get(), imageRect, image.get()); #else // There's a bug in CGContextDrawTiledImage that makes it incredibly slow // if it's doing a transformation - it's quicker to just draw lots of images manually if (&CGContextDrawTiledImage != nullptr && transform.isOnlyTranslation()) { - CGContextDrawTiledImage (context, imageRect, image); + CGContextDrawTiledImage (context.get(), imageRect, image.get()); } else { // Fallback to manually doing a tiled fill - auto clip = CGRectIntegral (CGContextGetClipBoundingBox (context)); + auto clip = CGRectIntegral (CGContextGetClipBoundingBox (context.get())); int x = 0, y = 0; while (x > clip.origin.x) x -= iw; @@ -553,7 +541,7 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans while (y < bottom) { for (int x2 = x; x2 < right; x2 += iw) - CGContextDrawImage (context, CGRectMake (x2, y, iw, ih), image); + CGContextDrawImage (context.get(), CGRectMake (x2, y, iw, ih), image.get()); y += ih; } @@ -562,11 +550,10 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans } else { - CGContextDrawImage (context, imageRect, image); + CGContextDrawImage (context.get(), imageRect, image.get()); } - CGImageRelease (image); // (This causes a memory bug in iOS sim 3.0 - try upgrading to a later version if you hit this) - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } //============================================================================== @@ -588,21 +575,21 @@ void CoreGraphicsContext::fillRectList (const RectangleList& list) if (state->fillType.isColour()) { - CGContextFillRects (context, rects, num); + CGContextFillRects (context.get(), rects, num); } else if (state->fillType.isGradient()) { - CGContextSaveGState (context); - CGContextClipToRects (context, rects, num); + CGContextSaveGState (context.get()); + CGContextClipToRects (context.get(), rects, num); drawGradient(); - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } else { - CGContextSaveGState (context); - CGContextClipToRects (context, rects, num); + CGContextSaveGState (context.get()); + CGContextClipToRects (context.get(), rects, num); drawImage (state->fillType.image, state->fillType.transform, true); - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } } @@ -616,12 +603,12 @@ void CoreGraphicsContext::setFont (const Font& newFont) if (auto osxTypeface = dynamic_cast (state->font.getTypeface())) { state->fontRef = osxTypeface->fontRef; - CGContextSetFont (context, state->fontRef); - CGContextSetFontSize (context, state->font.getHeight() * osxTypeface->fontHeightToPointsFactor); + CGContextSetFont (context.get(), state->fontRef); + CGContextSetFontSize (context.get(), state->font.getHeight() * osxTypeface->fontHeightToPointsFactor); state->textMatrix = osxTypeface->renderingTransform; state->textMatrix.a *= state->font.getHorizontalScale(); - CGContextSetTextMatrix (context, state->textMatrix); + CGContextSetTextMatrix (context.get(), state->textMatrix); state->inverseTextMatrix = CGAffineTransformInvert (state->textMatrix); } } @@ -648,24 +635,24 @@ void CoreGraphicsContext::drawGlyph (int glyphNumber, const AffineTransform& tra CGGlyph glyphs[1] = { (CGGlyph) glyphNumber }; CGPoint positions[1] = { { x, flipHeight - roundToInt (y) } }; - CGContextShowGlyphsAtPositions (context, glyphs, positions, 1); + CGContextShowGlyphsAtPositions (context.get(), glyphs, positions, 1); } else { - CGContextSaveGState (context); + CGContextSaveGState (context.get()); flip(); applyTransform (transform); - CGContextConcatCTM (context, state->inverseTextMatrix); + CGContextConcatCTM (context.get(), state->inverseTextMatrix); auto cgTransform = state->textMatrix; cgTransform.d = -cgTransform.d; - CGContextConcatCTM (context, cgTransform); + CGContextConcatCTM (context.get(), cgTransform); CGGlyph glyphs[1] = { (CGGlyph) glyphNumber }; CGPoint positions[1] = { { 0.0f, 0.0f } }; - CGContextShowGlyphsAtPositions (context, glyphs, positions, 1); + CGContextShowGlyphsAtPositions (context.get(), glyphs, positions, 1); - CGContextRestoreGState (context); + CGContextRestoreGState (context.get()); } } else @@ -681,7 +668,7 @@ void CoreGraphicsContext::drawGlyph (int glyphNumber, const AffineTransform& tra bool CoreGraphicsContext::drawTextLayout (const AttributedString& text, const Rectangle& area) { - CoreTextTypeLayout::drawToCGContext (text, area, context, (float) flipHeight); + CoreTextTypeLayout::drawToCGContext (text, area, context.get(), (float) flipHeight); return true; } @@ -693,27 +680,18 @@ CoreGraphicsContext::SavedState::SavedState() CoreGraphicsContext::SavedState::SavedState (const SavedState& other) : fillType (other.fillType), font (other.font), fontRef (other.fontRef), textMatrix (other.textMatrix), inverseTextMatrix (other.inverseTextMatrix), - gradient (other.gradient) + gradient (other.gradient.get()) { if (gradient != nullptr) - CGGradientRetain (gradient); + CGGradientRetain (gradient.get()); } -CoreGraphicsContext::SavedState::~SavedState() -{ - if (gradient != nullptr) - CGGradientRelease (gradient); -} +CoreGraphicsContext::SavedState::~SavedState() = default; void CoreGraphicsContext::SavedState::setFill (const FillType& newFill) { fillType = newFill; - - if (gradient != nullptr) - { - CGGradientRelease (gradient); - gradient = nullptr; - } + gradient = nullptr; } static CGGradientRef createGradient (const ColourGradient& g, CGColorSpaceRef colourSpace) @@ -745,37 +723,37 @@ void CoreGraphicsContext::drawGradient() { flip(); applyTransform (state->fillType.transform); - CGContextSetAlpha (context, state->fillType.getOpacity()); + CGContextSetAlpha (context.get(), state->fillType.getOpacity()); auto& g = *state->fillType.gradient; if (state->gradient == nullptr) - state->gradient = createGradient (g, rgbColourSpace); + state->gradient.reset (createGradient (g, rgbColourSpace.get())); auto p1 = convertToCGPoint (g.point1); auto p2 = convertToCGPoint (g.point2); if (g.isRadial) - CGContextDrawRadialGradient (context, state->gradient, p1, 0, p1, g.point1.getDistanceFrom (g.point2), + CGContextDrawRadialGradient (context.get(), state->gradient.get(), p1, 0, p1, g.point1.getDistanceFrom (g.point2), kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); else - CGContextDrawLinearGradient (context, state->gradient, p1, p2, + CGContextDrawLinearGradient (context.get(), state->gradient.get(), p1, p2, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); } void CoreGraphicsContext::createPath (const Path& path) const { - CGContextBeginPath (context); + CGContextBeginPath (context.get()); for (Path::Iterator i (path); i.next();) { switch (i.elementType) { - case Path::Iterator::startNewSubPath: CGContextMoveToPoint (context, i.x1, i.y1); break; - case Path::Iterator::lineTo: CGContextAddLineToPoint (context, i.x1, i.y1); break; - case Path::Iterator::quadraticTo: CGContextAddQuadCurveToPoint (context, i.x1, i.y1, i.x2, i.y2); break; - case Path::Iterator::cubicTo: CGContextAddCurveToPoint (context, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; - case Path::Iterator::closePath: CGContextClosePath (context); break; + case Path::Iterator::startNewSubPath: CGContextMoveToPoint (context.get(), i.x1, i.y1); break; + case Path::Iterator::lineTo: CGContextAddLineToPoint (context.get(), i.x1, i.y1); break; + case Path::Iterator::quadraticTo: CGContextAddQuadCurveToPoint (context.get(), i.x1, i.y1, i.x2, i.y2); break; + case Path::Iterator::cubicTo: CGContextAddCurveToPoint (context.get(), i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; + case Path::Iterator::closePath: CGContextClosePath (context.get()); break; default: jassertfalse; break; } } @@ -783,7 +761,7 @@ void CoreGraphicsContext::createPath (const Path& path) const void CoreGraphicsContext::createPath (const Path& path, const AffineTransform& transform) const { - CGContextBeginPath (context); + CGContextBeginPath (context.get()); for (Path::Iterator i (path); i.next();) { @@ -791,22 +769,22 @@ void CoreGraphicsContext::createPath (const Path& path, const AffineTransform& t { case Path::Iterator::startNewSubPath: transform.transformPoint (i.x1, i.y1); - CGContextMoveToPoint (context, i.x1, flipHeight - i.y1); + CGContextMoveToPoint (context.get(), i.x1, flipHeight - i.y1); break; case Path::Iterator::lineTo: transform.transformPoint (i.x1, i.y1); - CGContextAddLineToPoint (context, i.x1, flipHeight - i.y1); + CGContextAddLineToPoint (context.get(), i.x1, flipHeight - i.y1); break; case Path::Iterator::quadraticTo: transform.transformPoints (i.x1, i.y1, i.x2, i.y2); - CGContextAddQuadCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); + CGContextAddQuadCurveToPoint (context.get(), i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2); break; case Path::Iterator::cubicTo: transform.transformPoints (i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); - CGContextAddCurveToPoint (context, i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); + CGContextAddCurveToPoint (context.get(), i.x1, flipHeight - i.y1, i.x2, flipHeight - i.y2, i.x3, flipHeight - i.y3); break; case Path::Iterator::closePath: - CGContextClosePath (context); break; + CGContextClosePath (context.get()); break; default: jassertfalse; break; @@ -816,7 +794,7 @@ void CoreGraphicsContext::createPath (const Path& path, const AffineTransform& t void CoreGraphicsContext::flip() const { - CGContextConcatCTM (context, CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); + CGContextConcatCTM (context.get(), CGAffineTransformMake (1, 0, 0, -1, 0, flipHeight)); } void CoreGraphicsContext::applyTransform (const AffineTransform& transform) const @@ -828,7 +806,7 @@ void CoreGraphicsContext::applyTransform (const AffineTransform& transform) cons t.d = transform.mat11; t.tx = transform.mat02; t.ty = transform.mat12; - CGContextConcatCTM (context, t); + CGContextConcatCTM (context.get(), t); } //============================================================================== @@ -856,12 +834,11 @@ Image juce_loadWithCoreImage (InputStream& input) CGImageRef loadedImage = uiImage.CGImage; #else - auto provider = CGDataProviderCreateWithData (new MemoryBlockHolder::Ptr (memBlockHolder), - memBlockHolder->block.getData(), - memBlockHolder->block.getSize(), - [] (void * __nullable info, const void*, size_t) { delete (MemoryBlockHolder::Ptr*) info; }); - auto imageSource = CGImageSourceCreateWithDataProvider (provider, nullptr); - CGDataProviderRelease (provider); + auto provider = detail::DataProviderPtr { CGDataProviderCreateWithData (new MemoryBlockHolder::Ptr (memBlockHolder), + memBlockHolder->block.getData(), + memBlockHolder->block.getSize(), + [] (void * __nullable info, const void*, size_t) { delete (MemoryBlockHolder::Ptr*) info; }) }; + auto imageSource = CGImageSourceCreateWithDataProvider (provider.get(), nullptr); if (imageSource != nullptr) { @@ -884,8 +861,8 @@ Image juce_loadWithCoreImage (InputStream& input) auto cgImage = dynamic_cast (image.getPixelData()); jassert (cgImage != nullptr); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsPixelData class should have been used. - CGContextDrawImage (cgImage->context, convertToCGRect (image.getBounds()), loadedImage); - CGContextFlush (cgImage->context); + CGContextDrawImage (cgImage->context.get(), convertToCGRect (image.getBounds()), loadedImage); + CGContextFlush (cgImage->context.get()); #if ! JUCE_IOS CFRelease (loadedImage); @@ -908,9 +885,9 @@ Image juce_createImageFromCIImage (CIImage* im, int w, int h) { auto cgImage = new CoreGraphicsPixelData (Image::ARGB, w, h, false); - CIContext* cic = [CIContext contextWithCGContext: cgImage->context options: nil]; + CIContext* cic = [CIContext contextWithCGContext: cgImage->context.get() options: nil]; [cic drawImage: im inRect: CGRectMake (0, 0, w, h) fromRect: CGRectMake (0, 0, w, h)]; - CGContextFlush (cgImage->context); + CGContextFlush (cgImage->context.get()); return Image (*cgImage); } @@ -924,7 +901,7 @@ CGImageRef juce_createCoreGraphicsImage (const Image& juceImage, CGColorSpaceRef CGContextRef juce_getImageContext (const Image& image) { if (auto cgi = dynamic_cast (image.getPixelData())) - return cgi->context; + return cgi->context.get(); jassertfalse; return {}; @@ -953,15 +930,13 @@ CGContextRef juce_getImageContext (const Image& image) auto requiredSize = NSMakeSize (image.getWidth() / scaleFactor, image.getHeight() / scaleFactor); [im setSize: requiredSize]; - auto colourSpace = CGColorSpaceCreateDeviceRGB(); - auto imageRef = juce_createCoreGraphicsImage (image, colourSpace, true); - CGColorSpaceRelease (colourSpace); + auto colourSpace = detail::ColorSpacePtr { CGColorSpaceCreateWithName (kCGColorSpaceSRGB) }; + auto imageRef = detail::ImagePtr { juce_createCoreGraphicsImage (image, colourSpace.get(), true) }; - NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef]; + NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage: imageRef.get()]; [imageRep setSize: requiredSize]; [im addRepresentation: imageRep]; [imageRep release]; - CGImageRelease (imageRef); return im; } } diff --git a/modules/juce_graphics/native/juce_mac_Fonts.mm b/modules/juce_graphics/native/juce_mac_Fonts.mm index a4019b2387..7cf1e28ca5 100644 --- a/modules/juce_graphics/native/juce_mac_Fonts.mm +++ b/modules/juce_graphics/native/juce_mac_Fonts.mm @@ -201,7 +201,7 @@ namespace CoreTextTypeLayout static CFAttributedStringRef createCFAttributedString (const AttributedString& text) { #if JUCE_IOS - auto rgbColourSpace = CGColorSpaceCreateDeviceRGB(); + auto rgbColourSpace = CGColorSpaceCreateWithName (kCGColorSpaceSRGB); #endif auto attribString = CFAttributedStringCreateMutable (kCFAllocatorDefault, 0); diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index fab1f024ec..426b4a05b4 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -909,7 +909,7 @@ public: invokePaint (*context); } - CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); + CGColorSpaceRef colourSpace = CGColorSpaceCreateWithName (kCGColorSpaceSRGB); CGImageRef image = juce_createCoreGraphicsImage (temp, colourSpace, false); CGColorSpaceRelease (colourSpace); CGContextDrawImage (cg, CGRectMake (r.origin.x, r.origin.y, clipW, clipH), image);