packages feed

chalkboard 0.2 → 1.9.0.16

raw patch · 41 files changed

Files

+ Graphics/ChalkBoard.hs view
@@ -0,0 +1,29 @@+-- |+-- Module: Graphics.ChalkBoard+-- Copyright: (c) 2009 Andy Gill+-- License: BSD3+--+-- Maintainer: Andy Gill <andygill@ku.edu>+-- Stability: unstable+-- Portability: ghc+--+-- Public interface to the ChalkBoard utility.+--++module Graphics.ChalkBoard+	( module Graphics.ChalkBoard.Board+	, module Graphics.ChalkBoard.O+	, module Graphics.ChalkBoard.Shapes+	, module Graphics.ChalkBoard.Types+	, module Graphics.ChalkBoard.Main+	, module Graphics.ChalkBoard.Utils+	, module Graphics.ChalkBoard.Options+	) where++import Graphics.ChalkBoard.Board -- hiding (scale)+import Graphics.ChalkBoard.O+import Graphics.ChalkBoard.Shapes+import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.Main+import Graphics.ChalkBoard.Utils+import Graphics.ChalkBoard.Options
+ Graphics/ChalkBoard/Board.hs view
@@ -0,0 +1,158 @@+{-# LANGUAGE TypeFamilies, ExistentialQuantification, GADTs, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, UndecidableInstances #-}++module Graphics.ChalkBoard.Board +	( -- * The 'Board' +	  Board+	  -- * Ways of manipulating 'Board'.+	, (<$>)+	, move+	, rotate+	, scaleXY+	  -- * Ways of creating a new 'Board'.+	, boardOf+	, circle+	, box+	, square+	, triangle+	, polygon+	, readBoard+	, readNormalizedBoard+	) where+++import Graphics.ChalkBoard.Board.Internals+import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.O+import Graphics.ChalkBoard.O.Internals+import Graphics.ChalkBoard.Core+import Graphics.ChalkBoard.Utils+import Graphics.ChalkBoard.Expr+import Graphics.ChalkBoard.IStorable as IS++import Data.Array.Unboxed  as U+import Data.Array.MArray+import Data.Array.Storable+import Data.Word+import Codec.Image.DevIL+++import Prelude hiding (lookup)+++{-+instance ObsApp Board where+--	pure a = PrimConst (pure a)+	(<*>) (PrimConst a) brd = Fmap (a <*>) brd+--	(<*>) (Fmap f brd1) brd2 = Fzip (\ a b -> f a <*> b) brd1 brd2 +	(<*>) a b = error $ "Strange use of <*>"+-}++infixl 4 <$>++-- | 'fmap' like operator over a 'Board'.+(<$>) :: (O a -> O b) -> Board a -> Board b+(<$>) f brd = Fmap f brd -- PrimConst (lamO $ f) <*> brd+++-- | 'pure' like operator for 'Board'.	+boardOf :: O a -> Board a+boardOf = PrimConst++transPoint :: Trans -> (R,R) -> (R,R)+transPoint (Move (xd,yd)) 	(x,y) = (x - xd,y - yd)+transPoint (Scale (xn,yn)) 	(x,y) = (x / xn,y / yn)+transPoint (Rotate theta) 	(x,y) = (cos theta * x - sin theta * y,+					 sin theta * x + cos theta * y)+++-- |  Generate a unit square (1 by 1 square) centered on origin+square :: Board Bool+square = Polygon (const [(-0.5,-0.5),(-0.5,0.5),(0.5,0.5),(0.5,-0.5)])++-- | Generate a unit circle (radius .5) centered on origin+circle :: Board Bool+circle = Polygon $ \ sz' -> +	let sz = max (ceiling sz') 3+	in [ (sin x/2,cos x/2) +	   | x <- map (* (2*pi/fromIntegral sz)) $ take sz [0..]+	   ]++-- | Generate an arbitary triangle from 3 points.+triangle :: Point -> Point -> Point -> Board Bool+triangle p1 p2 p3 = Polygon (const [p1,p2,p3])++-- | Generate a (convex) polygon from a list of points. There must be at least 3 points,+-- and the points must form a convex polygon.+polygon :: [Point] -> Board Bool+polygon = Polygon . const++-- | 'box' generate a box between two corner points)+box :: (Point,Point) -> Board Bool+box ((x0,y0),(x1,y1)) = Polygon (const [(x0,y0),(x1,y0),(x1,y1),(x0,y1)])+++-- | 'move' moves the contents of 'Board'+move :: (R,R) -> Board a -> Board a+move = Trans . Move++instance Scale (Board a) where+  -- | 'scale' scales the contents of 'Board'+  scale n brd = scaleXY (n,n) brd++-- | 'scaleXY' scales the contents of 'Board' the X and Y dimension.+--  See also 'scale'.+scaleXY :: (R,R) -> Board a -> Board a+scaleXY = Trans . Scale++-- | 'rotate' rotates a 'Board' clockwise by a radian argument.+rotate :: Radian -> Board a -> Board a+rotate = Trans . Rotate++lookup :: Board a -> Float -> (R,R) -> a+lookup brd r (x,y) = unO $ lookupO brd r (x,y)++lookupO :: Board a -> Float -> (R,R) -> O a+lookupO (PrimFun f) r (x,y) = f (x,y)+lookupO (Trans t brd) r (x,y) = lookupO brd r (transPoint t (x,y))+lookupO (Fmap f brd) r (x,y) = f $ lookupO brd r (x,y)+lookupO (Polygon points) r (x,y) = +	if insidePoly (points r) (x,y)+	then true+	else false+lookupO other r (x,y) = error $ show ("lookup",other,r,(x,y))++-- miss-use of PrimFun and primO+	+--coord :: Board (R,R)+--coord = PrimFun (\ (x,y) -> primO (O_Pair (E $ Lit x) (E $ Lit y)) $ (x,y))++instance Over a => Over (Board a) where+	-- 'over' overlays two 'Board's.+	over b1 b2 = Over over b1 b2+++-- I would rather mask to be a Board Bool, and we could use <$>,+-- to choose, but the Board transformer will do for now.+mask :: ((R,R),(R,R)) -> Board a -> Board (Maybe a)+mask = Crop++++-- | read a file containing a common image format (jpg, gif, etc.), and create a 'Board RGBA', and the X and Y size of the image.+readBoard :: String -> IO (Int,Int,Board RGBA)+readBoard filename = do+  arr <- readImage filename +  iStore <- iStorableArray arr +  let ((0,0,0), (h,w,3)) = U.bounds arr+  return $ (h+1,w+1,Image iStore)+  +readNormalizedBoard :: String -> IO(Int,Int,Board RGBA)+readNormalizedBoard filename = do+    (x,y,imgBrd) <- readBoard (filename)+    let xy = fromIntegral $ max x y+        sc = 1 / xy+        xd = fromIntegral x / xy+        yd = fromIntegral y / xy+        img = move (-0.5 * yd,-0.5 * xd)  (scale sc imgBrd)+    return (x,y,img)+
+ Graphics/ChalkBoard/Board/Internals.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE TypeFamilies, ExistentialQuantification, GADTs, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts, UndecidableInstances #-}++module Graphics.ChalkBoard.Board.Internals+	( Board(..)+	, Trans(..)+	) where+		+import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.O+import Graphics.ChalkBoard.IStorable as IS++		+data Board a where+	PrimFun 	:: 		((R,R) -> O a)	-> Board a-- TODO: RM!+	PrimConst 	::		(O a)	-> Board a+	Trans 		:: Trans 	->	(Board a)	-> Board a+	Crop 		:: ((R,R),(R,R)) -> Board a	-> Board (Maybe a)+	Fmap  :: forall b . (O b -> O a) -> Board b	-> Board a+--	Fzip  :: forall b c . (O b -> O c -> O a) -> Board b	-> Board c -> Board a+	Polygon 	::	(Float -> [(R,R)])	-> 		Board Bool	-- later, have two types of Polygon+--	Circle		:: 						Board Bool+	-- only used in code generator, when types do not matter.+	Over  		:: 	(a -> a -> a) -> Board a -> Board a -> 	Board a+		-- we represent image as mutable arrays simply because+		-- we need a quick way to get to a pointer to the array+	Image		:: IStorableArray (Int,Int,Int) -> Board RGBA++instance Show (Board a) where+	show (PrimFun {}) = "PrimFun"+	show (PrimConst {}) = "PrimConst"+	show (Trans _ brd)  = "Trans (..) (" ++ show brd ++ ")"+	show (Polygon {})   = "Polygon"+--	show (Circle {})    = "Circle"+	show (Fmap _ brd)   = "Fmap (..) (" ++ show brd ++ ")"+	show (Image arr)    = "Image (..)"+	show (Over _ brd1 brd2)   = "Over (..) (" ++ show brd1 ++ " " ++ show brd2 ++ ")"+	+data Trans = Move (R,R)+	   | Scale (R,R)+	   | Rotate Radian+	deriving Show+	
+ Graphics/ChalkBoard/CBIR.hs view
@@ -0,0 +1,299 @@+module Graphics.ChalkBoard.CBIR where++import Foreign.Ptr (Ptr)+import Foreign.C.Types (CUChar)+import Data.Word+import Graphics.ChalkBoard.Types (UI,RGB(..),RGBA(..))+import Data.Array.Unboxed+import Data.Array.MArray+import Data.Array.Storable+import Graphics.ChalkBoard.IStorable as IS+import Graphics.ChalkBoard.Core++import Data.Binary+import Control.Monad++{-What do we need?++    * A way of creating a canvas+    * The canvas has size, pixels, depth, RGB/BW, opt alpha, perhaps 1-bit array.+    * We have ways of placing slices (rectangles?) of these canvases onto the 'screen'. ++        Difference places, sizes, rotations.++    * Ways drawing these to a canvas+    * Ways of importing and exporting canvases +-}+++type BufferId = Int		     -- make abstact later++type CBIR = ([Inst CBBO],CBBO)       -- A list of instructions, and a Buffer to render++-- ChalkBoardBufferObject+newtype CBBO = CBBO Int	-- unique 'label' or tag for each named thing.+        deriving (Eq,Ord)++instance Show CBBO where+  show (CBBO n) = "_" ++ show n+++data Depth = BitDepth		-- 1 bit per pixel+           | G8BitDepth        -- 8 bits per pixel (grey)+           | RGB24Depth	        -- (R,G,B), 8 bits per pixel+           | RGBADepth		-- (R,G,B,A), 8 bits per pixel+        deriving Show++-- In a sense, the Depth is the type of our CBBO.++-- KM: I would say leave as 0-1 since that's what OpenGL defaults to anyway for colors. Plus then if you want to use it for something else like you did with PointMap?, you can.++data Background+           = BackgroundBit Bool+{-+AG: does a pixel mean later 'draw this *color* (white/black), or draw this pixel *if* black?++KM: I would say the "draw this pixel if true" approach might be faster? Then could use the++    8Bit version if you want to force it to draw all pixels?+-}+           | BackgroundG8Bit UI+              -- this may have the same issue?+           | BackgroundRGB24Depth RGB+           | BackgroundRGBADepth RGBA+	   | BackgroundArr (IStorableArray (Int,Int,Int))++instance Show Background where+	show (BackgroundBit b) = "(BackgroundBit $ " ++ show b ++ ")"+	show (BackgroundG8Bit g) = "(BackgroundG8Bit $ " ++ show g ++ ")"+	show (BackgroundRGB24Depth c) = "(BackgrounddRGB24Depth $ " ++ show c ++ ")"+	show (BackgroundRGBADepth c) = "(BackgroundRGBADepth $ " ++ show c ++ ")"+	show (BackgroundArr {}) = "(BackgroundArr undefined)"+	+        ++-- type RGBA = (UI,UI,UI,UI)++type UIPoint = (UI,UI)+++-- A mapping from a point on the source CBBO to a corresponding point on the canvas CBBO.+data PointMap = PointMap UIPoint UIPoint+        deriving Show++-- Telling CopyBoard whether to use the source alpha or the destination alpha (use source for a /complete/ copy)+data WithAlpha = WithSrcAlpha+               | WithDestAlpha+        deriving Show+++-- AG: The depth is determined by the Background, we only need one!++-- We now use Inst var, but use Inst CBBO in most cases.+data Inst var+     = Allocate +        var             -- tag for this ChalkBoardBufferObject+        (Int,Int)       -- size of ChalkBoardBufferObject+        Depth           -- depth of buffer+        Background      -- what to draw at allocation++       -- ^ This means allocate a buffer, n * m pixels, with a specific depth, and a background (default) color.+{-+AG: other considerations include++    * Do we project into it using 0..1 x 0..1? (say yes for now) ++        (KM: Sounds fine as a first approach. Could support both exact position and percentage (0-1) eventually.)++    * Does it loop round, when viewed? ++        (KM: I would say not when printed onto the screen, at least. Maybe internally for 'from' CBBOs doing splats, but the 'to' board probably won't want it to wrap, just be off the edge.)+-}+       --- Everything can be written as triangles (for now)!+     | SplatTriangle+       var	--  to write from (may be a color, but will be allocated)+       var	--  to write to+       PointMap+       PointMap+       PointMap+     +     | SplatPolygon+       var+       var+       [PointMap]+     +     | SplatColor+       RGBA --Should probably make a color type or something?+       var+       Bool		-- do you do alpha blending (True), or just copy bits (False)+       [UIPoint]++{-+     | SplatWholeBoardColor+	RGBA+	var+-}++     | SplatBuffer+       var		-- src+       var		-- dest++     | CopyBuffer+       WithAlpha+       var		-- src+       var		-- dest+     +     | AllocateImage+       var+       FilePath+     +     | SaveImage+       var+       FilePath+       +     | Delete+       var+       +--     | ScaleAlpha var UI	-- LATER++    | Nested String [Inst var]+++    | Exit+        deriving Show+++copyBoard :: var -> var -> Inst var+copyBoard src target = CopyBuffer WithSrcAlpha src target++colorBoard :: RGB -> var -> Inst var+colorBoard (RGB r g b) target = SplatColor (RGBA r g b 1) target False [ p | p <- [(0,0),(0,1),(1,1),(1,0)]]++{-++AG: Questions and considerations++    * Do you average each same point, inside the triangle from its neighbours, or just sample 1? (We'll test both, and see how they look.) ++        KM: Maybe I'm interpreting the question wrong, but I would think you just take each _vertex_ color++            (1 point sample) and then have OpenGL do blending later? (texture maps would be special splats)++        AG: I think we'll want both. I think of splat as cutting out a piece of the source CBBO, and pasting it onto the dest CBBO.++    * How do we introduce alpha, here? Is it always a property of the source CBBO, or it there other places we can determine this. ++        KM: I would say source alpha. If you want something to cover completely, you leave source alpha as one. If you want it to be partly transparent, you change the source alpha beforehand?++    * Also, we should still support rectangles primitively? ++        KM: Right, and we technically only need both corners as input for this (you mean rectangle splatting right?) Might also want primitive support for lines at least, and since it's designed for presentations, we could have primitive circles/ellipses/text/(arrows?) as well if we want. At least, I think that calculating things like ellipse->triangles would probably be faster in OpenGL/C if we can get it pushed down that far.+-}++{-++Other Considerations ¶++    * How do we allocate (or load from a structure) a pre-existing image? Is this done at create time only, or do we want to update a CBBO? ++    * I'm not sure about the defaults, vs the loading of an 'image'. Both are sorts of assignment/update, as is loading from a file. ++   example1 = alloc (2,2) Bit [[ 0, 1 ], [ 1, 0 ]]+   example2 = alloc (2,2) Bit [[0]]+   example3 = alloc (2,2) Bit "foo.ppm"++-}+++showCBIRs :: Show i => [Inst i] -> String+showCBIRs insts = concat [ prespace " " ([ch] ++ " " ++ show' inst) | (ch,inst) <- zip ('[':repeat ',') insts ] ++ " ]\n"+ where+  show' (Nested msg [])     = "Nested " ++ show msg ++ "[]"+  show' (Nested msg insts') = "Nested " ++ show msg ++ "\n" ++ prespace "   " (showCBIRs insts')+  show' other		= show other+  prespace c		= unlines . map (\ m -> c ++ m) . lines++instance Binary PointMap where+  put (PointMap a b)  = put a >> put b+  get = liftM2 PointMap get get++instance Binary WithAlpha where+  put WithSrcAlpha = put (0 :: Word8)+  put WithDestAlpha = put (1 :: Word8)+  get = do tag <- getWord8+           case tag of+                  0 -> return $ WithSrcAlpha+                  1 -> return $ WithDestAlpha++instance Binary Depth where+  put BitDepth 	  = put (0 :: Word8)+  put G8BitDepth  = put (1 :: Word8)+  put RGB24Depth  = put (2 :: Word8)+  put RGBADepth   = put (3 :: Word8)+  get = do tag <- getWord8+           case tag of+                  0 -> return $ BitDepth+                  1 -> return $ G8BitDepth+                  2 -> return $ RGB24Depth+                  3 -> return $ RGBADepth++{-+data Background+           = BackgroundBit Bool+{-+AG: does a pixel mean later 'draw this *color* (white/black), or draw this pixel *if* black?++KM: I would say the "draw this pixel if true" approach might be faster? Then could use the++    8Bit version if you want to force it to draw all pixels?+-}+           | BackgroundG8Bit UI+              -- this may have the same issue?+           | BackgroundRGB24Depth UI UI UI+           | BackgroundRGBADepth UI UI UI UI+           | BackgroundPtr (Ptr CUChar)		-- the way to interpretate this depends on the Depth field.+	   | BackgroundArr (IStorableArray (Int,Int,Int))+	-}++instance Binary Background where+  put (BackgroundBit b) 	 = put (0 :: Word8) >> put b+  put (BackgroundG8Bit g) 	 = put (1 :: Word8) >> put g+  put (BackgroundRGB24Depth rgb) = put (2 :: Word8) >> put rgb+  put (BackgroundRGBADepth rgba) = put (3 :: Word8) >> put rgba+  put (BackgroundArr arr)        = put (4 :: Word8) >> put arr+  get = do tag <- getWord8+           case tag of+                  0 -> liftM BackgroundBit get+                  1 -> liftM BackgroundG8Bit get+                  2 -> liftM BackgroundRGB24Depth get+                  3 -> liftM BackgroundRGBADepth get+                  4 -> liftM BackgroundArr get++instance Binary var => Binary (Inst var) where+  put (Allocate v sz d b) 	= put (0 :: Word8) >> put v >> put sz >> put d >> put b+  put (SplatTriangle v1 v2 p1 p2 p3) +				= put (1 :: Word8) >> put v1 >> put v2 >> put p1 >> put p2 >> put p3+  put (SplatPolygon v1 v2 ps) 	= put (2 :: Word8) >> put v1 >> put v2 >> put ps+  put (SplatColor rgba v a ps) 	= put (3 :: Word8) >> put rgba >> put v >> put a >> put ps+  put (SplatBuffer src dst)     = put (4 :: Word8) >> put src >> put dst+  put (CopyBuffer wa src dst)   = put (5 :: Word8) >> put wa >> put src >> put dst+  put (AllocateImage rgba v) 	= error "AllocateImage"+  put (SaveImage v nm)		= put (7 :: Word8) >> put v >> put nm+  put (Delete v)		= put (8 :: Word8) >> put v +  put (Nested nm insts)		= put (9 :: Word8) >> put nm >> put insts+  put (Exit)			= put (10 :: Word8)++  get = do tag <- getWord8+	   case tag of+		0 -> liftM4 Allocate get get get get+		1 -> liftM5 SplatTriangle get get get get get+		2 -> liftM3 SplatPolygon get get get+		3 -> liftM4 SplatColor get get get get+		4 -> liftM2 SplatBuffer get get+		5 -> liftM3 CopyBuffer get get get+		6 -> error "AllocateImage"+		7 -> liftM2 SaveImage get get+		8 -> liftM  Delete get+		9 -> liftM2 Nested get get+		10 -> return $ Exit+		
+ Graphics/ChalkBoard/CBIR/Compiler.hs view
@@ -0,0 +1,327 @@+{-# LANGUAGE TypeFamilies, FlexibleInstances, ExistentialQuantification, RankNTypes+  #-}+module Graphics.ChalkBoard.CBIR.Compiler where++-- The idea is to compiler ChalkBoard specs into CBIR instructions.+-- No idea how it will work, only that it will work. So here goes...+-- Quite scrappy, but will clean up.++import Graphics.ChalkBoard.Board+import Graphics.ChalkBoard.Types as Ty++import Graphics.ChalkBoard.O as O+import Graphics.ChalkBoard.O.Internals as OI+import Graphics.ChalkBoard.Core as C+import Graphics.ChalkBoard.Board as B+import Graphics.ChalkBoard.Board.Internals as BI+import Graphics.ChalkBoard.CBIR as CBIR+import Data.Unique+import Data.Reify.Graph+import Graphics.ChalkBoard.Expr as Expr+import Data.Array.Unboxed+import Data.Array.MArray+import Data.Array.IO+import Control.Monad+import Graphics.ChalkBoard.IStorable as IS++import Unsafe.Coerce+import Debug.Trace++-- We always compile  a RGB board.+compile :: (Int,Int) -> BufferId -> Board RGB -> IO [CBIR.Inst Int]+compile (x,y) bufferId brd = compileBoard compileBoardRGB (initBoardContext (x,y) bufferId) brd++mapPoint :: [Trans] -> (R,R) -> (R,R)+mapPoint [] 			(x,y) = (x,y)+mapPoint (Move (xd,yd) : r) 	(x,y) = mapPoint r (x + xd,y + yd)+mapPoint (Scale (xn,yn) : r) 	(x,y) = mapPoint r (x * xn,y * yn)+mapPoint (Rotate theta : r) 	(x,y) = mapPoint r ( cos (-theta) * x - sin (-theta) * y+						   , sin (-theta) * x + cos (-theta) * y+						   )++-- n+1 attempt+initBoardContext (x,y) i = BoardContext [] (x,y) i+data BoardContext = BoardContext +	{ bcTrans :: [Trans]		-- movement of board+	, bcSize :: (Int,Int)		-- approx size of resolution required for final board+	, bcDest :: BufferId			-- board to draw onto+	}+	+updateTrans :: Trans -> BoardContext -> BoardContext +updateTrans mv bc = bc { bcTrans = mv : bcTrans bc }++data DrawWith = DrawWithColor   RGBA Bool		-- Draw with a alpha-ized color, Bool = if blending+	      | SplatFromBuffer BufferId	-- Splat from a specific Buffer+-- LATER	      | DrawWithTrue			-- just an on/off++drawWiths :: [DrawWith] -> BufferId -> (Point -> Point) -> [Point] -> [Inst BufferId]+drawWiths []       _    _ _     = []+drawWiths (dw:dws) dest f nodes = drawWith dw dest f nodes : drawWiths dws dest f nodes++drawWith :: DrawWith -> BufferId -> (Point -> Point) -> [Point] -> Inst BufferId+drawWith (DrawWithColor argb bld) dest f nodes  = +	SplatColor (RGBA r g b a) dest bld (map f nodes)+  where+	(RGBA r g b a) = argb+-- Strange, we are always going from the same point to the same point?+-- We use to have (x,y) (f (x,y))++drawWith (SplatFromBuffer bid) dest f nodes = +	SplatPolygon bid dest [ PointMap (f (x,y)) (f (x,y))+		              | (x,y) <- nodes+			      ]+++{- We have a different compileBoard for each of the 'n' supported types+ -- Right now, this is+ --  * Bool+ --  * RGB+ --  * RGBA+ -- TO BE DONE:+ --  * UI		-- between 0 and 1, gray map+ --  * (R,R)		-- coord+ -- + -}+-- All these generic rewrites are head-type preserving.+-- You can assume that trans has been removed, and that Fmap is normalized.++compileBoard :: (BoardContext -> Board a -> IO [Inst Int]) +		-> BoardContext+		 -> Board a+		 -> IO [CBIR.Inst Int]+-- compileBoard _ _ brd | trace (show ("compileBoard",brd)) False = undefined+compileBoard f bc (Trans mv brd) 		= compileBoard f (updateTrans mv bc) brd+-- (perhaps) we should not do this, until we can handle general functions+--compileBoard f bc (Fmap g (Fmap h brd)) 	= compileBoard f bc (Fmap (g . h) brd)+compileBoard f bc (Fmap g (Trans mv brd)) 	= compileBoard f bc (Trans mv (Fmap g brd))+compileBoard f bc other          		= f bc other++-- | compilerBoardBool interpretes a boolean board in context,+--- either drawing using a specific color, or drawing using a predefined texture.++-- This means write onto the given destination board (either a RGB board,+-- or a ??? board) the result.++compileBoardBool :: [DrawWith]+		 -> BoardContext+		 -> Board a		-- Bool+		 -> IO [CBIR.Inst Int]+compileBoardBool dw bc (Fmap g brd)   = error "(fmap (..) brd) :: Board Bool is not (yet) supported"+compileBoardBool dw bc (Over fn above below) = do+	-- not quite right; assumes that the backing board is white.+	before <- compileBoard (compileBoardBool dw) bc below+	after  <- compileBoard (compileBoardBool dw) bc above+	return   [ Nested "over Bool" +		   ( before +++		     [Nested "`over` Bool" []] +++		     after +		   )+		 ]+compileBoardBool dw bc (Polygon nodes) = do+	return $ [ Nested ("precision factor = " ++ show res) +		    (drawWiths dw (bcDest bc) +		    	       (mapPoint (bcTrans bc))+			       (nodes res))+	  	 ]+  where+	[(x0,y0),(x1,y1),(x2,y2)] = map (mapPoint [ Scale (a,b) | Scale (a,b) <- bcTrans bc]) [(0,0),(1,0),(0,1)]+	res   = 1 + max (abs (fromIntegral x * (x0 - x1))) (abs (fromIntegral y * (y0 - y2)))+	(x,y)  = bcSize bc+compileBoardBool _ _ brd = error $ show ("Bool",brd)+++-- compileBoardRGBA has the effect of drawing the result *on top of* the target board,+-- which is always a RGBA. It is someone elses problem to figure out what this board+-- is originally.++compileBoardRGBA :: BoardContext+		 -> Board a+		 -> IO [CBIR.Inst Int]	+compileBoardRGBA bc (Over fn above below) = do+	-- Correct: by the updating semantics of compileBoardRGBA.+	before <- compileBoard compileBoardRGBA bc below+	after  <- compileBoard compileBoardRGBA bc above+	return   [ Nested "over RGBA" +		   ( before +++		     [Nested "`over` RGBA" []] +++		     after +		   )+		 ]+compileBoardRGBA bc (Image arr) = do+	let ((0,0,0), (maxy,maxx,3)) = IS.bounds arr+	let moves = [Scale (fromIntegral (maxx+1),fromIntegral (maxy+1))] ++ bcTrans bc+	newBoard <- newNumber+	return $ [ Nested ("Image create " ++ show (maxx,maxy)) +		   [ Allocate +			newBoard 	   -- tag for this ChalkBoardBufferObject+        		(maxx+1,maxy+1)		   -- we know size+        		RGBADepth           -- depth of buffer+			(BackgroundArr arr)+		   , SplatPolygon newBoard (bcDest bc) +		    		[ PointMap (x,y) (mapPoint moves (x,y))+		    		| (x,y) <- [(0,0),(1,0),(1,1),(0,1)]+		    		]+	  	   ]+	         ]+compileBoardRGBA bc (PrimConst o) = +	case (evalE $ runO0 o) of+	   Just (E (O_RGBA (RGBA r g b 1))) -> do+		return [ Nested ("Const (a :: RGBA, a = 1)") $+	          	  [ colorBoard (RGB r g b) (bcDest bc) ]+	       	       ]	+	   Just (E (O_RGBA rgba)) -> do+		newBoard <- newNumber+		return [ Nested ("Const (a :: RGBA)") $+			  [ Allocate +		        	newBoard 	   -- tag for this ChalkBoardBufferObject+        			(1,1)		   -- tiny board+        			RGBADepth          -- depth of buffer	+				(BackgroundRGBADepth rgba)+			  , copyBoard newBoard (bcDest bc) +			  ]+	       	       ]	+	   other -> error $ "pure a :: Board RGBA, can not compute a, found " ++ show other+compileBoardRGBA bc (Fmap f other) = do+	case typeOfFun f of+	   FUN_TY (EXPR_TY BOOL_Ty) (EXPR_TY RGBA_Ty) -> do+		case (applyBool f True,applyBool f False) of+		  (Just (O_RGBA tRGBA@(RGBA r g b 0)),Just (O_RGBA fRGBA@(RGBA _ _ _ 0))) -> do+				-- silly case, both are transparent, so do ***NOTHING***+			return $ [ Nested ("Bool -> RGBA, where both values are transparent") [] ]+		  (Just (O_RGBA tRGBA@(RGBA r g b a)),Just (O_RGBA fRGBA@(RGBA _ _ _ 0))) -> do+			-- We take a copy of the back board.+			backBoard <- newNumber+			let overlap = perhapsOverlapBoardBool other+++			let drawWith = (if overlap then [SplatFromBuffer backBoard] else []) ++ [DrawWithColor (RGBA r g b a) False]++				-- Write onto the *same* board, but with projections from the backBoard+				-- which is a snapshot of the board right now.+			rest <- compileBoard (compileBoardBool drawWith)  bc other+			return $ +			     [ Allocate +		        	backBoard 	   -- tag for this ChalkBoardBufferObject+        			(bcSize bc)	   -- we know size+        			RGBADepth          -- depth of buffer	+				(BackgroundRGBADepth (RGBA 0 0 0 0))+			     , copyBoard (bcDest bc) backBoard +			     ] ++ rest ++ +			     [ Delete backBoard+			     ]+		  other -> error $ "fmap (f :: Bool -> RGBA) brd, when f False is not transparent, is unsupported (a = " +					++ show other+	   FUN_TY (EXPR_TY RGBA_Ty) (EXPR_TY RGBA_Ty) -> error $ "fmap (... :: RGBA -> RGBA) brd, unsupported fmap argument"+	   FUN_TY a b -> error $ "fmap (... :: " ++ show a ++ " -> " ++ show b ++ ") brd :: Board RGBA is not supported"+compileBoardRGBA _ brd = error $ show ("RGBA",brd)+++-- This means write onto the given destination board (always a RGB board) the result.+compileBoardRGB :: (BoardContext)+		-> Board a+		-> IO [CBIR.Inst Int]+compileBoardRGB bc (Over fn top bottom) = compileBoard compileBoardRGB bc top+compileBoardRGB bc (BI.PrimConst o) = +	case (evalE $ runO0 o) of+	   Just (E (O_RGB (RGB r g b))) -> do+		return [ Nested ("Const (a :: RGB)") $+	          	  [ colorBoard (RGB r g b) (bcDest bc) ]+	       	       ]	+	   _ -> error "pure a :: Board RGB, can not compute a??"+compileBoardRGB bc (Fmap f other) = do+	fMapFn <- patternOf $ f+	case typeOfFun f of+	   FUN_TY (EXPR_TY BOOL_Ty) (EXPR_TY RGB_Ty) -> do+		backBoard <- newNumber+		frontBoard <- newNumber+--		print $ runToFind (O_Bool False) fMapFn+		let (O_RGB fcol) = runToFind (O_Bool False) fMapFn+		let (O_RGB tcol) = runToFind (O_Bool True) fMapFn+		let (RGB r g b)    = tcol+		let (RGB r' g' b') = fcol+--		print (fcol,tcol)+		let bc' = bc +		rest <- compileBoard (compileBoardBool [DrawWithColor (RGBA r g b 1) False]) bc' other+		return [ Nested ("BOOL -> RGB") $+			 [ Allocate +        			backBoard 	   -- tag for this ChalkBoardBufferObject+        			(1,1)		   -- we know size+        			RGB24Depth           -- depth of buffer+				(BackgroundRGB24Depth (RGB r' g' b'))+			, Allocate +				frontBoard+        			(1,1)		   -- we know size+        			RGB24Depth           -- depth of buffer+				(BackgroundRGB24Depth (RGB r g b))+			, copyBoard backBoard (bcDest bc)+			] ++ rest ++ +			[ Delete backBoard, Delete frontBoard]]+	   FUN_TY (EXPR_TY RGBA_Ty) (EXPR_TY RGB_Ty) -> do+		-- turn rgb*ALPHA* thing, and translate this into a rgb.+		-- Assume unAlpha (for now)+		newBoard <- newNumber+		let bc' = bc+			 { bcDest = newBoard+  		         }+		rest <- compileBoard compileBoardRGBA bc' other+		return [ Nested ("RGBA -> RGB") $ +			[ Allocate +		        	newBoard 	   -- tag for this ChalkBoardBufferObject+        			(bcSize bc)		   -- we know size+        			RGBADepth           -- depth of buffer+				(BackgroundRGBADepth (RGBA 1 1 1 1))	-- ???+			] ++ rest +++			[  copyBoard newBoard (bcDest bc)+			, Delete newBoard+		        ]]+	   FUN_TY a b -> error $ "fmap (... :: " ++ show a ++ " -> " ++ show b ++ ") brd :: Board RGB is not supported"+compileBoardRGB _ brd = error $ show ("RGB",brd)+++-- Do you have overlapping shapes? Default to True, to be safe if do not know.+	+perhapsOverlapBoardBool :: Board a -> Bool+perhapsOverlapBoardBool (Trans mv brd) = perhapsOverlapBoardBool brd+perhapsOverlapBoardBool (Polygon _)    = False	-- single polygon; no overlap+perhapsOverlapBoardBool _              = True+++-- choice+patternOf :: (O a -> O b) -> IO (Graph Expr)+patternOf f = reifyO $ f (O (error "undefined shallow value") (E $ Var 1))+++runToFind :: Expr E -> Graph Expr -> Expr E+runToFind arg (Graph nodes root) = eval (find root)+   where+	find i = case Prelude.lookup i nodes of+		    Just v -> v+		    Nothing -> error $ "can not find " ++ show i+	eval (Choose a b c) =+		case eval (find c) of+		  O_Bool True -> eval (find a)	-- false+		  O_Bool False -> eval (find b)	-- false+		  e -> error $ "expected a Bool, found something else " ++ show e+	eval (Var 1) = arg+	eval (O_RGB c) = O_RGB c++	eval (UnAlpha c) = case eval (find c) of+			    Expr.Alpha i (E c') -> c'+		  	    v -> UnAlpha (E v)+	eval (Expr.Alpha i c) = case eval (find c) of+			    UnAlpha (E c') | i == 1 -> c'+		  	    v -> Expr.Alpha i (E v)+	eval e = error $ "opps (eval) " ++ show e++-- Notice the lower case 'bool', because we are untyped in the compiler.+applyBool :: (O bool -> O a) -> Bool -> Maybe (Expr E)+applyBool f b = liftM unE (evalE (runO1 f (E $ O_Bool b)))++applyVar :: (O a -> O b) -> Expr E+applyVar f = unE (runO1 f (E $ Var 0))+++newNumber :: IO Int+newNumber = do+	u <- newUnique+	return $ hashUnique u + 1000
+ Graphics/ChalkBoard/Core.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE TypeSynonymInstances #-}++module Graphics.ChalkBoard.Core +	( -- * Pointwise operators.+	  interpBool +	, sampleUI+	, withMask+	, withDefault+--	, choose+	  -- * Colors+	, alpha, withAlpha, unAlpha, transparent+	) where++-- This provided the internal functions, many of which are reflected into the "Observable", O.++import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.Utils++------------------------------------------------------------------------------++-- Pointwise operators++-- | Covert a Bool (mask point) into a unit interval.+interpBool :: Bool -> UI+interpBool True  = 1.0+interpBool False = 0.0++-- | sample a UI, giving a point of a mask.+sampleUI :: UI -> Bool+sampleUI n = n >= 0.5++-- | Use a mask to create a Just value, or Nothing.+withMask :: a -> (Bool -> Maybe a)+withMask a True  = Just a+withMask _ False = Nothing++-- | With a default if you do not have a Just.+withDefault :: a -> (Maybe a -> a)+withDefault a Nothing  = a+withDefault _ (Just b) = b++-- | 'choose' between two values.+choose :: a -> a -> (Bool -> a)+choose t  _f True  = t+choose _t f  False = f++------------------------------------------------------------------------------------------+-- Colors with alpha++alpha :: RGB -> RGBA+alpha (RGB r g b) = RGBA r g b 1++withAlpha :: RGB -> UI -> RGBA+withAlpha c a = RGBA r g b a+  where (RGB r g b) = c -- scale a c +			-- turn off scaling++unAlpha :: RGBA -> RGB+unAlpha (RGBA r g b _) = RGB r g b++transparent :: RGBA +transparent = RGBA 0 0 0 0
+ Graphics/ChalkBoard/Expr.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE TypeFamilies, GADTs #-}+module Graphics.ChalkBoard.Expr where+	+--import Control.Applicative+import Graphics.ChalkBoard.Types -- hiding (Alpha)+import qualified Graphics.ChalkBoard.Types as Ty+import Graphics.ChalkBoard.Core as C+import Data.Reify.Graph+import Data.Reify+import Control.Applicative as AF+import qualified Data.Traversable as T+import qualified Data.Foldable as F+import Data.Monoid+import Data.Maybe+import qualified Data.List as L+import Control.Monad++-- All the functions in our first order language.+data Expr s +	= Choose s s s+	| O_Bool Bool+	| O_RGB RGB+	| O_RGBA RGBA -- (Ty.Alpha RGB)+	| O_Pair s s 			-- (a,b)+	| O_Fst s+	| O_Snd s+	| Lit R+	| Var Int+	| OrBool		-- the || function+	| Alpha UI s		-- O_Alpha?+	| ScaleAlpha UI s			-- RGBA -> RGBA+	| UnAlpha s+	deriving Show++newtype E = E (Expr E)+	deriving Show++data ExprType = BOOL_Ty | RGB_Ty | RGBA_Ty	-- we seems to have this all over+	deriving (Show, Eq)++exprTypeE :: E -> Maybe ExprType+exprTypeE (E e) = exprType e++exprType :: Expr E -> Maybe ExprType+exprType (Choose _ a b)     = getFirst (First (exprTypeE a) `mappend` (First (exprTypeE b)))+exprType (O_Bool {})        = return BOOL_Ty+exprType (O_RGB {})         = return RGB_Ty+exprType (O_RGBA {}) 	    = return RGBA_Ty+exprType (Alpha {})	    = return RGBA_Ty+exprType (UnAlpha {})	    = return RGB_Ty+exprType (ScaleAlpha {})    = return RGBA_Ty+exprType _                  = Nothing++exprUnifyE :: E -> ExprType -> [(Int,ExprType)]+exprUnifyE (E e) = exprUnify e++-- exprUnify :: what the expected result type is, and does it unify+exprUnify :: Expr E -> ExprType -> [(Int,ExprType)]+exprUnify (Choose a b c) ty = L.nub (exprUnifyE a ty ++ exprUnifyE b ty ++ exprUnifyE c BOOL_Ty)+exprUnify (O_Bool {}) BOOL_Ty = []+exprUnify (O_RGB {}) RGB_Ty = []+exprUnify (O_RGBA {}) RGBA_Ty = []+exprUnify (Alpha _ e) RGBA_Ty = exprUnifyE e RGB_Ty+exprUnify (UnAlpha e) RGB_Ty = exprUnifyE e RGBA_Ty+exprUnify (ScaleAlpha _ e) RGBA_Ty = exprUnifyE e RGBA_Ty+exprUnify (Var i) ty = [(i,ty)]+exprUnify other ty = error $ "exprUnify" ++ show (other,ty)+++-- evaluate to a normal form (constant folding, really)+evalExprE :: Expr E -> Maybe (Expr E)+-- already values+evalExprE e@(Var {}) 		= return e+evalExprE e@(O_Bool {}) 	= return e+evalExprE e@(O_RGB {}) 	= return e+evalExprE e@(O_RGBA {}) 	= return e+-- try some evaluation, please.+evalExprE (Choose a b c) = +	case liftM unE $ evalE c of+	  Just (O_Bool True)  -> liftM unE $ evalE a+	  Just (O_Bool False) -> liftM unE $ evalE b+	  other -> Nothing+evalExprE (Alpha a e) = +	case liftM unE $ evalE e of+	    Just (O_RGB c) -> return $ O_RGBA (C.withAlpha c a)+	    other -> Nothing+evalExprE other = Nothing++unE :: E -> Expr E+unE (E e) = e++evalE :: E -> Maybe E+evalE (E e) = liftM E (evalExprE e)++-- The generic plubing for our Expr datatype.				-- ++instance MuRef E where+  type DeRef E = Expr+  mapDeRef f (E e) = T.traverse f e+++instance T.Traversable Expr where+	traverse f (Choose a b c) 	= Choose <$> f a <*> f b <*> f c+	traverse f (Alpha c e) 		= Alpha c <$> f e+	traverse f (UnAlpha e) 		= UnAlpha <$> f e+	traverse f (ScaleAlpha c e) 	= ScaleAlpha c <$> f e+	traverse f (O_Bool v)		= pure $ O_Bool v+	traverse f (O_RGB v)		= pure $ O_RGB v+	traverse f (Lit r)		= pure $ Lit r+	traverse f (Var i)		= pure $ Var i+	traverse f (O_RGBA v)		= pure $ O_RGBA v+	-- TODO+	+instance F.Foldable Expr where+	foldMap f (Choose a b c) = mconcat [f a, f b, f c]+	--- TODO+	+instance Functor Expr where+	fmap f (Choose a b c) = Choose (f a) (f b) (f c)+	--- TODO
+ Graphics/ChalkBoard/IStorable.hs view
@@ -0,0 +1,47 @@+{-# OPTIONS_GHC -fno-warn-unused-imports #-}+module Graphics.ChalkBoard.IStorable +	( IStorableArray 	-- abstract+	, iStorableArray+	, (!)+	, bounds+	, withIStorableArray+	, touchIStorableArray+	) where+	+	+import qualified Data.Array.MArray as M	-- bogus warning, see OPTIONS+import qualified Data.Array.Unboxed as U+import Data.Array.Unboxed (Ix, UArray)+import qualified Data.Array.Storable as S+import Foreign.Ptr+import Data.Word+import Data.Binary+import System.IO.Unsafe++-- This is a create one, read many times array, that is also+-- storable, that is you can get a 'Ptr' to it, provided you+-- promise not to change the (contents of the) Ptr.++data IStorableArray i = IStorableArray (S.StorableArray i Word8) (UArray i Word8)++instance (Ix ix, Binary ix) => Binary (IStorableArray ix) where+   put isa@(IStorableArray _ arr) = put arr+   get = do arr <- get+	    return $ unsafePerformIO $ iStorableArray arr++iStorableArray :: (Ix i) => UArray i Word8 -> IO (IStorableArray i)+iStorableArray arr = do+  arrT <- M.unsafeThaw arr+  return (IStorableArray arrT arr)+	+(!) :: (Ix i) => IStorableArray i -> i -> Word8+(!) (IStorableArray _ arr) ix = arr U.! ix++bounds :: (Ix i) => (IStorableArray i) -> (i,i)+bounds (IStorableArray sa ua) = U.bounds ua++withIStorableArray :: IStorableArray i -> (Ptr Word8 -> IO a) -> IO a+withIStorableArray (IStorableArray sa _) k = S.withStorableArray sa k++touchIStorableArray :: IStorableArray i -> IO ()+touchIStorableArray (IStorableArray sa _) = S.touchStorableArray sa
+ Graphics/ChalkBoard/Main.hs view
@@ -0,0 +1,192 @@+module Graphics.ChalkBoard.Main +	( ChalkBoard+	, drawChalkBoard+	, writeChalkBoard+	, updateChalkBoard+	, drawRawChalkBoard+	, exitChalkBoard+	, startChalkBoard+	, openChalkBoard+	, chalkBoardServer+	) where++import System.Process+import System.Environment+import System.IO+import System.Exit+import Control.Concurrent ++import Graphics.ChalkBoard.Core+import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.Board+import Graphics.ChalkBoard.CBIR+import Graphics.ChalkBoard.CBIR.Compiler+import Graphics.ChalkBoard.OpenGL.CBBE+import Graphics.ChalkBoard.O+import Graphics.ChalkBoard.Options+import Codec.Image.DevIL++import Data.Word+import Control.Concurrent.MVar+import Control.Concurrent+import System.Cmd+import Data.Binary as Bin++import qualified Data.ByteString.Lazy as B+	+	+data ChalkBoardCommand+	= DrawChalkBoard (Board RGB)+	| UpdateChalkBoard (Board RGB -> Board RGB)+	| WriteChalkBoard FilePath+	| ExitChalkBoard+	| DrawRawChalkBoard [Inst BufferId]+	+data ChalkBoard = ChalkBoard (MVar ChalkBoardCommand) (MVar ())+++-- | Draw a board onto the ChalkBoard.+drawChalkBoard :: ChalkBoard -> Board RGB -> IO ()+drawChalkBoard (ChalkBoard var _) brd = putMVar var (DrawChalkBoard brd)++-- | Write the contents of a ChalkBoard into a File.+writeChalkBoard :: ChalkBoard -> FilePath -> IO ()+writeChalkBoard (ChalkBoard var _) nm = putMVar var (WriteChalkBoard nm)+++-- | modify the current ChalkBoard.+updateChalkBoard :: ChalkBoard -> (Board RGB -> Board RGB) -> IO ()+updateChalkBoard (ChalkBoard var _) brd = putMVar var (UpdateChalkBoard brd)++-- | Debugging hook for writing raw CBIR code.+drawRawChalkBoard :: ChalkBoard -> [Inst BufferId] -> IO ()+drawRawChalkBoard (ChalkBoard var _) cmds = putMVar var (DrawRawChalkBoard cmds)++-- | pause for this many seconds, since the last redraw *started*.+pauseChalkBoard :: ChalkBoard -> Double -> IO ()+pauseChalkBoard _ n = do+	threadDelay (fromInteger (floor (n * 1000000)))+	+-- | quit ChalkBoard.+exitChalkBoard :: ChalkBoard -> IO ()+exitChalkBoard (ChalkBoard var end) = do+	putMVar var ExitChalkBoard+	takeMVar end +	return ()++-- | Start, in this process, a ChalkBoard window, and run some commands on it.+startChalkBoard :: [Options] -> (ChalkBoard -> IO ()) -> IO ()+startChalkBoard options cont = do+	putStrLn  "[Starting ChalkBoard]"+	ilInit++	v0 <- newEmptyMVar+	v1 <- newEmptyMVar +	v2 <- newEmptyMVar +	vEnd <- newEmptyMVar+	+	forkIO $ compiler options v1 v2 +	forkIO $ do+		() <- takeMVar v0+		cont (ChalkBoard v1 vEnd)+		print "[Done]"+	startRendering viewBoard v0 v2 options+	return ()	++-- | Open, remotely, a ChalkBoard windown, and return a handle to it.+-- Needs "CHALKBOARD_SERVER" set to the location of the ChalkBoard server.+openChalkBoard :: [Options] -> IO ChalkBoard+openChalkBoard args = do+	putStrLn "[Opening Channel to ChalkBoard Server]"+	ilInit++	v0 <- newEmptyMVar+	v1 <- newEmptyMVar +	v2 <- newEmptyMVar +	vEnd <- newEmptyMVar++	(ein,eout,err,pid) <- openServerStream		+	+	let options = encode (args :: [Options])+	B.hPut ein (encode (fromIntegral (B.length options) :: Word32))+	B.hPut ein options+	hFlush ein++	forkIO $ compiler args v1 v2+	forkIO $ do+		let loop n = do+			v <- takeMVar v2+			let code = encode v+			B.hPut ein (encode (fromIntegral (B.length code) :: Word32))+			B.hPut ein code+			hFlush ein+			case v of+			  [Exit] -> putMVar vEnd ()+			  _ -> loop $! (n+1)+		loop 0++	return (ChalkBoard v1 vEnd)++viewBoard :: Int+viewBoard = 0++compiler :: [Options] -> MVar ChalkBoardCommand -> MVar [Inst Int] -> IO ()+compiler options v1 v2 = do+	putMVar v2 [Allocate viewBoard (x,y) RGB24Depth (BackgroundRGB24Depth (RGB 1 1 1))]+	loop (0::Integer) (boardOf (o (RGB 1 1 1)))+  where     +     (x,y) = head ([ (x,y) | BoardSize x y <- options ] ++ [(400,400)])+     loop n old_brd = do+	cmd <- takeMVar v1+	case cmd of+	  DrawChalkBoard brd -> do+		cmds <- compile (x,y) viewBoard (move (0.5,0.5) brd)+--		putStrLn $ showCBIRs cmds+		putMVar v2 cmds+		loop (n+1) brd+	  UpdateChalkBoard fn -> do+		let brd = fn old_brd+		cmds <- compile (x,y) viewBoard (move (0.5,0.5) brd)+--		putStrLn $ showCBIRs cmds+		putMVar v2 cmds+		loop (n+1) brd+	  DrawRawChalkBoard cmds -> do+		putMVar v2 cmds+		loop (n+1) (error "Board in an unknown state")+	  WriteChalkBoard filename -> do+		putMVar v2 [SaveImage viewBoard filename]+		loop (n+1) old_brd++	  ExitChalkBoard -> putMVar v2 [Exit]+++openServerStream :: IO (Handle,Handle,Handle,ProcessHandle)+openServerStream = do+	server <- getEnv "CHALKBOARD_SERVER" `catch` (\ _ -> return "chalkboard-server-1_9_0_14")+	runInteractiveProcess server [] Nothing Nothing `catch` (\ _ -> do print "DOOL" ; error "")+++-- | create an instance of the ChalkBoard. Only used by the server binary.+chalkBoardServer :: IO ()+chalkBoardServer = do+	v0 <- newEmptyMVar+	v2 <- newEmptyMVar +	bs <- B.hGet stdin 4+	let n :: Word32+	    n = Bin.decode bs+	options <- B.hGet stdin (fromIntegral n)+	forkIO $ do+		let loop = do+			bs <- B.hGet stdin 4+			let n :: Word32+			    n = Bin.decode bs+			packet <- B.hGet stdin (fromIntegral n)+			putMVar v2 (decode packet :: [Inst BufferId])+			loop+		loop+	startRendering viewBoard v0 v2 (decode options :: [Options])+	return ()	++++	
+ Graphics/ChalkBoard/O.hs view
@@ -0,0 +1,120 @@+{-# LANGUAGE TypeFamilies, GADTs, FlexibleInstances #-}+module Graphics.ChalkBoard.O ( -- * The Observable datatype+	  O	-- abstract+	, Obs(..)+        , unO+	  -- * The Observable language+	, true, false+	, choose+	, alpha+	, withAlpha+	, unAlpha+	, transparent+	, red+	, green+	, blue+	, white+	, black+	, cyan+	, purple+	, yellow+	) where+	+import Graphics.ChalkBoard.Types as Ty+import Graphics.ChalkBoard.O.Internals as I+import qualified Graphics.ChalkBoard.Core as C+import Graphics.ChalkBoard.Expr as Expr+++------------------------------------------------------------------------------------------------+-- Obs Class+------------------------------------------------------------------------------------------------++-- Applicative Functor like thing.+------------------------------------------------------------------------------------------------++class Obs a where+	-- construct an Observable+  	o :: a -> O a++------------------------------------------------------------------------------------------------+-- Projection+------------------------------------------------------------------------------------------------++-- | project into an unobservable version of O.+unO :: O o -> o+unO (O o _) = o++------------------------------------------------------------------------------------------------+-- Instances of Pure+------------------------------------------------------------------------------------------------++-- Are you allowed to say "Pure Bool"?+instance Obs Bool where+	o a = primO (O_Bool a) a++instance Obs RGB where+	o c = primO (O_RGB c) c++instance Obs RGBA where+	o c = primO (O_RGBA c) c+++-- GADT attack+--lamO :: (O a -> O b) -> O (a -> b)+--lamO = Lam+++-- | choose between two Observable alternatives, based on a Observable 'Bool'+choose :: O o -> O o -> O Bool -> O o+choose (O a ea) (O b eb) (O c ec)  = O (if c then a else b) (E $ Choose ea eb ec)++-- square :: Board (O Bool)++-- | Observable 'True'.+true :: O Bool+true  = primO (O_Bool True) True++-- | Observable 'False'.+false :: O Bool+false = primO (O_Bool False) False++------------------------------------------------------------------------------------------------+-- Functions from Core, lifted into the O type.+------------------------------------------------------------------------------------------------++-- | Observable function to add an alpha channel.+alpha :: O RGB -> O RGBA+alpha (O a e) = O (C.alpha a) (E $ Expr.Alpha 1 e)++-- | Observable function to add a preset alpha channel.+withAlpha :: UI -> O RGB -> O RGBA+withAlpha n (O a e) = O (C.alpha a) (E $ Expr.Alpha n e)++-- | Observable function to remove the alpha channel.+unAlpha :: O (RGBA) -> O RGB+unAlpha (O a e) = O (C.unAlpha a) (E $ Expr.UnAlpha e)++-- | Observable function to add a transparent alpha channel.+transparent :: O RGB -> O RGBA+transparent (O a e) = O (C.alpha a) (E $ Expr.Alpha 0 e)++++red    :: O RGB+red    = o $ RGB 1.0 0.0 0.0+green  :: O RGB+green  = o $ RGB 0.0 1.0 0.0+blue   :: O RGB+blue   = o $ RGB 0.0 0.0 1.0+white  :: O RGB+white  = o $ RGB 1.0 1.0 1.0+black  :: O RGB+black  = o $ RGB 0.0 0.0 0.0+cyan   :: O RGB+cyan   = o $ RGB 0.0 1.0 1.0+purple :: O RGB+purple = o $ RGB 1.0 0.0 1.0+yellow :: O RGB+yellow = o $ RGB 1.0 1.0 0.0+
+ Graphics/ChalkBoard/O/Internals.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE TypeFamilies, GADTs  #-}+module Graphics.ChalkBoard.O.Internals+	( O(..) +	, primO+	, runO0+	, runO1+	, showO+	, reifyO+	, OType(..)+	, typeOfFun+	) where+	+import Graphics.ChalkBoard.Expr as Expr+import qualified Data.Traversable as T+import qualified Data.Foldable as F+import Data.Reify.Graph+import Data.Reify+import Data.List as L+	+------------------------------------------------------------------------------------------------+-- Our O (Observable) structure.+------------------------------------------------------------------------------------------------++		+data O o where+   O :: o -> E -> O o+--   Lam :: (O a -> O b) -> O (a -> b)++-- Assuming that o is *not* a function, otherwise+-- <*> will fail with a pattern match failure.+primO :: Expr E -> o -> O o+primO e o = O o (E $ e)+++runO1 :: (O a -> O b) -> E -> E+runO1 f v1 = case f (O (error "undefined shallow value") v1) of+	    O _ e -> e++runO0 :: O a -> E+runO0 (O _ e) = e++instance Show o => Show (O o) where+  show (O o _) = show o++-- showing structure, not the value+showO :: (Show a) => O a -> String+showO = undefined++reifyO :: O a -> IO (Graph Expr)+reifyO (O _ e) = reifyGraph e+++data OType = UNKNOWN_TY | FUN_TY OType OType | EXPR_TY ExprType+	deriving Show++-- Here is the problem: given the result type, what is the argument type?+	+typeOfO :: O a -> OType+typeOfO (O a e) =+	case exprTypeE e of+ 	  Nothing -> UNKNOWN_TY+	  Just ty  -> EXPR_TY ty+--typeOfO (Lam e) = typeOfO' 0 (Lam e)++typeOfO' :: Int -> O a -> OType+typeOfO' i o@(O {}) = typeOfO o++typeOfFun = typeOfFun' 0 +++typeOfFun' i e = FUN_TY ty1 ty2+	   where+	     e' = (e (O (error "typeoOfO") (E $ Var i)))+  	     ty2 = typeOfO (e (O (error "typeoOfO") (E $ Var i)))+  	     ty1 = case L.lookup i (exprUnifyO e' ty2) of+	 	     Nothing -> error "opps: typeOfO"+		     Just ty -> ty+		+exprUnifyO :: (O a) -> OType -> [(Int,OType)]+exprUnifyO (O a e) (EXPR_TY ty) = [ (i,EXPR_TY t) | (i,t) <- exprUnifyE e ty ]+exprUnifyO (O a e) ty = error $ "exprUnifyO (O ...) " ++ show ty+--exprUnifyO (Lam e) (FUN_TY t1 t2) = []		--- for now+--exprUnifyO (Lam e) ty = error $ "exprUnifyO (Lam ...) " ++ show ty++
+ Graphics/ChalkBoard/OpenGL/CBBE.hs view
@@ -0,0 +1,1049 @@+-- {-# OPTIONS_GHC -ddump-simpl-stats #-}++-- ChalkBoard Back End+-- August 2009+-- Kevin Matlage, Andy Gill+++module Graphics.ChalkBoard.OpenGL.CBBE where+++-- ChalkBoard or Non-Standard Packages+import Graphics.ChalkBoard.CBIR as CBIR+import Graphics.ChalkBoard.IStorable as IS+import Graphics.ChalkBoard.Types as T (RGB(..),RGBA(..))+import Graphics.ChalkBoard.OpenGL.Monad+import Graphics.ChalkBoard.Options++import Graphics.UI.GLUT hiding ( GLuint, GLint, GLfloat )+import qualified Graphics.UI.GLUT as GLUT +import Graphics.Rendering.OpenGL.Raw.Core31 as GL+import Graphics.Rendering.OpenGL.Raw.ARB.Compatibility (gl_LUMINANCE)+import Codec.Image.DevIL++-- Base Packages+import Prelude hiding ( lookup )+import Control.Concurrent.MVar ( MVar, newEmptyMVar, tryTakeMVar, takeMVar, putMVar )+import Control.Monad ( when )+import Foreign.Ptr ( Ptr, nullPtr, castPtr )+import Foreign.C.Types ( CUChar )+import Foreign.Marshal.Alloc ( malloc, free )+import Foreign.Storable ( peek )+import Data.Map ( Map, empty, insert, delete, lookup, notMember )+import Data.Maybe ( fromMaybe )+import Data.Array.Unboxed as U  +import Data.Array.Storable ( withStorableArray, StorableArray )+import Data.Array.MArray ( unsafeThaw, newArray_, MArray )+import System.Exit ( exitWith, ExitCode(..) )+++-- Debugging Packages+import System.IO ( writeFile, appendFile )+import System.Directory ( removeFile, doesFileExist )+import Data.Unique+--import Data.Time.Clock+++++++startRendering :: BufferId -> MVar () -> MVar ([Inst BufferId]) -> [Options] -> IO()+startRendering board booted insts options = do++    -- Take the initial CBIR instructions out of the mvar+    initChanges <- takeMVar insts+	+    let (x,y) = case initChanges of+	       [Allocate viewBoard (w,h) _ _] | viewBoard == board -> (fromIntegral w,fromIntegral h)+	       _ -> error $ "Opps: strange bootstrapping code: " ++ show initChanges++    -- Init GLUT and take/apply any command line arguments that pertain to it or X windows+    getArgsAndInitialize+    +    -- Select display mode: Double buffered, RGBA,  Alpha components, Depth buffer+    initialDisplayMode $= [  DoubleBuffered, RGBAMode, WithAlphaComponent, WithDepthBuffer ]+    -- Get an 800x600 window. Should we change the default?+    initialWindowSize $= Size x y+    -- Start the window in upper left corner of the screen+    initialWindowPosition $= Position 0 0+    -- Open the window+    createWindow "ChalkBoard"+    +    -- Initialize some OpenGL settings and features.+    initGL+    -- Also initialize devIL for importing/exporting images+    ilInit+    +    -- Initialize the ChalkBoard Monad state/environment+    let state = initCBMState board+    env <- initCBMEnv options state+    +    let debug = (debugFrames env)+    when (debug) $+        writeFile "./debug.html" "<HTML>\n<TITLE>ChalkBoard Debugging</TITLE>\n<br>\n"++    -- See which version of OpenGL is being used.+    (major,minor) <- get (majorMinor glVersion)+    print $ "OpenGL Version: " ++ (show major) ++ "." ++ (show minor)+    +    -- See if one of the fbo extensions is supported+    extensions <- get glExtensions+    let fboExtension = ("GL_EXT_framebuffer_object" `elem` extensions || "GL_ARB_framebuffer_object" `elem` extensions)+    +    fboOn <- if (fboSupport env == True && (major >= 3 || fboExtension))+                 then do+                     -- Initialize a FBO+                     (fboIdPtr, texIdPtr) <- initFBO -- The returned FBO is still bound as the current framebuffer+                     -- Check if FBOs are supported+                     status <- glCheckFramebufferStatus gl_FRAMEBUFFER+                     print $ "FBO Unsupported?: " ++ (show (status == gl_FRAMEBUFFER_UNSUPPORTED))++                     -- Depending on whether they're supported or not, determine whether FBOs should be used+                     complete <- if (status == gl_FRAMEBUFFER_COMPLETE)+                                     then do+                                         print "FBO Initialization Complete. Using FBOs."+                                         st <- takeMVar (envForStateVar env)+                                         putMVar (envForStateVar env) (st {fboPtr = fboIdPtr})+                                         return True+                                     else do+                                         print "FBO Initialization Incomplete. Not Using FBOs."+                                         glDeleteFramebuffers 1 fboIdPtr -- Delete the FBO since it isn't being used+                                         return False++                     -- Delete the texture that was just used to test if FBOs were supported+                     glDeleteTextures 1 texIdPtr+                     -- Return whether the FBO initialization was complete+                     return complete+                 else do+                     print "FBOs Not Supported. Not Using FBOs."+                     return False++    -- Start the changeboard timer callback, which will execute all CBIR instructions that are passed in+    runCBM (changeBoard' (changeBoard insts)  initChanges) (env {fboSupport = fboOn})++    -- Register the function called when the window is resized+    reshapeCallback $= Just resizeScene+    -- Register the function called when the keyboard is pressed.+    keyboardMouseCallback $= Just (keyPressed debug)+    +    -- Start the main GLUT event loop after telling the front end that OpenGL has been booted+    flush+    putMVar booted ()+    mainLoop+++++++-- Function to initialize the state of the CBBE+initCBMState :: BufferId -> CBstate+initCBMState board = CBstate board (empty::Map BufferId TextureInfo) nullPtr+++-- TODO: add option for verboseness+--Funciton to initialize the environment of the CBBE monad+initCBMEnv :: [Options] -> CBstate -> IO ( CBenv )+initCBMEnv options state = do+        let fboSupport' = not $ NoFBO `elem` options+            debugFrames' = DebugFrames `elem` options+            debugAll' = DebugAll `elem` options+            debugBoards' = concat [ids | DebugBoards ids <- options]+        v <- newEmptyMVar+        putMVar v state+        return $ CBenv debugFrames' debugAll' debugBoards' fboSupport' v+++++++-- Function to initialize some OpenGL settings and features+initGL :: IO ()+initGL = do+    clearColor $= Color4 1 1 1 1 -- Clear the background color to white+    +    -- Not sure if a couple of the things in this block are really needed+    clearDepth $= 1 -- Enables clearing of the depth buffer+    depthFunc  $= Just Less -- Type of depth test+    shadeModel $= Smooth -- Enables smooth color shading+    polygonMode $= (Fill,Fill)+    +    -- Blending and texture functions that make chalkboard work correctly+    blend $= Enabled+    blendFuncSeparate $= ((SrcAlpha, OneMinusSrcAlpha), (One, OneMinusSrcAlpha)) -- Specify color and alpha blend separately+    texture Texture2D $= Enabled+    textureFunction $= Replace --Replace destination color and alpha with texture's color and alpha+    +    Size width height <- get windowSize -- Get the size of the window+    resizeScene (Size width height) -- Resize the viewport and projection+    ++++++-- Will possibly want to change this from using the window w/h to something else (maintain ratio?)+-- Reshape callback function to resize the viewing area appropriately when the window is resized.+resizeScene :: Size -> IO ()+resizeScene (Size w 0) = resizeScene (Size w 1) -- prevents divide by zero+resizeScene s@(Size width height) = do+--    print "resizeScene"+    let w = fromIntegral width+        h = fromIntegral height+    viewport   $= (Position 0 0, s)	-- the whole window is used+    matrixMode $= Projection+    loadIdentity+    ortho2D 0 w 0 h -- Will probably want to change this from using the window w/h+    matrixMode $= Modelview 0+    flush -- Might not be necessary+    postRedisplay Nothing+++++++-- Keyboard and Mouse callback function+-- Right now just exits the program when the escape key is pressed.+keyPressed :: Bool -> KeyboardMouseCallback+keyPressed debug (Char '\27') Down _ _ = do+    when (debug) $ appendFile "./debug.html" "</HTML>"+    exitWith ExitSuccess -- 27 is ESCAPE+keyPressed _     _            _    _ _ = return ()+++++++-- Function to initiallize a framebuffer object (FBO) so that we can know whether FBOs are supported.+-- Will also possibly want to just test the OpenGL version string as an initial check before wasting the time to do this.+initFBO :: IO( (Ptr GLuint, Ptr GLuint) )+initFBO = do+    -- Create a Framebuffer object and bind it+    fboIdPtr <- malloc :: IO(Ptr GLuint)+    glGenFramebuffers 1 fboIdPtr+    fboId <- peek fboIdPtr+    glBindFramebuffer gl_FRAMEBUFFER fboId+    +    let w = 1+        h = 1+    +    {- +    -- Create a renderbuffer object to store depth info+    rboIdPtr <- malloc :: IO(Ptr GLuint)+    glGenRenderbuffers 1 rboIdPtr+    rboId <- peek rboIdPtr+    glBindRenderbuffer gl_RENDERBUFFER rboId+    glRenderbufferStorage gl_RENDERBUFFER gl_DEPTH_COMPONENT w h+    glBindRenderbuffer gl_RENDERBUFFER 0+    -- Attach the renderbuffer to the FBO depth attachment point+    glFramebufferRenderbuffer gl_FRAMEBUFFER gl_DEPTH_ATTACHMENT gl_RENDERBUFFER rboId+    --}++    -- Create a texture object and bind it    NEED: to abstract out the color (RGBA)+    texIdPtr <- malloc :: IO(Ptr GLuint)+    glGenTextures 1 texIdPtr+    texId <- peek texIdPtr+    glBindTexture gl_TEXTURE_2D texId  +      +    --Set up the texture object and its parameters+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+    --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE +    glTexImage2D gl_TEXTURE_2D 0 (fromIntegral gl_RGBA8) w h 0 gl_RGBA gl_UNSIGNED_BYTE nullPtr+    +    -- Unbind this texture so it isn't the one currently being used+    glBindTexture gl_TEXTURE_2D 0+    -- Attach the texture to a FBO color attachment point+    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texId 0+    +    return (fboIdPtr, texIdPtr)+++++++-- We need to come up with a better name for this function+-- Now, it only works *if* you already have a set of instructions to read.+changeBoard' :: CBM () -> [Inst BufferId] -> CBM ()+changeBoard' next changes = do+--    print "changeBoard"+    {-+    when (not (null changes)) $ do+       print changes+    --}+    --Draw all new instructions (into the textures with ptrs stored in the map)+    --tm <- liftIO $ getCurrentTime+    drawInsts changes+    --tm' <- liftIO $ getCurrentTime+    {-+    liftIO $ when (not (null changes)) $ do+        print (diffUTCTime tm' tm)+    --}+    +    debug <- getDebugFrames+    curBoard <- getCurrentBoard+    env <- getCBMEnv+    +    liftIO $ do+        temp <- get errors+        when (not (null temp)) $ +    	    print ("ERRORS",temp)+    +        when (debug && (not (null changes))) $ do+            imgUnique <- newUnique+            imgNum <- return $ hashUnique imgUnique+            appendFile "./debug.html" $ "<br><pre>" ++ showCBIRs changes ++ "</pre>\n"+            appendFile "./debug.html" $ "<br>\n<img src=\"debug-" ++ show imgNum ++ ".png\"/>\n<br>\n<br>\n<br>\n<hr>\n<br>\n<br>\n"+            alreadyExists <- doesFileExist $ "./debug-" ++ show imgNum ++ ".png"+            when (alreadyExists) $ removeFile ("./debug-" ++ show imgNum ++ ".png")+            runCBM (saveImage curBoard ("./debug-" ++ show imgNum ++ ".png")) env+    +        addTimerCallback 20 $ runCBM next env+        displayCallback $= runCBM (drawBoard) env+        postRedisplay Nothing++++-- Function to see if there were any new instructions passed in and if so to call the changeboard' function+--   * insts - An MVar possibly containing a list of CBIR instructions to make changes to the boards+changeBoard :: MVar ([Inst BufferId]) -> CBM ()+changeBoard insts = do+--    print "changeBoard"++    maybeInsts <- liftIO $ do +                        mbInsts <- tryTakeMVar insts+                        return mbInsts+        +    let changes = fromMaybe [] maybeInsts++    changeBoard' (changeBoard insts) changes+++++++-- Display callback function to make sure the right framebuffer is bound and display the final display board.+drawBoard :: CBM ()+drawBoard = do+--    liftIO $ print "drawBoard"+ +    -- First, see if we are using a FBO or not+    fboSupp <- getFBOSupport++    if fboSupp+        then do+            -- If using a FBO, get the ptr so we can reset it after displaying+            fboIdPtr <- getFBOPtr+            liftIO $ do+                -- Reset the framebuffer to the actual window+                glBindFramebuffer gl_FRAMEBUFFER 0+            -- Draw the final board+            displayBoard+            liftIO $ do+                -- Change the framebuffer back so that we can start drawing boards again+                flush+                swapBuffers+                fboId <- peek fboIdPtr+                glBindFramebuffer gl_FRAMEBUFFER fboId+        else do+            displayBoard+            liftIO $ do    +                flush+                swapBuffers+++++-- Function to display the current output board of a chalkboard image. Done once per frame.+displayBoard :: CBM ()+displayBoard = do+    texMap <- getTexMap+    b <- getCurrentBoard+    +    liftIO $ do+            -- Check to make sure the display board exists+            when (notMember b texMap) $ do+                    print "Error: The board to display doesn't exist."+                    exitWith (ExitFailure 1)+            +            -- Get some info about the current output board+            let (Just texInfo) = lookup b texMap+                texIdPtr = texPtr texInfo+                (w',h') = texSize texInfo+                (w,h) = (fromIntegral w', fromIntegral h')+            +            texId <- peek texIdPtr+            +            --{- Turn this off to center the image instead of snapping the window to its size+            Size winW winH <- get windowSize+            when (winW /= fromIntegral w || winH /= fromIntegral h) $+                if (w < 200)+                    then do +                        windowSize $= (Size 200 h)+                        resizeScene (Size 200 h)+                    else do+                        windowSize $= (Size w h)+                        resizeScene (Size w h)+            --}+            +            -- Calculations to center the image in the window+            Size winW2 winH2 <- get windowSize -- Get the size of the window    +            let minW = ((fromIntegral (fromIntegral winW2 -  w)) :: GLfloat) / 2.0+                minH = ((fromIntegral (fromIntegral winH2 - h)) :: GLfloat) / 2.0+                maxW = (fromIntegral winW2 - minW) +                maxH = (fromIntegral winH2 - minH) +            +            -- Bind the texture so that we can display it+            glBindTexture gl_TEXTURE_2D texId+            +            clear [ColorBuffer, DepthBuffer] -- clear the screen and the depth buffer+            loadIdentity -- reset view+            color (Color4 1 1 1 (1::GL.GLfloat))+            -- Display the final board, making sure that it is drawn in the upper left corner of the window (for now)+            renderPrimitive Quads $ do+                texCoord (TexCoord2 0 (1::GL.GLfloat)) -- Top Left+                vertex (Vertex3 minW maxH 0)+                texCoord (TexCoord2 0 (0::GL.GLfloat)) -- Bottom Left+                vertex (Vertex3 minW minH 0) -- Used to be GL.GLsizei+                texCoord (TexCoord2 1 (0::GL.GLfloat)) -- Bottom Right+                vertex (Vertex3 maxW minH 0)+                texCoord (TexCoord2 1 (1::GL.GLfloat)) -- Top Right+                vertex (Vertex3 maxW maxH 0) +            +            -- Unbind the texture in case we need to keep writing to it later+            glBindTexture gl_TEXTURE_2D 0+++++++++-- Function to loop (recurse) through CBIR instructions and apply all of their effects to change or create boards+--   * (i:is)  - The list of CBIR instructions that are left to execute+drawInsts :: [Inst BufferId] -> CBM ()+drawInsts [] = return ()+drawInsts (i:is) = do +    case i of+            (Allocate b size depth (BackgroundArr arr)) -> allocateArrBuffer b size depth arr+            (Allocate b size depth bgColor) -> allocateBuffer b size depth bgColor+            (AllocateImage b imagePath ) -> allocateImgBuffer b imagePath+            (SplatTriangle bSource bDest ptMap1 ptMap2 ptMap3) -> splatPolygon bSource bDest [ptMap1, ptMap2, ptMap3]+            (SplatPolygon bSource bDest ptMaps) -> splatPolygon bSource bDest ptMaps+            (SplatColor sColor bDest useBlend ptList) -> splatColor sColor bDest useBlend ptList+            (SplatBuffer bSource bDest) -> splatPolygon bSource bDest [ PointMap p p | p <- [(0,0),(0,1),(1,1),(1,0)] ]+            (CopyBuffer alpha bSource bDest) -> copyBuffer alpha bSource bDest+            (SaveImage b savePath) -> saveImage b savePath+            (Delete b) -> deleteBuffer b+            (Nested _ insts') -> drawInsts insts'+            (CBIR.Exit)  -> liftIO $ exitWith ExitSuccess +    drawInsts is+++++++++-- Function to allocate a new board/buffer object+--   * board - The buffer (board) object name+--   * (w,h) - The width and height of the new buffer being created+--   * d - The color depth of the buffer being created+--   * c - The initial color of the buffer that is being created+allocateBuffer :: BufferId -> (Int,Int) -> Depth -> Background -> CBM ()+allocateBuffer board (w,h) d c = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap+    +    texInfo' <- liftIO $ do+            -- Choose the internal format to use for this buffer based on the depth specified+            let colorType = case d of+                    BitDepth -> (fromIntegral gl_LUMINANCE)   -- 8 bit per pixel (still grey, not just black and white)+                    G8BitDepth -> (fromIntegral gl_LUMINANCE) -- 8 bits per pixel (grey)+                    RGB24Depth -> (fromIntegral gl_RGB) -- (R,G,B), 8 bits per pixel+                    RGBADepth -> (fromIntegral gl_RGBA) -- (R,G,B,A), 8 bits per pixel+            +            -- Choose the initial background color of the buffer based on the background specified+            let bgcolor = case c of +                    (BackgroundBit on) -> if on then (Color4 0 0 0 1) else (Color4 1 1 1 1) +                    (BackgroundG8Bit grey) -> (Color4 (floatToGLclampf grey) (floatToGLclampf grey) (floatToGLclampf grey) 1)+                    (BackgroundRGB24Depth (T.RGB r g b)) -> (Color4 (floatToGLclampf r) (floatToGLclampf g) (floatToGLclampf b) 1)+                    (BackgroundRGBADepth (T.RGBA r g b a)) -> (Color4 (floatToGLclampf r) (floatToGLclampf g) (floatToGLclampf b) (floatToGLclampf a))+            +            -- Create a texture object and bind it+            texIdPtr <- malloc :: IO(Ptr GLuint)+            glGenTextures 1 texIdPtr+            texId <- peek texIdPtr+            glBindTexture gl_TEXTURE_2D texId+               +            --Set up the texture object and its parameters+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+            --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR --Can maybe check into this now that generation is only done once+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE+            +            let texInfo = TextureInfo texIdPtr (fromIntegral w, fromIntegral h) colorType+            +            when (fboSupp) $ do+                -- Set up the texture so that it's image can be stored when drawing to the framebuffer+                -- colorType for both?+                glTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) (fromIntegral w) (fromIntegral h) 0 (fromIntegral colorType) gl_UNSIGNED_BYTE nullPtr +                -- Attach the texture to a FBO color attachment point+                glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texId 0+            +            preservingAttrib [ColorBufferAttributes] $ do --Temporarily change the clear color to make the buffer+                clearColor $= bgcolor -- Change the clearColor to the color of the board being created+                clear [ColorBuffer] -- Clear the screen to the new color to draw that color onto the board+                flush+                +            when (not fboSupp) $ do    +                -- Copy the texture from the framebuffer+                glCopyTexImage2D gl_TEXTURE_2D 0 colorType 0 0 (fromIntegral w) (fromIntegral h) 0+            +            -- Unbind Texture until it is needed (may want to take this out depending on how we order instructions coming in)+            glBindTexture gl_TEXTURE_2D 0+            return texInfo+    +    -- FBO is NOT unbound, nor is the texture image detached from the FBO+    setTexMap (insert board texInfo' texMap)+++++{- I've cut and pasted this from allocateImgBuffer -}+-- TODO: merge with function allocateArrBuffer, because allocateRawImgBuffer is only called in one place+allocateRawImgBuffer :: BufferId -> (Int,Int) -> Depth -> Ptr CUChar -> CBM ()+allocateRawImgBuffer board (w,h) depth imagePtr = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap+    +    texInfo' <- liftIO $ do+            -- Just set the colorType to RGBA for now, this should maybe change so that they can use any format of image data +            let colorType = case depth of+                    BitDepth -> (fromIntegral gl_LUMINANCE)   -- 8 bit per pixel (still grey, not just black and white)+                    G8BitDepth -> (fromIntegral gl_LUMINANCE) -- 8 bits per pixel (grey)+                    RGB24Depth -> (fromIntegral gl_RGB) -- (R,G,B), 8 bits per pixel+                    RGBADepth -> (fromIntegral gl_RGBA) -- (R,G,B,A), 8 bits per pixel++            -- Create a texture object and bind it+            texIdPtr <- malloc :: IO(Ptr GLuint)+            glGenTextures 1 texIdPtr+            texId <- peek texIdPtr+            glBindTexture gl_TEXTURE_2D texId+            +            --Set up the texture object and its parameters+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+            --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR --Can maybe check into this now that generation is only done once+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE+            +            glTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) (fromIntegral w) (fromIntegral h) 0 (fromIntegral colorType) gl_UNSIGNED_BYTE (castPtr imagePtr)+            +            let texInfo = TextureInfo texIdPtr (fromIntegral w, fromIntegral h) colorType++            -- Unbind this texture so it isn't the one currently being used+            glBindTexture gl_TEXTURE_2D 0+            +            -- Done to mirror the other allocates (leaving the texture attached to the fbo), but should maybe just get rid of this:+            when (fboSupp) $ do+                    -- Attach the texture to a FBO color attachment point+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texId 0+            +            return texInfo++    -- FBO is NOT unbound, nor is the texture image detached from the FBO+    setTexMap (insert board texInfo' texMap)+++++allocateArrBuffer :: BufferId -> (Int,Int) -> Depth -> IStorableArray (Int,Int,Int) -> CBM ()+allocateArrBuffer board (w,h) depth imageArr = do+        env <- getCBMEnv+	liftIO $ IS.withIStorableArray imageArr $ \p -> do+	        runCBM (allocateRawImgBuffer board (w,h) depth (castPtr p)) env+++++-- Function to allocate a new board/buffer object using a pre-existing image+--   * board - The buffer (board) object name+--   * imagePath - The path to the image file being loading into this new buffer+allocateImgBuffer :: BufferId -> FilePath -> CBM ()+allocateImgBuffer board imagePath = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap+    +    texInfo' <- liftIO $ do+            -- Just set the colorType to RGBA for now+            let colorType = gl_RGBA++            -- Create a texture object and bind it+            texIdPtr <- malloc :: IO(Ptr GLuint)+            glGenTextures 1 texIdPtr+            texId <- peek texIdPtr+            glBindTexture gl_TEXTURE_2D texId+            +            --Set up the texture object and its parameters+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+            --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR --Can maybe check into this now that generation is only done once+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE+            +            -- Read in the image to an array from the filepath that was given using devIL+            arr <- readImage imagePath+            +            --tm2 <- getCurrentTime+            -- Get the array data and give that to an openGL texture+            let ((0,0,0), (h,w,3)) = U.bounds arr+            arrT <- unsafeThaw arr+            --tm2' <- getCurrentTime+            --print (diffUTCTime tm2' tm2)++            withStorableArray arrT $ \ptr -> do+                -- Might have to just do RGBA instead of colorType!!!+                glTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) (fromIntegral w+1) (fromIntegral h+1) 0 (fromIntegral colorType) gl_UNSIGNED_BYTE (castPtr ptr)+            +            let texInfo = TextureInfo texIdPtr (fromIntegral w+1, fromIntegral h+1) colorType+            +            -- Unbind this texture so it isn't the one currently being used+            glBindTexture gl_TEXTURE_2D 0+            +            -- Done to mirror the other allocates (leaving the texture attached to the fbo), but should maybe just get rid of this:+            when (fboSupp) $ do+                    -- Attach the texture to a FBO color attachment point+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texId 0+            +            return texInfo++    -- FBO is NOT unbound, nor is the texture image detached from the FBO+    setTexMap (insert board texInfo' texMap)+++++++++-- Function to splat a polygon from one source buffer to one destination buffer+--   * bS - The source buffer (board) object name+--   * bD - The destination buffer (board) object name+--   * ps - A list of PointMaps, which specify a pairing of points: one on the source buffer that correspond one on the destination buffer+splatPolygon :: BufferId -> BufferId -> [PointMap] -> CBM ()+splatPolygon bS bD ps = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap++    liftIO $ do+            -- Check to make sure both the source and destination boards exist+            when (notMember bD texMap) $ do+                    print "Error: The destination board to splat to doesn't exist."+                    exitWith (ExitFailure 1)+            when (notMember bS texMap) $ do+                    print "Error: The source board to splat doesn't exist."+                    exitWith (ExitFailure 1)+            +            -- Look up all of the values that will be needed+            let (Just texInfoD) = lookup bD texMap+                (Just texInfoS) = lookup bS texMap+                texIdPtrD = texPtr texInfoD+                texIdPtrS' = texPtr texInfoS+                (w,h) = texSize texInfoD+                colorType = texFormat texInfoD+            +            texIdD <- peek texIdPtrD+            texIdS' <- peek texIdPtrS'+            +            if (not fboSupp)+                then do+                    clear [DepthBuffer] -- clear the depth buffer+                    loadIdentity+                    --Bind the destination texture to use first+                    glBindTexture gl_TEXTURE_2D texIdD+                    -- Turn off blending so the destination board isn't blended with the background color+                    blend $= Disabled+                    -- Render the destination board so we can draw onto it+                    renderPrimitive Quads $ do+                        texCoord (TexCoord2 0 (0::GL.GLfloat)) -- Bottom Left+                        vertex (Vertex3 0 0 (0::GL.GLfloat)) -- Used to be GLUT.GLsizei, does it matter?+                        texCoord (TexCoord2 1 (0::GL.GLfloat)) -- Bottom Right+                        vertex (Vertex3 (fromIntegral w) 0 (0::GL.GLfloat))+                        texCoord (TexCoord2 1 (1::GL.GLfloat)) -- Top Right+                        vertex (Vertex3 (fromIntegral w) (fromIntegral h) (0::GL.GLfloat))+                        texCoord (TexCoord2 0 (1::GL.GLfloat)) -- Top Left+                        vertex (Vertex3 0 (fromIntegral h) (0::GL.GLfloat))+                    -- Turn blending back on so that the source board can be blended with the destination board+                    blend $= Enabled+                    +                    -- Bind the source texture that will be splatted on    +                    glBindTexture gl_TEXTURE_2D texIdS'+                    --Uses relative positions (percentages) of source and destination boards+                    renderPrimitive Polygon $+                        placeVerticies w h ps++                    -- Bind the destination texture so we can copy the new image out to it+                    glBindTexture gl_TEXTURE_2D texIdD+                    -- Copy the texture from the framebuffer (make more efficient by only copying the changed subimage?)+                    glCopyTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) 0 0 (fromIntegral w) (fromIntegral h) 0 +                    +                else do+                    -- Attach the texture to a FBO color attachment point+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texIdD 0+                    -- Check to see if the texture is trying to recursively draw onto itself, and if so create a copy of the source texture+                    -- to prevent the undefined feedback loop that would result from drawing straight to the same texture that is being read+                    (texIdS, texIdPtrS) <- if (texIdD == texIdS')+                                               then fixTexLoopback texInfoS --Could call after binding texIdS' to avoid an extra binding or two maybe?+                                               else return (texIdS', texIdPtrS')+            +                    -- Bind the source texture that will be splatted on    +                    glBindTexture gl_TEXTURE_2D texIdS+                    --Uses relative positions (percentages) of source and destination boards+                    renderPrimitive Polygon $+                        placeVerticies w h ps  ++                    -- If a new source texture was created to prevent a feedback loop, then delete it+                    when (texIdS /= texIdS') $ do+                            glDeleteTextures 1 texIdPtrS++            -- Unbind Texture until it is needed (may want to take this out depending on how we order instructions coming in)+            glBindTexture gl_TEXTURE_2D 0+++++++-- Function to place all of the tex coords and verticies of a polygon splat from a list of PointMaps.+--   * w  - The width of the destination board.+--   * h  - The height of the destination board.+--   * ps - The list of PointMaps from the source board onto the destination board.+placeVerticies :: GLint -> GLint -> [PointMap] -> IO () -- Could maybe just make the first two as type 'a', which would be an integral+placeVerticies _ _ [] = return ()+placeVerticies w h (p:ps) = do+    let (PointMap (sx,sy) (dx,dy)) = p+    +    texCoord (TexCoord2 (floatToGLfloat sx) ((floatToGLfloat sy)::GL.GLfloat))+    vertex (Vertex3 (fromIntegral w * floatToGLfloat dx) (fromIntegral h * floatToGLfloat dy) (1::GL.GLfloat))+    +    placeVerticies w h ps+++-- Function to place all of the verticies of a color splat from a list of PointMaps.+--   * w  - The width of the destination board.+--   * h  - The height of the destination board.+--   * ps - The list of UIPoints to splat a color shape onto the destination board.+placeColorVerticies :: GLint -> GLint -> [UIPoint] -> IO () -- Could maybe just make the first two as type 'a', which would be an integral+placeColorVerticies _ _ [] = return ()+placeColorVerticies w h (p:ps) = do+    let (dx,dy) = p+    +    vertex (Vertex3 (fromIntegral w  * floatToGLfloat dx) (fromIntegral h * floatToGLfloat dy) (1::GL.GLfloat))+    +    placeColorVerticies w h ps++++-- Function to create a new source texture when a board recursively draws onto itself using a FBO+-- This prevents a feedback loop with undefined behavior that would draw and read from the same texture at the same time+--   * texInfoS - the texture information for the texture that is supposed to be drawn onto itself+--   returns - the new texture id of the copied texture and the pointer to this new texture (used to delete it)+fixTexLoopback :: TextureInfo -> IO ( (GLuint, Ptr GLuint) )+fixTexLoopback texInfoS = do+    let (w,h) = texSize texInfoS+        colorType = texFormat texInfoS+    +    -- Create and bind a new texture object to use as the source texture for splating+    texIdPtr <- malloc :: IO(Ptr GLuint)+    glGenTextures 1 texIdPtr+    texId <- peek texIdPtr+    glBindTexture gl_TEXTURE_2D texId+    +    --Set up the texture object and its parameters+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+    --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+    glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE++    -- Copy the texture from the current FBO+    glCopyTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) 0 0 (fromIntegral w) (fromIntegral h) 0+    -- Unbind the new texture+    glBindTexture gl_TEXTURE_2D 0+    +    return (texId, texIdPtr)+++++++-- Function to splat a color polygon onto one destination buffer+--   * (r,g,b,a) - The color to splat onto the destination board+--   * bD - The destination buffer (board) object name+--   * ps - A list of UIPoints, which specify the points of the colored polygon to draw onto the destination buffer+splatColor :: RGBA -> BufferId -> Bool -> [UIPoint] -> CBM ()+splatColor (T.RGBA r g b a) bD _useBlend ps = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap++    liftIO $ do+            -- Check to make sure the destination board exists+            when (notMember bD texMap) $ do+                    print "Error: The destination board to splat to doesn't exist."+                    exitWith (ExitFailure 1)+            +            -- Look up all of the values that will be needed+            let (Just texInfoD) = lookup bD texMap+                texIdPtrD = texPtr texInfoD+                (w,h) = texSize texInfoD+                colorType = texFormat texInfoD+                +            texIdD <- peek texIdPtrD++            if (not fboSupp)+                then do+                    clear [DepthBuffer] -- clear the depth buffer+                    loadIdentity+                    --Bind the destination texture to use first+                    glBindTexture gl_TEXTURE_2D texIdD+                    -- Turn off blending so the destination board isn't blended with the background color+                    blend $= Disabled+                    -- Render the destination board so we can draw onto it+                    renderPrimitive Quads $ do+                        texCoord (TexCoord2 0 (0::GL.GLfloat)) -- Bottom Left+                        vertex (Vertex3 0 0 (0::GL.GLfloat)) -- Used to be GL.GLsizei, does it matter?+                        texCoord (TexCoord2 1 (0::GL.GLfloat)) -- Bottom Right+                        vertex (Vertex3 (fromIntegral w) 0 (0::GL.GLfloat))+                        texCoord (TexCoord2 1 (1::GL.GLfloat)) -- Top Right+                        vertex (Vertex3 (fromIntegral w) (fromIntegral h) (0::GL.GLfloat))+                        texCoord (TexCoord2 0 (1::GL.GLfloat)) -- Top Left+                        vertex (Vertex3 0 (fromIntegral h) (0::GL.GLfloat))+                    -- Turn blending back on so that the source board can be blended with the destination board+                    blend $= Enabled+                    -- Unbind the texture to prevent mapping - doesn't work if this is removed.+                    glBindTexture gl_TEXTURE_2D 0+                else do+                    -- Attach the texture to a FBO color attachment point+                    -- AJG: This is also taking a lot of time, presumbily because it stalls the pipeline.+                    -- We can store what we've alread done, and not redo this for each target.+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texIdD 0+            +            -- Switch the color to the one we are trying to splat+            color (Color4 (floatToGLclampf r) (floatToGLclampf g) (floatToGLclampf b) ((floatToGLclampf a)::GLclampf))+            -- Uses relative positions (percentages) of source and destination boards+            -- most of the time is attributed to *renderPrimitive* (glBegin?)+{-+            if useBlend then+                 blendFuncSeparate $= ((SrcAlpha, OneMinusSrcAlpha), (One, OneMinusSrcAlpha)) -- Specify color and alpha blend separately+              else+                 blendFuncSeparate $= ((SrcAlpha, Zero), (SrcAlpha, Zero)) -- Specify color and alpha blend separately+-}	+            renderPrimitive Polygon $ do+                placeColorVerticies w h ps+            +            when (not fboSupp) $ do+                -- Bind the destination texture so we can copy the new image out to it+                glBindTexture gl_TEXTURE_2D texIdD+                -- Copy the texture from the framebuffer+                glCopyTexImage2D gl_TEXTURE_2D 0 (fromIntegral colorType) 0 0 (fromIntegral w) (fromIntegral h) 0 --make more efficient by only copying the changed subimage?+                -- Unbind Texture until it is needed (may want to take this out depending on how we order instructions coming in)+                glBindTexture gl_TEXTURE_2D 0+++++++-- Function to copy the image from one buffer into another buffer (using either its original alpha or the destination buffer's alpha)+--   * alpha - WithSrcAlpha to do a normal copy, keeping its own alpha values. WithDestAlpha to use the destination buffer's alpha values+--   * bS - The source buffer id+--   * bD - The destination buffer id+copyBuffer :: WithAlpha -> BufferId -> BufferId -> CBM ()+copyBuffer alpha bS bD = do+    case alpha of+            WithSrcAlpha -> do+                    liftIO $ blendFuncSeparate $= ((One, Zero), (One, Zero))+                    splatPolygon bS bD [ PointMap p p | p <- [(0,0),(0,1),(1,1),(1,0)] ]+                    liftIO $ blendFuncSeparate $= ((SrcAlpha, OneMinusSrcAlpha), (One, OneMinusSrcAlpha))+            WithDestAlpha -> do+                    liftIO $ blendFuncSeparate $= ((One, Zero), (Zero, One))+                    splatPolygon bS bD [ PointMap p p | p <- [(0,0),(0,1),(1,1),(1,0)] ]+                    liftIO $ blendFuncSeparate $= ((SrcAlpha, OneMinusSrcAlpha), (One, OneMinusSrcAlpha))+++++++-- Function to save an image out to a file from a specified board/buffer+--   * b        - The name of the buffer (board) object that will be saved out to a file+--   * savePath - The file path to the location where the image should be saved (including the image filename and extension)+-- This could maybe save a lot of code by just calling splatPolygon, but there may be complications.+saveImage :: BufferId -> FilePath -> CBM ()+saveImage b savePath = do+    fboSupp <- getFBOSupport+    texMap <- getTexMap+    +    liftIO $ do+            -- Check to make sure the board being saved exists+            when (notMember b texMap) $ do+                    print "Error: The board to be saved doesn't exist."+                    exitWith (ExitFailure 1)+            +            -- Check if an image with the same name already exists. If it does, delete it.+            alreadyExists <- doesFileExist $ savePath+            when (alreadyExists) $ removeFile savePath+            +            -- Look up the board we need to save+            let (Just texInfo) = lookup b texMap+                texIdPtr = texPtr texInfo+                (w,h) = texSize texInfo+            +            texId <- peek texIdPtr++            -- Create and bind a new texture object to use as the RGBA texture for outputting+            texIdPtr2 <- malloc :: IO(Ptr GLuint)+            glGenTextures 1 texIdPtr2+            texId2 <- peek texIdPtr2+            glBindTexture gl_TEXTURE_2D texId2+            +            --Set up the texture object and its parameters+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MAG_FILTER $ fromIntegral gl_LINEAR+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR+            --glTexParameteri gl_TEXTURE_2D gl_TEXTURE_MIN_FILTER $ fromIntegral gl_LINEAR_MIPMAP_LINEAR+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_S $ fromIntegral gl_CLAMP_TO_EDGE+            glTexParameteri gl_TEXTURE_2D gl_TEXTURE_WRAP_T $ fromIntegral gl_CLAMP_TO_EDGE+            +            when (fboSupp) $ do+                    -- Create the new texture object so that we can draw directly into it+                    glTexImage2D gl_TEXTURE_2D 0 (fromIntegral gl_RGBA) (fromIntegral w) (fromIntegral h) 0 gl_RGBA gl_UNSIGNED_BYTE nullPtr+                    -- Attach the new texture to a FBO color attachment point+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D texId2 0+                    +            -- Bind the original (non-RGBA) texture so that it can be copied into the new one+            glBindTexture gl_TEXTURE_2D texId+            +            clear [ColorBuffer, DepthBuffer] -- clear the screen and the depth buffer+            loadIdentity -- reset view+            +            color (Color4 1 1 1 (1::GL.GLfloat))+            -- Render the final board we want to save to file+            renderPrimitive Quads $ do+                texCoord (TexCoord2 0 (0::GL.GLfloat)) -- Bottom Left+                vertex (Vertex3 0 0 (0::GL.GLfloat)) -- Used to be GL.GLsizei, does it matter?+                texCoord (TexCoord2 1 (0::GL.GLfloat)) -- Bottom Right+                vertex (Vertex3 (fromIntegral w) 0 (0::GL.GLfloat))+                texCoord (TexCoord2 1 (1::GL.GLfloat)) -- Top Right+                vertex (Vertex3 (fromIntegral w) (fromIntegral h) (0::GL.GLfloat))+                texCoord (TexCoord2 0 (1::GL.GLfloat)) -- Top Left+                vertex (Vertex3 0 (fromIntegral h) (0::GL.GLfloat))+            +            -- Bind the new texture again so that it can be saved+            glBindTexture gl_TEXTURE_2D texId2+            +            if (fboSupp)+                then do+                    -- Unattach the new texture from the FBO color attachment point since it will be deleted+                    glFramebufferTexture2D gl_FRAMEBUFFER gl_COLOR_ATTACHMENT0 gl_TEXTURE_2D 0 0+                else do+                    -- Copy the texture from the screen to the new texture for saving+                    glCopyTexImage2D gl_TEXTURE_2D 0 (fromIntegral gl_RGBA) 0 0 (fromIntegral w) (fromIntegral h) 0   +++            -- Create a new array with the image data so that we can write it out with devIL+            let arrBounds = ((0,0,0), (fromIntegral h-1, fromIntegral w-1, 3))+            arr <- (newArray_ arrBounds) :: IO (StorableArray (Int,Int,Int) Word8)+            +            -- Have OpenGL fill the array with the texture data and then write out that data to an image file using DevIL+            withStorableArray arr $ \ptr2 -> do+                glGetTexImage gl_TEXTURE_2D 0 gl_RGBA gl_UNSIGNED_BYTE (castPtr ptr2)+                writeImageFromPtr savePath (fromIntegral h, fromIntegral w) (castPtr ptr2)+            +            -- Unbind this texture so it isn't the one being used anymore+            glBindTexture gl_TEXTURE_2D 0+            +            -- Delete the texture since it won't be needed anymore+            glDeleteTextures 1 texIdPtr2+            free texIdPtr2+++++++-- Function to delete a specified board/buffer from memory+--   * b - The name of the buffer (board) object to be deleted+deleteBuffer :: BufferId -> CBM ()+deleteBuffer b = do+    texMap <- getTexMap+    +    liftIO $ do+            -- Check to make sure the board being deleted exists+            when (notMember b texMap) $ do+                    print "Error: The board to be saved doesn't exist."+                    exitWith (ExitFailure 1)+            +            -- Look up the board we need to delete+            let (Just texInfo) = lookup b texMap+                texIdPtr = texPtr texInfo+            +            -- Delete the texture+            glDeleteTextures 1 texIdPtr+            free texIdPtr+    +    -- This deletes the mapping+    setTexMap (delete b texMap)+++++++++++floatToGLfloat :: Float -> GL.GLfloat+floatToGLfloat = realToFrac++floatToGLclampf :: Float -> GL.GLclampf+floatToGLclampf = realToFrac+ +++++++++{-+    -- Draw a circle (or an ellipse by scaling the circle)+    -- Parameters would be xPos, yPos, rotationDegree, xScale, yScale, Color4(RGBA), radius, slices (# of points used to draw it)+    translate (Vector3 100 100 (0::GL.GLfloat)) -- Move it around to center on right position+    rotate 15 (Vector3 0 0 (-1::GL.GLfloat)) -- Rotate about -z axis so that positive degrees are clockwise+    scale 1 0.5 (1::GL.GLfloat) -- Scale the circle if it should be more of an ellipse+    color (Color4 1 0 0 (0.3::GL.GLfloat)) -- Change the color (and alpha)+    renderQuadric (QuadricStyle (Just Smooth) NoTextureCoordinates Inside FillStyle) (Disk 0 100 100 1) --inner radius, outer radius, slices, loops+--}+++++++
+ Graphics/ChalkBoard/OpenGL/Monad.hs view
@@ -0,0 +1,135 @@+-- ChalkBoard Monad+-- October 2009+-- Kevin Matlage, Andy Gill+++module Graphics.ChalkBoard.OpenGL.Monad where++import Graphics.ChalkBoard.CBIR( BufferId )+import Graphics.Rendering.OpenGL.Raw.Core31 as GL ( GLint, GLuint, GLenum )+import Foreign.Ptr ( Ptr )+import Data.Map ( Map )+import Control.Concurrent.MVar ( MVar, takeMVar, putMVar )++++++data CBM a = CBM { runCBM :: CBenv -> IO a }+++instance Monad CBM where+    return n = CBM $ \_ -> return n+    m >>= k = CBM $ \env -> do+        a <- runCBM m env+        a' <- runCBM (k a) env+        return a'+    fail msg = CBM $ \_ -> fail msg+++data CBenv = CBenv+        { debugFrames :: Bool+        , debugAll :: Bool+        , debugBoards :: [BufferId]+        , fboSupport :: Bool+        , envForStateVar :: MVar CBstate+        }++data CBstate = CBstate+        { currentBoard :: BufferId+        , textureInfo  :: Map BufferId TextureInfo+        , fboPtr       :: Ptr GL.GLuint+        }+++data TextureInfo = TextureInfo+	{ texPtr    :: Ptr GL.GLuint+	, texSize   :: (GL.GLint,GL.GLint)+	, texFormat :: GL.GLenum+	}+++++++getCBMEnv :: CBM CBenv+getCBMEnv = CBM $ \env -> return env+++getDebugFrames :: CBM (Bool)+getDebugFrames = CBM $ \env -> return (debugFrames env)++getDebugAll :: CBM (Bool)+getDebugAll = CBM $ \env -> return (debugAll env)++getDebugBoards :: CBM ([BufferId])+getDebugBoards = CBM $ \env -> return (debugBoards env)++getFBOSupport :: CBM (Bool)+getFBOSupport = CBM $ \env -> return (fboSupport env)+++++++setCBMState :: CBstate -> CBM ()+setCBMState state = CBM $ \env -> do+        _ <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) state++getCBMState :: CBM CBstate+getCBMState = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) st+        return (st)+++++setTexMap :: Map BufferId TextureInfo -> CBM ()+setTexMap texMap = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) (st {textureInfo = texMap})++getTexMap :: CBM (Map BufferId TextureInfo)+getTexMap = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) st+        return (textureInfo st)+++setCurrentBoard :: BufferId -> CBM ()+setCurrentBoard board = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) (st {currentBoard = board})++getCurrentBoard :: CBM BufferId+getCurrentBoard = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) st+        return (currentBoard st)+++setFBOPtr :: Ptr GL.GLuint -> CBM ()+setFBOPtr ptr = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) (st {fboPtr = ptr})++getFBOPtr :: CBM (Ptr GL.GLuint)+getFBOPtr = CBM $ \env -> do+        st <- takeMVar (envForStateVar env)+        putMVar (envForStateVar env) st+        return (fboPtr st)++++++liftIO :: IO a -> CBM a+liftIO m = CBM $ \_ -> do+        a <- m+        return a++
+ Graphics/ChalkBoard/Options.hs view
@@ -0,0 +1,33 @@+-- ChalkBoard Options+-- October 2009+-- Kevin Matlage, Andy Gill+++module Graphics.ChalkBoard.Options where++import Graphics.ChalkBoard.CBIR( BufferId )+import Data.Binary+import Control.Monad+++data Options = NoFBO+             | DebugFrames+             | DebugAll				-- ^ not supported (yet!)+             | DebugBoards [BufferId]		-- ^ not supported (yet!)+	     | BoardSize Int Int		-- ^ default is 400x400.+	     | FullScreen			-- ^ not supported (yet!)+        deriving (Eq, Show)++instance Binary Options where+  put (NoFBO) 	 		 = put (0 :: Word8)+  put (DebugFrames) 	 	 = put (1 :: Word8)+  put (DebugBoards buffs)        = put (2 :: Word8) >> put buffs+  put (BoardSize w h) 		 = put (3 :: Word8) >> put w >> put h+  put (FullScreen) 		 = put (4 :: Word8)+  get = do tag <- getWord8+           case tag of+                  0 -> return $ NoFBO +                  1 -> return $ DebugFrames+                  2 -> liftM DebugBoards get+		  3 -> liftM2 BoardSize get get+		  4 -> return $ FullScreen
+ Graphics/ChalkBoard/Shapes.hs view
@@ -0,0 +1,98 @@+-- |+-- Module: Graphics.ChalkBoard.Shapes+-- Copyright: (c) 2009 Andy Gill+-- License: BSD3+--+-- Maintainer: Andy Gill <andygill@ku.edu>+-- Stability: unstable+-- Portability: ghc+--+-- This module contains some basic shape generators, expressed as @Board Bool@.+--++module Graphics.ChalkBoard.Shapes where++import Graphics.ChalkBoard.Board+import Graphics.ChalkBoard.Types+import Graphics.ChalkBoard.O+import Graphics.ChalkBoard.Utils++-- import Control.Applicative++{-+-- | unit circle, radius 0.5, over origin.+circle :: Board Bool+circle =  Cond (InsideCircle (0,0) 0.5 1 0) (Pure True) (Pure False)+circle' = (\ (x,y) -> x*x + y*y <= 0.5 * 0.5) <$> coord++-- | unit vertical bar,  1 wide over origin.+vbar :: Board Bool+vbar =  (\ (_x,y) -> y <= 0.5 && y >= -0.5) <$> coord++-- | unit horizontal bar, 1 high over origin.+hbar :: Board Bool+hbar =  (\ (x,_y) -> x <= 0.5 && x >= -0.5) <$> coord++-- | unit square, 1x1 over origin.+square	 = Cond (InsideBox (-0.5,-0.5) 1 1 0) (Pure True) (Pure False)+square' = liftA2 (&&) vbar hbar+-}++{-+--squareO :: Board (O Bool)+-- squareO = Polygon [(-0.5,-0.5),(-0.5,0.5),(0.5,0.5),(0.5,-0.5)]++-- | cheacker board, with squares 1x1.+checker :: Board Bool+checker = (\ (x,y) -> even ((floor x + floor y) :: Int)) <$> coord++-- | Given two @Point@s, and a thickness, draw a line between the points.+-- line :: Line -> Double -> Board Bool++-}+{-+straightline' ((x1,y1),(x2,y2)) width = (\ (x,y) ->+---	distance (x1,y1) (x,y) <= width ||+--	distance (x2,y2) (x,y) <= width ||+	(  let 	u = intervalOnLine ((x1,y1),(x2,y2))  (x,y)+	   in u >= 0 +	   && u <= 1 +	   && distance (lerp (x1,y1) (x2,y2) u) (x,y) <= width+	)) <$> coord+-}++-- | A straight line, of a given width, between two points.++straightLine :: (Point,Point) -> R -> Board Bool+straightLine (p1@(x1,y1),p2@(x2,y2)) w = +          move (x1,y1)+        $ rotate (pi /2 - th)+	$ box ((-w/2,0),(w/2,len))+  where+          (xd,yd)  = (x2 - x1,y2 - y1)+          (len,th) = toPolar (xd,yd)++pointsToLine :: [Point] -> R -> Board Bool+pointsToLine points width = stack+	[ straightLine (p1,p2) width+	| (p1,p2) <- zip points (tail points)+	] `over` stack +	[ dotAt p width | p <- tail (init points) ]++-- | place dot at this location, with given diameter.+dotAt :: Point -> R -> Board Bool+dotAt p w = move p $ scale w circle+          +-- | A line generated by sampling a function from @R@ to @Point@s,+-- with a specific width. There needs to be at least 2 sample points.++functionLine :: (R -> Point) -> R -> Int -> Board Bool+functionLine line width steps = pointsToLine samples width+    where+	samples = map line (outerSteps steps)++-- | arrowhead is a triangle, pointing straight up, height 1, width 1, with the (0,0) at the center of the base.+--arrowhead :: Point -> Radian -> R -> Board Bool+--arrowhead p rad sz = move p $ rotate rad $ scale sz $ (\ (x,y) -> y >= 0 && y <= 1 && abs x * 2 <= 1 - y) <$> coord		+		 +
+ Graphics/ChalkBoard/Types.hs view
@@ -0,0 +1,212 @@+{-# LANGUAGE TypeSynonymInstances #-}+-- |+-- Module: Graphics.ChalkBoard.Types+-- Copyright: (c) 2009 Andy Gill+-- License: BSD3+--+-- Maintainer: Andy Gill <andygill@ku.edu>+-- Stability: unstable+-- Portability: ghc+--+-- This module contains the types used by chalkboard, except Board itself.+--+module Graphics.ChalkBoard.Types +	( -- * Basic types+	  UI, R, Point, Radian,+	  -- * Overlaying+	  Over(..),+	  stack,+	  -- * Scaling+	  Scale(..),+	  -- * Linear Interpolation+	  Lerp(..),+	  -- * Averaging+	  Average(..),+{-+	  -- * Alpha Channel support+	  Alpha(..),+	 alpha, transparent, withAlpha, unAlpha,+	  -- * Z buffer support+	  Z(..),+-}+	  -- * Constants+	  nearZero+	  -- * Colors+	, Gray+	, RGB(..)+	, RGBA(..)+	) where++import Data.Binary+import Control.Monad++-- | A real number.+type R = Float++-- | Unit Interval: value between 0 and 1, inclusive.+type UI = R++-- | A point in R2.+type Point = (R,R)++-- | Angle units+type Radian = Float	++-- | Close to zero; needed for @Over (Alpha c)@ instance.+nearZero :: R+nearZero = 0.0000001 +++------------------------------------------------------------------------------++infixr 5 `over`++-- | For placing a value literally /over/ another value. The 2nd value /might/ shine through.+-- The operation /must/ be associative.+class Over c where+  over :: c -> c -> c++instance Over Bool where+  over = (||)++instance Over (Maybe a) where+  (Just a) `over` _    = Just a+  Nothing `over` other = other++-- | 'stack' stacks a list of things over each other, +-- where earlier elements are 'over' later elements.+-- Requires non empty lists, which can be satisfied by using an explicitly+-- transparent @Board@ as one of the elements.++stack :: (Over c) => [c] -> c+stack = foldr1 over++------------------------------------------------------------------------------++-- | 'Scale' something by a value. scaling value can be bigger than 1.++class Scale c where+  scale :: R -> c -> c++instance Scale R where+  scale u v = u * v++instance (Scale a,Scale b) => Scale (a,b) where+  scale u (x,y) = (scale u x,scale u y)+++------------------------------------------------------------------------------++-- | Linear interpolation between two values.+class Lerp a where+  lerp :: UI -> a -> a -> a++instance Lerp R where+  lerp s v v' = v + (s * (v' - v))++-- | 'Lerp' over pairs++instance (Lerp a,Lerp b) => Lerp (a,b) where+  lerp s (a,b) (a',b') = (lerp s a a',lerp s b b')++instance (Lerp a) => Lerp (Maybe a) where+  lerp _ Nothing  Nothing  = Nothing+  lerp _ (Just a) Nothing  = Just a +  lerp _ Nothing  (Just b) = Just b+  lerp s (Just a) (Just b) = Just (lerp s a b)++------------------------------------------------------------------------------++-- | 'Average' a set of values. weighting can be achived using multiple entries.++class Average a where+  -- | average is not defined for empty list+  average :: [a] -> a ++instance Average R where+  average xs = sum xs / fromIntegral (length xs)+  +instance (Average a,Average b) => Average (a,b) where+  average xs = (average $ map fst xs,average $ map snd xs)++------------------------------------------------------------------------------++-- | 'Gray' is just a value between 0 and 1, inclusive.+-- Be careful to consider if this is pre or post gamma.+type Gray = UI++instance Over Gray where+  over r _ = r++------------------------------------------------------------------------------+-- Simple colors++-- | 'RGB' is our color, with values between 0 and 1, inclusive.+data RGB  = RGB !UI !UI !UI deriving Show++instance Over RGB where+  -- simple overwriting+  over x _y = x++instance Lerp RGB where+  lerp s (RGB r g b) (RGB r' g' b')+	 = RGB (lerp s r r') +	       (lerp s g g')+	       (lerp s b b')++instance Scale RGB where+  scale s (RGB r g b)+	 = RGB (scale s r) +	       (scale s g)+	       (scale s b) ++instance Average RGB where+  average cs = RGB (average reds) (average greens) (average blues)+     where+	reds   = [ r | RGB r _ _ <- cs ]+	greens = [ g | RGB _ g _ <- cs ]+	blues  = [ b | RGB _ _ b <- cs ]+++-- Consider using 4 bytes for color, rather than 32 bytes for the double (or are they floats?)+instance Binary RGB where+  put (RGB r g b) = put r >> put g >> put b+  get = liftM3 RGB get get get+++------------------------------------------------------------------------------------------+-- Colors with alpha++-- | 'RGBA' is our color, with values between 0 and 1, inclusive.+-- These values are *not* prenormalized+data RGBA = RGBA !UI !UI !UI !UI deriving Show+++ -- Todo: rethink what this means++instance Over RGBA where+  over (RGBA r g b a) (RGBA r' g' b' a') =+	RGBA (f r r')+	     (f g g')+	     (f b b')+	     (a * a')+    where f x y = a * y + (1 - a) * x++{-+   -- An associative algorithm for handling the alpha channel+	-- Associative; please reinstate later++	| a <= nearZero = RGBA r' g' b' a_new+	| otherwise     = RGBA +			(lerp r' (scale (1/a) r) a) +			(lerp g' (scale (1/a) g) a) +			(lerp b' (scale (1/a) b) a) +				 a_new+     where+	-- can a_new be 0? only if a == 0 and a' == 0+	a_new     = a + a' * (1 - a)+-}++instance Binary RGBA where+  put (RGBA r g b a) = put r >> put g >> put b >> put a+  get = liftM4 RGBA get get get get
+ Graphics/ChalkBoard/Utils.hs view
@@ -0,0 +1,120 @@+-- |+-- Module: Graphics.Chalkboard.Utils+-- Copyright: (c) 2009 The University of Kansas+-- License: BSD3+--+-- Maintainer: Andy Gill <andygill@ku.edu>+-- Stability: unstable+-- Portability: ghc+--+-- This module has some basic, externally visable, definitions.++module Graphics.ChalkBoard.Utils +	( -- * Point Utilties.+	  insideRegion+	, insideCircle+	, distance+	, intervalOnLine+	, circleOfDots+	, insidePoly+	  -- * Utilties for @R@.+	, innerSteps, outerSteps, fracPart+	, fromPolar+	, toPolar+	, angleOfLine+	, +	) where++--	, red, green, blue, white, black, cyan, purple, yellow+import Graphics.ChalkBoard.Types++-- | innerSteps takes n even steps from 0 .. 1, by not actually touching 0 or 1.+-- The first and last step are 1/2 the size of the others, so that repeated innerSteps+-- can be tiled neatly.+innerSteps :: Int -> [R]+innerSteps n = map (/ fromIntegral (n * 2)) (map fromIntegral (take n [1::Int,3..]))++-- | outerSteps takes n even steps from 0 .. 1, starting with 0, and ending with 1,+--  returning n+1 elements.++outerSteps :: Int -> [R]+outerSteps n = map (/ fromIntegral n) (map fromIntegral (take (n + 1) [(0::Int)..]))++-- | Extract the fractional part of an @R@.+fracPart :: R -> R+fracPart x = x - fromIntegral ((floor x) :: Integer)++-- Point operations++-- | is a @Point@ inside a region?++insideRegion :: (Point,Point) -> Point -> Bool+insideRegion ((x1,y1),(x2,y2)) (x,y) = x1 <= x && x <= x2+	  		           && y1 <= y && y <= y2 ++-- | is a @Point@ inside a circle, where the first two arguments are the center of the circle,+-- and the radius.+++insideCircle :: Point -> R -> Point -> Bool+insideCircle (x1,y1) r (x,y) = distance (x1,y1) (x,y) <= r+++-- | What is the 'distance' between two points in R2?+-- This is optimised for the normal form @distance p1 p2 <= v@, which avoids using @sqrt@.++distance :: Point -> Point -> R+distance (x,y) (x',y') = sqrt (xd * xd + yd * yd)+  where+	xd = x - x'+	yd = y - y'++{-# INLINE distance #-}+-- The obvious sqrt (x * x) ==> x does not fire.	+{-# RULES "distance <= w" forall t u w . distance t u <= w = distanceLe t u w #-}+{-# INLINE distanceLe #-}+distanceLe :: Point -> Point -> R -> Bool+distanceLe (x,y) (x',y') w = (xd * xd + yd * yd) <= w * w+  where+	xd = x - x'+	yd = y - y'+++-- | 'intervalOnLine' find the place on a line (between 0 and 1) that is closest to the given point.+intervalOnLine :: (Point,Point) -> Point -> R +intervalOnLine  ((x1,y1),(x2,y2)) (x0,y0) =+	((x0-x1)*(x2-x1)+(y0-y1)*(y2-y1))/(xd * xd + yd * yd)		+  where+		xd = x2-x1+		yd = y2-y1++fromPolar :: (R,Radian) -> Point +fromPolar (p, phi) = (p * cos phi, p * sin phi) ++toPolar :: Point -> (R,Radian)+toPolar (x, y) = (sqrt (x * x + y * y), atan2 y x)++angleOfLine :: (Point,Point) -> Radian+angleOfLine ((x1,y1),(x2,y2)) = atan2 (x2 - x1) (y2 - y1)+++-- | circleOfDots generates a set of points between (-1..1,-1..1), inside a circle.+circleOfDots :: Int -> [Point]+circleOfDots 0 = error "circleOfDots 0"+circleOfDots n = [ (x,y)+		 | x <- map (\ t -> t * 2 - 1) $ outerSteps n+		 , y <- map (\ t -> t * 2 - 1) $ outerSteps n+		 , (x * x + y * y) <= 1.0 +		 ]++insidePoly :: [Point] -> Point -> Bool+insidePoly nodes (x,y) +	  -- no numbers above 0, or no numbers below zero+	  -- means that the numbers we the *same* sign (or zero)>+	| null (filter (> 0) vals) ||  null (filter (< 0) vals) = True+	| otherwise		   				= False+  where+	vals = [ (y - y0) * (x1 - x0) - (x - x0) * (y1 - y0)+	       | ((x0,y0),(x1,y1)) <- zip nodes (tail nodes ++ [head nodes]) + 	       ]+
− Graphics/Chalkboard.hs
@@ -1,32 +0,0 @@--- |--- Module: Graphics.Chalkboard--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ Public interface to the Chalkboard utilities.-----module Graphics.Chalkboard-	( module Graphics.Chalkboard.Array-	, module Graphics.Chalkboard.Ascii-	, module Graphics.Chalkboard.Board-	, module Graphics.Chalkboard.Color-	, module Graphics.Chalkboard.Shapes-	, module Graphics.Chalkboard.PPM-	, module Graphics.Chalkboard.Utils-	, module Graphics.Chalkboard.Types-	) where--import Graphics.Chalkboard.Array	-import Graphics.Chalkboard.Ascii-import Graphics.Chalkboard.Board hiding (scale)-import Graphics.Chalkboard.Color-import Graphics.Chalkboard.Shapes-import Graphics.Chalkboard.PPM-import Graphics.Chalkboard.Utils-import Graphics.Chalkboard.Types-
− Graphics/Chalkboard/Array.hs
@@ -1,130 +0,0 @@--- |--- Module: Graphics.Chalkboard.Array--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ This module coverts 2D arrays into 'Board's, and back, and supplies basic dithering algorithms.--module Graphics.Chalkboard.Array-	( -- * Converters-	  boardToArray, arrayToBoard,-	  -- * Dithering-	  threshold, floydSteinberg,-	  -- * Utilties-	  widthHeight-	)- where--import Data.Array--import Graphics.Chalkboard.Board as Board-import Graphics.Chalkboard.Utils-import Graphics.Chalkboard.Types--import Control.Applicative---- | 'boardToArray' turns a Board into a 2D Array (pixelization).--boardToArray :: (Average a) - => (Int,Int) 	-- ^ the x,y size of the image to be captured. We assume the bottom left hand size is 0,0.- -> Int       	-- ^ the square root of the amount of super-sampling to be done. I recommend 3, which is 9 points.- -> Board a	-- ^ the board to sample.- -> Array (Int,Int) a -- ^ the result array.-boardToArray (x_dim,y_dim) n board = array ((0,0),(x_dim,y_dim))-	[ ((x,y), average -		   [ fn (fromIntegral x + x',fromIntegral y + y') -		   | x' <- innerSteps n -		   , y' <- innerSteps n-		   ]-	   )-	| x <- [0..x_dim]-	, y <- [0..y_dim]- 	]-    where-	fn = Board.lookup board---- There are different ways of taking a 2d array into a Board.---   * Do you pixelize the input, or make it continuous (using Bilinear interpolation)?---   * Be careful at the edges! You want the samples to be inside the actual edge, not on it.---  How do we handle the alpha at the edges!-{---   0       1       2-   +---X---+---Y---+--   So, with pixels, what value does 1 have (X or Y), how about 0 and 2, do you biest to the left or right?-       with continuous, what value does 0 or 2 have?---}---- | 'arrayToBoard' turns a 2D Array into a Board, using bi-linear inteprelation.--arrayToBoard :: (Lerp a, Scale a) => Array (Int,Int) a -> Board (Maybe a)-arrayToBoard arr = arrayToBoard' arr (bounds arr)--arrayToBoard' :: (Lerp a, Scale a) => Array (Int,Int) a -> ((Int,Int),(Int,Int)) -> Board (Maybe a)-arrayToBoard' arr bnd@((0,0),(w,h)) = pure img <*> coord-  where -	outside x0 y0 = x0 < 0-		     || x0 > fromIntegral w-	             || y0 < 0-		     || y0 > fromIntegral h-	img (x,y) | outside x y = Nothing-	          | otherwise   = lerp p00_p10 p01_p11 y_gap-		where-		 (x',x_gap) = close (x - 0.5) -		 (y',y_gap) = close (y - 0.5) -		 find x0 y0 | not (inRange bnd (x0,y0))-				= Nothing-			    | otherwise-				= Just (arr ! (x0,y0))-		 p00 = find x' y'-		 p10 = find (succ x') y'-		 p01 = find x' (succ y')-		 p11 = find (succ x') (succ y')-		 p00_p10 = lerp p00 p10 x_gap-		 p01_p11 = lerp p01 p11 x_gap--- normalize the board to start at (0,0)-arrayToBoard' arr bnds@((low_w,low_h),_) = arrayToBoard (ixmap bnds (\ (w,h) -> (w - low_w,h - low_h)) arr)	---- how close are you to one of our samples?-close :: R -> (Int,R)-close v0 = (v_floor,fracPart v0)-  where-	v_floor = floor v0---------------------------------------------------------widthHeight :: Array ((Int,Int)) a -> (Int,Int)-widthHeight arr = (w+1,h+1)-	where-		((0,0),(w,h)) = bounds arr----------------------------------------------------------- | 'threshold' quantized based on a simple, pointwise function.--threshold :: (Floating a) => (a -> a) -> Array (Int,Int) a -> Array (Int,Int) a-threshold quantize = fmap quantize---- | 'floydSteinberg' quantized using the Floyd Steinberg algorithm.--floydSteinberg :: (Floating a) => (a -> a) -> Array (Int,Int) a -> Array (Int,Int) a-floydSteinberg quantize orig = fmap fst values-  where-	bnds@((x_min,y_min),(x_max,y_max)) = bounds orig -	errors (x,y) | inRange bnds (x,y) = snd (values ! (x,y))-		     | otherwise    = 0-	values = array bnds-		[ let value = orig ! (x,y) +-			(errors (x-1,y))   * 7 +-			(errors (x+1,y-1)) * 3 +-			(errors (x,y-1))   * 5 +-			(errors (x-1,y-1)) * 1-		      q_value = quantize value-		  in ((x,y),(q_value,(value - q_value) / 16))-		| x <- [x_min..x_max]-		, y <- [y_min..y_max]-		]
− Graphics/Chalkboard/Ascii.hs
@@ -1,79 +0,0 @@--- |--- Module: Graphics.Chalkboard.Array--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ This module supports basic ascii drawing of 'Board's.-----module Graphics.Chalkboard.Ascii -	( toAscii, toCount ) -  where--import Data.Array--import Graphics.Chalkboard.Board-import Graphics.Chalkboard.Array-import Graphics.Chalkboard.Types-import Graphics.Chalkboard.Color---- | 'toAscii' generates a board of ascii characters, where each char is two pixels, one wide and two high.--toAscii :: (Int,Int) -> Board Gray -> [String]-toAscii = toAsciiWithPen $ \ v v' -> case (sampleInk v,sampleInk v') of-		      (NoInk,NoInk) -> ' '-		      (NoInk,SomeInk) -> '.'-		      (NoInk,MostInk) -> '_'-		      (SomeInk,NoInk) -> head "'"-		      (SomeInk,SomeInk) -> ':'-		      (SomeInk,MostInk) -> ';'-		      (MostInk,NoInk) -> '"'-		      (MostInk,SomeInk) -> '?'-		      (MostInk,MostInk) -> '%'----- | 'toCount' generates a board of ascii characters, where each char is two pixels, one wide and two high.--- we uses digits 1 .. 9, then 0 (highest) to represent intensity, adding the two pixels for each char.--toCount :: (Int,Int) -> Board Gray -> [String]-toCount = toAsciiWithPen $ \ v v' -> -			case show (ceiling ((v + v') * 5) :: Int) of-			   "0"  -> ' '-			   [c]  -> c-			   "10" -> '0'-			   _    -> '?'--toAsciiWithPen :: (Gray -> Gray -> Char) -> (Int,Int) -> Board Gray -> [String]-toAsciiWithPen pen (x_dim,y_dim) board = [-	[	let v = arr' ! (x,y)-		    v' = arr' ! (x,y')-		in pen v v'-	|	x <- [0..x_dim]-	]-	|	(y,y') <- join [y_dim', y_dim'-2 ..]-	]-	where arr = boardToArray (x_dim,y_dim') 2 board-	      arr' = floydSteinberg sampleT arr-	      y_dim' = if even y_dim then succ y_dim else y_dim-	      join (x:xs) | x < 0     = [] -			  | otherwise = (x,x-1) : join xs-	      join _ = error "fatal error"--data Ink = NoInk | SomeInk | MostInk--sampleT :: UI -> UI-sampleT n-  | n <= 0.33 = 0.15-  | n <= 0.67 = 0.60-  | otherwise = 1---sampleInk :: UI -> Ink-sampleInk n -  | n <= 0.33 = MostInk-  | n <= 0.67 = SomeInk-  | otherwise = NoInk
− Graphics/Chalkboard/Board.hs
@@ -1,108 +0,0 @@--- |--- Module: Graphics.Chalkboard.Array--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ Boards are the principal type for our images. The are conceptually functions from--- 2D coordinates to values, typically a color. ------ Common Boards include------ * @Board Bool@           -- A masking @Board@, or region.------ * @Board RGB@	    -- @Color Board@------ * @Board (Alpha RGB)@    -- A @Color Board@ with alpha (transparency) values.------ * @Board (Maybe a)@      -- A @Board@ with binary transparency.------ * @Board (Maybe Color)@  -- A @Color Board@ with binary transparency.------ * @Board Point@          -- A @Board@ (or field) of @Point@ values.-----module Graphics.Chalkboard.Board -	( -- * The Board datatype-	  Board-	  -- * looking up a point on the @Board@.-	, lookup-	  -- * Creating @Board@s.-	, coord-	, maskFor-	, circularMaskFor-	  -- * Translations on a @Board@.-	, scale-	, scaleXY-	, move-	, rotate-	 -- -	, crop-	, Applicative(..)-	) where---import Prelude hiding (lookup)--import Graphics.Chalkboard.Utils-import Graphics.Chalkboard.Types--import Control.Applicative---- | '''Board''' is our primary data type, an infinite flat surface (or R2 field) of values.--- Conceptually, @Board a = Point -> a@.-data Board a = Board ((R,R) -> a)--- TODO: consider have a ConstantBoard--lookup :: Board a -> (R,R) -> a-lookup (Board f) = f---- Board functionals--instance Scale (Board a) where-  scale n (Board f) = Board $ \ (x,y) -> f (x / n,y / n)---- | move a Board by specified vector.-move :: (R,R) -> Board a -> Board a-move (xd,yd) (Board f) = Board $ \ (x,y) -> f (x - xd,y - yd)---- | A non-overloaded version of 'scale' which takes a independent x and y coordinate.-scaleXY :: (R,R) -> Board a -> Board a-scaleXY (xn,yn) (Board f) = Board $ \ (x,y) -> f (x / xn,y / yn)---- | rotate the Board.-rotate :: Radian -> Board a -> Board a-rotate theta (Board f) = Board $ \ (x,y) -> f (cos theta * x - sin theta * y,-				    	       sin theta * x + cos theta * y)---- | 'crop' crops a Board, based on a masking Board.-crop :: Board Bool -> Board a -> Board (Maybe a)-crop mask brd = liftA2 withMask brd mask---- board Generators---- | 'coord' field or 'Board', where each point is its own coordinate in R2.-coord :: Board Point-coord = Board id---- | build a rectangle mask or region.-maskFor :: (Point,Point) -> Board Bool-maskFor (p1,p2) = fmap (insideRegion (p1,p2)) coord---- | build a circular mask or region, with a circle of radius @R@, and center @Point@. -circularMaskFor :: Point -> R -> Board Bool-circularMaskFor p r = fmap (insideCircle p r) coord--instance Functor Board where-  fmap f (Board fn) = Board (f . fn)--instance Applicative Board where-  pure a = Board $ \ _ -> a-  (Board f) <*> (Board a) = Board (\ (x,y) -> f (x,y) $ a (x,y))--instance (Over c) => Over (Board c) where-  over = liftA2 over-
− Graphics/Chalkboard/Color.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}---- |--- Module: Graphics.Chalkboard.Color--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ Simple RGB colors.--module Graphics.Chalkboard.Color -	( Gray,-	  RGB(..),-	  red, green, blue, white, black, cyan, purple, yellow-        ) where--import Graphics.Chalkboard.Types------------------------------------------------------------------------------------ | 'Gray' is just a value between 0 and 1, inclusive.--- Be careful to consider if this is pre or post gamma.-type Gray = UI---instance Over Gray where-  over r _ = r----------------------------------------------------------------------------------- Simple colors---- | 'RGB' is our color, with values between 0 and 1, inclusive.-data RGB  = RGB !UI !UI !UI deriving Show--instance Over RGB where-  -- simple overwriting-  over x _y = x--instance Lerp RGB where-  lerp (RGB r g b) (RGB r' g' b') s -	 = RGB (lerp r r' s) -	       (lerp g g' s)-	       (lerp b b' s)--instance Scale RGB where-  scale s (RGB r g b)-	 = RGB (scale s r) -	       (scale s g)-	       (scale s b) --instance Average RGB where-  average cs = RGB (average reds) (average greens) (average blues)-     where-	reds   = [ r | RGB r _ _ <- cs ]-	greens = [ g | RGB _ g _ <- cs ]-	blues  = [ b | RGB _ _ b <- cs ]----red    :: RGB-red    = RGB 1.0 0.0 0.0-green  :: RGB-green  = RGB 0.0 1.0 0.0-blue   :: RGB-blue   = RGB 0.0 0.0 1.0-white  :: RGB-white  = RGB 1.0 1.0 1.0-black  :: RGB-black  = RGB 0.0 0.0 0.0-cyan   :: RGB-cyan   = RGB 0.0 1.0 1.0-purple :: RGB-purple = RGB 1.0 0.0 1.0-yellow :: RGB-yellow = RGB 1.0 1.0 0.0
− Graphics/Chalkboard/PPM.hs
@@ -1,102 +0,0 @@--- |--- Module: Graphics.Chalkboard.PPM--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ Reading and writing portable pix maps. For now, we only support color images (@P1@, @P3@ and @P6@ formats).-----module Graphics.Chalkboard.PPM where--import System.IO-import Data.Array-import Data.Char--import Graphics.Chalkboard.Types-import Graphics.Chalkboard.Color-import Graphics.Chalkboard.Array----- | 'readPPM' reads a PPM file, and outputs a @Board@, and the @x@ and @y@ dimensions of the image.-readPPM :: String -> IO (Array (Int,Int) RGB)-readPPM filename = do-	h <- openFile filename ReadMode-	ty <- hGetLine h-	bin <- case ty of-	   "P3" -> return False-	   "P6" -> return True-	   _ -> error $ "bad PPM format: " ++ ty-	szs <- hGetLine h-	let [width,height] = (map read (words szs) :: [Int])---	print width---	print height   - 	mx <- hGetLine h-	let [maxs] = (map read (words mx) :: [R])---	print mx-	str <- hGetContents h-	let num1 = if bin -		then map (\ x -> fromIntegral (ord x) / maxs) str-		else map (\ x -> read x / maxs) (words str)-	let joinN _ [] = []-	    joinN n xs = take n xs : joinN n (drop n xs)-	let num3     = joinN 3 num1-	let num_rows = joinN width num3-	let arr = array ((0,0),(width-1,height-1))-		[ ((w,h'),RGB r g b)-		| (row,h') <- zip num_rows [height-1,height-2..]-		, ([r,g,b],w) <- zip row [0..]-		]-	return $ arr -- (arrayToBoard arr,(width,height))----- | 'readBPM' reads a PPM file, and outputs a @Board@, and the @x@ and @y@ dimensions of the image.-readPBM :: String -> IO (Array (Int,Int) Bool)-readPBM filename = do-	h <- openFile filename ReadMode-	ty <- hGetLine h-	_bin <- case ty of-	   "P1" -> return False-	   "P4" -> error "P4 PBM format not (yet) supported"-	   _ -> error $ "bad PPM format: " ++ ty-	szs <- hGetLine h-	let [width,height] = (map read (words szs) :: [Int])---	print width---	print height   --- 	mx <- hGetLine h---	let [maxs] = (map read (words mx) :: [R])---	print mx-	str <- hGetContents h-	let num1 = map (\ x -> if x == '1' then True else-		                 if x == '0' then False -		                 else error $ "bad data inside P1 file" ++ show x) -		$ filter (not . isSpace) str-	let joinN _ [] = []-	    joinN n xs = take n xs : joinN n (drop n xs)-        let num_rows = joinN width num1-	let arr = array ((0,0),(width-1,height-1))-		[ ((w,h'),v)-		| (row,h') <- zip num_rows [height-1,height-2..]-		, (v,w) <- zip row [0..]-		]-	return $ arr -- (arrayToBoard arr,(width,height))---- | 'writePPM' writes a PPM file, based on a color @Board@, where bottom left corner of the image is as @(0,0)@.-writePPM :: String -> Array (Int,Int) RGB -> IO ()-writePPM filename arr = writeFile filename $ -	"P6\n" ++ show w ++ " " ++ show h ++ "\n255\n" ++-	concat-	[ let (RGB r g b) = arr ! (x,y)-	      f x' =  if v < 0 then chr 0 else-	              if v > 255 then chr 255 else chr v-		 where v = floor (x' * 255)-	  in [f r,f g,f b]-	| y <- reverse [0..(h-1)]-	, x <- [0..(w - 1)]-	]-   where (w,h) = widthHeight arr-	-	
− Graphics/Chalkboard/Shapes.hs
@@ -1,71 +0,0 @@--- |--- Module: Graphics.Chalkboard.Shapes--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ This module contains some basic shape generators, expressed as @Board Bool@.-----module Graphics.Chalkboard.Shapes where--import Graphics.Chalkboard.Board-import Graphics.Chalkboard.Utils-import Graphics.Chalkboard.Types--import Control.Applicative---- | unit circle, radius 0.5, over origin.-circle :: Board Bool-circle =  (\ (x,y) -> x*x + y*y <= 0.5 * 0.5) <$> coord---- | unit vertical bar,  1 wide over origin.-vbar :: Board Bool-vbar =  (\ (_x,y) -> y <= 0.5 && y >= -0.5) <$> coord---- | unit horizontal bar, 1 high over origin.-hbar :: Board Bool-hbar =  (\ (x,_y) -> x <= 0.5 && x >= -0.5) <$> coord---- | unit square, 1x1 over origin.-square :: Board Bool-square = liftA2 (&&) vbar hbar---- | cheacker board, with squares 1x1.-checker :: Board Bool-checker = (\ (x,y) -> even ((floor x + floor y) :: Int)) <$> coord---- | Given two @Point@s, and a thickness, draw a line between the points.--- line :: Line -> Double -> Board Bool--straightline :: (Point,Point) -> R -> Board Bool-straightline ((x1,y1),(x2,y2)) width = (\ (x,y) ->----	distance (x1,y1) (x,y) <= width ||---	distance (x2,y2) (x,y) <= width ||-	(  let 	u = intervalOnLine ((x1,y1),(x2,y2))  (x,y)-	   in u >= 0 -	   && u <= 1 -	   && distance (lerp (x1,y1) (x2,y2) u) (x,y) <= width-	)) <$> coord---- | A line generated by sampling a function from @R@ to @Point@s,--- with a specific width. There needs to be at least 2 sample points.--functionline :: (R -> Point) -> R -> Int -> Board Bool-functionline line width steps = stack-		[ straightline (p1,p2) width-		| (p1,p2) <- zip samples (tail samples)-		] `over` stack-		        -- not the first or last point-		[ dotAt p | p <- tail (init samples) ]-    where-	samples = map line (outerSteps steps)-	dotAt p = move p $ scale (width * 2) circle---- | arrowhead is a triangle, pointing straight up, height 1, width 1, with the (0,0) at the center of the base.-arrowhead :: Point -> Radian -> R -> Board Bool-arrowhead p rad sz = move p $ rotate rad $ scale sz $ (\ (x,y) -> y >= 0 && y <= 1 && abs x * 2 <= 1 - y) <$> coord		-		 
− Graphics/Chalkboard/Types.hs
@@ -1,159 +0,0 @@-{-# LANGUAGE TypeSynonymInstances #-}--- |--- Module: Graphics.Chalkboard.Types--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ This module contains the types used by chalkboard, except Board itself.-----module Graphics.Chalkboard.Types -	( -- * Basic types-	  UI, R, Point, Radian,-	  -- * Overlaying-	  Over(..),-	  stack,-	  -- * Scaling-	  Scale(..),-	  -- * Linear Interpolation-	  Lerp(..),-	  -- * Averaging-	  Average(..),-	  -- * Alpha Channel support-	  Alpha(..),-	 alpha, transparent, withAlpha, unAlpha,-	  -- * Z buffer support-	  Z(..),-	  -- * Constants-	  nearZero-	) where---- | A real number.-type R = Float---- | Unit Interval: value between 0 and 1, inclusive.-type UI = R---- | A point in R2.-type Point = (R,R)---- | Angle units-type Radian = Float	---- | Close to zero; needed for @Over (Alpha c)@ instance.-nearZero :: R-nearZero = 0.0000001 ------------------------------------------------------------------------------------ | For placing a value literally /over/ another value. The 2nd value /might/ shine through.--- The operation /must/ be assocative.-class Over c where-  over :: c -> c -> c--instance Over Bool where-  over = (||)--instance Over (Maybe a) where-  (Just a) `over` _  = Just a-  Nothing `over` other = other---- | 'stack' stacks a list of things over each other, where earlier elements are 'over' later elements.--- Requires non empty lists, which can be satisfied by using an explicity--- transparent @Board@ as one of the elements.--stack :: (Over c) => [c] -> c-stack = foldr1 over------------------------------------------------------------------------------------ | 'Scale' something by a value. scaling value can be bigger than 1.--class Scale c where-  scale :: R -> c -> c--instance Scale R where-  scale u v = u * v------------------------------------------------------------------------------------ | Linear interpolation between two values.-class Lerp a where-  lerp :: a -> a -> UI -> a--instance Lerp R where-  lerp v v' s = v + (s * (v' - v))---- | 'Lerp' over pairs--instance (Lerp a,Lerp b) => Lerp (a,b) where-  lerp (a,b) (a',b') s = (lerp a a' s,lerp b b' s)--instance (Lerp a) => Lerp (Maybe a) where-  lerp Nothing  Nothing  _s  = Nothing-  lerp (Just a) Nothing  _s = Just a -  lerp Nothing  (Just b) _s = Just b-  lerp (Just a) (Just b) s = Just (lerp a b s)------------------------------------------------------------------------------------ | 'Average' a set of values. weighting can be achived using multiple entries.--class Average a where-  -- | average is not defined for empty list-  average :: [a] -> a --instance Average R where-  average xs = sum xs / fromIntegral (length xs)----------------------------------------------------------------------------------- | Channels with alpha component, the channel @is@ pre-scaled.--data Alpha c = Alpha c !UI deriving Show---- | 'alpha' builds something that has an alpha channel, and is completely opaque.-alpha :: c -> Alpha c-alpha c = Alpha c 1.0---- | 'transparent' builds something that has an alpha channel, and is completely transparent.-transparent :: (Scale c) => c -> Alpha c-transparent c = Alpha (scale 0 c) 0.0---- | 'withAlpha' builds somethings that has a specific alpha value.-withAlpha :: (Scale c) => UI -> c -> Alpha c-withAlpha a c = Alpha (scale a c) a---- | 'unAlpha' removes the alpha component, and returns the channel inside.-unAlpha :: (Scale c) => Alpha c -> c-unAlpha (Alpha c _a) = c -- the channel is prescaled, hence we ignore the alpha value here.--instance (Scale c,Lerp c) => Over (Alpha c) where-   -- An associative algorithm for handling the alpha channel-  over (Alpha c a) (Alpha c' a') -	| a <= nearZero = Alpha c' a_new-	| otherwise     = Alpha (lerp c' (scale (1/a) c) a) a_new-     where-	-- can a_new be 0? only if a == 0 and a' == 0-	a_new     = a + a' * (1 - a)--instance Lerp c => Lerp (Alpha c) where-  lerp (Alpha c1 a1) (Alpha c2 a2) s = Alpha (lerp c1 c2 s) (lerp a1 a2 s)-  -instance Scale c => Scale (Alpha c) where-  scale s (Alpha c t) = Alpha (scale s c) (scale s t)------------------------------------------------------------------------------------ | A Z buffer style Z value for a point, where lower numbers are nearer the viewer.--- Assumes no transparency.--data Z c = Z c R deriving Show--instance Over (Z c) where-  over (Z c1 z1) (Z c2 z2) -	| z1 <= z2  = Z c1 z1-	| otherwise = Z c2 z2
− Graphics/Chalkboard/Utils.hs
@@ -1,145 +0,0 @@--- |--- Module: Graphics.Chalkboard.Utils--- Copyright: (c) 2009 Andy Gill--- License: BSD3------ Maintainer: Andy Gill <andygill@ku.edu>--- Stability: unstable--- Portability: ghc------ This module contains some general utilties.-----module Graphics.Chalkboard.Utils -	( -- * Utilties for @R@.-	  innerSteps, outerSteps, fracPart-	, fromPolar-	, toPolar-	, angleOfLine-	  -- * Pointwise operators.-	, interpBool -	, sampleUI-	, withMask-	, withDefault-	, choose-	  -- * Point Utilties.-	, insideRegion-	, insideCircle-	, distance-	, intervalOnLine-	, circleOfDots-	) where--import Graphics.Chalkboard.Types------------------------------------------------------------------------------------- | innerSteps takes n even steps from 0 .. 1, by not actually touching 0 or 1.--- The first and last step are 1/2 the size of the others, so that repeated innerSteps--- can be tiled neatly.-innerSteps :: Int -> [R]-innerSteps n = map (/ fromIntegral (n * 2)) (map fromIntegral (take n [1::Int,3..]))---- | outerSteps takes n even steps from 0 .. 1, starting with 0, and ending with 1,---  returning n+1 elements.--outerSteps :: Int -> [R]-outerSteps n = map (/ fromIntegral n) (map fromIntegral (take (n + 1) [(0::Int)..]))---- | Extract the fractional part of an @R@.-fracPart :: R -> R-fracPart x = x - fromIntegral ((floor x) :: Integer)------------------------------------------------------------------------------------ Pointwise operators---- | Covert a Bool (mask point) into a unit interval.-interpBool :: Bool -> UI-interpBool True  = 1.0-interpBool False = 0.0---- | sample a UI, giving a point of a mask.-sampleUI :: UI -> Bool-sampleUI n = n >= 0.5---- | Use a mask to create a Just value, or Nothing.-withMask :: a -> (Bool -> Maybe a)-withMask a True  = Just a-withMask _ False = Nothing---- | With a default if you do not have a Just.-withDefault :: a -> (Maybe a -> a)-withDefault a Nothing  = a-withDefault _ (Just b) = b---- | 'choose' between two values.-choose :: a -> a -> (Bool -> a)-choose t  _f True  = t-choose _t f  False = f------------------------------------------- Point operations---- | is a @Point@ inside a region?--insideRegion :: (Point,Point) -> Point -> Bool-insideRegion ((x1,y1),(x2,y2)) (x,y) = x1 <= x && x <= x2-	  		           && y1 <= y && y <= y2 ---- | is a @Point@ inside a circle, where the first two arguments are the center of the circle,--- and the radius.---insideCircle :: Point -> R -> Point -> Bool-insideCircle (x1,y1) r (x,y) = distance (x1,y1) (x,y) <= r----- | What is the 'distance' between two points in R2?--- This is optimised for the normal form @distance p1 p2 <= v@, which avoids using @sqrt@.--distance :: Point -> Point -> R-distance (x,y) (x',y') = sqrt (xd * xd + yd * yd)-  where-	xd = x - x'-	yd = y - y'--{-# INLINE distance #-}--- The obvious sqrt (x * x) ==> x does not fire.	-{-# RULES "distance <= w" forall t u w . distance t u <= w = distanceLe t u w #-}-{-# INLINE distanceLe #-}-distanceLe :: Point -> Point -> R -> Bool-distanceLe (x,y) (x',y') w = (xd * xd + yd * yd) <= w * w-  where-	xd = x - x'-	yd = y - y'----- | 'intervalOnLine' find the place on a line (between 0 and 1) that is closest to the given point.-intervalOnLine :: (Point,Point) -> Point -> R -intervalOnLine  ((x1,y1),(x2,y2)) (x0,y0) =-	((x0-x1)*(x2-x1)+(y0-y1)*(y2-y1))/(xd * xd + yd * yd)		-  where-		xd = x2-x1-		yd = y2-y1--fromPolar :: (R,Radian) -> Point -fromPolar (p, phi) = (p * cos phi, p * sin phi) --toPolar :: Point -> (R,Radian)-toPolar (x, y) = (x * x + y * y, atan2 x y)--angleOfLine :: (Point,Point) -> Radian-angleOfLine ((x1,y1),(x2,y2)) = atan2 (x2 - x1) (y2 - y1)----- | circleOfDots generates a set of points between (-1..1,-1..1), inside a circle.-circleOfDots :: Int -> [Point]-circleOfDots 0 = error "circleOfDots 0"-circleOfDots n = [ (x,y)-		 | x <- map (\ t -> t * 2 - 1) $ outerSteps n-		 , y <- map (\ t -> t * 2 - 1) $ outerSteps n-		 , (x * x + y * y) <= 1.0 -		 ]
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2009 Andy Gill+Copyright (c) 2009 University of Kansas All rights reserved.  Redistribution and use in source and binary forms, with or without
chalkboard.cabal view
@@ -1,52 +1,133 @@ Name:                chalkboard-Version:             0.2+Version:             1.9.0.16 Synopsis:            Combinators for building and processing 2D images. -Description:	     Chalkboard is a Haskell hosted Domain Specific Language (DSL) for image generation and processing.-		The basic structure is a chalk board, a two-dimensional canvas of values, typically colors. -		Chalkboard provides the usual image processing functions (masking, overlaying, function mapping,+Description:	     ChalkBoard is a Haskell hosted Domain Specific Language (DSL) for image generation and processing.+		The basic structure is a Chalk Board, a two-dimensional canvas of values, typically colors. +		ChalkBoard provides the usual image processing functions (masking, overlaying, function mapping, 		cropping, warping, rotating) as well as a few more unusual ones. -		Images can be imported into Chalkboard, as first-class color chalk boards. -		Chalkboard also provides combinators for drawing shapes on directly on boards.-		The system is based loosely on PAN, but the principal image type, a Board, is abstract. +		Images can be imported into ChalkBoard, as first-class color chalk boards. +		ChalkBoard also provides combinators for drawing shapes on directly on boards.+		The system is based loosely on Pan, but the principal image type, a Board, is abstract.   Category:            Graphics License:             BSD3 License-file:        LICENSE-Author:              Andy Gill+Author:              Andy Gill, Kevin Matlage Maintainer:          Andy Gill <andygill@ku.edu>-Copyright:           (c) 2009 Andy Gill-Homepage:            http://ittc.ku.edu/~andygill/chalkboard.php-Stability:	     alpha+Copyright:           (c) 2009 University of Kansas+Homepage:            http://www.ittc.ku.edu/csdl/fpg/ChalkBoard+Stability:	     Experimental build-type: 	     Simple Cabal-Version:       >= 1.6-extra-source-files: test/liam.ppm, test/Makefile+Extra-Source-Files:+        tutorial/basic/tutorial.pdf+        tutorial/basic/Main.hs+	tests/test1/images/cb-text.gif+	tests/test1/images/cb-text.jpg+	tests/test1/images/cb-text.png++Flag all+  Description: Enable full development tree, including all tests and examples+  Default:     False 	 Library-  Build-Depends:        base, array+  Build-Depends:        base >= 4 && < 5, array, data-reify, containers >= 0.2, GLUT>=2.1.2.1, OpenGLRaw>=1.0.1.0, Codec-Image-DevIL, time, directory, binary, bytestring, process   Exposed-modules:-       Graphics.Chalkboard,-       Graphics.Chalkboard.Array,-       Graphics.Chalkboard.Ascii,-       Graphics.Chalkboard.Board,-       Graphics.Chalkboard.Color,-       Graphics.Chalkboard.PPM,-       Graphics.Chalkboard.Shapes,-       Graphics.Chalkboard.Utils,-       Graphics.Chalkboard.Types+       Graphics.ChalkBoard,+       Graphics.ChalkBoard.Board,+       Graphics.ChalkBoard.Shapes,+       Graphics.ChalkBoard.Types,+       Graphics.ChalkBoard.Main,+       Graphics.ChalkBoard.O,+       Graphics.ChalkBoard.Utils+       Graphics.ChalkBoard.Options+  Other-modules:+       Graphics.ChalkBoard.Board.Internals,+       Graphics.ChalkBoard.O.Internals,+       Graphics.ChalkBoard.CBIR,+       Graphics.ChalkBoard.CBIR.Compiler,+       Graphics.ChalkBoard.IStorable,+       Graphics.ChalkBoard.Core+       Graphics.ChalkBoard.Expr+       Graphics.ChalkBoard.OpenGL.CBBE+       Graphics.ChalkBoard.OpenGL.Monad+-- We choose to build this with O2, because this is about acceleration+  Ghc-Options:  -O2+  Ghc-Options:  -Wall  -  Ghc-Options:  -Wall+-- The server is by default always built.+-- The suffix number is the same as a version number, above.+flag server { Default: True }+Executable chalkboard-server-1_9_0_16+  if flag(server)+    buildable:            True+  else+    Buildable:           False+  Hs-Source-Dirs:       .,server+  Ghc-Options:          -O2+  Main-Is:              Main.hs ---Executable chalkboard-test---  Build-Depends:        base, array, process---  Ghc-Options:    -O2---  Main-Is:        Test.hs---  Hs-Source-Dirs: ., test---  buildable: True------Executable chalkboard-test2---  Build-Depends:        base, array, process---  Ghc-Options:    -O2---  Main-Is:        Test2.hs---  Hs-Source-Dirs: ., test---  buildable: True+flag test1 { Default: False }+Executable chalkboard-tests-test1+  if flag(all) || flag(test1)+    buildable:            True+  else+    Buildable:           False+  Hs-Source-Dirs:       .,tests/test1+  Ghc-Options:          -O2+  Main-Is:              Main.hs++flag chalkmark { Default: False }+Executable chalkboard-tests-chalkmark+  if flag(all) || flag(chalkmark)+    buildable:            True+  else+    Buildable:           False+  Hs-Source-Dirs:       .,tests/chalkmark+  Ghc-Options:          -O2 -auto+  Main-Is:              Main.hs+  +flag simple { Default: False }+Executable chalkboard-tests-simple+  if flag(all) || flag(simple)+    Build-Depends:        +    buildable:            True+  else+    Build-Depends:        base+    Buildable:           False+  Hs-Source-Dirs:       .,tests/simple+  Ghc-Options:          -O2+  Main-Is:              Main.hs++flag cbbe1 { Default: False }+Executable chalkboard-tests-cbbe1+  if flag(all) || flag(cbbe1)+    buildable:            True+  else+    Buildable:           False+  Hs-Source-Dirs:       .,tests/cbbe1+  Ghc-Options:          -O2+  Main-Is:              Main.hs+--   C-Sources: example1/img1.c+++flag example { Default: False }+Executable chalkboard-examples-example+  if flag(all) || flag(example)+    buildable:            True+  else+    Buildable:           False+  Hs-Source-Dirs:       .,examples/example+  Ghc-Options:          -O2+  Main-Is:              Main.hs++flag tutorial { Default: False }+Executable chalkboard-tutorial-basic+  if flag(all) || flag(tutorial)+    buildable:          True+  else+    Buildable:          False+  Hs-Source-Dirs:       .,tutorial/basic+  Ghc-Options:          -O2+  Main-Is:              Main.hs
+ examples/example/Main.hs view
@@ -0,0 +1,13 @@+import Graphics.ChalkBoard++main :: IO ()+main = startChalkBoard [] $ \ cb -> loop cb 0 (cycle colors)++loop :: ChalkBoard -> Float -> [O RGB] -> IO ()+loop cb n rgb@(c1:c2:c3:_) | n >= 0.999 = loop cb (n - 1) (tail rgb)+              | otherwise = do+  drawChalkBoard cb (choose (o (lerp n (unO c3) (unO c2))) c1 <$> rotate (n * pi) (scale (n * 1.1) square))+  loop cb (n + 0.01) rgb++colors :: [O RGB]+colors = [red,green,blue,yellow,cyan,purple,black,white]
+ server/Main.hs view
@@ -0,0 +1,5 @@+module Main where++import Graphics.ChalkBoard.Main (chalkBoardServer)+		+main = chalkBoardServer
− test/Makefile
@@ -1,31 +0,0 @@-cbtest=../dist/build/chalkboard-test/chalkboard-test--test:: chess.png chessfilm.png liam2.png sinwaves.png pattern.png arrows.png blank.png---# I look at these using % open *.png on osx.--%.png: %.ppm-	pnmtopng < $< > $@--chess.ppm:-	$(cbtest) chess-chessfilm.ppm:-	$(cbtest) chessfilm-liam2.ppm:-	$(cbtest) liam2-sinwaves.ppm:-	$(cbtest) sinwaves 50-pattern.ppm:-	$(cbtest) pattern-# takes a long time (for now!)-arrows.ppm:-	$(cbtest) arrows 500-blank.ppm:-	$(cbtest) blank	--# not *.ppm because we have the initial liam.ppm file.-clean::-	rm -f chess.png chessfilm.png liam2.png sinwaves.png pattern.png arrows.png blank.png-	rm -f chess.ppm chessfilm.ppm liam2.ppm sinwaves.ppm pattern.ppm arrows.ppm blank.ppm-
− test/liam.ppm
@@ -1,1287 +0,0 @@-P3-89 107-255-96 154 200 97 153 200 97 154 199 98 154 199 98 154 199 97 154 200 97 154 199 98 153 200 -100 153 200 97 155 199 98 154 200 98 154 200 98 154 200 99 154 199 99 154 199 100 155 201 -99 155 200 99 154 198 98 152 197 76 111 137 113 155 187 100 154 199 101 154 199 100 155 199 -101 155 198 103 154 200 103 155 197 103 155 197 103 155 198 103 155 199 103 156 200 103 155 201 -102 155 199 103 155 200 102 155 198 102 155 199 102 156 198 103 156 199 102 156 200 103 156 199 -102 156 198 102 156 200 102 156 198 102 156 199 104 155 200 104 156 199 104 156 199 104 156 198 -104 157 199 103 156 199 103 156 200 105 156 200 106 156 198 105 157 199 105 157 198 104 156 200 -104 156 201 103 156 199 101 156 202 102 156 201 102 157 199 101 157 200 102 156 201 101 156 200 -101 156 201 102 157 201 103 156 201 102 156 201 102 156 200 102 156 200 101 156 201 102 157 202 -102 156 201 103 156 202 103 156 201 103 157 202 103 157 202 101 157 201 102 157 200 103 156 201 -102 156 201 102 156 201 102 156 201 103 156 202 102 156 201 104 156 202 103 157 201 104 156 202 -103 157 200 -98 155 200 99 155 199 98 154 200 100 154 200 100 155 199 98 155 200 99 154 199 100 155 199 -99 155 201 99 155 200 100 155 200 99 154 199 100 155 200 100 155 200 101 155 201 101 156 200 -101 154 201 103 155 199 100 154 199 73 109 136 116 155 186 101 155 199 102 155 198 101 156 198 -102 155 199 102 155 199 103 155 197 103 156 199 103 156 200 104 156 198 103 156 198 103 156 199 -103 157 198 104 156 199 104 156 199 103 157 199 102 157 198 103 156 199 103 156 199 103 156 200 -103 156 199 103 157 199 103 157 198 104 156 197 106 157 198 106 157 198 105 157 198 106 157 198 -106 157 199 105 157 199 105 157 198 105 157 200 106 157 199 105 157 199 105 157 199 105 157 200 -105 157 201 104 156 200 103 157 200 104 157 201 103 158 200 102 158 200 103 157 202 102 157 202 -103 158 201 104 158 200 102 157 201 104 157 202 103 157 201 103 157 200 103 157 201 103 157 201 -103 157 200 103 157 203 104 157 202 104 157 202 104 157 203 104 157 202 103 157 201 102 158 202 -103 157 201 103 157 202 103 157 202 105 157 203 104 157 203 104 157 201 104 157 201 104 157 201 -103 158 199 -99 155 201 101 155 200 100 155 200 99 156 201 100 155 200 100 155 201 101 155 202 101 155 201 -102 156 201 99 157 201 99 156 200 101 155 201 102 156 200 101 156 201 102 155 200 102 156 201 -102 156 201 102 156 199 102 155 198 71 110 137 114 153 179 103 157 199 103 156 200 103 157 200 -103 156 198 103 157 199 105 157 199 104 157 199 103 157 201 104 157 200 103 157 200 103 157 199 -104 157 198 104 156 199 105 156 199 105 157 199 104 157 199 105 158 198 104 157 200 105 157 201 -104 158 198 106 157 199 106 158 199 107 158 198 110 157 197 109 157 197 107 158 197 108 157 198 -109 157 197 109 158 199 108 157 198 106 158 199 104 158 198 105 159 199 106 158 200 105 158 200 -105 158 200 105 158 199 104 158 201 105 158 201 105 158 202 104 158 200 104 159 199 103 158 201 -104 158 200 105 159 201 103 157 202 105 157 202 105 158 202 105 157 203 105 158 202 104 157 203 -104 158 202 105 158 202 105 158 203 105 158 203 105 159 201 105 158 202 105 159 202 104 157 201 -105 158 200 105 158 201 104 158 201 105 158 202 105 158 200 106 159 201 105 158 202 106 159 200 -105 159 200 -100 156 200 101 156 201 102 156 200 102 156 200 102 156 201 101 156 200 101 157 201 100 156 202 -102 156 201 102 156 202 102 156 201 103 157 200 102 156 201 102 157 202 102 157 200 103 157 200 -102 157 199 102 157 202 104 156 200 72 112 141 116 152 177 104 157 199 104 158 200 103 157 200 -104 158 199 104 158 199 104 158 199 105 158 201 104 157 200 104 158 200 104 158 199 106 157 198 -108 158 198 109 158 196 110 158 196 110 157 198 108 158 198 108 158 197 108 159 198 110 158 198 -115 160 193 118 159 193 113 159 195 111 157 196 111 158 196 111 158 195 111 158 194 110 158 195 -110 159 198 109 158 199 110 158 197 108 159 197 107 158 199 107 159 199 107 158 200 106 159 200 -106 159 201 107 158 201 107 158 202 106 158 201 106 159 203 106 159 201 106 159 200 106 159 201 -105 159 201 105 159 200 105 159 201 106 159 202 105 159 201 105 159 201 105 159 200 105 159 201 -106 159 201 107 159 202 106 160 201 108 159 202 106 159 202 105 159 200 106 159 201 106 160 200 -107 158 201 106 159 200 106 159 200 106 159 202 106 159 201 107 158 202 106 159 202 107 160 201 -106 159 200 -103 157 202 103 157 200 103 157 201 101 157 200 103 157 201 101 157 201 103 157 200 102 157 202 -103 157 201 104 158 200 104 157 200 104 157 200 102 157 202 105 157 201 104 158 200 104 158 199 -104 158 200 103 158 200 104 157 199 72 113 145 117 152 172 106 158 200 106 158 202 103 159 199 -105 160 200 105 159 198 106 159 199 105 158 201 108 158 200 109 159 197 113 159 196 119 159 194 -124 160 193 123 159 192 124 159 193 122 160 193 117 160 194 119 160 193 121 159 194 120 159 194 -119 159 194 116 159 194 114 160 194 112 160 195 110 160 197 111 159 197 111 159 198 111 159 198 -111 159 197 111 159 197 110 160 198 108 159 200 108 160 199 107 160 200 109 159 202 108 159 201 -108 159 201 106 159 201 107 160 200 108 159 201 106 161 202 106 160 201 107 159 202 106 160 201 -105 160 201 107 160 202 107 159 201 107 160 200 106 159 202 107 159 202 107 159 201 107 160 200 -107 160 201 110 160 200 109 160 201 110 160 201 108 160 201 108 159 202 108 159 202 108 160 202 -109 160 201 108 160 200 108 161 199 109 161 199 108 160 200 108 160 199 108 160 201 107 159 201 -107 160 200 -103 158 201 103 158 200 103 157 202 103 158 201 102 159 200 104 158 200 103 158 200 103 157 201 -105 158 202 106 158 201 104 158 200 104 158 201 104 158 201 105 158 202 106 158 203 105 158 201 -105 158 200 105 159 201 105 158 201 76 117 151 119 150 171 107 160 198 106 158 202 105 160 200 -105 160 200 106 159 199 107 159 200 110 159 199 114 159 196 118 160 194 121 161 195 123 162 193 -125 162 192 122 159 193 124 161 192 120 161 192 119 160 194 124 161 190 124 161 194 122 161 193 -118 159 193 113 159 196 111 161 198 111 160 197 111 159 199 110 160 198 110 160 197 111 160 197 -112 160 197 110 160 197 110 160 200 110 160 199 109 161 199 108 160 200 109 161 201 110 160 200 -110 160 202 109 161 203 107 160 202 109 161 202 108 160 202 108 160 202 107 161 201 106 161 201 -107 161 202 108 160 203 108 160 201 108 161 201 107 161 202 108 160 201 108 161 200 108 161 201 -110 160 200 111 160 201 110 161 199 110 161 200 108 161 199 109 160 202 110 160 201 110 160 201 -110 160 200 110 160 200 109 160 200 111 160 201 110 160 200 111 160 200 110 161 201 108 161 201 -108 161 201 -104 159 201 104 159 199 104 158 202 103 159 200 104 159 201 104 159 201 105 159 201 106 158 202 -105 159 200 106 158 202 105 159 200 105 159 201 107 159 200 106 159 201 106 159 201 107 159 201 -106 159 199 107 159 200 107 159 199 78 121 153 118 146 165 111 160 196 114 160 197 109 160 199 -107 159 201 108 161 200 109 160 199 111 160 197 112 160 197 112 159 196 113 160 196 112 160 195 -112 161 195 115 160 196 115 161 195 113 160 196 114 161 194 117 161 191 116 160 194 117 161 194 -115 160 194 112 160 197 110 161 198 110 161 199 110 161 199 110 160 199 110 160 198 110 161 200 -111 162 199 109 161 199 109 161 200 111 160 202 110 161 201 109 161 199 109 161 200 111 161 202 -109 161 201 109 161 202 109 161 203 109 162 202 107 161 200 108 161 203 108 161 201 109 161 201 -109 162 202 109 161 202 108 160 202 110 161 202 109 161 202 109 160 202 109 161 201 110 161 202 -112 160 201 111 160 201 111 161 200 111 161 198 109 161 200 111 160 200 109 160 202 110 160 200 -111 161 201 111 161 201 111 160 202 111 160 201 110 161 201 110 162 201 111 161 200 110 161 201 -110 161 201 -105 159 201 106 159 201 105 160 202 105 159 201 105 159 202 105 160 201 107 159 202 107 159 203 -106 160 201 106 160 200 107 160 200 108 160 200 107 159 199 108 160 200 107 160 200 107 160 201 -107 160 200 107 160 202 107 159 201 82 125 160 115 140 160 115 159 196 113 160 198 110 161 196 -110 160 198 111 160 197 112 160 199 112 161 197 111 160 199 112 160 197 111 160 196 111 160 197 -111 161 198 111 161 197 111 161 197 111 160 198 112 160 196 112 161 197 113 161 196 114 160 196 -113 161 196 113 161 198 111 161 199 111 162 200 111 162 199 110 162 199 110 162 199 110 162 199 -110 163 198 111 161 200 110 161 201 110 160 203 111 161 201 112 161 200 112 161 202 109 162 201 -109 161 201 110 161 202 109 161 202 110 162 202 110 162 202 110 162 202 109 162 201 108 161 201 -110 162 202 110 161 202 110 162 201 109 161 202 110 162 202 110 161 202 111 161 201 112 161 201 -112 161 199 111 162 200 111 162 198 110 162 199 111 161 200 111 161 201 111 161 198 111 161 199 -112 161 199 111 161 198 112 160 199 112 161 198 109 161 198 110 162 197 111 161 196 111 161 197 -110 161 198 -107 160 200 107 160 201 107 160 202 107 160 202 107 160 202 105 159 201 107 160 201 107 160 201 -107 160 201 109 160 201 109 160 200 109 159 200 109 161 200 109 160 199 108 161 200 108 161 200 -109 161 200 109 160 200 110 160 199 85 129 163 111 138 154 114 159 197 112 160 199 111 161 198 -111 161 198 112 161 198 111 161 200 110 160 198 111 161 198 110 161 197 109 161 198 111 161 199 -111 161 198 111 161 199 111 161 197 112 161 196 113 160 197 113 161 197 112 161 198 112 162 198 -112 162 198 112 162 198 111 162 198 111 161 199 111 162 200 112 162 199 111 163 196 111 162 197 -110 163 198 111 161 197 112 161 196 110 161 197 110 162 196 110 161 195 111 159 195 110 159 193 -108 158 190 106 156 189 105 155 186 103 153 184 103 151 180 100 149 176 98 148 174 96 145 172 -95 142 169 94 140 164 92 137 161 89 136 157 87 132 155 86 129 152 85 127 149 82 124 145 -80 122 141 79 120 135 75 118 132 73 115 131 73 111 129 70 110 126 70 107 123 72 109 123 -69 104 121 66 101 116 63 98 113 61 95 108 58 94 105 58 91 104 58 90 102 56 86 99 -55 85 98 -106 161 202 106 161 201 107 161 200 107 161 201 107 160 201 108 160 202 108 161 201 108 161 200 -109 161 201 108 161 200 109 161 200 109 161 200 109 161 199 109 161 198 108 161 200 109 161 200 -109 161 201 110 161 201 109 161 198 89 133 166 110 137 149 115 162 195 111 160 199 112 161 198 -111 160 198 110 161 198 110 160 198 111 161 195 111 161 195 112 161 195 112 161 192 110 160 191 -109 159 190 108 157 188 107 155 184 105 154 181 103 151 178 102 149 174 99 146 170 97 142 166 -94 139 161 92 135 156 87 131 152 85 126 144 81 122 141 77 118 134 74 114 129 72 109 124 -67 104 118 65 102 113 65 100 112 53 85 98 50 79 90 46 75 85 45 71 81 43 67 74 -40 63 72 38 57 68 36 56 62 37 54 61 37 51 57 37 50 57 36 49 56 33 47 53 -41 56 62 38 47 55 40 48 54 39 49 54 40 47 53 40 48 52 42 48 52 44 48 55 -46 50 57 49 51 55 47 52 55 48 53 56 50 54 60 48 52 58 45 51 56 43 50 54 -44 50 55 45 50 56 47 51 57 46 52 58 47 54 57 50 54 59 53 54 60 52 55 60 -55 56 61 -108 162 201 109 162 199 109 161 199 108 161 199 109 161 199 109 161 198 109 160 197 111 160 197 -110 159 194 110 159 195 111 160 194 109 159 190 108 156 191 107 156 186 103 153 182 102 150 178 -100 148 175 96 145 172 92 142 164 78 117 137 84 105 113 89 127 145 82 123 143 77 118 137 -74 113 129 68 107 122 66 103 115 59 98 107 56 91 100 53 85 94 50 79 86 46 74 80 -41 67 75 37 62 70 44 67 72 35 55 61 34 50 55 36 48 56 34 46 53 35 47 50 -37 45 51 40 46 51 42 48 53 42 48 54 43 49 55 47 50 56 50 53 55 52 54 59 -53 56 59 51 54 56 54 59 62 64 67 68 71 73 74 72 73 75 70 70 72 75 73 76 -75 74 76 78 76 76 81 80 78 83 82 81 88 85 84 90 87 86 87 86 85 91 89 88 -98 93 93 101 96 95 104 99 97 108 105 101 111 107 103 110 107 102 114 110 105 117 112 106 -118 114 109 120 115 109 121 117 111 121 118 110 124 118 113 122 118 111 121 116 110 118 112 105 -107 103 97 113 110 104 116 112 107 117 114 107 117 115 105 117 115 107 122 116 109 122 115 110 -122 118 112 -89 137 162 86 132 153 81 126 147 79 121 140 75 116 134 74 113 130 66 105 119 61 98 110 -53 86 96 52 83 94 48 78 87 45 73 80 43 67 74 39 62 68 38 57 63 37 54 57 -37 50 55 37 47 53 36 46 51 36 46 49 40 47 52 46 54 60 44 49 56 47 50 56 -51 53 58 53 57 58 56 59 61 55 59 60 61 62 65 65 66 67 70 71 72 76 76 76 -82 81 81 85 84 83 94 90 91 98 95 92 103 100 96 108 103 98 110 107 101 113 111 103 -115 112 104 117 114 109 118 115 108 121 116 110 120 116 109 120 117 111 121 117 111 122 118 111 -125 121 113 126 122 116 125 121 114 128 124 115 130 126 115 132 127 118 123 119 112 126 123 114 -127 123 113 126 121 111 126 123 111 127 123 113 130 125 115 127 125 115 129 126 116 128 126 116 -129 126 117 128 126 116 127 124 114 128 124 116 126 123 113 125 123 111 125 122 111 126 123 113 -128 125 115 127 123 113 126 123 114 125 122 110 128 124 115 129 126 115 129 125 115 127 123 112 -121 117 109 125 122 112 124 122 110 125 123 111 125 122 111 122 120 109 125 122 111 126 122 112 -125 122 111 -40 49 56 41 49 54 46 49 57 48 52 58 48 53 58 50 56 59 56 59 62 59 60 64 -67 68 69 72 73 73 74 75 75 77 78 79 82 80 80 90 88 88 96 94 92 100 98 95 -103 101 97 107 104 102 112 108 102 111 107 102 116 111 105 121 116 110 122 118 112 126 120 113 -126 121 115 127 122 114 128 124 115 124 121 111 128 124 117 130 126 117 131 127 119 131 126 117 -133 128 120 133 129 119 131 128 117 133 130 118 134 130 121 133 129 118 132 129 116 133 129 118 -132 129 118 135 131 120 135 130 119 133 129 119 133 129 117 132 129 118 131 128 117 129 126 114 -132 128 117 133 130 118 131 128 118 132 129 119 131 129 117 132 130 119 124 121 110 128 126 113 -126 126 113 128 125 113 128 124 113 128 124 114 128 125 113 129 125 114 129 126 114 128 125 113 -127 124 114 127 125 114 125 122 111 126 124 112 126 124 112 127 123 112 124 120 110 125 121 112 -126 122 112 126 123 113 127 123 114 126 123 113 127 125 113 130 126 116 130 125 115 128 124 113 -121 117 107 127 123 112 125 122 112 126 122 113 127 123 114 124 123 112 124 121 110 125 121 110 -125 121 110 -102 101 96 110 107 102 117 112 108 121 116 110 121 118 111 124 121 115 126 124 114 129 124 114 -131 127 118 133 129 120 132 129 120 132 127 121 131 127 118 131 128 118 132 128 117 133 129 119 -132 129 118 132 128 117 134 130 118 135 131 119 133 131 119 134 131 119 135 132 121 134 131 119 -133 130 119 133 130 118 134 130 119 128 125 115 132 129 118 133 129 119 133 129 119 134 130 120 -134 131 120 133 131 118 132 130 118 132 129 117 133 129 117 133 128 117 131 128 117 133 129 119 -133 129 117 135 131 120 134 130 119 134 131 120 135 131 120 133 129 117 132 129 117 129 127 114 -132 129 117 132 129 117 130 127 115 132 129 117 131 129 117 132 129 118 126 121 111 128 125 114 -128 126 113 129 126 114 128 124 114 130 126 117 128 125 113 130 125 116 129 125 113 128 125 114 -129 125 115 129 126 115 126 122 111 127 124 113 127 123 112 129 125 114 126 122 111 127 122 111 -125 123 112 125 122 112 126 123 113 125 122 113 126 125 114 128 125 116 128 122 113 128 124 113 -120 115 105 128 124 112 127 123 114 126 120 111 124 123 112 124 121 111 126 121 113 125 122 111 -125 121 111 -129 126 113 133 129 118 134 130 120 134 131 120 134 130 119 134 131 120 132 130 118 135 131 118 -134 131 119 135 133 120 135 133 121 134 130 119 133 130 120 134 130 119 131 129 117 134 132 117 -134 133 120 134 132 118 135 132 120 134 132 120 135 132 120 135 131 119 135 132 120 135 130 119 -135 130 119 133 129 117 135 131 120 128 124 114 132 129 117 132 129 118 133 129 118 133 129 118 -133 129 117 131 128 117 130 128 117 133 129 118 132 128 117 132 128 117 133 129 117 133 130 118 -134 130 120 132 129 118 132 129 117 133 129 116 135 130 118 136 131 120 133 128 118 132 128 118 -132 128 117 133 129 118 131 129 117 131 129 117 131 128 116 132 128 119 125 123 113 129 126 115 -131 126 115 131 126 115 128 124 113 128 125 113 127 124 113 128 125 114 129 126 113 128 124 112 -129 126 114 128 126 114 126 123 112 128 124 114 127 124 112 128 124 113 128 125 112 128 124 113 -126 123 113 127 123 113 127 122 113 126 122 113 128 124 114 128 123 114 128 124 113 127 123 112 -120 115 105 126 121 111 127 123 113 126 122 110 125 121 112 123 119 111 124 119 110 123 119 109 -125 122 111 -130 128 116 134 131 120 133 132 121 133 131 119 134 130 119 135 131 120 134 130 119 135 133 119 -134 131 119 133 131 118 137 133 122 135 131 120 133 130 119 133 130 119 134 129 118 134 130 118 -135 132 120 135 132 119 136 133 121 136 132 120 136 132 121 135 132 118 134 132 119 135 131 119 -135 131 119 133 129 118 135 131 120 129 125 113 133 129 118 132 129 117 133 128 118 133 129 117 -132 129 116 131 128 116 132 128 117 130 127 116 125 124 113 118 118 106 120 118 107 112 111 102 -107 107 98 108 107 99 116 113 103 114 109 100 122 119 108 132 128 117 132 128 117 132 128 118 -135 129 119 131 128 115 132 129 118 132 128 117 131 127 116 133 128 116 125 122 109 130 126 114 -132 128 117 130 126 115 129 125 114 129 126 115 130 124 114 129 125 115 126 124 111 126 123 111 -128 124 113 126 123 112 126 123 111 128 124 114 127 124 112 128 124 112 128 124 113 126 122 110 -126 124 112 127 123 111 126 122 109 125 122 111 127 123 112 127 123 111 126 123 111 127 123 111 -119 114 104 125 119 109 125 121 110 124 121 110 123 120 110 124 120 109 123 119 108 122 118 109 -122 118 108 -132 129 116 133 131 119 135 133 122 135 133 123 135 131 120 134 130 119 135 132 120 135 132 120 -134 130 118 133 129 118 137 133 122 135 132 120 134 131 120 132 130 118 133 129 118 133 130 118 -133 129 117 136 131 120 135 133 120 137 132 121 136 132 120 135 131 119 135 131 119 134 131 118 -135 132 118 134 131 118 134 130 119 128 124 112 134 130 117 135 129 118 133 129 117 132 129 116 -131 128 114 127 126 113 121 118 110 105 102 98 85 83 81 77 72 69 71 64 62 73 64 63 -86 71 69 87 73 72 95 81 79 98 79 76 105 90 84 118 106 97 123 113 104 120 114 105 -130 126 115 133 128 116 132 129 116 132 129 118 133 127 115 134 130 116 124 122 110 130 126 113 -130 126 114 129 125 114 129 125 114 130 125 114 129 126 115 129 125 114 128 125 112 126 123 111 -129 125 113 127 123 111 127 124 112 128 124 112 127 122 112 127 123 111 127 124 112 125 121 111 -125 122 111 125 121 110 125 122 110 124 120 109 125 122 110 126 122 110 125 121 109 125 121 109 -117 113 102 120 117 106 123 120 109 122 118 108 122 118 107 120 117 107 121 117 105 121 117 105 -121 117 105 -132 128 115 133 130 119 135 133 120 136 133 122 134 131 120 135 132 121 135 133 120 134 131 118 -134 130 118 134 131 119 137 134 122 135 133 118 133 131 118 133 130 116 134 130 117 133 130 118 -134 130 117 134 130 118 136 132 119 136 132 120 137 132 120 135 132 119 136 131 119 135 132 118 -136 132 119 133 130 116 134 130 117 131 126 114 132 129 116 133 130 115 134 130 118 133 129 118 -119 117 107 91 87 84 84 75 75 76 66 67 70 60 58 83 68 66 91 69 63 83 64 59 -98 75 69 98 76 71 97 79 68 101 82 74 103 83 75 129 106 95 134 111 101 126 106 97 -115 101 92 123 118 108 132 129 116 133 128 116 133 129 116 134 131 117 126 122 110 130 125 113 -130 125 114 130 124 113 129 124 112 128 124 111 130 125 111 130 125 114 128 124 112 127 123 112 -128 123 112 127 124 109 126 123 112 126 122 109 127 123 113 127 123 110 127 122 111 127 122 110 -125 121 110 125 121 109 126 120 109 126 121 109 127 121 110 126 121 110 125 121 109 125 121 109 -117 114 102 123 119 107 122 119 107 123 119 108 122 118 106 120 117 104 121 117 106 120 117 104 -120 116 104 -134 130 116 132 129 116 136 132 121 136 133 121 136 133 120 135 132 119 134 131 118 135 132 118 -135 131 116 133 129 117 138 133 121 137 133 120 134 130 119 133 130 116 133 131 118 134 129 119 -133 129 118 136 132 120 136 131 119 137 132 120 136 133 119 135 132 119 136 132 120 138 134 120 -137 133 120 133 132 118 134 131 117 130 127 112 131 128 114 132 128 116 131 127 118 129 121 115 -114 106 105 93 82 79 85 70 66 74 60 57 74 59 56 96 72 66 107 81 73 102 77 68 -102 77 66 109 82 73 110 86 76 108 84 73 135 110 97 143 118 102 169 143 129 140 113 102 -137 111 103 130 111 103 140 130 120 134 129 116 132 130 117 137 130 118 128 123 111 130 127 113 -132 127 115 131 126 113 130 124 113 128 123 111 130 125 113 131 126 114 129 125 112 129 125 112 -128 124 114 127 124 109 127 124 112 127 123 112 128 124 111 129 124 111 129 123 113 127 123 112 -126 122 111 128 123 111 126 121 111 126 121 110 127 122 111 128 122 110 127 122 110 127 120 109 -116 114 102 121 118 106 122 118 107 124 120 108 121 118 105 121 118 106 120 117 105 121 116 105 -121 117 105 -133 130 117 133 128 117 135 133 118 136 133 119 136 132 120 136 132 121 136 132 120 137 133 119 -135 131 117 135 129 117 137 133 119 136 133 120 135 131 119 134 130 116 134 130 117 135 130 117 -135 131 119 135 132 119 134 132 118 135 131 119 134 130 119 136 132 119 134 132 118 135 132 119 -135 131 116 134 130 118 135 130 118 131 126 114 132 127 115 133 128 118 139 130 121 145 134 125 -130 123 113 134 120 113 116 101 94 86 68 62 90 66 61 102 77 68 112 84 72 116 89 77 -114 86 75 121 94 82 125 101 88 134 110 97 137 111 95 161 135 117 189 164 146 170 144 130 -169 144 130 168 146 135 173 152 140 156 145 135 138 132 120 135 131 118 127 123 112 131 127 115 -133 128 115 133 127 115 130 125 113 128 125 111 129 125 112 130 126 113 130 125 111 128 125 113 -130 125 112 130 124 111 127 123 111 128 123 112 130 124 112 127 122 110 128 123 111 129 122 111 -128 120 110 128 123 112 128 121 111 128 122 111 127 122 110 126 122 110 125 122 108 128 121 109 -118 112 101 121 117 106 123 120 108 123 120 109 121 117 107 120 116 105 118 114 102 120 115 103 -121 116 104 -133 131 117 132 130 116 135 132 119 136 132 120 136 132 120 136 132 119 137 134 122 137 134 122 -136 132 120 135 129 117 135 131 119 138 132 120 135 131 118 134 131 118 135 131 119 134 131 117 -133 130 115 135 132 119 134 131 119 136 132 119 136 131 119 134 131 117 136 132 118 135 131 120 -136 134 117 134 132 118 135 131 118 133 129 116 119 117 109 113 108 102 98 94 87 88 83 75 -130 121 110 139 126 115 142 127 117 123 102 96 106 78 72 106 78 69 109 81 69 126 97 84 -128 100 88 133 106 94 158 135 119 171 145 129 187 161 146 182 156 138 198 176 160 220 201 187 -216 197 184 217 201 187 211 195 181 198 180 166 182 171 160 137 131 120 130 124 111 132 128 114 -132 128 115 131 127 114 130 126 111 128 124 111 126 123 109 129 125 111 129 125 110 128 123 111 -129 125 111 130 124 113 128 125 112 128 122 109 130 124 112 128 124 109 127 123 111 129 123 112 -127 121 107 126 121 108 125 121 109 126 121 110 126 122 110 126 124 109 127 122 110 126 120 107 -118 113 101 121 117 105 121 117 104 123 118 106 122 116 104 119 115 104 118 113 101 121 115 103 -120 115 103 -137 132 117 132 128 115 135 132 119 135 132 118 136 133 118 136 132 119 135 132 118 136 133 120 -137 133 120 134 130 117 136 132 119 137 132 120 137 133 118 135 131 119 135 131 119 137 133 118 -136 131 118 135 132 117 136 133 118 136 132 118 137 131 118 135 130 116 138 132 117 135 131 118 -136 133 118 135 132 118 134 130 116 114 114 105 78 78 77 65 63 63 62 58 58 74 64 63 -97 85 76 94 77 70 115 97 88 133 112 106 117 93 88 116 84 77 119 87 75 137 108 94 -146 119 104 152 125 112 193 171 152 203 182 166 213 195 177 231 215 201 240 225 209 249 239 222 -246 236 221 229 217 201 237 227 212 227 213 197 229 215 200 177 165 156 129 124 112 133 127 114 -133 128 113 133 129 116 133 127 113 129 125 112 128 124 111 129 124 112 128 124 112 127 123 111 -129 124 111 129 124 109 127 123 111 128 123 112 129 123 108 128 123 110 128 124 112 128 122 111 -125 121 106 124 120 107 125 121 109 126 120 107 127 122 110 125 121 108 125 121 108 124 119 106 -118 114 102 119 115 102 121 116 103 119 115 102 113 109 98 103 104 90 94 95 82 85 87 74 -74 77 63 -138 135 118 133 129 114 137 133 120 135 132 118 135 132 116 134 131 118 135 132 115 136 133 117 -136 134 118 134 131 118 135 132 118 137 134 120 136 133 118 134 131 117 136 132 119 137 132 119 -135 130 118 137 133 119 136 132 118 137 133 120 136 131 118 135 130 117 136 131 119 135 131 117 -134 133 116 135 132 117 128 125 113 71 75 76 55 54 60 53 49 53 56 50 54 73 59 60 -91 73 69 102 82 78 120 100 93 152 127 120 168 141 132 171 141 132 164 130 122 154 121 109 -169 138 120 193 167 150 203 183 163 240 228 211 227 211 197 241 226 211 238 222 209 230 215 199 -234 219 203 236 221 206 240 227 212 241 227 209 227 213 196 223 208 195 151 143 133 132 126 115 -133 128 113 131 127 114 132 126 113 130 125 110 129 125 109 128 125 112 128 125 111 129 123 110 -127 123 109 128 124 110 126 122 110 126 122 110 128 124 109 128 122 110 128 123 111 128 123 109 -125 120 106 125 122 109 121 118 105 120 116 102 111 110 96 102 102 90 92 93 81 84 85 73 -68 71 62 55 58 50 41 47 40 29 34 31 21 26 25 15 22 21 12 18 19 13 17 20 -11 15 19 -138 135 120 130 128 112 136 133 117 135 134 118 135 132 117 135 132 116 136 132 118 136 133 117 -135 132 116 132 129 115 135 132 116 137 133 120 135 133 116 134 131 117 135 132 119 136 132 120 -136 131 117 136 131 120 136 131 116 133 131 116 134 130 116 133 129 115 133 129 115 135 130 118 -134 130 116 134 129 116 103 104 97 55 57 64 58 56 67 55 54 64 67 59 63 94 79 76 -114 95 88 124 102 96 131 109 104 149 123 115 166 138 125 177 147 135 188 159 145 194 165 149 -197 168 154 200 175 157 211 190 172 227 212 193 240 225 213 229 213 201 231 214 204 226 208 198 -215 198 182 218 201 183 235 220 204 220 205 187 222 207 188 215 201 184 174 163 149 132 126 113 -132 128 113 132 126 113 131 124 111 129 123 108 129 123 108 128 123 110 129 124 110 127 123 108 -128 123 111 127 122 108 121 119 103 116 113 99 109 109 92 101 101 84 91 91 76 79 79 64 -65 67 54 52 53 44 38 39 33 26 28 25 17 21 21 14 19 19 13 19 20 14 18 19 -13 16 19 15 16 22 16 16 22 17 18 24 27 26 31 37 36 38 49 46 44 54 51 51 -30 32 34 -137 135 117 130 127 112 135 132 118 135 132 117 134 132 116 135 132 118 135 132 119 135 132 116 -135 130 114 132 129 113 134 130 115 135 131 118 136 133 116 136 132 116 135 131 116 134 131 117 -134 131 114 133 129 114 134 130 115 134 130 116 135 129 117 133 128 115 134 129 114 134 129 114 -132 129 113 128 125 112 79 82 78 66 65 73 63 62 73 61 60 70 72 61 68 98 83 82 -119 100 96 128 107 102 137 114 108 145 124 116 156 130 117 165 137 126 183 155 142 196 167 154 -204 179 165 208 185 172 213 194 182 225 208 199 232 215 205 232 215 207 231 213 205 228 210 201 -219 199 187 202 179 160 213 196 174 214 198 180 198 181 159 213 198 182 184 169 156 130 124 111 -129 124 111 125 123 109 122 121 103 114 113 97 106 105 89 97 97 83 88 88 78 76 78 66 -62 65 55 48 51 42 33 37 30 22 26 22 18 22 19 16 20 19 16 18 21 18 18 21 -19 18 23 18 18 23 17 20 22 24 24 25 35 34 34 51 47 47 66 61 58 77 72 69 -87 81 78 93 86 80 104 98 91 112 106 97 116 109 99 117 110 99 114 108 98 74 74 70 -39 46 45 -139 134 120 132 127 111 136 132 118 134 131 116 135 131 117 136 131 117 134 131 116 133 130 116 -132 130 113 131 129 113 132 129 112 134 131 114 134 131 116 134 130 114 133 130 112 132 130 114 -131 130 112 133 129 114 134 130 114 134 129 116 132 128 116 131 127 114 131 128 114 131 128 112 -132 129 113 127 124 113 68 69 68 70 69 74 66 63 72 61 57 65 67 60 65 85 73 74 -108 92 88 120 103 98 127 108 102 133 115 107 146 123 116 161 133 124 176 148 137 188 159 147 -198 173 160 205 183 170 213 193 183 221 204 195 228 210 203 230 213 203 229 210 200 225 206 195 -221 199 187 203 176 161 187 162 140 198 179 159 188 166 146 185 167 147 184 168 152 93 92 79 -63 65 56 48 51 43 33 37 29 24 26 23 19 22 21 19 20 20 18 20 23 18 19 22 -17 18 22 19 19 23 25 25 25 34 34 32 48 45 44 63 60 55 75 70 66 88 81 75 -97 91 83 104 98 89 112 106 96 115 110 99 120 114 103 123 117 105 123 118 104 123 119 105 -123 116 104 116 110 98 123 117 105 123 117 104 122 117 104 115 109 98 72 72 68 40 47 47 -40 45 46 -139 133 119 131 126 113 136 130 115 134 130 116 133 129 116 135 130 116 132 130 116 130 128 113 -131 127 113 131 128 111 131 128 111 130 128 112 132 129 114 131 129 113 131 128 112 132 128 115 -131 128 114 131 127 114 132 128 113 132 128 114 132 127 114 130 126 112 130 126 112 131 128 113 -131 128 113 120 118 107 67 64 63 72 68 75 69 62 69 65 58 62 67 56 61 77 64 68 -92 78 80 104 89 89 111 95 91 116 98 94 134 112 106 153 127 118 163 138 127 175 148 137 -185 160 147 196 172 158 205 184 170 214 195 185 224 205 195 227 208 197 225 205 194 224 203 190 -219 197 184 203 178 160 172 144 125 164 140 117 174 152 131 165 141 123 164 146 130 41 38 35 -22 23 24 24 22 22 31 29 26 43 39 36 56 52 47 71 66 59 82 76 68 91 84 77 -97 94 85 106 100 89 109 105 93 111 107 94 114 109 96 116 112 98 118 113 99 115 111 96 -113 110 94 110 108 89 112 108 91 106 105 90 103 102 87 99 97 82 97 96 80 94 92 76 -88 88 75 82 83 65 86 84 69 83 81 67 78 77 64 56 56 48 28 31 28 26 28 27 -26 27 27 -138 132 119 129 126 111 132 130 115 134 130 115 132 129 113 133 130 115 132 128 114 131 126 110 -130 127 109 129 125 111 129 126 110 131 127 112 131 126 113 130 127 111 131 126 112 132 127 115 -130 126 113 130 127 114 130 126 112 130 127 112 129 126 112 129 125 113 129 125 111 130 126 112 -129 126 111 115 111 101 72 63 61 78 70 73 73 63 67 70 59 63 70 57 62 72 58 63 -78 63 66 85 72 74 90 76 76 98 82 81 119 98 95 137 113 108 149 124 115 155 130 121 -167 140 129 179 152 141 191 163 151 205 181 167 214 194 181 220 200 189 221 200 189 219 197 183 -213 192 177 202 176 157 167 138 120 145 118 96 159 134 113 155 132 114 143 125 110 42 36 31 -50 48 40 57 54 45 62 61 49 67 63 51 66 64 51 63 63 50 60 61 48 55 55 44 -49 51 38 44 45 34 38 39 28 33 33 24 30 30 22 28 27 19 24 25 16 21 22 14 -21 21 14 19 18 10 17 16 11 15 15 11 15 14 10 14 14 11 13 13 11 14 12 11 -13 12 11 13 12 10 13 12 11 12 11 10 11 12 11 12 10 9 12 10 9 11 9 10 -11 9 10 -135 130 114 129 125 111 130 127 113 131 127 110 128 125 112 129 125 111 128 125 110 127 125 108 -125 123 108 125 123 107 127 125 107 128 126 110 129 126 110 128 126 110 126 124 111 127 126 108 -128 125 110 127 125 109 127 124 107 125 124 106 127 124 107 123 122 105 120 118 100 119 118 99 -116 115 98 105 104 92 72 62 58 82 71 72 78 65 68 75 60 61 75 59 61 76 58 60 -76 61 62 78 62 65 78 63 66 82 66 69 99 80 79 117 95 91 127 105 99 135 112 105 -147 121 114 160 134 124 173 144 134 190 162 150 206 183 169 214 191 178 215 192 180 212 190 176 -208 185 169 200 173 155 164 136 119 137 108 89 146 119 97 152 130 111 125 110 100 33 26 25 -21 14 13 19 15 13 18 13 12 18 14 13 17 13 13 17 12 13 16 13 12 16 12 12 -16 12 12 17 12 12 16 12 11 16 12 11 15 12 12 15 12 12 15 11 13 16 12 12 -15 12 12 16 11 10 17 11 13 16 11 13 14 12 12 14 12 11 14 12 12 15 12 13 -13 12 13 14 12 12 13 11 12 13 11 11 14 11 12 13 11 12 14 11 12 14 11 12 -14 11 12 -129 126 111 124 122 108 122 121 107 122 120 101 121 119 103 116 115 98 114 114 95 108 109 90 -106 105 87 98 98 81 97 97 78 95 96 78 93 94 77 88 88 70 83 82 66 77 77 59 -70 72 54 63 63 47 57 58 42 51 53 39 48 49 36 43 45 34 38 40 27 34 36 26 -30 31 25 44 43 38 69 60 54 84 72 69 83 68 69 78 62 62 79 59 59 79 58 57 -80 59 60 79 61 62 79 61 64 82 63 66 90 68 70 101 79 79 111 89 84 115 92 87 -126 102 95 142 116 109 157 129 121 175 148 136 196 170 156 204 180 164 207 183 168 206 182 167 -205 180 165 195 167 150 166 136 122 136 104 87 143 112 93 152 127 110 110 97 90 34 26 27 -23 16 18 21 16 16 21 15 16 21 15 17 21 15 17 20 15 17 20 14 15 20 15 15 -18 15 15 18 14 15 18 15 16 16 14 14 12 11 11 13 12 12 13 12 12 12 11 10 -12 11 11 12 10 11 11 10 10 11 10 11 11 12 11 15 14 14 16 14 15 16 12 13 -15 14 14 15 13 14 16 13 14 16 13 14 15 12 13 14 12 13 13 13 13 13 12 13 -15 12 13 -59 60 44 53 54 39 46 47 32 41 42 28 39 37 25 31 31 19 30 28 17 29 25 18 -26 23 15 26 22 16 23 21 15 31 27 21 48 42 40 37 33 31 22 17 14 22 17 17 -20 18 18 18 18 18 17 17 18 15 17 19 16 18 22 14 18 23 13 18 21 14 18 21 -15 17 21 35 33 32 66 56 49 80 69 65 86 70 70 81 64 61 82 61 58 83 59 56 -83 60 57 82 61 59 82 62 62 81 63 63 83 65 62 89 70 69 97 74 75 99 77 74 -106 81 76 123 96 88 141 113 105 161 133 122 187 157 146 200 173 158 205 179 165 204 179 163 -204 181 164 194 167 150 164 135 118 142 111 91 147 117 96 147 122 102 95 83 76 20 17 17 -25 18 20 22 18 18 24 18 19 23 17 18 23 17 18 22 17 18 21 16 18 21 16 17 -21 15 17 19 16 17 21 16 18 17 14 15 9 9 9 8 9 9 9 10 10 10 10 10 -10 11 11 10 12 13 11 12 12 11 10 13 10 9 10 17 13 16 18 15 16 19 14 16 -17 14 15 17 15 16 15 14 15 15 14 14 16 14 16 16 13 15 15 13 13 14 13 15 -14 12 13 -22 19 19 23 19 19 22 19 19 20 20 21 22 21 21 24 23 24 25 24 26 23 23 25 -25 25 27 28 27 28 32 30 30 40 37 35 27 27 24 62 61 59 20 20 19 16 16 18 -15 17 20 14 17 18 16 16 18 15 18 20 16 18 19 17 18 19 17 18 19 17 18 18 -18 18 17 31 28 24 64 51 47 78 65 62 87 72 71 82 66 63 78 60 58 80 59 55 -81 58 55 82 61 58 84 62 58 84 63 62 83 63 62 86 66 62 90 69 68 91 69 70 -99 71 72 114 89 84 138 110 105 161 133 126 186 157 148 203 179 167 208 185 172 204 182 167 -206 184 169 200 174 159 170 138 121 148 115 96 151 122 100 151 127 109 85 78 71 19 18 19 -26 20 21 25 20 21 26 19 21 25 19 21 24 18 19 24 17 18 24 18 20 21 17 18 -22 17 17 23 17 18 22 16 18 20 16 17 10 10 11 10 11 13 9 12 14 14 15 18 -14 21 19 20 25 27 22 28 26 15 19 21 8 10 11 17 14 15 19 17 17 19 15 16 -19 16 17 18 14 15 16 14 16 17 15 15 17 13 15 16 14 15 17 13 14 18 13 15 -17 13 14 -15 18 23 15 18 22 15 19 21 16 19 23 16 19 22 20 21 24 20 23 24 20 21 22 -23 24 24 26 25 25 37 35 34 24 23 23 16 19 20 16 16 16 14 14 16 16 16 18 -17 17 18 15 17 17 16 16 16 14 15 17 14 14 16 12 14 14 12 12 14 13 14 15 -14 16 17 23 23 24 64 49 44 79 65 63 86 74 76 79 65 65 74 56 57 74 54 54 -76 53 54 79 56 54 82 59 54 84 61 59 84 62 63 86 64 63 90 67 62 91 67 65 -99 74 73 116 88 81 141 115 106 176 149 141 200 178 169 210 190 180 213 194 183 212 192 180 -214 193 182 212 190 178 182 150 135 154 121 101 144 114 94 146 120 100 83 75 70 20 18 18 -27 21 20 27 20 22 27 21 23 25 19 21 24 18 20 26 19 21 24 19 21 23 18 19 -23 19 20 23 19 20 23 17 19 20 16 18 10 11 12 9 10 13 8 12 13 13 16 18 -19 25 25 20 27 27 21 28 26 16 20 21 9 10 11 18 14 15 18 16 17 20 16 18 -19 15 16 17 16 16 17 14 16 17 14 16 18 14 16 17 13 15 16 13 15 16 14 15 -16 13 14 -19 20 21 18 19 19 18 20 19 17 18 19 18 18 18 16 16 18 16 17 16 16 18 17 -15 18 18 17 19 18 36 33 32 27 27 27 14 16 20 19 19 20 14 14 15 21 24 26 -31 34 36 26 29 29 29 30 29 30 31 32 28 32 29 20 21 21 13 13 16 21 22 25 -27 28 28 31 33 33 64 54 48 80 70 68 84 75 77 76 63 62 73 52 50 73 48 45 -75 48 44 79 52 45 80 55 48 82 60 55 84 62 59 85 63 61 89 64 61 93 64 59 -95 65 56 98 66 59 108 78 68 136 108 96 177 152 138 205 183 168 214 196 184 217 200 190 -220 201 190 219 199 187 198 171 158 155 123 106 143 110 91 130 103 83 77 68 63 20 18 18 -27 22 23 27 22 23 25 21 21 27 20 22 26 20 22 27 19 22 24 20 22 24 20 21 -24 18 20 24 19 21 23 18 20 20 16 19 10 11 13 9 11 12 10 11 13 11 13 15 -11 16 17 13 18 17 14 19 20 13 16 19 9 10 10 18 15 17 19 17 17 18 15 17 -17 17 17 17 15 16 17 15 16 17 15 16 17 14 16 18 14 18 17 13 16 15 13 15 -15 14 14 -16 20 21 17 20 21 18 21 23 17 21 22 17 20 21 12 14 16 14 15 17 18 21 22 -19 24 23 21 23 25 37 33 33 27 25 26 12 14 16 22 24 27 14 15 16 31 34 36 -46 50 52 38 42 45 37 42 43 36 41 43 33 39 41 23 25 28 13 14 17 20 24 27 -28 33 36 33 38 37 68 57 53 83 73 73 84 73 75 79 60 58 80 53 50 76 52 49 -74 49 47 73 48 43 78 55 46 83 60 53 84 60 56 86 61 61 87 64 61 92 65 59 -90 61 55 88 58 56 91 62 61 101 71 67 129 99 87 172 143 129 203 181 168 215 199 188 -223 205 196 223 202 191 204 178 164 156 124 106 161 124 104 186 151 133 161 137 132 32 24 26 -30 22 23 29 21 25 28 22 24 27 20 23 25 21 22 26 20 22 24 20 21 23 19 20 -25 18 20 23 19 20 21 19 18 20 17 19 9 11 14 9 10 14 9 11 13 11 12 15 -10 11 13 9 11 13 8 12 14 10 11 12 9 10 10 18 15 18 20 16 16 21 16 19 -18 15 17 18 16 17 18 15 17 18 15 16 17 15 16 17 14 15 17 14 15 15 14 16 -15 14 14 -14 17 18 16 20 21 16 19 21 16 19 20 17 20 20 12 15 17 13 15 18 20 23 25 -21 24 26 23 26 28 35 33 32 28 27 28 13 14 17 15 16 16 14 14 15 34 35 39 -61 65 68 56 64 67 54 62 65 53 61 63 51 59 62 33 36 39 11 15 19 30 34 37 -49 55 59 51 57 60 76 63 56 86 74 72 86 75 73 84 63 56 71 48 45 57 38 39 -45 32 35 46 32 35 58 40 37 75 56 49 82 61 57 82 60 61 86 66 64 79 58 57 -73 47 46 63 40 42 71 49 51 88 62 61 102 71 63 135 103 90 178 152 139 207 188 177 -222 205 196 223 204 192 199 174 158 160 126 107 177 135 113 190 145 121 208 163 141 110 90 86 -29 22 23 29 22 25 27 22 23 25 20 21 25 20 21 25 20 21 25 19 20 24 19 20 -23 19 21 23 18 20 24 18 19 22 17 20 11 12 14 11 12 16 10 10 13 11 12 15 -9 11 13 10 11 13 10 11 14 9 11 12 9 11 10 17 15 16 20 17 19 20 16 17 -19 17 18 17 16 17 19 13 19 18 16 18 18 15 16 16 15 16 17 14 16 18 13 16 -16 13 15 -11 12 16 15 19 21 17 21 23 17 21 22 18 21 23 12 16 18 13 15 18 18 23 27 -21 26 29 23 27 29 33 32 32 33 31 31 13 13 17 15 15 19 13 14 15 30 33 36 -67 74 77 66 75 80 66 75 77 67 75 77 65 74 74 42 47 49 12 15 19 30 36 37 -52 62 64 54 64 66 69 64 60 87 73 70 84 72 69 73 54 48 50 34 34 37 28 30 -22 21 23 25 21 23 45 32 36 68 51 50 79 61 63 79 60 62 85 67 68 73 56 62 -53 36 38 40 30 32 41 32 31 83 64 63 126 97 95 144 112 110 181 155 147 207 188 177 -222 203 193 222 201 192 198 169 155 170 133 116 157 109 93 153 92 72 180 114 87 102 80 71 -27 23 24 28 22 24 27 24 24 25 21 22 24 19 21 24 20 20 24 20 20 24 18 20 -24 19 21 23 19 20 23 18 19 22 18 19 12 12 13 11 12 15 9 11 14 11 12 14 -9 13 14 9 12 13 11 11 15 10 12 13 9 10 11 18 14 15 20 16 17 19 17 18 -18 15 16 18 15 17 18 15 16 18 14 16 17 15 16 17 14 15 16 13 15 18 15 16 -16 13 14 -12 14 15 13 16 20 17 21 25 17 22 25 18 21 24 14 16 19 13 16 18 20 24 27 -22 26 30 22 26 32 29 30 32 30 29 31 12 14 20 25 26 30 16 16 17 24 30 31 -62 73 72 65 77 78 65 75 77 65 75 76 64 74 75 44 51 53 13 17 18 29 34 37 -55 63 66 54 66 67 57 64 67 83 73 74 82 72 75 70 57 63 70 52 59 66 45 51 -58 38 44 54 35 41 55 39 45 70 53 58 94 73 78 134 109 115 122 99 104 85 66 72 -66 45 50 79 50 52 106 74 74 143 108 106 184 155 147 211 189 182 224 205 198 220 201 193 -221 202 193 220 200 189 199 170 155 167 121 105 173 120 104 194 146 137 157 104 86 35 28 26 -27 21 23 27 21 23 27 21 21 24 20 21 24 20 21 24 18 20 24 18 20 24 18 20 -22 18 19 22 18 19 22 18 19 22 16 18 12 12 13 10 11 14 10 11 12 10 12 14 -9 12 15 9 12 17 10 13 18 10 11 18 9 10 14 15 13 14 17 16 16 18 15 16 -18 15 16 18 14 16 16 14 15 17 14 16 17 14 15 16 15 16 15 14 15 16 12 15 -15 13 15 -12 14 16 11 13 14 16 22 25 17 23 26 18 22 26 14 18 19 12 17 20 17 21 25 -22 25 30 23 28 36 23 28 30 17 19 21 11 13 17 15 16 20 13 14 15 24 25 27 -58 66 67 59 69 69 67 75 76 71 80 79 69 76 79 45 51 55 13 17 20 25 34 34 -54 64 65 54 64 66 51 60 64 71 68 69 88 76 80 76 62 71 67 54 62 64 48 55 -61 41 48 57 39 51 65 50 60 82 62 65 164 133 130 217 191 185 217 195 192 161 138 137 -122 98 103 111 80 86 136 103 103 171 138 134 204 177 169 224 206 197 231 214 206 226 209 199 -221 204 193 216 196 184 209 182 170 155 102 92 164 99 82 203 157 139 130 100 95 20 18 20 -31 21 24 31 22 25 30 21 23 30 21 23 31 20 23 33 20 22 33 21 22 33 21 22 -36 23 24 40 25 25 42 26 24 46 28 26 23 16 18 10 11 14 9 10 12 11 13 14 -9 12 14 9 13 20 9 13 16 11 12 17 9 10 13 16 14 15 16 15 15 17 16 16 -17 14 15 18 14 16 17 14 15 16 13 14 17 14 15 15 14 15 15 14 14 15 12 14 -15 12 15 -12 16 19 11 14 15 16 17 23 20 23 28 41 42 46 19 24 24 15 17 20 45 46 50 -55 59 64 60 65 66 55 59 62 22 24 27 11 13 17 12 13 18 12 13 16 20 22 26 -41 48 51 35 44 45 55 61 62 71 79 77 60 70 67 30 38 38 16 17 20 22 26 30 -38 47 46 33 40 43 27 34 37 51 48 49 88 79 81 78 69 74 70 60 69 64 53 63 -63 53 63 68 56 64 75 58 65 90 64 69 167 129 120 223 194 185 234 211 204 191 168 158 -159 134 127 167 137 131 195 168 156 210 187 177 223 204 195 235 218 210 235 218 210 230 212 202 -222 204 193 212 191 179 220 193 182 182 133 126 172 110 104 211 168 155 106 84 80 72 50 46 -82 54 54 81 55 50 81 55 51 79 52 47 86 57 50 87 57 51 86 56 49 88 54 48 -89 56 52 90 59 51 88 57 49 91 58 49 51 31 31 10 11 13 7 11 11 11 13 13 -9 11 13 10 12 16 10 13 18 9 13 16 8 10 12 16 13 14 17 16 17 18 15 16 -17 15 14 17 14 15 19 14 15 18 14 15 16 14 15 16 13 14 16 13 14 15 13 14 -15 12 12 -15 19 22 15 19 21 15 16 18 18 23 25 34 38 39 17 23 24 14 18 19 29 35 36 -33 39 39 33 40 39 28 33 34 16 17 20 10 12 15 13 17 19 14 15 15 19 22 26 -32 35 40 17 20 22 18 20 23 20 24 26 22 22 24 26 23 24 29 22 23 32 25 27 -36 30 30 40 31 33 44 33 33 58 43 44 89 77 81 81 70 77 77 64 73 76 62 71 -76 60 67 78 59 64 79 56 59 94 62 64 126 83 75 181 138 123 213 180 164 228 201 187 -166 137 130 130 97 88 154 123 111 191 163 149 218 198 188 233 215 205 235 217 208 230 213 203 -226 204 195 215 194 183 223 198 187 232 200 189 226 193 183 199 169 160 74 50 45 77 53 45 -96 63 57 96 62 52 95 63 52 96 60 52 95 56 47 96 58 46 98 62 52 96 59 49 -98 61 50 96 62 51 91 55 46 93 56 47 53 33 32 10 11 15 9 10 14 12 13 15 -14 15 18 13 15 19 13 14 19 12 15 18 8 11 14 15 13 14 16 14 15 17 15 16 -17 15 14 17 14 15 18 14 15 18 14 15 17 14 15 17 14 15 15 13 14 15 13 14 -15 12 13 -18 18 21 23 19 23 24 20 22 27 22 23 30 24 26 35 27 28 40 29 30 43 31 31 -49 36 34 52 38 34 48 34 33 26 23 24 12 13 16 46 34 33 35 25 24 19 21 24 -60 49 48 72 51 48 73 51 45 80 53 47 77 50 45 82 53 47 81 52 43 81 53 46 -81 51 48 79 50 45 81 52 44 81 54 48 93 79 82 89 74 79 86 66 70 85 63 68 -85 65 66 80 60 59 86 58 55 91 55 47 105 66 57 122 76 66 117 64 54 169 126 108 -137 108 99 104 72 69 118 83 74 152 116 105 191 160 148 213 188 175 223 202 190 225 204 194 -225 204 195 218 196 184 228 205 191 228 200 186 234 204 193 145 122 116 78 52 48 88 61 54 -94 64 55 98 64 54 98 62 52 94 59 50 98 62 50 98 62 49 97 62 48 98 60 49 -98 61 49 98 62 48 99 61 48 90 58 50 49 31 32 10 11 15 9 10 14 13 14 14 -13 16 19 12 16 21 12 14 20 11 14 20 9 10 12 16 13 14 19 15 16 17 15 16 -17 14 16 17 14 15 17 14 15 18 14 15 17 14 15 16 13 16 16 13 14 16 14 15 -16 12 13 -75 50 44 78 51 47 78 49 43 76 45 41 77 50 42 77 51 42 77 48 39 79 48 40 -80 52 43 78 52 43 67 42 37 43 35 34 13 14 17 46 31 28 47 31 26 19 20 23 -55 47 44 58 40 35 56 40 31 60 41 34 52 34 27 52 31 26 50 33 28 51 32 29 -49 30 28 49 31 27 52 33 30 52 32 27 90 73 73 96 75 75 95 68 67 95 66 65 -92 67 64 82 61 60 78 56 58 78 51 55 85 54 58 95 60 61 145 112 110 189 162 157 -128 102 103 94 66 69 111 76 70 126 86 76 157 117 105 187 152 136 207 179 164 213 191 178 -221 199 190 208 185 173 202 170 145 231 203 189 199 169 158 106 77 67 99 68 59 99 67 58 -94 66 59 97 65 57 94 59 51 95 60 49 96 62 54 99 62 49 99 63 51 97 62 52 -98 62 51 101 66 55 95 60 50 71 44 39 20 16 17 10 11 14 10 10 13 11 12 15 -10 13 17 10 15 23 11 17 25 10 14 23 9 10 13 15 14 15 18 15 16 19 16 17 -17 15 15 18 13 16 17 14 16 16 15 16 16 13 14 17 13 15 15 13 14 17 13 14 -14 12 13 -60 38 32 59 36 30 56 34 27 54 32 28 54 33 28 50 33 27 50 31 25 53 31 27 -52 31 26 54 32 28 58 35 30 47 35 35 13 14 16 55 39 36 57 37 32 20 20 20 -64 53 49 73 42 38 71 41 36 79 52 46 78 46 40 86 50 42 90 58 51 88 52 45 -94 58 48 91 56 46 91 55 46 96 61 52 98 74 68 100 78 72 102 73 65 103 72 65 -99 72 65 87 62 60 80 58 63 78 55 61 93 64 69 137 103 101 200 172 163 214 194 184 -173 151 151 90 65 69 105 71 63 123 87 76 133 92 81 157 120 104 185 150 137 204 176 165 -215 193 181 170 147 135 135 100 79 155 123 105 111 81 71 100 68 60 102 70 60 100 70 59 -95 68 63 97 66 59 93 64 57 97 62 54 99 63 51 102 64 52 99 62 51 96 62 54 -98 65 57 98 63 54 70 43 38 28 20 21 15 14 15 9 11 14 9 10 14 12 12 15 -10 12 15 11 13 16 15 16 17 14 14 17 11 10 15 14 13 14 17 15 17 16 16 17 -19 15 16 19 15 17 17 15 18 17 14 17 16 14 15 16 14 13 17 13 14 15 13 14 -14 12 13 -83 46 37 87 49 39 91 59 50 87 52 44 89 53 44 93 62 51 94 57 45 94 57 46 -95 62 52 93 58 48 94 62 52 53 42 38 14 14 18 71 47 43 81 51 44 22 22 24 -74 58 54 97 64 55 97 62 52 98 63 52 101 68 58 97 61 49 100 64 52 103 69 57 -99 62 49 102 66 53 105 69 56 99 64 48 99 67 58 101 77 73 104 75 66 109 75 67 -106 76 66 97 67 62 92 62 60 86 51 53 96 58 56 112 70 63 112 71 62 117 83 74 -124 96 90 94 66 64 99 68 60 116 80 69 127 87 77 145 109 97 173 140 127 197 167 155 -206 185 172 127 103 94 107 73 63 104 71 61 101 68 60 102 71 62 102 73 65 99 71 63 -101 73 65 101 72 63 98 65 57 96 64 53 97 64 54 97 61 47 99 63 52 94 61 53 -91 58 50 67 43 38 27 20 21 22 18 19 16 14 15 10 11 15 9 10 12 10 12 16 -9 12 14 11 13 14 13 14 14 14 15 15 9 11 13 14 13 14 17 15 17 18 14 15 -18 14 16 18 14 15 16 14 16 16 14 16 15 13 15 15 14 14 15 14 15 16 13 14 -14 13 13 -98 63 52 100 65 53 97 62 49 100 67 56 97 61 51 99 62 49 105 68 56 100 63 51 -97 64 52 100 67 55 95 63 54 55 45 41 13 14 17 71 50 44 87 57 51 23 22 22 -81 66 62 99 64 52 103 66 52 104 70 57 100 65 52 102 64 52 103 68 56 101 65 52 -101 63 52 100 66 53 101 65 51 101 66 51 101 68 57 102 77 72 103 76 67 103 74 65 -99 71 61 81 53 48 77 47 48 81 45 51 82 39 49 80 38 45 87 45 54 86 52 60 -86 58 63 80 56 61 85 57 55 108 74 65 125 89 80 151 116 106 173 139 129 191 161 150 -196 174 163 167 151 145 165 148 146 158 141 143 113 86 83 103 70 63 104 70 61 100 66 58 -100 69 63 100 67 58 104 68 57 99 66 56 97 61 53 98 66 57 97 64 53 93 60 52 -62 40 38 26 21 21 22 19 20 21 18 19 15 14 15 9 11 15 9 11 13 11 12 15 -10 11 14 11 12 13 13 13 14 13 13 14 10 11 12 15 14 13 17 15 16 18 15 16 -16 14 13 17 14 15 16 16 16 15 13 16 15 14 17 16 13 14 14 13 13 15 13 13 -16 12 13 -99 62 51 97 63 51 102 72 61 96 65 52 98 63 51 102 72 62 101 66 50 103 67 53 -99 66 55 101 67 56 100 65 54 61 48 44 13 13 16 68 47 39 89 56 45 23 21 20 -75 60 56 99 68 58 98 66 53 98 64 51 101 68 55 98 63 49 97 61 47 101 67 53 -99 60 47 97 60 46 102 66 55 99 58 45 98 59 48 102 73 66 104 78 73 107 77 69 -104 75 67 92 66 63 94 69 65 100 74 70 107 78 75 108 79 74 105 77 73 98 75 75 -92 71 72 94 69 73 96 71 69 114 81 75 130 94 87 147 113 105 164 134 123 182 155 145 -189 166 153 156 130 112 156 134 119 212 205 200 210 202 205 113 91 86 103 72 63 101 71 61 -97 66 61 99 68 59 95 62 52 99 63 53 96 64 56 90 61 53 86 58 51 56 40 40 -25 21 22 22 19 20 20 18 19 20 18 19 15 15 16 9 11 13 11 11 15 12 12 15 -12 11 14 12 12 14 12 12 15 12 12 14 9 10 13 13 12 13 18 15 15 18 15 16 -17 15 15 16 14 15 15 14 14 17 15 17 15 13 16 16 13 15 15 13 14 15 12 13 -16 12 13 -98 63 49 95 64 50 96 63 48 98 66 50 96 64 51 95 62 50 100 64 50 97 62 51 -95 62 50 101 68 54 99 62 49 62 46 41 14 15 18 63 45 40 88 54 46 23 21 20 -63 49 46 98 61 50 96 62 50 100 68 58 99 60 48 99 64 51 99 67 55 98 61 50 -97 61 49 95 61 51 97 61 48 101 66 54 100 69 57 101 67 57 100 72 67 107 80 73 -111 83 72 105 77 71 99 75 71 97 73 70 95 71 67 92 69 66 91 68 67 91 71 70 -97 73 75 102 75 74 111 84 78 121 92 81 128 95 86 136 104 95 149 120 111 180 155 141 -180 159 144 119 90 73 153 130 115 209 202 196 234 233 230 182 174 177 99 72 63 101 69 59 -100 71 63 99 66 58 99 67 55 95 66 56 94 62 53 93 61 55 55 36 35 26 22 22 -24 21 22 23 19 20 22 19 18 22 18 19 16 15 16 10 11 13 11 11 15 12 11 16 -11 11 14 11 11 13 12 12 14 11 11 14 10 11 13 13 13 13 16 14 15 18 14 17 -17 14 15 16 15 15 17 15 16 15 14 16 15 14 15 15 13 14 14 13 14 14 14 14 -14 13 13 -97 61 45 98 59 47 101 68 54 98 61 46 96 59 48 98 65 54 101 66 53 96 62 54 -96 64 52 96 62 50 97 61 52 67 50 44 16 15 16 62 41 36 89 57 50 23 22 21 -62 49 47 92 60 49 97 66 56 94 58 47 94 56 43 93 59 47 96 59 49 95 61 51 -97 61 49 96 64 53 95 59 48 94 54 44 92 61 52 92 70 71 78 66 74 83 69 72 -109 86 76 115 87 77 111 85 76 103 78 73 97 71 73 96 69 73 98 74 76 115 88 88 -123 97 93 116 89 82 122 94 84 127 98 86 130 97 87 131 98 87 150 118 107 196 170 152 -160 135 120 134 104 88 143 117 102 183 172 164 220 219 215 229 227 227 169 162 162 104 86 84 -96 72 68 99 70 65 96 66 58 97 66 59 93 66 60 54 36 34 25 22 22 23 21 23 -23 21 23 22 19 20 22 20 20 23 19 21 17 15 17 11 12 16 11 12 15 12 13 17 -10 14 14 11 12 16 11 12 16 10 12 17 11 11 15 14 12 13 17 15 16 16 16 16 -16 15 16 15 15 16 16 14 15 16 15 15 15 13 14 15 13 15 14 13 15 15 13 14 -13 12 13 -94 58 48 99 64 52 97 59 44 100 62 47 98 62 49 93 56 44 97 62 48 98 62 49 -92 58 45 92 61 48 94 58 46 71 52 46 17 15 16 54 36 34 94 61 53 27 22 21 -63 51 47 96 63 51 97 62 51 101 67 57 98 64 55 100 65 54 100 65 53 103 67 53 -100 64 53 100 66 54 102 67 61 91 71 78 70 67 77 61 60 71 55 52 63 47 45 55 -64 60 65 100 82 74 122 96 84 127 98 87 127 95 85 126 97 87 128 98 90 142 114 102 -147 120 107 128 101 88 126 100 86 128 99 85 129 97 85 134 101 88 175 145 128 199 174 158 -127 103 91 140 111 98 133 110 99 169 158 149 210 209 205 224 224 221 227 226 224 219 215 217 -150 138 141 101 75 67 100 70 60 95 67 60 56 40 38 28 24 25 25 22 23 25 22 23 -24 23 23 23 20 22 23 19 23 22 19 21 17 15 18 12 12 17 10 13 16 10 15 18 -11 14 19 11 12 19 11 12 19 10 13 17 10 11 15 13 13 13 17 15 16 18 16 17 -16 14 15 16 14 15 16 15 16 15 14 14 17 13 15 17 13 14 14 13 14 15 12 13 -14 13 13 -96 61 51 96 60 48 103 66 55 100 65 51 100 64 50 102 64 50 100 63 49 101 65 52 -102 66 50 101 64 52 98 66 55 72 51 45 19 18 17 53 34 32 94 58 49 28 23 21 -56 44 42 96 61 48 100 64 53 98 64 54 94 61 49 100 64 52 99 65 52 105 67 55 -102 66 54 95 70 68 76 73 86 63 65 80 63 59 65 62 54 58 56 49 55 48 44 49 -51 51 61 51 46 48 86 70 62 124 98 87 145 114 98 150 117 101 150 117 103 146 113 97 -140 108 94 133 102 88 130 99 85 127 96 82 128 97 83 164 137 123 212 188 173 137 116 104 -118 96 86 135 112 103 115 98 91 161 153 145 206 205 201 183 185 178 197 198 191 215 216 210 -225 224 223 176 168 172 93 70 65 56 39 39 29 27 29 26 25 25 25 23 24 24 23 23 -24 22 23 23 20 21 23 19 21 21 20 21 17 17 19 11 12 16 12 14 17 10 15 17 -9 13 18 9 13 18 11 13 18 11 13 17 11 11 16 13 13 14 17 16 17 16 15 17 -18 14 16 18 14 16 15 15 15 16 15 16 14 14 14 16 14 15 15 13 14 14 13 14 -14 13 15 -95 61 49 98 65 54 98 60 49 102 62 48 104 67 55 101 64 53 99 64 48 106 69 54 -104 68 54 102 65 54 100 64 52 81 60 52 21 19 17 53 35 33 98 67 57 30 24 22 -56 46 44 101 68 57 100 63 51 103 66 55 101 64 52 98 64 53 99 65 54 99 66 58 -87 75 82 71 78 100 64 72 93 69 66 72 69 60 64 60 57 62 56 52 60 51 47 53 -57 54 61 57 51 56 62 50 49 85 65 62 112 86 75 134 105 92 145 114 98 146 113 96 -141 108 92 135 101 85 126 95 81 129 100 88 172 143 129 206 183 167 173 150 137 101 82 74 -133 111 103 136 117 111 109 97 92 166 161 155 210 210 207 135 134 132 124 126 117 173 174 169 -193 195 190 224 223 223 129 126 128 35 34 35 30 28 30 27 26 28 26 25 25 25 23 24 -24 21 24 23 21 22 22 21 23 20 20 21 17 17 18 11 13 16 10 14 16 10 14 18 -9 13 17 10 12 18 10 14 18 11 13 17 10 11 16 13 13 15 16 15 16 17 16 18 -16 15 17 17 15 17 17 15 16 15 15 15 19 17 18 25 22 22 20 16 19 16 14 15 -15 14 15 -97 65 53 94 62 52 100 64 51 102 65 51 102 68 53 102 67 53 99 65 53 103 68 55 -102 65 53 103 67 56 101 67 57 81 55 48 23 20 20 48 34 30 89 60 53 33 26 25 -54 43 41 99 62 52 102 66 55 100 64 54 98 60 49 99 62 50 93 65 64 73 76 93 -66 84 106 65 76 97 68 69 80 67 64 65 63 61 66 56 58 68 63 59 66 58 51 57 -59 56 60 61 57 59 60 48 48 85 64 61 99 74 70 109 83 73 123 95 83 130 100 87 -129 97 85 122 93 81 131 100 92 169 137 126 189 161 145 187 164 147 99 79 72 128 110 106 -123 106 101 119 108 103 110 100 98 185 184 179 201 202 199 130 129 126 133 132 131 160 160 158 -209 209 206 233 233 231 212 211 215 70 70 76 31 30 33 26 26 27 25 25 26 25 23 25 -24 22 23 23 21 22 22 20 21 21 21 21 18 17 18 12 13 16 12 14 17 11 14 17 -10 13 17 10 14 17 11 15 17 11 13 17 10 12 15 13 13 14 17 16 17 16 16 16 -16 15 16 16 15 16 15 15 15 20 20 20 38 34 33 50 43 44 54 47 47 36 31 33 -15 14 14 -99 66 54 103 67 55 103 65 49 99 62 46 102 66 52 102 65 51 100 62 52 102 64 52 -101 65 53 102 62 51 103 64 51 87 64 56 24 22 23 47 34 32 100 71 62 37 27 26 -51 43 40 101 66 58 101 64 53 102 69 58 99 67 56 96 74 69 74 75 87 59 76 92 -60 77 98 70 77 96 65 65 70 64 63 69 62 66 79 60 70 85 71 71 83 63 60 65 -65 61 63 68 63 67 57 47 48 83 63 60 104 79 72 116 87 80 123 96 87 129 100 92 -127 98 91 134 107 98 158 129 119 173 143 132 182 156 143 122 102 92 120 105 103 154 146 145 -110 102 102 119 109 110 112 109 110 207 207 202 196 197 194 165 165 163 189 189 187 206 206 205 -227 227 225 233 233 231 236 236 235 165 165 171 34 33 39 28 27 30 26 24 26 25 24 26 -23 22 23 23 20 23 22 21 22 22 20 20 18 17 19 12 14 17 13 17 19 13 15 18 -12 15 16 13 15 19 14 15 20 11 15 20 11 12 17 13 13 14 16 15 17 16 16 17 -16 15 17 16 14 16 17 16 18 15 15 15 31 29 27 35 32 31 33 30 27 46 35 35 -19 15 18 -102 66 53 97 62 45 98 60 48 99 64 49 98 64 51 96 61 49 97 62 51 101 65 53 -102 64 49 102 65 49 100 66 52 82 56 46 28 24 23 43 30 29 89 60 50 39 29 25 -47 37 36 98 66 56 101 67 57 98 63 54 94 61 51 87 77 79 59 65 75 66 72 85 -69 80 99 67 76 93 55 60 70 60 72 93 64 76 95 66 76 89 115 117 130 84 81 88 -72 68 71 72 70 73 63 58 61 69 52 49 105 80 73 120 95 88 129 102 94 132 105 97 -137 108 100 147 119 109 159 132 120 176 148 136 155 130 121 104 87 83 158 151 148 225 224 223 -115 113 114 148 143 146 135 134 133 215 214 212 193 193 186 192 193 188 202 203 200 223 223 221 -231 231 229 237 237 235 239 239 239 209 209 212 42 42 46 29 29 30 28 25 27 25 23 26 -24 23 24 22 21 23 20 20 21 22 21 21 17 17 19 12 16 19 13 17 21 13 16 20 -12 15 19 12 15 19 12 15 19 12 14 18 13 12 18 14 13 15 17 16 17 17 17 21 -17 16 19 16 15 17 16 15 17 14 14 14 18 18 18 22 20 19 59 41 40 144 102 106 -36 24 31 -95 57 46 97 60 47 95 59 47 94 60 48 97 61 47 97 62 48 98 62 50 101 61 46 -101 64 48 101 61 45 102 64 48 89 63 54 30 28 26 45 30 28 100 64 56 43 31 27 -50 43 38 101 68 56 101 66 54 98 62 51 99 64 51 90 75 77 55 66 82 57 67 84 -70 81 100 65 76 96 48 59 77 61 74 99 61 72 86 162 165 169 226 225 225 167 166 167 -84 82 85 84 81 86 83 79 84 61 47 47 93 73 68 120 96 90 134 106 100 144 115 109 -150 122 112 158 129 119 172 143 132 174 147 137 113 89 84 129 117 117 210 207 206 239 240 239 -147 147 148 200 199 198 172 173 170 197 197 191 164 164 156 187 188 184 218 218 216 230 230 228 -236 236 234 236 236 234 238 238 238 232 232 234 83 85 92 30 31 31 28 27 28 25 25 28 -23 23 25 23 23 24 22 22 24 21 21 22 20 20 23 16 17 20 16 17 19 16 17 18 -16 16 19 15 15 19 15 15 18 16 16 18 16 15 18 15 14 15 16 16 18 17 17 18 -17 15 16 16 16 18 14 14 16 16 16 16 22 16 18 39 29 29 88 58 59 139 102 102 -47 34 42 -99 62 49 98 62 47 96 61 45 100 63 50 100 63 51 98 59 45 100 60 46 103 65 51 -95 57 42 96 58 43 101 65 51 89 56 44 42 35 33 41 28 25 95 60 50 43 32 28 -52 43 39 97 65 53 100 63 49 98 62 51 96 62 50 95 70 68 64 73 90 53 64 84 -68 80 96 70 82 103 53 69 89 59 73 93 71 75 86 128 129 128 196 199 195 216 215 215 -108 107 110 93 91 95 94 92 96 88 78 81 92 71 70 121 93 90 154 125 119 170 143 135 -172 146 136 176 149 139 186 159 149 141 117 111 126 112 110 168 164 164 232 232 230 242 242 240 -207 207 207 222 221 221 204 204 201 202 200 197 186 186 182 211 211 211 227 228 226 233 233 231 -234 234 232 235 235 233 237 237 236 236 236 236 122 124 132 33 32 34 29 28 31 25 24 28 -25 24 27 23 22 24 22 21 23 23 23 23 20 20 21 19 17 19 18 16 17 16 16 17 -16 15 16 17 15 16 17 15 16 15 15 15 16 15 15 18 16 19 17 16 19 17 17 19 -18 16 18 17 17 19 16 16 21 27 21 24 67 42 48 83 53 60 94 61 62 116 77 84 -56 38 45 -97 64 52 97 64 52 98 62 48 101 65 53 100 63 51 99 61 50 98 62 49 98 58 46 -100 63 48 96 58 47 93 56 42 99 62 52 51 40 39 40 26 23 98 63 50 46 33 30 -44 38 35 97 66 54 97 60 48 95 59 45 95 58 48 96 73 72 78 86 101 49 59 77 -72 77 91 79 86 94 88 101 116 57 72 88 71 73 83 80 80 79 76 83 80 187 190 188 -158 157 158 102 101 105 105 104 109 114 112 113 152 136 137 172 146 139 182 155 146 188 161 151 -188 160 150 186 161 148 171 146 137 121 100 97 141 134 131 214 214 213 234 234 234 230 230 230 -229 230 228 225 225 223 204 204 198 171 171 167 142 143 140 214 215 212 232 232 231 236 236 234 -231 231 229 233 233 230 236 237 234 236 236 235 146 148 155 32 33 36 28 28 31 26 25 30 -24 23 26 23 22 24 24 23 25 22 20 23 21 20 21 20 19 20 20 18 20 19 17 19 -18 17 18 19 17 18 19 17 19 18 17 18 17 17 19 18 18 21 18 17 21 18 17 21 -18 17 22 30 34 48 47 55 88 50 39 52 86 57 62 96 65 71 109 78 81 150 110 119 -44 35 44 -98 63 51 96 60 48 95 60 48 98 59 48 99 64 51 99 62 49 102 62 50 101 66 54 -99 62 48 98 62 48 101 66 51 95 60 47 40 32 29 46 34 32 93 56 46 50 34 30 -37 33 30 91 61 51 98 63 49 95 60 44 96 60 49 92 75 81 73 81 97 70 75 90 -56 62 69 73 72 75 94 98 102 61 67 80 65 65 71 51 53 52 40 43 43 101 106 104 -207 207 205 187 187 185 208 208 207 216 215 213 235 231 228 216 202 198 196 173 163 192 166 155 -187 160 149 175 148 139 135 110 105 129 112 111 166 165 164 199 203 202 225 226 226 199 204 204 -169 177 177 213 213 211 170 170 166 129 130 127 128 129 127 219 220 217 234 234 232 235 235 233 -236 236 234 235 236 234 236 236 234 235 235 234 158 160 166 34 33 38 29 28 33 26 26 28 -24 23 28 23 23 25 22 22 23 22 22 22 20 20 20 18 18 19 19 18 21 19 19 19 -18 18 19 18 17 19 18 18 20 18 18 20 18 18 20 18 18 21 19 18 21 19 21 30 -26 36 62 51 73 111 70 94 136 64 77 112 76 61 76 92 69 79 121 110 116 195 192 206 -104 104 129 -101 67 52 101 64 49 99 62 50 101 63 52 100 60 47 101 62 48 99 62 48 96 59 46 -99 63 50 100 63 48 96 58 42 99 61 48 38 30 26 47 36 33 93 61 52 54 37 34 -37 33 32 94 64 53 99 63 50 99 61 49 99 62 48 95 77 77 70 80 97 69 76 89 -66 74 86 63 62 67 59 57 59 68 68 71 50 49 51 30 29 30 44 41 40 46 48 48 -114 120 116 182 185 180 223 223 219 214 216 212 197 202 198 223 220 219 219 210 205 191 172 163 -171 148 138 137 112 106 126 107 104 156 150 150 210 211 209 194 198 201 130 139 143 146 158 174 -168 173 174 181 183 181 111 114 111 108 108 112 160 162 159 225 225 223 232 232 231 229 229 227 -232 233 230 236 236 235 237 237 237 235 235 234 171 173 178 37 36 39 29 29 32 26 27 29 -24 24 26 23 23 25 23 23 26 22 22 24 21 21 23 20 20 22 20 20 21 20 20 21 -19 18 19 19 18 20 19 18 20 19 18 20 19 18 21 19 19 22 22 30 43 48 71 111 -57 90 140 57 90 142 64 95 142 85 108 149 122 135 162 157 163 181 198 206 217 222 225 241 -128 131 155 -102 70 57 102 63 47 101 63 49 99 60 46 101 64 49 102 62 45 101 60 42 103 64 49 -99 57 42 100 60 44 102 67 51 100 63 48 41 30 27 30 24 21 90 59 48 57 40 33 -36 33 31 94 65 56 101 63 50 100 63 50 102 67 55 95 71 65 81 87 104 60 74 94 -70 81 96 62 68 81 45 46 53 52 51 54 55 54 55 36 34 36 41 40 44 40 38 40 -52 51 49 83 86 79 183 185 182 192 193 192 88 106 116 124 136 139 232 231 229 230 225 223 -145 134 131 127 113 113 158 154 151 214 214 214 227 227 226 223 225 227 130 147 172 174 184 207 -167 161 150 133 132 128 87 89 89 109 109 111 177 178 175 205 206 201 212 213 209 215 216 212 -213 213 211 218 219 214 236 236 233 234 234 234 195 195 199 42 43 47 31 30 34 26 26 30 -25 25 27 23 23 23 21 21 23 22 21 23 21 20 23 19 19 21 19 19 21 19 18 22 -19 17 19 19 18 20 19 19 21 18 18 21 19 18 21 26 33 46 61 86 125 71 103 152 -102 129 167 174 186 215 144 160 190 184 197 217 185 197 215 211 217 232 200 209 224 199 204 220 -114 117 140 -103 78 70 97 60 47 97 60 48 100 65 51 99 62 46 100 61 46 101 64 46 101 61 45 -99 61 42 100 63 46 101 63 46 101 62 47 47 36 31 19 18 19 74 48 41 61 41 33 -32 30 29 93 62 54 103 65 52 100 62 49 98 62 49 95 75 74 85 90 107 68 82 102 -60 78 100 69 78 99 52 60 74 37 40 45 44 45 46 42 42 43 36 39 46 47 50 61 -59 58 59 106 108 106 188 191 192 116 129 137 54 78 102 88 98 108 221 221 219 224 224 223 -162 163 163 170 169 169 216 216 216 222 222 222 231 231 229 178 186 191 167 171 183 153 150 143 -163 153 143 82 84 86 80 81 85 126 126 126 160 160 158 156 155 151 156 156 152 180 181 176 -194 194 192 193 194 190 230 231 227 235 235 236 230 229 231 132 134 140 34 33 38 28 28 31 -25 24 26 23 22 25 23 23 26 21 21 23 20 20 21 19 19 19 19 19 20 18 17 21 -19 17 20 19 18 22 18 18 20 18 18 22 19 18 23 57 72 94 91 116 155 172 189 212 -149 165 196 189 201 216 206 213 232 195 206 221 214 222 236 194 203 220 154 165 184 101 110 129 -35 36 49 -108 82 75 99 66 55 100 63 52 101 62 45 101 65 49 100 64 46 99 60 43 101 65 48 -99 61 44 98 60 42 103 65 48 99 64 49 47 36 33 22 19 20 52 35 30 58 39 33 -33 31 30 94 67 57 102 65 49 103 64 50 103 71 60 93 85 89 82 84 92 79 83 90 -70 83 97 64 80 99 58 71 89 39 48 61 32 35 39 34 34 37 31 33 36 59 65 78 -59 62 68 108 107 104 104 122 141 74 93 115 109 116 128 95 100 107 153 154 154 188 188 185 -173 176 173 204 205 201 201 201 198 196 198 194 221 222 220 123 129 127 152 148 138 160 163 163 -158 155 149 61 62 64 100 100 99 144 141 139 144 143 139 144 143 142 160 160 160 185 185 184 -202 202 201 211 211 209 231 231 229 237 237 237 236 236 236 211 211 215 44 45 52 28 27 32 -25 25 28 23 22 25 21 20 24 20 20 22 21 21 22 19 19 20 20 19 20 19 18 18 -18 18 18 18 17 21 17 17 19 19 19 21 19 21 27 78 96 116 134 154 184 132 154 175 -171 185 210 131 152 173 204 213 228 200 209 225 199 208 226 158 170 188 173 182 201 122 126 152 -26 26 39 -116 89 80 102 72 62 98 64 53 100 68 56 99 63 49 101 65 48 103 68 54 100 64 50 -104 62 48 105 66 52 101 65 49 100 64 50 52 39 36 23 19 21 67 41 36 45 35 32 -29 29 28 87 60 51 104 70 56 103 68 56 97 66 57 87 85 93 76 83 93 71 80 92 -66 77 87 68 78 92 60 73 91 50 60 77 34 39 50 27 29 32 26 26 29 35 37 43 -44 44 46 123 128 133 163 174 183 121 126 133 103 103 108 97 93 95 102 91 90 78 71 72 -77 70 76 127 126 120 168 167 163 152 152 151 205 207 204 100 105 104 155 146 133 159 160 156 -167 172 175 96 99 102 136 134 132 154 152 149 175 175 173 206 206 205 214 214 214 215 215 215 -215 215 215 222 222 221 231 231 229 238 238 238 238 238 237 237 238 238 122 123 131 32 31 36 -26 26 30 24 24 26 22 21 25 21 21 24 20 20 22 20 19 21 20 19 21 18 18 20 -18 18 19 18 18 21 18 17 22 19 19 22 22 29 34 70 96 131 100 124 155 180 194 210 -161 174 201 94 117 148 140 156 177 188 200 215 168 179 201 143 157 175 136 144 166 45 50 65 -14 14 22 -114 89 79 105 80 72 97 68 57 97 63 53 96 62 54 100 66 53 96 64 51 97 63 49 -98 59 46 100 65 50 102 66 54 99 66 53 55 44 39 22 18 19 81 51 48 31 27 25 -26 27 26 77 54 46 87 51 41 84 50 39 87 64 60 77 84 101 77 89 109 69 88 110 -60 81 102 55 69 92 58 72 90 50 64 84 39 47 64 29 31 40 22 22 24 41 41 43 -36 36 37 107 110 108 175 177 174 116 115 117 72 70 72 74 67 67 70 64 67 65 60 67 -76 71 76 74 69 68 118 115 113 161 161 160 171 173 169 168 171 172 135 129 120 155 147 137 -154 151 146 159 160 159 190 190 188 187 187 186 168 170 168 207 207 207 217 217 217 219 219 218 -222 222 220 229 229 227 237 237 235 239 239 237 238 238 236 237 237 235 195 195 200 36 36 41 -27 26 32 24 23 28 22 22 25 21 21 24 20 20 23 20 19 23 20 20 21 19 18 21 -19 19 21 19 19 22 19 20 23 21 21 25 34 43 49 105 126 156 121 142 168 192 203 219 -142 154 183 93 113 146 106 124 152 133 149 174 118 130 159 47 59 76 19 24 35 15 15 19 -13 12 18 -107 86 78 105 83 74 81 53 44 81 54 43 77 47 38 80 46 36 81 50 37 78 46 34 -78 44 33 72 45 35 74 41 32 75 44 35 43 30 28 18 17 17 72 47 40 36 27 24 -30 29 28 79 57 50 91 56 45 89 50 40 92 68 66 76 91 112 68 90 116 70 92 115 -64 87 108 57 80 104 52 73 97 49 68 89 39 53 71 31 37 51 21 22 26 37 33 34 -38 34 35 74 74 72 147 146 146 89 88 90 72 64 69 55 50 54 74 69 72 72 69 72 -59 59 68 39 40 48 50 50 56 95 100 99 82 90 93 117 123 121 138 142 145 129 127 123 -157 152 143 180 180 178 171 172 170 175 177 176 184 185 184 200 200 199 212 212 210 218 218 216 -218 218 216 224 224 222 230 230 228 238 238 236 237 237 237 232 232 230 221 221 223 46 49 55 -29 28 33 26 25 31 24 23 28 23 22 27 21 21 24 21 21 23 20 19 22 19 19 21 -19 19 22 18 18 22 19 19 22 19 20 23 63 73 92 94 115 144 137 154 179 165 178 196 -158 167 190 109 118 129 142 153 168 123 140 163 69 82 108 17 23 38 14 14 17 12 12 16 -11 12 16 -109 87 82 141 129 128 111 96 91 95 65 58 93 58 50 98 62 52 96 58 44 99 60 45 -103 64 49 99 62 51 100 56 43 99 58 46 58 36 30 19 16 17 87 55 47 45 30 26 -28 28 28 87 65 57 105 68 55 100 60 49 97 75 74 84 95 111 97 109 127 153 158 165 -165 170 175 124 132 141 82 93 110 67 82 100 58 71 88 47 55 71 36 37 48 29 26 28 -35 31 32 29 26 28 70 70 71 76 75 80 53 50 54 37 33 35 57 49 50 62 55 56 -63 61 65 80 79 88 53 56 63 57 64 73 147 151 152 59 63 67 79 83 84 134 129 123 -122 119 115 88 87 86 115 114 115 165 165 166 189 189 189 205 205 205 215 215 214 224 224 223 -229 229 228 226 226 224 220 220 218 221 221 217 231 231 229 230 230 227 229 229 230 76 77 84 -28 27 32 24 24 27 22 22 25 21 21 22 20 20 22 19 19 21 18 19 19 18 18 20 -18 19 19 18 18 21 18 18 21 20 20 23 58 71 88 104 121 144 172 175 187 168 173 189 -132 136 155 113 116 111 176 179 171 143 150 163 26 39 57 17 21 36 14 13 18 12 12 15 -12 13 16 -112 92 86 176 171 171 214 212 212 104 83 74 100 68 60 101 68 56 99 66 52 100 63 50 -102 66 51 102 68 57 102 63 48 103 67 53 63 41 35 17 17 17 84 58 49 51 35 31 -26 27 27 86 66 58 108 76 63 103 72 63 100 87 84 132 140 147 167 171 176 180 184 184 -196 197 196 207 208 205 191 194 195 107 116 125 73 79 96 66 70 82 48 48 61 32 30 34 -59 52 54 105 90 91 72 61 61 25 24 26 26 25 34 24 23 30 53 47 53 48 43 48 -33 31 35 49 49 54 54 53 53 77 82 84 188 187 187 104 106 113 42 44 48 127 121 112 -122 117 112 86 82 83 113 112 112 138 138 138 159 159 156 198 198 196 216 216 214 223 223 221 -230 230 229 236 236 235 235 235 234 223 223 221 216 216 212 230 230 226 230 231 231 100 103 110 -28 30 34 24 26 29 22 24 26 23 24 25 21 23 23 23 24 26 19 22 23 18 21 22 -18 23 23 18 22 24 16 20 21 16 21 20 54 68 81 63 68 80 138 110 102 165 141 142 -92 92 102 115 113 113 123 122 109 133 134 127 20 29 44 15 21 35 15 15 19 14 14 14 -13 15 18 -117 98 91 175 168 168 237 237 236 156 151 146 107 80 70 104 75 62 106 76 64 106 72 61 -112 75 62 107 72 60 109 72 58 109 71 57 71 48 41 18 17 17 84 55 47 52 37 32 -26 26 26 81 59 51 106 69 56 104 75 65 107 104 105 121 127 127 161 163 163 186 187 184 -181 184 182 176 177 173 191 192 187 177 178 179 80 87 98 70 76 86 62 62 70 37 36 40 -45 39 39 120 103 103 107 95 95 74 69 75 36 45 64 46 51 73 48 49 63 47 51 67 -37 44 66 35 39 58 23 28 34 63 68 71 117 121 124 34 37 43 27 28 34 108 107 100 -91 89 83 83 79 80 96 91 93 95 87 90 89 80 78 117 113 111 172 173 170 204 205 201 -219 219 215 230 230 228 235 236 233 236 236 235 223 223 222 217 218 214 224 226 226 73 80 84 -22 28 27 18 25 26 18 23 22 17 23 21 16 22 19 17 21 20 16 21 20 15 20 19 -14 20 18 14 20 18 15 19 19 16 20 19 34 44 43 59 59 64 89 74 70 142 113 110 -127 120 120 140 137 131 136 135 123 114 115 116 18 25 43 14 23 39 15 16 25 14 14 17 -11 15 16 -121 102 95 176 170 169 231 230 229 212 210 209 112 86 76 107 74 59 105 70 55 106 67 53 -107 67 52 103 67 52 107 70 55 106 70 52 72 53 39 18 19 17 86 64 52 71 58 47 -24 25 24 85 67 58 116 89 71 106 88 76 74 75 73 78 82 88 78 81 85 100 96 96 -141 136 136 156 151 147 163 159 152 165 161 159 95 94 99 83 84 92 73 71 77 52 48 54 -27 22 23 113 96 93 115 102 100 93 87 92 46 50 67 50 55 78 54 57 79 54 58 82 -61 65 90 66 78 103 61 75 98 76 90 109 171 175 177 109 107 106 97 90 88 111 107 102 -48 47 45 81 75 77 90 82 85 81 71 73 79 71 72 101 91 92 107 99 97 130 126 122 -156 155 146 195 196 187 225 224 217 232 232 226 232 233 231 210 211 206 151 156 155 31 37 35 -23 27 25 19 25 23 19 24 22 17 23 21 14 22 19 16 21 20 14 22 19 15 21 18 -15 21 19 17 21 20 16 21 20 16 21 19 29 37 32 83 84 82 66 58 57 109 86 83 -187 158 152 180 172 164 191 192 187 101 108 119 19 27 44 20 28 45 15 19 31 13 13 17 -11 14 16 -117 99 93 185 179 179 242 241 241 244 244 244 166 161 155 137 117 101 141 121 99 144 125 101 -144 124 98 140 122 98 120 104 75 112 96 66 91 82 60 20 20 18 102 94 69 70 67 48 -23 22 22 90 84 62 115 113 74 108 111 77 77 79 78 75 79 89 71 74 83 79 75 79 -97 79 75 151 129 120 167 144 136 137 118 112 120 107 105 105 98 101 86 79 86 63 58 65 -31 25 27 97 82 79 127 107 104 103 93 94 76 69 74 80 71 78 89 84 97 64 68 86 -57 60 80 61 64 86 71 82 102 140 148 153 161 166 164 128 121 111 124 114 104 94 87 82 -32 32 32 72 67 70 76 65 70 64 46 50 76 59 62 73 57 60 69 53 53 85 67 65 -105 85 75 136 116 96 147 136 114 213 204 181 228 226 217 195 195 196 52 55 57 36 36 37 -33 33 34 33 32 33 26 28 27 19 25 21 18 24 19 18 23 20 19 22 20 17 24 19 -16 24 17 16 22 17 17 24 19 17 23 18 18 26 19 53 55 50 60 54 53 78 57 58 -161 134 130 202 195 196 127 134 149 34 48 72 21 28 47 20 28 44 17 24 38 12 15 22 -11 15 18 -112 94 90 182 174 174 229 229 229 243 243 243 222 223 219 127 130 98 116 120 78 105 115 67 -108 116 70 106 111 67 101 108 60 96 104 51 71 77 41 19 22 17 76 80 44 59 66 34 -24 24 23 65 69 40 88 98 45 96 101 63 85 85 84 75 76 75 89 88 93 92 82 82 -162 132 120 207 178 159 221 197 182 211 188 181 124 102 100 115 94 94 107 93 97 81 70 74 -48 39 39 57 47 47 125 106 105 108 99 100 76 72 80 27 26 30 80 71 76 84 81 89 -85 79 87 87 76 84 67 61 69 152 148 145 171 174 172 101 102 98 119 113 106 55 52 50 -33 32 34 67 58 63 59 46 51 76 59 63 88 71 74 127 110 105 173 152 144 183 159 153 -125 98 96 115 86 66 166 138 111 130 112 85 213 202 178 160 160 157 28 29 30 29 29 29 -28 28 29 32 31 31 47 45 43 58 63 44 60 70 34 58 66 36 63 69 40 64 70 36 -66 74 37 63 77 36 62 74 34 64 74 35 59 67 38 29 36 28 80 79 78 75 72 73 -167 168 169 227 230 232 165 175 196 28 42 68 20 29 46 21 29 40 18 26 40 12 17 28 -10 18 26 -100 85 81 165 156 156 216 216 216 236 236 236 233 236 232 122 128 94 103 106 64 106 108 64 -106 107 60 105 105 61 100 103 54 93 100 47 74 77 39 20 20 17 72 75 39 65 68 38 -25 24 22 72 69 48 93 93 52 90 92 53 89 89 80 85 88 93 84 80 85 88 68 68 -150 119 107 200 169 149 220 193 175 226 199 185 211 184 177 107 85 85 107 90 91 90 77 80 -66 51 53 23 18 18 111 94 88 120 105 105 75 73 84 57 57 68 92 82 87 78 69 73 -69 65 72 39 37 44 62 57 58 111 102 102 143 143 140 181 182 183 71 72 76 29 28 32 -34 32 36 60 50 55 59 42 48 83 63 68 138 115 108 197 172 154 218 193 176 227 203 188 -224 197 186 130 99 93 123 91 65 98 72 52 154 136 104 158 148 134 23 22 24 23 23 24 -34 31 33 36 33 34 45 42 43 61 59 53 74 80 49 89 98 54 91 100 55 76 93 38 -80 99 44 79 101 41 77 97 41 71 90 37 74 86 39 32 39 24 66 75 69 114 127 129 -209 217 219 231 236 242 129 145 166 26 40 66 19 29 45 18 28 37 20 27 42 13 18 31 -12 22 31 -92 79 74 159 149 149 209 208 210 240 240 239 245 245 244 157 162 143 98 104 60 98 105 56 -95 106 54 97 106 54 98 103 54 103 102 58 75 79 42 18 20 17 64 71 35 61 68 35 -26 24 21 76 77 51 94 102 55 99 107 64 95 100 79 83 83 88 65 54 54 81 64 64 -140 109 99 195 162 144 218 190 171 229 202 184 231 203 190 204 177 171 100 81 81 95 79 79 -70 55 54 22 17 16 56 46 43 112 93 93 60 56 62 57 58 67 96 91 96 101 90 95 -96 88 96 66 64 75 63 59 66 102 93 97 124 121 122 126 131 129 67 65 63 32 30 30 -42 37 42 48 38 43 63 47 51 117 96 92 181 152 138 207 179 160 222 196 179 230 205 189 -230 205 189 207 177 163 83 53 45 81 53 36 96 70 49 149 135 118 25 23 24 17 17 17 -32 30 31 40 35 38 44 42 44 54 52 54 45 43 39 74 76 48 88 98 50 87 101 48 -82 99 47 84 100 48 83 99 48 81 103 45 78 97 46 40 50 32 91 102 100 150 158 163 -211 219 218 228 232 242 75 92 114 26 40 60 20 29 44 16 26 35 22 31 43 15 24 34 -23 37 47 -90 78 76 120 109 107 185 185 185 233 233 233 246 246 246 199 207 196 94 111 60 97 109 58 -92 105 54 89 102 48 93 101 53 88 100 49 68 80 38 19 21 18 65 75 38 66 77 39 -23 23 21 80 83 58 89 102 51 91 107 55 86 100 69 68 68 67 67 53 51 81 63 65 -130 97 92 188 153 136 215 186 166 228 201 183 233 205 190 231 203 191 182 158 152 81 65 62 -60 44 42 41 30 29 44 33 33 58 44 43 63 52 49 42 39 44 94 89 96 99 91 97 -59 56 63 67 63 69 66 65 70 99 92 95 107 103 107 81 83 91 33 31 34 30 27 30 -45 38 42 48 38 41 89 74 68 160 133 122 192 162 145 210 183 165 225 199 184 232 207 193 -231 204 188 220 190 168 133 104 96 67 40 29 84 57 37 132 122 108 24 24 24 21 21 21 -26 25 26 42 37 38 55 49 50 40 39 39 32 31 31 38 38 28 76 88 47 81 94 50 -78 96 49 74 94 46 73 96 42 79 101 49 77 98 49 45 58 34 96 104 104 115 130 140 -160 171 172 188 195 205 28 45 67 24 35 56 22 29 47 15 22 33 21 30 47 17 26 40 -40 58 69 -136 133 130 111 100 99 158 156 158 221 217 216 239 236 235 218 221 216 90 91 67 73 71 48 -62 65 41 52 55 33 48 50 32 43 49 26 27 32 17 17 18 16 58 69 31 62 74 36 -21 22 19 47 49 38 42 49 26 46 56 31 55 61 49 64 56 55 71 57 55 78 63 64 -113 84 81 176 142 125 209 180 158 224 198 179 233 205 190 234 205 193 223 197 186 87 73 67 -53 39 37 45 35 32 56 43 40 62 47 45 87 71 68 103 89 91 100 95 100 110 102 106 -72 66 71 60 56 59 65 65 68 94 89 92 129 122 123 91 90 99 33 34 43 35 31 39 -56 50 52 73 59 56 142 118 108 180 149 134 201 169 151 216 190 171 227 204 189 234 211 197 -228 202 185 219 189 166 173 144 131 58 38 28 88 68 49 121 112 105 24 24 24 24 24 24 -24 22 24 45 40 41 60 55 54 46 46 46 34 34 34 27 25 24 36 37 26 32 39 24 -33 39 26 30 38 23 31 39 23 32 40 25 30 38 23 24 29 23 35 40 38 50 57 59 -61 71 69 64 76 85 22 35 56 21 32 50 22 29 46 14 19 30 20 29 44 17 26 38 -56 80 95 -241 240 240 204 202 200 126 113 108 181 149 139 196 169 155 207 180 170 203 165 153 189 148 140 -141 114 106 39 38 26 30 35 20 32 37 21 31 34 20 18 19 15 53 66 29 58 72 31 -21 20 18 18 21 15 20 25 13 22 26 15 28 31 22 65 60 49 75 61 58 78 62 63 -98 73 71 160 126 113 200 169 149 219 191 171 230 202 187 234 206 193 230 203 191 136 119 112 -59 47 39 62 48 41 58 44 39 72 54 50 70 54 49 93 76 72 116 103 104 94 83 85 -103 88 89 101 84 86 84 73 74 92 81 82 104 93 92 91 84 89 70 69 79 66 62 70 -73 62 61 123 102 94 171 143 127 194 162 144 209 181 161 221 197 179 230 208 194 233 211 196 -225 199 179 219 188 167 188 158 141 54 37 29 136 119 99 88 85 81 30 29 30 28 26 27 -24 24 24 51 47 47 63 56 57 58 57 57 44 44 44 40 38 39 32 27 25 23 22 19 -22 22 17 21 22 19 21 21 20 21 22 19 20 20 18 21 20 20 19 19 19 20 22 22 -21 24 26 17 25 39 18 27 44 20 29 46 20 29 42 13 19 27 20 26 43 16 27 39 -71 99 118 -227 228 228 222 209 202 193 158 141 180 142 127 209 173 160 205 165 149 203 154 140 211 158 151 -177 133 122 167 144 123 72 84 36 75 93 41 70 85 41 18 22 17 59 71 40 62 76 37 -19 19 16 41 48 29 66 80 36 74 84 41 70 81 42 79 89 50 79 74 58 80 64 66 -85 64 63 138 106 96 187 153 136 212 182 163 226 198 182 231 203 190 230 204 192 175 156 146 -69 55 49 73 58 52 67 52 50 69 55 51 76 58 53 78 64 59 110 92 89 86 73 73 -97 82 82 100 82 83 79 65 64 94 77 76 95 79 78 76 64 63 66 57 61 70 61 65 -103 82 79 161 133 118 192 161 141 206 176 155 217 190 172 226 204 187 233 214 200 231 210 195 -222 195 176 215 187 165 181 150 133 70 54 40 185 178 166 134 135 138 35 34 38 23 23 24 -28 27 27 53 46 48 65 56 56 65 63 62 58 57 57 40 40 40 51 49 37 60 62 41 -82 83 52 76 78 50 76 77 49 84 83 53 65 67 47 44 47 33 29 34 30 99 103 103 -121 123 124 46 54 70 12 20 37 12 21 31 16 25 35 13 19 28 20 27 40 25 40 48 -74 102 120 -208 208 206 153 130 117 119 89 73 143 109 97 210 172 159 200 161 148 141 104 96 146 112 107 -125 99 88 176 146 126 88 95 51 84 95 46 79 90 44 18 22 15 58 66 39 76 86 52 -20 21 18 51 53 37 86 88 53 93 88 56 81 83 48 88 97 54 80 79 56 83 66 66 -80 60 62 112 86 78 167 132 117 200 166 148 218 189 171 229 202 187 230 204 191 209 184 173 -74 62 58 73 62 59 75 61 57 73 59 54 79 63 58 73 59 57 73 60 57 93 77 74 -95 79 79 97 78 79 91 75 73 94 77 75 94 75 76 85 67 65 84 67 66 89 73 71 -148 120 109 191 160 141 207 181 158 216 189 169 223 199 182 230 209 196 233 213 199 226 202 186 -216 188 168 210 179 159 139 115 101 142 134 120 225 224 218 197 196 199 44 44 47 25 25 27 -32 32 32 50 43 45 63 56 56 60 59 58 61 61 58 49 49 49 51 50 47 60 63 43 -84 87 54 80 84 50 77 81 49 78 84 45 61 70 39 47 50 36 23 28 26 103 108 107 -133 134 136 51 59 75 17 25 40 16 21 31 13 21 30 14 19 28 18 25 36 46 68 78 -72 103 131 -122 118 113 70 44 37 74 45 39 85 56 49 133 94 82 150 111 97 197 158 145 200 164 149 -133 108 90 108 98 70 89 88 55 77 79 45 75 78 44 19 21 17 49 53 30 66 69 41 -19 20 18 50 50 41 74 74 46 78 77 50 69 70 43 67 77 39 54 60 36 82 69 65 -78 61 62 90 67 67 132 102 91 178 144 126 208 177 157 223 196 177 229 201 188 225 199 188 -99 85 82 77 63 61 77 65 62 76 63 57 77 64 58 72 60 56 46 38 38 72 59 54 -53 45 42 55 44 44 63 53 52 70 57 58 77 62 63 80 66 65 89 70 66 132 108 101 -185 154 137 206 176 157 217 192 171 223 200 183 229 207 193 231 211 197 227 205 191 219 192 175 -209 180 159 192 167 149 179 175 166 230 229 223 232 232 229 191 193 194 44 47 48 26 27 27 -36 34 35 45 40 41 59 55 53 60 56 56 60 59 60 50 50 52 42 41 42 42 40 33 -81 82 53 87 86 54 74 78 46 87 86 52 66 70 43 40 41 31 25 27 24 58 64 60 -106 111 113 24 36 49 19 25 36 13 18 27 12 15 23 10 14 20 17 28 40 60 88 105 -55 86 116 -27 23 20 58 45 37 73 59 45 69 41 35 88 53 46 74 44 37 95 59 49 149 112 100 -86 80 59 77 82 58 81 80 60 86 82 55 79 80 51 20 20 17 48 46 31 66 66 41 -19 21 19 50 52 42 76 83 50 86 92 56 75 81 47 80 90 45 73 85 45 85 76 61 -78 63 60 74 59 61 94 70 68 146 113 100 190 155 136 213 183 163 227 198 185 214 186 177 -152 127 124 168 138 133 156 132 127 84 70 67 78 64 59 77 62 55 67 54 49 89 72 64 -107 89 81 128 107 102 116 96 91 83 68 67 60 47 48 63 50 47 112 90 83 175 145 130 -207 177 159 217 189 170 225 200 183 228 206 191 230 209 195 226 204 190 220 196 178 210 182 160 -200 172 151 228 221 211 235 232 229 223 223 218 232 233 229 227 228 229 120 122 126 31 32 33 -44 37 40 46 39 38 60 58 56 63 59 58 55 55 54 50 50 48 43 42 41 36 35 34 -62 67 41 80 88 54 77 83 50 87 91 57 77 82 51 37 39 27 53 57 37 25 31 21 -70 82 62 21 33 44 13 21 36 13 20 31 13 18 28 8 13 20 17 31 45 72 103 127 -52 75 101 -28 20 19 85 77 58 76 75 48 73 68 43 52 31 24 59 36 30 101 71 65 102 79 75 -73 70 70 67 69 77 73 71 78 83 72 59 90 82 59 23 23 18 55 56 36 74 77 48 -19 19 17 41 44 34 77 80 48 75 77 46 69 71 41 80 79 48 68 72 43 74 68 50 -80 64 57 75 58 59 77 57 61 104 78 75 159 125 110 199 164 147 159 134 130 108 85 91 -121 89 92 169 130 126 185 144 138 212 182 175 105 91 85 81 64 61 149 107 103 206 175 170 -222 193 188 228 201 195 233 205 201 232 206 201 225 200 197 157 136 131 161 132 121 201 166 147 -217 187 167 224 198 180 229 205 189 228 206 190 223 200 184 217 194 176 210 182 162 200 169 149 -213 201 187 240 240 236 226 226 222 229 230 225 235 235 232 233 233 231 206 207 210 38 40 43 -44 39 40 37 35 36 56 55 54 64 62 63 52 52 51 49 49 48 46 42 43 40 36 37 -44 44 34 70 79 49 65 72 45 77 80 51 61 66 46 21 25 18 63 66 44 24 28 22 -54 68 42 33 45 50 16 25 35 11 18 28 11 13 21 10 15 25 32 45 60 56 74 95 -36 41 50 -71 57 54 134 108 100 114 96 80 64 61 42 17 14 14 35 25 26 66 49 51 98 87 91 -91 83 86 65 60 65 61 52 53 85 63 54 97 88 63 26 26 18 49 48 31 78 77 49 -19 20 17 54 53 42 105 101 69 95 91 62 90 87 59 76 71 48 56 54 41 51 46 37 -76 62 56 77 60 59 76 58 61 85 64 67 137 114 107 139 118 111 88 75 75 79 67 68 -70 55 56 76 54 54 97 65 61 137 108 98 93 81 73 82 65 62 109 67 64 157 117 108 -189 161 152 200 177 166 220 193 185 233 205 198 236 211 206 232 207 202 206 177 165 216 187 168 -223 196 178 229 202 187 229 202 186 222 197 179 214 188 168 208 182 162 196 166 146 193 176 157 -236 234 227 231 231 226 227 227 223 233 233 230 234 234 232 233 234 233 233 234 231 127 130 129 -51 50 52 32 32 33 33 34 34 34 36 35 45 45 46 52 52 52 44 44 44 38 37 36 -48 45 44 41 44 40 24 31 28 18 27 25 20 26 26 15 18 19 22 30 29 22 24 26 -19 30 31 22 34 49 17 24 41 12 18 33 10 14 25 11 17 27 45 56 70 31 38 50 -35 39 49 -100 84 82 107 100 115 110 98 105 29 28 25 37 29 32 69 58 61 72 60 59 91 80 83 -67 53 53 38 27 26 41 29 28 82 59 52 97 84 61 32 33 23 42 42 30 71 70 47 -24 24 22 45 45 39 83 78 57 70 66 47 60 56 43 47 46 40 37 34 32 26 23 22 -55 43 39 79 62 57 119 100 98 176 154 154 55 51 49 22 20 20 15 15 17 16 16 17 -23 22 23 26 24 22 31 29 28 34 32 31 38 37 36 53 51 51 72 69 70 115 109 107 -116 114 111 103 98 93 103 90 85 162 138 129 219 188 180 232 203 196 229 206 198 226 202 187 -230 204 188 228 201 184 222 193 175 210 182 160 203 174 153 192 160 141 182 159 142 231 226 219 -234 233 229 230 229 226 230 230 227 234 234 232 230 231 228 237 237 235 235 234 232 218 218 218 -194 195 193 150 152 153 54 57 60 25 27 26 35 35 36 51 51 51 56 55 57 36 36 36 -48 47 47 53 55 57 35 47 57 32 48 64 26 40 51 17 26 34 26 38 48 20 25 31 -21 33 45 19 30 51 17 26 41 13 19 33 9 13 24 12 20 31 34 45 58 15 20 34 -31 37 54 -131 121 111 107 106 104 56 50 52 48 35 37 87 78 81 121 115 114 132 124 123 76 65 64 -33 20 18 36 24 24 98 91 90 138 130 123 118 116 101 71 72 67 44 43 40 49 47 38 -39 36 32 59 50 46 58 52 46 39 35 33 39 35 35 32 29 28 29 26 25 24 22 22 -33 29 30 115 94 94 179 151 152 106 86 89 23 20 20 22 18 19 19 17 17 24 19 19 -26 23 20 41 34 28 53 44 38 63 52 45 49 43 37 57 46 41 52 43 41 64 60 56 -68 67 63 77 76 73 66 65 60 102 91 89 140 109 103 203 164 158 230 202 198 228 203 194 -228 202 188 220 191 173 211 177 156 199 165 144 187 153 135 173 151 135 222 219 211 236 235 233 -232 232 229 232 232 230 233 233 231 230 231 229 227 227 225 239 239 237 235 235 234 214 214 213 -197 198 194 217 218 215 196 198 202 45 47 52 30 30 31 43 43 43 45 45 45 37 36 36 -62 59 60 59 60 60 44 53 59 32 48 69 30 44 61 29 44 63 28 42 60 21 26 35 -19 30 42 18 30 48 15 22 37 12 19 30 10 18 29 10 20 33 39 49 61 24 29 44 -38 45 65 -54 48 41 52 38 37 69 47 50 93 74 77 152 141 140 179 172 168 113 106 102 39 31 29 -65 37 38 126 94 94 199 194 189 206 204 198 170 170 161 97 97 93 34 35 33 32 30 28 -55 45 42 50 43 40 30 28 26 38 32 31 27 24 24 18 18 17 19 17 18 30 26 26 -37 29 32 119 93 99 82 61 73 34 23 32 20 14 14 20 14 15 16 13 13 18 13 14 -18 13 13 21 15 17 20 15 14 28 20 18 24 19 17 31 23 22 24 18 17 22 18 18 -38 30 25 70 63 57 56 41 36 82 61 58 108 80 72 195 158 153 227 198 193 229 203 195 -221 195 179 210 178 158 196 160 140 180 146 128 168 147 134 212 207 199 224 224 219 222 222 219 -224 224 220 229 229 225 234 234 232 227 227 225 221 221 218 240 239 237 233 233 231 219 219 218 -185 186 183 203 204 199 231 231 230 140 143 149 26 27 30 29 29 29 32 32 32 46 46 44 -64 64 64 64 64 65 62 66 67 79 94 99 69 79 89 38 57 68 34 50 66 27 35 43 -22 33 47 21 32 48 18 27 44 14 21 37 10 19 31 10 20 37 46 56 66 32 36 45 -27 30 43 -66 49 47 69 50 50 146 129 130 157 143 143 105 84 75 93 67 59 59 38 37 44 37 37 -116 53 59 139 112 109 179 177 165 186 181 170 139 136 126 71 69 63 32 31 29 37 32 29 -47 41 36 30 29 27 34 30 27 26 24 23 22 20 21 11 11 11 17 14 15 22 21 21 -37 27 28 79 53 59 70 50 61 53 38 48 27 19 23 18 14 12 17 12 12 17 11 11 -18 12 12 20 12 13 22 14 15 24 15 16 24 16 16 28 19 18 30 20 21 27 18 19 -32 23 20 112 87 82 169 131 128 184 147 141 197 167 160 223 195 191 228 203 199 223 194 187 -209 179 164 193 161 142 176 143 129 131 109 100 107 99 93 126 124 118 133 129 121 137 133 125 -150 146 140 169 167 160 204 203 196 224 225 221 215 216 209 234 234 230 224 224 222 205 205 201 -206 207 202 227 227 224 231 232 229 193 194 199 27 31 35 25 26 25 37 36 36 48 48 47 -64 64 64 51 52 53 65 66 65 131 139 134 128 133 133 135 142 139 138 145 145 123 129 126 -121 125 133 20 30 50 19 27 42 16 24 39 12 20 34 10 20 38 27 38 49 39 45 55 -14 14 22 -60 38 34 69 44 42 106 78 72 97 62 54 91 49 39 84 45 41 52 32 28 59 42 43 -104 38 43 114 99 93 152 144 133 162 156 143 92 89 81 54 50 46 30 29 29 35 28 27 -39 34 34 25 23 23 35 26 25 26 21 21 14 13 13 11 10 11 20 16 16 21 19 20 -13 13 13 59 41 40 81 54 55 75 45 50 66 39 49 48 34 39 23 14 15 21 13 14 -17 12 13 17 12 12 18 12 13 21 13 13 21 13 15 22 15 15 24 16 19 25 18 19 -35 22 20 121 77 75 147 90 92 185 135 128 213 178 171 216 187 180 215 180 174 209 176 163 -195 164 148 174 145 133 120 101 94 77 68 67 76 68 65 74 66 63 84 75 71 100 91 85 -110 100 92 115 105 95 126 122 111 226 226 219 235 234 230 227 227 223 216 216 214 217 218 215 -227 227 225 228 228 226 227 227 225 196 197 201 48 50 52 54 52 50 53 52 51 62 59 57 -64 65 65 54 54 57 59 60 58 124 128 118 147 151 144 153 156 148 160 162 158 140 144 136 -143 145 147 21 33 51 24 34 51 19 26 42 15 23 38 12 21 38 17 28 42 42 48 58 -10 11 13 -56 31 26 62 33 26 83 44 38 94 42 30 86 39 28 77 36 29 62 44 36 75 37 38 -97 34 35 96 83 74 137 128 114 129 124 112 81 73 68 46 40 39 22 20 19 33 27 25 -32 28 28 17 16 16 30 23 23 27 22 22 9 9 9 13 11 11 19 16 15 14 14 14 -7 7 7 31 22 23 80 58 56 78 46 44 79 42 44 83 51 54 34 17 20 22 13 14 -22 15 15 21 15 13 22 15 15 24 16 17 33 19 20 74 48 51 82 58 63 42 26 31 -46 26 31 110 73 73 115 67 64 123 71 63 150 104 97 161 119 110 177 136 123 204 171 156 -170 143 133 114 99 96 77 71 72 79 74 75 79 76 77 80 76 77 79 77 77 78 73 71 -89 82 78 109 98 90 154 149 138 230 229 223 225 226 221 221 221 219 225 226 223 229 229 227 -226 227 225 224 224 221 212 212 212 141 143 148 59 59 57 70 67 67 54 53 52 61 59 58 -65 65 64 62 62 62 58 58 57 87 89 83 168 169 163 176 177 169 180 180 176 134 136 130 -127 127 125 79 87 94 70 77 94 50 58 81 21 30 46 14 22 34 15 25 41 18 27 37 -20 21 21 -40 19 17 46 24 16 63 28 19 82 33 22 82 36 24 92 45 33 87 62 52 133 83 81 -80 38 34 101 90 76 122 113 102 92 88 78 68 62 54 35 33 31 20 16 17 33 27 25 -30 29 28 14 14 12 27 23 21 20 17 18 7 7 7 11 9 10 19 16 17 12 11 11 -7 7 7 18 14 13 73 55 52 77 53 52 76 49 48 77 48 52 65 39 45 61 37 42 -64 43 47 48 29 32 23 13 13 24 16 14 75 44 42 117 76 75 128 95 97 86 57 63 -81 56 61 85 51 56 82 42 48 83 42 44 94 52 48 145 106 99 185 148 135 186 153 143 -107 95 93 97 95 95 140 140 136 167 165 162 177 176 173 179 179 175 174 174 170 168 168 164 -160 161 156 162 162 156 203 203 193 229 229 226 227 227 224 225 225 223 221 221 219 215 215 213 -212 212 210 215 215 213 162 165 168 43 45 49 47 47 48 67 66 66 56 55 54 53 53 53 -63 63 64 65 65 65 62 63 61 58 60 57 127 130 123 172 174 166 185 186 182 133 133 129 -109 108 104 101 102 105 84 87 100 64 71 87 25 34 53 17 25 40 20 30 43 25 31 39 -45 45 44 -35 15 11 31 16 12 40 17 14 62 27 19 80 37 25 95 50 33 68 42 31 137 106 98 -75 56 47 108 100 86 107 101 89 79 75 69 60 56 50 40 37 34 19 17 15 33 27 28 -26 25 25 12 12 11 28 21 22 17 14 15 7 7 7 13 11 12 17 14 14 10 10 10 -6 6 6 10 9 9 70 62 60 75 56 52 72 48 44 77 50 51 76 46 45 80 43 46 -83 42 49 82 43 47 27 13 13 23 14 14 61 36 35 77 38 39 91 51 46 94 60 54 -97 65 63 98 63 64 96 59 58 94 58 55 116 80 74 142 106 96 154 116 104 125 102 93 -87 79 81 115 110 110 152 150 146 174 173 169 195 196 191 211 212 207 217 218 213 218 219 214 -217 217 213 215 216 212 211 212 208 205 205 204 192 192 192 192 192 190 196 196 194 208 208 206 -218 218 216 210 211 211 80 82 87 34 33 35 31 31 33 56 55 56 59 59 59 47 47 48 -55 55 54 60 59 58 58 55 56 56 56 55 72 76 70 168 171 161 185 186 182 156 160 153 -139 137 134 102 102 101 83 86 91 62 64 75 28 33 45 19 27 40 23 31 43 45 48 50 -78 72 66 -25 11 9 23 10 10 25 11 10 50 24 19 71 38 28 73 50 40 66 49 36 136 117 107 -85 72 63 101 92 79 99 94 86 77 75 74 57 57 56 35 34 31 22 20 19 36 32 29 -26 24 23 13 11 11 26 19 20 14 12 12 8 8 8 17 13 15 12 12 12 8 8 9 -7 7 7 18 18 19 81 82 89 71 58 54 67 43 42 72 46 47 72 45 45 73 40 39 -73 35 40 79 40 48 49 24 29 37 23 22 89 56 56 79 41 48 78 43 46 80 47 51 -87 53 57 91 54 53 96 59 54 139 103 96 174 140 132 160 125 116 160 127 117 79 70 68 -68 65 65 69 64 65 70 66 68 75 72 71 85 83 82 100 99 98 118 116 114 143 143 141 -168 167 162 174 174 169 165 165 162 170 170 166 184 184 180 200 201 197 213 214 210 215 216 212 -218 218 216 174 174 176 121 106 98 81 69 63 36 33 32 44 43 43 64 63 62 41 38 41 -37 36 37 55 54 53 56 52 53 58 56 55 68 69 66 151 153 146 183 183 178 158 162 155 -178 179 176 77 83 91 32 42 53 28 34 49 35 39 51 37 39 50 22 28 38 52 49 47 -89 81 71 -21 11 8 22 11 9 31 14 11 56 31 27 27 17 15 89 84 80 99 88 80 123 99 83 -83 74 60 109 100 90 98 98 95 76 77 77 60 59 59 43 41 39 20 17 18 37 31 30 -20 19 18 11 11 10 24 20 19 13 12 11 10 10 10 15 12 12 11 11 9 8 8 9 -15 14 11 84 82 78 80 84 94 67 64 68 71 52 56 65 42 45 68 44 41 71 40 38 -77 39 41 85 45 48 60 30 33 22 13 13 49 29 27 73 39 38 89 56 53 95 63 62 -98 64 64 101 64 61 124 85 78 140 99 89 139 101 93 122 89 80 103 90 86 74 72 75 -75 74 76 77 76 79 78 78 79 78 78 79 79 79 82 87 88 90 100 99 98 127 126 124 -158 157 153 183 182 177 191 191 186 200 200 196 201 202 197 205 206 201 201 202 197 207 208 204 -201 203 204 110 120 133 138 127 123 141 127 118 137 119 110 94 81 77 64 64 67 37 36 46 -31 30 34 39 37 38 54 48 49 61 59 58 67 67 65 117 110 107 166 157 155 134 140 135 -154 159 154 122 128 130 86 88 92 99 97 104 88 86 100 46 44 59 16 16 17 49 43 39 -58 48 40 -30 13 13 34 18 15 53 29 24 32 21 18 25 17 17 82 69 66 91 70 60 118 91 72 -97 91 77 131 127 121 101 101 99 75 77 77 67 64 65 43 40 38 16 14 14 30 25 24 -24 22 22 13 11 12 23 19 18 12 11 11 11 11 11 15 13 13 12 12 11 25 23 17 -118 109 96 134 127 119 78 83 93 61 64 71 61 55 62 69 49 55 69 44 50 67 37 42 -68 34 42 35 15 18 20 13 12 17 13 12 18 13 15 18 13 12 33 17 17 55 30 29 -71 42 40 94 59 57 154 114 107 198 166 158 178 148 141 153 138 133 179 179 175 176 177 175 -169 169 166 173 173 169 169 170 166 172 173 169 165 165 163 173 173 170 143 143 142 135 134 132 -156 156 151 178 179 173 175 176 171 184 184 182 185 186 183 200 201 198 203 203 200 205 205 203 -157 163 173 86 98 124 82 95 120 82 95 119 91 97 117 71 75 91 77 89 114 82 93 120 -65 71 91 31 30 33 44 38 39 77 66 65 138 116 116 191 161 162 192 164 167 155 155 150 -181 183 176 168 171 168 136 136 134 115 110 119 79 76 92 22 20 28 26 24 25 51 44 39 -66 56 43 -48 25 20 59 43 37 54 35 28 89 71 59 60 44 35 71 46 36 98 63 52 120 94 77 -129 121 113 128 127 123 95 96 95 77 79 78 76 74 72 39 39 36 16 15 14 23 20 21 -22 20 21 12 11 13 26 21 21 15 13 14 12 12 11 16 13 14 26 23 19 115 105 91 -155 141 123 120 114 106 72 78 84 63 67 76 57 61 71 61 58 65 60 44 49 60 30 35 -68 32 40 30 14 17 16 11 11 17 12 12 18 12 13 43 22 25 86 47 57 123 81 82 -202 172 165 222 194 188 219 190 182 202 172 166 125 112 117 75 80 94 80 85 101 71 76 90 -70 72 79 70 73 80 82 88 93 102 109 115 100 107 112 123 126 134 114 119 126 112 118 124 -126 129 132 142 146 148 134 137 138 143 145 146 154 156 155 175 176 174 185 187 184 193 197 198 -111 120 139 76 87 116 70 80 109 78 90 119 74 87 115 67 83 109 76 91 120 79 93 121 -82 91 119 76 70 85 137 105 113 163 120 132 181 137 150 167 130 141 129 113 115 153 156 149 -181 181 176 170 171 169 163 163 158 115 108 109 52 46 45 21 21 20 40 37 33 58 49 44 -70 58 49 -65 36 31 124 116 110 40 35 31 78 55 39 86 63 43 73 46 36 109 72 58 126 98 83 -136 130 124 120 121 117 104 104 102 82 82 81 85 84 77 35 35 32 16 15 15 23 20 19 -21 20 20 13 12 13 25 21 22 19 17 18 17 16 15 22 20 19 98 90 84 119 108 97 -108 99 89 78 74 66 42 44 46 42 44 51 46 47 56 48 48 56 31 31 36 22 18 17 -23 15 15 20 13 13 18 12 12 18 12 12 19 13 13 36 18 19 75 38 38 107 57 54 -149 107 98 155 115 109 133 100 91 87 73 80 63 68 89 70 76 103 74 83 108 78 88 114 -72 78 103 69 78 98 73 82 105 79 89 113 76 86 110 79 90 115 80 88 114 78 89 113 -77 90 108 82 94 114 92 98 120 99 103 122 101 109 122 119 128 141 97 106 124 79 89 110 -74 87 112 64 75 102 71 82 108 77 90 118 74 88 116 75 86 114 75 89 117 75 89 115 -78 88 115 93 85 101 134 95 98 135 93 110 95 70 81 70 61 61 66 63 62 71 73 72 -85 89 88 79 82 84 77 78 78 81 75 73 41 36 35 26 24 22 61 50 44 68 56 49 -71 59 52 -79 39 28 61 41 35 25 17 16 75 51 34 138 100 69 93 64 46 119 81 64 118 90 75 -123 118 112 128 126 124 102 102 99 81 81 79 84 81 75 28 28 26 14 14 14 22 18 19 -21 20 20 15 13 14 23 18 19 19 18 19 19 17 18 37 37 38 39 39 38 28 28 29 -26 27 27 22 23 26 9 10 14 9 9 12 13 14 18 16 16 18 18 16 16 19 18 16 -17 15 15 15 14 14 16 14 13 17 13 14 21 15 16 25 16 15 29 17 15 38 20 18 -46 25 20 71 47 31 129 98 79 94 76 71 41 43 58 51 54 75 49 56 78 49 54 75 -48 56 79 54 64 85 59 69 89 73 82 107 70 81 106 65 75 100 51 60 82 45 53 76 -40 45 65 39 44 64 40 47 66 43 47 67 38 43 60 41 49 69 48 58 78 58 70 91 -71 83 108 76 87 114 72 82 112 62 71 99 58 69 94 72 83 110 78 90 117 75 88 116 -68 81 108 112 107 111 135 108 96 111 77 69 75 60 55 71 60 53 58 49 48 26 28 29 -36 52 61 39 53 69 33 39 51 42 40 40 24 22 18 61 51 43 64 54 50 67 56 50 -74 63 54 -87 44 30 47 24 18 78 51 43 70 51 39 123 92 67 112 78 57 122 80 63 112 86 71 -121 117 112 123 120 117 99 99 96 79 79 76 72 70 64 21 20 20 15 15 15 21 17 18 -19 18 18 21 18 18 23 19 18 24 23 23 23 23 23 30 32 31 26 26 26 23 24 23 -21 24 29 11 14 22 10 10 16 17 19 26 23 23 30 15 13 14 13 12 13 17 13 14 -15 13 14 15 13 13 17 13 13 25 17 15 37 27 24 29 20 17 42 28 19 70 49 37 -101 72 54 138 94 73 136 86 69 126 84 75 55 39 38 20 20 26 21 21 30 25 25 34 -28 30 42 34 39 54 40 45 63 64 71 93 74 83 109 72 82 110 58 67 92 44 53 76 -31 35 54 22 25 37 19 23 34 21 24 36 38 43 58 55 65 83 69 81 103 70 81 105 -65 76 100 57 66 92 48 59 82 49 55 80 51 60 86 68 77 102 77 87 114 78 90 117 -67 76 102 126 118 114 170 147 126 136 105 87 111 76 65 68 46 41 29 22 23 17 17 19 -37 51 60 42 60 80 33 39 50 25 25 25 19 19 17 50 42 35 66 55 52 66 58 52 -69 58 53 -86 43 30 53 29 21 52 36 29 85 59 45 86 62 47 121 87 66 117 74 56 106 88 72 -115 112 108 114 113 109 91 90 88 85 83 79 64 61 55 18 18 17 16 14 15 19 16 17 -17 18 17 25 23 23 28 23 22 30 30 28 28 28 27 28 28 29 24 24 27 22 25 32 -14 17 29 21 23 33 28 29 39 24 24 34 17 16 22 16 13 14 14 9 11 16 8 10 -21 9 8 40 15 10 70 26 16 95 42 23 106 52 28 113 59 33 129 72 43 138 82 54 -140 82 55 135 76 52 132 78 59 128 76 69 114 78 74 44 32 32 17 16 20 17 17 20 -18 17 20 19 20 25 24 25 33 40 44 59 63 71 96 79 89 117 83 93 123 82 93 121 -76 88 115 71 82 107 65 73 96 70 78 102 69 77 104 65 73 99 61 71 95 55 62 85 -48 54 78 45 53 74 51 58 81 59 69 91 61 73 95 61 70 94 64 74 97 75 86 111 -67 72 95 144 132 120 171 149 129 163 138 120 123 87 70 117 79 65 35 25 20 16 16 16 -36 40 43 41 57 75 33 36 41 19 19 20 14 15 15 49 43 36 68 58 53 68 60 54 -73 62 55 -109 80 74 110 88 81 74 61 53 54 41 29 68 40 30 119 87 68 108 71 52 81 67 54 -92 90 87 108 106 104 84 83 82 92 89 84 51 49 45 18 17 17 18 15 16 21 19 20 -17 15 15 32 30 29 34 28 26 25 23 23 29 29 28 26 27 27 29 29 35 25 30 42 -29 30 42 25 29 41 28 27 39 38 29 35 50 27 29 57 24 18 61 22 14 69 23 15 -81 31 17 90 34 18 94 37 19 103 42 20 111 44 17 116 45 17 124 51 19 126 56 27 -132 65 35 133 71 44 132 77 56 128 74 62 122 74 67 116 78 72 60 43 43 16 14 16 -15 15 18 16 16 20 19 18 23 22 21 29 36 40 54 49 56 76 65 73 100 69 79 106 -70 78 105 63 72 100 56 67 91 54 61 86 48 55 78 44 49 72 37 42 62 34 40 58 -43 53 72 56 65 86 60 71 96 62 73 96 57 66 88 32 38 56 33 40 53 66 75 98 -71 75 85 162 143 124 169 148 125 172 151 129 146 117 98 137 95 77 97 66 55 16 14 14 -52 51 48 50 65 81 28 30 35 18 19 20 15 15 14 46 37 32 68 58 50 69 59 51 -74 63 53 -38 20 16 29 16 13 84 83 80 118 115 110 68 39 32 112 84 65 98 70 50 42 37 29 -94 91 87 91 92 89 78 77 74 89 85 78 41 39 36 22 19 18 20 18 19 20 17 18 -18 16 17 32 31 29 35 29 29 22 22 23 35 34 36 38 38 45 28 31 42 25 28 40 -37 32 44 49 36 44 68 35 36 77 31 26 85 33 21 90 34 22 94 36 19 93 37 18 -100 42 20 103 44 20 105 45 19 106 45 20 107 46 21 111 47 22 118 51 25 118 51 23 -123 54 25 126 61 35 133 72 49 132 76 57 127 73 57 121 74 59 118 80 73 99 71 67 -60 47 46 29 23 25 19 19 22 20 19 23 23 22 27 29 29 41 35 40 55 43 46 69 -44 49 71 41 46 67 36 40 58 35 38 55 30 32 47 29 31 50 42 48 68 51 60 83 -49 59 81 56 65 90 64 74 100 60 69 97 67 77 103 66 72 96 24 25 39 54 61 80 -119 110 102 164 142 120 165 144 121 171 150 128 167 139 117 128 90 75 126 83 69 59 43 36 -44 41 41 44 55 67 24 25 26 18 18 18 16 16 16 39 32 26 67 54 44 70 61 49 -73 60 52 -18 10 9 19 11 12 62 63 62 92 85 79 78 43 32 109 81 60 83 59 41 33 28 24 -59 56 53 76 77 76 85 82 79 79 72 68 35 33 30 23 19 18 19 19 18 18 16 17 -25 22 23 36 34 38 28 29 35 20 23 29 25 27 38 24 29 42 32 31 43 42 30 39 -46 24 27 59 28 22 77 40 29 96 61 45 101 69 54 96 63 47 102 69 51 101 67 48 -106 71 51 110 77 56 103 73 53 115 82 61 123 89 66 125 85 59 122 74 48 125 71 46 -124 64 42 124 64 42 125 68 50 131 78 59 132 77 62 129 75 58 126 73 61 122 75 63 -119 81 74 113 81 78 92 69 70 56 44 45 23 20 23 23 22 28 27 25 35 24 24 36 -24 23 35 22 21 33 21 21 32 29 30 42 42 47 63 53 60 82 50 59 84 45 54 77 -44 51 74 54 63 88 70 82 109 75 89 117 72 86 114 76 84 114 54 59 82 70 73 77 -154 136 117 163 142 120 164 142 119 167 147 126 177 150 126 123 89 72 130 84 69 103 68 56 -56 49 48 44 50 59 23 23 26 17 17 18 16 16 19 32 26 22 60 46 36 63 52 45 -68 55 52 -23 13 15 21 15 15 67 68 65 66 51 44 79 42 28 129 97 73 54 43 32 31 26 22 -40 36 34 74 73 73 81 78 73 68 63 58 35 32 30 20 16 17 11 11 11 32 30 32 -37 37 42 23 25 35 19 21 33 24 26 38 26 28 38 32 24 34 36 20 24 42 25 24 -69 50 42 73 53 42 76 54 45 75 53 44 70 51 37 74 50 38 71 51 39 79 57 43 -94 70 56 101 77 60 111 91 72 107 84 67 106 83 66 114 86 70 118 89 69 117 87 70 -124 87 70 122 79 62 129 77 60 128 77 58 130 82 67 127 81 69 128 75 64 126 72 60 -120 69 59 116 70 64 114 72 71 119 86 86 105 80 78 68 56 60 29 28 35 25 24 30 -26 25 37 31 32 47 42 43 62 53 56 77 56 62 86 51 57 83 47 52 78 45 51 76 -42 50 73 48 58 83 68 79 104 73 87 113 79 88 117 79 88 118 77 89 117 81 90 112 -134 123 113 159 138 115 163 140 118 173 155 136 175 147 125 132 98 82 136 92 80 131 85 70 -57 43 38 41 41 49 22 22 25 16 16 16 16 17 16 33 28 27 58 46 36 69 56 45 -73 58 48 -31 20 19 53 42 37 62 52 47 62 33 26 72 40 27 138 104 75 54 44 33 29 24 21 -30 28 26 66 64 62 78 74 70 64 59 55 38 34 31 28 26 28 34 36 43 26 27 33 -15 16 24 20 20 30 21 23 33 25 20 28 28 17 22 33 21 22 53 40 35 51 41 36 -50 38 33 54 36 28 70 54 44 72 58 47 80 69 55 85 71 59 93 81 70 91 79 67 -78 66 56 73 60 50 70 60 52 85 75 63 100 86 72 105 84 71 109 88 72 105 82 69 -117 91 78 124 100 85 122 98 83 127 88 71 128 81 68 122 79 68 121 79 72 120 74 68 -122 73 63 119 69 62 117 69 67 120 83 81 123 93 90 123 92 87 105 84 82 64 55 58 -43 45 61 44 49 70 51 58 80 51 60 84 53 61 83 50 57 82 45 53 75 45 50 74 -42 48 72 46 53 77 55 63 87 63 74 100 71 82 110 75 89 116 75 90 117 79 90 117 -91 95 112 145 127 113 160 138 117 180 160 141 161 131 107 136 108 92 137 94 81 138 85 67 -99 73 64 36 37 43 21 21 23 16 16 20 15 15 18 37 32 29 57 44 38 69 55 42 -75 59 47 -30 15 15 76 56 45 33 21 14 57 32 20 42 23 12 115 82 55 65 54 40 50 43 35 -62 56 45 83 75 67 86 78 69 79 70 64 49 49 51 28 30 39 14 17 25 15 14 19 -16 17 26 20 19 29 24 16 22 26 15 18 31 21 21 35 27 26 28 22 20 35 26 25 -53 44 38 58 48 37 60 48 41 58 46 40 30 23 20 31 23 19 32 21 17 31 19 17 -26 16 13 26 17 16 26 18 15 25 17 16 40 30 24 44 35 26 85 71 59 97 80 68 -110 90 77 118 98 85 141 123 112 140 121 110 129 103 87 133 95 83 124 83 76 116 74 72 -115 70 71 121 73 68 118 73 68 122 77 73 116 76 77 118 81 73 118 85 81 124 95 89 -99 82 88 70 69 88 59 66 90 55 63 89 54 59 84 50 57 81 49 55 78 48 54 77 -47 54 78 52 60 86 57 64 91 58 70 96 63 75 101 71 82 109 75 88 115 78 89 119 -80 88 118 100 100 109 164 147 131 179 156 137 143 110 88 155 126 113 138 94 80 136 85 67 -120 86 75 36 35 42 21 21 24 16 16 21 14 14 15 34 30 24 52 44 45 54 46 45 -62 52 50 -36 25 20 68 52 41 63 54 46 90 72 59 75 70 59 91 82 71 92 87 80 98 93 85 -100 98 92 102 98 94 80 75 73 34 35 40 17 21 28 14 14 18 13 13 18 16 15 25 -16 16 22 17 14 16 24 14 17 32 23 22 36 30 30 23 21 20 26 24 21 46 43 38 -48 41 35 37 27 21 26 15 14 26 15 12 25 17 14 27 17 16 28 16 12 34 20 16 -30 17 15 27 16 15 26 17 16 28 17 16 31 19 16 30 18 16 31 19 16 35 22 19 -53 40 32 97 82 70 127 108 90 147 130 121 171 157 149 141 121 107 145 115 105 138 105 98 -121 87 84 117 81 80 118 78 79 121 83 82 120 82 79 121 80 75 124 82 74 128 90 82 -122 89 87 111 87 87 72 65 79 52 57 80 49 53 77 47 52 76 48 52 76 47 50 74 -45 51 75 47 55 80 51 60 84 54 63 88 55 62 88 59 68 95 66 77 102 72 83 110 -79 89 118 82 93 120 133 129 128 170 143 122 123 91 70 172 142 131 147 100 78 143 89 66 -129 86 68 36 35 35 20 20 22 16 17 20 13 12 13 32 28 21 60 49 44 66 54 50 -73 61 52 -84 85 78 93 92 87 93 94 92 101 99 95 94 96 95 95 95 96 91 90 89 91 86 82 -75 75 72 56 56 57 24 26 31 17 18 23 14 13 19 15 14 19 15 14 20 15 14 19 -15 12 13 17 15 15 31 23 24 36 30 29 17 16 16 30 28 26 31 27 25 24 20 16 -29 18 14 27 15 11 26 15 12 27 14 13 29 15 12 28 15 11 29 16 10 31 15 12 -33 16 15 29 17 15 30 17 15 32 18 16 34 19 16 33 19 15 35 21 17 37 21 18 -36 20 19 42 28 23 79 64 51 104 87 73 143 128 121 164 149 136 138 121 108 148 124 114 -169 145 139 154 127 115 123 98 91 132 98 92 136 104 99 133 96 88 127 91 84 135 99 92 -128 90 86 129 89 85 119 86 80 97 77 79 49 48 65 44 47 68 45 48 72 45 50 74 -51 56 82 52 63 88 55 63 91 58 65 91 59 67 92 60 68 95 62 73 100 68 79 106 -77 84 114 79 90 119 111 111 120 162 131 111 135 108 89 180 151 144 156 110 89 143 90 67 -145 98 70 50 44 41 20 20 24 16 16 18 15 15 15 37 30 24 62 52 43 71 57 49 -72 58 49 
+ tests/cbbe1/Main.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- ChalkBoard Back End Example 1+-- August 2009+-- Kevin Matlage+++module Main where++import Graphics.ChalkBoard+import Graphics.ChalkBoard.CBIR+import Graphics.ChalkBoard.OpenGL.CBBE+import Control.Concurrent.MVar+import Control.Concurrent+import Foreign.Ptr (Ptr)+import Foreign.C.Types (CUChar)+import Graphics.ChalkBoard.Core	-- TODO: remove, and fix with O++++main = do startChalkBoard [] main2+++-- Will need to fork off a thread to pass more instructions to the mvar if we want animation+-- Do we want an mvar for the board as well so that we can switch which board we are displaying?+main2 :: ChalkBoard -> IO ()+main2 cb = do+    let ex = example1+    let   animation speed 100 _ = drawRawChalkBoard cb [Exit]+	  animation speed count [] =  drawRawChalkBoard cb [Exit]+	  animation speed count (inst:insts) = do+               drawRawChalkBoard cb inst+               threadDelay speed+	       animation speed (succ count) insts+    animation 0{-1000000-} 2 (fst ex)+++-- Hardcode example of some CBIR instructions+-- The first instruction is *always* setting the the viewing board (??)+example1:: ([[Inst BufferId]], BufferId)+example1 = ( +             [[ Allocate 0 (sz,sz) RGBADepth (BackgroundRGBADepth (RGBA 1 1 1 1))+             , Allocate 1 (sz,sz) RGBADepth (BackgroundRGBADepth (RGBA 0 0 1 0.6))+             , Allocate 2 (sz,sz) RGBADepth (BackgroundRGBADepth (RGBA 0 1 1 0.6))+             , Allocate 3 (sz,sz) RGBADepth (BackgroundRGBADepth (RGBA 0 1 0 0.6))+             , Allocate 4 (sz,sz) RGBADepth (BackgroundRGBADepth (RGBA 1 0 1 0.6))+     	]] ++  +	     [	[+              SplatTriangle ((i + j) `mod` 4 + 1) +			     0 (PointMap (1,1) (0.5,0.5)) +			        (PointMap (1,1) (0.5 + scale * sin (fromIntegral j/10),0.5 + scale * cos (fromIntegral j/10)))+			        (PointMap (1,1) (0.5 + scale * sin (fromIntegral j/8),0.5 + scale * cos (fromIntegral j/8)))+	     | j <- [0..5000]+	     ] | i <- [0..]+	     ] , 0 )+  where scale = 0.2+        sz = 200+example2:: ([[Inst BufferId]], BufferId)+example2 = ( [ Allocate 0 (500,500) RGBADepth (BackgroundG8Bit 0.8)+	     , AllocateImage 2 "back.jpg"+	     , Allocate 3 (1,1) RGBADepth (BackgroundG8Bit 0.8)+             , AllocateImage 6 "jhwk_RF_250px.gif"+	     , SplatPolygon 3 0 [(PointMap (0,0) (0,0)), (PointMap (1,0) (1,0)), (PointMap (1,1) (1,1)), (PointMap (0,1) (0,1))]+             ] :+ 	     [ [ SplatPolygon 2 0 [(PointMap (t0,t0) (0,0)), (PointMap (t1,t0) (1,0)), (PointMap (t1,t1) (1,1)), (PointMap (t0,t1) (0,1))]+	       , SplatPolygon 6 0 [(PointMap (0,0) (0+x,0.5 - y)), (PointMap (0,1) (0 + x,1 - y)), (PointMap (1,1) (0.5 + x,1 - y)), (PointMap (1,0) (0.5  + x,0.5 - y))]+	       ]+	     | (x,y,z) <- zip3 (let t = take (50 * 5) [0,0.002..] in cycle (t ++ reverse t))+			       (let t = take (40 * 5) [0,0.0025..] in cycle (t ++ reverse t))+			       (let t = take (40 * 20) [0,0.00025..] in cycle (t ++ reverse t))+	     , let t0 = z+	     , let t1 = 1 - z+	     ]+           , 0+           )+           +example3 :: ([[Inst BufferId]], BufferId)+example3 = ( [[ AllocateImage 1 "back.jpg"+             ,  Allocate 2 (300,300) RGBADepth (BackgroundRGBADepth (RGBA 1 1 1 1))+             ,  SplatPolygon 1 2 [(PointMap (0,0) (0,0)), (PointMap (1,0) (1,0)), (PointMap (1,1) (1,1)), (PointMap (0,1) (0,1))]+             ,  SplatColor (RGBA 0 0 0 1) 2 True [(0.15,0.15), (0.145,0.145), (0.145,0.855), (0.15,0.85)]+             ,  SplatColor (RGBA 0 0 0 1) 2 True [(0.15,0.85), (0.145,0.855), (0.855,0.855), (0.85,0.85)]+             ,  SplatColor (RGBA 0 0 0 1) 2 True [(0.85,0.85), (0.855,0.855), (0.855,0.85), (0.8535,0.8465),+                                               (0.1535,0.1465), (0.15,0.145), (0.145,0.145), (0.15,0.15)]+             ,  SaveImage 2 "TestImage1.bmp"+	     ,  Allocate 3 (300,300) RGBADepth (BackgroundRGBADepth (RGBA 0.9 0 0 1))+	     ,  Allocate 0 (300,300) RGBADepth (BackgroundRGBADepth (RGBA 0 0 0 0.5))+	         ]] +++	         [[  SplatColor (RGBA 0 0 0.9 1) 3 True [(x0,t0), (x1,t0), (x1,t1), (x0,t1)]+	            | t0 <- [0,0.1..0.9], let t1 = t0+0.1, x0 <- if ((round (t1*10))`mod`2==0) then [0,0.2..0.8] else [0.1,0.3..0.9], let x1 = x0+0.1+	         ]]+	         ++ [[+             --,  SplatPolygon 1 3 [(PointMap (0.25,0.25) (0.25,0.75)), (PointMap (0.25,0.75) (0.75,0.75)), (PointMap (0.75,0.75) (0.25,0.75))] -- to flip it+                SplatPolygon 1 3 [(PointMap (0.15,0.15) (0.85,0.85)), (PointMap (0.15,0.85) (0.85,0.15)), (PointMap (0.85,0.85) (0.15,0.15))]+             ,  SplatColor (RGBA 0 0 0 1) 3 True [(0.85,0.85), (0.855,0.855), (0.855,0.145), (0.85,0.15)]+             ,  SplatColor (RGBA 0 0 0 1)  3 True [(0.85,0.15), (0.855,0.145), (0.145,0.145), (0.15,0.15)]+             ,  SplatColor (RGBA 0 0 0 1) 3 True [(0.15,0.15), (0.145,0.145), (0.145,0.15), (0.1465,0.1535),+                                               (0.8465,0.8535), (0.85,0.855), (0.855,0.855), (0.85,0.85)]+             ,  SaveImage 3 "TestImage2.bmp"+             ,  CopyBuffer WithDestAlpha 3 0+             ,  SaveImage 0 "TestImage3.bmp"+             ,  SplatBuffer 0 0+             ,  SaveImage 0 "TestImage0.bmp"+             ]]+           , 0+           )+	          ++++--foreign import ccall "&" myptr :: Ptr CUChar
+ tests/chalkmark/Main.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -ddump-simpl-stats #-}+module Main where+	+import Graphics.ChalkBoard as CB hiding (Board)+--import Control.Applicative+import Data.Array+import System.Cmd+import Graphics.ChalkBoard+++main = startChalkBoard [] $ \ chalkBoard -> do+	let loop n d | n > 3 = exitChalkBoard chalkBoard+      	    loop n d = do+  	        drawChalkBoard chalkBoard (example10 n)+	        loop (n+d) d+	loop 0 0.01++example10 :: R -> Board RGB+example10 rX = rotate rX $ scale (0.5 + 0.5 * log (1 + (rX / 1))) +	$ (unAlpha <$> (foldr (\ (x,y) w -> cir1 (x,y) (rX/(x+count)) (rX/(y+count)) `over` w) (boardOf (alpha white))+		$ [ (x,y) | x <- [0..count], y <- [0..count]]))+  where+    cir1 (x,y) r r2 =  +	   move (-0.5 + x / count,-0.5 + y / count)+         $ rotate (r2 * 200)  	+	 $ scaleXY (0.5,1)+  	 $ scale (0.8 / count)+	 ( choose (alpha c) (transparent white) <$> square)+       where c = o $ RGB (x/count) (y/count) ((rX / 3) - fromIntegral (floor (rX / 3)))+	     r' = r * 50 + y+	+    count = 20 -- + (fromIntegral(round (rX * 2) :: Int))+--	20 -- 10 -- 1-- 20++
+ tests/simple/Main.hs view
@@ -0,0 +1,52 @@+module Main where++import Graphics.ChalkBoard+++main = startChalkBoard [] cbMain++++cbMain cb = do+        let example1 = boardOf blue+            example2 = scale 0.5 $ choose red green <$> square+            example3 = scale 0.5 $ choose red blue <$> circle `over` (scale 0.9 square)+            example4 = unAlpha <$> scale 0.5 (choose (withAlpha 0.2 blue) (transparent white) <$> triangle (-0.5,-0.5) (0.5,-0.5) (0,0.5))+            example5 = unAlpha <$> ((scale 0.7 cir) `over` poly)+                    where+                            cir = choose (withAlpha 0.5 blue) (transparent white) <$> circle+                            poly = choose (alpha red) (transparent white) <$> polygon [(0,-0.5), (-0.4,-0.3), (0,0.5), (0.4,-0.3)]+        +        +        (w,h,imgBrd) <- readBoard ("lambda.png")+        let wh = fromIntegral $ max w h+            sc = 1 / wh+            wd = fromIntegral w / wh+            hd = fromIntegral h / wh+            img = move (-0.5 * hd,-0.5 * wd)  (scale sc imgBrd)+	    +	(w2,h2,img2) <- readNormalizedBoard ("lambda.png")+	    +	let example6 = unAlpha <$> img2+	    example7 = unAlpha <$> img2 `over` (boardOf (alpha red))+	    example8 = unAlpha <$> (rotate 1 (scale 0.8 img2)) `over` (boardOf (alpha red))+	    +	    +	let example9 x = unAlpha <$> (rotate x (scale 0.8 img2)) `over` (boardOf (alpha red))+	    example10 x = unAlpha <$> (rotate (4*x) (scale x img2)) `over` (boardOf (alpha (o (RGB x x x))))+	+        +        drawChalkBoard cb example6+        --sequence_ [ drawChalkBoard cb (example9 x) | x <- [0,0.01..] ]+++++++{-+example1 cb = drawChalkBoard cb $ boardOf blue++example2 cb = drawChalkBoard cb $ scale 0.5 $ choose red blue <$> square++--}
+ tests/test1/Main.hs view
@@ -0,0 +1,145 @@+module Main where+	+import Graphics.ChalkBoard as CB+--import Control.Applicative+import Data.Array+import System.Cmd+import System.Environment+import Graphics.ChalkBoard+--	(white,  black,  red,   green,  blue,  cyan,  purple,  yellow, RGB(..), RGBA(..))++import Graphics.ChalkBoard.CBIR as CBIR++-- A rather messy test, tries out various aspects of our compiler and render engine.++-- normal test+main = do+	args <- getArgs+	case args of+	  ["server"] -> do+		cb <- openChalkBoard [BoardSize 100 100]+		cbMain cb+	  _ -> startChalkBoard [BoardSize 100 100] $ cbMain++-- server test+--main = do cb <- openChalkBoard []+--          cbMain cb++colors :: [(O RGB,String)]+colors = zip +	[white,  black,  red,   green,  blue,  cyan,  purple,  yellow]+	["white","black","red","green","blue","cyan","purple","yellow"]++cbMain cb = do++	-- first examples, pure colors.+	sequence_ [ do drawChalkBoard cb (boardOf col)+		       writeChalkBoard cb ("test1-" ++ nm ++ ".png")+		  | (col,nm) <- colors+		  ]++	-- load an image to use for rotations, etc.+	(x,y,imgBrd) <- readBoard ("images/cb-text.png")+	let xy = fromIntegral $ max x y+	let sc = 1 / xy+	let xd = fromIntegral x / xy+	let yd = fromIntegral y / xy+	let img = unAlpha <$> move (-0.5 * yd,-0.5 * xd)  (scale sc imgBrd)++	-- next, test basic shapes with rotations, scalings, etc.+        sequence_ [ do+	   	sequence_ [ do drawChalkBoard cb (scale n shape)+		               writeChalkBoard cb ("test2-scale-" ++ shape_name ++ "-" ++ show n ++ ".png")+	                  | n <- [1,0.5]+		          ]+	   	sequence_ [ do drawChalkBoard cb ((rotate r (scale 0.5 shape))+					 )+		               writeChalkBoard cb ("test2-rotate-" ++ shape_name ++ "-" ++ nm ++ ".png")+	             	  | (r,nm) <- zip+				[0,0.1,-0.1,pi/10,pi,2*pi]+				["0","0.1","neg0.1","pi_div10","pi","2pi"]+		          ]+	   	sequence_ [ do drawChalkBoard cb ((move (x,y) (scale 0.5 shape))+					 )+		               writeChalkBoard cb ("test2-move-" ++ shape_name ++ "-" ++ nmY ++ nmX ++ ".png")+	 	     	  | let amount = 0.25+		          , (x,nmX) <- [(-amount,"left"),(0,"center"),(amount,"right")]+	 	          , (y,nmY) <- [(amount,"top"),(0,"middle"),(-amount,"bottom")]+		          ]+		sequence_ [ do  drawChalkBoard cb ((scaleXY (x,y) shape)+					 )+		                writeChalkBoard cb ("test2-scaleXY-" ++ shape_name ++ "_" ++ nmX ++ "_" ++ nmY ++ "_.png")+			  | let ranges =  [(1,"1"),(0.5,"0.5"),(0.1,"0.1"),(-0.1,"neg0.1")]+			  , (x,nmX) <- ranges+			  , (y,nmY) <- ranges+			  ]+		sequence_ [ do  drawChalkBoard cb ((f (scale 0.5 shape))+					 )+		                writeChalkBoard cb ("test2-chain-" ++ shape_name ++ "-" ++ chain ++ ".png")+			  | let ranges =  [(1,"1"),(0.5,"0.5"),(0.1,"0.1"),(-0.1,"neg0.1")]+			  , (f,chain) <- [ (move (0.2,0.2) . rotate 1, "move-after-rot")+					 , (rotate 1 . move (0.2,0.2), "rot-after-move")+					 , (move (0.2,0.2) . scale 0.9, "move-after-scale")+					 , (scale 0.9 . move (0.2,0.2), "scale-after-move")+					 ]+			  ]+			+            | (shape,shape_name) <- [ (choose (red) (white) <$> square,"square")+				    , (choose (blue) (white) <$> circle,"circle")+				    , (img,"img")+				    , (choose (green) (white) <$> triangle (-0.5,-0.5) (0.5,-0.5) (0,0.5),"triangle")+				    ]+            ]++	-- load an image; display it.+	sequence_ [ do+		(x,y,imgBrd) <- readBoard ("images/" ++ nm)+		let xy = max x y+		drawChalkBoard cb (unAlpha <$> move (-0.5,-0.5) (scale (1/fromIntegral xy) imgBrd))+		writeChalkBoard cb $ "test3-image-load-" ++ nm ++ ".png"+	   | nm <- [ "cb-text.gif"+		   , "cb-text.jpg"+		   , "cb-text.png"+		   ] +	   ]++	sequence_ [ do let r = move (0.26,0.15)  (choose (withAlpha a red) (transparent white) <$> circle)+	                   g = move (-0.26,0.15) (choose (withAlpha a green) (transparent white) <$> circle)+	                   b = move (0,-0.3)      (choose (withAlpha a blue) (transparent white) <$> circle)+		       drawChalkBoard cb (scale 0.5 (unAlpha <$> (r `over` b `over` g `over` boardOf (transparent white))))+		       writeChalkBoard cb $ "test4-" ++ show a ++  ".png"+		 | a <- [0,0.5,0.7,0.9,1]+		 ]++	-- These should be a single color,+	-- and not bleed through each other++	sequence_ [ do let r = move (0.26,0.15) circle+	                   g = move (-0.26,0.15) circle+	                   b = move (0,-0.3)    circle+		       drawChalkBoard cb (scale 0.5 (unAlpha <$> +							(choose (withAlpha a green) (transparent white) <$>+							    (r `over` b `over` g))))+		       writeChalkBoard cb $ "test5-" ++ show a ++  ".png"+		 | a <- [0,0.5,0.7,0.9,1]+		 ]++-- This should show a single shape of overlap between the two snowmen.+++	sequence_ [ do let rs0 = [ move (i * 0.26,j * 0.26) circle+			        | i <- [-1,1], j <- [-1,1]+			        ]+		       let rs = [ scale i b | (i,b) <- zip [1,0.9..] rs0 ]+		       drawChalkBoard cb (scale 0.5 (unAlpha <$> +							((choose (withAlpha a green) +								(transparent white) <$>+							    ((rs !! 0) `over` (rs !! 1))) `over`+							 (choose (withAlpha a red) +								(transparent white) <$>+							    ((rs !! 2) `over` (rs !! 3))))))+		       writeChalkBoard cb $ "test6-" ++ show a ++  ".png"+		 | a <- [0,0.5,0.7,0.9,1]+		 ]++	exitChalkBoard cb
+ tests/test1/images/cb-text.gif view

binary file changed (absent → 9987 bytes)

+ tests/test1/images/cb-text.jpg view

binary file changed (absent → 10676 bytes)

+ tests/test1/images/cb-text.png view

binary file changed (absent → 65114 bytes)

+ tutorial/basic/Main.hs view
@@ -0,0 +1,42 @@+module Main where++import Graphics.ChalkBoard+++main = startChalkBoard [] cbMain+++cbMain cb = do+        let example1 = boardOf blue+            example2 = scale 0.5 $ choose red green <$> square+            example3 = scale 0.5 $ choose red blue <$> circle `over` (scale 0.9 square)+            example4 = unAlpha <$> scale 0.5 (choose (withAlpha 0.2 blue) (transparent white) <$> triangle (-0.5,-0.5) (0.5,-0.5) (0,0.5))+            example5 = unAlpha <$> ((scale 0.7 cir) `over` poly)+                    where+                            cir = choose (withAlpha 0.5 blue) (transparent white) <$> circle+                            poly = choose (alpha red) (transparent white) <$> polygon [(0,-0.5), (-0.4,-0.3), (0,0.5), (0.4,-0.3)]+        +        +        (w,h,imgBrd) <- readBoard ("lambda.png")+        let wh = fromIntegral $ max w h+            sc = 1 / wh+            wd = fromIntegral w / wh+            hd = fromIntegral h / wh+            img = move (-0.5 * hd,-0.5 * wd)  (scale sc imgBrd)+	+	(w2,h2,img2) <- readNormalizedBoard ("lambda.png")+	+	+	let example6 = unAlpha <$> img2+	    example7 = unAlpha <$> img2 `over` (boardOf (alpha (o (RGB 0.5 1 0.8))))+	    example8 = unAlpha <$> move (0.25, -0.25) ((rotate 1 (scale 0.7 img2)) `over` (boardOf (alpha red)))+	+	+	let example9 x = unAlpha <$> (rotate (5*x) (scale 0.8 img2)) `over` (boardOf (alpha red))+	    example10 x = unAlpha <$> (rotate (4*x) (scale (abs x) img2)) `over` (boardOf (alpha (o (RGB x x (abs x)))))+	+        +        drawChalkBoard cb example1+        --sequence_ [ drawChalkBoard cb (example9 (sin x)) | x <- [0,0.01..] ]++
+ tutorial/basic/tutorial.pdf view

binary file changed (absent → 240143 bytes)