2011-09-19 27 views
4

我正在編寫的應用程序使用libcairo輸出矢量圖形;對於支持多頁(PDF,PostScript)的輸出格式,一切正常,但是我也想支持SVG和光柵圖像格式。使用libcairo和Haskell的多頁SVG

我現在只是簡單地用showPage推動頁面,只要我會溢出底部邊距,我想保持這種方式的代碼結構。我來了兩個theroretically可能的解決方案:

一)一個輔助的單子是環繞開羅Render單子,但提供了一個flushPage動作,當鏈接到它,使當前渲染動作到內部頁堆棧, liftRender將通過將其鏈接到以前緩存的動作中,將單個動作解壓到單聲道中,然後使用輔助函數提取Render()動作列表,每個頁面一個動作。所以我只是簡單地調用我的主要渲染函數,而不是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),其作用類似於在外面多頁文檔開羅面型,但產生了一系列的外單頁文檔。這將是理想的,因爲它根本不需要對渲染代碼進行任何更改,但是我不確定是否可以在不破壞開源本身的情況下做到這一點。

所以,實際問題:以上解決方案是否已經存在?如有,有人寫過'分頁包裝monad'或'多頁SVG表面'嗎?並且,如果答案是「否」;哪一個更好?你將如何去實施它?

回答

2

如果有人有興趣,我理解了它感謝一些友好的幫助,從球員在#haskell。

我的渲​​染函數不是編寫自定義包裝monad,而是返回Render [Render()]。我遞歸地呈現片段,傳遞一些狀態,並且在每次迭代中,我檢查當前操作是否會溢出當前頁面。如果會,那麼遞歸調用會附加一個新頁面並再次嘗試;否則,它會將當前操作鏈接到頂層頁面。結果是一個Render()操作的列表,每個頁面一個。

然後,主函數將這些Render()動作放在渲染函數的結果之外。然後它檢查所需的輸出格式;如果它是像PostScript或PDF這樣的多頁面格式,它只需將操作鏈接在一起,在它們之間插入showPage操作。如果是單頁格式,則爲每個頁面創建一個新的渲染表面,並將一個頁面操作呈現給它。第一頁翻譯爲初始渲染調用的上下文。

0

如果不需要打印'doc',那麼多個svg'g'節點層可以作爲頁面可見。 要進行分頁,則可見性可以打開或關閉。

如果打印過程很智能,那麼打印是可能的?

MARKT

+0

這不完全是我正在尋找的 - 我實際上將SVG和其他矢量格式輸出到文件中,並且因爲我正在使用libcairo進行此操作,所以我沒有達到此級別的控制要求。 – tdammers