Core Graphics: CGContextClip() Edge Unwanted Weird Antialiasing

625 views Asked by At

I am trying to use CGContextClip() to do some drawing, however I am running into some weird antialiasing problems. The problem appears to be that that the filling is being blended with the colour that it is replacing, instead of the surrounding pixels. See images for a slightly better description of the problem!

Example of issue:

enter image description here

(Note that the blue edge is being antialiased correctly)

Weird antialiased edge:

enter image description here (Edge should be blended with white, not blue)

Code:

-(void) drawRect:(CGRect)rect {

    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextSaveGState(c);
    {

        CGContextBeginPath(c);
        CGContextAddEllipseInRect(c, CGRectMake(25, 25, 200, 200));
        CGContextClosePath(c);
        CGContextClip(c);

        CGContextSetFillColorWithColor(c, [UIColor blueColor].CGColor);
        CGContextFillRect(c, rect);

        CGContextSetFillColorWithColor(c, [UIColor redColor].CGColor);
        CGContextFillRect(c, CGRectMake(0, 0, 250, 125));

    }
    CGContextRestoreGState(c);


}

Any ideas on how to prevent this weird antialiasing? I can't disable it, as the circle edges still need antialiasing!

Just to be clear, this is simply an example. I am trying to solve this issue on a much more complicated shape, where the solution of only filling half of the clipping to begin with simply isn't possible!

1

There are 1 answers

1
Hamish On BEST ANSWER

Well, this doesn't 100% fix the problem, but it does reduce the weird antialiasing by a considerable amount. I got the idea from this question. The idea is that you clear any previous rendering in the area where you are going to draw before drawing, by changing the blend mode to clear, performing the drawing and then switching it back to normal and then re-drawing. The modified code looks like this:

-(void) drawRect:(CGRect)rect {

    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextSaveGState(c);
    {

        CGContextBeginPath(c);
        CGContextAddEllipseInRect(c, CGRectMake(25, 25, 200, 200));
        CGContextClosePath(c);
        CGContextClip(c);

        CGContextSetFillColorWithColor(c, [UIColor blueColor].CGColor);
        CGContextFillRect(c, CGRectMake(25, 25, 200, 200));

        CGContextSetFillColorWithColor(c, [UIColor redColor].CGColor);
        CGRect r = CGRectMake(0, 0, 250, 125);

        CGContextSetBlendMode(c, kCGBlendModeClear);
        CGContextFillRect(c, r);
        CGContextSetBlendMode(c, kCGBlendModeNormal);
        CGContextFillRect(c, r);


    }
    CGContextRestoreGState(c);

} 

If anyone comes up with a better solution that 100% fixes this issue, then post it as an answer and I'll accept it!