diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h index bf26ce8ee2..9beefef00f 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h @@ -77,7 +77,6 @@ private: const CGFloat flipHeight; float targetScale; CGColorSpaceRef rgbColourSpace, greyColourSpace; - CGFunctionCallbacks gradientCallbacks; mutable Rectangle lastClipRect; mutable bool lastClipRectIsValid; @@ -87,24 +86,17 @@ private: SavedState (const SavedState&); ~SavedState(); - void setFill (const FillType& newFill); - CGShadingRef getShading (CoreGraphicsContext& owner); - - static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData); + void setFill (const FillType&); FillType fillType; Font font; CGFontRef fontRef; CGAffineTransform fontTransform; - - private: - CGShadingRef shading; - HeapBlock gradientLookupTable; - int numGradientLookupEntries; + CGGradientRef gradient; }; - ScopedPointer state; - OwnedArray stateStack; + ScopedPointer state; + OwnedArray stateStack; void drawGradient(); void createPath (const Path&) const; diff --git a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm index 309a02a427..31e7ee12cc 100644 --- a/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm +++ b/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm @@ -178,9 +178,6 @@ CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, const float h, const f CGContextSetBlendMode (context, kCGBlendModeNormal); rgbColourSpace = CGColorSpaceCreateDeviceRGB(); greyColourSpace = CGColorSpaceCreateDeviceGray(); - gradientCallbacks.version = 0; - gradientCallbacks.evaluate = SavedState::gradientCallback; - gradientCallbacks.releaseInfo = 0; setFont (Font()); } @@ -251,7 +248,7 @@ bool CoreGraphicsContext::clipToRectangleListWithoutTest (const RectangleList rects (numRects); + HeapBlock rects (numRects); int i = 0; for (const Rectangle* r = clipRegion.begin(), * const e = clipRegion.end(); r != e; ++r) @@ -519,7 +516,7 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans while (x > clip.origin.x) x -= iw; while (y > clip.origin.y) y -= ih; - const int right = (int) (clip.origin.x + clip.size.width); + const int right = (int) (clip.origin.x + clip.size.width); const int bottom = (int) (clip.origin.y + clip.size.height); while (y < bottom) @@ -600,7 +597,7 @@ void CoreGraphicsContext::setFont (const Font& newFont) state->fontRef = 0; state->font = newFont; - if (OSXTypeface* osxTypeface = dynamic_cast (state->font.getTypeface())) + if (OSXTypeface* osxTypeface = dynamic_cast (state->font.getTypeface())) { state->fontRef = osxTypeface->fontRef; CGContextSetFont (context, state->fontRef); @@ -678,89 +675,78 @@ bool CoreGraphicsContext::drawTextLayout (const AttributedString& text, const Re } CoreGraphicsContext::SavedState::SavedState() - : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity), - shading (0), numGradientLookupEntries (0) + : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity), gradient (0) { } CoreGraphicsContext::SavedState::SavedState (const SavedState& other) : fillType (other.fillType), font (other.font), fontRef (other.fontRef), - fontTransform (other.fontTransform), shading (0), - gradientLookupTable ((size_t) other.numGradientLookupEntries), - numGradientLookupEntries (other.numGradientLookupEntries) + fontTransform (other.fontTransform), gradient (other.gradient) { - memcpy (gradientLookupTable, other.gradientLookupTable, sizeof (PixelARGB) * (size_t) numGradientLookupEntries); + if (gradient != 0) + CGGradientRetain (gradient); } CoreGraphicsContext::SavedState::~SavedState() { - if (shading != 0) - CGShadingRelease (shading); + if (gradient != 0) + CGGradientRelease (gradient); } void CoreGraphicsContext::SavedState::setFill (const FillType& newFill) { fillType = newFill; - if (fillType.isGradient() && shading != 0) + if (gradient != 0) { - CGShadingRelease (shading); - shading = 0; + CGGradientRelease (gradient); + gradient = 0; } } -CGShadingRef CoreGraphicsContext::SavedState::getShading (CoreGraphicsContext& owner) +static CGGradientRef createGradient (const ColourGradient& g, CGColorSpaceRef colourSpace) { - if (shading == 0) + const int numColours = g.getNumColours(); + CGFloat* const data = (CGFloat*) alloca (numColours * 5 * sizeof (CGFloat)); + CGFloat* const locations = data; + CGFloat* const components = data + numColours; + CGFloat* comps = components; + + for (int i = 0; i < numColours; ++i) { - ColourGradient& g = *(fillType.gradient); - numGradientLookupEntries = g.createLookupTable (fillType.transform, gradientLookupTable) - 1; - - CGFunctionRef function = CGFunctionCreate (this, 1, 0, 4, 0, &(owner.gradientCallbacks)); - CGPoint p1 (convertToCGPoint (g.point1)); - - if (g.isRadial) - { - shading = CGShadingCreateRadial (owner.rgbColourSpace, p1, 0, - p1, g.point1.getDistanceFrom (g.point2), - function, true, true); - } - else - { - shading = CGShadingCreateAxial (owner.rgbColourSpace, p1, - convertToCGPoint (g.point2), - function, true, true); - } - - CGFunctionRelease (function); + const Colour colour (g.getColour (i)); + *comps++ = colour.getFloatRed(); + *comps++ = colour.getFloatGreen(); + *comps++ = colour.getFloatBlue(); + *comps++ = colour.getFloatAlpha(); + locations[i] = g.getColourPosition (i); } - return shading; -} - -void CoreGraphicsContext::SavedState::gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) -{ - const SavedState* const s = static_cast (info); - - const int index = roundToInt (s->numGradientLookupEntries * inData[0]); - PixelARGB colour (s->gradientLookupTable [jlimit (0, s->numGradientLookupEntries, index)]); - colour.unpremultiply(); - - outData[0] = colour.getRed() / 255.0f; - outData[1] = colour.getGreen() / 255.0f; - outData[2] = colour.getBlue() / 255.0f; - outData[3] = colour.getAlpha() / 255.0f; + return CGGradientCreateWithColorComponents (colourSpace, components, locations, numColours); } void CoreGraphicsContext::drawGradient() { flip(); applyTransform (state->fillType.transform); - - 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)); + + const 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); + + if (state->gradient == 0) + state->gradient = createGradient (g, rgbColourSpace); + + if (g.isRadial) + CGContextDrawRadialGradient (context, state->gradient, p1, 0, p1, g.point1.getDistanceFrom (g.point2), + kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + else + CGContextDrawLinearGradient (context, state->gradient, p1, p2, + kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); } void CoreGraphicsContext::createPath (const Path& path) const @@ -917,7 +903,7 @@ CGImageRef juce_createCoreGraphicsImage (const Image& juceImage, CGColorSpaceRef CGContextRef juce_getImageContext (const Image& image) { - if (CoreGraphicsImage* const cgi = dynamic_cast (image.getPixelData())) + if (CoreGraphicsImage* const cgi = dynamic_cast (image.getPixelData())) return cgi->context; jassertfalse;