Filling the inverse of the CGPath without clipping - iphone

Say I have a CGPath which is a circle in the CGContextRef. What I would like to do is to fill the inverse of the path with color. Demonstrated below where the circle is the current path drawn and I would like to fill the inverse of the circle with color, leaving a hollow hole:

First add the rectangle to the path and then add the circle (or whatever your path is) to the same path. Then do an even-odd fill which will won't fill the circle because that is covered by both the circle and the rectangle.
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, bigRect); // add the big rect
CGPathAddPath(path, NULL, circlePath); // add your shape (the circle)
CGContextDrawPath(path, kCGPathEOFill); // even-odd fill

Since you have overlapping circles you'll need to create a single path which represents the union of those circles, then add that path to your rectangle and fill as David suggested.
To create the union of the circle paths, this project will prove invaluable:
https://bitbucket.org/martinwinter/vectorbooleancg
Make sure that you check out the 'CGPath' branch to get iOS support.

Related

How to fill space between two UIBezierPaths

I'm working on drawing application which provides drawing lines with variable line width which depends on drawing speed. This behavior inspired by Paper app.
Algorithm which I'm trying to implement -- draw two bezier path with variable distance between them. The solution which described in sosborn's answer. Then smooth paths and fill the distance between them.
Actually I don't figured out how to fill space between paths.
You create a single path from the 2 bezier curves and fill it, like this:
NSBezierPath* path = [NSBezierPath bezierPath];
// Move to the start point
[path moveToPoint:startPt];
// Make the lower part of the curve
[path curveToPoint:endPt controlPoint1:cp1 controlPoint2:cp2];
// Make the upper part of the curve as part of the same path:
[path curveToPoint:startPt contorPoint1:cp3 controlPoint2:cp4];
// Now fill it
[path fill];

How to clip or subtract a CGMutablePathRf by another CGMutalbePathRef?

I have a rectangular CGMutablePathRef and I want to subtract a circle which lays exactly on centered on one edge of that rectangle, so the edge does not cross the circle anymore.
There seem to be no functions to intersect or subtract paths from another. How can I do it?
You need to look at the CGContext you are drawing into and use the clipping on the context rather than the path.
Apple's documentation is here.
If I understand your question, you can draw your rectangle into the context and then "clip out" the circle path. If you are filling the paths, you'll need to pay attention to the winding rules.
Alternatively, you can make your path with a series of commands such as CGPathAddLineToPoint, CGPathAddArcToPoint, etc and then stoke the path in your context. If you use this approach, you can then apply transforms to the final path for scaling and rotating as needed. Depending on what you are trying to accomplish, this may be the better approach.

CGPath masked off CGPoints

I'm trying to build this:
Where the white background is in fact transparent. I know how to clip a CGPath to a set region, but this seems to be to other way around, since I need to substract regions from a filled CGPath.
I guess the right way to go would be to substract the whole outer-circles from the CGPath and then to draw smaller circles at my CGPoints, but I'm not sure how to execute the former. Can anyone point me in the right direction?
That's what I would do :
1) Draw your general line
2) CGContextSetBlendMode(context, kCGBlendModeClear) to "clear the context" when you draw.
3) Draw you bigger circles
4) CGContextSetBlendMode(context, kCGBlendModeNormal) to return to normal drawing
5) Draw your little circles.
You could instead start a transparency layer, draw the lines, then draw the larger transparent circles using the clear color, then draw the smaller black circles. Then when you finish the transparency layer, it will composite exactly what you want back onto the context.

CoreGraphics rounded corner thickness

Whenever I stroke a path with rounded corners on iPhone, the rounded corners are thicker than the rest of the stroked path. See here for what I mean:
rounded corner thickness http://img181.imageshack.us/img181/6372/screenshot20100320at123.png
Not sure why this happens, any ideas?
I agree with Peter Hosey's analysis that the outer half of your lines is getting clipped off, but my recommendation would be to move all the coordinates .5 pixels inward instead. This way your straight lines will be crisper (not antialiased across 2 screen pixels) as well.
I suspect that you're drawing within a rectangular clipping path; the corners fall completely within the rectangle, but the sides get cut in half: half inside the clipping path and so drawn, half outside and so clipped out.
Try adding the path to the clipping path before stroking it.
To do this, you will need to add the CGPath to the context's current path twice:
Add CGPath to current path.
Add current path to clipping path (thereby emptying current path).
Add CGPath to current path.
Stroke current path.
It just looks thicker. If you zoom in on it you will see what looks like a couple extra pixels of black is actually some pixels of gray caused by antialiasing.
Try turning off antialiasing to see if the result looks better.
Edit: Also the bottom right corner seems to have a drop shadow effect.

Moving CGPaths by x,y pixels?

Is there a way to move a path on screen by (x,y) pixels using directly a CGPathRef instead of walking through its points and lines again in drawRect method? I want to be reusing my old CGPathRef when I want to move it on screen instead of recreating it with new pixels.
Depending on your needs, you could just translate the drawing context via CGContextTranslateCTM before drawing your path (then restore the old context, either with push/popping contexts, or inverting the translation). You might also like CGPathApply, which will call a function for every path element in the path (so you can translate the points by hand).