1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-19 01:04:20 +00:00

Updated gradient rendering on OSX to use newer APIs.

This commit is contained in:
jules 2015-02-22 20:16:26 +00:00
parent cd2f7d6ffb
commit 8eb2fef209
2 changed files with 49 additions and 71 deletions

View file

@ -77,7 +77,6 @@ private:
const CGFloat flipHeight;
float targetScale;
CGColorSpaceRef rgbColourSpace, greyColourSpace;
CGFunctionCallbacks gradientCallbacks;
mutable Rectangle<int> 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 <PixelARGB> gradientLookupTable;
int numGradientLookupEntries;
CGGradientRef gradient;
};
ScopedPointer <SavedState> state;
OwnedArray <SavedState> stateStack;
ScopedPointer<SavedState> state;
OwnedArray<SavedState> stateStack;
void drawGradient();
void createPath (const Path&) const;

View file

@ -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<in
else
{
const size_t numRects = (size_t) clipRegion.getNumRectangles();
HeapBlock <CGRect> rects (numRects);
HeapBlock<CGRect> rects (numRects);
int i = 0;
for (const Rectangle<int>* 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 <OSXTypeface*> (state->font.getTypeface()))
if (OSXTypeface* osxTypeface = dynamic_cast<OSXTypeface*> (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 <const SavedState*> (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 <CoreGraphicsImage*> (image.getPixelData()))
if (CoreGraphicsImage* const cgi = dynamic_cast<CoreGraphicsImage*> (image.getPixelData()))
return cgi->context;
jassertfalse;