如何使用 CgLayer 进行最佳绘图
Posted
技术标签:
【中文标题】如何使用 CgLayer 进行最佳绘图【英文标题】:How to use CgLayer for optimal drawing 【发布时间】:2012-07-05 09:46:08 【问题描述】:我创建了一个简单的绘图项目,代码工作正常,但我想将绘图缓存到 CGlayer 中,因为我读到它更有效的绘图方式。我已阅读文件,但无法正确理解。所以朋友们,我请求你们在这方面帮助我。
下面是我的代码,我想知道如何在这里面使用CgLayer
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
if(myLayerRef == nil)
myLayerRef = CGLayerCreateWithContext(context, self.bounds.size, NULL);
CGContextRef layerContext = CGLayerGetContext(myLayerRef);
CGContextDrawLayerAtPoint(context, CGPointZero, myLayerRef);
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
UITouch *mytouch=[[touches allObjects] objectAtIndex:0];
m_previousPoint2 = m_previousPoint1;
m_previousPoint1 = [mytouch previousLocationInView:self];
m_currentPoint = [mytouch locationInView:self];
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
testpath = CGPathCreateMutable();
CGPathMoveToPoint(testpath, NULL, mid1.x, mid1.y);
CGPathAddQuadCurveToPoint(testpath, NULL, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);
CGContextRef context = UIGraphicsGetCurrentContext();
context = CGLayerGetContext(myLayerRef);
CGRect bounds = CGPathGetBoundingBox(testpath);
CGPathRelease(testpath);
CGRect drawBox = bounds;
//Pad our values so the bounding box respects our line width
drawBox.origin.x -= self.lineWidth * 2;
drawBox.origin.y -= self.lineWidth * 2;
drawBox.size.width += self.lineWidth * 4;
drawBox.size.height += self.lineWidth * 4;
[self setNeedsDisplayInRect:drawBox];
- (void) drawingOperations
CGContextRef context1 = CGLayerGetContext(myLayerRef);
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
CGContextMoveToPoint(context1, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context1, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);
CGContextSetLineCap(context1, kCGLineCapRound);
CGContextSetLineWidth(context1, self.lineWidth);
CGContextSetStrokeColorWithColor(context1, self.lineColor.CGColor);
CGContextSetFlatness(context1, 2.0);
CGContextSetAllowsAntialiasing(context1, true);
CGContextStrokePath(context1);
问候 兰吉特
【问题讨论】:
你好,谁能帮帮我 您好朋友,我想我已经解决了使用 CgLayer 缓存行的问题,但不确定是正确的方法,它工作正常。我已经用最新的代码更新了我的帖子,我想要有人请验证我的代码并让我知道我是否正确。这样我就可以将问题标记为已解决。谢谢 添加您的图层使用代码作为答案,而不是更新问题,否则问题没有意义。 这看起来不错。只在drawRect之外进行绘图操作可能会更好,但如果它足够平滑,那么它并不重要。此外,设置线帽宽度等只需执行一次(因为没有其他人使用图层的上下文,因此不会更改)。 嘿,谢谢 borrrden,正如你所说,绘图操作应该在 drawRect 之外完成,你的意思是说所有从 CGcontextmovetoPint() 到 CGcontextDrawLayeratPoint() 的代码都应该在外面吧?我为它创建了一个不同的函数并从 touchesmoved 调用它? 【参考方案1】:@hfossli 发布的链接现已失效,但这里是存档内容:
不再推荐使用 CGLayer
robnapier 于 2012 年 7 月 13 日在图书更新中发表
我花了很多时间在 WWDC 的实验室里提出问题并与开发人员交谈。这次我和 Core Graphics 工程师坐下来,向他们询问了我最喜欢的未充分利用的工具之一:CGLayer,我将在第 6 章末尾讨论。CGLayer 听起来是个好主意:专门为在屏幕上绘图而优化的绘图上下文,与硬件优化。会出什么问题?
不过,我开始怀疑 CGLayer 始终是一场伟大的胜利。如果您的图层太大而无法存储在 GPU 纹理中怎么办? CGLayer 被宣传用作您反复绘制的“印章”。将数据移入和移出 GPU 的成本很高。除非你画了一定次数,否则 CGLayer 可能没有意义。文档对此没有提供任何指导。
所以我问 Core Graphics 团队“我应该什么时候使用 CGLayer?”
“从不。”
... ???绝不?但是要冲压对吗?
从不。
所以我们又谈了一些。看起来 CGLayer 是那些在纸上听起来很棒的东西之一,但在实践中并不总是有效。有时它会更快。有时它更慢。什么时候会更快,没有简单的规则。随着时间的推移,他们似乎已经悄悄地放弃了它而没有真正弃用它。我已要求更新文档以符合 Apple 当前的建议。 CGLayer 参考自 2006 年以来未更新。
我收到的建议是使用 CGBitmapContext 或 CALayer 进行标记。 对于第 131-132 页给出的具体示例,CATextLayer 可能是最好的工具。请记住,您可以使用 initWithLayer: 轻松克隆 CALayer。 (John Mueller 在下面指出实际上并不支持。)
【讨论】:
我认为最大的问题是他们没有微软的 Direct2D 已经实现的东西:依赖于设备的资源,当内存被其他人重用时会被丢弃。【参考方案2】:不再适合使用 CGLayer
http://iosptl.com/posts/cglayer-no-longer-recommended/
【讨论】:
链接已失效,但我已在此问题的另一个答案中发布了存档内容。以上是关于如何使用 CgLayer 进行最佳绘图的主要内容,如果未能解决你的问题,请参考以下文章