Skip to content

How to use backends

Tim Docker edited this page Aug 19, 2015 · 8 revisions

After writing your first chart you want to render it to some output. At the time of writing there are two backends to do so:

To use one of them you have to import their main module and call their rendering function runBackend. As a result you will get backend specific rendering instructions to use.

Usually runBackend function has two parameters. The first is a backend specific environment to configure the backend and the second is a ChartBackend instance that contains the rendering instructions to execute. The backend will provide a way to construct a environment for your needs. Cairo and Diagrams both offer a defaultEnv function for this purpose.

The environments usually needs to be configured with a AlignmentFns. They are used to realign lines and fills in a diagrams to pixels boundaries in case you render to a bitmap. Charts provides the two instances bitmapAlignmentFns and vectorAlignmentFns. Use the first when rendering to bitmaps (e.g. PNGs) and the second when rendering vector based graphics (e.g. SVG, EPS, PDF).

Examples

Chart-cairo

To use the Cairo backend use the following import:

import Graphics.Rendering.Chart.Backend.Cairo 

A configuration environment can be created using defaultEnv function. Afterwards you can call runBackend to create a Cairo Render instance from your ChartBackend.

defaultEnv :: AlignmentFns -> CEnv
runBackend :: CEnv -> ChartBackend a -> Graphics.Rendering.Cairo.Render a

But these are fairly low level functions that assume you want to be working with cairo output directly. As a convenience the module also offers some utilities to get started quickly:

data FileFormat = PNG | SVG | PS| PDF

data FileOptions = FileOptions {
  _fo_size :: (Int,Int),
  _fo_format :: FileFormat
}

renderableToFile :: FileOptions -> FilePath -> Renderable a -> IO (PickFn a)

FileOptions has a Default instance, so that renderableToFile def path r will produce a 800x600 PNG output file of the Renderable r. Generally chart are produced as Renderables, or there are appropriate conversion functions.

Have a look at this example to see how this works in action.

SVG files generated by the cairo backend embed glyph names that are generated within the cairo library. The SVG standard requires that these names be unique. Individual SVG files generated by cairo will meet this property. However if SVG files are composed to build a composite SVG image, or to build a single HTML file, this uniqueness property will not be met. To achieve this, some post processing of the SVG may be required.

Chart-diagrams

To use the Diagrams backend use the following import:

import Graphics.Rendering.Chart.Backend.Diagrams

A configuration environment can be created using defaultEnv function. Afterwards you can call runBackend to create a Cairo Diagram b R2 instance from your ChartBackend.

defaultEnv :: AlignmentFns -> Double -> Double -> IO (DEnv b)
runBackend :: (...) => DEnv (N b) -> ChartBackend a -> (D.QDiagram b V2 (N b) Any, a)

The width and height of the final output has to be supplied to defaultEnv. Creating an environment is a IO operation since this caches the available fonts for later (pure) use inside the produces diagram.

As a convenience the module also offers utilities to get started quickly:

runBackendR :: (...) => DEnv (N b) -> Renderable a -> (D.QDiagram b V2 (N b) Any, PickFn a)

data FileFormat = EPS| SVG | SVG_EMBEDDED

data FileOptions = FileOptions {
  _fo_size :: (Double,Double),
  _fo_format :: FileFormat,
  _fo_fonts :: IO (FontSelector Double)
}

renderableToFile :: FileOptions -> FilePath -> Renderable a -> IO (PickFn a)

Most of the time charts are produced in form of Renderables. This is why the utilities take a Renderable instead of a ChartBackend. FileOptions has a Default instance, such that renderableToFile def path r will write the given Renderable to a 800x600 svg file, with sans serif fonts.

Here is a complete example of how to use this backend:

import Graphics.Rendering.Chart 
import Graphics.Rendering.Chart.Backend.Diagrams
import Data.Default.Class
import Control.Lens
import System.Environment(getArgs)

chart = toRenderable layout 
  where
    values = [ ("Mexico City",19.2,e), ("Mumbai",12.9,e)
             , ("Sydney",4.3,e), ("London",8.3,e), ("New York",8.2,e1) ]
    e = 0
    e1 = 25
    pitem (s,v,o) = pitem_value .~ v
                  $ pitem_label .~ s
                  $ pitem_offset .~ o
                  $ def

    layout = pie_title .~ "Relative Population"
           $ pie_plot . pie_data .~ map pitem values
           $ def

main1 ["svg"] = renderableToFile def "example5.svg" chart
main1 ["eps"] = renderableToFile def{_fo_format=EPS} "example5.eps" chart

main = getArgs >>= main1
Clone this wiki locally