diff --git a/codeworld-api.cabal b/codeworld-api.cabal
--- a/codeworld-api.cabal
+++ b/codeworld-api.cabal
@@ -1,11 +1,12 @@
 Name:                codeworld-api
-Version:             0.2.2.1
+Version:             0.2.3
 Synopsis:            Graphics library for CodeWorld
 License:             Apache
 License-file:        LICENSE
 Author:              The CodeWorld Authors
 Maintainer:          Chris Smith <cdsmith@gmail.com>
 Copyright:           (c) 2018, The CodeWorld Authors
+Bug-reports:         https://github.com/google/codeworld/issues
 Build-type:          Simple
 Cabal-version:       >=1.8
 
@@ -20,14 +21,16 @@
 
 Library
   Hs-source-dirs:      src
-  Exposed-modules:     CodeWorld
+  Exposed-modules:     CodeWorld,
+                       CodeWorld.App,
+                       CodeWorld.App2
   Other-modules:       CodeWorld.CanvasM,
                        CodeWorld.Color,
                        CodeWorld.Picture,
                        CodeWorld.Event,
                        CodeWorld.Driver
                        CodeWorld.CollaborationUI
-  Build-depends:       base                 >= 4.8 && < 5,
+  Build-depends:       base                 >= 4.9 && < 5,
                        containers           >= 0.5.7 && < 0.6,
                        hashable             >= 1.2.4 && < 1.3,
                        text                 >= 1.2.2 && < 1.3,
@@ -51,3 +54,4 @@
 
   Exposed:             True
   Ghc-options:         -O2
+                       -Werror=incomplete-patterns
diff --git a/src/CodeWorld/App.hs b/src/CodeWorld/App.hs
new file mode 100644
--- /dev/null
+++ b/src/CodeWorld/App.hs
@@ -0,0 +1,107 @@
+{-# LANGUAGE GADTSyntax #-}
+{-# LANGUAGE KindSignatures #-}
+
+{-
+  Copyright 2018 The CodeWorld Authors. All rights reserved.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-}
+
+module CodeWorld.App
+    {-# WARNING "This is an experimental API.  It can change at any time." #-}
+    (
+    Rule,
+    timeRule,
+    eventRule,
+    pictureRule,
+    multiEventRule,
+    multiPictureRule,
+    subrule,
+    rules,
+    applicationOf,
+    unsafeMultiApplicationOf
+    ) where
+
+import CodeWorld
+import Data.List (foldl')
+import System.Random (StdGen)
+
+data Rule :: * -> * where
+    TimeRule :: (Double -> state -> state) -> Rule state
+    EventRule :: (Int -> Event -> state -> state) -> Rule state
+    PictureRule :: (Int -> state -> Picture) -> Rule state
+    Rules :: [Rule state] -> Rule state
+
+timeRule :: (Double -> state -> state) -> Rule state
+timeRule = TimeRule
+
+eventRule :: (Event -> state -> state) -> Rule state
+eventRule = EventRule . const
+
+pictureRule :: (state -> Picture) -> Rule state
+pictureRule = PictureRule . const
+
+multiEventRule :: (Int -> Event -> state -> state) -> Rule state
+multiEventRule = EventRule
+
+multiPictureRule :: (Int -> state -> Picture) -> Rule state
+multiPictureRule = PictureRule
+
+subrule :: (a -> b) -> (b -> a -> a) -> Rule b -> Rule a
+subrule getter setter (TimeRule step_b) = TimeRule step_a
+  where step_a dt a = setter (step_b dt (getter a)) a
+subrule getter setter (EventRule event_b) = EventRule event_a
+  where event_a k ev a = setter (event_b k ev (getter a)) a
+subrule getter setter (PictureRule pic_b) = PictureRule pic_a
+  where pic_a n = pic_b n . getter
+subrule getter setter (Rules rules) = Rules (map (subrule getter setter) rules)
+
+rules :: [Rule state] -> Rule state
+rules = Rules
+
+applicationOf :: world -> [Rule world] -> IO ()
+applicationOf w rules = interactionOf w step event picture
+  where step dt   = foldl' (.) id [ f dt | f <- concatMap stepHandlers rules ]
+        event ev  = foldl' (.) id [ f ev | f <- concatMap eventHandlers rules ]
+        picture w = pictures [ pic w | pic <- concatMap pictureHandlers rules ]
+
+        stepHandlers (TimeRule f)       = [f]
+        stepHandlers (Rules rs)         = concatMap stepHandlers rs
+        stepHandlers _                  = []
+
+        eventHandlers (EventRule f)     = [f 0]
+        eventHandlers (Rules rs)        = concatMap eventHandlers rs
+        eventHandlers _                 = []
+
+        pictureHandlers (PictureRule f) = [f 0]
+        pictureHandlers (Rules rs)      = concatMap pictureHandlers rs
+        pictureHandlers _               = []
+
+unsafeMultiApplicationOf :: Int -> (StdGen -> state) -> [Rule state] -> IO ()
+unsafeMultiApplicationOf n initial rules =
+    unsafeCollaborationOf n initial step event picture
+  where step dt     = foldl' (.) id [ f dt | f <- concatMap stepHandlers rules ]
+        event k ev  = foldl' (.) id [ f k ev | f <- concatMap eventHandlers rules ]
+        picture k w = pictures [ pic k w | pic <- concatMap pictureHandlers rules ]
+
+        stepHandlers (TimeRule f)       = [f]
+        stepHandlers (Rules rs)         = concatMap stepHandlers rs
+        stepHandlers _                  = []
+
+        eventHandlers (EventRule f)     = [f]
+        eventHandlers (Rules rs)        = concatMap eventHandlers rs
+        eventHandlers _                 = []
+
+        pictureHandlers (PictureRule f) = [f]
+        pictureHandlers (Rules rs)      = concatMap pictureHandlers rs
+        pictureHandlers _               = []
diff --git a/src/CodeWorld/App2.hs b/src/CodeWorld/App2.hs
new file mode 100644
--- /dev/null
+++ b/src/CodeWorld/App2.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE GADTSyntax #-}
+{-# LANGUAGE KindSignatures #-}
+
+{-
+  Copyright 2018 The CodeWorld Authors. All rights reserved.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-}
+
+module CodeWorld.App2
+    {-# WARNING "This is an experimental API.  It can change at any time." #-}
+    (
+    Application,
+    defaultApplication,
+    withTimeStep,
+    withEventHandler,
+    withPicture,
+    withMultiEventHandler,
+    withMultiPicture,
+    subapplication,
+    applicationOf
+    ) where
+
+import CodeWorld
+import Data.List (foldl')
+import System.Random (StdGen)
+
+data Application :: * -> * where
+    App :: state
+        -> (Double -> state -> state)
+        -> (Int -> Event -> state -> state)
+        -> (Int -> state -> Picture)
+        -> Application state
+
+defaultApplication :: state -> Application state
+defaultApplication s =
+    App s (const id) (const (const id)) (const (const blank))
+
+withTimeStep :: (Double -> state -> state)
+             -> Application state
+             -> Application state
+withTimeStep f (App initial step event picture) =
+    App initial (\dt -> f dt . step dt) event picture
+
+withEventHandler :: (Event -> state -> state)
+                 -> Application state
+                 -> Application state
+withEventHandler f (App initial step event picture) =
+    App initial step (\k ev -> f ev . event k ev) picture
+
+withPicture :: (state -> Picture) -> Application state -> Application state
+withPicture f (App initial step event picture) =
+    App initial step event (\k s -> f s & picture k s)
+
+withMultiEventHandler :: (Int -> Event -> state -> state)
+                      -> Application state
+                      -> Application state
+withMultiEventHandler f (App initial step event picture) =
+    App initial step (\k ev -> f k ev . event k ev) picture
+
+withMultiPicture :: (Int -> state -> Picture)
+                 -> Application state
+                 -> Application state
+withMultiPicture f (App initial step event picture) =
+    App initial step event (\k s -> f k s & picture k s)
+
+subapplication :: (a -> b)
+               -> (b -> a -> a)
+               -> Application b
+               -> (b -> a)
+               -> Application a
+subapplication getter setter (App initial step event picture) f =
+    App (f initial)
+        (\dt s   -> setter (step dt (getter s)) s)
+        (\k ev s -> setter (event k ev (getter s)) s)
+        (\k      -> picture k . getter)
+
+applicationOf :: Application world -> IO ()
+applicationOf (App initial step event picture) =
+    interactionOf initial step (event 0) (picture 0)
diff --git a/src/CodeWorld/CollaborationUI.hs b/src/CodeWorld/CollaborationUI.hs
--- a/src/CodeWorld/CollaborationUI.hs
+++ b/src/CodeWorld/CollaborationUI.hs
@@ -251,4 +251,4 @@
         colored connectColor (solidRectangle 14 3)
     connectColor =
         let k = (1 + sin (3 * t)) / 5
-        in fromHSL (k + 0.5) 0.8 0.7
+        in HSL (k + 0.5) 0.8 0.7
diff --git a/src/CodeWorld/Driver.hs b/src/CodeWorld/Driver.hs
--- a/src/CodeWorld/Driver.hs
+++ b/src/CodeWorld/Driver.hs
@@ -77,12 +77,13 @@
 import qualified Data.JSString
 import Data.JSString.Text
 import Data.Word
+import GHCJS.Concurrent (withoutPreemption)
 import GHCJS.DOM
 import qualified GHCJS.DOM.ClientRect as ClientRect
 import GHCJS.DOM.Document
 import GHCJS.DOM.Element
 import GHCJS.DOM.EventM
-import GHCJS.DOM.GlobalEventHandlers
+import GHCJS.DOM.GlobalEventHandlers hiding (error)
 import GHCJS.DOM.MouseEvent
 import GHCJS.DOM.NonElementParentNode
 import GHCJS.DOM.Types (Element, unElement)
@@ -209,11 +210,28 @@
 type NodeId = Int
 
 pictureToDrawing :: Picture -> Drawing
-pictureToDrawing (Polygon _ pts s) = Shape $ polygonDrawer pts s
-pictureToDrawing (Path _ pts w c s) = Shape $ pathDrawer pts w c s
+pictureToDrawing (SolidClosedCurve _ pts) = Shape $ polygonDrawer pts True
+pictureToDrawing (SolidPolygon _ pts) = Shape $ polygonDrawer pts False
+pictureToDrawing (Polygon _ pts) = Shape $ pathDrawer pts 0 True False
+pictureToDrawing (ThickPolygon _ pts w) = Shape $ pathDrawer pts w True False
+pictureToDrawing (Rectangle _ w h) = Shape $ pathDrawer (rectangleVertices w h) 0 True False
+pictureToDrawing (SolidRectangle _ w h) = Shape $ polygonDrawer (rectangleVertices w h) False
+pictureToDrawing (ThickRectangle _ lw w h) = Shape $ pathDrawer (rectangleVertices w h) lw True False
+pictureToDrawing (ClosedCurve _ pts) = Shape $ pathDrawer pts 0 True True
+pictureToDrawing (ThickClosedCurve _ pts w) = Shape $ pathDrawer pts w True True
+pictureToDrawing (Circle _ r) = Shape $ arcDrawer 0 (2 * pi) r 0
+pictureToDrawing (SolidCircle _ r) = Shape $ sectorDrawer 0 (2 * pi) r 
+pictureToDrawing (ThickCircle _ r lw) = Shape $ arcDrawer 0 (2 * pi) r lw
+pictureToDrawing (Polyline _ pts) = Shape $ pathDrawer pts 0 False False
+pictureToDrawing (ThickPolyline _ pts w) = Shape $ pathDrawer pts w False False
+pictureToDrawing (Curve _ pts) = Shape $ pathDrawer pts 0 False True
+pictureToDrawing (ThickCurve _ pts w) = Shape $ pathDrawer pts w False True
 pictureToDrawing (Sector _ b e r) = Shape $ sectorDrawer b e r
-pictureToDrawing (Arc _ b e r w) = Shape $ arcDrawer b e r w
-pictureToDrawing (Text _ sty fnt txt) = Shape $ textDrawer sty fnt txt
+pictureToDrawing (Arc _ b e r) = Shape $ arcDrawer b e r 0
+pictureToDrawing (ThickArc _ b e r w) = Shape $ arcDrawer b e r w
+pictureToDrawing (Text _ txt) = Shape $ textDrawer Plain Serif txt
+pictureToDrawing (Blank _) = Drawings $ []
+pictureToDrawing (StyledText _ sty fnt txt) = Shape $ textDrawer sty fnt txt
 pictureToDrawing (Logo _) = Shape $ logoDrawer
 pictureToDrawing (CoordinatePlane _) = Shape $ coordinatePlaneDrawer
 pictureToDrawing (Color _ col p) =
@@ -437,22 +455,163 @@
 picToObj' :: Picture -> State.StateT Int IO JSVal
 picToObj' pic =
     case pic of
-        Polygon cs pts smooth -> do
+        SolidPolygon cs pts -> do
+            obj <- init "solidPolygon"
+            ptsJS <- pointsToArr pts
+            setProps [("points", ptsJS), ("smooth", pToJSVal False)] obj
+            retVal obj
+        SolidClosedCurve cs pts -> do
+            obj <- init "solidClosedCurve"
+            ptsJS <- pointsToArr pts
+            setProps [("points", ptsJS), ("smooth", pToJSVal True)] obj
+            retVal obj
+        Polygon cs pts -> do
             obj <- init "polygon"
             ptsJS <- pointsToArr pts
-            setProps [("points", ptsJS), ("smooth", pToJSVal smooth)] obj
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal (0 :: Double))
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
             retVal obj
-        Path cs pts w closed smooth -> do
-            obj <- init "path"
+        ThickPolygon cs pts w -> do
+            obj <- init "thickPolygon"
             ptsJS <- pointsToArr pts
             setProps
                 [ ("points", ptsJS)
                 , ("width", pToJSVal w)
-                , ("closed", pToJSVal closed)
-                , ("smooth", pToJSVal smooth)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
                 ]
                 obj
             retVal obj
+        Rectangle _ w h -> do
+            obj <- init "rectangle"
+            setProps
+                [ ("width",  pToJSVal w)
+                , ("height", pToJSVal h)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        SolidRectangle _ w h -> do
+            obj <- init "solidRectangle"
+            setProps 
+                [ ("width",  pToJSVal w)
+                , ("height", pToJSVal h)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        ThickRectangle _ lw w h-> do
+            obj <- init "thickRectangle"
+            setProps
+                [
+                  ("linewidth", pToJSVal lw)
+                , ("width",  pToJSVal w)
+                , ("height", pToJSVal h)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        ClosedCurve cs pts -> do
+            obj <- init "closedCurve"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal (0 :: Double))
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal True)
+                ]
+                obj
+            retVal obj
+        ThickClosedCurve cs pts w -> do
+            obj <- init "thickClosedCurve"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal w)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal True)
+                ]
+                obj
+            retVal obj
+        Circle cs r -> do
+            obj <- init "circle"
+            setProps
+                [ ("radius", pToJSVal r)
+                , ("closed", pToJSVal True)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        SolidCircle cs r -> do
+            obj <- init "solidCircle"
+            setProps
+                [ ("radius", pToJSVal r)
+                , ("closed", pToJSVal True)
+                ]
+                obj
+            retVal obj
+        ThickCircle cs r lw -> do
+            obj <- init "thickCircle"
+            setProps
+                [ ("radius", pToJSVal r)
+                , ("linewidth", pToJSVal lw)
+                , ("endAngle", pToJSVal True)
+                , ("radius", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        Polyline cs pts -> do
+            obj <- init "polyline"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal (0 :: Double))
+                , ("closed", pToJSVal False)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        ThickPolyline cs pts w -> do
+            obj <- init "thickPolyline"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal w)
+                , ("closed", pToJSVal False)
+                , ("smooth", pToJSVal False)
+                ]
+                obj
+            retVal obj
+        Curve cs pts -> do
+            obj <- init "curve"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal (0 :: Double))
+                , ("closed", pToJSVal False)
+                , ("smooth", pToJSVal True)
+                ]
+                obj
+            retVal obj
+        ThickCurve cs pts w -> do
+            obj <- init "thickCurve"
+            ptsJS <- pointsToArr pts
+            setProps
+                [ ("points", ptsJS)
+                , ("width", pToJSVal w)
+                , ("closed", pToJSVal False)
+                , ("smooth", pToJSVal True)
+                ]
+                obj
+            retVal obj
         Sector cs b e r -> do
             obj <- init "sector"
             setProps
@@ -462,19 +621,37 @@
                 ]
                 obj
             retVal obj
-        Arc cs b e r w -> do
+        Arc cs b e r -> do
             obj <- init "arc"
             setProps
                 [ ("startAngle", pToJSVal b)
                 , ("endAngle", pToJSVal e)
                 , ("radius", pToJSVal r)
+                , ("width", pToJSVal (0 :: Double))
+                ]
+                obj
+            retVal obj
+        ThickArc cs b e r w -> do
+            obj <- init "thickArc"
+            setProps
+                [ ("startAngle", pToJSVal b)
+                , ("endAngle", pToJSVal e)
+                , ("radius", pToJSVal r)
                 , ("width", pToJSVal w)
                 ]
                 obj
             retVal obj
-        Text cs style font txt -> do
+        Text cs txt -> do
             obj <- init "text"
             setProps
+                [ ("font", pToJSVal $ fontString Plain Serif)
+                , ("text", pToJSVal txt)
+                ]
+                obj
+            retVal obj
+        StyledText cs style font txt -> do
+            obj <- init "styledText"
+            setProps
                 [ ("font", pToJSVal $ fontString style font)
                 , ("text", pToJSVal txt)
                 ]
@@ -519,6 +696,7 @@
             setProps [("pictures", unsafeCoerce arr)] obj
             retVal obj
         Logo cs -> init "logo" >>= retVal
+        Blank cs -> init "blank" >>= retVal
         CoordinatePlane cs -> init "coordinatePlane" >>= retVal
   where
     incId :: State.StateT Int IO Int
@@ -566,11 +744,28 @@
     Data.List.find ((== "main") . srcLocPackage . snd) (getCallStack cs)
 
 getPictureCS :: Picture -> CallStack
-getPictureCS (Polygon cs _ _) = cs
-getPictureCS (Path cs _ _ _ _) = cs
+getPictureCS (SolidPolygon cs _) = cs
+getPictureCS (SolidClosedCurve cs _) = cs
+getPictureCS (Polygon cs _) = cs
+getPictureCS (ThickPolygon cs _ _) = cs
+getPictureCS (Rectangle cs _ _) = cs
+getPictureCS (SolidRectangle cs _ _) = cs
+getPictureCS (ThickRectangle cs _ _ _) = cs
+getPictureCS (ClosedCurve cs _) = cs
+getPictureCS (ThickClosedCurve cs _ _) = cs
+getPictureCS (Circle cs _) = cs
+getPictureCS (SolidCircle cs _) = cs
+getPictureCS (ThickCircle cs _ _) = cs
+getPictureCS (Polyline cs _) = cs
+getPictureCS (ThickPolyline cs _ _) = cs
+getPictureCS (Curve cs _) = cs
+getPictureCS (ThickCurve cs _ _) = cs
 getPictureCS (Sector cs _ _ _) = cs
-getPictureCS (Arc cs _ _ _ _) = cs
-getPictureCS (Text cs _ _ _) = cs
+getPictureCS (Arc cs _ _ _) = cs
+getPictureCS (ThickArc cs _ _ _ _) = cs
+getPictureCS (Text cs _) = cs
+getPictureCS (Blank cs) = cs
+getPictureCS (StyledText cs _ _ _) = cs
 getPictureCS (Color cs _ _) = cs
 getPictureCS (Translate cs _ _ _) = cs
 getPictureCS (Scale cs _ _ _) = cs
@@ -1387,6 +1582,7 @@
             case proto of
                 "http:" -> "ws://" <> hostname <> ":9160/gameserver"
                 "https:" -> "wss://" <> hostname <> "/gameserver"
+                _ -> error "Unrecognized protocol"
     return url
 
 connectToGameServer :: (ServerMessage -> IO ()) -> IO WS.WebSocket
@@ -1604,7 +1800,7 @@
     debugState <- newMVar debugStateInit
     let draw =
             flip drawDebugState (pictureToDrawing pic) <$> readMVar debugState
-        drawToScreen = do
+        drawToScreen = withoutPreemption $ do
             drawing <- draw
             rect <- getBoundingClientRect canvas
             buffer <-
diff --git a/src/CodeWorld/Picture.hs b/src/CodeWorld/Picture.hs
--- a/src/CodeWorld/Picture.hs
+++ b/src/CodeWorld/Picture.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 {-
   Copyright 2018 The CodeWorld Authors. All rights reserved.
 
@@ -48,14 +50,47 @@
 dotProduct (x1, y1) (x2, y2) = x1 * x2 + y1 * y2
 
 data Picture
-    = Polygon CallStack
+    = SolidPolygon CallStack
               [Point]
-              !Bool
-    | Path CallStack
+    | SolidClosedCurve CallStack
+              [Point]
+    | Polygon CallStack
            [Point]
+    | ThickPolygon CallStack
+           [Point]
            !Double
-           !Bool
-           !Bool
+    | Rectangle CallStack
+           !Double
+           !Double
+    | SolidRectangle CallStack
+           !Double
+           !Double
+    | ThickRectangle CallStack
+           !Double
+           !Double
+           !Double
+    | ClosedCurve CallStack
+           [Point]
+    | ThickClosedCurve CallStack
+           [Point]
+           !Double
+    | Polyline CallStack
+           [Point]
+    | ThickPolyline CallStack
+           [Point]
+           !Double
+    | Curve CallStack
+           [Point]
+    | ThickCurve CallStack
+           [Point]
+           !Double
+    | Circle CallStack
+           !Double
+    | SolidCircle CallStack
+           !Double
+    | ThickCircle CallStack
+           !Double
+           !Double
     | Sector CallStack
              !Double
              !Double
@@ -64,11 +99,17 @@
           !Double
           !Double
           !Double
+    | ThickArc CallStack
           !Double
-    | Text CallStack
+          !Double
+          !Double
+          !Double
+    | StyledText CallStack
            !TextStyle
            !Font
            !Text
+    | Text CallStack
+           !Text
     | Color CallStack
             !Color
             !Picture
@@ -86,6 +127,7 @@
     | CoordinatePlane CallStack
     | Logo CallStack
     | Pictures [Picture]
+    | Blank CallStack
 
 data TextStyle
     = Plain
@@ -101,122 +143,119 @@
     | NamedFont !Text
 
 -- | A blank picture
-blank :: Picture
-blank = Pictures []
+blank :: HasCallStack => Picture
+blank = Blank callStack
 
 -- | A thin sequence of line segments, with these points as endpoints
 polyline :: HasCallStack => [Point] -> Picture
-polyline ps = Path callStack ps 0 False False
+polyline ps = Polyline callStack ps
 
 -- | A thin sequence of line segments, with these points as endpoints
 path :: HasCallStack => [Point] -> Picture
-path ps = Path callStack ps 0 False False
+path ps = Polyline callStack ps
 
 {-# WARNING path "Please use polyline instead of path." #-}
 
 -- | A thick sequence of line segments, with given line width and endpoints
 thickPolyline :: HasCallStack => Double -> [Point] -> Picture
-thickPolyline n ps = Path callStack ps n False False
+thickPolyline n ps = ThickPolygon callStack ps n
 
 -- | A thick sequence of line segments, with given line width and endpoints
 thickPath :: HasCallStack => Double -> [Point] -> Picture
-thickPath n ps = Path callStack ps n False False
+thickPath n ps = ThickPolyline callStack ps n
 
 {-# WARNING thickPath "Please used thickPolyline instead of thickPath." #-}
 
 -- | A thin polygon with these points as vertices
 polygon :: HasCallStack => [Point] -> Picture
-polygon ps = Path callStack ps 0 True False
+polygon ps = Polygon callStack ps
 
 -- | A thick polygon with this line width and these points as
 -- vertices
 thickPolygon :: HasCallStack => Double -> [Point] -> Picture
-thickPolygon n ps = Path callStack ps n True False
+thickPolygon n ps = ThickPolygon callStack ps n
 
 -- | A solid polygon with these points as vertices
 solidPolygon :: HasCallStack => [Point] -> Picture
-solidPolygon ps = Polygon callStack ps False
+solidPolygon ps = SolidPolygon callStack ps
 
 -- | A smooth curve passing through these points.
 curve :: HasCallStack => [Point] -> Picture
-curve ps = Path callStack ps 0 False True
+curve ps = Curve callStack ps
 
 -- | A thick smooth curve with this line width, passing through these points.
 thickCurve :: HasCallStack => Double -> [Point] -> Picture
-thickCurve n ps = Path callStack ps n False True
+thickCurve n ps = ThickCurve callStack ps n
 
 -- | A smooth closed curve passing through these points.
 closedCurve :: HasCallStack => [Point] -> Picture
-closedCurve ps = Path callStack ps 0 True True
+closedCurve ps = ClosedCurve callStack ps
 
 -- | A smooth closed curve passing through these points.
 loop :: HasCallStack => [Point] -> Picture
-loop ps = Path callStack ps 0 True True
+loop ps = ClosedCurve callStack ps
 
 {-# WARNING loop "Please use closedCurve instead of loop." #-}
 
 -- | A thick smooth closed curve with this line width, passing through these points.
 thickClosedCurve :: HasCallStack => Double -> [Point] -> Picture
-thickClosedCurve n ps = Path callStack ps n True True
+thickClosedCurve n ps = ThickClosedCurve callStack ps n
 
 -- | A thick smooth closed curve with this line width, passing through these points.
 thickLoop :: HasCallStack => Double -> [Point] -> Picture
-thickLoop n ps = Path callStack ps n True True
+thickLoop n ps = ThickClosedCurve callStack ps n
 
 {-# WARNING thickLoop "Please use thickClosedCurve instead of thickLoop." #-}
 
 -- | A solid smooth closed curve passing through these points.
 solidClosedCurve :: HasCallStack => [Point] -> Picture
-solidClosedCurve ps = Polygon callStack ps True
+solidClosedCurve ps = SolidClosedCurve callStack ps
 
 -- | A solid smooth closed curve passing through these points.
 solidLoop :: HasCallStack => [Point] -> Picture
-solidLoop ps = Polygon callStack ps True
+solidLoop ps = SolidClosedCurve callStack ps
 
 {-# WARNING solidLoop "Please use solidClosedCurve instead of solidLoop." #-}
 
+rectangleVertices :: Double -> Double -> [Point]
+rectangleVertices w h = [ (w / 2, h / 2), (w / 2, -h / 2), (-w / 2, -h / 2), (-w / 2, h / 2) ]
+
 -- | A thin rectangle, with this width and height
 rectangle :: HasCallStack => Double -> Double -> Picture
-rectangle w h =
-    polygon [(-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2), (-w / 2, h / 2)]
+rectangle w h = Rectangle callStack w h
 
 -- | A solid rectangle, with this width and height
 solidRectangle :: HasCallStack => Double -> Double -> Picture
-solidRectangle w h =
-    solidPolygon
-        [(-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2), (-w / 2, h / 2)]
+solidRectangle w h = SolidRectangle callStack w h
 
 -- | A thick rectangle, with this line width, and width and height
 thickRectangle :: HasCallStack => Double -> Double -> Double -> Picture
-thickRectangle lw w h =
-    thickPolygon
-        lw
-        [(-w / 2, -h / 2), (w / 2, -h / 2), (w / 2, h / 2), (-w / 2, h / 2)]
+thickRectangle lw w h = ThickRectangle callStack lw w h
 
 -- | A thin circle, with this radius
 circle :: HasCallStack => Double -> Picture
-circle = arc 0 (2 * pi)
+circle = Circle callStack 
 
 -- | A thick circle, with this line width and radius
 thickCircle :: HasCallStack => Double -> Double -> Picture
-thickCircle w = thickArc w 0 (2 * pi)
+thickCircle = ThickCircle callStack
 
 -- | A thin arc, starting and ending at these angles, with this radius
 --
 -- Angles are in radians.
 arc :: HasCallStack => Double -> Double -> Double -> Picture
-arc b e r = Arc callStack b e r 0
+arc b e r = Arc callStack b e r
 
 -- | A thick arc with this line width, starting and ending at these angles,
 -- with this radius.
 --
 -- Angles are in radians.
 thickArc :: HasCallStack => Double -> Double -> Double -> Double -> Picture
-thickArc w b e r = Arc callStack b e r w
+thickArc w b e r = ThickArc callStack b e r w
 
 -- | A solid circle, with this radius
 solidCircle :: HasCallStack => Double -> Picture
-solidCircle = sector 0 (2 * pi)
+solidCircle = SolidCircle callStack 
 
 -- | A solid sector of a circle (i.e., a pie slice) starting and ending at these
 -- angles, with this radius
@@ -227,10 +266,10 @@
 
 -- | A piece of text
 text :: HasCallStack => Text -> Picture
-text = Text callStack Plain Serif
+text = Text callStack
 
 styledText :: HasCallStack => TextStyle -> Font -> Text -> Picture
-styledText = Text callStack
+styledText = StyledText callStack
 
 -- | A picture drawn entirely in this color.
 colored :: HasCallStack => Color -> Picture -> Picture
@@ -261,6 +300,14 @@
 -- A picture made by drawing these pictures, ordered from top to bottom.
 pictures :: [Picture] -> Picture
 pictures = Pictures
+
+#if MIN_VERSION_base(4,11,0)
+
+instance Semigroup Picture where
+    a <> (Pictures bs) = Pictures (a : bs)
+    a <> b             = Pictures [a, b]
+
+#endif
 
 instance Monoid Picture where
     mempty = blank
