【问题标题】:Multi-page SVG using libcairo and Haskell使用 libcairo 和 Haskell 的多页 SVG
【发布时间】:2011-09-19 06:13:56
【问题描述】:

我正在编写的应用程序使用 libcairo 来输出矢量图形;对于支持多页(PDF、PostScript)的输出格式,一切正常,但我也希望支持 SVG 和光栅图像格式。

我目前只是使用showPage 推送页面,否则我会溢出底部边距,并且我希望保持这种代码结构。我提出了两种理论上可能的解决方案:

a) 一个 helper monad,它包裹 Cairo 的 Render monad,但提供了一个 flushPage 动作,当它链接到它时,将当前的 Render 动作推送到一个内部页面堆栈上,一个 liftRender 动作会,好吧,通过将Render 动作链接到先前缓冲的动作和一个辅助函数来提取Render () 动作列表,将其提升到 monad 中,每个页面一个。所以我会简单地调用我的主渲染函数,而不是 Render () 动作,它会返回一个分页包装器动作,然后我会从中提取单个页面并处理它们 - 对于多页格式,我可以简单地链接它们在一起,在它们之间插入showPage 动作,而对于单页格式,我会单独呈现它们。例如,它的外观如下:

-- original code
renderMe :: Render ()
renderMe = do
    newPath
    moveTo 10 10
    lineTo 20 20
    lineTo 10 30
    lineTo 10 10
    fill

    showPage

    newPath
    moveTo 10 10
    lineTo 20 20
    lineTo 10 30
    lineTo 10 10
    fill

-- new code
renderPages :: PagedRender ()
renderPages = do
    liftRender (do
        newPath
        moveTo 10 10
        lineTo 20 20
        lineTo 10 30
        lineTo 10 10
        fill)

    flushPage

    liftRender (do
        newPath
        moveTo 10 10
        lineTo 20 20
        lineTo 10 30
        lineTo 10 10
        fill)

    flushPage

b) 一种 cairo 表面类型,它在外部类似于多页文档,但在外部生成一系列单页文档。这将是理想的,因为它根本不需要对渲染代码进行任何更改,但我不确定是否可以在不弄乱源代码级别的情况下做到这一点。

那么,实际的问题是:上述解决方案是否已经存在? 有没有人写过“分页包装单子”或“多页 SVG 表面”?而且,如果答案是“不”;其中哪一个更可取,您将如何实施?

【问题讨论】:

    标签: haskell svg cairo


    【解决方案1】:

    如果有人有兴趣,我在#haskell 的一些友好帮助下想通了。

    我的渲染函数没有编写自定义包装器 monad,而是返回 Render [Render ()]。我递归地渲染片段,传递一些状态,并且在每次迭代中,我检查当前操作是否会溢出当前页面。如果可以,则递归调用会附加一个新页面并再次尝试;否则,它将当前操作链接到首页。结果是Render () 操作列表,每个页面一个。

    然后,主函数将这些Render() 操作从渲染函数的结果中取出。然后它检查所需的输出格式;如果它是像 PostScript 或 PDF 这样的多页格式,它只是将动作链接在一起,在它们之间插入 showPage 动作。如果它是单页格式,它会为每个页面创建一个新的渲染表面,并在其上渲染一个页面动作。第一页兼作初始渲染调用的上下文。

    【讨论】:

      【解决方案2】:

      如果您不必打印 'doc',则可以将多层 svg 'g' 节点显示为页面。 要分页,则可见性可以打开或关闭。

      如果打印过程有智慧理解这一点,那么打印是可能的吗?

      马克T

      【讨论】:

      • 这并不是我想要的——我实际上是在将 SVG 和其他矢量格式输出到文件中,因为我为此使用 libcairo,所以我没有控制级别为此需要。
      猜你喜欢
      • 2019-09-19
      • 1970-01-01
      • 2016-08-30
      • 2020-06-04
      • 2015-09-12
      • 2018-04-18
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多