{-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleContexts #-} -- | This module provides efficient functions for rendering vector -- graphics to a number of formats, including EPS, PostScript, and -- PDF. It provides an abstraction for multi-page documents, as well -- as a set of graphics primitives for page descriptions. -- -- The graphics model is similar to that of the PostScript and PDF -- languages, but we only implement a subset of their functionality. -- Care has been taken that graphics rendering is done efficiently and -- as lazily as possible; documents are rendered \"on the fly\", -- without the need to store the whole document in memory. -- -- The provided document description model consists of two separate -- layers of abstraction: -- -- * /drawing/ is concerned with placing marks on a fixed surface, and -- takes place in the 'Draw' monad; -- -- * /document structure/ is concerned with a sequence of pages, their -- bounding boxes, and other meta-data. It takes place in the -- 'Document' monad. module Graphics.EasyRender ( -- * Types -- ** Coordinates X, Y, -- ** Color Color(..), -- ** Fonts Basefont(..), Font(..), nominalsize, text_width, -- ** Alignment Alignment, align_left, align_center, align_right, -- * The Document monad -- $DOCUMENTMODEL Document, newpage, newpage_defer, endpage, -- * The Draw monad -- $DRAWINGMODEL Draw, -- ** Path construction commands -- $PATHCONSTRUCTION newpath, moveto, lineto, curveto, closepath, arc, arc_append, oval, rectangle, -- ** Painting commands stroke, fill, fillstroke, -- ** Clipping path clip, -- ** Text commands textbox, -- ** Graphics parameters -- $GRAPHICSPARAMETERS setlinewidth, setcolor, -- ** Coordinate system -- $COORDINATESYSTEM translate, scale, -- ** Comments comment, -- ** Block structure -- $BLOCKSTRUCTURE block, -- * Backends -- $BACKENDS RenderFormat(..), render_stdout, render_file, render_string, -- * Customization -- $CUSTOMIZATION -- ** Custom drawing commands -- $CUSTOMCOMMANDS draw_subroutine, custom_ps, custom_pdf, custom_ascii, -- ** Customization interface Custom(..), custom, -- ** Customized rendering functions -- $CUSTOMRENDER render_custom_stdout, render_custom_file, render_custom_string, ) where import Graphics.EasyRender.Internal -- $DOCUMENTMODEL -- -- Document description takes place in the 'Document' monad. A basic -- multi-page document has the following structure: -- -- > document :: Document () -- > document = do -- > newpage x y $ do -- > <<>> -- > newpage x y $ do -- > <<>> -- > ... -- -- Here, each 'newpage' command describes one page of the -- document. The parameters /x/ and /y/ specify the dimensions of the -- page bounding box. They are expressed in units of PostScript -- points, i.e., multiples of 1/72 inch. -- -- Sometimes the bounding box for a page is not known until after the -- page content has been generated. For this purpose, we also provide -- the following alternative to the 'newpage' command: -- -- > newpage_defer $ do -- > <<>> -- > endpage x y -- -- It works just like the 'newpage' command, except that the bounding -- box is given at the end. -- $DRAWINGMODEL -- -- The description of the visible content of a page take place in the -- 'Draw' monad. It takes the form of a sequence of drawing commands, -- for example: -- -- > moveto 10 10 -- > lineto 10 100 -- > lineto 100 100 -- > lineto 100 10 -- > closepath -- > stroke -- -- The graphics model is similar to that of the PostScript and PDF -- languages. The basic concept is that of a /path/, which is a -- sequence of straight and curved line segments. Paths are first -- constructed using /path construction commands/, and then painted -- using /painting commands/, depending on a set of current -- /graphics parameters/ and a current /coordinate system/. -- -- We also provide block structure. Changes to the graphics state -- (color, coordinate system, etc.) that are done within a block are -- local to the block. -- -- > block $ do -- > <> -- $PATHCONSTRUCTION -- -- During path construction, there is a notion of /current path/ and -- /current point/. A path may consist of zero or more connected -- subpaths, and each subpath is either open or closed. -- $GRAPHICSPARAMETERS -- -- The painting commands rely on a set of graphics parameters. The -- graphics parameters are initially set to default values, and can be -- altered with the following commands. -- $COORDINATESYSTEM -- -- Coordinates, lengths, widths, etc, are all interpreted relative to -- a /current coordinate system/. The initial coordinate system of -- each page has the origin in the lower left corner, with each unit -- equaling one PostScript point (1/72 inch). The following commands -- can be used to change the current coordinate system. -- $BLOCKSTRUCTURE -- -- Drawing operations can be grouped into blocks with the 'block' -- operator. Changes to the graphics parameters and coordinate system -- are local to the block. It is undefined whether changes to the -- current path made within a block persist after the end of the block -- (they do in PDF, but not in PostScript). Therefore, path -- construction should not be broken up across end-of-block boundaries. -- $CUSTOMIZATION -- -- The document and drawing abstractions provided by this module are -- purposely kept general-purpose, and do not include -- application-specific features. However, we provide a mechanism by -- which applications can provide customized drawing commands and -- other custom features. -- $CUSTOMCOMMANDS -- -- It is sometimes useful to use customized drawing commands. For -- example, an application that draws many rectangles might like to -- define a custom 'rectangle' function for appending a rectangle to -- the current path. Of course this can be defined as an ordinary -- Haskell function, using elementary drawing commands: -- -- > my_rect :: X -> Y -> X -> Y -> Draw () -- > my_rect x0 y0 x1 y1 = do -- > moveto x0 y0 -- > lineto x0 y1 -- > lineto x1 y1 -- > lineto x1 y0 -- > closepath -- -- However, sometimes it is nice to make use of specialized abilities -- of individual backends. For example, PDF already has a built-in -- rectangle drawing command, and PostScript has the ability to define -- custom subroutines within the document text. Using these features -- can decrease the size of the generated documents. -- -- We therefore provide a facility for defining new drawing commands -- with backend-specific implementations. For example, a more general -- version of the above 'my_rect' function can be defined as -- follows: -- -- > my_rect :: X -> Y -> X -> Y -> Draw () -- > my_rect x0 y0 x1 y1 = draw_subroutine alt $ do -- > moveto x0 y0 -- > lineto x0 y1 -- > lineto x1 y1 -- > lineto x1 y0 -- > closepath -- > where -- > alt = [ -- > custom_ps $ printf "%f %f %f %f rect\n" x0 y0 x1 y1, -- > custom_pdf $ printf "%f %f %f %f re\n" x0 y0 (x1-x0) (y1-y0), -- > custom_ascii $ printf "My_rect %f %f %f %f\n" x0 y0 x1 y1 -- > ] -- -- The idea is to provide a default definition in terms of primitive -- drawing commands, as well as a list of various backend specific -- definitions. In the case of PostScript subroutines, the PostScript -- file must then also be supplied with a definition for the /rect/ -- subroutine, which can be done with the command 'render_ps_custom': -- -- > my_ps_defs = "/rect { ... } bind def\n" -- > -- > my_render_ps = render_ps_custom custom { ps_defs = my_ps_defs } -- -- Note that the 'draw_subroutine' customization mechanism is entirely -- optional. Its purpose is to generate shorter output for some -- backends; if it is omitted, the file may be be longer but should -- look the same. -- $BACKENDS -- -- The following commands can be used to render documents to various -- available formats. The available formats are PostScript, PDF, EPS, -- and an ASCII-based debugging format. Output can be written to -- standard output, to a file, or to a string. -- $CUSTOMRENDER -- -- The following are versions of the generic rendering functions that -- also take a customization data structure as an additional -- parameter.