Will Larche
Will Larche

Reputation: 3149

Why is CAShapeLayer too big despite setting contentsScale?

I have a CAShapeLayer that I'm using to draw tiny dots in a bar chart. The problem is that they are all too big on the retina displays. I have set the contentsScale and checked that it is getting set. Still I see no difference with it or without it!

CAShapeLayer *lineShapeLayer = [CAShapeLayer layer];
lineShapeLayer.contentsScale = [[UIScreen mainScreen] scale]; 
CGMutablePathRef path = CGPathCreateMutable();
lineShapeLayer.backgroundColor = [UIColor clearColor].CGColor;
lineShapeLayer.bounds = CGRectMake(0, 0, self.backgroundLayer.bounds.size.width, 1.5);

lineShapeLayer.anchorPoint = CGPointMake(0, 0);
lineShapeLayer.position = CGPointMake(0, rint((self.verticalPartitionHeight)*i));
lineShapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithFloat:1], [NSNumber numberWithInt:2], nil];
lineShapeLayer.strokeColor = [UIColor blackColor].CGColor;
lineShapeLayer.lineWidth = 1;
NSLog(@"contentsScale: %f", lineShapeLayer.contentsScale);

CGPathMoveToPoint(path, nil, 0, .5);       
CGPathAddLineToPoint(path, nil, lineShapeLayer.frame.size.width, .5);
[lineShapeLayer setPath:path];

[self.backgroundLayer addSublayer:lineShapeLayer];

Here is the view if I make it with PNGs: PNGs showing 1px dots

Here is the view with the CAShapeLayer code (set to line width .5 even.): CAShapeLayer showing 4px dots :(

Upvotes: 2

Views: 1856

Answers (3)

bhushan
bhushan

Reputation: 1

Best way to scale CAShapeLayer is the following:

CAShapeLayer *pathLayer = [CAShapeLayer layer];   
[pathLayer setTransform:CATransform3DMakeScale(0.1, 0.1, 0.1)];

Upvotes: 0

Will Larche
Will Larche

Reputation: 3149

@David Ronnqvist was right! The contentsScale was working. I just had to make the line width even smaller and then put the whole thing on the .25 (which is .5/2)!

    CAShapeLayer *lineShapeLayer = [CAShapeLayer layer];
    lineShapeLayer.contentsScale=[[UIScreen mainScreen] scale]; 
    CGMutablePathRef path = CGPathCreateMutable();
    lineShapeLayer.backgroundColor=[UIColor clearColor].CGColor;
    lineShapeLayer.bounds=CGRectMake(0, 0, self.backgroundLayer.bounds.size.width, 0.5);

    lineShapeLayer.anchorPoint=P(0,0);
    lineShapeLayer.position=P(0,rint((self.verticalPartitionHeight)*i));
    lineShapeLayer.lineDashPattern=[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.5], [NSNumber numberWithInt:1], nil];
    lineShapeLayer.strokeColor=[UIColor grayColor].CGColor;
    lineShapeLayer.lineWidth=0.5;
    lineShapeLayer.shadowColor=[UIColor whiteColor].CGColor;
    lineShapeLayer.shadowOffset=CGSizeMake(0, 0.5);
    lineShapeLayer.shadowOpacity=1.0;
    lineShapeLayer.shadowRadius=0;


    NSLog(@"lineShapeLayer.frame: %@", NSStringFromCGRect(lineShapeLayer.frame));
    CGPathMoveToPoint(path, nil, 0, 0.25);       
    CGPathAddLineToPoint(path, nil, lineShapeLayer.frame.size.width, 0.25);
    [lineShapeLayer setPath:path];

Of course I'll make this not hardcoded for scale but divisible by the scale.

Looks perfect

Upvotes: 0

David Rönnqvist
David Rönnqvist

Reputation: 56635

There is nothing wrong with you code unless its somewhere else. I ran the code above inside a loop (I'm assuming i is the index) with self.verticalPartitionHeight = 30.0.

The two images below are the result in both normal resolution and retina resolution. I've scaled up the normal image to make them the same size. The dots are, as you can see, the same size (in points, not pixels) on both resolutions.

Normal resolution, scaled up two times

Retina resolution

Edit:

You mention that the Stocks app does this in Landscape but if you zoom in on a screenshot of it you will actually see that it actually uses points (since every dot is 2x2 pixels). You can see this in the screenshot below (from a retina screenshot) where I zoomed in a lot on the dots and selected one pixel of one dot.

This is the expected behavior.

Stocks.app dots

Edit 2:

One more zoomed up look at your dots. They are actually the exact same size as the dots in Apples Stocks app. You can see it in the image below where I have selected one pixel.

enter image description here

Upvotes: 4

Related Questions