views:

518

answers:

3

I made a "Circle" view with this drawRect

- (void)drawRect:(CGRect)rect 
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(ctx, color.CGColor);
    CGContextAddEllipseInRect(ctx, rect);
    CGContextFillPath(ctx);
}

When I try to scale the view up using CGAffineTransformMakeScale(2.0, 2.0), the result is blurry and pixelated on the edges. However, the programming guide says that Quartz uses vector-based commands to draw views, and that they would continue to look good when using affine transforms:

The Quartz drawing system uses a vector-based drawing model. Compared to a raster-based drawing model, in which drawing commands operate on individual pixels, drawing commands in Quartz are specified using a fixed-scale drawing space, known as the user coordinate space. iPhone OS then maps the coordinates in this drawing space onto the actual pixels of the device. The advantage of this model is that graphics drawn using vector commands continue to look good when scaled up or down using an affine transform.

Or am I not using vector-based commands? If not, how would I do that to draw a circle?

Thanks.

A: 

It depends when you're applying the scaling transformation, I expect. If you draw it first, then do the scale transform, then it will look pixelated (because it's been scaled post drawing). If you do the scale before you do the drawing routine, I'd expect it would work as expected.

So yes, you're using vector-based commands to achieve this; I suspect it's an ordering issue. When are you making the transformation and drawing?

AlBlue
Thanks for your response. To my knowledge, doing a transform makes the view to redraw itself afterwards regardless.But I tried anyway, doing a [circle setNeedsDisplay] after the transform and it didn't change anything, nor did setting the transform before doing the draw.
Dan
Can you post the code where you're setting the transform?
AlBlue
Changing the transformation matrix after drawing won't affect what you've already drawn. The graphics state doesn't work that way. I still want to see the code with the CTM-changing statements in it, though.
Peter Hosey
Right - that was the issue. I tried calling self.transform = CGAffineTransformMakeScale(2.0, 2.0) in the drawRect method. Brad's response explained it.
Dan
A: 

You could try calling setNeedsDisplay after the transform, I'm not sure if this will work or not but it's worth a shot.

David Kanarek
Nope, doesn't change anything.
Dan
+2  A: 

Applying a transform to a view does not cause it to be redrawn. All that it does is scale the view's layer, which is a bitmap texture stored on the GPU. This will lead to blurry graphics.

When drawing a view on the iPhone, -drawRect: is called to supply the content for the view's layer. That content is then cached as a texture on the GPU.

What they are referring to in the guide is the application of a transform during -drawRect:, when the vector graphics are being drawn. If you use a transform there (through CGContextConcatCTM() or the like), the circle will be drawn smoothly at the larger scale. However, you will also need to resize your view to reflect this larger shape. I recommend using a scale property on your custom view subclass that you can set to a different scale factor and that will handle resizing the view and redrawing its contents sharply.

Brad Larson
Thanks a lot, great explanation.
Dan