diagrams-cairo- Cairo backend for diagrams drawing EDSL

Safe HaskellNone




Convenient creation of command-line-driven executables for rendering diagrams using the cairo backend.

  • defaultMain creates an executable which can render a single diagram at various options.
  • multiMain is like defaultMain but allows for a list of diagrams from which the user can choose one to render.
  • animMain is like defaultMain but for animations instead of diagrams.
  • mainWith is a generic form that does all of the above but with a slightly scarier type. See Diagrams.Backend.CmdLine. This form can also take a function type that has a subtable final result (any of arguments to the above types) and Parseable arguments.

If you want to generate diagrams programmatically---i.e. if you want to do anything more complex than what the below functions provide---you have several options.

  • Use a function with mainWith. This may require making Parseable instances for custom argument types.
  • Make a new Mainable instance. This may require a newtype wrapper on your diagram type to avoid the existing instances. This gives you more control over argument parsing, intervening steps, and diagram creation.
  • Build option records and pass them along with a diagram to mainRender from Diagrams.Backend.CmdLine.
  • A more flexible approach is to use the renderCairo function provided in the Diagrams.Backend.Cairo module.
  • For the most flexibility, you can call the generic renderDia function directly; see Diagrams.Backend.Cairo for more information.

For a tutorial on command-line diagram creation see http://projects.haskell.org/diagrams/doc/cmdline.html.


General form of main

The mainWith method unifies all of the other forms of main and is now the recommended way to build a command-line diagrams program. It works as a direct replacement for defaultMain, multiMain, or animMain as well as allowing more general arguments. For example, given a function that produces a diagram when given an Int and a Colour Double, mainWith will produce a program that looks for additional number and color arguments.

 ... definitions ...
 f :: Int -> Colour Double -> Diagram Cairo R2
 f i c = ...

 main = mainWith f

We can run this program as follows:

 $ ghc --make MyDiagram

 # output image.png built by `f 20 red`
 $ ./MyDiagram -o image.png -w 200 20 red

mainWith :: (Mainable d, Parseable (MainOpts d)) => d -> IO ()

Main entry point for command-line diagram creation. This is the method that users will call from their program main. For instance an expected user program would take the following form.

 import Diagrams.Prelude
 import Diagrams.Backend.TheBestBackend.CmdLine

 d :: Diagram B R2
 d = ...

 main = mainWith d

Most backends should be able to use the default implementation. A different implementation should be used to handle more complex interactions with the user.

Supported forms of main

defaultMain :: Diagram Cairo R2 -> IO ()Source

This is the simplest way to render diagrams, and is intended to be used like so:

 ... other definitions ...
 myDiagram = ...

 main = defaultMain myDiagram

Compiling a source file like the above example will result in an executable which takes command-line options for setting the size, output file, and so on, and renders myDiagram with the specified options.

On Unix systems, the generated executable also supports a rudimentary "looped" mode, which watches the source file for changes and recompiles itself on the fly.

Pass --help to the generated executable to see all available options. Currently it looks something like


Usage: ./Program [-w|--width WIDTH] [-h|--height HEIGHT] [-o|--output OUTPUT]
                  [--loop] [-s|--src ARG] [-i|--interval INTERVAL]
   Command-line diagram generation.

Available options:
   -?,--help                Show this help text
   -w,--width WIDTH         Desired WIDTH of the output image
   -h,--height HEIGHT       Desired HEIGHT of the output image
   -o,--output OUTPUT       OUTPUT file
   -l,--loop                Run in a self-recompiling loop
   -s,--src ARG             Source file to watch
   -i,--interval INTERVAL   When running in a loop, check for changes every INTERVAL seconds.

For example, a couple common scenarios include

 $ ghc --make MyDiagram

# output image.png with a width of 400px (and auto-determined height)
 $ ./MyDiagram -o image.png -w 400

# output 200x200 dia.pdf, then watch for changes every 10 seconds
 $ ./MyDiagram -o dia.pdf -h 200 -w 200 -l -i 10

multiMain :: [(String, Diagram Cairo R2)] -> IO ()Source

multiMain is like defaultMain, except instead of a single diagram it takes a list of diagrams paired with names as input. The generated executable then takes a --selection option specifying the name of the diagram that should be rendered. The list of available diagrams may also be printed by passing the option --list.

Example usage:

 $ ghc --make MultiTest
 [1 of 1] Compiling Main             ( MultiTest.hs, MultiTest.o )
 Linking MultiTest ...
 $ ./MultiTest --list
 Available diagrams:
   foo bar
 $ ./MultiTest --selection bar -o Bar.png -w 200

animMain :: Animation Cairo R2 -> IO ()Source

animMain is like defaultMain, but renders an animation instead of a diagram. It takes as input an animation and produces a command-line program which will crudely "render" the animation by rendering one image for each frame, named by extending the given output file name by consecutive integers. For example if the given output file name is foo/blah.png, the frames will be saved in foo/blah001.png, foo/blah002.png, and so on (the number of padding digits used depends on the total number of frames). It is up to the user to take these images and stitch them together into an actual animation format (using, e.g. ffmpeg).

Of course, this is a rather crude method of rendering animations; more sophisticated methods will likely be added in the future.

The --fpu option can be used to control how many frames will be output for each second (unit time) of animation.

Backend tokens

data Cairo Source

This data declaration is simply used as a token to distinguish the cairo backend: (1) when calling functions where the type inference engine would otherwise have no way to know which backend you wanted to use, and (2) as an argument to the Backend and Renderable type classes.

type B = CairoSource