{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
module Brick.BorderMap
    ( BorderMap
    , Edges(..)
    , eTopL, eBottomL, eRightL, eLeftL
    , empty, clear, emptyCoordinates, singleton
    , insertH, insertV, insert
    , unsafeUnion
    , coordinates, bounds
    , values
    , lookupRow, lookupCol, lookupH, lookupV, lookup
    , setCoordinates, crop, expand
    , translate
    ) where

import Brick.Types.Common (Edges(..), Location(..), eTopL, eBottomL, eRightL, eLeftL, origin)
import Control.Applicative (liftA2)
import Data.IMap (IMap, Run(Run))
import GHC.Generics
import Control.DeepSeq
import Prelude hiding (lookup)
import qualified Data.IMap as IM

-- | Internal use only.
neighbors :: Edges a -> Edges (a, a)
neighbors :: forall a. Edges a -> Edges (a, a)
neighbors (Edges a
vt a
vb a
vl a
vr) = forall a. a -> a -> a -> a -> Edges a
Edges (a, a)
horiz (a, a)
horiz (a, a)
vert (a, a)
vert where
    horiz :: (a, a)
horiz = (a
vl, a
vr)
    vert :: (a, a)
vert  = (a
vt, a
vb)

-- Invariant: corner values are present on all the edges incident on that
-- corner. Widthless or heightless rectangles replicate the IMaps exactly on
-- the two coincident edges.
--
-- Practically speaking, this means for lookup you can look on any edge that
-- could contain the key you care about, while for insertion you must insert on
-- every edge that could contain the keys being inserted.

-- | A @BorderMap a@ is like a @Map Location a@, except that there is a
-- rectangle, and only 'Location's on the border of this rectangle are
-- retained. The 'BorderMap' can be queried for the position and size of the
-- rectangle. There are also efficient bulk query and bulk update operations
-- for adjacent positions on the border.
data BorderMap a = BorderMap
    { forall a. BorderMap a -> Edges Int
_coordinates :: Edges Int
    , forall a. BorderMap a -> Edges (IMap a)
_values :: Edges (IMap a)
    } deriving (BorderMap a -> BorderMap a -> Bool
forall a. Eq a => BorderMap a -> BorderMap a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BorderMap a -> BorderMap a -> Bool
$c/= :: forall a. Eq a => BorderMap a -> BorderMap a -> Bool
== :: BorderMap a -> BorderMap a -> Bool
$c== :: forall a. Eq a => BorderMap a -> BorderMap a -> Bool
Eq, BorderMap a -> BorderMap a -> Bool
BorderMap a -> BorderMap a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (BorderMap a)
forall a. Ord a => BorderMap a -> BorderMap a -> Bool
forall a. Ord a => BorderMap a -> BorderMap a -> Ordering
forall a. Ord a => BorderMap a -> BorderMap a -> BorderMap a
min :: BorderMap a -> BorderMap a -> BorderMap a
$cmin :: forall a. Ord a => BorderMap a -> BorderMap a -> BorderMap a
max :: BorderMap a -> BorderMap a -> BorderMap a
$cmax :: forall a. Ord a => BorderMap a -> BorderMap a -> BorderMap a
>= :: BorderMap a -> BorderMap a -> Bool
$c>= :: forall a. Ord a => BorderMap a -> BorderMap a -> Bool
> :: BorderMap a -> BorderMap a -> Bool
$c> :: forall a. Ord a => BorderMap a -> BorderMap a -> Bool
<= :: BorderMap a -> BorderMap a -> Bool
$c<= :: forall a. Ord a => BorderMap a -> BorderMap a -> Bool
< :: BorderMap a -> BorderMap a -> Bool
$c< :: forall a. Ord a => BorderMap a -> BorderMap a -> Bool
compare :: BorderMap a -> BorderMap a -> Ordering
$ccompare :: forall a. Ord a => BorderMap a -> BorderMap a -> Ordering
Ord, Int -> BorderMap a -> ShowS
forall a. Show a => Int -> BorderMap a -> ShowS
forall a. Show a => [BorderMap a] -> ShowS
forall a. Show a => BorderMap a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BorderMap a] -> ShowS
$cshowList :: forall a. Show a => [BorderMap a] -> ShowS
show :: BorderMap a -> String
$cshow :: forall a. Show a => BorderMap a -> String
showsPrec :: Int -> BorderMap a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> BorderMap a -> ShowS
Show, forall a b. a -> BorderMap b -> BorderMap a
forall a b. (a -> b) -> BorderMap a -> BorderMap b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> BorderMap b -> BorderMap a
$c<$ :: forall a b. a -> BorderMap b -> BorderMap a
fmap :: forall a b. (a -> b) -> BorderMap a -> BorderMap b
$cfmap :: forall a b. (a -> b) -> BorderMap a -> BorderMap b
Functor, ReadPrec [BorderMap a]
ReadPrec (BorderMap a)
ReadS [BorderMap a]
forall a. Read a => ReadPrec [BorderMap a]
forall a. Read a => ReadPrec (BorderMap a)
forall a. Read a => Int -> ReadS (BorderMap a)
forall a. Read a => ReadS [BorderMap a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [BorderMap a]
$creadListPrec :: forall a. Read a => ReadPrec [BorderMap a]
readPrec :: ReadPrec (BorderMap a)
$creadPrec :: forall a. Read a => ReadPrec (BorderMap a)
readList :: ReadS [BorderMap a]
$creadList :: forall a. Read a => ReadS [BorderMap a]
readsPrec :: Int -> ReadS (BorderMap a)
$creadsPrec :: forall a. Read a => Int -> ReadS (BorderMap a)
Read, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (BorderMap a) x -> BorderMap a
forall a x. BorderMap a -> Rep (BorderMap a) x
$cto :: forall a x. Rep (BorderMap a) x -> BorderMap a
$cfrom :: forall a x. BorderMap a -> Rep (BorderMap a) x
Generic, forall a. NFData a => BorderMap a -> ()
forall a. (a -> ()) -> NFData a
rnf :: BorderMap a -> ()
$crnf :: forall a. NFData a => BorderMap a -> ()
NFData)

-- | Given a rectangle (specified as the coordinates of the top, left, bottom,
-- and right sides), initialize an empty 'BorderMap'.
emptyCoordinates :: Edges Int -> BorderMap a
emptyCoordinates :: forall a. Edges Int -> BorderMap a
emptyCoordinates Edges Int
cs = BorderMap { _coordinates :: Edges Int
_coordinates = Edges Int
cs, _values :: Edges (IMap a)
_values = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. IMap a
IM.empty }

-- | An empty 'BorderMap' that tracks the same points as the input.
clear :: BorderMap a -> BorderMap b
clear :: forall a b. BorderMap a -> BorderMap b
clear = forall a. Edges Int -> BorderMap a
emptyCoordinates forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. BorderMap a -> Edges Int
coordinates

-- | An empty 'BorderMap' that does not track any points.
empty :: BorderMap a
empty :: forall a. BorderMap a
empty = forall a. Edges Int -> BorderMap a
emptyCoordinates Edges
    { eTop :: Int
eTop = Int
0
    , eBottom :: Int
eBottom = -Int
1
    , eLeft :: Int
eLeft = Int
0
    , eRight :: Int
eRight = -Int
1
    }

-- | A 'BorderMap' that tracks only the given the point (and initially maps it
-- to the given value).
singleton :: Location -> a -> BorderMap a
singleton :: forall a. Location -> a -> BorderMap a
singleton Location
l a
v = forall a. Location -> BorderMap a -> BorderMap a
translate Location
l forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Location -> a -> BorderMap a -> BorderMap a
insert Location
origin a
v forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Edges Int -> BorderMap a
emptyCoordinates forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
0

{-# INLINE coordinates #-}
-- | The positions of the edges of the rectangle whose border is retained in a
-- 'BorderMap'. For example, if @coordinates m = e@, then the top border
-- contains the 'Location's on row @eTop e@ and between columns @eLeft e@ to
-- @eRight e@ inclusive.
coordinates :: BorderMap a -> Edges Int
coordinates :: forall a. BorderMap a -> Edges Int
coordinates = forall a. BorderMap a -> Edges Int
_coordinates

-- | A complementary way to query the edges of the rectangle whose border is
-- retained in a 'BorderMap'. For example, if @bounds m = b@, then a
-- 'Location'\'s column must be between @fst (eTop b)@ and @snd (eTop b)@ to be
-- retained. See also 'coordinates', which is in most cases a more natural
-- border query.
bounds :: BorderMap a -> Edges (Int, Int)
bounds :: forall a. BorderMap a -> Edges (Int, Int)
bounds = forall a. Edges a -> Edges (a, a)
neighbors forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. BorderMap a -> Edges Int
coordinates

{-# INLINE values #-}
-- | Maps giving the values along each edge. Corner values are replicated in
-- all relevant edges.
values :: BorderMap a -> Edges (IMap a)
values :: forall a. BorderMap a -> Edges (IMap a)
values = forall a. BorderMap a -> Edges (IMap a)
_values

-- | Bulk insertion of horizontally-adjacent values. The 'Location' gives the
-- start point, and the 'Run' extends in the "larger columns" direction.
insertH :: Location -> Run a -> BorderMap a -> BorderMap a
insertH :: forall a. Location -> Run a -> BorderMap a -> BorderMap a
insertH = forall a.
Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
-> Location -> Run a -> BorderMap a -> BorderMap a
insertDirAgnostic (forall a. a -> a -> a -> a -> Edges a
Edges forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPerp forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPerp) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Location -> Location
swapLoc
    where
    swapLoc :: Location -> Location
swapLoc (Location (Int
col, Int
row)) = (Int, Int) -> Location
Location (Int
row, Int
col)

-- | Bulk insertion of vertically-adjacent values. The 'Location' gives the
-- start point, and the 'Run' extends in the "larger rows" direction.
insertV :: Location -> Run a -> BorderMap a -> BorderMap a
insertV :: forall a. Location -> Run a -> BorderMap a -> BorderMap a
insertV = forall a.
Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
-> Location -> Run a -> BorderMap a -> BorderMap a
insertDirAgnostic (forall a. a -> a -> a -> a -> Edges a
Edges forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPerp forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPerp forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar)

insertDirAgnostic
    :: Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
    -> Location -> Run a -> BorderMap a -> BorderMap a
insertDirAgnostic :: forall a.
Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
-> Location -> Run a -> BorderMap a -> BorderMap a
insertDirAgnostic Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
insertions Location
l Run a
r BorderMap a
m =
    BorderMap a
m { _values :: Edges (IMap a)
_values = Edges (Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a)
insertions forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Location
l forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure Run a
r forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges (Int, Int)
bounds BorderMap a
m forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m }

insertPar, insertPerp :: Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar :: forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPar (Location (Int
kPar, Int
kPerp)) Run a
r Int
herePar (Int
loPerp, Int
hiPerp)
    | Int
kPar forall a. Eq a => a -> a -> Bool
== Int
herePar Bool -> Bool -> Bool
&& Int
loPerp forall a. Ord a => a -> a -> Bool
<= Int
kPerp forall a. Num a => a -> a -> a
+ forall a. Run a -> Int
IM.len Run a
r forall a. Num a => a -> a -> a
- Int
1 Bool -> Bool -> Bool
&& Int
kPerp forall a. Ord a => a -> a -> Bool
<= Int
hiPerp
        = forall a. Int -> Run a -> IMap a -> IMap a
IM.insert Int
beg Run a
r { len :: Int
IM.len = Int
end forall a. Num a => a -> a -> a
- Int
beg forall a. Num a => a -> a -> a
+ Int
1 }
    | Bool
otherwise = forall a. a -> a
id
    where
    beg :: Int
beg = forall a. Ord a => a -> a -> a
max Int
kPerp Int
loPerp
    end :: Int
end = forall a. Ord a => a -> a -> a
min (Int
kPerp forall a. Num a => a -> a -> a
+ forall a. Run a -> Int
IM.len Run a
r forall a. Num a => a -> a -> a
- Int
1) Int
hiPerp
insertPerp :: forall a.
Location -> Run a -> Int -> (Int, Int) -> IMap a -> IMap a
insertPerp (Location (Int
kPar, Int
kPerp)) Run a
r Int
herePerp (Int
loPar, Int
hiPar)
    | Int
loPar forall a. Ord a => a -> a -> Bool
<= Int
kPar Bool -> Bool -> Bool
&& Int
kPar forall a. Ord a => a -> a -> Bool
<= Int
hiPar Bool -> Bool -> Bool
&& Int
kPerp forall a. Ord a => a -> a -> Bool
<= Int
herePerp Bool -> Bool -> Bool
&& Int
herePerp forall a. Ord a => a -> a -> Bool
<= Int
kPerp forall a. Num a => a -> a -> a
+ forall a. Run a -> Int
IM.len Run a
r forall a. Num a => a -> a -> a
- Int
1
        = forall a. Int -> Run a -> IMap a -> IMap a
IM.insert Int
kPar Run a
r { len :: Int
IM.len = Int
1 }
    | Bool
otherwise = forall a. a -> a
id

-- | Insert a single value at the given location.
insert :: Location -> a -> BorderMap a -> BorderMap a
insert :: forall a. Location -> a -> BorderMap a -> BorderMap a
insert Location
l = forall a. Location -> Run a -> BorderMap a -> BorderMap a
insertV Location
l forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> a -> Run a
Run Int
1

-- | Look up all values on a given row. The 'IMap' returned maps columns to
-- values.
lookupRow :: Int -> BorderMap a -> IMap a
lookupRow :: forall a. Int -> BorderMap a -> IMap a
lookupRow Int
row BorderMap a
m
    | Int
row forall a. Eq a => a -> a -> Bool
== forall a. Edges a -> a
eTop    (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) = forall a. Edges a -> a
eTop    (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m)
    | Int
row forall a. Eq a => a -> a -> Bool
== forall a. Edges a -> a
eBottom (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) = forall a. Edges a -> a
eBottom (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m)
    | Bool
otherwise = forall a. [(Int, Run a)] -> IMap a
IM.fromList
        forall a b. (a -> b) -> a -> b
$  [(forall a. Edges a -> a
eLeft   (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m), forall a. Int -> a -> Run a
Run Int
1 a
a) | Just a
a <- [forall a. Int -> IMap a -> Maybe a
IM.lookup Int
row (forall a. Edges a -> a
eLeft   (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m))]]
        forall a. [a] -> [a] -> [a]
++ [(forall a. Edges a -> a
eRight  (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m), forall a. Int -> a -> Run a
Run Int
1 a
a) | Just a
a <- [forall a. Int -> IMap a -> Maybe a
IM.lookup Int
row (forall a. Edges a -> a
eRight  (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m))]]

-- | Look up all values on a given column. The 'IMap' returned maps rows to
-- values.
lookupCol :: Int -> BorderMap a -> IMap a
lookupCol :: forall a. Int -> BorderMap a -> IMap a
lookupCol Int
col BorderMap a
m
    | Int
col forall a. Eq a => a -> a -> Bool
== forall a. Edges a -> a
eLeft   (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) = forall a. Edges a -> a
eLeft   (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m)
    | Int
col forall a. Eq a => a -> a -> Bool
== forall a. Edges a -> a
eRight  (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) = forall a. Edges a -> a
eRight  (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m)
    | Bool
otherwise = forall a. [(Int, Run a)] -> IMap a
IM.fromList
        forall a b. (a -> b) -> a -> b
$  [(forall a. Edges a -> a
eTop    (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m), forall a. Int -> a -> Run a
Run Int
1 a
a) | Just a
a <- [forall a. Int -> IMap a -> Maybe a
IM.lookup Int
col (forall a. Edges a -> a
eTop    (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m))]]
        forall a. [a] -> [a] -> [a]
++ [(forall a. Edges a -> a
eBottom (forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m), forall a. Int -> a -> Run a
Run Int
1 a
a) | Just a
a <- [forall a. Int -> IMap a -> Maybe a
IM.lookup Int
col (forall a. Edges a -> a
eBottom (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m))]]

-- | Bulk lookup of horizontally-adjacent values. The 'Location' gives the
-- starting point, and the 'Run' extends in the "larger columns" direction. The
-- 'IMap' returned maps columns to values.
lookupH :: Location -> Run ignored -> BorderMap a -> IMap a
lookupH :: forall ignored a. Location -> Run ignored -> BorderMap a -> IMap a
lookupH (Location (Int
col, Int
row)) Run ignored
r = forall ignored a. Int -> Run ignored -> IMap a -> IMap a
IM.restrict Int
col Run ignored
r forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> BorderMap a -> IMap a
lookupRow Int
row

-- | Bulk lookup of vertically-adjacent values. The 'Location' gives the
-- starting point, and the 'Run' extends in the "larger rows" direction. The
-- 'IMap' returned maps rows to values.
lookupV :: Location -> Run ignored -> BorderMap a -> IMap a
lookupV :: forall ignored a. Location -> Run ignored -> BorderMap a -> IMap a
lookupV (Location (Int
col, Int
row)) Run ignored
r = forall ignored a. Int -> Run ignored -> IMap a -> IMap a
IM.restrict Int
row Run ignored
r forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> BorderMap a -> IMap a
lookupCol Int
col

-- | Look up a single position.
lookup :: Location -> BorderMap a -> Maybe a
lookup :: forall a. Location -> BorderMap a -> Maybe a
lookup (Location (Int
col, Int
row)) = forall a. Int -> IMap a -> Maybe a
IM.lookup Int
row forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Int -> BorderMap a -> IMap a
lookupCol Int
col

-- | Set the rectangle being tracked by this 'BorderMap', throwing away any
-- values that do not lie on this new rectangle.
setCoordinates :: Edges Int -> BorderMap a -> BorderMap a
setCoordinates :: forall a. Edges Int -> BorderMap a -> BorderMap a
setCoordinates Edges Int
coordinates' BorderMap a
m = BorderMap
    { _values :: Edges (IMap a)
_values = Edges (IMap a)
values'
    , _coordinates :: Edges Int
_coordinates = Edges Int
coordinates'
    }
    where
    bounds' :: Edges (Int, Int)
bounds' = forall a. Edges a -> Edges (a, a)
neighbors Edges Int
coordinates'
    values' :: Edges (IMap a)
values' = forall {t} {a}.
Eq t =>
t
-> t
-> (Int, Int)
-> IMap a
-> (t -> BorderMap a -> IMap a)
-> IMap a
gc
        forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. BorderMap a -> Edges Int
_coordinates BorderMap a
m
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Edges Int
coordinates'
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Edges (Int, Int)
bounds'
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m
        forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Edges { eTop :: Int -> BorderMap a -> IMap a
eTop = forall a. Int -> BorderMap a -> IMap a
lookupRow, eBottom :: Int -> BorderMap a -> IMap a
eBottom = forall a. Int -> BorderMap a -> IMap a
lookupRow, eLeft :: Int -> BorderMap a -> IMap a
eLeft = forall a. Int -> BorderMap a -> IMap a
lookupCol, eRight :: Int -> BorderMap a -> IMap a
eRight = forall a. Int -> BorderMap a -> IMap a
lookupCol }
    gc :: t
-> t
-> (Int, Int)
-> IMap a
-> (t -> BorderMap a -> IMap a)
-> IMap a
gc t
oldPar t
newPar (Int
loPerp, Int
hiPerp) IMap a
imPar t -> BorderMap a -> IMap a
lookupPerp
        | t
oldPar forall a. Eq a => a -> a -> Bool
== t
newPar = forall ignored a. Int -> Run ignored -> IMap a -> IMap a
IM.restrict Int
loPerp (forall a. Int -> a -> Run a
Run (Int
hiPerpforall a. Num a => a -> a -> a
-Int
loPerpforall a. Num a => a -> a -> a
+Int
1) ()) IMap a
imPar
        | Bool
otherwise = t -> BorderMap a -> IMap a
lookupPerp t
newPar BorderMap a
m

-- | Ensure that the rectangle being tracked by this 'BorderMap' extends no
-- farther than the given one.
crop :: Edges Int -> BorderMap a -> BorderMap a
crop :: forall a. Edges Int -> BorderMap a -> BorderMap a
crop Edges Int
cs BorderMap a
m = forall a. Edges Int -> BorderMap a -> BorderMap a
setCoordinates (Edges (Int -> Int -> Int)
shrink forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Edges Int
cs forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) BorderMap a
m where
    shrink :: Edges (Int -> Int -> Int)
shrink = Edges
        { eTop :: Int -> Int -> Int
eTop    = forall a. Ord a => a -> a -> a
max
        , eBottom :: Int -> Int -> Int
eBottom = forall a. Ord a => a -> a -> a
min
        , eLeft :: Int -> Int -> Int
eLeft   = forall a. Ord a => a -> a -> a
max
        , eRight :: Int -> Int -> Int
eRight  = forall a. Ord a => a -> a -> a
min
        }

-- | Ensure that the rectangle being tracked by this 'BorderMap' extends at
-- least as far as the given one.
expand :: Edges Int -> BorderMap a -> BorderMap a
expand :: forall a. Edges Int -> BorderMap a -> BorderMap a
expand Edges Int
cs BorderMap a
m = forall a. Edges Int -> BorderMap a -> BorderMap a
setCoordinates (Edges (Int -> Int -> Int)
grow forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Edges Int
cs forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. BorderMap a -> Edges Int
coordinates BorderMap a
m) BorderMap a
m where
    grow :: Edges (Int -> Int -> Int)
grow = Edges
        { eTop :: Int -> Int -> Int
eTop    = forall a. Ord a => a -> a -> a
min
        , eBottom :: Int -> Int -> Int
eBottom = forall a. Ord a => a -> a -> a
max
        , eLeft :: Int -> Int -> Int
eLeft   = forall a. Ord a => a -> a -> a
min
        , eRight :: Int -> Int -> Int
eRight  = forall a. Ord a => a -> a -> a
max
        }

-- | Move a 'BorderMap' by adding the given 'Location' to all keys in the map.
translate :: Location -> BorderMap a -> BorderMap a
-- fast path: do nothing for (0,0)
translate :: forall a. Location -> BorderMap a -> BorderMap a
translate (Location (Int
0, Int
0)) BorderMap a
m = BorderMap a
m
translate (Location (Int
c, Int
r)) BorderMap a
m = BorderMap
    { _coordinates :: Edges Int
_coordinates = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Num a => a -> a -> a
(+)          Edges Int
cOffsets (forall a. BorderMap a -> Edges Int
_coordinates BorderMap a
m)
    , _values :: Edges (IMap a)
_values      = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Int -> IMap a -> IMap a
IM.addToKeys Edges Int
vOffsets (forall a. BorderMap a -> Edges (IMap a)
_values      BorderMap a
m)
    }
    where
    cOffsets :: Edges Int
cOffsets = Edges { eTop :: Int
eTop = Int
r, eBottom :: Int
eBottom = Int
r, eLeft :: Int
eLeft = Int
c, eRight :: Int
eRight = Int
c }
    vOffsets :: Edges Int
vOffsets = Edges { eTop :: Int
eTop = Int
c, eBottom :: Int
eBottom = Int
c, eLeft :: Int
eLeft = Int
r, eRight :: Int
eRight = Int
r }

-- | Assumes the two 'BorderMap's are tracking the same rectangles, but have
-- disjoint keys. This property is not checked.
unsafeUnion :: BorderMap a -> BorderMap a -> BorderMap a
unsafeUnion :: forall a. BorderMap a -> BorderMap a -> BorderMap a
unsafeUnion BorderMap a
m BorderMap a
m' = BorderMap a
m { _values :: Edges (IMap a)
_values = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. IMap a -> IMap a -> IMap a
IM.unsafeUnion (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m) (forall a. BorderMap a -> Edges (IMap a)
_values BorderMap a
m') }