Skip to content

Instantly share code, notes, and snippets.

@beschulz
Created February 17, 2015 15:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beschulz/36cca0c38302bcd05618 to your computer and use it in GitHub Desktop.
Save beschulz/36cca0c38302bcd05618 to your computer and use it in GitHub Desktop.
juce_use_CGContextDrawXYZGradient_on_osx_10_5_plus.diff
diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h
index bf26ce8..41a8571 100644
--- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h
+++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h
@@ -77,7 +77,9 @@ private:
const CGFloat flipHeight;
float targetScale;
CGColorSpaceRef rgbColourSpace, greyColourSpace;
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
CGFunctionCallbacks gradientCallbacks;
+ #endif
mutable Rectangle<int> lastClipRect;
mutable bool lastClipRectIsValid;
@@ -88,9 +90,12 @@ private:
~SavedState();
void setFill (const FillType& newFill);
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
CGShadingRef getShading (CoreGraphicsContext& owner);
-
static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData);
+ #else
+ CGGradientRef getGradient(CGColorSpaceRef colourSpace);
+ #endif
FillType fillType;
Font font;
@@ -98,9 +103,13 @@ private:
CGAffineTransform fontTransform;
private:
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
CGShadingRef shading;
HeapBlock <PixelARGB> gradientLookupTable;
int numGradientLookupEntries;
+ #else
+ CGGradientRef gradient;
+ #endif
};
ScopedPointer <SavedState> state;
diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
index 309a02a..c968295 100644
--- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
+++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
@@ -178,9 +178,11 @@ CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, const float h, const f
CGContextSetBlendMode (context, kCGBlendModeNormal);
rgbColourSpace = CGColorSpaceCreateDeviceRGB();
greyColourSpace = CGColorSpaceCreateDeviceGray();
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
gradientCallbacks.version = 0;
gradientCallbacks.evaluate = SavedState::gradientCallback;
gradientCallbacks.releaseInfo = 0;
+ #endif
setFont (Font());
}
@@ -679,36 +681,62 @@ bool CoreGraphicsContext::drawTextLayout (const AttributedString& text, const Re
CoreGraphicsContext::SavedState::SavedState()
: font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity),
- shading (0), numGradientLookupEntries (0)
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ shading (0),
+ numGradientLookupEntries (0)
+#else
+ gradient(0)
+#endif
{
}
CoreGraphicsContext::SavedState::SavedState (const SavedState& other)
: fillType (other.fillType), font (other.font), fontRef (other.fontRef),
- fontTransform (other.fontTransform), shading (0),
+ fontTransform (other.fontTransform),
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
+ shading (0),
gradientLookupTable ((size_t) other.numGradientLookupEntries),
numGradientLookupEntries (other.numGradientLookupEntries)
+#else
+ gradient(0)
+#endif
{
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
memcpy (gradientLookupTable, other.gradientLookupTable, sizeof (PixelARGB) * (size_t) numGradientLookupEntries);
+ #endif
}
CoreGraphicsContext::SavedState::~SavedState()
{
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
if (shading != 0)
CGShadingRelease (shading);
+#else
+ if (gradient != 0)
+ CGGradientRelease(gradient);
+#endif
}
void CoreGraphicsContext::SavedState::setFill (const FillType& newFill)
{
fillType = newFill;
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
if (fillType.isGradient() && shading != 0)
{
CGShadingRelease (shading);
shading = 0;
}
+#else
+ if (fillType.isGradient() && gradient != 0)
+ {
+ CGGradientRelease (gradient);
+ gradient = 0;
+ }
+#endif
}
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
CGShadingRef CoreGraphicsContext::SavedState::getShading (CoreGraphicsContext& owner)
{
if (shading == 0)
@@ -752,15 +780,76 @@ void CoreGraphicsContext::SavedState::gradientCallback (void* info, const CGFloa
outData[3] = colour.getAlpha() / 255.0f;
}
+#else
+
+CGGradientRef CoreGraphicsContext::SavedState::getGradient(CGColorSpaceRef colourSpace)
+{
+ if(gradient == 0)
+ {
+ ColourGradient& g = *(fillType.gradient);
+
+ //CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
+
+ CGFloat* components = new CGFloat[g.getNumColours() * 4];
+ CGFloat* locations = new CGFloat[g.getNumColours()];
+
+ for(int i=0; i!=g.getNumColours(); ++i)
+ {
+ Colour colour = g.getColour(i);
+ components[i * 4 + 0] = colour.getFloatRed();
+ components[i * 4 + 1] = colour.getFloatGreen();
+ components[i * 4 + 2] = colour.getFloatBlue();
+ components[i * 4 + 3] = colour.getFloatAlpha();
+ locations[i] = g.getColourPosition(i);
+ }
+
+ gradient = CGGradientCreateWithColorComponents(colourSpace, components, locations, g.getNumColours());
+ //CGColorSpaceRelease(colourSpace);
+ delete[] components;
+ delete[] locations;
+ }
+
+ return gradient;
+}
+#endif
+
void CoreGraphicsContext::drawGradient()
{
flip();
applyTransform (state->fillType.transform);
+ CGContextSetAlpha (context, state->fillType.getOpacity());
+ #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if
// you draw a gradient with high quality interp enabled).
- CGContextSetAlpha (context, state->fillType.getOpacity());
CGContextDrawShading (context, state->getShading (*this));
+ #else
+ ColourGradient& g = *(state->fillType.gradient);
+ CGPoint p1 (convertToCGPoint (g.point1));
+ CGPoint p2 (convertToCGPoint (g.point2));
+
+ state->fillType.transform.transformPoints(p1.x, p1.y, p2.x, p2.y);
+
+ CGGradientRef gradient = state->getGradient(rgbColourSpace);
+
+ if (g.isRadial)
+ {
+ CGFloat dx = p2.x-p1.x;
+ CGFloat dy = p2.y-p1.y;
+ CGFloat r = sqrt(dx*dx+dy*dy);
+
+ CGContextDrawRadialGradient(context, gradient,
+ p1, 0, p1, r,
+ kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation
+ );
+ }
+ else
+ {
+ CGContextDrawLinearGradient(context, gradient,
+ p1, p2,
+ kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
+ }
+ #endif
}
void CoreGraphicsContext::createPath (const Path& path) const
@beschulz
Copy link
Author

This patch modifies the CoreGraphicsContext of Juce to use CGGradient instead of CGShading for drawing gradients. The code that uses CGGradient is only enabled, if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 (because CGGradient did not exist back then).

This patch was necessary, because the SavedState object that is passed to CGFunctionCreate was already released when a page based CoreGraphics context starts to draw the gradients (indirectly via CGContextEndPage). Apparently drawing of gradients is deferred on page based Graphics Contexts (like CGPDFContextCreateWithURL).

Further Info:
http://www.juce.com/forum/topic/render-juce-screenshots-pdf-osx#comment-310182
https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGFunction/index.html#//apple_ref/c/func/CGFunctionCreate
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGShading/index.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment