0

I calculate a new color and need to render it in a gradient in the drawRect method of a view.

This is taking up a lot of execution time in time profiler and also leads to drawRect calls to be skipped or missed.

What would be the best way to optimise the rendering of a gradient in drawRect?

I have the following code

    CGContextSaveGState(ctx);

    CGContextAddPath(ctx, path.CGPath);
    CGContextClip(ctx);

    // get the color components
    const CGFloat* components = CGColorGetComponents(fillColor.CGColor);

    // create the gradient
    CGGradientRef gradient;
    CGColorSpaceRef colorspace;
    size_t num_locations = 3;

    CGFloat componentsArray[12] =
    {
        components[0], components[1], components[2], 1.0, // Start color
        components[0], components[1], components[2], 1.0, // Middle color
        components[0], components[1], components[2], 0.0  // End color
    };

    colorspace = CGColorSpaceCreateDeviceRGB();
    gradient = CGGradientCreateWithColorComponents(colorspace, componentsArray, locations, num_locations);
    CGContextDrawLinearGradient (ctx, gradient, gradientStartPoint, gradientEndPoint, 0);
    CGGradientRelease(gradient);

    CGContextRestoreGState(ctx);
some_id
  • 29,466
  • 62
  • 182
  • 304
  • Why are you calling this often? Are you animating the gradient or is it changing to reflect some other data? – David Rönnqvist May 24 '13 at 08:58
  • It is real time rendering with data. I am using UIBezierPaths and I need to store these in an array and rerender all paths in the array and a new one in each drawRect call. It runs smoothly without the gradient. – some_id May 24 '13 at 09:06
  • Is the gradient the only thing that changes? If so maybe you could use `CAGradientLayer` and some Layer blending to achieve your desired result. – Jonathan Cichon May 24 '13 at 09:33
  • As JonathanCichon said, you could try using a CAGradientLayer which will be very good if you are animating the gradient change. I expect the gain to be much less if you are manually changing the colour at every frame – David Rönnqvist May 24 '13 at 09:37
  • The BezierPaths change. And the gradient inside them. Layer blending sounds interesting. I will take a look at that. How differently would the code be if I was using a CAGradient Layer? Also, how would I put them inside a BezierPath? – some_id May 24 '13 at 09:37
  • @DavidRönnqvist - How would the animation take place? I render a number of bezierpaths, each with their own gradient fill. – some_id May 24 '13 at 09:43
  • @Helium3 you would have CAGradientLayer (masked by CAShapeLayer) and animate the `colors` property of the gradient layer. – David Rönnqvist May 24 '13 at 09:45
  • @Helium3 [my answer here](http://stackoverflow.com/questions/15866179/draw-segments-from-a-circle-or-donut/15868472#15868472) could be used to know how to setup CAGradientLayer + CAShapeLayer mask combination. Scroll down to *For reference: the same drawing using Core Animation* – David Rönnqvist May 24 '13 at 09:48
  • @DavidRönnqvist - Great answer on that link. I converted to using CAGradientLayer, but when I call this gradient.frame = CGPathGetBoundingBox(path.CGPath); where path is a bezierPath, the rendering is incorrect and the frames seems completely incorrect. I save each Bezier Path after closing its path with [path closePath]; – some_id May 24 '13 at 10:03
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30551/discussion-between-david-ronnqvist-and-helium3) – David Rönnqvist May 24 '13 at 10:11

0 Answers0