在 NSView 和 HWND 中嵌入 skia 画布,当窗口调整大小时画布刷新为空白

Posted

技术标签:

【中文标题】在 NSView 和 HWND 中嵌入 skia 画布,当窗口调整大小时画布刷新为空白【英文标题】:Embed skia canvas in NSView and HWND, canvas flushed as blank when window resize 【发布时间】:2016-01-17 11:05:37 【问题描述】:

我正在尝试将skia canvas 嵌入到NSView 和HWND 中以进行一些跨平台绘图。我使用的是skia源代码自带的SkView类,并使用SkOSWindow作为窗口。但是当窗口调整大小时,窗口变黑了。如下图所示

这是 SkWindow 在调整大小时使用的代码,

void SkWindow::resize(int width, int height, SkColorType ct) 
    if (ct == kUnknown_SkColorType)
        ct = fColorType;

    if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) 
        fColorType = ct;
        fBitmap.allocPixels(SkImageInfo::Make(width, height,
                                              ct, kPremul_SkAlphaType));

        this->setSize(SkIntToScalar(width), SkIntToScalar(height));
        this->inval(nullptr);
    

我是skia 的新手,我找不到任何关于这个问题的文档。有没有人遇到过这个问题?任何建议将不胜感激!

【问题讨论】:

【参考方案1】:

您可以通过单独处理实时调整大小的情况来解决它。我的猜测是,当窗口处于实时调整大小时,skia 位图后端会重新创建,但不会重新绘制。所以只需要自己做一个后端,在drawRect方法中复制到CGContext中。请参阅下面的代码。

这个解决方案并不完美。如果您知道如何优雅地解决它,请告诉我。

- (void)drawRect:(NSRect)rect 
  [super drawRect:rect];

  CGContextRef ctx =
      (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];

  if ([self inLiveResize]) 
    SkBitmap bm;
    bm.allocN32Pixels(rect.size.width, rect.size.height);
    SkCanvas canvas(bm);

    _document.draw(&canvas); // replace your drawing code

    CGImageRef img = SkCreateCGImageRef(bm);
    if (img) 
      CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
      CGContextRef cg = reinterpret_cast<CGContextRef>(ctx);
      CGContextSaveGState(cg);
      CGContextTranslateCTM(cg, 0, r.size.height);
      CGContextScaleCTM(cg, 1, -1);
      CGContextDrawImage(cg, r, img);
      CGContextRestoreGState(cg);
      CGImageRelease(img);
    

   else 
    SkCGDrawBitmap(ctx, fWind->getBitmap(), 0, 0);
  

【讨论】:

以上是关于在 NSView 和 HWND 中嵌入 skia 画布,当窗口调整大小时画布刷新为空白的主要内容,如果未能解决你的问题,请参考以下文章

Skia 和 Android Paint 绘图对象及其使用或文档

Swift:在Container View / NSView中切换NSViewController

System.InvalidOperationException:“寄宿 HWND 必须是子窗口。”

在 NSView 中添加边框和圆角矩形

如何将 QML 视图嵌入到本机窗口中

在 Android NDK 中使用 Skia