gpt4 book ai didi

iphone - 为什么 UIBezierPath 比 Core Graphics 路径快?

转载 作者:IT王子 更新时间:2023-10-29 07:30:32 25 4
gpt4 key购买 nike

我在研究绘制路径时发现,至少在某些情况下,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];
}

两条路径都使用 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:]

看起来 UIBezierPath 正在以某种方式优化它创建的路径,或者我正在以一种天真的方式创建 CGPath。我可以做些什么来加快我的 CGPath 绘图?

最佳答案

您是正确的,UIBezierPath 只是 Core Graphics 的 objective-c 包装器,因此性能相当。差异(以及性能差异的原因)是直接绘制 CGPath 时的 CGContext 状态与 UIBezierPath 的设置完全不同。如果您查看 UIBezierPath,它具有以下设置:

  • 线宽,
  • lineJoinStyle,
  • lineCapStyle,
  • miterLimit
  • 平坦度

检查对[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];
}

来自 Instruments 的快照: Instruments snapshot showing equal performance

关于iphone - 为什么 UIBezierPath 比 Core Graphics 路径快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6327817/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com