packages feed

diagrams 0.1 → 0.2

raw patch · 11 files changed

+974/−1558 lines, 11 filesdep +colourdep +containers

Dependencies added: colour, containers

Files

+ CHANGELOG view
@@ -0,0 +1,14 @@+New in version 0.2:++  * rawCairo function for creating primitive diagrams from raw Cairo code+  * line join, cap, and dashing attributes+  * bouding box visualization functions for debugging+  * new padding and positioning combinators+  * PDF, PS, and SVG output+  * experimental tree layout+  * paths, polygons, bezier curves+  * create diagrams from text+  * render on top of arbitrary background images+  * depend on colour package instead of built-in colors+  * new examples: snellen, wordcloud, dragon+  * emptyPath and pathConcat
Graphics/Rendering/Diagrams.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -fno-warn-type-defaults #-} ----------------------------------------------------------------------------- -- | -- Module      :  Graphics.Rendering.Diagrams@@ -8,7 +9,8 @@ -- Portability :  portable -- -- An embedded domain-specific language (EDSL) for creating simple--- diagrams, built on top of the Cairo rendering engine.+-- diagrams, illustrations, and other types of graphics, built on top+-- of the Cairo rendering engine. -- ----------------------------------------------------------------------------- @@ -26,9 +28,17 @@   -- ** Shapes    , circle-  , poly   , rect+  , roundRect++  , regPolyPath+  , regPoly+  , rotRegPoly+   , shape+  , rawCairo+  , text+  , textPath    -- ** Spacers @@ -36,6 +46,18 @@   , vspace   , empty +  -- ** Paths++  , Path+  , emptyPath+  , pathFromVertices, pathFromVectors+  , pathConcat+  , closed, isClosed+  , rotPath++  , straight+  , curved+   -- * Combinators   -- $comb @@ -53,11 +75,23 @@   , hdistrib, vdistrib   , hdistribA, vdistribA +  , position, positionA+   , VAlignment   , top, vcenter, bottom   , HAlignment   , left, hcenter, right +  -- ** Complex layouts++  , tree++  -- ** Miscellaneous++  , pad, padA+  , showBBox, showBBoxes+  , withSize+   -- * Transformations   -- $transf @@ -70,64 +104,71 @@   -- * Attributes   -- $attr +  -- ** Colors+  -- $color++  , Color+  , module Data.Colour.Names   , fillColor, fc-  , fillTransparency, ft   , lineColor, lc++  -- ** Other attributes+   , lineWidth, lw -  , Color-  , rgb-  , rgba-  , module Graphics.Rendering.Diagrams.Colors+  , lineCap, LineCap(..)+  , lineJoin, LineJoin(..)+  , dashing +  , typeface, tf    -- * Rendering+  -- $render -  , renderToPng-  , compose+  , renderAs+  , OutputType(..)+  , SizeSpec(..)+  , renderOverPNG    ) where  import Graphics.Rendering.Diagrams.Types import Graphics.Rendering.Diagrams.Shapes+import Graphics.Rendering.Diagrams.Paths import Graphics.Rendering.Diagrams.Attributes-import Graphics.Rendering.Diagrams.Colors import Graphics.Rendering.Diagrams.Layouts import Graphics.Rendering.Diagrams.Engine+import Data.Colour.Names  {- $intro  "Graphics.Rendering.Diagrams" is an embedded domain-specific language-(EDSL) for creating simple diagrams.  It is compositional; starting+(EDSL) for creating simple graphics.  It is compositional; starting with some basic shapes, you can build up complex diagrams by combining simpler diagrams in various ways.  A few fundamental concepts to keep in mind:    * When constructing diagrams, there is no concept of an absolute-    coordinate system; everything is relative.  You cannot say \"this-    diagram should go at (2,1)\"; you can only say \"this diagram should-    go to the right of this other one\", or \"this diagram should go two-    units to the right and one unit above where it would otherwise-    be\".+    coordinate system, although each diagram does have a local+    coordinate system.    * Every diagram has an associated rectangular bounding box, which     determines its positioning and alignment relative to other     diagrams.  Usually this makes no difference but there are times-    when it's nice to be aware of it. For example, translating a+    when it\'s nice to be aware of it. For example, translating a     diagram works by moving the diagram relative to its bounding box;     positioning the bounding box where it would have gone means the-    diagram itself ends up elsewhere.  Also, some shapes have-    non-obvious bounding boxes; for example, regular polygons have a-    bounding box that fits their circumcircle.+    diagram itself ends up elsewhere.  To visualize bounding boxes,+    you can use the 'showBBox' and 'showBBoxes' functions. -  * The positive y-axis points downwards.+  * The positive y-axis points downwards.  This also means that+    positive rotations are clockwise. -For some simple examples, see-<http://byorgey.wordpress.com/2008/04/30/new-haskell-diagrams-library/>.+For some simple examples, see <http://code.haskell.org/diagrams/>.  Enjoy!  Please send comments, suggestions, bug reports, or patches to-byorgey at gmail dot com.+byorgey at cis dot upenn dot edu.  -} @@ -139,6 +180,10 @@ shape :: (ShapeClass s) => s -> Diagram shape = Prim . Shape +-- | Create text with black fill, no outline, and a default font.+text :: Double -> String -> Diagram+text sz str = fc black $ lw 0 $ textPath sz str+ -- | @hspace w@ is a 'Diagram' which produces no output but takes up --   @w@ amount of space horizontally.  Useful for manually creating --   horizontal separation between two diagrams.  A negative value@@ -160,23 +205,54 @@ empty :: Double -> Double -> Diagram empty w h = Sized (w, h) Empty +-- $comb+-- Various ways to combine 'Diagram's into larger 'Diagram's.+ -- $transf -- Various ways to modify and transform 'Diagram's. --- | XXX comment me+-- | Explicitly set a diagram's bounding box, by giving the+--   coordinates of the upper left and lower right corners (keeping in+--   mind that the positive y-axis points downwards).  Particularly+--   useful for applying to the top-level diagram in order to only+--   view a portion of it in the rendered output. view :: Point -> Point -> Diagram -> Diagram-view (x1,y1) (x2,y2) d = Sized (x2-x1, y2-y1) . translate ((x1-x2)/2) ((y1-y2)/2) $ d+view (x1,y1) (x2,y2) = Sized (x2-x1, y2-y1) . translate ((x1-x2)/2 - x1)+                                                        ((y1-y2)/2 - y1)  -- $attr -- Attributes which affect the way in which a 'Diagram' is rendered.--- For a large list of predefined 'Color' values, see--- "Graphics.Rendering.Diagrams.Colors". --- | Render a diagram to a file in PNG format.-renderToPng :: String     -- ^ The name of the file to create.-            -> Int        -- ^ The desired width of the image, in pixels.-            -> Int        -- ^ The desired height of the image.-            -> Diagram    -- ^ The diagram to render.-            -> IO ()-renderToPng name w h dia = writePng name w h $-                             compose (fromIntegral w) (fromIntegral h) dia+-- $color+-- Diagrams depends on the "Data.Colour" library (available on Hackage+-- as the \"colour\" package) for colo(u)r. Any functions expecting a+-- color can take any instance of the 'Color' type class, which has+-- instances for both the 'Data.Colour.Colour' and+-- 'Data.Colour.AlphaColour' types from "Data.Colour".+--+-- For normal use, you can just use color names from+-- "Data.Colour.Names", which is re-exported by+-- "Graphics.Rendering.Diagrams" for convenience. For more+-- sophisticated color manipulation, use the facilities provided by+-- the "Data.Colour" library.  For example, to create a color directly+-- from RGB values, you can use the @rgb@ function from+-- "Data.Colour.SRGB.Linear".++-- $render+-- Rendering diagrams to a file is accomplished with the 'renderAs'+-- function.  'renderOverPNG' also provides a specialized rendering+-- method, which overlays a rendererd diagram on top of an existing+-- PNG.++-- | Render a diagram to a file.+renderAs :: OutputType -- ^ The output type to use (PNG, PS, PDF, or SVG)+         -> String     -- ^ The name of the file to create.+         -> SizeSpec   -- ^ The desired width or height of the image.+         -> Diagram    -- ^ The diagram to render.+         -> IO ()+renderAs otype = renderWithBackend (chooseBackend otype)++-- | @renderOverPNG infile outfile d@ reads the PNG @infile@+--   and renders @d@ over this, saving the output as a PNG to @outfile@.+renderOverPNG :: FilePath -> FilePath -> Diagram -> IO ()+renderOverPNG srcfile dstfile dia = renderOverlayPNG srcfile dstfile dia
Graphics/Rendering/Diagrams/Attributes.hs view
@@ -12,11 +12,16 @@ -- ----------------------------------------------------------------------------- module Graphics.Rendering.Diagrams.Attributes-  ( fillColor, fc-  , fillTransparency, ft+  ( defaultAttributes+  , fillColor, fc   , lineColor, lc   , lineWidth, lw+  , lineCap, C.LineCap(..)+  , lineJoin, C.LineJoin(..)+  , dashing +  , typeface, tf+   , stretch, scale, scaleX, scaleY   , translate, translateX, translateY   , rotate, rotateR@@ -31,40 +36,38 @@ -- Fill color ----------------------  -- | Specify the default fill color for a 'Diagram'.-newtype Fill = Fill Color  deriving (Eq, Show, Read)+newtype Fill = Fill SomeColor instance AttrClass Fill where-  renderAttr (Fill f) = return (setEnvFillColor f)+  renderAttr (Fill (SomeColor f)) = return (setEnvFillColor f)  -- | Draw a diagram using the given fill color.  Note that the new --   color only applies to parts of the diagram which are not --   otherwise colored; subdiagrams which already have an explicit --   fill color will not be affected.  The default fill color is --   completely transparent.-fillColor :: Color -> Diagram -> Diagram-fillColor = Ann . Attr . Fill+fillColor :: Color c => c -> Diagram -> Diagram+fillColor = Ann . Attr . Fill . SomeColor  -- | 'fc' is provided as a convenient short synonym for 'fillColor'.-fc :: Color -> Diagram -> Diagram+fc :: Color c => c -> Diagram -> Diagram fc = fillColor -- -- Stroke color ----------------------  -- | Specify the default stroke color for a 'Diagram'.-newtype Stroke = Stroke Color  deriving (Eq, Show, Read)+newtype Stroke = Stroke SomeColor instance AttrClass Stroke where-  renderAttr (Stroke sc) = return (setEnvStrokeColor sc)+  renderAttr (Stroke (SomeColor sc)) = return (setEnvStrokeColor sc)  -- | Draw a diagram using the given color for lines.   Note that the new --   color only applies to parts of the diagram which are not --   otherwise colored; subdiagrams which already have an explicit --   line color will not be affected.  The default line color is black.-lineColor :: Color -> Diagram -> Diagram-lineColor = Ann . Attr . Stroke+lineColor :: Color c => c -> Diagram -> Diagram+lineColor = Ann . Attr . Stroke . SomeColor  -- | 'lc' is provided as a convenient short synonym for 'lineColor'.-lc :: Color -> Diagram -> Diagram+lc :: Color c => c -> Diagram -> Diagram lc = lineColor  @@ -90,32 +93,20 @@ lw :: Double -> Diagram -> Diagram lw = lineWidth ----- Transparency --------------------------------newtype FillTransparency = FT Double  deriving (Eq, Show, Read)-instance AttrClass FillTransparency where-  renderAttr (FT t) = return setFillAlpha-    where setFillAlpha env = env { envFillColor = newFillColor env }-          newFillColor env   = RGBA r g b t-            where (RGBA r g b _)     = envFillColor env+-- Fonts ----------------------------- --- XXX improve this -- currently, you have to put it AFTER the color!--- | Set the transparency used for the fill color, from 0 (completely---   transparent) to 255 (completely opaque).  Note that you can set---   the alpha channel of the fill color using 'fillColor' combined---   with 'rgba', but 'fillTransparency' allows you to set the alpha---   channel independently of the color channels.  This means you can---   use it together with the colors defined in---   "Graphics.Rendering.Diagrams.Colors".-fillTransparency :: Int -> Diagram -> Diagram-fillTransparency = Ann . Attr . FT . (/255) . fromIntegral+-- | Set the typeface for a text diagram+newtype Typeface = Typeface String deriving (Eq, Show, Read)+instance AttrClass Typeface where+  renderAttr (Typeface fontname) = c $ C.selectFontFace fontname C.FontSlantNormal C.FontWeightNormal >> return id --- | 'ft' is provided as a convenient short synonym for 'fillTransparency'.-ft = fillTransparency+-- | Change the default typeface to one named.+typeface :: String -> Diagram -> Diagram+typeface fontname = Ann (Attr (Typeface fontname)) --- XXX put a line transparency attribute here+-- | Convenience function to change the typeface.+tf :: String -> Diagram -> Diagram+tf = typeface  -- Rotate ---------------------------- @@ -167,7 +158,7 @@ --   respectively. newtype Scale = Scale Point  deriving (Eq, Show, Read) instance AttrClass Scale where-  attrSize (Scale k) s = k .* s+  attrSize (Scale k) s = k .*. s   renderAttr (Scale (x,y)) = c $ C.scale x y >> return id  -- | Stretch a diagram by a separate scaling factor for each axis.@@ -191,3 +182,49 @@ --   to @stretch 1 s@. scaleY :: Double -> Diagram -> Diagram scaleY sy = stretch 1 sy+++-- Stroke styles ----------------------------------++newtype LCap = LCap C.LineCap+instance AttrClass LCap where+  renderAttr (LCap lcap) = c $ C.setLineCap lcap >> return id++-- | Set the line cap style.  Valid values for 'LineCap' are+--   @LineCapButt@, @LineCapRound@, and @LineCapSquare@.+lineCap :: C.LineCap -> Diagram -> Diagram+lineCap = Ann . Attr . LCap++newtype LJoin = LJoin C.LineJoin+instance AttrClass LJoin where+  renderAttr (LJoin lj) = c $ C.setLineJoin lj >> return id++-- | Set the line join style.  Valid values for 'LineJoin' are+--   @LineJoinMiter@, @LineJoinRound@, and @LineJoinBevel@.+lineJoin :: C.LineJoin -> Diagram -> Diagram+lineJoin = Ann . Attr . LJoin++data Dashing = Dashing [Double] Double+instance AttrClass Dashing where+  renderAttr (Dashing ds offs) = c $ C.setDash ds offs >> return id++-- | Set the line dashing pattern.+dashing :: [Double]  -- ^ a list specifying alternate lengths of on+                     --   and off portions of the stroke.  The empty+                     --   list indicates no dashing.+        -> Double    -- ^ an offset into the dash pattern at which the+                     --   stroke should start+        -> Diagram -> Diagram+dashing ds offs = Ann (Attr (Dashing ds offs))++-- | Apply all the default attributes to a 'Diagram'.+defaultAttributes :: Diagram -> Diagram+defaultAttributes =+  case defaultDiaRenderEnv of+    (DREnv (SomeColor fillC) (SomeColor strokeC) strokeW) ->+      lc strokeC .+      lw strokeW .+      lineCap C.LineCapButt .+      lineJoin C.LineJoinMiter .+      dashing [] 0 .+      fc fillC
− Graphics/Rendering/Diagrams/Colors.hs
@@ -1,1338 +0,0 @@--------------------------------------------------------------------------------- |--- Module      :  Graphics.Rendering.Diagrams.Colors--- Copyright   :  (c) Brent Yorgey 2008--- License     :  BSD-style (see LICENSE)--- Maintainer  :  byorgey@gmail.com--- Stability   :  experimental--- Portability :  portable------ Convenient pre-defined colors for "Graphics.Rendering.Diagrams", an--- embedded domain-specific language (EDSL) for creating simple--- diagrams.  Color names and definitions pulled from X11\'s list of--- colors.----------------------------------------------------------------------------------module Graphics.Rendering.Diagrams.Colors where--import Graphics.Rendering.Diagrams.Types--rgb' :: Int -> Int -> Int -> Color-rgb' r g b = rgb (fromIntegral r / 255)-                 (fromIntegral g / 255)-                 (fromIntegral b / 255)--snow                 :: Color-snow                 =  rgb' 255 250 250-ghostWhite           :: Color-ghostWhite           =  rgb' 248 248 255-whiteSmoke           :: Color-whiteSmoke           =  rgb' 245 245 245-gainsboro            :: Color-gainsboro            =  rgb' 220 220 220-floralWhite          :: Color-floralWhite          =  rgb' 255 250 240-oldLace              :: Color-oldLace              =  rgb' 253 245 230-linen                :: Color-linen                =  rgb' 250 240 230-antiqueWhite         :: Color-antiqueWhite         =  rgb' 250 235 215-papayaWhip           :: Color-papayaWhip           =  rgb' 255 239 213-blanchedAlmond       :: Color-blanchedAlmond       =  rgb' 255 235 205-bisque               :: Color-bisque               =  rgb' 255 228 196-peachPuff            :: Color-peachPuff            =  rgb' 255 218 185-navajoWhite          :: Color-navajoWhite          =  rgb' 255 222 173-moccasin             :: Color-moccasin             =  rgb' 255 228 181-cornsilk             :: Color-cornsilk             =  rgb' 255 248 220-ivory                :: Color-ivory                =  rgb' 255 255 240-lemonChiffon         :: Color-lemonChiffon         =  rgb' 255 250 205-seashell             :: Color-seashell             =  rgb' 255 245 238-honeydew             :: Color-honeydew             =  rgb' 240 255 240-mintCream            :: Color-mintCream            =  rgb' 245 255 250-azure                :: Color-azure                =  rgb' 240 255 255-aliceBlue            :: Color-aliceBlue            =  rgb' 240 248 255-lavender             :: Color-lavender             =  rgb' 230 230 250-lavenderBlush        :: Color-lavenderBlush        =  rgb' 255 240 245-mistyRose            :: Color-mistyRose            =  rgb' 255 228 225-white                :: Color-white                =  rgb' 255 255 255-black                :: Color-black                =  rgb'   0   0   0-darkSlateGray        :: Color-darkSlateGray        =  rgb'  47  79  79-darkSlateGrey        :: Color-darkSlateGrey        =  rgb'  47  79  79-dimGray              :: Color-dimGray              =  rgb' 105 105 105-dimGrey              :: Color-dimGrey              =  rgb' 105 105 105-slateGray            :: Color-slateGray            =  rgb' 112 128 144-slateGrey            :: Color-slateGrey            =  rgb' 112 128 144-lightSlateGray       :: Color-lightSlateGray       =  rgb' 119 136 153-lightSlateGrey       :: Color-lightSlateGrey       =  rgb' 119 136 153-gray                 :: Color-gray                 =  rgb' 190 190 190-grey                 :: Color-grey                 =  rgb' 190 190 190-lightGrey            :: Color-lightGrey            =  rgb' 211 211 211-lightGray            :: Color-lightGray            =  rgb' 211 211 211-midnightBlue         :: Color-midnightBlue         =  rgb'  25  25 112-navy                 :: Color-navy                 =  rgb'   0   0 128-navyBlue             :: Color-navyBlue             =  rgb'   0   0 128-cornflowerBlue       :: Color-cornflowerBlue       =  rgb' 100 149 237-darkSlateBlue        :: Color-darkSlateBlue        =  rgb'  72  61 139-slateBlue            :: Color-slateBlue            =  rgb' 106  90 205-mediumSlateBlue      :: Color-mediumSlateBlue      =  rgb' 123 104 238-lightSlateBlue       :: Color-lightSlateBlue       =  rgb' 132 112 255-mediumBlue           :: Color-mediumBlue           =  rgb'   0   0 205-royalBlue            :: Color-royalBlue            =  rgb'  65 105 225-blue                 :: Color-blue                 =  rgb'   0   0 255-dodgerBlue           :: Color-dodgerBlue           =  rgb'  30 144 255-deepSkyBlue          :: Color-deepSkyBlue          =  rgb'   0 191 255-skyBlue              :: Color-skyBlue              =  rgb' 135 206 235-lightSkyBlue         :: Color-lightSkyBlue         =  rgb' 135 206 250-steelBlue            :: Color-steelBlue            =  rgb'  70 130 180-lightSteelBlue       :: Color-lightSteelBlue       =  rgb' 176 196 222-lightBlue            :: Color-lightBlue            =  rgb' 173 216 230-powderBlue           :: Color-powderBlue           =  rgb' 176 224 230-paleTurquoise        :: Color-paleTurquoise        =  rgb' 175 238 238-darkTurquoise        :: Color-darkTurquoise        =  rgb'   0 206 209-mediumTurquoise      :: Color-mediumTurquoise      =  rgb'  72 209 204-turquoise            :: Color-turquoise            =  rgb'  64 224 208-cyan                 :: Color-cyan                 =  rgb'   0 255 255-lightCyan            :: Color-lightCyan            =  rgb' 224 255 255-cadetBlue            :: Color-cadetBlue            =  rgb'  95 158 160-mediumAquamarine     :: Color-mediumAquamarine     =  rgb' 102 205 170-aquamarine           :: Color-aquamarine           =  rgb' 127 255 212-darkGreen            :: Color-darkGreen            =  rgb'   0 100   0-darkOliveGreen       :: Color-darkOliveGreen       =  rgb'  85 107  47-darkSeaGreen         :: Color-darkSeaGreen         =  rgb' 143 188 143-seaGreen             :: Color-seaGreen             =  rgb'  46 139  87-mediumSeaGreen       :: Color-mediumSeaGreen       =  rgb'  60 179 113-lightSeaGreen        :: Color-lightSeaGreen        =  rgb'  32 178 170-paleGreen            :: Color-paleGreen            =  rgb' 152 251 152-springGreen          :: Color-springGreen          =  rgb'   0 255 127-lawnGreen            :: Color-lawnGreen            =  rgb' 124 252   0-green                :: Color-green                =  rgb'   0 255   0-chartreuse           :: Color-chartreuse           =  rgb' 127 255   0-mediumSpringGreen    :: Color-mediumSpringGreen    =  rgb'   0 250 154-greenYellow          :: Color-greenYellow          =  rgb' 173 255  47-limeGreen            :: Color-limeGreen            =  rgb'  50 205  50-yellowGreen          :: Color-yellowGreen          =  rgb' 154 205  50-forestGreen          :: Color-forestGreen          =  rgb'  34 139  34-oliveDrab            :: Color-oliveDrab            =  rgb' 107 142  35-darkKhaki            :: Color-darkKhaki            =  rgb' 189 183 107-khaki                :: Color-khaki                =  rgb' 240 230 140-paleGoldenrod        :: Color-paleGoldenrod        =  rgb' 238 232 170-lightGoldenrodYellow :: Color-lightGoldenrodYellow =  rgb' 250 250 210-lightYellow          :: Color-lightYellow          =  rgb' 255 255 224-yellow               :: Color-yellow               =  rgb' 255 255   0-gold                 :: Color-gold                 =  rgb' 255 215   0-lightGoldenrod       :: Color-lightGoldenrod       =  rgb' 238 221 130-goldenrod            :: Color-goldenrod            =  rgb' 218 165  32-darkGoldenrod        :: Color-darkGoldenrod        =  rgb' 184 134  11-rosyBrown            :: Color-rosyBrown            =  rgb' 188 143 143-indianRed            :: Color-indianRed            =  rgb' 205  92  92-saddleBrown          :: Color-saddleBrown          =  rgb' 139  69  19-sienna               :: Color-sienna               =  rgb' 160  82  45-peru                 :: Color-peru                 =  rgb' 205 133  63-burlywood            :: Color-burlywood            =  rgb' 222 184 135-beige                :: Color-beige                =  rgb' 245 245 220-wheat                :: Color-wheat                =  rgb' 245 222 179-sandyBrown           :: Color-sandyBrown           =  rgb' 244 164  96-tan                  :: Color-tan                  =  rgb' 210 180 140-chocolate            :: Color-chocolate            =  rgb' 210 105  30-firebrick            :: Color-firebrick            =  rgb' 178  34  34-brown                :: Color-brown                =  rgb' 165  42  42-darkSalmon           :: Color-darkSalmon           =  rgb' 233 150 122-salmon               :: Color-salmon               =  rgb' 250 128 114-lightSalmon          :: Color-lightSalmon          =  rgb' 255 160 122-orange               :: Color-orange               =  rgb' 255 165   0-darkOrange           :: Color-darkOrange           =  rgb' 255 140   0-coral                :: Color-coral                =  rgb' 255 127  80-lightCoral           :: Color-lightCoral           =  rgb' 240 128 128-tomato               :: Color-tomato               =  rgb' 255  99  71-orangeRed            :: Color-orangeRed            =  rgb' 255  69   0-red                  :: Color-red                  =  rgb' 255   0   0-hotPink              :: Color-hotPink              =  rgb' 255 105 180-deepPink             :: Color-deepPink             =  rgb' 255  20 147-pink                 :: Color-pink                 =  rgb' 255 192 203-lightPink            :: Color-lightPink            =  rgb' 255 182 193-paleVioletRed        :: Color-paleVioletRed        =  rgb' 219 112 147-maroon               :: Color-maroon               =  rgb' 176  48  96-mediumVioletRed      :: Color-mediumVioletRed      =  rgb' 199  21 133-violetRed            :: Color-violetRed            =  rgb' 208  32 144-magenta              :: Color-magenta              =  rgb' 255   0 255-violet               :: Color-violet               =  rgb' 238 130 238-plum                 :: Color-plum                 =  rgb' 221 160 221-orchid               :: Color-orchid               =  rgb' 218 112 214-mediumOrchid         :: Color-mediumOrchid         =  rgb' 186  85 211-darkOrchid           :: Color-darkOrchid           =  rgb' 153  50 204-darkViolet           :: Color-darkViolet           =  rgb' 148   0 211-blueViolet           :: Color-blueViolet           =  rgb' 138  43 226-purple               :: Color-purple               =  rgb' 160  32 240-mediumPurple         :: Color-mediumPurple         =  rgb' 147 112 219-thistle              :: Color-thistle              =  rgb' 216 191 216-snow1                :: Color-snow1                =  rgb' 255 250 250-snow2                :: Color-snow2                =  rgb' 238 233 233-snow3                :: Color-snow3                =  rgb' 205 201 201-snow4                :: Color-snow4                =  rgb' 139 137 137-seashell1            :: Color-seashell1            =  rgb' 255 245 238-seashell2            :: Color-seashell2            =  rgb' 238 229 222-seashell3            :: Color-seashell3            =  rgb' 205 197 191-seashell4            :: Color-seashell4            =  rgb' 139 134 130-antiqueWhite1        :: Color-antiqueWhite1        =  rgb' 255 239 219-antiqueWhite2        :: Color-antiqueWhite2        =  rgb' 238 223 204-antiqueWhite3        :: Color-antiqueWhite3        =  rgb' 205 192 176-antiqueWhite4        :: Color-antiqueWhite4        =  rgb' 139 131 120-bisque1              :: Color-bisque1              =  rgb' 255 228 196-bisque2              :: Color-bisque2              =  rgb' 238 213 183-bisque3              :: Color-bisque3              =  rgb' 205 183 158-bisque4              :: Color-bisque4              =  rgb' 139 125 107-peachPuff1           :: Color-peachPuff1           =  rgb' 255 218 185-peachPuff2           :: Color-peachPuff2           =  rgb' 238 203 173-peachPuff3           :: Color-peachPuff3           =  rgb' 205 175 149-peachPuff4           :: Color-peachPuff4           =  rgb' 139 119 101-navajoWhite1         :: Color-navajoWhite1         =  rgb' 255 222 173-navajoWhite2         :: Color-navajoWhite2         =  rgb' 238 207 161-navajoWhite3         :: Color-navajoWhite3         =  rgb' 205 179 139-navajoWhite4         :: Color-navajoWhite4         =  rgb' 139 121  94-lemonChiffon1        :: Color-lemonChiffon1        =  rgb' 255 250 205-lemonChiffon2        :: Color-lemonChiffon2        =  rgb' 238 233 191-lemonChiffon3        :: Color-lemonChiffon3        =  rgb' 205 201 165-lemonChiffon4        :: Color-lemonChiffon4        =  rgb' 139 137 112-cornsilk1            :: Color-cornsilk1            =  rgb' 255 248 220-cornsilk2            :: Color-cornsilk2            =  rgb' 238 232 205-cornsilk3            :: Color-cornsilk3            =  rgb' 205 200 177-cornsilk4            :: Color-cornsilk4            =  rgb' 139 136 120-ivory1               :: Color-ivory1               =  rgb' 255 255 240-ivory2               :: Color-ivory2               =  rgb' 238 238 224-ivory3               :: Color-ivory3               =  rgb' 205 205 193-ivory4               :: Color-ivory4               =  rgb' 139 139 131-honeydew1            :: Color-honeydew1            =  rgb' 240 255 240-honeydew2            :: Color-honeydew2            =  rgb' 224 238 224-honeydew3            :: Color-honeydew3            =  rgb' 193 205 193-honeydew4            :: Color-honeydew4            =  rgb' 131 139 131-lavenderBlush1       :: Color-lavenderBlush1       =  rgb' 255 240 245-lavenderBlush2       :: Color-lavenderBlush2       =  rgb' 238 224 229-lavenderBlush3       :: Color-lavenderBlush3       =  rgb' 205 193 197-lavenderBlush4       :: Color-lavenderBlush4       =  rgb' 139 131 134-mistyRose1           :: Color-mistyRose1           =  rgb' 255 228 225-mistyRose2           :: Color-mistyRose2           =  rgb' 238 213 210-mistyRose3           :: Color-mistyRose3           =  rgb' 205 183 181-mistyRose4           :: Color-mistyRose4           =  rgb' 139 125 123-azure1               :: Color-azure1               =  rgb' 240 255 255-azure2               :: Color-azure2               =  rgb' 224 238 238-azure3               :: Color-azure3               =  rgb' 193 205 205-azure4               :: Color-azure4               =  rgb' 131 139 139-slateBlue1           :: Color-slateBlue1           =  rgb' 131 111 255-slateBlue2           :: Color-slateBlue2           =  rgb' 122 103 238-slateBlue3           :: Color-slateBlue3           =  rgb' 105  89 205-slateBlue4           :: Color-slateBlue4           =  rgb'  71  60 139-royalBlue1           :: Color-royalBlue1           =  rgb'  72 118 255-royalBlue2           :: Color-royalBlue2           =  rgb'  67 110 238-royalBlue3           :: Color-royalBlue3           =  rgb'  58  95 205-royalBlue4           :: Color-royalBlue4           =  rgb'  39  64 139-blue1                :: Color-blue1                =  rgb'   0   0 255-blue2                :: Color-blue2                =  rgb'   0   0 238-blue3                :: Color-blue3                =  rgb'   0   0 205-blue4                :: Color-blue4                =  rgb'   0   0 139-dodgerBlue1          :: Color-dodgerBlue1          =  rgb'  30 144 255-dodgerBlue2          :: Color-dodgerBlue2          =  rgb'  28 134 238-dodgerBlue3          :: Color-dodgerBlue3          =  rgb'  24 116 205-dodgerBlue4          :: Color-dodgerBlue4          =  rgb'  16  78 139-steelBlue1           :: Color-steelBlue1           =  rgb'  99 184 255-steelBlue2           :: Color-steelBlue2           =  rgb'  92 172 238-steelBlue3           :: Color-steelBlue3           =  rgb'  79 148 205-steelBlue4           :: Color-steelBlue4           =  rgb'  54 100 139-deepSkyBlue1         :: Color-deepSkyBlue1         =  rgb'   0 191 255-deepSkyBlue2         :: Color-deepSkyBlue2         =  rgb'   0 178 238-deepSkyBlue3         :: Color-deepSkyBlue3         =  rgb'   0 154 205-deepSkyBlue4         :: Color-deepSkyBlue4         =  rgb'   0 104 139-skyBlue1             :: Color-skyBlue1             =  rgb' 135 206 255-skyBlue2             :: Color-skyBlue2             =  rgb' 126 192 238-skyBlue3             :: Color-skyBlue3             =  rgb' 108 166 205-skyBlue4             :: Color-skyBlue4             =  rgb'  74 112 139-lightSkyBlue1        :: Color-lightSkyBlue1        =  rgb' 176 226 255-lightSkyBlue2        :: Color-lightSkyBlue2        =  rgb' 164 211 238-lightSkyBlue3        :: Color-lightSkyBlue3        =  rgb' 141 182 205-lightSkyBlue4        :: Color-lightSkyBlue4        =  rgb'  96 123 139-slateGray1           :: Color-slateGray1           =  rgb' 198 226 255-slateGray2           :: Color-slateGray2           =  rgb' 185 211 238-slateGray3           :: Color-slateGray3           =  rgb' 159 182 205-slateGray4           :: Color-slateGray4           =  rgb' 108 123 139-lightSteelBlue1      :: Color-lightSteelBlue1      =  rgb' 202 225 255-lightSteelBlue2      :: Color-lightSteelBlue2      =  rgb' 188 210 238-lightSteelBlue3      :: Color-lightSteelBlue3      =  rgb' 162 181 205-lightSteelBlue4      :: Color-lightSteelBlue4      =  rgb' 110 123 139-lightBlue1           :: Color-lightBlue1           =  rgb' 191 239 255-lightBlue2           :: Color-lightBlue2           =  rgb' 178 223 238-lightBlue3           :: Color-lightBlue3           =  rgb' 154 192 205-lightBlue4           :: Color-lightBlue4           =  rgb' 104 131 139-lightCyan1           :: Color-lightCyan1           =  rgb' 224 255 255-lightCyan2           :: Color-lightCyan2           =  rgb' 209 238 238-lightCyan3           :: Color-lightCyan3           =  rgb' 180 205 205-lightCyan4           :: Color-lightCyan4           =  rgb' 122 139 139-paleTurquoise1       :: Color-paleTurquoise1       =  rgb' 187 255 255-paleTurquoise2       :: Color-paleTurquoise2       =  rgb' 174 238 238-paleTurquoise3       :: Color-paleTurquoise3       =  rgb' 150 205 205-paleTurquoise4       :: Color-paleTurquoise4       =  rgb' 102 139 139-cadetBlue1           :: Color-cadetBlue1           =  rgb' 152 245 255-cadetBlue2           :: Color-cadetBlue2           =  rgb' 142 229 238-cadetBlue3           :: Color-cadetBlue3           =  rgb' 122 197 205-cadetBlue4           :: Color-cadetBlue4           =  rgb'  83 134 139-turquoise1           :: Color-turquoise1           =  rgb'   0 245 255-turquoise2           :: Color-turquoise2           =  rgb'   0 229 238-turquoise3           :: Color-turquoise3           =  rgb'   0 197 205-turquoise4           :: Color-turquoise4           =  rgb'   0 134 139-cyan1                :: Color-cyan1                =  rgb'   0 255 255-cyan2                :: Color-cyan2                =  rgb'   0 238 238-cyan3                :: Color-cyan3                =  rgb'   0 205 205-cyan4                :: Color-cyan4                =  rgb'   0 139 139-darkSlateGray1       :: Color-darkSlateGray1       =  rgb' 151 255 255-darkSlateGray2       :: Color-darkSlateGray2       =  rgb' 141 238 238-darkSlateGray3       :: Color-darkSlateGray3       =  rgb' 121 205 205-darkSlateGray4       :: Color-darkSlateGray4       =  rgb'  82 139 139-aquamarine1          :: Color-aquamarine1          =  rgb' 127 255 212-aquamarine2          :: Color-aquamarine2          =  rgb' 118 238 198-aquamarine3          :: Color-aquamarine3          =  rgb' 102 205 170-aquamarine4          :: Color-aquamarine4          =  rgb'  69 139 116-darkSeaGreen1        :: Color-darkSeaGreen1        =  rgb' 193 255 193-darkSeaGreen2        :: Color-darkSeaGreen2        =  rgb' 180 238 180-darkSeaGreen3        :: Color-darkSeaGreen3        =  rgb' 155 205 155-darkSeaGreen4        :: Color-darkSeaGreen4        =  rgb' 105 139 105-seaGreen1            :: Color-seaGreen1            =  rgb'  84 255 159-seaGreen2            :: Color-seaGreen2            =  rgb'  78 238 148-seaGreen3            :: Color-seaGreen3            =  rgb'  67 205 128-seaGreen4            :: Color-seaGreen4            =  rgb'  46 139  87-paleGreen1           :: Color-paleGreen1           =  rgb' 154 255 154-paleGreen2           :: Color-paleGreen2           =  rgb' 144 238 144-paleGreen3           :: Color-paleGreen3           =  rgb' 124 205 124-paleGreen4           :: Color-paleGreen4           =  rgb'  84 139  84-springGreen1         :: Color-springGreen1         =  rgb'   0 255 127-springGreen2         :: Color-springGreen2         =  rgb'   0 238 118-springGreen3         :: Color-springGreen3         =  rgb'   0 205 102-springGreen4         :: Color-springGreen4         =  rgb'   0 139  69-green1               :: Color-green1               =  rgb'   0 255   0-green2               :: Color-green2               =  rgb'   0 238   0-green3               :: Color-green3               =  rgb'   0 205   0-green4               :: Color-green4               =  rgb'   0 139   0-chartreuse1          :: Color-chartreuse1          =  rgb' 127 255   0-chartreuse2          :: Color-chartreuse2          =  rgb' 118 238   0-chartreuse3          :: Color-chartreuse3          =  rgb' 102 205   0-chartreuse4          :: Color-chartreuse4          =  rgb'  69 139   0-oliveDrab1           :: Color-oliveDrab1           =  rgb' 192 255  62-oliveDrab2           :: Color-oliveDrab2           =  rgb' 179 238  58-oliveDrab3           :: Color-oliveDrab3           =  rgb' 154 205  50-oliveDrab4           :: Color-oliveDrab4           =  rgb' 105 139  34-darkOliveGreen1      :: Color-darkOliveGreen1      =  rgb' 202 255 112-darkOliveGreen2      :: Color-darkOliveGreen2      =  rgb' 188 238 104-darkOliveGreen3      :: Color-darkOliveGreen3      =  rgb' 162 205  90-darkOliveGreen4      :: Color-darkOliveGreen4      =  rgb' 110 139  61-khaki1               :: Color-khaki1               =  rgb' 255 246 143-khaki2               :: Color-khaki2               =  rgb' 238 230 133-khaki3               :: Color-khaki3               =  rgb' 205 198 115-khaki4               :: Color-khaki4               =  rgb' 139 134  78-lightGoldenrod1      :: Color-lightGoldenrod1      =  rgb' 255 236 139-lightGoldenrod2      :: Color-lightGoldenrod2      =  rgb' 238 220 130-lightGoldenrod3      :: Color-lightGoldenrod3      =  rgb' 205 190 112-lightGoldenrod4      :: Color-lightGoldenrod4      =  rgb' 139 129  76-lightYellow1         :: Color-lightYellow1         =  rgb' 255 255 224-lightYellow2         :: Color-lightYellow2         =  rgb' 238 238 209-lightYellow3         :: Color-lightYellow3         =  rgb' 205 205 180-lightYellow4         :: Color-lightYellow4         =  rgb' 139 139 122-yellow1              :: Color-yellow1              =  rgb' 255 255   0-yellow2              :: Color-yellow2              =  rgb' 238 238   0-yellow3              :: Color-yellow3              =  rgb' 205 205   0-yellow4              :: Color-yellow4              =  rgb' 139 139   0-gold1                :: Color-gold1                =  rgb' 255 215   0-gold2                :: Color-gold2                =  rgb' 238 201   0-gold3                :: Color-gold3                =  rgb' 205 173   0-gold4                :: Color-gold4                =  rgb' 139 117   0-goldenrod1           :: Color-goldenrod1           =  rgb' 255 193  37-goldenrod2           :: Color-goldenrod2           =  rgb' 238 180  34-goldenrod3           :: Color-goldenrod3           =  rgb' 205 155  29-goldenrod4           :: Color-goldenrod4           =  rgb' 139 105  20-darkGoldenrod1       :: Color-darkGoldenrod1       =  rgb' 255 185  15-darkGoldenrod2       :: Color-darkGoldenrod2       =  rgb' 238 173  14-darkGoldenrod3       :: Color-darkGoldenrod3       =  rgb' 205 149  12-darkGoldenrod4       :: Color-darkGoldenrod4       =  rgb' 139 101   8-rosyBrown1           :: Color-rosyBrown1           =  rgb' 255 193 193-rosyBrown2           :: Color-rosyBrown2           =  rgb' 238 180 180-rosyBrown3           :: Color-rosyBrown3           =  rgb' 205 155 155-rosyBrown4           :: Color-rosyBrown4           =  rgb' 139 105 105-indianRed1           :: Color-indianRed1           =  rgb' 255 106 106-indianRed2           :: Color-indianRed2           =  rgb' 238  99  99-indianRed3           :: Color-indianRed3           =  rgb' 205  85  85-indianRed4           :: Color-indianRed4           =  rgb' 139  58  58-sienna1              :: Color-sienna1              =  rgb' 255 130  71-sienna2              :: Color-sienna2              =  rgb' 238 121  66-sienna3              :: Color-sienna3              =  rgb' 205 104  57-sienna4              :: Color-sienna4              =  rgb' 139  71  38-burlywood1           :: Color-burlywood1           =  rgb' 255 211 155-burlywood2           :: Color-burlywood2           =  rgb' 238 197 145-burlywood3           :: Color-burlywood3           =  rgb' 205 170 125-burlywood4           :: Color-burlywood4           =  rgb' 139 115  85-wheat1               :: Color-wheat1               =  rgb' 255 231 186-wheat2               :: Color-wheat2               =  rgb' 238 216 174-wheat3               :: Color-wheat3               =  rgb' 205 186 150-wheat4               :: Color-wheat4               =  rgb' 139 126 102-tan1                 :: Color-tan1                 =  rgb' 255 165  79-tan2                 :: Color-tan2                 =  rgb' 238 154  73-tan3                 :: Color-tan3                 =  rgb' 205 133  63-tan4                 :: Color-tan4                 =  rgb' 139  90  43-chocolate1           :: Color-chocolate1           =  rgb' 255 127  36-chocolate2           :: Color-chocolate2           =  rgb' 238 118  33-chocolate3           :: Color-chocolate3           =  rgb' 205 102  29-chocolate4           :: Color-chocolate4           =  rgb' 139  69  19-firebrick1           :: Color-firebrick1           =  rgb' 255  48  48-firebrick2           :: Color-firebrick2           =  rgb' 238  44  44-firebrick3           :: Color-firebrick3           =  rgb' 205  38  38-firebrick4           :: Color-firebrick4           =  rgb' 139  26  26-brown1               :: Color-brown1               =  rgb' 255  64  64-brown2               :: Color-brown2               =  rgb' 238  59  59-brown3               :: Color-brown3               =  rgb' 205  51  51-brown4               :: Color-brown4               =  rgb' 139  35  35-salmon1              :: Color-salmon1              =  rgb' 255 140 105-salmon2              :: Color-salmon2              =  rgb' 238 130  98-salmon3              :: Color-salmon3              =  rgb' 205 112  84-salmon4              :: Color-salmon4              =  rgb' 139  76  57-lightSalmon1         :: Color-lightSalmon1         =  rgb' 255 160 122-lightSalmon2         :: Color-lightSalmon2         =  rgb' 238 149 114-lightSalmon3         :: Color-lightSalmon3         =  rgb' 205 129  98-lightSalmon4         :: Color-lightSalmon4         =  rgb' 139  87  66-orange1              :: Color-orange1              =  rgb' 255 165   0-orange2              :: Color-orange2              =  rgb' 238 154   0-orange3              :: Color-orange3              =  rgb' 205 133   0-orange4              :: Color-orange4              =  rgb' 139  90   0-darkOrange1          :: Color-darkOrange1          =  rgb' 255 127   0-darkOrange2          :: Color-darkOrange2          =  rgb' 238 118   0-darkOrange3          :: Color-darkOrange3          =  rgb' 205 102   0-darkOrange4          :: Color-darkOrange4          =  rgb' 139  69   0-coral1               :: Color-coral1               =  rgb' 255 114  86-coral2               :: Color-coral2               =  rgb' 238 106  80-coral3               :: Color-coral3               =  rgb' 205  91  69-coral4               :: Color-coral4               =  rgb' 139  62  47-tomato1              :: Color-tomato1              =  rgb' 255  99  71-tomato2              :: Color-tomato2              =  rgb' 238  92  66-tomato3              :: Color-tomato3              =  rgb' 205  79  57-tomato4              :: Color-tomato4              =  rgb' 139  54  38-orangeRed1           :: Color-orangeRed1           =  rgb' 255  69   0-orangeRed2           :: Color-orangeRed2           =  rgb' 238  64   0-orangeRed3           :: Color-orangeRed3           =  rgb' 205  55   0-orangeRed4           :: Color-orangeRed4           =  rgb' 139  37   0-red1                 :: Color-red1                 =  rgb' 255   0   0-red2                 :: Color-red2                 =  rgb' 238   0   0-red3                 :: Color-red3                 =  rgb' 205   0   0-red4                 :: Color-red4                 =  rgb' 139   0   0-deepPink1            :: Color-deepPink1            =  rgb' 255  20 147-deepPink2            :: Color-deepPink2            =  rgb' 238  18 137-deepPink3            :: Color-deepPink3            =  rgb' 205  16 118-deepPink4            :: Color-deepPink4            =  rgb' 139  10  80-hotPink1             :: Color-hotPink1             =  rgb' 255 110 180-hotPink2             :: Color-hotPink2             =  rgb' 238 106 167-hotPink3             :: Color-hotPink3             =  rgb' 205  96 144-hotPink4             :: Color-hotPink4             =  rgb' 139  58  98-pink1                :: Color-pink1                =  rgb' 255 181 197-pink2                :: Color-pink2                =  rgb' 238 169 184-pink3                :: Color-pink3                =  rgb' 205 145 158-pink4                :: Color-pink4                =  rgb' 139  99 108-lightPink1           :: Color-lightPink1           =  rgb' 255 174 185-lightPink2           :: Color-lightPink2           =  rgb' 238 162 173-lightPink3           :: Color-lightPink3           =  rgb' 205 140 149-lightPink4           :: Color-lightPink4           =  rgb' 139  95 101-paleVioletRed1       :: Color-paleVioletRed1       =  rgb' 255 130 171-paleVioletRed2       :: Color-paleVioletRed2       =  rgb' 238 121 159-paleVioletRed3       :: Color-paleVioletRed3       =  rgb' 205 104 137-paleVioletRed4       :: Color-paleVioletRed4       =  rgb' 139  71  93-maroon1              :: Color-maroon1              =  rgb' 255  52 179-maroon2              :: Color-maroon2              =  rgb' 238  48 167-maroon3              :: Color-maroon3              =  rgb' 205  41 144-maroon4              :: Color-maroon4              =  rgb' 139  28  98-violetRed1           :: Color-violetRed1           =  rgb' 255  62 150-violetRed2           :: Color-violetRed2           =  rgb' 238  58 140-violetRed3           :: Color-violetRed3           =  rgb' 205  50 120-violetRed4           :: Color-violetRed4           =  rgb' 139  34  82-magenta1             :: Color-magenta1             =  rgb' 255   0 255-magenta2             :: Color-magenta2             =  rgb' 238   0 238-magenta3             :: Color-magenta3             =  rgb' 205   0 205-magenta4             :: Color-magenta4             =  rgb' 139   0 139-orchid1              :: Color-orchid1              =  rgb' 255 131 250-orchid2              :: Color-orchid2              =  rgb' 238 122 233-orchid3              :: Color-orchid3              =  rgb' 205 105 201-orchid4              :: Color-orchid4              =  rgb' 139  71 137-plum1                :: Color-plum1                =  rgb' 255 187 255-plum2                :: Color-plum2                =  rgb' 238 174 238-plum3                :: Color-plum3                =  rgb' 205 150 205-plum4                :: Color-plum4                =  rgb' 139 102 139-mediumOrchid1        :: Color-mediumOrchid1        =  rgb' 224 102 255-mediumOrchid2        :: Color-mediumOrchid2        =  rgb' 209  95 238-mediumOrchid3        :: Color-mediumOrchid3        =  rgb' 180  82 205-mediumOrchid4        :: Color-mediumOrchid4        =  rgb' 122  55 139-darkOrchid1          :: Color-darkOrchid1          =  rgb' 191  62 255-darkOrchid2          :: Color-darkOrchid2          =  rgb' 178  58 238-darkOrchid3          :: Color-darkOrchid3          =  rgb' 154  50 205-darkOrchid4          :: Color-darkOrchid4          =  rgb' 104  34 139-purple1              :: Color-purple1              =  rgb' 155  48 255-purple2              :: Color-purple2              =  rgb' 145  44 238-purple3              :: Color-purple3              =  rgb' 125  38 205-purple4              :: Color-purple4              =  rgb'  85  26 139-mediumPurple1        :: Color-mediumPurple1        =  rgb' 171 130 255-mediumPurple2        :: Color-mediumPurple2        =  rgb' 159 121 238-mediumPurple3        :: Color-mediumPurple3        =  rgb' 137 104 205-mediumPurple4        :: Color-mediumPurple4        =  rgb'  93  71 139-thistle1             :: Color-thistle1             =  rgb' 255 225 255-thistle2             :: Color-thistle2             =  rgb' 238 210 238-thistle3             :: Color-thistle3             =  rgb' 205 181 205-thistle4             :: Color-thistle4             =  rgb' 139 123 139-gray0                :: Color-gray0                =  rgb'   0   0   0-grey0                :: Color-grey0                =  rgb'   0   0   0-gray1                :: Color-gray1                =  rgb'   3   3   3-grey1                :: Color-grey1                =  rgb'   3   3   3-gray2                :: Color-gray2                =  rgb'   5   5   5-grey2                :: Color-grey2                =  rgb'   5   5   5-gray3                :: Color-gray3                =  rgb'   8   8   8-grey3                :: Color-grey3                =  rgb'   8   8   8-gray4                :: Color-gray4                =  rgb'  10  10  10-grey4                :: Color-grey4                =  rgb'  10  10  10-gray5                :: Color-gray5                =  rgb'  13  13  13-grey5                :: Color-grey5                =  rgb'  13  13  13-gray6                :: Color-gray6                =  rgb'  15  15  15-grey6                :: Color-grey6                =  rgb'  15  15  15-gray7                :: Color-gray7                =  rgb'  18  18  18-grey7                :: Color-grey7                =  rgb'  18  18  18-gray8                :: Color-gray8                =  rgb'  20  20  20-grey8                :: Color-grey8                =  rgb'  20  20  20-gray9                :: Color-gray9                =  rgb'  23  23  23-grey9                :: Color-grey9                =  rgb'  23  23  23-gray10               :: Color-gray10               =  rgb'  26  26  26-grey10               :: Color-grey10               =  rgb'  26  26  26-gray11               :: Color-gray11               =  rgb'  28  28  28-grey11               :: Color-grey11               =  rgb'  28  28  28-gray12               :: Color-gray12               =  rgb'  31  31  31-grey12               :: Color-grey12               =  rgb'  31  31  31-gray13               :: Color-gray13               =  rgb'  33  33  33-grey13               :: Color-grey13               =  rgb'  33  33  33-gray14               :: Color-gray14               =  rgb'  36  36  36-grey14               :: Color-grey14               =  rgb'  36  36  36-gray15               :: Color-gray15               =  rgb'  38  38  38-grey15               :: Color-grey15               =  rgb'  38  38  38-gray16               :: Color-gray16               =  rgb'  41  41  41-grey16               :: Color-grey16               =  rgb'  41  41  41-gray17               :: Color-gray17               =  rgb'  43  43  43-grey17               :: Color-grey17               =  rgb'  43  43  43-gray18               :: Color-gray18               =  rgb'  46  46  46-grey18               :: Color-grey18               =  rgb'  46  46  46-gray19               :: Color-gray19               =  rgb'  48  48  48-grey19               :: Color-grey19               =  rgb'  48  48  48-gray20               :: Color-gray20               =  rgb'  51  51  51-grey20               :: Color-grey20               =  rgb'  51  51  51-gray21               :: Color-gray21               =  rgb'  54  54  54-grey21               :: Color-grey21               =  rgb'  54  54  54-gray22               :: Color-gray22               =  rgb'  56  56  56-grey22               :: Color-grey22               =  rgb'  56  56  56-gray23               :: Color-gray23               =  rgb'  59  59  59-grey23               :: Color-grey23               =  rgb'  59  59  59-gray24               :: Color-gray24               =  rgb'  61  61  61-grey24               :: Color-grey24               =  rgb'  61  61  61-gray25               :: Color-gray25               =  rgb'  64  64  64-grey25               :: Color-grey25               =  rgb'  64  64  64-gray26               :: Color-gray26               =  rgb'  66  66  66-grey26               :: Color-grey26               =  rgb'  66  66  66-gray27               :: Color-gray27               =  rgb'  69  69  69-grey27               :: Color-grey27               =  rgb'  69  69  69-gray28               :: Color-gray28               =  rgb'  71  71  71-grey28               :: Color-grey28               =  rgb'  71  71  71-gray29               :: Color-gray29               =  rgb'  74  74  74-grey29               :: Color-grey29               =  rgb'  74  74  74-gray30               :: Color-gray30               =  rgb'  77  77  77-grey30               :: Color-grey30               =  rgb'  77  77  77-gray31               :: Color-gray31               =  rgb'  79  79  79-grey31               :: Color-grey31               =  rgb'  79  79  79-gray32               :: Color-gray32               =  rgb'  82  82  82-grey32               :: Color-grey32               =  rgb'  82  82  82-gray33               :: Color-gray33               =  rgb'  84  84  84-grey33               :: Color-grey33               =  rgb'  84  84  84-gray34               :: Color-gray34               =  rgb'  87  87  87-grey34               :: Color-grey34               =  rgb'  87  87  87-gray35               :: Color-gray35               =  rgb'  89  89  89-grey35               :: Color-grey35               =  rgb'  89  89  89-gray36               :: Color-gray36               =  rgb'  92  92  92-grey36               :: Color-grey36               =  rgb'  92  92  92-gray37               :: Color-gray37               =  rgb'  94  94  94-grey37               :: Color-grey37               =  rgb'  94  94  94-gray38               :: Color-gray38               =  rgb'  97  97  97-grey38               :: Color-grey38               =  rgb'  97  97  97-gray39               :: Color-gray39               =  rgb'  99  99  99-grey39               :: Color-grey39               =  rgb'  99  99  99-gray40               :: Color-gray40               =  rgb' 102 102 102-grey40               :: Color-grey40               =  rgb' 102 102 102-gray41               :: Color-gray41               =  rgb' 105 105 105-grey41               :: Color-grey41               =  rgb' 105 105 105-gray42               :: Color-gray42               =  rgb' 107 107 107-grey42               :: Color-grey42               =  rgb' 107 107 107-gray43               :: Color-gray43               =  rgb' 110 110 110-grey43               :: Color-grey43               =  rgb' 110 110 110-gray44               :: Color-gray44               =  rgb' 112 112 112-grey44               :: Color-grey44               =  rgb' 112 112 112-gray45               :: Color-gray45               =  rgb' 115 115 115-grey45               :: Color-grey45               =  rgb' 115 115 115-gray46               :: Color-gray46               =  rgb' 117 117 117-grey46               :: Color-grey46               =  rgb' 117 117 117-gray47               :: Color-gray47               =  rgb' 120 120 120-grey47               :: Color-grey47               =  rgb' 120 120 120-gray48               :: Color-gray48               =  rgb' 122 122 122-grey48               :: Color-grey48               =  rgb' 122 122 122-gray49               :: Color-gray49               =  rgb' 125 125 125-grey49               :: Color-grey49               =  rgb' 125 125 125-gray50               :: Color-gray50               =  rgb' 127 127 127-grey50               :: Color-grey50               =  rgb' 127 127 127-gray51               :: Color-gray51               =  rgb' 130 130 130-grey51               :: Color-grey51               =  rgb' 130 130 130-gray52               :: Color-gray52               =  rgb' 133 133 133-grey52               :: Color-grey52               =  rgb' 133 133 133-gray53               :: Color-gray53               =  rgb' 135 135 135-grey53               :: Color-grey53               =  rgb' 135 135 135-gray54               :: Color-gray54               =  rgb' 138 138 138-grey54               :: Color-grey54               =  rgb' 138 138 138-gray55               :: Color-gray55               =  rgb' 140 140 140-grey55               :: Color-grey55               =  rgb' 140 140 140-gray56               :: Color-gray56               =  rgb' 143 143 143-grey56               :: Color-grey56               =  rgb' 143 143 143-gray57               :: Color-gray57               =  rgb' 145 145 145-grey57               :: Color-grey57               =  rgb' 145 145 145-gray58               :: Color-gray58               =  rgb' 148 148 148-grey58               :: Color-grey58               =  rgb' 148 148 148-gray59               :: Color-gray59               =  rgb' 150 150 150-grey59               :: Color-grey59               =  rgb' 150 150 150-gray60               :: Color-gray60               =  rgb' 153 153 153-grey60               :: Color-grey60               =  rgb' 153 153 153-gray61               :: Color-gray61               =  rgb' 156 156 156-grey61               :: Color-grey61               =  rgb' 156 156 156-gray62               :: Color-gray62               =  rgb' 158 158 158-grey62               :: Color-grey62               =  rgb' 158 158 158-gray63               :: Color-gray63               =  rgb' 161 161 161-grey63               :: Color-grey63               =  rgb' 161 161 161-gray64               :: Color-gray64               =  rgb' 163 163 163-grey64               :: Color-grey64               =  rgb' 163 163 163-gray65               :: Color-gray65               =  rgb' 166 166 166-grey65               :: Color-grey65               =  rgb' 166 166 166-gray66               :: Color-gray66               =  rgb' 168 168 168-grey66               :: Color-grey66               =  rgb' 168 168 168-gray67               :: Color-gray67               =  rgb' 171 171 171-grey67               :: Color-grey67               =  rgb' 171 171 171-gray68               :: Color-gray68               =  rgb' 173 173 173-grey68               :: Color-grey68               =  rgb' 173 173 173-gray69               :: Color-gray69               =  rgb' 176 176 176-grey69               :: Color-grey69               =  rgb' 176 176 176-gray70               :: Color-gray70               =  rgb' 179 179 179-grey70               :: Color-grey70               =  rgb' 179 179 179-gray71               :: Color-gray71               =  rgb' 181 181 181-grey71               :: Color-grey71               =  rgb' 181 181 181-gray72               :: Color-gray72               =  rgb' 184 184 184-grey72               :: Color-grey72               =  rgb' 184 184 184-gray73               :: Color-gray73               =  rgb' 186 186 186-grey73               :: Color-grey73               =  rgb' 186 186 186-gray74               :: Color-gray74               =  rgb' 189 189 189-grey74               :: Color-grey74               =  rgb' 189 189 189-gray75               :: Color-gray75               =  rgb' 191 191 191-grey75               :: Color-grey75               =  rgb' 191 191 191-gray76               :: Color-gray76               =  rgb' 194 194 194-grey76               :: Color-grey76               =  rgb' 194 194 194-gray77               :: Color-gray77               =  rgb' 196 196 196-grey77               :: Color-grey77               =  rgb' 196 196 196-gray78               :: Color-gray78               =  rgb' 199 199 199-grey78               :: Color-grey78               =  rgb' 199 199 199-gray79               :: Color-gray79               =  rgb' 201 201 201-grey79               :: Color-grey79               =  rgb' 201 201 201-gray80               :: Color-gray80               =  rgb' 204 204 204-grey80               :: Color-grey80               =  rgb' 204 204 204-gray81               :: Color-gray81               =  rgb' 207 207 207-grey81               :: Color-grey81               =  rgb' 207 207 207-gray82               :: Color-gray82               =  rgb' 209 209 209-grey82               :: Color-grey82               =  rgb' 209 209 209-gray83               :: Color-gray83               =  rgb' 212 212 212-grey83               :: Color-grey83               =  rgb' 212 212 212-gray84               :: Color-gray84               =  rgb' 214 214 214-grey84               :: Color-grey84               =  rgb' 214 214 214-gray85               :: Color-gray85               =  rgb' 217 217 217-grey85               :: Color-grey85               =  rgb' 217 217 217-gray86               :: Color-gray86               =  rgb' 219 219 219-grey86               :: Color-grey86               =  rgb' 219 219 219-gray87               :: Color-gray87               =  rgb' 222 222 222-grey87               :: Color-grey87               =  rgb' 222 222 222-gray88               :: Color-gray88               =  rgb' 224 224 224-grey88               :: Color-grey88               =  rgb' 224 224 224-gray89               :: Color-gray89               =  rgb' 227 227 227-grey89               :: Color-grey89               =  rgb' 227 227 227-gray90               :: Color-gray90               =  rgb' 229 229 229-grey90               :: Color-grey90               =  rgb' 229 229 229-gray91               :: Color-gray91               =  rgb' 232 232 232-grey91               :: Color-grey91               =  rgb' 232 232 232-gray92               :: Color-gray92               =  rgb' 235 235 235-grey92               :: Color-grey92               =  rgb' 235 235 235-gray93               :: Color-gray93               =  rgb' 237 237 237-grey93               :: Color-grey93               =  rgb' 237 237 237-gray94               :: Color-gray94               =  rgb' 240 240 240-grey94               :: Color-grey94               =  rgb' 240 240 240-gray95               :: Color-gray95               =  rgb' 242 242 242-grey95               :: Color-grey95               =  rgb' 242 242 242-gray96               :: Color-gray96               =  rgb' 245 245 245-grey96               :: Color-grey96               =  rgb' 245 245 245-gray97               :: Color-gray97               =  rgb' 247 247 247-grey97               :: Color-grey97               =  rgb' 247 247 247-gray98               :: Color-gray98               =  rgb' 250 250 250-grey98               :: Color-grey98               =  rgb' 250 250 250-gray99               :: Color-gray99               =  rgb' 252 252 252-grey99               :: Color-grey99               =  rgb' 252 252 252-gray100              :: Color-gray100              =  rgb' 255 255 255-grey100              :: Color-grey100              =  rgb' 255 255 255-darkGrey             :: Color-darkGrey             =  rgb' 169 169 169-darkGray             :: Color-darkGray             =  rgb' 169 169 169-darkBlue             :: Color-darkBlue             =  rgb'   0   0 139-darkCyan             :: Color-darkCyan             =  rgb'   0 139 139-darkMagenta          :: Color-darkMagenta          =  rgb' 139   0 139-darkRed              :: Color-darkRed              =  rgb' 139   0   0-lightGreen           :: Color-lightGreen           =  rgb' 144 238 144
Graphics/Rendering/Diagrams/Engine.hs view
@@ -26,7 +26,10 @@     -- ** User interface    , compose-  , writePng+  , writePNG, writePS, writePDF, writeSVG+  , renderWithBackend+  , renderOverlayPNG+  , chooseBackend      -- ** Internals @@ -36,13 +39,9 @@   ) where  import Graphics.Rendering.Diagrams.Types-import Graphics.Rendering.Diagrams.Attributes-import Graphics.Rendering.Diagrams.Layouts  import qualified Graphics.Rendering.Cairo as C-import Control.Arrow ((***)) import Control.Monad.Reader-import Data.List (foldl1')  -- $preproc -- These functions take a user-generated 'Diagram' object and@@ -71,56 +70,130 @@ sizeAndPos (Compound (Layout l ds)) = (s, Union ds')   where (s, ds') = layoutSizeAndPos l (fmap sizeAndPos ds) +sizeAndPos (Union _) = error "sizeAndPos (Union _): This should never happen!"+ -- $render -- The rendering code takes a 'Diagram' and turns it into -- actual graphics output, using the Cairo library to perform the low-level -- drawing operations. --- | Given a target width and height and a user-constructed 'Diagram',+-- | Given a target width or height and a user-constructed 'Diagram', --   render it using the Cairo rendering library.  Note that 'compose' --   takes care of all the rendering details, including preprocessing --   of the 'Diagram', and scaling/translating the final output so---   that it fits within the given width and height.+--   that it fits within the given width or height.  'compose' also+--   produces the size of the final diagram; the width or height will+--   be equal to that specified in the input, and the other dimension+--   will be determined by the aspect ratio of the diagram. -- --   The background of the output diagram will be opaque white. -- --   In order to produce a physical output, the output of 'compose' --   must be given as input to an output adapter such as 'writePng'.-compose :: Double      -- ^ output width-        -> Double      -- ^ output height-        -> Diagram     -- ^ 'Diagram' to render-        -> C.Render ()-compose w h d = do+--   Normally, however, a user of the diagrams library should not need+--   to call 'compose' directly.+compose :: SizeSpec      -- ^ output width or height+        -> Diagram       -- ^ 'Diagram' to render+        -> (Point, C.Render ())+                         -- ^ Output width and height, and Cairo action+                         --   to render it+compose size d = compose' 1 size d +compose' :: Double -> SizeSpec -> Diagram -> (Point, C.Render ())+compose' opacity size d =+   -- Preprocess the diagram, and use the global bounding box size to   -- scale and translate the output so that it fits within the target   -- output width and height.   let ((x,y), d') = sizeAndPos d-      s           = min (w/x) (w/y)-  C.scale s s-  C.translate (x/2) (y/2)+      s           = case size of+                      Width  w -> w/x    -- scale so width is as desired+                      Height h -> h/y    -- scale so height is as desired+                      Auto     -> 1      -- do not scale+  in (,) (s*x,s*y) $ do+    C.scale s s+    C.translate (x/2) (y/2) -  -- Set the output background to opaque white.-  C.save-  C.setSourceRGBA 1 1 1 1-  C.paint-  C.restore+    -- Set the output background to opaque white.+    C.save+    C.setSourceRGBA 1 1 1 opacity+    C.paint+    C.restore -  -- render the final diagram.-  flip runDiaRenderM defaultDiaRenderEnv . render $ d'+    -- render the final diagram.+    flip runDiaRenderM defaultDiaRenderEnv . render $ d' --- | Given a rendered diagram, output it to a .png file with the given---   width and height.-writePng :: String -> Int -> Int -> C.Render () -> IO ()-writePng fileName w h render =-  C.withImageSurface C.FormatARGB32 w h $ \surface -> do-    C.renderWith surface render-    C.surfaceWriteToPNG surface fileName+-- | Given a rendered diagram, output it to a file in PNG format with+--   the given width and height.+writePNG :: String -> Point -> C.Render () -> IO ()+writePNG dstfile wh r = usingBackground wh+  (\surface -> writeSurfaceToPNG surface dstfile r) +-- | Given a rendered diagram, output it to a file in PNG format with+--   the size and background of the PNG image @srcfile@.+overlayPNG :: String -> String -> C.Render () -> IO ()+overlayPNG srcfile dstfile r = usingPNG srcfile+  (\surface -> writeSurfaceToPNG surface dstfile r)++writeSurfaceToPNG :: C.Surface -> FilePath -> C.Render () -> IO ()+writeSurfaceToPNG surface dstfile r = do+  C.renderWith surface r+  C.surfaceWriteToPNG surface dstfile++usingPNG :: FilePath -> (C.Surface -> IO ()) -> IO ()+usingPNG srcfile = C.withImageSurfaceFromPNG srcfile+usingBackground :: Point -> (C.Surface -> IO ()) -> IO ()+usingBackground (w,h) = C.withImageSurface C.FormatARGB32 (ceiling w) (ceiling h)++writeSurface :: (String -> Double -> Double -> (C.Surface -> IO a) -> IO a)+             -> String+             -> Point+             -> C.Render a+             -> IO a+writeSurface withSurface fileName (w,h) r =+  withSurface fileName w h $ \surface ->+    C.renderWith surface r++-- | Given a rendered diagram, output it to a file in PostScript+--   format with the given width and height.+writePS  :: String -> Point -> C.Render () -> IO ()+writePS = writeSurface C.withPSSurface++-- | Given a rendered diagram, output it to a file in PDF+--   format with the given width and height.+writePDF :: String -> Point -> C.Render () -> IO ()+writePDF = writeSurface C.withPDFSurface++-- | Given a rendered diagram, output it to a file in SVG+--   format with the given width and height.+writeSVG :: String -> Point -> C.Render () -> IO ()+writeSVG = writeSurface C.withSVGSurface++-- | Given a file name, an output size specification, and a 'Diagram',+--   use a \"backend\" to render the 'Diagram' to an actual physical+--   output.+renderWithBackend :: (String -> Point -> C.Render () -> IO ())  -- ^ backend+                  -> String      -- ^ file name+                  -> SizeSpec    -- ^ output size specification+                  -> Diagram     -- ^ the diagram to render+                  -> IO ()+renderWithBackend backend name size dia = backend name wh r+  where (wh, r) = compose size dia++renderOverlayPNG :: FilePath -> FilePath -> Diagram -> IO ()+renderOverlayPNG srcfile dstfile dia = overlayPNG srcfile dstfile r+  where r = snd $ compose' 0 Auto dia++chooseBackend :: OutputType -> (String -> Point -> C.Render () -> IO ())+chooseBackend PNG = writePNG+chooseBackend PS  = writePS+chooseBackend PDF = writePDF+chooseBackend SVG = writeSVG+ -- | Perform a rendering operation atomically, by saving the state and --   restoring it afterwards. atomic :: DiaRenderM () -> DiaRenderM ()-atomic render = (c C.save) >> render >> (c C.restore)+atomic r = (c C.save) >> r >> (c C.restore)  -- | Render a diagram. render :: Diagram -> DiaRenderM ()@@ -129,3 +202,4 @@ render (Ann (Attr a) d) = atomic $ renderAttr a >>= flip local (render d) render (Union ds) = mapM_ render ds render (Sized _ d) = render d+render d@(Compound _) = render $ snd $ sizeAndPos d
Graphics/Rendering/Diagrams/Layouts.hs view
@@ -29,17 +29,33 @@   , hdistrib, vdistrib   , hdistribA, vdistribA +  , position, positionA+   , VAlignment   , top, vcenter, bottom   , HAlignment   , left, hcenter, right +    -- * Tree++  , tree++    -- * Miscellaneous++  , pad, padA+  , showBBox, showBBoxes+  , withSize+   ) where  import Graphics.Rendering.Diagrams.Types import Graphics.Rendering.Diagrams.Attributes-import Control.Arrow ((***), first, (>>>))+import Graphics.Rendering.Diagrams.Shapes+import Graphics.Rendering.Diagrams.Engine (sizeAndPos)+import Control.Arrow (first) +import Data.Tree+ -- Union -----------------------------------------------  -- | The union layout, which lays out diagrams superimposed on one@@ -54,8 +70,8 @@     where (sizes, diagrams) = unzip pds           (xs, ys)          = unzip sizes           (w,h)             = (maximum xs, maximum ys)-          xs'               = align halign w xs-          ys'               = align valign h ys+          xs'               = aligns halign w xs+          ys'               = aligns valign h ys           positionedDs      = zipWith3 translate xs' ys' diagrams  -- | Create a 'Diagram' as a union of subdiagrams which will not be@@ -64,7 +80,7 @@ union :: [Diagram] -> Diagram union = unionA hcenter vcenter --- | Superimpose one diagram atop another.  @d1 ## d2@ results in a+-- | Superimpose one diagram atop another.  @d1 \#\# d2@ results in a --   diagram in which @d2@ is on top of @d1@ (i.e., @d1@ is drawn --   first, then @d2@). (##) :: Diagram -> Diagram -> Diagram@@ -107,11 +123,31 @@  -- | Compute new coordinates for the centers of the subdiagrams of a --   list, based on the alignment.-align :: Alignment -> Double -> [Double] -> [Double]-align TopLeft     h hs = map ((/2) . (subtract h)) hs-align Center      h hs = repeat 0-align BottomRight h hs = map negate (align TopLeft h hs)+aligns :: Alignment    -- ^ the alignment to use+       -> Double       -- ^ the total height (resp. width) we're working with+       -> [Double]     -- ^ the individual heights (resp. widths) of+                       --   the diagrams to align+       -> [Double]     -- ^ the amount to translate each diagram in+                       --   order to be properly aligned+aligns a h hs = map (align a h) hs +-- | Given a requested alignment, the total width (resp. height) of+--   the enclosing bounding box, and the width (resp. height) of a+--   diagram, compute the offset needed to properly align the diagram.+align :: Alignment    -- ^ the alignment to use+      -> Double       -- ^ the total height (resp. width) we're working with+      -> Double       -- ^ the height (resp. widths) of the diagram to+                      --   align+      -> Double       -- ^ the offset needed to align the diagram+align a h x = alignOffset a (h - x)++-- | Compute an offset corresponding to a given alignment and width.+alignOffset :: Alignment -> Double -> Double+alignOffset TopLeft x     = -x/2+alignOffset Center  _     = 0+alignOffset BottomRight x = x/2++ -- | A list of 'Diagram's can be distributed in one of several ways. data Distribution = Sep Double  -- ^ Put a constant separation between                                 --   each pair of diagrams@@ -179,7 +215,7 @@         offsWSeps  = zipWith (+) offsets (zipWith (*) [0..] (repeat sep))         centers    = zipWith (+) (init offsWSeps) (map (/2) ws)         xs         = map (subtract (w/2)) centers-        ys         = align a h hs+        ys         = aligns a h hs  listPosns a (Distrib da sep) (w,h) sizes = zip xs ys   where (ws,hs)    = unzip sizes@@ -189,14 +225,14 @@         centerOffs Center  _     = sep/2         centerOffs BottomRight width = sep - width/2         xs         = map (subtract (w/2)) centers-        ys         = align a h hs+        ys         = aligns a h hs  -- | Lay out a list of 'Diagram's horizontally from left to right, --   aligned along their top edges. hcat :: [Diagram] -> Diagram hcat = hsep 0 --- | @d1 <> d2@ is a 'Diagram' with @d1@ to the left of @d2@, aligned+-- | @d1 \<\> d2@ is a 'Diagram' with @d1@ to the left of @d2@, aligned --   along their top edges. (<>) :: Diagram -> Diagram -> Diagram d1 <> d2 = hcat [d1, d2]@@ -214,7 +250,7 @@  -- | Lay out a list of 'Diagram's horizontally, with the given --   amount of separation in between each pair, using the given---   vertical alignment ('top', 'center', or 'bottom').+--   vertical alignment ('top', 'vcenter', or 'bottom'). hsepA :: Double       -- ^ amount of separation between each pair of diagrams       -> VAlignment   -- ^ alignment to use ('top', 'vcenter', or 'bottom')       -> [Diagram] -> Diagram@@ -242,7 +278,7 @@ vcat :: [Diagram] -> Diagram vcat = vsep 0 --- | @d1 <> d2@ is a 'Diagram' with @d1@ above @d2@, aligned+-- | @d1 \/\/ d2@ is a 'Diagram' with @d1@ above @d2@, aligned --   along their left edges. (//) :: Diagram -> Diagram -> Diagram d1 // d2 = vcat [d1, d2]@@ -287,10 +323,129 @@ -- | The mother-combinator for all the @sep@ functions, used --   internally. sepA :: ListType -> Double -> Alignment -> [Diagram] -> Diagram-sepA lt sep align = Compound . Layout (List lt align (Sep sep))+sepA lt sep algn = Compound . Layout (List lt algn (Sep sep))  -- | The mother-combinator for all the @distrib@ functions, used --   internally. distribA :: ListType -> Double -> Alignment -> Alignment -> [Diagram] -> Diagram-distribA lt sep alignD align =-  Compound . Layout (List lt align (Distrib alignD sep))+distribA lt sep alignD algn =+  Compound . Layout (List lt algn (Distrib alignD sep))+++-- Explicit subdiagram positioning ---------------------++data Positioned = Positioned [Point] HAlignment VAlignment+instance LayoutClass Positioned [] where+  layoutSizeAndPos _ [] = ((0,0), [])+  layoutSizeAndPos (Positioned ps ha va) dss = ((w,h), pds)+    where (sizes, diagrams) = unzip dss+          (ws, hs) = unzip sizes+          (pxs, pys) = unzip ps++          xs' = zipWith (\x w1 -> x - alignOffset ha w1) pxs ws+          ys' = zipWith (\y h1 -> y - alignOffset va h1) pys hs++          hws = map (/2) ws+          hhs = map (/2) hs+          xmax = maximum (zipWith (+) xs' hws)+          xmin = minimum (zipWith (-) xs' hws)+          w = xmax - xmin+          ymax = maximum (zipWith (+) ys' hhs)+          ymin = minimum (zipWith (-) ys' hhs)+          h = ymax - ymin++          xs'norm = map (subtract (xmin + w/2)) xs'+          ys'norm = map (subtract (ymin + h/2)) ys'++          pds = zipWith3 translate xs'norm ys'norm diagrams++-- | Create a diagram from a list of subdiagrams with explicit+--   positions in a local coordinate system.  Each subdiagram will be+--   positioned with its center at the corresponding+--   position. @position@ is equivalent to @positionA hcenter+--   vcenter@.+position :: [(Point, Diagram)] -> Diagram+position = positionA hcenter vcenter++-- | Create a diagram from a list of subdiagrams with explicit+--   positions in a local coordinate system.  The alignment options+--   specify what part of each subdiagram should be placed on the+--   corresponding position.  For example, @positionA left top@ will+--   position the top left corner of each subdiagram at the+--   corresponding point.+positionA :: HAlignment -> VAlignment -> [(Point,Diagram)] -> Diagram+positionA ha va pds = Compound (Layout (Positioned ps ha va) ds)+  where (ps, ds) = unzip pds+++-- Tree ------------------------------------------++-- | Lay out a 'Tree' (from "Data.Tree") of 'Diagram's in a top-down+--   fashion.  This layout is experimental; future releases of the+--   Diagrams library are planned which will be able to automatically+--   draw edges between nodes in the tree.+tree :: Double    -- ^ separation between layers+     -> Double    -- ^ separation between siblings+     -> Tree Diagram+     -> Diagram+tree _  _  (Node d []) = d+tree ls ss (Node d ts) = vsepA ls hcenter [ d, hsep ss (map (tree ls ss) ts) ]++-- Miscellaneous ---------------------------------++newtype Identity a = Identity a+instance Functor Identity where+  fmap f (Identity x) = Identity (f x)++data Padded = Padded Double Double HAlignment VAlignment+instance LayoutClass Padded Identity where+  layoutSizeAndPos (Padded dw dh ha va) (Identity ((w,h), d))+      = ((w', h'), [translate (align ha w' w) (align va h' h) d])+    where w' = w + dw+          h' = h + dh++-- | Add extra padding to a diagram.  @pad w h d@ is a diagram which+--   is the same as @d@, but with @w@ units added to the width and @h@+--   units added to the height, with @d@ centered in the available+--   space.  Thus @pad w h@ is equivalent to @padA w h hcenter vcenter@.+pad :: Double -> Double -> Diagram -> Diagram+pad pw ph d = padA pw ph hcenter vcenter d++-- | Add extra padding to a diagram, aligning the diagram as indicated+--   within the avilable space.+padA :: Double -> Double -> HAlignment -> VAlignment -> Diagram -> Diagram+padA pw ph aw ah d = Compound (Layout (Padded pw ph aw ah) (Identity d))++++data ShowBBox = ShowBBox+instance LayoutClass ShowBBox Identity where+  layoutSizeAndPos _ (Identity ((w,h), d))+      = ((w,h), [defaultAttributes $ rect w h, d])++-- | Show a rectangle denoting a diagram's bounding box, in addition+--   to the diagram itself.+showBBox :: Diagram -> Diagram+showBBox Empty = Empty+showBBox d = Compound . Layout ShowBBox . Identity $ d++-- | Show the bounding boxes of a diagram and all its subdiagrams.+showBBoxes :: Diagram -> Diagram+showBBoxes Empty = Empty+showBBoxes d@(Prim _) = showBBox d+showBBoxes (Ann a d) = showBBox (Ann a (showBBoxes d))+showBBoxes (Compound (Layout l ds)) = showBBox (Compound (Layout l (fmap showBBoxes ds)))+showBBoxes (Union ds) = showBBox (Union (map showBBoxes ds))+showBBoxes (Sized p d) = showBBox (Sized p (showBBoxes d))++data FromSize = FromSize (Double -> Double -> Diagram)+instance LayoutClass FromSize Identity where+  layoutSizeAndPos (FromSize f) (Identity  ((w,h),_))+    = let d = f w h in (fst (sizeAndPos d), [d])++-- | Create one diagram using the current size of another.+--   The new diagram is returned, the old one is discarded.+withSize :: (Double -> Double -> Diagram) -- ^ Function for new diagram+         -> Diagram                       -- ^ Old diagram+         -> Diagram+withSize f dia = Compound (Layout (FromSize f) (Identity dia))
+ Graphics/Rendering/Diagrams/Paths.hs view
@@ -0,0 +1,177 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Diagrams.Paths+-- Copyright   :  (c) Brent Yorgey 2008+-- License     :  BSD-style (see LICENSE)+-- Maintainer  :  byorgey@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-- Type definitions and convenience functions for+-- "Graphics.Rendering.Diagrams", an embedded domain-specific language+-- (EDSL) for creating simple diagrams.+--+-----------------------------------------------------------------------------++module Graphics.Rendering.Diagrams.Paths+  (+    emptyPath++  , pathFromVertices, pathFromVectors+  , pathConcat+  , closed, isClosed++  , rotPath++  , pathSizeAndOffset+  , renderPath++  ) where++import Graphics.Rendering.Diagrams.Types+import qualified Graphics.Rendering.Cairo as C++import Control.Monad (when)++-- | \"Integrate\" a path given by a starting point and a sequence of+--   displacements, resulting in a list of vertex coordinates.+pathInt :: Point -> Path -> [Point]+pathInt s (Path _ vs) = scanl (.+.) s vs++-- | \"Differentiate\" a list of vertex coordinates to produce an open+--   path.  Calling 'pathDeriv' on an empty list will result in a+--   run-time error.+pathDeriv :: [Point] -> Path+pathDeriv ps = Path Open $ zipWith (.-.) (tail ps) ps++-- | Create an open path from a list of edge displacement vectors.+--   For example, @pathFromVectors [(1,1), (3,4)]@ describes the path+--   with two segments which first moves one unit in the positive x+--   and y directions, and then moves three units in the positive x+--   direction and four in the positive y direction.+pathFromVectors :: [Vec] -> Path+pathFromVectors = Path Open++-- | The empty path, i.e. a path with no edges.+emptyPath :: Path+emptyPath = pathFromVectors []++-- | Create an open path from a list of vertices.  For example,+--   @pathFromVertices [(1,3), (4,4), (6,5)]@ describes the path with+--   two segments which starts at (1,3), has a corner at (4,4), and+--   ends at (6,5).  Note, however, that the vertices themselves are+--   not significant, only the distances between them.  That is,+--   @pathFromVertices [(0,1), (3,2), (5,3)]@ describes exactly the+--   same path.+pathFromVertices :: [Point] -> Path+pathFromVertices [] = emptyPath+pathFromVertices vs = pathDeriv vs++-- | Concatenate two open paths into a single open path consisting of+--   the first followed by the second.+pathConcat :: Path -> Path -> Path+pathConcat (Path _ es1) (Path _ es2) = Path Open (es1 ++ es2)++-- | Create a closed path (by connecting the first and last points in+--   the path).+closed :: Path -> Path+closed (Path _ vs) = Path Closed vs++-- | Determine whether a 'Path' is closed or open.+isClosed :: Path -> Bool+isClosed (Path Closed _) = True+isClosed _ = False++-- | Rotate a path by a fraction of a circle.  @rotPath d@ rotates+--   paths by an angle of @d*2*pi@ radians.  Note that creating a+--   'Diagram' from a 'Path' (using 'straight' or 'curved' or some+--   other such function) and then applying 'rotate' to it is+--   different than first applying 'rotPath' to the 'Path' before+--   making it into a 'Diagram'.  In the latter case, the bounding box+--   will be correct, whereas in the former case, the bounding box+--   will still correspond to the unrotated version of the path.+rotPath :: Double -> Path -> Path+rotPath d (Path clsd ps) = Path clsd (map rot ps)+  where ang = d*2*pi+        ca  = cos ang+        sa  = sin ang+        rot (x,y) = (x * ca - y * sa, x * sa + y * ca)++-- | Compute the size of a bounding box for the given 'Path', and the+-- | offset of the starting vertex from the center.+pathSizeAndOffset :: Path -> (Vec,Point)+pathSizeAndOffset p = case pathInt (0,0) p of+  [] -> ((0,0),(0,0))+  ps -> ((xmax - xmin, ymax - ymin), ((-xmax - xmin)/2, (-ymax - ymin)/2))+    where (xs,ys) = unzip ps+          xmax = maximum xs+          xmin = minimum xs+          ymax = maximum ys+          ymin = minimum ys++-- | Render a path using a particular style in the Cairo rendering monad.+renderPath :: PathStyle -> Path -> C.Render ()+renderPath Straight   = renderPathStraight+renderPath (Bezier d) = renderPathBezier d++-- | Render a path using straight line segments.+renderPathStraight :: Path -> C.Render ()+renderPathStraight p@(Path clsd vs) = do+  let (_,offs) = pathSizeAndOffset p  -- not nice to recalculate this,+                                      -- but oh well++  uncurry C.moveTo offs               -- move to the start+  mapM_ (uncurry C.relLineTo) vs      -- draw all the segments+  when (clsd==Closed) $ C.closePath   -- maybe close the path++-- | Render a path using Bezier curves.  The first parameter+--   determines what fraction of the path segments will be rounded off+--   with curves; the remainder of the segments will be drawn with+--   straight lines.+renderPathBezier :: Double -> Path -> C.Render ()+renderPathBezier _ (Path _ []) = return ()+renderPathBezier d p@(Path clsd segs) | d > 1 = renderPathBezier 1 p+                                      | d < 0 = renderPathBezier 0 p+                                      | otherwise = do+  let (_,offs)   = pathSizeAndOffset p+      segcls  = ((-1)*.) . last $ pathInt (0,0) p+      isClsd  = (clsd == Closed)++  uncurry C.moveTo offs       -- move to the first path vertex++                              -- move to start of the first straight segment+                              -- (draw a line if not closed)+  uncurry (if' isClsd C.relMoveTo C.relLineTo) ((d/2) *. head segs)++                              -- draw (straight, curved) pairs along path+  mapM_ (drawCurveSegment d) (zip segs (tail segs))++                              -- if closed path, we still need to draw+                              -- two more (straight, curved) pairs:+                              -- one for last segment + closing+                              -- segment, one for closing segment ++                              -- first segment+  if isClsd+    then do+      drawCurveSegment d (last segs, segcls)+      drawCurveSegment d (segcls, head segs)+    else                      -- otherwise, just finish off the last+                              -- segment with a straight line+      uncurry C.relLineTo ((1 - d/2) *. last segs)++if' :: Bool -> a -> a -> a+if' True  x _ = x+if' False _ x = x++-- | Given a fraction specifying which part of the segments should be+--   rounded off, and two segments, draw the straight portion of the+--   first segment and the curve between the first and second+--   segments, using the shared vertex as a control point.+drawCurveSegment :: Double -> (Vec,Vec) -> C.Render ()+drawCurveSegment d (v1, v2) = do+  let s = 1 - d+  uncurry C.relLineTo $ s *. v1++  let ctrl@(ctrlx, ctrly) = (d/2) *. v1+  let (endx,  endy)    = ctrl .+. ((d/2) *. v2)+  C.relCurveTo ctrlx ctrly ctrlx ctrly endx endy
Graphics/Rendering/Diagrams/Shapes.hs view
@@ -13,34 +13,49 @@ ----------------------------------------------------------------------------- module Graphics.Rendering.Diagrams.Shapes   ( circle-  , poly++  , regPolyPath+  , regPoly+  , rotRegPoly+   , rect+  , roundRect -  , draw+  , straight+  , curved++  , textPath++  , rawCairo+   ) where  import Graphics.Rendering.Diagrams.Types import Graphics.Rendering.Diagrams.Attributes (scale)+import Graphics.Rendering.Diagrams.Paths  import qualified Graphics.Rendering.Cairo as C-import Control.Arrow ((&&&), (***))+import qualified Graphics.Rendering.Cairo.Internal as CI+import Control.Arrow ((&&&)) import Control.Monad.Reader+import System.IO.Unsafe (unsafePerformIO)+import Control.Exception (bracket)  -- | Draw the shape defined by the current cairo path, using the --   current fill color, stroke color, and stroke width settings. draw :: DiaRenderM () draw = do c $ C.save-          (RGBA r g b a) <- asks envFillColor-          c $ C.setSourceRGBA r g b a+          (rf,gf,bf,af) <- asks (colorToRGBA . envFillColor)+          c $ C.setSourceRGBA rf gf bf af           c $ C.fillPreserve -          (RGBA r g b a) <- asks envStrokeColor-          c $ C.setSourceRGBA r g b a+          (rs,gs,bs,as) <- asks (colorToRGBA . envStrokeColor)+          c $ C.setSourceRGBA rs gs bs as           sw <- asks envStrokeWidth           c $ fmap dist (C.deviceToUserDistance sw 0) >>= C.setLineWidth           c $ C.stroke           c $ C.restore-  where dist = sqrt . uncurry (+) . ((^2) *** (^2))+  where dist (x,y) = sqrt (x*x + y*y)  -- | A unit circle centered at the origin. data Circle = Circle  deriving (Eq, Show, Read)@@ -54,28 +69,56 @@ circle :: Double -> Diagram circle r = scale r $ Prim (Shape Circle) +-- | A path-based shape.+data PathShape = PathShape PathStyle Path  deriving (Eq, Show, Read)+instance ShapeClass PathShape where+  shapeSize (PathShape _ p) = fst $ pathSizeAndOffset p+  renderShape (PathShape style p) = c (renderPath style p) >> draw +-- | @straight@ creates a 'Diagram' from a path, by drawing straight+--   lines along the path edges.+straight :: Path -> Diagram+straight = Prim . Shape . PathShape Straight --- | @RPoly n@ is a regular n-gon centered at the origin, with a---   vertex at (1,0).-data RPoly = RPoly Int  deriving (Eq, Show, Read)-instance ShapeClass RPoly where-  shapeSize _ = (2,2)-  renderShape (RPoly n) = do-      c $ C.moveTo 1 0-      c $ mapM_ (uncurry C.lineTo . (cos &&& sin)) $-        tail [0,2*pi/nd .. (nd-1)*2*pi/nd]-      c $ C.closePath-      draw-    where nd = fromIntegral n+-- | @curved d p@ is a curved path which follows generally the path+--   @p@.  The parameter @d@ specifies the amount of corner rounding.+--   In particular, @d@ should be a value between 0 and 1, which+--   specifies what fraction of the path segments should be rounded+--   off with bezier curves, using the path vertices as control+--   points.  Thus @d = 0@ produces the polygonal path itself, with no+--   curved segments; @d = 1@ produces a continuously curving path+--   tangent to the midpoints of the path segments; and intermediate+--   values of @d@ interpolate between the two. The curved path+--   produced will be everywhere differentiable as long as @d > 0@.+--   If the path is not closed, the curve will begin and end at the+--   first and last path vertices (no rounding will take place at+--   these vertices).+curved :: Double -> Path -> Diagram+curved d = Prim . Shape . PathShape (Bezier d) --- | @poly n r@ is a regular n-gon, with a circumcircle of radius @r@.---   One vertex is oriented along the positive x-axis.  Note that the---   bounding box is the square circumscribed around the circumcircle.-poly :: Int -> Double -> Diagram-poly n r = scale r $ Prim (Shape (RPoly n))+-- | @regPolyPath n r@ is an open path corresponding to a regular+--   polygon, with the first vertex oriented along the positive+--   x-axis and proceeding clockwise.+regPolyPath :: Int -> Double -> Path+regPolyPath n r = pathFromVertices verts+  where verts = map (((*r) . cos) &&& ((*r) . sin))+                    [0,2*pi/nd .. (nd-1)*2*pi/nd]+        nd = fromIntegral n +-- | @regPoly n r@ is a regular n-gon, with a circumcircle of radius+--   @r@.  One vertex is oriented along the positive x-axis.+regPoly :: Int -> Double -> Diagram+regPoly n r = straight . closed $ regPolyPath n r +-- | @rotRegPoly n r a@ is the same as @'regPoly' n r@ but rotated+--   through an angle of @a*2*pi@ radians (i.e., @a@ represents a+--   fraction of an entire revolution).  This is different than+--   @'rotate' a $ 'regPoly' n r@; @rotRegPoly@ will adjust the+--   bounding box correctly (using 'rotPath'), whereas the+--   construction using @rotate@ will still have a bounding box+--   corresponding to the unrotated polygon.+rotRegPoly :: Int -> Double -> Double -> Diagram+rotRegPoly n r a = straight . closed . rotPath a $ regPolyPath n r  -- | @Rect w@ is a 2w (width) by 2 (height) rectangle, centered at the --   origin.@@ -90,3 +133,72 @@ rect :: Double -> Double -> Diagram rect w h = scale (h/2) $ Prim (Shape (Rect (w/h))) +-- | @RoundRect w h@ is a rectangle with rounded corners.+--   Both dimensions are given to avoid unnecessary+--   distortion in the curves when scaling.+data RoundRect = RoundRect Double Double deriving (Eq, Show, Read)+instance ShapeClass RoundRect where+  shapeSize (RoundRect w h) = (w,h)+  renderShape (RoundRect w h) = do+    let (x,y) = (w/2, h/2)+        r     = min (w/3) (h/3)+    c $ do C.arc (r-x) (r-y) r pi (-pi/2)+           C.lineTo (x-r) (-y)+           C.arc (x-r) (r-y) r (-pi/2) 0+           C.lineTo (x) (y-r)+           C.arc (x-r) (y-r) r 0 (pi/2)+           C.lineTo (r-x) (y)+           C.arc (r-x) (y-r) r (pi/2) pi+           C.closePath+    draw++-- | @roundRect w h@ is a rectangle of width @w@ and height @h@ with+--   rounded corners having a radius one third the length of the+--   shortest edge.+roundRect :: Double -> Double -> Diagram+roundRect w h = Prim $ Shape $ RoundRect w h++-- | @Text s t@ is a text string @t@ at size @s@.+data Text = Text Double String deriving (Eq, Show, Read)+instance ShapeClass Text where+    shapeSize t = (x,y)+        where x     = C.textExtentsWidth e + C.textExtentsXbearing e+              y     = C.fontExtentsHeight f+              (f,e) = unsafeExtents t+    renderShape (Text s t) = do+        c $ do C.setFontSize s+               (x,y) <- C.getCurrentPoint+               te <- C.textExtents t+               fe <- C.fontExtents+               C.moveTo+                (x - (C.textExtentsWidth te/2) - C.textExtentsXbearing te)+                (y + (C.fontExtentsHeight fe/2) - C.fontExtentsDescent fe)+               C.textPath t+        draw++{-# NOINLINE unsafeExtents #-}+unsafeExtents :: Text -> (CI.FontExtents, CI.TextExtents)+unsafeExtents (Text s t) = unsafePerformIO $ do+            bracket+                (CI.create =<< C.createImageSurface C.FormatARGB32 1000 1000)+                (CI.destroy)+                (\cxt -> do CI.setFontSize cxt s+                            te <- CI.textExtents cxt t+                            fe <- CI.fontExtents cxt+                            return (fe, te))++-- | @textPath s t@ is a string of text @t@ at size @s@,+--   represented as an outline with separate stroke and fill.+textPath :: Double -> String -> Diagram+textPath s t = Prim (Shape (Text s t))++data RawCairo = RawCairo Point (C.Render ())+instance ShapeClass RawCairo where+  shapeSize (RawCairo s _) = s+  renderShape (RawCairo _ r) = c r++-- | @rawCairo s r@ is a diagram with bounding box size @s@, rendered+--   by executing Cairo 'Render' action @r@. Import+--   "Graphics.Rendering.Cairo" to access Cairo operations.+rawCairo :: Point -> C.Render () -> Diagram+rawCairo s r = Prim (Shape (RawCairo s r))
Graphics/Rendering/Diagrams/Types.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ExistentialQuantification, GeneralizedNewtypeDeriving, MultiParamTypeClasses #-}+{-# LANGUAGE ExistentialQuantification, GeneralizedNewtypeDeriving, MultiParamTypeClasses, FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module      :  Graphics.Rendering.Diagrams.Types@@ -21,10 +21,14 @@      Diagram(..) -  , Color(..), rgb, rgba-  , Point-  , (.+), (.*)+  , Color(..), SomeColor(..)+  , Point, Vec+  , (*.), (.+.), (.-.), (.*.) +  , Path(..)+  , PathType(..)+  , PathStyle(..)+   -- * Shapes, attributes, and layouts    , ShapeClass(..), Shape(..)@@ -40,11 +44,19 @@   , runDiaRenderM   , c +  , SizeSpec(..)+  , OutputType(..)+   ) where -import Graphics.Rendering.Cairo+import qualified Graphics.Rendering.Cairo as C import Control.Monad.Reader+import Data.Colour+import Data.Colour.Names (black)+import qualified Data.Colour.SRGB.Linear as RGB +-- Diagrams ----------------------------------------------------------+ -- | 'Diagram' is the core data type which describes a diagram. --   'Diagram's may be constructed, transformed, combined, and --   ultimately rendered as an image.@@ -58,51 +70,94 @@                -- ^ An explicitly sized diagram whose bounding box                --   takes up a particular amount of space. --- | An existential wrapper type for layouts.  A layout consists of a---   (possibly parameterized) layout type, along with a container of---   'Diagram's.-data Layout = forall l f. (LayoutClass l f) => Layout l (f Diagram)+-- Colors ------------------------------------------------------------ --- | All layouts must be instances of 'LayoutClass', along with an---   appropriate container type which must be an instance of Functor.-class (Functor f) => LayoutClass l f where-  -- | Given a layout and a container of @(size, diagram)@ pairs (which-  --   have already had all subdiagrams appropriately positioned),-  --   compute the overall bounding box size for this layout, as well-  --   as a list of positioned subdiagrams.-  layoutSizeAndPos :: l -> f (Point,Diagram) -> (Point, [Diagram])+-- | The 'Color' type class encompasses color representations which+--   can be used by the Diagrams library; that is, every function in+--   the Diagrams library which expects a color can take any type+--   which is an instance of 'Color'.  Instances are provided for both+--   the 'Data.Colour.Colour' and 'Data.Colour.AlphaColour' types from+--   the "Data.Colour" library.+class Color c where+  colorToRGBA :: c -> (Double,Double,Double,Double) --- | The 'Color' type represents colors in red-green-blue-alpha---   format, with each channel in the range 0-1.  For a large list of---   predefined colors, see "Graphics.Rendering.Diagrams.Colors".-data Color = RGBA Double Double Double Double-  deriving (Eq, Show, Read)+-- | Existential wrapper for instances of the 'Color' class.+data SomeColor = forall c. Color c => SomeColor c --- | Construct an opaque (alpha = 1) color from RGB values specified---   as Doubles in the range 0-1.-rgb :: Double    -- ^ red channel-    -> Double    -- ^ green channel-    -> Double    -- ^ blue channel-    -> Color-rgb r g b = rgba r g b 1+-- Note: we would like to just be able to say 'instance Color (Colour+-- Double)' and so on, but the problem is that the named color+-- constants in Data.Colour.Names are polymorphic with type (Floating+-- a, Ord a) => Colour a, so trying to pass one of these constants to+-- a function like 'lc' gives an error that there is no instance for+-- Color (Colour a).  Adding a type annotation like 'lc (black ::+-- Colour Double)' works, but this is a pain for the user.  The+-- (admittedly hackish) solution is to make general instances which+-- require Floating and Real (so that we can convert to Double with+-- fromRational . toRational), and let type defaulting figure out that+-- in the expression 'lc black', black should have type Colour Double.+-- This is still unsatisfactory, though---even though we know we will+-- (almost) always be getting (Colour Doubles), we still run the+-- values through fromRational . toRational! --- | Construct a color from RGBA values, specified as Doubles in the---   range 0-1.-rgba :: Double    -- ^ red channel-     -> Double    -- ^ green channel-     -> Double    -- ^ blue channel-     -> Double    -- ^ alpha (transparency) channel-     -> Color-rgba = RGBA+instance (Floating a, Real a) => Color (Colour a) where+  colorToRGBA col = (r,g,b,1)+    where c' = RGB.toRGB col+          r  = toDouble $ RGB.channelRed c'+          g  = toDouble $ RGB.channelGreen c'+          b  = toDouble $ RGB.channelBlue c' +instance (Floating a, Real a) => Color (AlphaColour a) where+  colorToRGBA col = (r,g,b,a)+    where a  = toDouble $ alphaChannel col+          c' = RGB.toRGB $ alphaToColour col+          r  = toDouble $ RGB.channelRed c'+          g  = toDouble $ RGB.channelGreen c'+          b  = toDouble $ RGB.channelBlue c'++toDouble :: (Real a) => a -> Double+toDouble = fromRational . toRational++instance Color SomeColor where+  colorToRGBA (SomeColor col) = colorToRGBA col++alphaToColour :: (Floating a, Ord a, Fractional a) => AlphaColour a -> Colour a+alphaToColour ac = darken (recip (alphaChannel ac)) (ac `over` black)++-- Points ------------------------------------------------------------+ -- | Basic 2D points/vectors. type Point = (Double,Double)+type Vec = Point --- | Elementwise addition and multiplication for 'Point's.-(.+), (.*) :: Point -> Point -> Point-(x1,y1) .+ (x2,y2) = (x1 + x2, y1 + y2)-(x1,y1) .* (x2,y2) = (x1 * x2, y1 * y2)+-- | Scalar multiplication.+(*.) :: Double -> Point -> Point+s *. (x,y) = (s*x, s*y) +-- | Elementwise addition, subtraction and multiplication for 'Point's.+(.+.), (.-.), (.*.) :: Point -> Point -> Point+(x1,y1) .+. (x2,y2) = (x1 + x2, y1 + y2)+(x1,y1) .*. (x2,y2) = (x1 * x2, y1 * y2)+a .-. b = a .+. ((-1) *. b)++-- Paths -------------------------------------------------------------++-- | A path can be open (normal) or closed (first and last vertices+--   connected automatically).+data PathType = Open | Closed+  deriving (Eq, Show, Read)++-- | A path is a series of edges which can be stroked, filled, etc.+--   It can be either open (the default) or closed (i.e. the first and+--   last vertices are connected).+data Path = Path PathType+                 [Vec]+  deriving (Eq, Show, Read)++-- | The styles in which a path can be rendered.+data PathStyle = Straight | Bezier Double  deriving (Eq, Show, Read)++-- Attributes --------------------------------------------------------+ -- | Existential wrapper type for attributes. data Attr = forall a. AttrClass a => Attr a @@ -125,6 +180,8 @@   --    former state afterwards.   renderAttr :: a -> DiaRenderM (DiaRenderEnv -> DiaRenderEnv) +-- Shapes ------------------------------------------------------------+ -- | Existential wrapper type for shapes. data Shape = forall s. ShapeClass s => Shape s @@ -156,44 +213,70 @@   -- | Calculate a cairo Render action to render a shape.   renderShape :: s -> DiaRenderM () +-- Layouts -----------------------------------------------------------++-- | An existential wrapper type for layouts.  A layout consists of a+--   (possibly parameterized) layout type, along with a container of+--   'Diagram's.+data Layout = forall l f. (LayoutClass l f) => Layout l (f Diagram)++-- | All layouts must be instances of 'LayoutClass', along with an+--   appropriate container type which must be an instance of Functor.+class (Functor f) => LayoutClass l f where+  -- | Given a layout and a container of @(size, diagram)@ pairs (which+  --   have already had all subdiagrams appropriately positioned),+  --   compute the overall bounding box size for this layout, as well+  --   as a list of positioned subdiagrams.+  layoutSizeAndPos :: l -> f (Point,Diagram) -> (Point, [Diagram])++-- Rendering ---------------------------------------------------------+ -- | An environment containing additional parameters to be made --   available while rendering, which for one reason or another are --   not or cannot be provided by the cairo 'Render' monad itself. --   For example, cairo only tracks one current color, so we must --   track a fill color and stroke color separately.-data DiaRenderEnv = DREnv { envFillColor   :: Color-                          , envStrokeColor :: Color+data DiaRenderEnv = DREnv { envFillColor   :: SomeColor+                          , envStrokeColor :: SomeColor                           , envStrokeWidth :: Double                           }-  deriving (Show) -setEnvFillColor :: Color -> DiaRenderEnv -> DiaRenderEnv-setEnvFillColor c d = d { envFillColor = c }+setEnvFillColor :: Color c => c -> DiaRenderEnv -> DiaRenderEnv+setEnvFillColor col d = d { envFillColor = SomeColor col } -setEnvStrokeColor :: Color -> DiaRenderEnv -> DiaRenderEnv-setEnvStrokeColor c d = d { envStrokeColor = c }+setEnvStrokeColor :: Color c => c -> DiaRenderEnv -> DiaRenderEnv+setEnvStrokeColor col d = d { envStrokeColor = SomeColor col }  setEnvStrokeWidth :: Double -> DiaRenderEnv -> DiaRenderEnv-setEnvStrokeWidth c d = d { envStrokeWidth = c }+setEnvStrokeWidth w d = d { envStrokeWidth = w }  -- | The default rendering environment: transparent fill with 1-pixel --   black strokes. defaultDiaRenderEnv :: DiaRenderEnv-defaultDiaRenderEnv = DREnv { envFillColor   = RGBA 1 1 1 0-                            , envStrokeColor = RGBA 0 0 0 1+defaultDiaRenderEnv = DREnv { envFillColor   = SomeColor (transparent :: AlphaColour Double)+                            , envStrokeColor = SomeColor (black :: Colour Double)                             , envStrokeWidth = 1                             }  -- | The custom rendering monad: ReaderT 'DiaRenderEnv' on top of --   cairo's Render monad.-newtype DiaRenderM a = DRM (ReaderT DiaRenderEnv Render a)+newtype DiaRenderM a = DRM (ReaderT DiaRenderEnv C.Render a)   deriving (Functor, Monad, MonadReader DiaRenderEnv)  -- | Run a 'DiaRenderM' action, given an initial rendering --   environment, to produce a cairo @Render@ action.-runDiaRenderM :: DiaRenderM a -> DiaRenderEnv -> Render a+runDiaRenderM :: DiaRenderM a -> DiaRenderEnv -> C.Render a runDiaRenderM (DRM m) e = runReaderT m e  -- | Lift a cairo @Render@ action into a 'DiaRenderM' action.-c :: Render a -> DiaRenderM a+c :: C.Render a -> DiaRenderM a c = DRM . lift++-- | A specification of the size of a rendered 'Diagram'.+data SizeSpec = Width  Double   -- ^ an explicit width; the height is determined automatically+              | Height Double   -- ^ an explicit height; the width is determined automatically+              | Auto            -- ^ determine the size automatically+                                --   (do not scale)++-- | The supported output file types for rendered diagrams.+data OutputType = PNG | PS | PDF | SVG
README view
@@ -1,12 +1,14 @@  Graphics.Rendering.Diagrams provides an embedded domain-specific-language (EDSL) for creating simple diagrams in a compositional style.+language (EDSL) for creating simple graphics in a compositional style. +For some examples of use, see http://code.haskell.org/diagrams/ .+ ------------------------------------------------------------------------ -Building:+To install the Diagrams library: -Get the dependencies+1. Get the dependencies      The diagrams library uses Haskell bindings to the Cairo vector     graphics library.  In order to build the diagrams library, you@@ -24,26 +26,39 @@       website (http://www.haskell.org/gtk2hs/) and follow the       instructions to download and build it. +    * The colour library, which is available from Hackage.  If you use+      the cabal-install build option described below, the colour+      library will be downloaded and installed for you automatically. -Build with Cabal:+2. Build -    runhaskell Setup.lhs configure --prefix=$HOME --user-    runhaskell Setup.lhs build-    runhaskell Setup.lhs install+   * Option 1: use cabal-install -    (Optionally, you can omit the --prefix and --user arguments to the-    configure step, and run the install step with 'sudo' in order to-    install the library systemwide.)+     If you have cabal-install, *after* installing gtk2hs, you can+     install diagrams and the remaining dependencies with+     cabal-install: +       cabal install diagrams -Building Haddock documentation (recommended):+     Optionally, you can also pass options such as --user+     --prefix=$HOME to install locally. -    runhaskell Setup.lhs haddock+  * Option 2: manual build -    Once the documentation has been built, you can access it by -    pointing your browser to dist/doc/html/index.html.+    Once all the dependencies are built and installed, you can build+    and install diagrams as follows:+      +      runhaskell Setup.lhs configure --prefix=$HOME --user+      runhaskell Setup.lhs build+      runhaskell Setup.lhs install +    (Optionally, you can omit the --prefix and --user arguments to the+    configure step, and run the install step with 'sudo' in order to+    install the library systemwide.) -For some examples of use, see +3. Building Haddock documentation (recommended) -http://byorgey.wordpress.com/2008/04/30/new-haskell-diagrams-library/+     runhaskell Setup.lhs haddock++   Once the documentation has been built, you can access it by +   pointing your browser to dist/doc/html/diagrams/index.html.
diagrams.cabal view
@@ -1,22 +1,33 @@ Name:                diagrams-Version:             0.1+Version:             0.2 Stability:           experimental Description:         An embedded domain-specific language (EDSL) for                       creating simple diagrams, built on top of the Cairo                      rendering engine.  +Homepage:            http://code.haskell.org/diagrams Synopsis:            An EDSL for creating simple diagrams License:             BSD3 License-file:        LICENSE-Extra-source-files:  README+Extra-source-files:  README,CHANGELOG Author:              Brent Yorgey Maintainer:          byorgey@gmail.com Category:            Graphics-Build-Depends:       base,mtl,cairo Build-type:          Simple-Exposed-Modules:     Graphics.Rendering.Diagrams,+Cabal-version:       >= 1.2++flag testing+  description: Testing mode+  default: False++library+  ghc-options:         -Wall+  if flag(testing)+    ghc-options: -Werror+  Build-Depends:       base,mtl,containers,cairo,colour+  Exposed-Modules:   Graphics.Rendering.Diagrams,                      Graphics.Rendering.Diagrams.Types,+                     Graphics.Rendering.Diagrams.Paths,                      Graphics.Rendering.Diagrams.Shapes,                      Graphics.Rendering.Diagrams.Attributes,                      Graphics.Rendering.Diagrams.Layouts,-                     Graphics.Rendering.Diagrams.Colors,                      Graphics.Rendering.Diagrams.Engine