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.
精彩评论