M Mondrian.cabal => Mondrian.cabal +1 -1
@@ 22,7 22,7 @@ library
                        Graphics.Rendering.Rect.Backgrounds,
                        Graphics.Rendering.Rect.CSS,
                        Graphics.Rendering.Rect.CSS.Colour,
-                       Graphics.Rendering.Rect.CSS.Background
+                       Graphics.Rendering.Rect.CSS.Backgrounds
   other-modules:       Graphics.Rendering.Rect.Types
   -- other-extensions:
   build-depends:       base >=4.13 && <4.14, stylist-traits >= 0.1.3.1 && < 1,
 
M lib/Graphics/Rendering/Rect/Backgrounds.hs => lib/Graphics/Rendering/Rect/Backgrounds.hs +5 -2
@@ 1,10 1,11 @@
 module Graphics.Rendering.Rect.Backgrounds(Backgrounds(..), renderBackgrounds) where
 
-import Graphics.Rendering.Rect.CSS.Background
+import Graphics.Rendering.Rect.CSS.Backgrounds
 import Graphics.Rendering.Rect.Types
 import qualified Data.ByteString.Char8 as B8
 import Linear (M44)
 import Control.Monad.IO.Class (MonadIO(..))
+import Data.Maybe (fromMaybe, listToMaybe)
 
 baseFragmentShader = B8.pack $ unlines [
     "#version 330 core",
@@ 17,4 18,6 @@ renderBackgrounds :: (MonadIO m, MonadIO n) =>
     n (Backgrounds -> Rects -> M44 Float -> m ())
 renderBackgrounds = do
     base <- renderRectWith baseFragmentShader ["colour"]
-    return $ \self -> base [c $ background self] paddingBox
+    return $ \self -> base [c $ background self] $ headDef borderBox $ clip self
+
+headDef def = fromMaybe def . listToMaybe
 
M lib/Graphics/Rendering/Rect/CSS.hs => lib/Graphics/Rendering/Rect/CSS.hs +2 -2
@@ 3,12 3,12 @@ module Graphics.Rendering.Rect.CSS(RectStyle(..), colour) where
 
 import Stylist (PropertyParser(..))
 import Graphics.Rendering.Rect.CSS.Colour (ColourPallet(foreground))
-import Graphics.Rendering.Rect.CSS.Background (Backgrounds(..))
+import Graphics.Rendering.Rect.CSS.Backgrounds (Backgrounds(..))
 
 data RectStyle = RectStyle {
     colours :: ColourPallet,
     backgrounds :: Backgrounds
-} deriving (Read, Show, Eq)
+}
 colour = foreground . colours
 
 instance PropertyParser RectStyle where
 
D lib/Graphics/Rendering/Rect/CSS/Background.hs => lib/Graphics/Rendering/Rect/CSS/Background.hs +0 -26
@@ 1,26 0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Graphics.Rendering.Rect.CSS.Background (Backgrounds(..)) where
-
-import Stylist (PropertyParser(..), parseUnorderedShorthand)
-import Graphics.Rendering.Rect.CSS.Colour (ColourPallet, parseColour)
-import Data.Colour (AlphaColour, transparent)
-
-data Backgrounds = Backgrounds {
-    pallet :: ColourPallet,
-    background :: AlphaColour Float
-} deriving (Read, Show, Eq)
-
-instance PropertyParser Backgrounds where
-    temp = Backgrounds { pallet = temp, background = transparent }
-    inherit _ = temp
-    priority _ = []
-
-    longhand _ self@Backgrounds{ pallet = c } "background-color" toks
-        | Just ([], val) <- parseColour c toks = Just self { background = val }
-    longhand _ _ _ _ = Nothing
-
-    shorthand self "background" toks = parseUnorderedShorthand self [
-        "background-color"
-      ] toks
-    shorthand self key val | Just _ <- longhand self self key val = [(key, val)]
-        | otherwise = []
 
A lib/Graphics/Rendering/Rect/CSS/Backgrounds.hs => lib/Graphics/Rendering/Rect/CSS/Backgrounds.hs +76 -0
@@ 0,0 1,76 @@
+{-# LANGUAGE OverloadedStrings #-}
+module Graphics.Rendering.Rect.CSS.Backgrounds (Backgrounds(..)) where
+
+import Stylist (PropertyParser(..), parseUnorderedShorthand)
+import Data.CSS.Syntax.Tokens (Token(..))
+import Data.Maybe (isJust, catMaybes)
+
+import Graphics.Rendering.Rect.CSS.Colour (ColourPallet, parseColour)
+import Data.Colour (AlphaColour, transparent)
+import Graphics.Rendering.Rect.Types (Rects(..), Rect(..))
+
+data Backgrounds = Backgrounds {
+    pallet :: ColourPallet,
+    background :: AlphaColour Float,
+    clip :: [Rects -> Rect]
+}
+
+instance PropertyParser Backgrounds where
+    temp = Backgrounds {
+        pallet = temp, background = transparent, clip = [borderBox]
+      }
+    inherit _ = temp
+    priority _ = []
+
+    longhand _ self@Backgrounds{ pallet = c } "background-color" toks
+        | Just ([], val) <- parseColour c toks = Just self { background = val }
+    longhand _ self "background-clip" t | val@(_:_) <- parseCSSList inner t =
+        Just self { clip = val }
+      where
+        inner [Ident "content-box"] = Just contentBox
+        inner [Ident "padding-box"] = Just paddingBox
+        inner [Ident "border-box"] = Just borderBox
+        inner [Ident "initial"] = Just borderBox -- To aid shorthand implementation.
+        inner _ = Nothing
+    longhand _ _ _ _ = Nothing
+
+    -- The multi-layered shorthand is one source of parsing complexity.
+    shorthand self "background" t = catProps $ reverse $ parseCSSList inner t
+      where
+        catProps [] = []
+        catProps (props:pss)
+            | Just [Ident "initial"] <- "background-color" `lookup` catProps pss =
+                map (catProp $ catProps pss) props
+            | otherwise = [] -- Only allow background-color in bottommost layer.
+        catProp _ ret@("background-color", _) = ret
+        catProp bases (key, val)
+            | Just base <- key `lookup` bases = (key, val ++ Comma:base)
+            -- Shouldn't happen, `inner` expands all props at least to "initial"!
+            | otherwise = (key, val)
+        inner toks | ret@(_:_) <- parseUnorderedShorthand self [
+                "background-color", "background-clip"
+              ] toks = Just ret
+          | otherwise = Nothing
+    shorthand self key val | Just _ <- longhand self self key val = [(key, val)]
+        | otherwise = []
+
+parseCSSList cb toks | all isJust ret = catMaybes ret
+    | otherwise = []
+  where ret = map cb $ splitList Comma toks
+
+------
+--- Utils taken from HappStack
+------
+
+-- | Repeadly splits a list by the provided separator and collects the results
+splitList :: Eq a => a -> [a] -> [[a]]
+splitList _   [] = []
+splitList sep list = h:splitList sep t
+        where (h,t)=split (==sep) list
+
+-- | Split is like break, but the matching element is dropped.
+split :: (a -> Bool) -> [a] -> ([a], [a])
+split f s = (left,right)
+        where
+        (left,right')=break f s
+        right = if null right' then [] else tail right'