ios – 如何缓存CGContextRef

不满意我以前的结果,我被要求创建一个徒手绘制视图,在缩放时不会模糊.我可以想象的唯一方法是使用CATiledLayer,否则在缩放时绘制线条时速度太慢.目前,我已将其设置为每次都会重新绘制每一行,但我想知道是否可以在上下文或其他内容中缓存前一行的结果(而不是像素,因为它们需要很好地缩放).

我想过CGBitmapContext,但这是否意味着我需要在每次缩放后拆除并设置新的上下文?问题是在视网膜显示器上,线条画太慢(在iPad 2上它是如此),特别是在缩放时绘制. App Store中有一个名为GoodNotes的应用程序,可以很好地证明这是可行的,并且可以顺利完成,但我无法理解他们是如何做到的.这是我到目前为止的代码(今天大部分时间的结果):

- (void)drawRect:(CGRect)rect
{   
    CGContextRef c = UIGraphicsGetCurrentContext();

    CGContextSetLineWidth(c, mLineWidth);
    CGContextSetAllowsAntialiasing(c, true);
    CGContextSetShouldAntialias(c, true);
    CGContextSetLineCap(c, kCGLineCapRound);
    CGContextSetLineJoin(c, kCGLineJoinRound);

    //Protect the local variables against the multithreaded nature of CATiledLayer
    [mLock lock]; 
    NSArray *pathsCopy = [mStrokes copy];
    for(UIBezierPath *path in pathsCopy) //**Would like to cache these**
    {
        CGContextAddPath(c, path.CGPath);
        CGContextStrokePath(c);
    }
    if(mCurPath)
    {
        CGContextAddPath(c, mCurPath.CGPath);
        CGContextStrokePath(c);
    }

    CGRect pathBounds = mCurPath.bounds;
    if(pathBounds.size.width > 32 || pathBounds.size.height > 32)
    {
        [mStrokes addObject:mCurPath];
        mCurPath = [[UIBezierPath alloc] init];
    }
   [mLock unlock];
}

分析显示目前最热门的功能是GCSFillDRAM8by1

最佳答案 首先,因为路径描边是最昂贵的操作,所以不应该锁定它,因为这会阻止您在不同的核心上同时绘制切片.

其次,我认为你可以通过在上下文中添加所有路径并完全抚摸它们来避免多次调用CGContextStrokePath.

[mLock lock]; 
for ( UIBezierPath *path in mStrokes ) {
    CGContextAddPath(c, path.CGPath);
}
if ( mCurPath ) {
    CGContextAddPath(c, mCurPath.CGPath);
}
CGRect pathBounds = mCurPath.bounds;
if ( pathBounds.size.width > 32 || pathBounds.size.height > 32 )
{
    [mStrokes addObject:mCurPath];
    mCurPath = [[UIBezierPath alloc] init];
}
[mLock unlock];
CGContextStrokePath(c);

CGContextRef只是一个用于绘图操作的画布.您无法缓存它,但您可以使用路径的扁平位图图像创建CGImageRef并重用该图像.这对缩放没有帮助(因为您需要在细节级别更改时重新创建图像),但在用户绘制非常长的路径时可以提高性能.

关于该主题,有一个非常有趣的WWDC 2012会议视频:Optimizing 2D Graphics and Animation Performance.

点赞