renderer: move w/h region into rendering context

This commit is contained in:
Jonathan Daugherty 2015-05-18 19:30:35 -07:00
parent d47de345ab
commit 3a8bb03e03

View File

@ -26,6 +26,8 @@ data Render =
data Context =
Context { _attr :: Attr
, _w :: Int
, _h :: Int
}
makeLenses ''Context
@ -40,8 +42,8 @@ renderFinal :: [Prim a]
-> (a, Picture, Maybe CursorLocation)
renderFinal layerPrims sz chooseCursor st = (newState, pic, theCursor)
where
(layerResults, newState) = flip runState st $ sequence $ render sz ctx <$> layerPrims
ctx = Context defAttr
(layerResults, newState) = flip runState st $ sequence $ render ctx <$> layerPrims
ctx = Context defAttr (fst sz) (snd sz)
pic = picForLayers $ uncurry resize sz <$> image <$> layerResults
layerCursors = cursors <$> layerResults
theCursor = chooseCursor $ concat layerCursors
@ -49,7 +51,7 @@ renderFinal layerPrims sz chooseCursor st = (newState, pic, theCursor)
addCursorOffset :: Location -> Render -> Render
addCursorOffset off r =
let onlyVisible = filter isVisible
isVisible (CursorLocation (Location (w, h)) _) = w >= 0 && h >= 0
isVisible (CursorLocation (Location (width, height)) _) = width >= 0 && height >= 0
in r { cursors = onlyVisible $ (`clOffset` off) <$> cursors r
}
@ -59,92 +61,92 @@ setImage i r = r { image = i }
unrestricted :: Int
unrestricted = 1000
render :: DisplayRegion -> Context -> Prim a -> State a Render
render sz c (With target f) = do
render :: Context -> Prim a -> State a Render
render c (With target f) = do
outerState <- get
let innerPrim = f oldInnerState
oldInnerState = outerState^.target
(innerRender, newInnerState) = runState (render sz c innerPrim) oldInnerState
(innerRender, newInnerState) = runState (render c innerPrim) oldInnerState
target .= newInnerState
return innerRender
render (w, h) c (Txt s) =
return $ if w > 0 && h > 0
then setImage (crop w h $ string (c^.attr) s) def
render c (Txt s) =
return $ if c^.w > 0 && c^.h > 0
then setImage (crop (c^.w) (c^.h) $ string (c^.attr) s) def
else def
render (w, h) _ (Raw img) =
return $ if w > 0 && h > 0
then setImage (crop w h img) def
render c (Raw img) =
return $ if c^.w > 0 && c^.h > 0
then setImage (crop (c^.w) (c^.h) img) def
else def
render (w, h) a (CropLeftBy c p) = do
result <- render (w, h) a p
render c (CropLeftBy cols p) = do
result <- render c p
let img = image result
amt = imageWidth img - c
amt = imageWidth img - cols
cropped = if amt < 0 then emptyImage else cropLeft amt img
return $ addCursorOffset (Location (-1 * c, 0)) $
return $ addCursorOffset (Location (-1 * cols, 0)) $
setImage cropped result
render (w, h) a (CropRightBy c p) = do
result <- render (w, h) a p
render c (CropRightBy cols p) = do
result <- render c p
let img = image result
amt = imageWidth img - c
amt = imageWidth img - cols
cropped = if amt < 0 then emptyImage else cropRight amt img
-- xxx cursors
return $ setImage cropped result
render (w, h) a (CropTopBy c p) = do
result <- render (w, h) a p
render c (CropTopBy rows p) = do
result <- render c p
let img = image result
amt = imageHeight img - c
amt = imageHeight img - rows
cropped = if amt < 0 then emptyImage else cropTop amt img
return $ addCursorOffset (Location (0, -1 * c)) $
return $ addCursorOffset (Location (0, -1 * rows)) $
setImage cropped result
render (w, h) a (CropBottomBy c p) = do
result <- render (w, h) a p
render c (CropBottomBy rows p) = do
result <- render c p
let img = image result
amt = imageHeight img - c
amt = imageHeight img - rows
cropped = if amt < 0 then emptyImage else cropBottom amt img
-- xxx crop cursors
return $ setImage cropped result
render (w, h) c (HPad ch) = return $ setImage (charFill (c^.attr) ch w (max 1 h)) def
render (w, h) c (VPad ch) = return $ setImage (charFill (c^.attr) ch (max 1 w) h) def
render (w, h) c (HFill ch) = return $ setImage (charFill (c^.attr) ch w (min h 1)) def
render (w, h) c (VFill ch) = return $ setImage (charFill (c^.attr) ch (min w 1) h) def
render (_, h) c (HLimit w p) =
render c (HPad ch) = return $ setImage (charFill (c^.attr) ch (c^.w) (max 1 (c^.h))) def
render c (VPad ch) = return $ setImage (charFill (c^.attr) ch (max 1 (c^.w)) (c^.h)) def
render c (HFill ch) = return $ setImage (charFill (c^.attr) ch (c^.w) (min (c^.h) 1)) def
render c (VFill ch) = return $ setImage (charFill (c^.attr) ch (min (c^.w) 1) (c^.h)) def
render c (HLimit w' p) =
-- xxx crop cursors
render (w, h) c p
render (w, _) c (VLimit h p) =
render (c & w .~ w') p
render c (VLimit h' p) =
-- xxx crop cursors
render (w, h) c p
render (_, h) c (HRelease p) = render (unrestricted, h) c p --- NB
render (w, _) c (VRelease p) = render (w, unrestricted) c p --- NB
render (w, h) c (UseAttr a p) = render (w, h) (c & attr .~ a) p
render (w, h) c (Translate tw th p) = do
result <- render (w, h) c p
render (c & h .~ h') p
render c (HRelease p) = render (c & w .~ unrestricted) p --- NB
render c (VRelease p) = render (c & h .~ unrestricted) p --- NB
render c (UseAttr a p) = render (c & attr .~ a) p
render c (Translate tw th p) = do
result <- render c p
let img = image result
return $ addCursorOffset (Location (tw, th)) $
setImage (crop w h $ translate tw th img) result
render sz c (ShowCursor n loc p) = do
result <- render sz c p
setImage (crop (c^.w) (c^.h) $ translate tw th img) result
render c (ShowCursor n loc p) = do
result <- render c p
return $ result { cursors = (CursorLocation loc (Just n)):cursors result }
render sz c (SetSize sizeSetter p) = do
result <- render sz c p
render c (SetSize sizeSetter p) = do
result <- render c p
let img = image result
imgSz = (imageWidth img, imageHeight img)
modify (sizeSetter imgSz)
return result
render (w, h) c (HBox pairs) = do
render c (HBox pairs) = do
let pairsIndexed = zip [(0::Int)..] pairs
his = filter (\p -> (snd $ snd p) == High) pairsIndexed
lows = filter (\p -> (snd $ snd p) == Low) pairsIndexed
renderedHis <- mapM (\(i, (prim, _)) -> (i,) <$> render (w, h) c prim) his
renderedHis <- mapM (\(i, (prim, _)) -> (i,) <$> render c prim) his
let remainingWidth = w - (sum $ (imageWidth . image . snd) <$> renderedHis)
let remainingWidth = c^.w - (sum $ (imageWidth . image . snd) <$> renderedHis)
widthPerLow = remainingWidth `div` length lows
padFirst = if widthPerLow * length lows < remainingWidth
then remainingWidth - widthPerLow * length lows
else 0
heightPerLow = maximum $ (imageHeight . image . snd) <$> renderedHis
renderedLows <- mapM (\(i, (prim, _)) -> (i,) <$> render (widthPerLow + (if i == 0 then padFirst else 0), heightPerLow) c prim) lows
renderedLows <- mapM (\(i, (prim, _)) -> (i,) <$> render (c & w .~ widthPerLow + (if i == 0 then padFirst else 0) & h .~ heightPerLow) prim) lows
let rendered = sortBy (compare `DF.on` fst) $ renderedHis ++ renderedLows
allResults = snd <$> rendered
@ -157,21 +159,21 @@ render (w, h) c (HBox pairs) = do
return $ Render (horizCat allImages) (concat allTranslatedCursors)
render (w, h) c (VBox pairs) = do
render c (VBox pairs) = do
let pairsIndexed = zip [(0::Int)..] pairs
his = filter (\p -> (snd $ snd p) == High) pairsIndexed
lows = filter (\p -> (snd $ snd p) == Low) pairsIndexed
renderedHis <- mapM (\(i, (prim, _)) -> (i,) <$> render (w, h) c prim) his
renderedHis <- mapM (\(i, (prim, _)) -> (i,) <$> render c prim) his
let remainingHeight = h - (sum $ (imageHeight . image . snd) <$> renderedHis)
let remainingHeight = c^.h - (sum $ (imageHeight . image . snd) <$> renderedHis)
heightPerLow = remainingHeight `div` length lows
padFirst = if heightPerLow * length lows < remainingHeight
then remainingHeight - heightPerLow * length lows
else 0
widthPerLow = maximum $ (imageWidth . image . snd) <$> renderedHis
renderedLows <- mapM (\(i, (prim, _)) -> (i,) <$> render (widthPerLow, heightPerLow + if i == 0 then padFirst else 0) c prim) lows
renderedLows <- mapM (\(i, (prim, _)) -> (i,) <$> render (c & w .~ widthPerLow & h .~ (heightPerLow + if i == 0 then padFirst else 0)) prim) lows
let rendered = sortBy (compare `DF.on` fst) $ renderedHis ++ renderedLows
allResults = snd <$> rendered