开发者

Confused about UIBezierPath + applyTransform + CGPath

I scale UIBezierPath (built of one [0,0 - 1x1] rect) by factor 2 in both x and y directions. UIBezierPath ".bounds" is alright (i.e. scaled as expected), while ".CGPath" remains unchanged...

Code:

#import <UIKit/UIKit.h>

int main(int argc, char *argv[])
{
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMa开发者_C百科ke(0, 0,
                                                                     1, 1)];
    NSLog(@"path.bounds box before transform:%@",
          NSStringFromCGRect(path.bounds));
    NSLog(@"path.CGPath box before transform:%@",
          NSStringFromCGRect(CGPathGetBoundingBox(path.CGPath)));

    [path applyTransform:CGAffineTransformMakeScale(2, 2)];

    NSLog(@"path.bounds box after transform:%@",
          NSStringFromCGRect(path.bounds));
    NSLog(@"path.CGPath box after transform:%@",
          NSStringFromCGRect(CGPathGetBoundingBox(path.CGPath)));

    return 0;        
}

Output:

path.bounds box before transform:{{0, 0}, {1, 1}}
path.CGPath box before transform:{{0, 0}, {1, 1}}
path.bounds box after transform:{{0, 0}, {2, 2}}
path.CGPath box after transform:{{0, 0}, {1, 1}}

Why?


As of iOS 5.1, the CGPath returned from UIBezier's .CGPath property is indeed updated when the UIBezierPath has a new transform applied.

However, this doesn't preclude a solution for older iOS versions. You can get the CGPath from the UIBezierPath, transform it directly, then set it back onto the UIBezierPath. Lo and behold, all the other properties, like bounds and origins, will update correctly and immediately.

UIBezierPath* path = [UIBezierPath bezierPathWithRect:CGRectMake(0.0f, 0.0f,
                                                                 1.0f, 1.0f)];

CGAffineTransform transform = CGAffineTransformMakeScale(2.0f, 2.0f);
CGPathRef intermediatePath = CGPathCreateCopyByTransformingPath(path.CGPath,
                                                                &transform);

path.CGPath = intermediatePath;

CGPathRelease(intermediatePath);


The reason for this difference is because the call to applyTransform simply stores the transform matrix in the path object. It does not cause the path itself to be modified. path.bounds is a calculated property that is derived using the transform, whereas the call the CGPathGetBoundingBox is simply iterating over the elements of the passed in CGPath object.

Because there could potentially be a great number of path elements, storing the transform matrix, and not modifying all of the the path elements every time a new matrix is assigned, is done as an optimization. This work is only done once, or minimally, when only certain properties, such as the bounds, of the UIBezierPath are queried.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜