1

I'm actually trying to draw lines on a view. In order to not clear the context before every draws, I understood that I have to create my own context in order to draw on it.

I found this way to create a context :

CGContextRef MyCreateBitmapContext (int pixelsWide,
                                int pixelsHigh)
{
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    bitmapBytesPerRow   = (pixelsWide * 4);
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

    colorSpace = CGColorSpaceCreateDeviceRGB();
    bitmapData = calloc( bitmapByteCount, sizeof(int) );
    if (bitmapData == NULL)
    {
        fprintf (stderr, "Memory not allocated!");
        return NULL;
    }
    context = CGBitmapContextCreate (bitmapData,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,      // bits per component
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedLast);
    if (context== NULL)
    {
        free (bitmapData);
        fprintf (stderr, "Context not created!");
        return NULL;
    }
    CGColorSpaceRelease( colorSpace );

    return context;
}

But my question is : how can I use this context in order to not have my view cleaned every time ?

EDIT (after the answer of @Peter Hosey) :

I try to do something like :

- (void)drawRect:(CGRect)rect {
    // Creation of the custom context
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGImageRef cgImage = CGBitmapContextCreateImage(context);
    CGContextDrawImage(context, CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), cgImage);
    CGImageRelease(cgImage);
    if (isAuthorizeDrawing) {
         [self drawInContext:context andRect:rect]; // Method which draw all the lines sent by the server
         isAuthorizeDrawing = NO;
    }

    // Draw the line
    [currentDrawing stroke];
}

I also set clearsContextBeforeDrawing to NO for the UIView.

When I zoom (isAuthorizeDrawing is set to YES in order to redraw all the lines correctly scaled), the lines don't disappear but when I try to draw new lines (isAuthorizeDrawing is set to NO in order to not redraw everything at each setNeedsDisplay call), all the lines disappeared and the drawing is going really slow.. :/

Am I doing something wrong ?

EDIT 2

Here are my drawing methods :

-(void)drawInContext:(CGContextRef)context {
    for (int i = 0; i < self.drawings.count; ++i) {
        Drawing* drawing = [self.drawings objectAtIndex:i];

        CGContextSetStrokeColorWithColor(context, drawing.colorTrait.CGColor);
        CGContextSetLineWidth(context, 1.0);

        CGContextMoveToPoint(context, [[drawing.points objectAtIndex:0] CGPointValue].x * self.zoomScale, [[drawing.points objectAtIndex:] CGPointValue].y * self.zoomScale);

        for (int i = 1; i < drawing.points.count; i++) {
            CGContextAddLineToPoint(context, [[drawing.points objectAtIndex:i] CGPointValue].x * self.zoomScale, [[drawing.points objectAtIndex:i] CGPointValue].y * self.zoomScale);
        }

        CGContextStrokePath(context);
    }
}

-(void)drawRect:(CGRect)rect {
    if (isRedrawing) {
        [self drawInContext:UIGraphicsGetCurrentContext()];
        isRedrawing = NO;
    }

    [[UIColor redColor] set];
    [currentPath stroke];
}
Seb
  • 545
  • 9
  • 29

1 Answers1

4

Your context holds onto all of your drawing for you.

When you're drawing into a context supplied by a view (i.e., within drawRect:), either the view is creating a new context each time or it has erased the context's contents, like shaking an Etch-a-Sketch. Either way, you're getting a context into which (effectively, at least) nothing has been drawn.

When you're drawing into your context, assuming you're not doing anything to erase it between uses, everything you draw into it just piles up.

One ramification of this is that you need to be careful of drawing state like the current transformation matrix, clipping path, etc., because nothing is resetting those parameters between drawing sessions. That may be useful, depending on what you're doing, but either way, you need to be aware of it and plan accordingly.

Presumably you want to show the user what you've drawn so far from time to time (namely, when drawRect: happens). To do that, ask the bitmap context to create an image of its contents and draw that image into the current (UIKit-supplied) context.

Alternatively, just tell the view not to clear itself before every draw, and don't bother managing your own bitmap context at all.

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • I edited my question with a first piece of code but something's wrong, can you help me ? – Seb Dec 26 '12 at 20:23
  • @Seb: You're capturing the contents of the context to an image, then drawing that image back to the same context. At most, this will give everything a double-struck appearance, which I don't think is what you want; assuming you only want to add new stuff to what you've already drawn, you don't need to create an image from the context. That past drawing is already there (which is how CreateImage could capture it in the first place). – Peter Hosey Dec 26 '12 at 22:31
  • I'm not sure to understand entirely. It's not necessary to draw the image of the current context in the context itself, ok. So, what I have to do ? I'm hoping to find a solution where I will not have to redraw everything (so not call [self drawInContext:context andRect:rect] at each setNeedsDisplay call) when I'm drawing new lines. – Seb Dec 26 '12 at 22:53
  • @Seb: Having set `clearsContextBeforeDrawing` to `NO` should be enough for you to keep prior drawing and need only to draw new stuff on top of it. – Peter Hosey Dec 26 '12 at 23:05
  • Hoser: I already set `clearsContextBefoereDrawing` to `NO` and when I draw new lines, the lines which come from the server disappeared... :/ – Seb Dec 26 '12 at 23:13
  • I added my drawing methods in my question. – Seb Dec 26 '12 at 23:14