Question

The code below draws the following. One can notice the left side line has thin line as compare to that on right. Other observation the Quad curve is not so sharp. How can I make it look better?

- (void)drawRect:(CGRect)rect
{    
    CGContextRef contextRef=UIGraphicsGetCurrentContext();
    [self drawBatteryEdges:contextRef withFinalBorderRect:rect];
}

-(void) drawBatteryEdges:(CGContextRef) contectRef withFinalBorderRect:(CGRect) batteryRect{
    CGFloat topOffset=20.0f;
    CGFloat bottomOffset=20.0f;
    CGFloat curveOffset=4f;

    CGMutablePathRef path=CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, 0, topOffset);
    CGPathAddQuadCurveToPoint(path, NULL, batteryRect.size.width/2.0, topOffset-(curveOffset), batteryRect.size.width, topOffset);
    CGPathAddLineToPoint(path, NULL, batteryRect.size.width, batteryRect.size.height-bottomOffset);
    CGPathAddQuadCurveToPoint(path, NULL,
                              batteryRect.size.width/2.0, (CGPathGetCurrentPoint(path).y)+(curveOffset),
                              0, (CGPathGetCurrentPoint(path).y));

    CGPathCloseSubpath(path);

    CGContextAddPath(contectRef, path);
    CGContextDrawPath(contectRef, kCGPathStroke);

}

It draws the following.

enter image description here

Was it helpful?

Solution

Wenderlich, Ray. "Core Graphics Tutorial: Lines, Rectangles, and Gradients." 15 Apr. 2013. http://www.raywenderlich.com/32283/core-graphics-tutorial-lines-rectangles-and-gradients

Well, it turns out that when Core Graphics strokes a path, it draws the stroke on the middle of the exact edge of the path.

In your case, the edge of the path is the rectangle you wish to fill. So when drawing a 1 pixel line along that edge, half of the line (1/2 pixel) will be on the inside of the rectangle, and the other half of the line (1/2 pixel) will be on the outside of the rectangle.

But of course, since there’s no way to draw 1/2 a pixel, instead Core Graphics uses anti-aliasing to draw in both pixels, but just a lighter shade to give the appearance that it is only a single pixel drawn.

But you don’t want no anti-aliasing, you want just one pixel, darnit! There are several ways to fix this:

  • You can use clipping to cut out the undesirable pixels
  • You can disable antialiasing and also modify the rectangle boundaries to make sure the stroke is where you want
  • You can modify the path to stroke so it takes the 1/2 pixel effect into consideration

I would suggest drawing your stroke on a half pixel, which would involve doing something like this:

CGRectMake(rect.origin.x + 0.5, rect.origin.y + 0.5, rect.size.width - 1, rect.size.height - 1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top