Core Graphics not drawing line with correct width

I am trying to match a border from a UIView with a line drawn in drawRect. I am using the same width. But the problem is that sometimes the resulting line width is drawn the same for both, and sometimes not - it even changes with the orientation of the device! But even without changing the orientation of the device, it does not differ from the width at all.

The border is drawn with:

view.layer.borderColor = [UIColor blackColor].CGColor;
view.layer.borderWidth = 1.0f;

      

Above this view is another view, which is a subclass of UIView. Both views are the same width and this second view spans the top section above. The coverage view uses the following code in drawRect to draw a line on the left, which should be perfectly aligned with the border of the above view below:

CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat x = self.bounds.origin.x;
CGFloat y = self.bounds.origin.y;
CGFloat width = self.bounds.size.width;
CGFloat height = self.bounds.size.height;

CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);
CGContextSetLineWidth(context, 1.0f);

// Left line
CGContextMoveToPoint(context, x, y);
CGContextAddLineToPoint(context, x, height);
CGContextStrokePath(context);

// Right line
CGContextMoveToPoint(context, width - 1.0f, y);
CGContextAddLineToPoint(context, width - 1.0f, height);
CGContextStrokePath(context);

      

Any ideas how this can be achieved? Right now, even though the width is always 1.0f, it's just a coincidence if both lines are drawn with the same apparent width.

The goal is to end up with something similar to the view with rounded corners at the bottom, but with normal edges at the top. This is why I am doing this. The first view has rounded corners, while the second view above it is the same width but covers the top, so the rounded cornes from above are not visible.

Screenshot in portrait: enter image description here

Screenshot in landscape: enter image description here

The yellow is above the white. The black lines of the white view are drawn as a result of view.layer.borderWidth = 1.0f. The black lines to the left and right of the yellow view are drawn in drawRect using the above code. Orientation changes initiate redrawing, but the drawing code itself remains unchanged. Both screenshots are from an iPhone with a retina display (iPhone 4S).

As far as I can tell, all values ​​are "integers":

x: 0.000000, y: 0.000000
width: 264.000000, height: 10.000000
frame.origin.x: 33.000000, frame.origin.y: 38.000000

      

+2


source to share


1 answer


I am assuming that the line you are drawing is not pixel-aligned. If I'm wrong then ignore my tangent. But nevertheless, this is useful information.

I'm going to take some screenshots from this WWDC 2011 video:

1-29 Session 129 - Hands-On Drawing for iOS Developers

I suggest you watch it all. The corresponding section starts at 20:50.

Basically, imagine you want to draw a 1pt line from (1,2) to (4,2)

enter image description here

Core graphics will try to center it on the y value, which is 2.0. This means that it will try to draw a line with its top edge at y = 1.5 and the bottom edge at y = 2.5:

enter image description here



On a retina screen, this will work fine because y = 1.5 and y = 2.5 are pixel-aligned:

enter image description here

However, on a non-retina screen, the graphics system will be forced to fill 2 vertical pixels at half intensity to get the closest match:

enter image description here

Note that this effect will still show up on mesh displays when you are dealing with lower decimal point values. Thus, these problems can still be seen on retinal displays depending on your angle.

To fix this problem, anytime you have an odd line width, you need to offset the value of the point where you draw it by 0.5. You have to compensate for it up / down / left / right depending on the situation.

enter image description here

Hope this helps. Without a screenshot, it's hard to tell what the problem is.

+8


source







All Articles