Search code examples
iphonecocoacocoa-touchquartz-2d

How to set up a user Quartz2D coordinate system with scaling that avoids fuzzy drawing?


This topic has been scratched once or twice, but I am still puzzled. And Google was not friendly either.

Since Quartz allows for arbitrary coordinate systems using affine transforms, I want to be able to draw things such as floorplans using real-life coordinate, e.g. feet.

So basically, for the sake of an example, I want to scale the view so that when I draw a 10x10 rectangle (think a 10-inch box for example), I get a 60x60 pixels rectangle.

It works, except the rectangle I get is quite fuzzy. Another question here got an answer that explains why. However, I'm not sure I understood that reason why, and moreover, I don't know how to fix it. Here is my code:

I set my coordinate system in my awakeFromNib custom view method:

- (void) awakeFromNib {
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
    self.transform = scale;
}

And here is my draw routine:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect r = CGRectMake(10., 10., 10., 10.);
    CGFloat lineWidth = 1.0;
    CGContextStrokeRectWithWidth(context, r, lineWidth);
}

The square I get is scaled just fine, but totally fuzzy. Playing with lineWidth doesn't help: when lineWidth is set smaller, it gets lighter, but not crisper.

So is there a way to set up a view to have a scaled coordinate system, so that I can use my domain coordinates? Or should I go back and implementing scaling in my drawing routines?

Note that this issue doesn't occur for translation or rotation.

Thanks


Solution

  • Well, as often, explaining the issue lead me to a solution.

    The problem is that the view transform property is applied to it after it has been drawn into a bit buffer. The scaling transform has to be applied before drawing, ie. in the drawRect method. So scratch the awakeFromNib I gave, and here is a correct drawRect:

    - (void)drawRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
        CGContextConcatCTM(context, scale);
        CGRect r = CGRectMake(10., 10., 10., 10.);
        CGFloat lineWidth = 0.1;
        CGContextStrokeRectWithWidth(context, r, lineWidth);
    }