Cal*_*leb 87 iphone bezier drawing ios
我正在玩绘图路径,我注意到至少在某些情况下,UIBezierPath优于我认为的Core Graphics等价物.-drawRect:下面的方法创建两个路径:一个UIBezierPath和一个CGPath.除了它们的位置之外,路径是相同的,但是抚摸CGPath所需的时间大约是抚摸UIBezierPath的两倍.
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Create the two paths, cgpath and uipath.
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath, NULL, 0, 100);
UIBezierPath *uipath = [[UIBezierPath alloc] init];
[uipath moveToPoint:CGPointMake(0, 200)];
// Add 200 curve segments to each path.
int iterations = 200;
CGFloat cgBaseline = 100;
CGFloat uiBaseline = 200;
CGFloat xincrement = self.bounds.size.width / iterations;
for (CGFloat x1 = 0, x2 = xincrement;
x2 < self.bounds.size.width;
x1 = x2, x2 += xincrement)
{
CGPathAddCurveToPoint(cgpath, NULL, x1, cgBaseline-50, x2, cgBaseline+50, x2, cgBaseline);
[uipath addCurveToPoint:CGPointMake(x2, uiBaseline)
controlPoint1:CGPointMake(x1, uiBaseline-50)
controlPoint2:CGPointMake(x2, uiBaseline+50)];
}
[[UIColor blackColor] setStroke];
CGContextAddPath(ctx, cgpath);
// Stroke each path.
[self strokeContext:ctx];
[self strokeUIBezierPath:uipath];
[uipath release];
CGPathRelease(cgpath);
}
- (void)strokeContext:(CGContextRef)context
{
CGContextStrokePath(context);
}
- (void)strokeUIBezierPath:(UIBezierPath*)path
{
[path stroke];
}
Run Code Online (Sandbox Code Playgroud)
两个路径都使用CGContextStrokePath(),因此我创建了单独的方法来描边每个路径,以便我可以看到Instruments中每个路径使用的时间.以下是典型结果(呼叫树倒置); 你可以看到-strokeContext:需要9.5秒,而-strokeUIBezierPath:只需要5秒:
Running (Self) Symbol Name
14638.0ms 88.2% CGContextStrokePath
9587.0ms 57.8% -[QuartzTestView strokeContext:]
5051.0ms 30.4% -[UIBezierPath stroke]
5051.0ms 30.4% -[QuartzTestView strokeUIBezierPath:]
Run Code Online (Sandbox Code Playgroud)
看起来UIBezierPath在某种程度上优化了它创建的路径,或者我是以天真的方式创建CGPath.我该怎么做才能加快我的CGPath绘图速度?
Stu*_*nie 150
你是对的,UIBezierPath它只是Core Graphics的一个Objective-c包装器,因此性能相当.差异(以及您的性能增量的原因)是CGContext您CGPath直接绘制时的状态与设置完全不同UIBezierPath.如果你看一下UIBezierPath,它有以下设置:
lineWidth,lineJoinStyle,lineCapStyle,miterLimit 和flatness在检查调用(反汇编)时[path stroke],您将注意到它在执行CGContextStrokePath调用之前根据这些先前的值配置当前图形上下文.如果在绘制CGPath之前执行相同操作,它将执行相同的操作:
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Create the two paths, cgpath and uipath.
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath, NULL, 0, 100);
UIBezierPath *uipath = [[UIBezierPath alloc] init];
[uipath moveToPoint:CGPointMake(0, 200)];
// Add 200 curve segments to each path.
int iterations = 80000;
CGFloat cgBaseline = 100;
CGFloat uiBaseline = 200;
CGFloat xincrement = self.bounds.size.width / iterations;
for (CGFloat x1 = 0, x2 = xincrement;
x2 < self.bounds.size.width;
x1 = x2, x2 += xincrement)
{
CGPathAddCurveToPoint(cgpath, NULL, x1, cgBaseline-50, x2, cgBaseline+50, x2, cgBaseline);
[uipath addCurveToPoint:CGPointMake(x2, uiBaseline)
controlPoint1:CGPointMake(x1, uiBaseline-50)
controlPoint2:CGPointMake(x2, uiBaseline+50)];
}
[[UIColor blackColor] setStroke];
CGContextAddPath(ctx, cgpath);
// Stroke each path
CGContextSaveGState(ctx); {
// configure context the same as uipath
CGContextSetLineWidth(ctx, uipath.lineWidth);
CGContextSetLineJoin(ctx, uipath.lineJoinStyle);
CGContextSetLineCap(ctx, uipath.lineCapStyle);
CGContextSetMiterLimit(ctx, uipath.miterLimit);
CGContextSetFlatness(ctx, uipath.flatness);
[self strokeContext:ctx];
CGContextRestoreGState(ctx);
}
[self strokeUIBezierPath:uipath];
[uipath release];
CGPathRelease(cgpath);
}
- (void)strokeContext:(CGContextRef)context
{
CGContextStrokePath(context);
}
- (void)strokeUIBezierPath:(UIBezierPath*)path
{
[path stroke];
}
Run Code Online (Sandbox Code Playgroud)
仪器快照:

| 归档时间: |
|
| 查看次数: |
24696 次 |
| 最近记录: |