0

I have created a simple drawing project,the code works fine, but I want to cache the drawing into CGlayer, because I read that its more efficient way in drawing . I have read through the documents, but not able to understand it properly. So friends, I request you to please help me in this regard.

Below is my code, I want to know how to use CgLayer in this

- (void)drawRect:(CGRect)rect
{

   CGContextRef context = UIGraphicsGetCurrentContext();

   if(myLayerRef == nil)
   {

       myLayerRef = CGLayerCreateWithContext(context, self.bounds.size, NULL);
   }

    CGContextRef layerContext = CGLayerGetContext(myLayerRef);

    CGContextDrawLayerAtPoint(context, CGPointZero, myLayerRef);   
}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *mytouch=[[touches allObjects] objectAtIndex:0];

    m_previousPoint2 = m_previousPoint1;
    m_previousPoint1 = [mytouch previousLocationInView:self];
    m_currentPoint = [mytouch locationInView:self];

    CGPoint mid1    = midPoint(m_previousPoint1, m_previousPoint2); 
    CGPoint mid2    = midPoint(m_currentPoint, m_previousPoint1);  

    testpath = CGPathCreateMutable();
    CGPathMoveToPoint(testpath, NULL, mid1.x, mid1.y);

    CGPathAddQuadCurveToPoint(testpath, NULL, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);       


    CGContextRef context = UIGraphicsGetCurrentContext();

    context = CGLayerGetContext(myLayerRef);

    CGRect bounds = CGPathGetBoundingBox(testpath);   

     CGPathRelease(testpath);


    CGRect drawBox = bounds;

    //Pad our values so the bounding box respects our line width
    drawBox.origin.x        -= self.lineWidth * 2;
    drawBox.origin.y        -= self.lineWidth * 2;
    drawBox.size.width      += self.lineWidth * 4;
    drawBox.size.height     += self.lineWidth * 4;


   [self setNeedsDisplayInRect:drawBox];       
}


- (void) drawingOperations
{

    CGContextRef context1 = CGLayerGetContext(myLayerRef);



    CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2); 
    CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);



    CGContextMoveToPoint(context1, mid1.x, mid1.y);
    CGContextAddQuadCurveToPoint(context1, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y); 
    CGContextSetLineCap(context1, kCGLineCapRound);
    CGContextSetLineWidth(context1, self.lineWidth);
    CGContextSetStrokeColorWithColor(context1, self.lineColor.CGColor);

    CGContextSetFlatness(context1, 2.0);

    CGContextSetAllowsAntialiasing(context1, true);


    CGContextStrokePath(context1);
}

Regards Ranjit

Ranjit
  • 4,576
  • 11
  • 62
  • 121
  • Hello, can anyone help me out – Ranjit Jul 05 '12 at 13:57
  • Hello friends, I think I have solved the issue, of using CgLayer to cache the lines, but not sure is the right method, it works fine.I have updated my post with latest code, I want someone to please verify my code and let me know whether I am right. So that I can mark the question as solved. thanks – Ranjit Jul 05 '12 at 14:32
  • 1
    Add your layer-using code as an answer, not an update to the question, otherwise the question doesn't make sense. – jrturton Jul 05 '12 at 14:35
  • This looks pretty good. You could be better by only doing the drawing operations outside of drawRect, but if it is smooth enough then it doesn't really matter. Also things like setting line cap width, etc. only need to be done once (since no one else is using the context of the layer it will not be changed). – borrrden Jul 06 '12 at 01:17
  • Hey thanks borrrden , as u said, the drawing operations should be done outside drawRect, u mean to say that all that code starting from, CGcontextmovetoPint() to CGcontextDrawLayeratPoint() should be outside right?, shall I make a different function for it and call it from touchesmoved? – Ranjit Jul 06 '12 at 06:37
  • @borrrden, you are right, lines are not smooth. :( – Ranjit Jul 06 '12 at 06:57
  • Yes, you want to do as little as possible inside drawRect: so that the system can draw as fast as possible. The layer doesn't care if it is drawn to inside drawRect: or not, only the graphics context of your view does. So draw everything to your layer outside of drawRect:, then all you need to do is the last line that you have there (aside from the initial creation of course). – borrrden Jul 06 '12 at 07:42
  • When you say "not smooth" do you mean the drawing, or the lines themselves? You set the flatness extremely low, so they are not going to be smooth curves no matter how efficiently you render them. – borrrden Jul 06 '12 at 07:44
  • Hi @borrrden , lines are not smooth I mean when I see them, they are little pixelated, what I feel, I have updated the above code, according to tour suggestions, please check it – Ranjit Jul 06 '12 at 08:23
  • @borrrden, can you please look at this link, I am not getting it http://stackoverflow.com/questions/11394839/undo-redo-issues-with-cglayer – Ranjit Jul 10 '12 at 11:06
  • I haven't gotten undo working well either (well I did on an iPad 2 but not iPad 3) so I won't be much help at the moment. – borrrden Jul 10 '12 at 11:25
  • Hey I want to chat with you, can you please come for chat, I will not take your much time, I have few doubts, it would be better for me. – Ranjit Jul 10 '12 at 11:27
  • Please tell me where I am goin wrong? – Ranjit Jul 10 '12 at 11:31
  • @borrden, whether we should store CgLayers into array or Dictionary? – Ranjit Jul 10 '12 at 11:44

2 Answers2

3

The link posted by @hfossli is now dead, but here is the archived content:

CGLayer no longer recommended

Posted by robnapier on Jul 13, 2012 in Book Updates

I spend a lot of time in the labs at WWDC asking questions and talking with the developers. I sat down the Core Graphics engineers this time and asked them about one of my favorite underused tools: CGLayer, which I discuss at the end of Chapter 6. CGLayer sounds like a great idea: a drawing context optimized specifically for drawing on the screen, with hardware optimization. What could go wrong?

I started to have doubts, though, that CGLayer was always a great win. What if your layers were too large to store in GPU textures? CGLayer is advertised for use as a “stamp” that you repeatedly draw. Moving data to and from the GPU is expensive. Maybe CGLayer doesn’t make sense unless you draw it a certain number of times. The docs give no guidance on this.

So I asked the Core Graphics team “When should I be using CGLayer?”

“Never.”

… ??? Never? But for stamping right?

Never.

So we talked some more. It appears that CGLayer was one of those things that sounded great on paper, but just doesn’t always work in practice. Sometimes it’s faster. Sometimes its slower. There’s no easy rule for when it’s going to be faster. Over time it seems they’ve quietly abandoned it without actually deprecating it. I’ve asked that the docs be updated to match Apple’s current recommendation. The CGLayer Reference hasn’t been updated since 2006.

The recommendation I received was to use CGBitmapContext or CALayer for stamping. For the specific example given on pages 131-132, CATextLayer would probably be the best tool. Remember that you can easily clone a CALayer using initWithLayer:. (John Mueller points out below that this isn’t actually supported.)

Gene Z. Ragan
  • 2,643
  • 2
  • 31
  • 41
  • I think there big problem is that they don't have what Direct2D from microsoft has implemented: device dependent resources that can be thrown away when memory gets reused by others. – Lothar Dec 24 '18 at 18:42
0

Not optimal to use CGLayer anymore

http://iosptl.com/posts/cglayer-no-longer-recommended/

hfossli
  • 22,616
  • 10
  • 116
  • 130