如何在 Haskell gtk2hs 中将开罗绘图渲染到打印机

How do I render a Cairo drawing to a printer in Haskell gtk2hs

我正在使用 GTK3 build of gtk2hs. I have a Cairo drawing in the Render monad,我想将它发送到打印机。

我看到有一个 Surface 类型封装了 Cairo 后端。例如,可以使用 withSVGSurface, and there are similar functions for PDF, Postscript and PNG. Once you have a Surface you can apply a Render action (i.e. actually draw on it) using renderWith 创建 SVG 表面。这非常简单,我可以看到如何使用这些功能将图纸导出为文件。

但是打印似乎不是这样工作的。 printOptDrawPage signal provides its callback with a printContext 值。这有一个函数 printContextGetCairoContext 其中 returns 开罗 Context。但是,库文档没有此 Context 类型的条目,而且我找不到任何使用它的函数。

看起来应该有 printContextGetSurface 函数,或者有一种方法可以将 Context 转换为 Surface。我错过了什么吗?

哈,哎呀,好尴尬!看来这个部门的绑定有点不完整。

幸运的是,更新它们应该很容易。看一下 Render monad 的定义:

newtype Render m = Render { runRender :: ReaderT Cairo IO m }

我们可以看到,您从 printContextGetCairoContext 获得的 Cairo 对象正是您使用 Render 操作做一些有用的事情所需要的。 renderWith 函数的实现为您提供了有关应采取哪些清理操作的线索:

renderWith surface (Render m) = liftIO $
  bracket (Internal.create surface)
          (\context -> do status <- Internal.status context
                          Internal.destroy context
                          unless (status == StatusSuccess) $
                            fail =<< Internal.statusToString status)
          (\context -> runReaderT m context)

我认为两个补丁之一在这里是明智的:

  1. 公开一个消耗 CairorenderWith-like。让用户连接 printContextGetCairoContext 与新的 renderWith-相似。
  2. 根本不暴露printContextGetCairoContext;将其替换为

    printContextRender :: PrintContextClass self => self -> Render a -> IO a
    

    printContextRender将对printContextGetCairoContext的调用与renderWith风格的清理合并。

我喜欢选项 (1),因为它的故事很干净 backwards-compatibility;但我更喜欢 (2) API-design 方面的东西。由于您所描述的原因,此模块可能没有太多用处,因此我倾向于补丁 (2)。

我还注意到,您可能需要稍微查看一下 gtk 文档,以检查 Cairo 上下文清理是否由其他人负责(例如,PrintOperation 的)。

祝黑客愉快!