packages feed

Hieroglyph (empty) → 0.85

raw patch · 10 files changed

+982/−0 lines, 10 filesdep +IfElsedep +basedep +cairosetup-changed

Dependencies added: IfElse, base, cairo, containers, gtk, mtl

Files

+ Graphics/Rendering/Hieroglyph.hs view
@@ -0,0 +1,13 @@+module Graphics.Rendering.Hieroglyph +    (module Graphics.Rendering.Hieroglyph.UIState+    ,module Graphics.Rendering.Hieroglyph.Cairo+    ,module Graphics.Rendering.Hieroglyph.Primitives+    ,module Graphics.Rendering.Hieroglyph.Interactive+    ,module Graphics.Rendering.Hieroglyph.Colors) where++import Graphics.Rendering.Hieroglyph.UIState+import Graphics.Rendering.Hieroglyph.Cairo+import Graphics.Rendering.Hieroglyph.Primitives+import Graphics.Rendering.Hieroglyph.Interactive+import Graphics.Rendering.Hieroglyph.Colors+
+ Graphics/Rendering/Hieroglyph/BasicUIState.hs view
@@ -0,0 +1,64 @@+-- | If the items in the UIState module are the only state you need in your+--   program, then it is sufficient to import this module and start with the+--   defaultBasicState.+--+--   [@Author@] Jeff Heard+--+--   [@Copyright@] © 2008 Renaissance Computing Institute+--+module Graphics.Rendering.Hieroglyph.BasicUIState where++import qualified Graphics.Rendering.Hieroglyph.UIState as U+import Graphics.Rendering.Hieroglyph.Primitives+import qualified Graphics.UI.Gtk as Gtk+import Control.Concurrent (MVar)+import Data.Map (Map)+++-- The most basic implementation of a UIState+data BasicUIState = BasicUIState +    { mousePosition :: Point+    , mouseLeftButtonDown :: Bool+    , mouseRightButtonDown :: Bool+    , mouseMiddleButtonDown :: Bool+    , mouseWheel :: Int+    , keyCtrl :: Bool+    , keyShift :: Bool+    , keyAlt :: Bool+    , key :: U.Key +    , drawing :: Maybe Gtk.Widget +    , sizeX :: Double+    , sizeY :: Double +    , imageCache :: Maybe U.ImageCache }++instance U.UIState BasicUIState where+    mousePosition = mousePosition+    mouseLeftButtonDown = mouseLeftButtonDown+    mouseRightButtonDown = mouseRightButtonDown+    mouseMiddleButtonDown = mouseMiddleButtonDown+    mouseWheel = mouseWheel+    keyCtrl = keyCtrl+    keyShift = keyShift+    keyAlt = keyAlt+    key = key+    drawing = drawing+    sizeX = sizeX+    sizeY = sizeY+    imageCache = imageCache++    setMousePosition p a  = a{ mousePosition = p }+    setMouseLeftButtonDown p a  = a{ mouseLeftButtonDown = p }+    setMouseRightButtonDown p a  = a{ mouseRightButtonDown = p }+    setMouseMiddleButtonDown p a  = a{ mouseMiddleButtonDown = p }+    setMouseWheel p a  = a{ mouseWheel = p }+    setKeyCtrl p a  = a{ keyCtrl = p }+    setKeyShift p a  = a{ keyShift = p }+    setKeyAlt p a  = a{ keyAlt = p }+    setKey p a  = a{ key = p }+    setDrawing p a  = a{ drawing = p }+    setSizeX p a = a{ sizeX = p }+    setSizeY p a = a{ sizeY = p }+    setImageCache p a = a{ imageCache = p }++-- This is the default state you should pass to the interactive function.+defaultBasicUIState = BasicUIState (Point 0 0) False False False 0 False False False (U.Character '\0') Nothing 800 600 Nothing
+ Graphics/Rendering/Hieroglyph/Cairo.hs view
@@ -0,0 +1,340 @@+-- | Cairo backend to Hieroglyph.  Future plans include making 'StateModifier' part +--   of the base distribution and making 'Frame' the basis for all backends to +--   Hieroglyph.  The real challenge will be making all implementations /look/ the+--   same.+--+--   Note in particular that pattern functionality and Pango layouts and font+--   rendering engines are not implemented yet.  This is both because these+--   features are fairly complicated, and because I haven't figured out yet+--   how I might make them portable to OpenGL using textures and FTGL.  if +--   someone wants to take this task on, I'd be pleased as punch.+--+--      [@Author@] Jeff Heard+--      +--      [@Copyright@] &copy; 2008 Renaissance Computing Institute+--      +--      [@License@] A LICENSE file should be included as part of this distribution+--+--      [@Version@] 0.5+--+module Graphics.Rendering.Hieroglyph.Cairo where++import Data.Map (Map)+import qualified Data.Map as M+import System.Mem.Weak+import Control.Concurrent+import Control.Monad.Trans (liftIO)+import Graphics.Rendering.Hieroglyph.Primitives+import Graphics.UI.Gtk.Gdk.Pixbuf +import qualified Graphics.UI.Gtk.Cairo as Cairo+import qualified Graphics.Rendering.Cairo as Cairo+import Control.Monad+import Control.Monad.IfElse+import Data.List (foldl')+import Graphics.Rendering.Hieroglyph.UIState++-- | Modifies the way that primitives are drawn in subtrees where a 'Setup' marker +--   in the parent nodes.  All state changes are inherited lie you might think they+--   ought to be.   All colors are specified like in Cairo, using Doubles in the +--   range [0..1].+data StateModifier = +      ResetClip                                 -- ^ Reset the clipping plane+    | Translate Double Double                   -- ^ @Translate x y@ translates all subitems by x and y+    | Scale Double Double                       -- ^ @Scale x y@ scales the subitems by x and y  +    | Rotate Double                             -- ^ @Rotate r@ everything clockwise by r radians+    | Font String                               -- ^ Set the font family.  See 'Graphics.Rendering.Cairo.selectFontFace' for behaviour.+    | FontSlant Cairo.FontSlant                 -- ^ Set the font slant. +    | FontWeight Cairo.FontWeight               -- ^ Set the font weight. +    | FillRule Cairo.FillRule                   -- ^ Set the way patterns are filled.  Does nothing if you haven't yet set the pattern yourself.+    | FillRed Double                            -- ^ Set the fill color's red component without changing anything else+    | FillGreen Double                          -- ^ Set the fill color's green component without changing anything else+    | FillBlue Double                           -- ^ Set the fill color's blue component without changing anything else+    | FillAlpha Double                          -- ^ Set the fill color's alpha component without changing anything else+    | FillRGB Double Double Double              -- ^ @FillRGB r g b@ sets the fill RGB to r g b and the alpha component to 1+    | StrokeRGB Double Double Double           -- ^ @StrokeRGB r g b@ sets the stroke RGB to r g b and the alpha component to 1+    | StrokeRGBA Double Double Double Double   -- ^ @StrokeRGBA r g b a@ sets the stroke color+    | FillRGBA Double Double Double Double      -- ^ @FillRGBA r g b a@ sets the fill color+    | Dash [Double] Double                      -- ^ @Dash pattern width@ sets the dash pattern for lines (OpenGL will need to use a stipple pattern, I think) +    | StrokeRed Double                         -- ^ Set the stroke color's red component without changing anything else+    | StrokeGreen Double                       -- ^ Set the stroke color's green component without changing anything else+    | StrokeBlue Double                        -- ^ Set the stroke color's blue component without changing anything else+    | StrokeAlpha Double                       -- ^ Set the stroke color's alpha component without changing anything else+    | Antialias Cairo.Antialias                 -- ^ Set the way antialiasing is performed.  This may be non-portable between Cairo and OpenGL without employing a shader+    | LineCap Cairo.LineCap                     -- ^ Set the line cap style+    | LineJoin Cairo.LineJoin                   -- ^ Set the line join style+    | LineWidth Double                          -- ^ Set the width of the line in points+    | MiterLimit Double                         -- ^ Set the miter limit for corners+    | Tolerance Double                          -- ^ Set the trapezoidal tolerance. This may be irrelevant in OpenGL, but it controls the quality of lines in Cairo.+    | Operator Cairo.Operator                   -- ^ Set the way the source is transferred to the surface through the stencil.  Emulating this functionality in OpenGL may be difficult.+    | CurrentPoint Point                      -- ^ Set the current point that the pen is at.  Note that this only sets it, any changes made to the current point by the children are still changes.  To ensure that this is the current point, use a 'Pen' draw command.++-- | A tree structure that defines a frame.  The first argument is either a +--   'Draw' or a 'Setup' command and the list is a list of children. +data Object = Group [Object]+            | Draw Primitive+            | Context [StateModifier] Object++-- | The current state of the renderer.  Carried down the tree and modified with 'StateModifier' 'Node's. +data RendererState = RendererState+    { fontfamily   :: String                    -- ^ The font name+    , fontslant    :: Cairo.FontSlant           -- ^ The font slant+    , fontsize     :: Double                    -- ^ The font size in points+    , fontweight   :: Cairo.FontWeight          -- ^ The font weight+    , fillrule     :: Cairo.FillRule            -- ^ The pattern fill rule+    , fillred      :: Double                    -- ^ The red component of the fill color in the range [0..1]+    , fillgreen    :: Double                    -- ^ The green component of the fill color in the range [0..1]+    , fillblue     :: Double                    -- ^ The blue component of the fill color in the range [0..1]+    , fillalpha    :: Double                    -- ^ The alpha component of the fill color in the range [0..1]+    , dash         :: Maybe ([Double],Double)   -- ^ The shape of the line dashing, if any+    , strokered   :: Double                    -- ^ The red component of the stroke color in the range [0..1]+    , strokegreen :: Double                    -- ^ The red component of the stroke color in the range [0..1]+    , strokeblue  :: Double                    -- ^ The red component of the stroke color in the range [0..1]+    , strokealpha :: Double                    -- ^ The red component of the stroke color in the range [0..1]+    , antialias    :: Cairo.Antialias           -- ^ The way things are antialiased+    , linecap      :: Cairo.LineCap             -- ^ The way lines are capped+    , linejoin     :: Cairo.LineJoin            -- ^ The way lines are joined+    , linewidth    :: Double                    -- ^ The width of a line in points+    , miterlimit   :: Double                    -- ^ The miter limit of lines.  See Cairo's documentation+    , tolerance    :: Double                    -- ^ The trapezoidal tolerance.  See Cairo's documentation+    , operator     :: Cairo.Operator            -- ^ The transfer operator.  See Cairo's documentation for more <http://cairographics.org>+    , currentpoint :: Point                   -- ^ Current base point for the first child's graphics operation +    , translatex   :: Double                    -- ^ The current translation x component+    , translatey   :: Double                    -- ^ The current translation y component    +    , scalex       :: Double                    -- ^ The current scale x component+    , scaley       :: Double                    -- ^ The current scale y component+    , rotation     :: Double }                  -- ^ The current clockwise rotation in radians.++fillStrokeAndClip state isfilled isoutlined isclipped = do +    when isfilled $ +        Cairo.setSourceRGBA (fillred state) (fillgreen state) (fillblue state) (fillalpha state) >> +        if isoutlined then Cairo.fillPreserve else Cairo.fill+    when isoutlined $ +        Cairo.setSourceRGBA (strokered state) (strokegreen state) (strokeblue state) (strokealpha state) >>+        Cairo.stroke+    when isclipped $ Cairo.clip++-- | @renderPrimitive state prim@ draws a single primitive.+renderPrimitive :: ImageCache -> RendererState -> Primitive -> Cairo.Render ()+renderPrimitive _ state (Arc (Point cx cy) radius angle0 angle1 isnegative f o c) = do+    if isnegative +        then Cairo.arcNegative cx cy radius angle0 angle1 +        else Cairo.arc cx cy radius angle0 angle1+    fillStrokeAndClip state f o c++renderPrimitive _ state (Curve (Point ox oy) segs isclosed f o c) = do +    Cairo.moveTo ox oy+    forM_ segs $ \(Point x1 y1,Point x2 y2,Point x3 y3) -> Cairo.curveTo x1 y1 x2 y2 x3 y3+    when isclosed (Cairo.lineTo ox oy)+    fillStrokeAndClip state f o c++renderPrimitive _ state (Line (Point ox oy) segs isclosed f o c) = do+    Cairo.moveTo ox oy+    mapM (\seg -> case seg of Point x y -> Cairo.lineTo x y) segs+    when isclosed (Cairo.lineTo ox oy)+    fillStrokeAndClip state f o c++renderPrimitive images state i@(Image filename (Left (Point ox oy)) _) = do+    pbuf <- loadImage images i+    w <- liftIO $ pixbufGetWidth pbuf+    h <- liftIO $ pixbufGetHeight pbuf+    Cairo.save+    Cairo.setSourcePixbuf pbuf ox oy+    Cairo.rectangle ox oy (fromIntegral w) (fromIntegral h)+    Cairo.fill+    Cairo.restore+renderPrimitive images state i@(Image filename (Right (Rect ox oy w h)) _) = do+    pbuf <- loadImage images i+    Cairo.save+    Cairo.setSourcePixbuf pbuf ox oy+    Cairo.rectangle ox oy w h+    Cairo.fill+    Cairo.restore++renderPrimitive _ _ Hidden = return () +renderPrimitive _ _ (Pen (Point ox oy)) = Cairo.moveTo ox oy+renderPrimitive _ state (Rectangle (Point ox oy) w h f o c) = Cairo.rectangle ox oy w h >> fillStrokeAndClip state f o c+renderPrimitive _ state (Text str (Point ox oy) f o c) = Cairo.showText str >> fillStrokeAndClip state f o c+renderPrimitive images state (Compound prims f o c) = mapM (renderPrimitive images state . unfoc) prims >> fillStrokeAndClip state f o c+    where unfoc prim = prim{ filled=False, outlined=False, clipped=False }++-- | The initial state of Cairo, encoded as an object.+defaultState :: RendererState+defaultState = +    RendererState +        { fontfamily = "arial"+        , fontslant = Cairo.FontSlantNormal+        , fontweight = Cairo.FontWeightNormal+        , fontsize = 10+        , fillrule = Cairo.FillRuleWinding+        , fillred = 1+        , fillgreen = 1+        , fillblue = 1+        , fillalpha = 1+        , dash = Nothing+        , strokered = 1+        , strokegreen = 1+        , strokeblue = 1+        , strokealpha = 1+        , antialias = Cairo.AntialiasDefault+        , linecap = Cairo.LineCapButt+        , linejoin = Cairo.LineJoinMiter+        , linewidth = 1+        , miterlimit = 0+        , tolerance = 0.1+        , operator = Cairo.OperatorOver+        , currentpoint = origin +        , translatex = 0+        , translatey = 0+        , scalex = 1+        , scaley = 1+        , rotation = 0 } ++-- | Load the Cairo state machine with a 'RenderState' object.+loadStateIntoCairo :: RendererState -> Cairo.Render ()+loadStateIntoCairo s = do+    Cairo.selectFontFace (fontfamily s) (fontslant s) (fontweight s)+    Cairo.setFillRule . fillrule $ s+    awhen (dash s) $ \(a,b) -> Cairo.setDash a b+    Cairo.setAntialias . antialias $ s+    Cairo.setLineCap . linecap $ s+    Cairo.setLineJoin . linejoin $ s+    Cairo.setLineWidth . linewidth $ s+    Cairo.setMiterLimit . miterlimit $ s+    Cairo.setTolerance . tolerance $ s+    Cairo.setOperator . operator $ s+    case currentpoint s of (Point px py) -> Cairo.moveTo px py+    Cairo.translate (translatex s) (translatey s)+    Cairo.scale (scalex s) (scaley s)+    Cairo.rotate (rotation s)++changeRenderState :: RendererState -> [StateModifier] -> Cairo.Render RendererState+changeRenderState state changes = do+    let state' = foldl' applyStateChangeToLocalEnv state changes+    mapM (applyStateChangeToCairo state') changes+    return state'++applyStateChangeToLocalEnv state ResetClip = state+applyStateChangeToLocalEnv state (Translate byx byy) = state{ translatex = byx, translatey = byy }+applyStateChangeToLocalEnv state (Scale byx byy) = state{ scalex = byx, scaley = byy }+applyStateChangeToLocalEnv state (Rotate by) = state{ rotation = by }+applyStateChangeToLocalEnv state (Font s) = state{ fontfamily=s }+applyStateChangeToLocalEnv state (FontSlant s) = state{ fontslant=s }+applyStateChangeToLocalEnv state (FontWeight s) = state{ fontweight=s }+applyStateChangeToLocalEnv state (FillRule s) = state{ fillrule=s }+applyStateChangeToLocalEnv state (FillRed s) = state{ fillred=s }+applyStateChangeToLocalEnv state (FillGreen s) = state{ fillgreen=s }+applyStateChangeToLocalEnv state (FillBlue s) = state{ fillblue=s }+applyStateChangeToLocalEnv state (FillAlpha s) = state{ fillalpha=s }+applyStateChangeToLocalEnv state (Dash a b) = state{ dash=Just (a,b)  }+applyStateChangeToLocalEnv state (StrokeRed s) = state{ strokered=s }+applyStateChangeToLocalEnv state (StrokeGreen s) = state{ strokegreen=s }+applyStateChangeToLocalEnv state (StrokeBlue s) = state{ strokeblue=s }+applyStateChangeToLocalEnv state (StrokeAlpha s) = state{ strokealpha=s }+applyStateChangeToLocalEnv state (Antialias s) = state{ antialias=s }+applyStateChangeToLocalEnv state (LineCap s) = state{ linecap=s }+applyStateChangeToLocalEnv state (LineJoin s) = state{ linejoin=s }+applyStateChangeToLocalEnv state (LineWidth s) = state{ linewidth=s } +applyStateChangeToLocalEnv state (MiterLimit s) = state{ miterlimit=s }+applyStateChangeToLocalEnv state (Tolerance s) = state{ tolerance=s }+applyStateChangeToLocalEnv state (Operator s) = state{ operator=s }+applyStateChangeToLocalEnv state (CurrentPoint s) = state{ currentpoint=s }+applyStateChangeToLocalEnv state (FillRGB r g b) = state{ fillred = r, fillgreen = g, fillblue = b }+applyStateChangeToLocalEnv state (FillRGBA r g b a) = state{ fillred = r, fillgreen = g, fillblue = b , fillalpha = a }+applyStateChangeToLocalEnv state (StrokeRGB r g b) = state{ strokered = r, strokegreen=g, strokeblue = b }+applyStateChangeToLocalEnv state (StrokeRGBA r g b a) = state{strokered = r, strokegreen=g, strokeblue = b, strokealpha = a } ++applyStateChangeToCairo state ResetClip = Cairo.resetClip+applyStateChangeToCairo state (Translate byx byy) = Cairo.translate byx byy+applyStateChangeToCairo state (Scale byx byy) = Cairo.scale byx byy+applyStateChangeToCairo state (Rotate by) = Cairo.rotate by+applyStateChangeToCairo state (Font s) = Cairo.selectFontFace s (fontslant state) (fontweight state)+applyStateChangeToCairo state (FontSlant s) = Cairo.selectFontFace (fontfamily state) s (fontweight state)+applyStateChangeToCairo state (FontWeight s) = Cairo.selectFontFace (fontfamily state) (fontslant state) s+applyStateChangeToCairo state (FillRule s) = Cairo.setFillRule s+applyStateChangeToCairo state (FillRed s) = return ()+applyStateChangeToCairo state (FillGreen s) = return ()+applyStateChangeToCairo state (FillBlue s) = return ()+applyStateChangeToCairo state (FillAlpha s) = return ()+applyStateChangeToCairo state (Dash a b) = Cairo.setDash a b+applyStateChangeToCairo state (StrokeRed s) = return ()+applyStateChangeToCairo state (StrokeGreen s) = return ()+applyStateChangeToCairo state (StrokeBlue s) = return ()+applyStateChangeToCairo state (StrokeAlpha s) = return ()+applyStateChangeToCairo state (Antialias s) = Cairo.setAntialias s+applyStateChangeToCairo state (LineCap s) = Cairo.setLineCap s+applyStateChangeToCairo state (LineJoin s) = Cairo.setLineJoin s+applyStateChangeToCairo state (LineWidth s) = Cairo.setLineWidth s+applyStateChangeToCairo state (MiterLimit s) = Cairo.setMiterLimit s+applyStateChangeToCairo state (Tolerance s) = Cairo.setTolerance s+applyStateChangeToCairo state (Operator s) = Cairo.setOperator s+applyStateChangeToCairo state (CurrentPoint (Point px py)) = Cairo.moveTo px py+applyStateChangeToCairo state (FillRGB r g b) = return ()+applyStateChangeToCairo state (FillRGBA r g b a) = return ()+applyStateChangeToCairo state (StrokeRGB r g b) = return ()+applyStateChangeToCairo state (StrokeRGBA r g b a) = return ()+++renderObject :: ImageCache -> Object -> Cairo.Render () +renderObject images = renderObjectWithState images defaultState ++renderObjectWithState :: ImageCache -> RendererState -> Object -> Cairo.Render ()+renderObjectWithState images state (Group objects) = mapM_ (renderObjectWithState images state) objects+renderObjectWithState images state (Draw prim) = renderPrimitive images state prim+renderObjectWithState images state (Context setup object) = do +    Cairo.save+    state' <- changeRenderState state setup+    renderObjectWithState images state' object+    Cairo.restore+    loadStateIntoCairo state++-- | @renderFrameToSurface surface frame@ renders a frame to a particular surface+renderObjectToSurfaceWithImageCache :: ImageCache ->  Cairo.Surface -> Object -> IO ()+renderObjectToSurfaceWithImageCache images surf frame = Cairo.renderWith surf (renderObject images frame)++renderObjectToSurface :: Cairo.Surface -> Object -> IO ()+renderObjectToSurface s o = do { i <- initImageCache; renderObjectToSurfaceWithImageCache i s o }++-- | @renderframeToPNGWithImageCache  filename xres yres frame@ renders a frame to an image file+renderObjectToPNGWithImageCache  :: ImageCache -> FilePath -> Int -> Int -> Object -> IO ()+renderObjectToPNGWithImageCache images filename xres yres frame = Cairo.withImageSurface Cairo.FormatARGB32 xres yres $ \s -> renderObjectToSurfaceWithImageCache images s frame >> Cairo.surfaceWriteToPNG s filename+renderObjectToPNG f w h o = do { i <- initImageCache ; renderObjectToPNGWithImageCache i f w h o }++-- | @renderObjectToPDFWithImageCache  filename width height frame@ renders a frame to a PDF file.  width and height are in points.+renderObjectToPDFWithImageCache  :: ImageCache -> FilePath -> Double -> Double -> Object -> IO ()+renderObjectToPDFWithImageCache images filename width height frame = Cairo.withPDFSurface filename width height $ \s -> renderObjectToSurfaceWithImageCache images s frame+renderObjectToPDF f w h o = do { i <- initImageCache ; renderObjectToPDFWithImageCache i f w h o } ++-- | @renderObjectToPostscriptWithImageCache  filename width height frame@ renders a frame to a Postscript file.  width and height are in points.+renderObjectToPostscriptWithImageCache  :: ImageCache -> FilePath -> Double -> Double -> Object -> IO ()+renderObjectToPostscriptWithImageCache  images filename width height frame = Cairo.withPSSurface filename width height $ \s -> renderObjectToSurfaceWithImageCache images s frame+renderObjectToPostscript f w h o = do { i <- initImageCache ; renderObjectToPostscriptWithImageCache i f w h o }++-- | @renderObjectToSVGWithImageCache  filename width height frame@ renders a frame to a SVG file.  width and height are in points.+renderObjectToSVGWithImageCache  :: ImageCache -> FilePath -> Double -> Double -> Object -> IO ()+renderObjectToSVGWithImageCache images filename width height frame = Cairo.withSVGSurface filename width height $ \s -> renderObjectToSurfaceWithImageCache images s frame+renderObjectToSVG f w h o = do { i <- initImageCache ; renderObjectToSVGWithImageCache i f w h o }++-- | @loadImage dictRef image@ pulls an image out of the cache's hat.+loadImage :: ImageCache -> Primitive -> Cairo.Render (Pixbuf)+loadImage dictRef im@(Image filename (Right (Rect x y w h)) aspect) = do+  liftIO $ modifyMVar dictRef $ \dict -> +    if (show im) `M.member` dict+      then do value <- deRefWeak $ dict M.! (show im)+              pbuf <- case value of+                          Just pb -> return pb +                          Nothing -> pixbufNewFromFileAtScale filename (round w) (round h) aspect+              return (dict,pbuf)+      else do pbuf <- pixbufNewFromFileAtScale filename (round w) (round h) aspect+              wk <-  mkWeakPtr pbuf Nothing+              return ((M.insert (show im) wk dict), pbuf)+loadImage dictRef im@(Image filename (Left (Point x y)) _) = do+  liftIO $ modifyMVar dictRef $ \dict -> +    if (show im) `M.member` dict+      then do value <- deRefWeak $ dict M.! (show im)+              pbuf <- case value of+                          Just pb -> return pb +                          Nothing -> pixbufNewFromFile filename +              return (dict,pbuf)+      else do pbuf <- pixbufNewFromFile filename +              wk <-  mkWeakPtr pbuf Nothing+              return ((M.insert (show im) wk dict), pbuf)
+ Graphics/Rendering/Hieroglyph/Colors.hs view
@@ -0,0 +1,77 @@+module Graphics.Rendering.Hieroglyph.Colors where++import Graphics.Rendering.Hieroglyph.Cairo++strokeWhite = StrokeRGBA 1 1 1 1+strokeBlack = StrokeRGBA 0 0 0 1+strokeRed = StrokeRGBA 1 0 0 1+strokeGreen = StrokeRGBA 0 1 0 1+strokeBlue = StrokeRGBA 0 0 1 1+strokeYellow = StrokeRGBA 1 1 0 1+strokeViolet = StrokeRGBA 1 0 1 1+strokeCyan = StrokeRGBA 0 1 1 1+strokeDarkRed = attenuate 0.5 strokeRed+strokeDarkGreen = attenuate 0.5 strokeGreen+strokeDarkBlue = attenuate 0.5 strokeBlue+strokeDarkYellow = attenuate 0.5 strokeYellow +strokeDarkViolet = attenuate 0.5 strokeViolet+strokeDarkCyan = attenuate 0.5 strokeCyan++strokeGrey90 = attenuate 0.9 strokeWhite+strokeGrey80 = attenuate 0.8 strokeWhite+strokeGrey70 = attenuate 0.7 strokeWhite+strokeGrey60 = attenuate 0.6 strokeWhite+strokeGrey50 = attenuate 0.5 strokeWhite+strokeGrey40 = attenuate 0.4 strokeWhite+strokeGrey30 = attenuate 0.3 strokeWhite+strokeGrey20 = attenuate 0.2 strokeWhite+strokeGrey10 = attenuate 0.1 strokeWhite++fillWhite = FillRGBA 1 1 1 1+fillBlack = FillRGBA 0 0 0 1+fillRed = FillRGBA 1 0 0 1+fillGreen = FillRGBA 0 1 0 1+fillBlue = FillRGBA 0 0 1 1+fillYellow = FillRGBA 1 1 0 1+fillViolet = FillRGBA 1 0 1 1+fillCyan = FillRGBA 0 1 1 1+fillDarkRed = attenuate 0.5 fillRed+fillDarkGreen = attenuate 0.5 fillGreen+fillDarkBlue = attenuate 0.5 fillBlue+fillDarkYellow = attenuate 0.5 fillYellow +fillDarkViolet = attenuate 0.5 fillViolet+fillDarkCyan = attenuate 0.5 fillCyan++fillGrey90 = attenuate 0.9 fillWhite+fillGrey80 = attenuate 0.8 fillWhite+fillGrey70 = attenuate 0.7 fillWhite+fillGrey60 = attenuate 0.6 fillWhite+fillGrey50 = attenuate 0.5 fillWhite+fillGrey40 = attenuate 0.4 fillWhite+fillGrey30 = attenuate 0.3 fillWhite+fillGrey20 = attenuate 0.2 fillWhite+fillGrey10 = attenuate 0.1 fillWhite++toStroke (FillRGBA r g b a) = (StrokeRGBA r g b a)+toStroke (StrokeRGBA r g b a) = (StrokeRGBA r g b a)+toFill (StrokeRGBA r g b a) = (FillRGBA r g b a)+toFill (FillRGBA r g b a) = (FillRGBA r g b a)++unattenuate by (FillRGBA r g b a) = FillRGBA (clamp 0 1 $ (1+by)*r) (clamp 0 1 $ (1+by)*g) (clamp 0 1 $ (1+by)*b) a+unattenuate by (StrokeRGBA r g b a) = StrokeRGBA (clamp 0 1 $ (1+by)*r) (clamp 0 1 $ (1+by)*g) (clamp 0 1 $ (1+by)*b) a+attenuate by (FillRGBA r g b a) = FillRGBA (clamp 0 1 $ by*r) (clamp 0 1 $ by*g) (clamp 0 1 $ by*b) a+attenuate by (StrokeRGBA r g b a) = StrokeRGBA (clamp 0 1 $ by*r) (clamp 0 1 $ by*g) (clamp 0 1 $ by*b) a+fade by (FillRGBA r g b a) = FillRGBA r g b (clamp 0 1 $ by*a)+fade by (StrokeRGBA r g b a) = StrokeRGBA r g b (clamp 0 1 $ by*a)+unfade by (FillRGBA r g b a) = FillRGBA r g b (clamp 0 1 $ (1+by)*a)+unfade by (StrokeRGBA r g b a) = StrokeRGBA r g b (clamp 0 1 $ (1+by)*a)++mix ratio (FillRGBA r1 g1 b1 a1) (FillRGBA r2 g2 b2 a2) = (FillRGBA r' g' b' a') +    where r' = clamp 0 1 $ (r1+r2) * ratio+          g' = clamp 0 1 $ (g1+g2) * ratio+          b' = clamp 0 1 $ (b1+b2) * ratio+          a' = clamp 0 1 $ (a1+a2) * ratio++clamp lo hi val = min hi (max lo val)++
+ Graphics/Rendering/Hieroglyph/Interactive.hs view
@@ -0,0 +1,234 @@+-- | An interactive scene graph library for Cairo +--+--   [@Author@] Jeff Heard+--+--   [@Copyright@] &copy; 2008 Renaissance Computing Institute+--+module Graphics.Rendering.Hieroglyph.Interactive where++import Graphics.Rendering.Hieroglyph.Primitives+import Graphics.Rendering.Hieroglyph.Cairo+import Graphics.Rendering.Hieroglyph.UIState+import qualified Graphics.UI.Gtk.Cairo as Gtk+import qualified Graphics.Rendering.Cairo as Cairo+import qualified Graphics.UI.Gtk as Gtk++import Data.List+import Data.Maybe+import Control.Monad+import Control.Concurrent.MVar++-- | A scene element.  This is the basic building block of your interactive app.+data SceneElement a = +      StaticElement Object Rect               -- ^ An unreactive element in the scene.  Not modified by program state.+    | BoundedElement (a -> Object) Rect       -- ^ A reactive, but bounded element in the scene.   The element reacts to a UIState instance, but is confined within a particular rectangle.  +    | UnboundedElement (a -> Object)            -- ^ An unbounded reactive element in the scene.  The element reacts to a UIState instance, but can go anywhere in the scene.  +    | BoundedActiveElement (a -> (a, Object)) Rect +    | UnboundedActiveElement (a -> (a,Object)) ++-- | The scene itself+type Scene a = [SceneElement a] ++-- | Applies the current UIState instance to a single scene element, returning an Object+--   FIXME: Should do bounds checking.+renderSceneElement :: UIState a => a -> SceneElement a -> (a, Object)+renderSceneElement uistate (StaticElement obj _) = (uistate, obj)+renderSceneElement uistate (BoundedElement obj _) = (uistate, obj uistate)+renderSceneElement uistate (UnboundedElement obj) = (uistate, obj uistate)+renderSceneElement uistate (BoundedActiveElement obj _) = obj uistate+renderSceneElement uistate (UnboundedActiveElement obj) = obj uistate++-- | @renderScene state scene@ applies the current UIState to the entire scene+renderScene :: UIState a => a -> Scene a -> (a, Object)+renderScene state elts = (state', Group objs)+	where (state', objs) = mapAccumL renderSceneElement state elts++-- | Gets the keyboard state from Gtk and changes the UIState.  You do not need+--   to call this in your own code+keyboardHandler :: UIState a => MVar a -> Scene a ->Gtk.Event -> IO Bool+keyboardHandler uistate_mvar scene event = do+    let k = case Gtk.eventKeyName event of +                "Insert" -> Insert+                "Delete" -> Delete+                "Enter" -> Enter+                "F1" -> PF1+                "F2" -> PF2+                "F3" -> PF3+                "F4" -> PF4+                "F5" -> PF5+                "F6" -> PF6+                "F7" -> PF7+                "F8" -> PF8+                "F9" -> PF9+                "F10" -> PF10+                "F11" -> PF11+                "F12" -> PF12+                "Home" -> Home+                "End" -> End+                "PageUp" -> PgUp+                "PageDown" -> PgDown+                [x] -> Character x+                _ -> Character '\0'+    modifyMVar_ uistate_mvar $ return . setKey k+    withMVar uistate_mvar $ \s -> do+        dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ s+        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . sizeX $ s) (round . sizeY $ s)) False+    return False+    +-- | Gets the mouse position and changes the UIState to reflect it.  YOu do not need this in your own code.+mouseMotionHandler :: UIState a => MVar a -> Gtk.Event -> IO Bool+mouseMotionHandler uistate_mvar event = do +    state <- takeMVar uistate_mvar+    putMVar uistate_mvar +        $ setMousePosition (Point (Gtk.eventX event) (Gtk.eventY event)) state+    dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ state+    Gtk.drawWindowGetPointer dwin+    Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . sizeX $ state) (round . sizeY $ state)) False+    return False++mouseReleaseHandler :: UIState a => MVar a -> Scene a -> Gtk.Event -> IO Bool+mouseReleaseHandler uistate_mvar scene event = do+    let x = Gtk.eventX event+        y = Gtk.eventY event+        button = Gtk.eventButton event+        modifiers = Gtk.eventModifier event+        shift = elem Gtk.Shift modifiers+        alt = elem Gtk.Alt modifiers+        ctrl = elem Gtk.Control modifiers+    +    modifyMVar_ uistate_mvar +        $ return +        . setMousePosition (Point x y)+        . setKeyShift shift+        . setKeyAlt alt+        . setKeyCtrl ctrl+        . (case button of+            Gtk.LeftButton -> setMouseLeftButtonDown False+                                . setMouseWheel 0 +            Gtk.RightButton -> setMouseRightButtonDown False+                                . setMouseWheel 0+            Gtk.MiddleButton -> setMouseRightButtonDown False+                                . setMouseWheel 0)+    withMVar uistate_mvar $ \s -> do+        dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ s+        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . sizeX $ s) (round . sizeY $ s)) False+    return True++-- | Gets the mouse button state and changes the UIState to reflect it.  You do not need this in your own code.+mouseButtonHandler :: UIState a => MVar a -> Scene a -> Gtk.Event -> IO Bool+mouseButtonHandler uistate_mvar scene event = do+    let x = Gtk.eventX event+        y = Gtk.eventY event+        button = Gtk.eventButton event+        modifiers = Gtk.eventModifier event+        shift = elem Gtk.Shift modifiers+        alt = elem Gtk.Alt modifiers+        ctrl = elem Gtk.Control modifiers+    +    modifyMVar_ uistate_mvar +        $ return +        . setMousePosition (Point x y)+        . setKeyShift shift+        . setKeyAlt alt+        . setKeyCtrl ctrl+        . (case button of+            Gtk.LeftButton -> setMouseLeftButtonDown True+                                . setMouseRightButtonDown False+                                . setMouseMiddleButtonDown False+                                . setMouseWheel 0 +            Gtk.RightButton -> setMouseLeftButtonDown False+                                . setMouseRightButtonDown True+                                . setMouseMiddleButtonDown False+                                . setMouseWheel 0+            Gtk.MiddleButton -> setMouseLeftButtonDown False+                                . setMouseRightButtonDown False+                                . setMouseRightButtonDown True+                                . setMouseWheel 0)+    withMVar uistate_mvar $ \s -> do+        dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ s+        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . sizeX $ s) (round . sizeY $ s)) False+    return True++-- | Window resize handler. Changes the UIState to reflect the new sizing.  You do not need this in your own code.+resize state scene event = do+    let sizex = Gtk.eventWidth event+        sizey = Gtk.eventHeight event+    modifyMVar_ state $ return . setSizeX (fromIntegral sizex) . setSizeY (fromIntegral sizey)+    withMVar state $ \s -> do+        dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ s+        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 sizex sizey) False+    return False++-- | Render function.  All Cairo is called through here.  You do not need to call this in your own code.+renderer :: UIState a => MVar a -> Scene a -> IO ()+renderer state scene = modifyMVar_ state $ \st -> do+    dwin <- Gtk.widgetGetDrawWindow . fromJust . drawing $ st+    let (state',object) = renderScene st scene+    Gtk.renderWithDrawable dwin $ (renderObject (fromJust (imageCache st)) object)+    return state'+           ++-- | A lowish level funtion for creating a GUI.  Does not set the size of the+--   window or expose any windows.+guiInit :: UIState a +        => MVar a           -- ^ The current UIState +        -> Scene a          -- ^ The scene graph to render+        -> String           -- ^ The name of the window +        -> Bool             -- ^ Whether or not to make this GUI motion sensitive+        -> IO Gtk.Window    -- ^ Returns the window that was created+guiInit state scene name motionSensitive = do +    Gtk.unsafeInitGUIForThreadedRTS++    window <- Gtk.windowNew+    canvas <- Gtk.drawingAreaNew+    Gtk.windowSetTitle window name+    Gtk.containerAdd window canvas+    imgcache <- initImageCache++    modifyMVar_ state $ return . setDrawing (Just . Gtk.castToWidget $ canvas) . setImageCache (Just imgcache)++    Gtk.onExpose canvas $ \evt -> renderer state scene >> return True+    Gtk.onConfigure window $ resize state scene+    Gtk.onButtonPress canvas $ mouseButtonHandler state scene+    Gtk.onButtonRelease canvas $ mouseReleaseHandler state scene+    Gtk.onKeyPress window $ keyboardHandler state scene+    when motionSensitive $ (Gtk.onMotionNotify canvas True $ mouseMotionHandler state) >> return ()+    return window++-- | A higher level function for creating a GUI.  Does not set the size of the +--   window or expose any windows, but does kill the app if this window is +--   closed+guiConstruct :: UIState a +             => a           -- ^ The default UIState+             -> Scene a     -- ^ The scene to render+             -> String      -- ^ The name of the scene+             -> Bool        -- ^ Whether or not this GUI is motion sensitive+             -> IO Gtk.Window+guiConstruct state scene name motionSensitive = do+    mvar <- newMVar state+    window <- guiInit mvar scene name motionSensitive+    Gtk.onDestroy window Gtk.mainQuit+    return window++-- | A high level function for creating a GUI.  Just specify a default+--   state, the name of the scene, and the scene, and you get an 800 by+--   600 motion insensitive GUI.+simpleGui :: UIState a +          => a +          -> Scene a +          -> String +          -> IO ()+simpleGui state scene name = do+    win <- guiConstruct state scene name False+    Gtk.windowSetDefaultSize win 800 600+    Gtk.widgetShowAll win+    Gtk.mainGUI++-- | A high level function for creating a GUI.  Just specify the default+--   state, the name of the scene, and the scene, and you get an 800 by+--   600 motion sensitive GUI+simpleMotionSensitiveGui state scene name = do+    win <- guiConstruct state scene name True+    Gtk.windowSetDefaultSize win 800 600+    Gtk.widgetShowAll win+    Gtk.mainGUI
+ Graphics/Rendering/Hieroglyph/Primitives.hs view
@@ -0,0 +1,136 @@+-- | This is Hieroglyph, a 2D scenegraph library similar in functionality to a barebones+--   stripped down version of Processing, but written in a purely functional manner.+--+--   See individual implementations (like the Graphics.Rendering.Hieroglyph.Cairo module)+--   for more information on how to use this library.+--+--      [@Author@] Jeff Heard+--      +--      [@Copyright@] &copy; 2008 Renaissance Computing Institute+--      +--      [@License@] A LICENSE file should be included as part of this distribution+--+--      [@Version@] 0.5+--+module Graphics.Rendering.Hieroglyph.Primitives where++import qualified Graphics.Rendering.Cairo as Cairo++-- | A 2D point+data Point = Point Double Double deriving (Show, Read, Eq)++data Rect = Rect Double Double Double Double deriving (Show, Read, Eq)++-- | A 2D primitive in an arbitrary Cartesian 2d space+data Primitive =       +      -- | An arc+      Arc                                               -- A possibly filled pie slice or arc+        { center   :: Point                           -- ^ center of the arc+        , radius   :: Double                            -- ^ radius of the arc+        , angle1   :: Double                            -- ^ begin angle+        , angle2   :: Double                            -- ^ end angle+        , negative :: Bool                              -- ^ whether or not to consider this a slice of or a slice out of the pie+        , filled   :: Bool                              -- ^ pie, or just crust?+        , outlined :: Bool                              -- ^ crustless pie?+        , clipped  :: Bool  -- ^ add this to the clipping plane+        }                           +    -- | A cubic spline+    | Curve                                             -- An arbitrary cubic spline+        { begin    :: Point                           -- ^ starting point+        , curve_segments :: [(Point,Point,Point)] -- ^ A sequential list of curve segments.  Note that the first two points are control points.+        , closed   :: Bool                              -- ^ Whether or not to close this curve with a final line+        , filled   :: Bool                              -- ^ Whether or not to fill the curve+        , outlined :: Bool                              -- ^ Whether or not to outline the curve+        , clipped  :: Bool                            -- ^ Add the curve to the clipping plane+        }+    -- | A series of straight lines+    | Line                                              -- An arbitrary series of line segments+        { begin    :: Point                           -- ^ Starting Point+        , segments :: [Point]                         -- ^ Line segments.+        , closed   :: Bool                              -- ^ Whether or not to finish this curve with a last line from the end segment to the begin point.+        , filled   :: Bool                              -- ^ Whether or not to fill the curve+        , outlined :: Bool                              -- ^ Whether or not to draw the outline+        , clipped  :: Bool                             -- ^ Add to the clipping plane+        }+    -- | Move the pen+    | Pen +        { moveto :: Point -- ^ Move the current point.  Matters for arcs sometimes.  May remove the begin point for Curve and Line in favor of this.+        }                           +    -- | A rectangle+    | Rectangle                                         -- An possibly filled rectangle+        { topleft  :: Point                           -- ^ The top left point+        , width    :: Double                            -- ^ The width+        , height   :: Double                            -- ^ The height+        , filled   :: Bool                              -- ^ Fill the rectangle?+        , outlined :: Bool                              -- ^ Draw the outline?+        , clipped  :: Bool                             -- ^ Add to the clipping plane?+        }+    -- | A simple text object+    | Text                                              -- A simple text string+        { str        :: String                          -- ^ The string to print  +        , bottomleft :: Point                         -- ^ The anchor point for the text.  Baseline, not bottom.+        , filled     :: Bool                            -- ^ Fill the text?  Usually you want this and not outline.+        , outlined   :: Bool                            -- ^ Draw the outline?+        , clipped     :: Bool                         -- ^ Add to the clipping plane? +        }+    -- | A compound object+    | Compound                                          -- Use this to create an arbitrary shape before calling fill, stroke, and clip.+        { primitives :: [Primitive]                     -- ^ primitives to use+        , filled :: Bool                                -- ^ fill the result?+        , outlined :: Bool                              -- ^ outline the result?+        , clipped :: Bool                              -- ^ clip the result?+        }+    | Image +        { filename :: String+        , dimensions :: Either Point Rect+        , preserveaspect :: Bool+        }+    | Hidden +    deriving (Show,Read,Eq)++-- | the origin point+origin :: Point+origin = Point 0 0 ++arc :: Primitive -- ^ A unit circle by default, modifiable with record syntax.+arc = Arc origin 1 0 (2*pi) False False True False++arcFilled :: Primitive -- ^ A filled unit circle by default, modifiable with record syntax.+arcFilled = Arc origin 1 0 (2*pi) False True False False++curve :: Primitive -- ^ A cubic spline with a starting point of the origin.+curve = Curve origin [] False False True False++curveFilled :: Primitive -- ^ A filled loop with a starting point at the origin.+curveFilled = Curve origin [] True True False False++line :: Primitive -- ^ A line starting at the origin.+line = Line origin [] False False True False++polygon :: Primitive -- ^ An arbitrary filled polygon starting at the origin.+polygon = Line origin [] True True False False++pen :: Primitive -- ^ move the pen to the origin+pen = Pen origin++rectangle :: Primitive -- ^ an outlined rectangle+rectangle = Rectangle (Point 0 1) 1 1 False True False++rectangleFilled :: Primitive -- ^ A filled, but not outlined rectanglee+rectangleFilled = Rectangle (Point 0 1) 1 1 True False False++text :: Primitive -- ^ A rendered string starting at the origin.+text = Text [] origin True False False ++compound :: Primitive -- ^ An outlined compound object+compound = Compound [] True False False++degrees :: Double -> Double -- ^ Convert degrees to radians+degrees x = x * 0.0174532925++hidden :: Primitive -- ^ A hidden object.+hidden = Hidden++image :: Primitive -- ^ An image.  These are efficiently cached using weak references where possible+image = Image "" (Left origin) False +
+ Graphics/Rendering/Hieroglyph/UIState.hs view
@@ -0,0 +1,66 @@+-- | Establish a class for all things that are utterly required to be part of +--   the program state for the interactive renderer.  These will all be set +--   by the interactive system for you, so they just must be defined in your +--   state object.+--+--   [@Author@] Jeff Heard +--+--   [@Copyright@] &copy; 2008 Renaissance Computing Institute+--   +module Graphics.Rendering.Hieroglyph.UIState where++import Graphics.Rendering.Hieroglyph.Primitives+import qualified Graphics.UI.Gtk as Gtk+import Data.Map (Map, empty)+import Control.Concurrent +import Graphics.UI.Gtk.Gdk.Pixbuf (Pixbuf)+import System.Mem.Weak++type ImageCache = MVar (Map String (Weak Pixbuf))++initImageCache = newMVar empty++-- | A keystroke+data Key =+      Character Char+    | Enter +    | Tab +    | BackSpace+    | Insert +    | Delete+    | Home +    | End +    | PgUp +    | PgDown+    | PF1 | PF2 | PF3 | PF4 | PF5 | PF6 | PF7 | PF8 | PF9 | PF10 | PF11 | PF12++-- | The basic UI state.  This will get passed to all scene elements+class UIState a where+    mousePosition :: a -> Point                   -- ^ The current mouse position+    mouseLeftButtonDown :: a -> Bool                -- ^ Mouse left button.  Is it down?+    mouseRightButtonDown :: a -> Bool               -- ^ Mouse right button, is it down?+    mouseMiddleButtonDown :: a -> Bool              -- ^ Mouse middle button, is it down?+    mouseWheel :: a -> Int                          -- ^ Moues wheel, has it moved?+    keyCtrl :: a -> Bool                            -- ^ Is the control key down?+    keyShift :: a -> Bool                           -- ^ Is the shift key down?+    keyAlt :: a -> Bool                             -- ^ Is the alt key down?+    key :: a -> Key                                 -- ^ Is there a real key down?+    drawing :: a -> Maybe Gtk.Widget                -- ^ The draw window+    sizeX :: a -> Double                            -- ^ The width of the drawing area+    sizeY :: a -> Double                            -- ^ The height of the drawing area+    imageCache :: a -> Maybe ImageCache++    setMousePosition :: Point -> a-> a            -- ^ Set the mouse position (do not call in your own code)+    setMouseLeftButtonDown :: Bool -> a-> a         -- ^ Set the left button (do not call in your own code)+    setMouseRightButtonDown :: Bool -> a-> a        -- ^ Set the right button (do not call in your own code)+    setMouseMiddleButtonDown :: Bool -> a-> a       -- ^ Set the middle button (do not call in your own code)+    setMouseWheel :: Int -> a-> a                   -- ^ Set the mouse wheel delta (do not call in your own code)+    setKeyCtrl :: Bool -> a-> a                     -- ^ Set the control modifier state (do not call in your own code)+    setKeyShift :: Bool -> a-> a                    -- ^ Set the shift modifier state (do not call in your own code)+    setKeyAlt :: Bool -> a-> a                      -- ^ Set the alt modifier state (do not call in your own code)+    setKey :: Key -> a-> a                          -- ^ Set the key that is pressed (do not call in your own code)+    setDrawing :: Maybe Gtk.Widget -> a-> a         -- ^ Set the draw window  (do not call in your own code)+    setSizeX :: Double -> a -> a                    -- ^ Set the drawing area width (do not call in your own code)+    setSizeY :: Double -> a -> a                    -- ^ Set the drawing area height (do not call in your own code)+    setImageCache :: Maybe ImageCache -> a -> a+
+ Hieroglyph.cabal view
@@ -0,0 +1,26 @@+Name:           Hieroglyph+Version:        0.85+Cabal-Version:  >= 1.2+License:        BSD3+License-File:   LICENSE+Author:         J.R. Heard+Maintainer:     J.R. Heard+Category:       Graphics+Description:    +  A purely functional 2D scenegraph library with functionality similar to a barebones Processing.+  Currently entirely implmeneted using Cairo, although I would like to go to OpenGL as well.+Synopsis:       Purely functional 2D drawing+Build-Type:     Simple++Library+   Build-Depends: cairo, base, mtl, gtk, IfElse, containers+   Exposed-Modules:+      Graphics.Rendering.Hieroglyph+      Graphics.Rendering.Hieroglyph.Primitives+      Graphics.Rendering.Hieroglyph.Cairo+      Graphics.Rendering.Hieroglyph.BasicUIState+      Graphics.Rendering.Hieroglyph.UIState+      Graphics.Rendering.Hieroglyph.Interactive+      Graphics.Rendering.Hieroglyph.Colors++
+ LICENSE view
@@ -0,0 +1,24 @@+Copyright 2008, Jeff Heard.  All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice,+this list of conditions and the following disclaimer.+ +- Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.+ +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain