Get front row seat and watch the development of micro-isv. We make cool product that solves all your problems...

logo

Friends
         
Haskell gtk2hs printing
2009-04-07

Haskell rocks. Gtk2hs rocks. Unfortunately gtk2hs doesn't have a printing API wired up yet. I don't think that this is because it isn't possible, just that no-one smart enough has actually needed yet.

Here's a bit of a hack that lets you print stuff rendered using Cairo's neat rendering engine. Rather than 'do it properly' we will use the command line cups tools to query the printer, then render the Cairo surface to ps and queue it with the 'lpr' command line tool.

We can still get access to control the printout mode and duplex settings. These are passed in with the '-o' option to lpr. We can query the settings available for a printer using


# lpoptions -l

PageSize/Media Size: Letter *A4 Photo Photo5x7 PhotoTearOff…
PageRegion/Media Size: Letter A4 Photo Photo5x7 PhotoTearOff…
PrintoutMode/Printout Mode: Draft Draft.Gray *Normal 
                           Normal.Gray High High.Gray Photo
InputSlot/Media Source: *Default PhotoTray Upper Lower…
Duplex/Double-Sided Printing: DuplexNoTumble DuplexTumble *None
DryTime/Additional Dry Time: *Zero Five Ten Fifteen Twenty TwentyFive Thirty
Quality/Resolution, Quality, Ink Type, Media Type: *FromPrintoutMode…


So to print in draft mode we want to call lpr with “-o PrintoutMode=Draft”

Here's my Haskell recipe:

import Graphics.Rendering.Cairo
import Graphics.UI.Gtk.Cairo

import System.Process

inch = (*) 72

myDraw :: Render ()
myDraw = do
	setSourceRGB 1 1 0
	setLineWidth 5
	
	moveTo 120 60
	lineTo 60 110
	lineTo 180 110
	closePath
	
	stroke
	
	setSourceRGB 0 0 0
	setLineWidth 1
	moveTo (inch 5) (inch 5)
	lineTo (inch 6) (inch 6)
	closePath
	stroke
	
	moveTo 20 20
	rotate (pi/4)
	l <- createLayout "Haskell and Cairo is cool."
	showLayout l
	

main = do
	let tempFileName = "/tmp/foo.ps"
	withPSSurface tempFileName 595 842 $ \surface -> renderWith surface myDraw
	h <- runProcess "lpr" ["-o","PrintoutMode=Draft",tempFileName] Nothing Nothing Nothing Nothing Nothing
	e <- waitForProcess h
	print e

You call it 'ugly hack' I call it 'process isolation safety'