Multipage SVG using libcairo and Haskell

The application I'm writing uses libcairo to output vector graphics; everything works fine for output formats that support multiple pages (PDF, PostScript), however I would also like to support SVG and bitmap formats.

Currently, I just click pages with showPage whenever I otherwise overflow the bottom edge and I would like the code to be structured this way. I came up with two theoretically possible solutions:

a) An auxiliary monad that goes around the Cairo Render monad, but provides a flushPage action, which, when chained to it, flushPage current Render action on the stack of the internal page, performs the liftRender action, which, well, raise the Render action to the monad, binding it to the previously buffered an action and a helper function to retrieve the list of Render () actions, one for each page. So I would just call my main rendering function, but instead of the Render () action, it would return the pagination-wrapper action, from which I would then extract individual pages and process them - for multi-page formats, I could just chain them together by inserting the showPage actions between them, while for single-page formats, I would do them individually. As an example, here's how it would look:

 -- 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) A cairo surface type that acts as a multi-page document from the outside, but creates a series of one-page documents from the outside. This would be ideal, since it would not require any changes in the rendering code at all, but I'm not sure that this can be done without delving into cairo itself at the initial level.

So, the actual question is: Is there any of the above solutions? As in any case, did anyone write either a "page wrapper nonsense" or a "multi-page SVG surface"? And in the case of the answer "no"; which one is preferable, and how are you going to implement it?

+4
source share
2 answers

In case anyone is interested, I realized this thanks to the friendly help of the guys at #haskell.

Instead of writing a custom wrapper wrapper, my rendering function returns Render [Render ()] . I recursively process fragments, passing some state, and at each iteration I check whether the current operation will overflow the current page. If this happens, then the recursive call will add a new page and try again; otherwise, it binds the current operation to the top page. The result is a list of Render () actions, one for each page.

The main function then takes these Render() actions from the result of the render function. Then it checks the desired output format; if it is a multi-page format such as PostScript or PDF, it simply combines actions by inserting showPage actions between them. If this is a one-page format, it creates a new visualization surface for each page and displays one page action on it. The first page doubles as context for the first render call.

+2
source

If you do not need to print "doc", then several layers of svg 'g' nodes can be seen as pages. For pagination, then visibility can be turned on or off.

If the printing process has the ability to understand this, is printing possible?

Markt

0
source

All Articles