保存和恢复CGContext

发布于 2024-08-05 02:38:29 字数 472 浏览 4 评论 0原文

我试图保存和恢复 CGContext 以避免再次进行繁重的绘图计算,但收到错误 : CGGStackRestore: gstack underflow

我做错了什么?这样做的正确方法是什么?

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

    if (initialized) {
        CGContextRestoreGState(context);
        //scale context
        return;
    }

    initialized = YES;

    //heavy drawing computation and drawing

    CGContextSaveGState(context);
}

I'm trying to save and restore a CGContext to avoid doing heavy drawing computations for a second time and I'm getting the error <Error>: CGGStackRestore: gstack underflow.

What am I doing wrong? What is the correct way to do this?

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

    if (initialized) {
        CGContextRestoreGState(context);
        //scale context
        return;
    }

    initialized = YES;

    //heavy drawing computation and drawing

    CGContextSaveGState(context);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

香橙ぽ 2024-08-12 02:38:29

我认为您可能误解了 CGContextSaveGState() 和 CGContextRestoreGState() 的作用。它们将当前图形状态推入堆栈并将其弹出,让您可以变换当前绘图空间、更改线条样式等,然后将状态恢复到设置这些值之前的状态。它不存储绘图元素,例如路径。

来自 关于 CGContextSaveGState() 的文档

每个图形上下文都维护一个
图形状态堆栈。注意
并非当前绘图的所有方面
环境是构成要素
图形状态。例如,
当前路径不被视为一部分
图形状态,因此
当您调用时未保存
CGContextSaveGState() 函数。

图形状态堆栈应在 drawRect: 开始时重置,这就是当您尝试从堆栈中弹出图形状态时出现错误的原因。由于您没有推入任何一个,因此没有任何一个可以弹出。所有这些意味着您无法将绘图作为图形状态存储在堆栈上,然后在以后恢复。

如果您所担心的只是缓存您的绘图,那么支持您的 UIView(在 iPhone 上)的 CALayer 可以为您完成此操作。如果您所做的只是移动视图,则不会重新绘制视图。只有当您手动告诉它这样做时,它才会被绘制。如果您确实必须更新绘图的一部分,我建议将静态元素拆分到它们自己的视图或 CALayers 中,以便仅重绘更改的部分。

I think you might be misinterpreting what CGContextSaveGState() and CGContextRestoreGState() do. They push the current graphics state onto a stack and pop it off, letting you transform the current drawing space, change line styles, etc., then restore the state to what it was before you set those values. It does not store drawing elements, like paths.

From the documentation on CGContextSaveGState():

Each graphics context maintains a
stack of graphics states. Note that
not all aspects of the current drawing
environment are elements of the
graphics state. For example, the
current path is not considered part of
the graphics state and is therefore
not saved when you call the
CGContextSaveGState() function.

The graphics state stack should be reset at the start of your drawRect:, which is why you're getting errors when you try to pop a graphics state off the stack. Since you hadn't pushed one on, there was none to pop off. All of this means that you can't store your drawing as graphics state on the stack, then restore it later.

If all you are worried about is caching your drawing, that is done for you by the CALayer that backs your UIView (on the iPhone). If all you are doing is moving your view around, it won't be redrawn. It will only be drawn if you manually tell it to do so. If you do have to update part of the drawing, I recommend splitting the static elements off into their own views or CALayers so that only the part that changes is redrawn.

忆梦 2024-08-12 02:38:29

您不想先保存再恢复吗?如果您在保存之前进行恢复,则没有要恢复的上下文,并且您会遇到下溢。

这是我使用它的方式:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextClipToRect(context, CGRectMake(stripe[i][8], stripe[i][9], stripe[i][10], stripe[i][11]));
CGContextDrawLinearGradient(context, gradient, CGPointMake(15, 5), CGPointMake(15, 25), 0);
CGContextRestoreGState(context);

或者:

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState(context);
  CGContextAddRect(context, originalRect);
  CGContextClip(context);

  [self drawInRect:rect];

  CGContextRestoreGState(context);

也许你正在尝试做其他事情。

Don't you want to Save first and then Restore? If you are restoring before a save, then there is no context to restore, and you'd get an underflow.

Here is the way I have used it:

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextClipToRect(context, CGRectMake(stripe[i][8], stripe[i][9], stripe[i][10], stripe[i][11]));
CGContextDrawLinearGradient(context, gradient, CGPointMake(15, 5), CGPointMake(15, 25), 0);
CGContextRestoreGState(context);

or:

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState(context);
  CGContextAddRect(context, originalRect);
  CGContextClip(context);

  [self drawInRect:rect];

  CGContextRestoreGState(context);

Maybe you are trying to do something else.

时光倒影 2024-08-12 02:38:29

..根据你的代码!,
看来您正在保存上下文之前恢复它。
第一件事首先:

  1. 创建一个上下文
  2. 保存其状态,又名推送
  3. 对上下文执行一些操作
  4. 恢复上下文,又名 Pop
  5. 每个 Store(push) 的一般规则必须有 < code>Restore(pop)
  6. 完成后释放上下文!,这是指它们拥有的上下文 CGCreateCGCopy

Sample代码:

        [super drawRect:rect];
        CGContextRef ctx = UIGraphicsGetCurrentContext();
// save context 
        CGContextSaveGState(ctx);
// do some stuff 
        CGContextSetRGBStrokeColor(ctx, 1.0, 0.5, 0.5, 1.0);
        // drawing vertical lines
        CGContextSetLineWidth(ctx, 1.0);
        for (int i = 0; i < [columns count]; i++) {
            CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue];
            CGContextMoveToPoint(ctx, f+(i*20.5), 0.5);
            CGContextAddLineToPoint(ctx, f+(i*20.5), self.bounds.size.height);
        }
// restore context 
        CGContextRestoreGState(ctx);
// do some other stuff 
        // drawing hozizontal lines
        CGContextSetLineWidth(ctx, 1.0);
         CGContextSetRGBStrokeColor(ctx, 0.12385, 0.43253, 0.51345, 1.0);
        for (int i = 0; i < [columns count]; i++) {
            CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue];
            CGContextMoveToPoint(ctx, 0.5, f+(i*20.5));
            CGContextAddLineToPoint(ctx,self.bounds.size.width,f+(i*20.5));
        }

        CGContextStrokePath(ctx);
    }
// No context CGContextRelease , since we never used CGContextCreate 

.. Based on your code !,
It seems that you are Restoring the Context before Saving it.
First Thing First:

  1. Create a context
  2. Save its state, aka push
  3. Do some stuff with the context
  4. Restore the context aka Pop
  5. General rule for each Store(push) there must be Restore(pop)
  6. Release the context when you are done with it !, This refers to those context/s which they have CGCreate, CGCopy,

Sample code:

        [super drawRect:rect];
        CGContextRef ctx = UIGraphicsGetCurrentContext();
// save context 
        CGContextSaveGState(ctx);
// do some stuff 
        CGContextSetRGBStrokeColor(ctx, 1.0, 0.5, 0.5, 1.0);
        // drawing vertical lines
        CGContextSetLineWidth(ctx, 1.0);
        for (int i = 0; i < [columns count]; i++) {
            CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue];
            CGContextMoveToPoint(ctx, f+(i*20.5), 0.5);
            CGContextAddLineToPoint(ctx, f+(i*20.5), self.bounds.size.height);
        }
// restore context 
        CGContextRestoreGState(ctx);
// do some other stuff 
        // drawing hozizontal lines
        CGContextSetLineWidth(ctx, 1.0);
         CGContextSetRGBStrokeColor(ctx, 0.12385, 0.43253, 0.51345, 1.0);
        for (int i = 0; i < [columns count]; i++) {
            CGFloat f = [((NSNumber*) [columns objectAtIndex:i]) floatValue];
            CGContextMoveToPoint(ctx, 0.5, f+(i*20.5));
            CGContextAddLineToPoint(ctx,self.bounds.size.width,f+(i*20.5));
        }

        CGContextStrokePath(ctx);
    }
// No context CGContextRelease , since we never used CGContextCreate 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文