12

Anyone have any idea why CGContextFillPath won't work in the code snippet below? I'm using the following code to draw to a UIImageView. It's stroking the path correctly, but ignoring CGContextFillPath.

UIGraphicsBeginImageContext(self.frame.size);
[drawingView.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), YES);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextSetRGBFillColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), firstMovedTouch.x, firstMovedTouch.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFillPath(UIGraphicsGetCurrentContext());
drawingView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
RyJ
  • 3,995
  • 6
  • 34
  • 54

4 Answers4

28

To solve this problem, use the following code:

CGContextRef context = UIGraphicsGetCurrentContext(); 

CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineWidth(context, 8.0);

CGMutablePathRef pathRef = CGPathCreateMutable();

/* do something with pathRef. For example:*/
CGPathMoveToPoint(pathRef, NULL, x, y);
CGPathAddLineToPoint(pathRef, NULL, x, y+100);
CGPathAddLineToPoint(pathRef, NULL, x+100, y+100);
CGPathAddLineToPoint(pathRef, NULL, x+100, y);
CGPathCloseSubpath(pathRef);

CGContextAddPath(context, pathRef);
CGContextFillPath(context);

CGContextAddPath(context, pathRef);
CGContextStrokePath(context);

CGPathRelease(pathRef);
Alex Kantaev
  • 434
  • 4
  • 10
19

I believe that the best way to stroke and fill your path is to add the following line of code after you've finished setting up your path:

    CGContextDrawPath(myContext, kCGPathFillStroke);
Mazyod
  • 22,319
  • 10
  • 92
  • 157
  • It's simply a matter of watching Stanford CS193P course back in the day... I think it was the second, or third lecture they introduced this. – Mazyod May 12 '13 at 10:29
10

I had the same trouble. I found that you can not use

CGContextStrokePath( UIGraphicsGetCurrentContext() ) 
CGContextFillPath( UIGraphicsGetCurrentContext() ) 

consecutively: the latter will not work because after committing the stroke on the path, the path is removed from the context.

So, I used the same path twice; one for stroke,the other for fill.

// ... create a path of CGMutablePathRef ....

CGContextSaveGState( context );
//....fill the path .....
CGContextRestoreGState( context );

CGContextSaveGState ( context );
//....stroke the path .....
CGContextRestoreGState( context );

CFRelease( path );
Mazyod
  • 22,319
  • 10
  • 92
  • 157
lupengshou
  • 101
  • 1
  • 3
  • Thanks. That saved me after ages of problem shooting – Designer023 Sep 15 '11 at 09:13
  • It is in the docs: When you want to append the path to a graphics context, you call the function CGContextAddPath. The path stays in the graphics context until Quartz paints it. You can add the path again by calling CGContextAddPath. – Joris Mans Jul 10 '13 at 10:52
5

I think you need to call CGContextClosePath before you can fill the path. I am not sure what you are trying to draw, but CGContextFillPath will fill the area inside the path and I only see single line here.

tia
  • 9,518
  • 1
  • 30
  • 44
  • Oh... you're right. I'm using the code for ghetto finger line drawing. But that makes sense. This code is fired on touchesMoved: and works great for line drawings, but I'll have to save all of the points to an array, or something, in order to fill the path once the user lifts their finger. – RyJ Sep 28 '10 at 01:28