I'm using the GTK3 build of gtk2hs. I have a Cairo drawing in the Render
monad and I want to send it to a printer.
I see that there is a Surface
type which encapsulates the Cairo back end. For example it is possible to create an SVG surface using 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
. This is perfectly straightforward, and I can see how to use these functions to export drawings as files.
However printing does not seem to work this way. The printOptDrawPage
signal provides its callback with a printContext
value. This has a function printContextGetCairoContext
which returns a Cairo Context
. However the library documentation doesn't have an entry for this Context
type, and I can't find any functions that use it.
It looks like there ought to be printContextGetSurface
function, or else a way to convert a Context
into a Surface
. Am I missing something?
Hah, whoops, that's embarrassing! It seems the bindings are just a little incomplete in this department.
Luckily it should be pretty easy to update them. Taking a look at the definition of the Render
monad:
newtype Render m = Render { runRender :: ReaderT Cairo IO m }
We can see that the Cairo
object you get from printContextGetCairoContext
is just what you need to do something useful with a Render
action. The implementation of the renderWith
function gives you a clue about what cleanup actions you should take:
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)
I think one of two patches would be sensible here:
renderWith
-alike that consumes a Cairo
. Let the user connect up printContextGetCairoContext
with the new renderWith
-alike.Don't expose printContextGetCairoContext
at all; replace it with
printContextRender :: PrintContextClass self => self -> Render a -> IO a
and have printContextRender
merge the call to printContextGetCairoContext
with the renderWith
-style cleanup.
I like option (1) for its clean backwards-compatibility story; but I like (2) a lot better from the API-design side of things. Since this module probably hasn't seen much use for the reasons you're describing, I'd lean towards patch (2).
I'd also note that you may want to look into the gtk documentation a bit to check whether the Cairo context cleanup is somebody else's responsibility (the PrintOperation's, for example).
Happy hacking!