packages feed

Hieroglyph 2.22 → 2.23

raw patch · 11 files changed

+210/−579 lines, 11 files

Files

Graphics/Rendering/Hieroglyph.hs view
@@ -1,11 +1,7 @@-module Graphics.Rendering.Hieroglyph -    (module Graphics.Rendering.Hieroglyph.Cairo-    ,module Graphics.Rendering.Hieroglyph.Primitives-    ,module Graphics.Rendering.Hieroglyph.Interactive+module Graphics.Rendering.Hieroglyph+    (module Graphics.Rendering.Hieroglyph.Primitives     ,module Graphics.Rendering.Hieroglyph.Visual) where -import Graphics.Rendering.Hieroglyph.Cairo import Graphics.Rendering.Hieroglyph.Primitives-import Graphics.Rendering.Hieroglyph.Interactive import Graphics.Rendering.Hieroglyph.Visual 
+ Graphics/Rendering/Hieroglyph/Cache.hs view
@@ -0,0 +1,58 @@+-----------------------------------------------------------------------------+--+-- Module      :  Graphics.UI.Hieroglyph.Cache+-- Copyright   :+-- License     :  BSD3+--+-- Maintainer  :  J.R. Heard+-- Stability   :+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module Graphics.Rendering.Hieroglyph.Cache where++import qualified Data.Map as Map+import qualified Data.IntMap as IntMap++data Cache k a = Cache { store :: Map.Map k a, times :: IntMap.IntMap k, now :: Int, maxsize :: Int, size :: Int, decimation :: Int }++empty mxsz dec = Cache Map.empty IntMap.empty 0 mxsz 0 dec++get :: Ord k => k -> Cache k a -> (Cache k a,Maybe a)+get key cache = (cache',value)+    where value = Map.lookup key (store cache)+          cache' = maybe (cache{ now = now cache + 1 }) (\_ -> cache{ now = now cache + 1, times = IntMap.insert (now cache) key (times cache) }) value++put :: Ord k => k -> a -> Cache k a -> Cache k a+put key value cache+    | size cache < maxsize cache && (not $ Map.member key (store cache)) = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) , size = size cache + 1 }+    | size cache < maxsize cache = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) }+    | size cache >= maxsize cache && (Map.member key (store cache)) = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) }+    | size cache >= maxsize cache = cache{ now = now cache + 1, times = IntMap.insert (now cache) key times', store = Map.insert key value store', size = size cache - decimation cache }+    where times' = foldr IntMap.delete (times cache) lowtimes+          (lowtimes,lowtimekeys) = unzip . take (decimation cache) . IntMap.toAscList . times $ cache+          store' = foldr Map.delete (store cache) lowtimekeys++put' :: Ord k => k -> a -> Cache k a -> ([a], Cache k a)+put' key value cache+    | size cache < maxsize cache && (not $ Map.member key (store cache)) = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) , size = size cache + 1 })+    | size cache < maxsize cache = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) })+    | size cache >= maxsize cache && (Map.member key (store cache)) = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) })+    | size cache >= maxsize cache = (freed, cache{ now = now cache + 1, times = IntMap.insert (now cache) key times', store = Map.insert key value store', size = size cache - decimation cache })+    where times' = foldr IntMap.delete (times cache) lowtimes+          (lowtimes,lowtimekeys) = unzip . take (decimation cache) . IntMap.toAscList . times $ cache+          store' = foldr Map.delete (store cache) lowtimekeys+          freed = map (store cache Map.!) lowtimekeys++free :: Ord k => Cache k a -> ((k,a),Cache k a)+free cache = ((minkey,minval),cache')+    where minkey = IntMap.findMin (times cache)+          minval = store cache Map.! minkey+          cache' = cache{ now = now cache + 1, times = IntMap.deleteMin (times cache), store = Map.delete minkey (store cache), size = (size cache) }++member :: Ord k => k -> Cache k a -> Bool+member key cache = Map.member key (store cache)+
Graphics/Rendering/Hieroglyph/Cairo.hs view
@@ -19,6 +19,7 @@ -- module Graphics.Rendering.Hieroglyph.Cairo where +import qualified Graphics.UI.Hieroglyph.Cache as Cache import qualified Data.Set as Set import qualified Graphics.UI.Gtk.Cairo as Gtk import Graphics.UI.Gtk.Pango.Context@@ -29,7 +30,6 @@ import Control.Concurrent import Control.Monad.Trans (liftIO) import Graphics.Rendering.Hieroglyph.Primitives-import Graphics.Rendering.Hieroglyph.ImageCache import Graphics.Rendering.Hieroglyph.Visual import Graphics.UI.Gtk.Gdk.Pixbuf import qualified Graphics.UI.Gtk.Cairo as Cairo@@ -43,7 +43,9 @@ import Data.Colour.Names (black) import qualified Text.PrettyPrint as Pretty +type ImageCache = MVar (Cache.Cache Primitive Pixbuf) + toCairoAntialias AntialiasDefault = Cairo.AntialiasDefault toCairoAntialias AntialiasNone = Cairo.AntialiasNone toCairoAntialias AntialiasGray = Cairo.AntialiasGray@@ -208,50 +210,48 @@ renderToSurfaceWithImageCache context images surf frame = Cairo.renderWith surf (render context images frame)  renderToSurface :: Visual t => PangoContext -> Cairo.Surface -> t -> IO ()-renderToSurface c s o = do { i <- initImageCache; renderToSurfaceWithImageCache c i s o }+renderToSurface c s o = do { i <- newMVar (Cache.empty 1024 33) ;renderToSurfaceWithImageCache c i s o }  -- | @renderframeToPNGWithImageCache  filename xres yres frame@ renders a frame to an image file renderToPNGWithImageCache  :: Visual t => PangoContext -> ImageCache -> FilePath -> Int -> Int -> t -> IO () renderToPNGWithImageCache c images filename xres yres frame = Cairo.withImageSurface Cairo.FormatARGB32 xres yres $ \s -> renderToSurfaceWithImageCache c images s frame >> Cairo.surfaceWriteToPNG s filename-renderToPNG f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- initImageCache ; renderToPNGWithImageCache c i f w h o }+renderToPNG f w h o = do { c <- Gtk.cairoCreateContext Nothing ;   i <- newMVar (Cache.empty 1024 33) ; renderToPNGWithImageCache c i f w h o }  -- | @renderToPDFWithImageCache  filename width height frame@ renders a frame to a PDF file.  width and height are in points. renderToPDFWithImageCache  :: Visual t => PangoContext -> ImageCache -> FilePath -> Double -> Double -> t -> IO () renderToPDFWithImageCache c images filename width height frame = Cairo.withPDFSurface filename width height $ \s -> renderToSurfaceWithImageCache c images s frame-renderToPDF f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- initImageCache ; renderToPDFWithImageCache c i f w h o }+renderToPDF f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- newMVar (Cache.empty 1024 33) ; renderToPDFWithImageCache c i f w h o }  -- | @renderToPostscriptWithImageCache  filename width height frame@ renders a frame to a Postscript file.  width and height are in points. renderToPostscriptWithImageCache  :: Visual t => PangoContext -> ImageCache -> FilePath -> Double -> Double -> t -> IO () renderToPostscriptWithImageCache  c images filename width height frame = Cairo.withPSSurface filename width height $ \s -> renderToSurfaceWithImageCache c images s frame-renderToPostscript f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- initImageCache ; renderToPostscriptWithImageCache c i f w h o }+renderToPostscript f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- newMVar (Cache.empty 1024 33) ; renderToPostscriptWithImageCache c i f w h o }  -- | @renderToSVGWithImageCache  filename width height frame@ renders a frame to a SVG file.  width and height are in points. renderToSVGWithImageCache  :: Visual t => PangoContext -> ImageCache -> FilePath -> Double -> Double -> t -> IO () renderToSVGWithImageCache c images filename width height frame = Cairo.withSVGSurface filename width height $ \s -> renderToSurfaceWithImageCache c images s frame-renderToSVG f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- initImageCache ; renderToSVGWithImageCache c i f w h o }+renderToSVG f w h o = do { c <- Gtk.cairoCreateContext Nothing ; i <- newMVar (Cache.empty 1024 33) ; renderToSVGWithImageCache c 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)+    if im `Cache.member` dict+      then do let (cache',value) = Cache.get im dict               pbuf <- case value of                           Just pb -> return pb                           Nothing -> pixbufNewFromFileAtScale filename (round w) (round h) aspect-              return (dict,pbuf)+              return (cache',pbuf)       else do pbuf <- pixbufNewFromFileAtScale filename (round w) (round h) aspect-              wk <-  mkWeakPtr pbuf Nothing-              return ((M.insert (show im) wk dict), pbuf)+              return ((Cache.put im pbuf 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)+    if im `Cache.member` dict+      then do let (cache',value) = Cache.get im dict               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)+              return  ((Cache.put im pbuf dict), pbuf) 
− Graphics/Rendering/Hieroglyph/ImageCache.hs
@@ -1,10 +0,0 @@-module Graphics.Rendering.Hieroglyph.ImageCache where--import Data.Map (Map,empty)-import Control.Concurrent-import System.Mem.Weak-import qualified Graphics.UI.Gtk as Gtk--type ImageCache = MVar (Map String (Weak Gtk.Pixbuf))--initImageCache = newMVar empty
− Graphics/Rendering/Hieroglyph/Interactive.hs
@@ -1,226 +0,0 @@--- | An interactive scene graph library for Cairo------   [@Author@] Jeff Heard------   [@Copyright@] &copy; 2008 Renaissance Computing Institute----module Graphics.Rendering.Hieroglyph.Interactive where--import qualified Data.Set as Set-import Graphics.UI.Gtk.Pango.Context-import Graphics.Rendering.Hieroglyph.Primitives-import Graphics.Rendering.Hieroglyph.ImageCache-import Graphics.Rendering.Hieroglyph.Cairo-import Graphics.Rendering.Hieroglyph.Scaffolds.Interactive-import Graphics.Rendering.Hieroglyph.Visual-import qualified Graphics.UI.Gtk.Cairo as Gtk-import qualified Graphics.Rendering.Cairo as Cairo-import qualified Graphics.UI.Gtk as Gtk-import qualified Graphics.UI.Gtk.Cairo as Gtk-import qualified Graphics.UI.Gtk.Gdk.Events as Gtk-import Control.Parallel.Strategies--import Data.List-import Data.Maybe-import Control.Monad-import Control.Concurrent.MVar---- | Applies the current Interactive instance to a single scene element, returning an Object-applyDataToVisual :: (Interactive a, Visual b) => a -> (a -> b) -> b-applyDataToVisual vdata obj = obj vdata---- | Render function.  All Cairo is called through here.  You do not need to call this in your own code.-renderer :: (Interactive a, Visual b) => PangoContext -> MVar [Primitive] -> MVar a -> (a -> b) -> IO ()-renderer context extant_geometry state scene = do-    geom <- takeMVar extant_geometry-    st <- takeMVar state-    let state' = interactionFold st geom-        geom' = scene state'-    dwin <- Gtk.widgetGetDrawWindow . fromJust . getDrawing $ st-    Gtk.renderWithDrawable dwin (render context (fromJust (getImageCache st)) geom')-    putMVar extant_geometry . sort . primitives $ geom'-    putMVar state state'----- | Gets the keyboard state from Gtk and changes the Interactive.  You do not need---   to call this in your own code-keyboardHandler :: Interactive a => MVar a -> Gtk.Event -> IO Bool-keyboardHandler uistate_mvar 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 . getDrawing $ s-        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . getSizeX $ s) (round . getSizeY $ s)) False-    return False---- | Gets the mouse position and changes the Interactive to reflect it.  YOu do not need this in your own code.-mouseMotionHandler :: Interactive 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 . getDrawing $ state-    Gtk.drawWindowGetPointer dwin-    Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . getSizeX $ state) (round . getSizeY $ state)) False-    return False--mouseReleaseHandler :: Interactive a => MVar a -> Gtk.Event -> IO Bool-mouseReleaseHandler uistate_mvar 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 . getDrawing $ s-        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . getSizeX $ s) (round . getSizeY $ s)) False-    return True---- | Gets the mouse button state and changes the Interactive to reflect it.  You do not need this in your own code.-mouseButtonHandler :: Interactive a => MVar a -> Gtk.Event -> IO Bool-mouseButtonHandler uistate_mvar 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 . getDrawing $ s-        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 (round . getSizeX $ s) (round . getSizeY $ s)) False-    return True---- | Window resize handler. Changes the Interactive to reflect the new sizing.  You do not need this in your own code.-resize state 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 . getDrawing $ s-        Gtk.drawWindowInvalidateRect dwin (Gtk.Rectangle 0 0 sizex sizey) False-    return False----- | A lowish level funtion for creating a GUI.  Does not set the size of the---   window or expose any windows.-guiInit :: (Interactive a, Visual b)-        => MVar a               -- ^ The current Interactive-        -> (a-> b)               -- ^ The scene to render-        -> String               -- ^ The name of the window-        -> Bool                 -- ^ Whether or not to make this GUI motion sensitive-        -> IO Gtk.DrawingArea   -- ^ Returns the window that was created-guiInit state scene name motionSensitive = do-    Gtk.unsafeInitGUIForThreadedRTS--    canvas <- Gtk.drawingAreaNew-    imgcache <- initImageCache-    modifyMVar_ state $ return . setDrawing (Just . Gtk.castToWidget $ canvas) . setImageCache (Just imgcache)-    primitiveData <- newMVar []-    context <- Gtk.cairoCreateContext Nothing--    Gtk.onExpose canvas $ \evt -> renderer context primitiveData state scene >> return True-    Gtk.onConfigure canvas $ resize state-    Gtk.onButtonPress canvas $ mouseButtonHandler state-    Gtk.onButtonRelease canvas $ mouseReleaseHandler state-    Gtk.onKeyPress canvas $ keyboardHandler state-    when motionSensitive $ (Gtk.onMotionNotify canvas True $ mouseMotionHandler state) >> return ()-    return canvas---- | 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 :: (Interactive a, Visual b)-             => a           -- ^ The default Interactive-             -> ( a -> b )   -- ^ 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-    canvas <- guiInit mvar scene name motionSensitive-    window <- Gtk.windowNew-    Gtk.windowSetTitle window name-    Gtk.containerAdd window canvas-    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 :: (Interactive a, Visual b)-          => a-          -> (a -> b)-          -> 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/OpenGL.hs view
@@ -66,7 +66,7 @@  reverseMouseCoords b x y = do     let renderDataE = fromJust $ Buster.eventByQName "Hieroglyph" "Hieroglyph" "RenderData" b-    (_,sy) <- Gtk.drawingAreaGetSize . Gtk.castToDrawingArea . drawarea . head . Buster.eventdata $ renderDataE+    (_,sy) <- Gtk.widgetGetSize . Gtk.castToWidget . drawarea . (\(Buster.EOther a) -> a) . head . Buster.eventdata $ renderDataE     return (Point x (fromIntegral sy-y))  arcFn _ _ _ [] = []@@ -410,32 +410,7 @@ --optimize !ptr i (CompiledImage _ attrs vs c b w h t iid) = --optimize !ptr i (Optimized attrs vbo tbo t iid) = -{--    { afillrule     :: FillRule                      -- ^ The pattern fill rule-    , afillRGBA     :: AlphaColour Double            -- ^ The components of the stroke color in the range [0..1]-    , adash         :: Maybe ([Double],Double)       -- ^ The shape of the line dashing, if any-    , astrokeRGBA   :: AlphaColour Double            -- ^ The components of the stroke color in the range [0..1]-    , aantialias    :: Antialias                     -- ^ The way things are antialiased-    , alinecap      :: LineCap                       -- ^ The way lines are capped-    , alinejoin     :: LineJoin                      -- ^ The way lines are joined-    , alinewidth    :: Double                        -- ^ The width of a line in points-    , amiterlimit   :: Double                        -- ^ The miter limit of lines.  See Cairo's documentation-    , atolerance    :: Double                        -- ^ The trapezoidal tolerance.  See Cairo's documentation-    , aoperator     :: Operator                      -- ^ The transfer operator.  See Cairo's documentation for more <http://cairographics.org>-    , atranslatex   :: Double                        -- ^ The current translation x component-    , atranslatey   :: Double                        -- ^ The current translation y component-    , ascalex       :: Double                        -- ^ The current scale x component-    , ascaley       :: Double                        -- ^ The current scale y component-    , arotation     :: Double                        -- ^ The rotation in degrees that this primitive is seen in-    , afilled       :: Bool                          -- ^ Whether or not this primitive is filled in-    , aoutlined     :: Bool                          -- ^ Whether or not this primitive is outlined-    , aclipped      :: Bool                          -- ^ Whether or not this primitive is part of the clipping plane-    , layer        :: Int                           -- ^ This sorts out which primitives are located on top of each other.  Do not set this yourself.  Use Graphics.Rendering.Hieroglyph.Visual.over-    , bbox         :: Rect                          -- ^ The clockwise rotation in radians.-    , aname         :: Maybe String                  -- ^ The name of the object-    , lod          :: Int                           -- ^ The level of detail that this primitive is at. Use Graphics.Rendering.Hieroglyph.Visual.moreSpecific-    }--}+ loadAttrs attrs = GL.preservingMatrix $ do     GL.lineWidth $= (realToFrac . alinewidth $ attrs)     GL.matrixMode $= GL.Modelview 0@@ -454,21 +429,9 @@     -- TODO support dash/stipple     -- TODO support pattern fill rule --- the idea here is that we should:---      * initialize the GL subsystem---      * allocate some number of textures---      * allocate some buffer objects for tex coords and vertices---      * add any other state variables we want to check on to save time.---      * add lookup tables for geometry.---      * add weak table for optimized geometry.+-- | Widget for initializing the bus+initializeBus :: String -> Int -> Int -> Buster.Widget [Buster.EData HieroglyphGLRuntime] initializeBus name w h bus = do--- b <- takeMVar bus---    let numTexturesE = Buster.topEvent . Buster.eventsFor (Just "Environment") Nothing (Just "numTextures") $ b---        numBufferObjectsE = Buster.topEvent . Buster.eventsFor (Just "Environment") Nothing (Just "numBufferObjects") $ b---        Buster.EInt numTextures = head . Buster.eventdata $ numTexturesE---        Buster.EInt numBufferObjects = head . Buster.eventdata $ numBufferObjectsE--- putMVar bus b-     let numTextures = 400         numBufferObjects = 1     Gtk.unsafeInitGUIForThreadedRTS@@ -499,24 +462,9 @@      Gtk.onExpose area (\_ -> renderOnExpose bus >> return True)     return ()-    -- print "bus initialized" --- a behaviour to actually render hieroglyph data.---      On a separate thread and using STM:---          * get the lookup tables for geometry and optimized geometry.---          * merge the two by checking the guids of the current geometry against the optimized geometry and the non-optimized geometry---          * compile any uncompiled geometry---          * load unloaded textures---          * queue geometry to optimize---      * clear the buffers---      * setup GL state machine for a fresh render.---      * setup the viewport---      * setup the frustum---      * render the buffer---      * optimize any queued optimizable geometry---      * add optimized geometry to the weak table---      * wash hands, rinse, repeat.-+-- | a behaviour to render hieroglyph data to the selection buffer when it sees a (Hieroglyph,Hieroglyph,PleaseSelect) event.+--   Produces (Selection,Hieroglyph,@objectname@) events. selectionBehaviour :: Buster.Behaviour [Buster.EData HieroglyphGLRuntime] selectionBehaviour bus =     case selectionRequested of@@ -544,7 +492,8 @@           drawingEs = Set.toList $ Buster.eventsByGroup "Visible" bus           selectionRequested = Buster.eventByQName "Hieroglyph" "Hieroglyph" "PleaseSelect" bus -+-- | make Hieroglyph render on the main window exposure+renderOnExpose :: Buster.Widget [Buster.EData HieroglyphGLRuntime] renderOnExpose busV = do     bus <- takeMVar busV     putMVar busV bus@@ -565,6 +514,7 @@     let bus' = Buster.addEvent revent' bus     putMVar busV bus' +-- | Make Hieroglyph send out expose events when it sees a (Hieroglyph,Hieroglyph,Rerender) event. renderBehaviour bus = Buster.consumeFullyQualifiedEventWith bus "Hieroglyph" "Hieroglyph"  "Rerender" $ \event -> do     let Buster.EOther renderdata = head . Buster.eventdata . fromJust $ Buster.eventByQName "Hieroglyph" "Hieroglyph" "RenderData" bus     (w,h) <- Gtk.widgetGetSize (window renderdata)@@ -572,11 +522,8 @@     return []  render runtime@(HgGL _ _ _ _ win _ _ _) geo = Gtk.withGLDrawingArea win $ \drawable -> do-    -- print "rendering"     GL.drawBuffer $= GL.BackBuffers     (GL.Position px py, GL.Size sx sy ) <- GL.get GL.viewport-    -- print (px,py)-    -- print (sx,sy)     GL.matrixMode $= GL.Projection     GL.loadIdentity     GL.ortho2D 0 (fromIntegral sx) 0 (fromIntegral sy)@@ -587,19 +534,15 @@     GL.lineSmooth $= GL.Enabled     GL.polygonSmooth $= GL.Enabled     r' <- renderObjects (sort geo) runtime-    -- print "finished rednering objects"     Gtk.glDrawableSwapBuffers drawable-    -- print "swapped buffers"     return r' -renderObjects (o:os) !r = {- print o >> -} renderObj o r >>= renderObjects os+renderObjects (o:os) !r = renderObj o r >>= renderObjects os renderObjects [] r = return r  renderObj :: Primitive -> HieroglyphGLRuntime -> IO HieroglyphGLRuntime renderObj obj runtime = do-        -- print (aname . attribs $ obj)         (runtime',cg0) <- compile runtime obj-        -- print "compiled"         renderCompiledGeometry cg0         return runtime'{ compiledgeometry = Map.insert (uid cg0) cg0 . compiledgeometry $ runtime'                        , namemap=Map.insert (uid cg0)@@ -627,8 +570,9 @@                 A.readArray pixels sample >>= pokeByteOff ptr sample     return (w0,h0,w,h,channels,buf) --mouseSelectionBehaviour bus = Buster.pollFullyQualifiedEventWith bus "Mouse" "Hierolgyph.KeyboardMouseWidget" "SingleClick" $ \event -> do+-- | Select based on mouse clicks+mouseSelectionBehaviour :: Buster.Behaviour [Buster.EData HieroglyphGLRuntime]+mouseSelectionBehaviour bus = Buster.pollFullyQualifiedEventWith bus "Mouse" "Hieroglyph.KeyboardMouseWidget" "SingleClick" $ \event -> do     let (Buster.EAssocL alist) = head . Buster.eventdata $ event         (Buster.EDoubleL (x:y:_)) = fromJust $ "coords" `lookup` alist     Buster.listM $ Buster.produce "Hieroglyph" "Hieroglyph" "PleaseSelect" Buster.once [Buster.EDouble x, Buster.EDouble y]
Graphics/Rendering/Hieroglyph/Primitives.hs view
@@ -48,7 +48,12 @@ -- | A 2D point data Point = Point Double Double deriving (Show, Read, Eq, Ord) +-- | Translate a point horizontally+xplus :: Double -> Point -> Point xplus x (Point a b) = Point (x+a) b++-- | Translate a point vertically+yplus :: Double -> Point -> Point yplus y (Point a b) = Point a (b+y)  pmap f (Point a b) = Point (f a) (f b)@@ -67,16 +72,24 @@     (/) = comb (/)     fromRational a = Point (fromRational a) (fromRational a) +-- | Find the distance between two points+dist :: Point -> Point -> Double dist (Point x0 y0) (Point x1 y1) = sqrt $ (x1-x0)**2 + (y1-y0)**2 +-- | Find the average of a bunch of points+centroid :: [Point] -> Point centroid ps = centroid' (Point 0 0) 0 ps centroid' !s !n (p:ps) = centroid' (s+p) (n+1) ps centroid' s n [] = s/n +-- | A rectangle for dimensions data Rect = Plane | Singularity | Rect { x1 :: Double, y1 :: Double, x2 :: Double, y2 :: Double } deriving (Show, Read, Eq) +-- | A line segment data LineSegment = Line Point | Spline Point Point Point | EndPoint Point deriving (Show,Read,Eq) +-- | A convenience function for getting points out of line segments in a path+ls2pt :: LineSegment -> Point ls2pt (Line x) = x ls2pt (Spline _ _ x) = x ls2pt (EndPoint x) = x@@ -114,6 +127,7 @@         . zipWith compare [xa1,xa2,ya1,ya2]         $ [xb1,xb2,yb1,yb2] +-- | Test to see if two rectangles overlap overlaps :: Rect -> Rect -> Bool overlaps _ Plane = True overlaps Plane _ = True@@ -352,18 +366,46 @@ 		, updated = True }  --- | following combinators added to Text.PrettyPrint+-- | See pango span tag+tspan :: String -> Doc -> Doc tspan a s = text "<span " <> text a <> char '>' <> s <> text "</span>"  mark m d = char '<' <> text m <> char '>' <> d <> text "</" <> text m <> char '>'++-- | See pango layout bold tag+bold :: Doc -> Doc bold = mark "b"++-- | See pango layout bigger tag+bigger :: Doc -> Doc bigger = mark "big"++-- | See pango layout italic tag+italic :: Doc -> Doc italic = mark "i"++-- | See pango layout strikethrough tag+strikethrough :: Doc -> Doc strikethrough = mark "s"++-- | See pango layout superscript tag+subscript :: Doc -> Doc subscript = mark "sub"++-- | See pango layout superscript tag+superscript :: Doc -> Doc superscript = mark "sup"++-- | See pango layout smaller tag+smaller :: Doc -> Doc smaller = mark "small"++-- | See pango layout monospace tag+monospace :: Doc -> Doc monospace = mark "tt"++-- | See pango layout underline tag+underline :: Doc -> Doc underline = mark "u"  -- end Text.PrettyPrint combinators.@@ -371,6 +413,7 @@ nguid :: () -> Int -- GAAAH!!! Just name your objects, folks, please. nguid () = unsafePerformIO $ getStdRandom (randomR (0,2147483648)) +sign :: Primitive -> Primitive sign x = x{ sig = fromMaybe (nguid ()) (fromIntegral . Data.HashTable.hashString <$> (aname . attribs $ x)) }  -- | the origin point
− Graphics/Rendering/Hieroglyph/Scaffolds/Interactive.hs
@@ -1,186 +0,0 @@--- | 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@] &copy; 2008 Renaissance Computing Institute----module Graphics.Rendering.Hieroglyph.Scaffolds.Interactive where--import Graphics.Rendering.Hieroglyph.Primitives-import Graphics.Rendering.Hieroglyph.ImageCache-import Graphics.Rendering.Hieroglyph.Visual-import qualified Graphics.UI.Gtk as Gtk-import Control.Concurrent -import Data.Map (Map,empty)-import System.Mem.Weak----- | 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---- | All that you need to provide interactivity-data Scaffolding = Scaffolding  -    { mousePosition :: Point-    , mouseLeftButtonDown :: Bool-    , mouseRightButtonDown :: Bool-    , mouseMiddleButtonDown :: Bool-    , mouseWheel :: Int-    , keyCtrl :: Bool-    , keyShift :: Bool-    , keyAlt :: Bool-    , key :: Key -    , drawing :: Maybe Gtk.Widget -    , sizeX :: Double-    , sizeY :: Double -    , imageCache :: Maybe ImageCache }-    -instance Interactive Scaffolding where-    getInteractiveScaffolding = id-    setInteractiveScaffolding a b = b-    interactionFold a b = a    ---- | Implement this class to make your application interactive-class Interactive a where-    getInteractiveScaffolding :: a -> Scaffolding	-- ^ get the interactive Scaffolding record from your data-    setInteractiveScaffolding :: a -> Scaffolding -> a  -- ^ set the Interactive Scaffolding record in your data    -    -- | Interaction can be thought of as a foldr on an infinite list of data.-    --   The intent of implementing this function is that the implementer will-    --   fold the given event data (in the Scaffolding instance) with the data-    --   being visualized and the geometry that goes with the event data to -    --   produce a new set of data to visualize.-    interactionFold :: a -> [Primitive] -> a -    --- | The initial Scaffolding record.  Start with this.-scaffold :: Scaffolding -scaffold = Scaffolding (Point 0 0) False False False 0 False False False (Character '\0') Nothing 800 600 Nothing---- | Get the mouse position in window coordinates-getMousePosition :: Interactive a => a -> Point-getMousePosition = mousePosition . getInteractiveScaffolding---- | Get the left button state-getMouseLeftButtonDown :: Interactive a => a -> Bool-getMouseLeftButtonDown = mouseLeftButtonDown . getInteractiveScaffolding---- | Get the right button state-getMouseRightButtonDown :: Interactive a => a -> Bool-getMouseRightButtonDown = mouseRightButtonDown . getInteractiveScaffolding---- | Get the middle button state-getMouseMiddleButtonDown :: Interactive a => a -> Bool-getMouseMiddleButtonDown = mouseMiddleButtonDown . getInteractiveScaffolding---- | Get the number of clicks up or down the mouse button has gone-getMouseWheel :: Interactive a => a -> Int-getMouseWheel = mouseWheel . getInteractiveScaffolding---- | Get the ctrl modifier state-getKeyCtrl :: Interactive a => a -> Bool-getKeyCtrl = keyCtrl . getInteractiveScaffolding---- | Get the shift modifier state-getKeyShift :: Interactive a => a -> Bool-getKeyShift = keyShift . getInteractiveScaffolding---- | Get the shift modifier state-getKeyAlt :: Interactive a => a -> Bool-getKeyAlt = keyAlt . getInteractiveScaffolding---- | Get the key that was pressed-getKey :: Interactive a => a -> Key-getKey = key . getInteractiveScaffolding---- | Get the drawing window.  Not usually needed by the user, as there's not much you can do with it.-getDrawing :: Interactive a => a -> Maybe Gtk.Widget -getDrawing = drawing . getInteractiveScaffolding---- | Get the width of the drawing window-getSizeX :: Interactive a => a -> Double-getSizeX = sizeX . getInteractiveScaffolding---- | Get the height of the drawing window-getSizeY :: Interactive a => a -> Double -getSizeY = sizeY . getInteractiveScaffolding---- | Get the image cache-getImageCache :: Interactive a => a -> Maybe ImageCache-getImageCache = imageCache . getInteractiveScaffolding--setMousePosition :: Interactive a => Point -> a -> a-setMousePosition p v = setInteractiveScaffolding v s' -    where s = getInteractiveScaffolding v-          s' = s{ mousePosition = p }  -          -setMouseLeftButtonDown :: Interactive a => Bool -> a -> a-setMouseLeftButtonDown p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ mouseLeftButtonDown = p }--setMouseRightButtonDown :: Interactive a => Bool -> a -> a-setMouseRightButtonDown p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ mouseRightButtonDown = p }-          -setMouseMiddleButtonDown :: Interactive a => Bool -> a -> a-setMouseMiddleButtonDown p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ mouseMiddleButtonDown = p }-          -setMouseWheel :: Interactive a => Int -> a -> a-setMouseWheel p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ mouseWheel = p }--setKeyCtrl :: Interactive a => Bool -> a -> a-setKeyCtrl p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ keyCtrl = p }-          -setKeyShift :: Interactive a => Bool -> a -> a-setKeyShift p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ keyShift = p }-          -setKeyAlt :: Interactive a => Bool -> a -> a-setKeyAlt p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ keyAlt = p }--setKey :: Interactive a => Key -> a -> a-setKey p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ key = p }-          -setDrawing :: Interactive a => Maybe Gtk.Widget -> a -> a-setDrawing p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ drawing = p }--setSizeX :: Interactive a => Double -> a -> a-setSizeX p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ sizeX = p }--setSizeY :: Interactive a => Double -> a -> a-setSizeY p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ sizeY = p }--setImageCache :: Interactive a => Maybe ImageCache -> a -> a-setImageCache p v = setInteractiveScaffolding v s'-    where s = getInteractiveScaffolding v-          s' = s{ imageCache = p }-
Graphics/Rendering/Hieroglyph/Visual.hs view
@@ -6,6 +6,7 @@ --   forall a, Visual b : a -> Visual b module Graphics.Rendering.Hieroglyph.Visual where +import Data.Colour import Data.Monoid import qualified Data.Map as M import qualified Data.IntMap as IM@@ -55,6 +56,7 @@ occludes this that = ((\p -> p{ layer = maxlev+1 }) <%> primitives this) ++ (primitives that)     where maxlev = maximum . map (layer . attribs) . primitives $ that +-- | Declare that a Visual doesn't occlude another Visual beside :: (Visual t, Visual u) => t -> u -> BaseVisual beside this that = ((\p -> p{ layer = maxlev }) <%> primitives this) ++ (primitives that)     where maxlev = maximum . map (layer . attribs) . primitives $ that@@ -62,8 +64,17 @@ pure x = [x]  f <%> x = map (\a -> a{ attribs = (f . attribs $ a)})  x++-- | The beside operator.  Same as @beside@+(#+#) :: BaseVisual -> BaseVisual -> BaseVisual (#+#) = (++)++-- | The occludes operator.  The left occludes the right.+(#/#) :: BaseVisual -> BaseVisual -> BaseVisual (#/#) = occludes++-- | The under operator.  The right occludes the left.+(#\#) :: BaseVisual -> BaseVisual -> BaseVisual (#\#) = flip occludes  infixr 9 `occludes`@@ -72,25 +83,86 @@ infixr 9 #/# infixr 9 #\# +-- | Set the fill rule for this visual (Cairo)+fillrule :: Visual a =>  FillRule -> a -> BaseVisual fillrule x os = (\o -> o{ afillrule = x }) <%> primitives os++-- | Set the fill colour+fillcolour :: Visual a =>  AlphaColour Double -> a -> BaseVisual fillcolour x os = (\o -> o{ afillRGBA = x }) <%> primitives os++-- | Set the stipple pattern for lines (Cairo)+dash :: Visual a => Maybe ([Double],Double) -> a -> BaseVisual dash x os = (\o -> o{adash = x}) <%> primitives os++-- | Set the stroke colour+strokecolour :: Visual a => AlphaColour Double -> a -> BaseVisual strokecolour x os = (\o -> o{ astrokeRGBA = x }) <%> primitives os++-- | Set the line cap shape (Cairo)+linecap :: Visual a => LineCap -> a -> BaseVisual linecap x os = (\o -> o{alinecap = x}) <%> primitives os++-- | Set the miter limit (Cairo)+miterlimit :: Visual a =>  Double -> a -> BaseVisual miterlimit x os = (\o -> o{amiterlimit = x}) <%> primitives os++-- | Set the polygon tolerance (Cairo)+tolerance :: Visual a => Double -> a -> BaseVisual tolerance x os = (\o -> o{atolerance = x}) <%> primitives os++-- | Set the scale of the Visual+scalex :: Visual a => Double -> a -> BaseVisual scalex x os = (\o -> o{ascalex = x}) <%> primitives os++-- | Set the scale of the Visual+scaley :: Visual a => Double -> a -> BaseVisual scaley x os = (\o -> o{ascaley = x}) <%> primitives os++-- | Adjust the scale of the visual+scale :: Visual a => Double -> Double -> a -> BaseVisual scale x y os = (\o -> o{ascalex = x * ascalex o, ascaley = y * ascaley o})<%> primitives os++-- | Set the translation of the visual+settranslatex :: Visual a =>  Double -> a -> BaseVisual settranslatex x os = (\o -> o{atranslatex = x })<%> primitives os++-- | Set the translation of the visual+settranslatey :: Visual a =>  Double -> a -> BaseVisual settranslatey y os = (\o -> o{atranslatey = y })<%> primitives os++-- | Adjust the translation of the visual+translate ::  Visual a => Double -> Double -> a -> BaseVisual translate x y os = (\o -> o{atranslatex = x + atranslatex o, atranslatey = y + atranslatey o})<%> primitives os++-- | Set the rotation of the visual+rotation ::  Visual a =>  Double -> a -> BaseVisual rotation x os = (\o -> o{arotation = x}) <%> primitives os++-- | Set whether or not objects in the visual are filled+filled :: Visual a => Bool -> a -> BaseVisual filled x os = (\o -> o{afilled = x}) <%> primitives os++-- | Set whether or not objects in the visual are outlined+outlined ::  Visual a => Bool -> a -> BaseVisual outlined x os = (\o -> o{aoutlined = x}) <%> primitives os++-- | Set whether or not the objects in the visual are part of the clipping plane (Cairo)+clipped :: Visual a => Bool -> a -> BaseVisual clipped x os = (\o -> o{aclipped = x}) <%> primitives os++-- | Set the name of the objects for selection purposes+name :: Visual a => String -> a -> BaseVisual name x os = (\o -> o{aname = Just x}) <%> primitives os++-- | Set whether the objects have already been cached.+cached :: Visual a =>  a -> BaseVisual cached os = (\o -> o{updated = False}) <%> primitives os++-- | Set whether the objects have been updated.+fresh :: Visual a => a -> BaseVisual fresh os = (\o -> o{updated = True}) <%> primitives os++linewidth :: Visual a => Double -> a -> BaseVisual linewidth x os = (\o -> o{alinewidth = x}) <%> primitives os 
− Graphics/UI/Hieroglyph/Cache.hs
@@ -1,58 +0,0 @@------------------------------------------------------------------------------------ Module      :  Graphics.UI.Hieroglyph.Cache--- Copyright   :--- License     :  BSD3------ Maintainer  :  J.R. Heard--- Stability   :--- Portability :------ |-----------------------------------------------------------------------------------module Graphics.UI.Hieroglyph.Cache where--import qualified Data.Map as Map-import qualified Data.IntMap as IntMap--data Cache k a = Cache { store :: Map.Map k a, times :: IntMap.IntMap k, now :: Int, maxsize :: Int, size :: Int, decimation :: Int }--empty mxsz dec = Cache Map.empty IntMap.empty 0 mxsz 0 dec--get :: Ord k => k -> Cache k a -> (Cache k a,Maybe a)-get key cache = (cache',value)-    where value = Map.lookup key (store cache)-          cache' = maybe (cache{ now = now cache + 1 }) (\_ -> cache{ now = now cache + 1, times = IntMap.insert (now cache) key (times cache) }) value--put :: Ord k => k -> a -> Cache k a -> Cache k a-put key value cache-    | size cache < maxsize cache && (not $ Map.member key (store cache)) = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) , size = size cache + 1 }-    | size cache < maxsize cache = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) }-    | size cache >= maxsize cache && (Map.member key (store cache)) = cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) }-    | size cache >= maxsize cache = cache{ now = now cache + 1, times = IntMap.insert (now cache) key times', store = Map.insert key value store', size = size cache - decimation cache }-    where times' = foldr IntMap.delete (times cache) lowtimes-          (lowtimes,lowtimekeys) = unzip . take (decimation cache) . IntMap.toAscList . times $ cache-          store' = foldr Map.delete (store cache) lowtimekeys--put' :: Ord k => k -> a -> Cache k a -> ([a], Cache k a)-put' key value cache-    | size cache < maxsize cache && (not $ Map.member key (store cache)) = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) , size = size cache + 1 })-    | size cache < maxsize cache = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) })-    | size cache >= maxsize cache && (Map.member key (store cache)) = ([],cache { now = now cache + 1, times = IntMap.insert (now cache) key (times cache), store = Map.insert key value (store cache) })-    | size cache >= maxsize cache = (freed, cache{ now = now cache + 1, times = IntMap.insert (now cache) key times', store = Map.insert key value store', size = size cache - decimation cache })-    where times' = foldr IntMap.delete (times cache) lowtimes-          (lowtimes,lowtimekeys) = unzip . take (decimation cache) . IntMap.toAscList . times $ cache-          store' = foldr Map.delete (store cache) lowtimekeys-          freed = map (store cache Map.!) lowtimekeys--free :: Ord k => Cache k a -> ((k,a),Cache k a)-free cache = ((minkey,minval),cache')-    where minkey = IntMap.findMin (times cache)-          minval = store cache Map.! minkey-          cache' = cache{ now = now cache + 1, times = IntMap.deleteMin (times cache), store = Map.delete minkey (store cache), size = (size cache) }--member :: Ord k => k -> Cache k a -> Bool-member key cache = Map.member key (store cache)-
Hieroglyph.cabal view
@@ -1,13 +1,13 @@ name: Hieroglyph-version: 2.22+version: 2.23 cabal-version: >=1.2 build-type: Simple license: BSD3 license-file: LICENSE copyright: maintainer: J.R. Heard-build-depends: IfElse -any, OpenGL -any, array -any,-               base -any, buster >=2.0, bytestring -any, cairo -any, colour -any,+build-depends: IfElse -any, OpenGL -any, array -any, base -any,+               buster >=2.0, bytestring -any, cairo -any, colour -any,                containers -any, gtk -any, gtkglext -any, mtl -any, parallel -any,                pretty -any, random -any stability:@@ -24,14 +24,12 @@ data-dir: "" extra-source-files: extra-tmp-files:-exposed-modules: Graphics.UI.Hieroglyph.Cache-                 Graphics.Rendering.Hieroglyph Graphics.Rendering.Hieroglyph.Cairo+exposed-modules: Graphics.Rendering.Hieroglyph+                 Graphics.Rendering.Hieroglyph.Cairo                  Graphics.Rendering.Hieroglyph.OpenGL-                 Graphics.Rendering.Hieroglyph.ImageCache-                 Graphics.Rendering.Hieroglyph.Interactive+                 Graphics.Rendering.Hieroglyph.Cache                  Graphics.Rendering.Hieroglyph.Primitives                  Graphics.Rendering.Hieroglyph.Visual-                 Graphics.Rendering.Hieroglyph.Scaffolds.Interactive exposed: True buildable: True build-tools: