Thingie (empty) → 0.5
raw patch · 5 files changed
+451/−0 lines, 5 filesdep +basedep +cairodep +mtlsetup-changed
Dependencies added: base, cairo, mtl
Files
- Graphics/Rendering/Thingie/Cairo.hs +292/−0
- Graphics/Rendering/Thingie/Primitives.hs +113/−0
- LICENSE +24/−0
- Setup.hs +2/−0
- Thingie.cabal +20/−0
+ Graphics/Rendering/Thingie/Cairo.hs view
@@ -0,0 +1,292 @@+-- | Cairo backend to Thingie. Future plans include making 'StateModifier' part +-- of the base distribution and making 'Frame' the basis for all backends to +-- Thingie. 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@] © 2008 Renaissance Computing Institute+-- +-- [@License@] A LICENSE file should be included as part of this distribution+--+-- [@Version@] 0.5+--+module Graphics.Rendering.Thingie.Cairo where++import Graphics.Rendering.Thingie.Primitives+import qualified Graphics.Rendering.Cairo as Cairo+import Control.Monad+import Control.Monad.IfElse+import Data.List (foldl')++-- | 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+ | OutlineRGB Double Double Double -- ^ @OutlineRGB r g b@ sets the outline RGB to r g b and the alpha component to 1+ | OutlineRGBA Double Double Double Double -- ^ @OutlineRGBA r g b a@ sets the outline 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) + | OutlineRed Double -- ^ Set the outline color's red component without changing anything else+ | OutlineGreen Double -- ^ Set the outline color's green component without changing anything else+ | OutlineBlue Double -- ^ Set the outline color's blue component without changing anything else+ | OutlineAlpha Double -- ^ Set the outline 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 Point2D -- ^ 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 Frame = Node MyEither [Frame]++-- | A more mnemonic Either type, constraining the Left to be drawing primitives+-- and the Right to be lists of state changes to make before drawing children.+data MyEither = Draw Primitive | Setup [StateModifier]++-- | @e --\< c@ is a combinator to create a @Node e c@ structure. The point+-- is that the left side happens before the children. Suggest a better name+-- for this operator and consider it done.+e --< c = Node e c++-- | @leaf e@ is equivalent to @e --\< []@. It creates a leaf node.+leaf e = e --< []++-- | 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+ , outlinered :: Double -- ^ The red component of the outline color in the range [0..1]+ , outlinegreen :: Double -- ^ The red component of the outline color in the range [0..1]+ , outlineblue :: Double -- ^ The red component of the outline color in the range [0..1]+ , outlinealpha :: Double -- ^ The red component of the outline 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 :: Point2D -- ^ 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.++fillOutlineAndClip 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 (outlinered state) (outlinegreen state) (outlineblue state) (outlinealpha state) >>+ Cairo.stroke+ when isclipped $ Cairo.clip++-- | @renderPrimitive state prim@ draws a single primitive.+renderPrimitive :: RendererState -> Primitive -> Cairo.Render ()+renderPrimitive state (Arc (Point2D 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+ fillOutlineAndClip state f o c++renderPrimitive state (Curve (Point2D ox oy) segs isclosed f o c) = do + Cairo.moveTo ox oy+ forM_ segs $ \(Point2D x1 y1,Point2D x2 y2,Point2D x3 y3) -> Cairo.curveTo x1 y1 x2 y2 x3 y3+ when isclosed (Cairo.lineTo ox oy)+ fillOutlineAndClip state f o c++renderPrimitive state (Line (Point2D ox oy) segs isclosed f o c) = do+ Cairo.moveTo ox oy+ mapM (\seg -> case seg of Point2D x y -> Cairo.lineTo x y) segs+ when isclosed (Cairo.lineTo ox oy)+ fillOutlineAndClip state f o c+ +renderPrimitive _ (Pen (Point2D ox oy)) = Cairo.moveTo ox oy+renderPrimitive state (Rectangle (Point2D ox oy) w h f o c) = Cairo.rectangle ox oy w h >> fillOutlineAndClip state f o c+renderPrimitive state (Text str (Point2D ox oy) f o c) = Cairo.showText str >> fillOutlineAndClip state f o c+renderPrimitive state (Compound prims f o c) = mapM (renderPrimitive state . unfoc) prims >> fillOutlineAndClip 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+ , outlinered = 1+ , outlinegreen = 1+ , outlineblue = 1+ , outlinealpha = 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 (Point2D 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 (OutlineRed s) = state{ outlinered=s }+applyStateChangeToLocalEnv state (OutlineGreen s) = state{ outlinegreen=s }+applyStateChangeToLocalEnv state (OutlineBlue s) = state{ outlineblue=s }+applyStateChangeToLocalEnv state (OutlineAlpha s) = state{ outlinealpha=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 (OutlineRGB r g b) = state{ outlinered = r, outlinegreen=g, outlineblue = b }+applyStateChangeToLocalEnv state (OutlineRGBA r g b a) = state{outlinered = r, outlinegreen=g, outlineblue = b, outlinealpha = 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 (OutlineRed s) = return ()+applyStateChangeToCairo state (OutlineGreen s) = return ()+applyStateChangeToCairo state (OutlineBlue s) = return ()+applyStateChangeToCairo state (OutlineAlpha 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 (Point2D px py)) = Cairo.moveTo px py+applyStateChangeToCairo state (FillRGB r g b) = return ()+applyStateChangeToCairo state (FillRGBA r g b a) = return ()+applyStateChangeToCairo state (OutlineRGB r g b) = return ()+applyStateChangeToCairo state (OutlineRGBA r g b a) = return ()++-- | @renderFrame node@ renders a Frame object to the current surface+renderFrame :: Frame -> Cairo.Render ()+renderFrame node = renderFrameCustom defaultState node++renderFrameCustom state (Node (Draw prim) frames) = do+ renderPrimitive state prim+ mapM_ (renderFrameCustom state) frames +renderFrameCustom state (Node (Setup pdirective) frames) = do+ Cairo.save+ state' <- changeRenderState state pdirective+ mapM_ (renderFrameCustom state') frames+ Cairo.restore++-- | @renderFrameToSurface surface frame@ renders a frame to a particular surface+renderFrameToSurface :: Cairo.Surface -> Frame -> IO ()+renderFrameToSurface surf frame = Cairo.renderWith surf (renderFrame frame)++-- | @renderframeToPNG filename xres yres frame@ renders a frame to an image file+renderFrameToPNG :: FilePath -> Int -> Int -> Frame -> IO ()+renderFrameToPNG filename xres yres frame = Cairo.withImageSurface Cairo.FormatARGB32 xres yres $ \s -> renderFrameToSurface s frame >> Cairo.surfaceWriteToPNG s filename++-- | @renderFrameToPDF filename width height frame@ renders a frame to a PDF file. width and height are in points.+renderFrameToPDF :: FilePath -> Double -> Double -> Frame -> IO ()+renderFrameToPDF filename width height frame = Cairo.withPDFSurface filename width height $ \s -> renderFrameToSurface s frame++-- | @renderFrameToPostscript filename width height frame@ renders a frame to a Postscript file. width and height are in points.+renderFrameToPostscript :: FilePath -> Double -> Double -> Frame -> IO ()+renderFrameToPostscript filename width height frame = Cairo.withPSSurface filename width height $ \s -> renderFrameToSurface s frame++-- | @renderFrameToSVG filename width height frame@ renders a frame to a SVG file. width and height are in points.+renderFrameToSVG :: FilePath -> Double -> Double -> Frame -> IO ()+renderFrameToSVG filename width height frame = Cairo.withSVGSurface filename width height $ \s -> renderFrameToSurface s frame+
+ Graphics/Rendering/Thingie/Primitives.hs view
@@ -0,0 +1,113 @@+-- | This is Thingie, 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.Thingie.Cairo module)+-- for more information on how to use this library.+--+-- [@Author@] Jeff Heard+-- +-- [@Copyright@] © 2008 Renaissance Computing Institute+-- +-- [@License@] A LICENSE file should be included as part of this distribution+--+-- [@Version@] 0.5+--+module Graphics.Rendering.Thingie.Primitives where++import qualified Graphics.Rendering.Cairo as Cairo++-- | A 2D point+data Point2D = Point2D Double Double deriving (Show, Read)++-- | A 2D primitive in an arbitrary Cartesian 2d space+data Primitive = + Arc -- ^ A possibly filled pie slice or arc+ { center :: Point2D -- ^ 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++ | Curve -- ^ An arbitrary cubic spline+ { begin :: Point2D -- ^ starting point+ , curve_segments :: [(Point2D,Point2D,Point2D)] -- ^ 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++ | Line -- ^ An arbitrary series of line segments+ { begin :: Point2D -- ^ Starting Point+ , segments :: [Point2D] -- ^ 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+ | Pen + { moveto :: Point2D } -- ^ Move the current point. Matters for arcs sometimes. May remove the begin point for Curve and Line in favor of this.++ | Rectangle -- ^ An possibly filled rectangle+ { topleft :: Point2D -- ^ 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?++ | Text -- ^ A simple text string+ { str :: String -- ^ The string to print + , bottomleft :: Point2D -- ^ 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?++ | 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?+ deriving (Show,Read)++-- | the origin point+origin :: Point2D+origin = Point2D 0 0 ++arc :: Primitive -- ^ A unit circle by default, modifiable with record syntax.+arc = Arc origin 1 0 (2*pi) False False True False++arc_filled :: Primitive -- ^ A filled unit circle by default, modifiable with record syntax.+arc_filled = 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++curve_filled :: Primitive -- ^ A filled loop with a starting point at the origin.+curve_filled = 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 (Point2D 0 1) 1 1 False True False++rectangle_filled :: Primitive -- ^ A filled, but not outlined rectanglee+rectangle_filled = Rectangle (Point2D 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+
+ 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
+ Thingie.cabal view
@@ -0,0 +1,20 @@+Name: Thingie+Version: 0.5+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+ Exposed-Modules:+ Graphics.Rendering.Thingie.Primitives+ Graphics.Rendering.Thingie.Cairo+