    {-# LANGUAGE ConstraintKinds #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE TypeFamilies     #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Diagrams.TwoD.Size
    -- Copyright   :  (c) 2011 diagrams-lib team (see LICENSE)
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  diagrams-discuss@googlegroups.com
    --
    -- Utilities for working with sizes of two-dimensional objects.
    --
    -----------------------------------------------------------------------------
    module Diagrams.TwoD.Size
           (
             -- ** Computing sizes
             width, height
           , extentX, extentY

             -- ** Specifying sizes
           , mkSizeSpec2D
           , mkWidth
           , mkHeight
           , dims2D

           ) where

    import           Diagrams.Core
    import           Diagrams.Core.Envelope
    import           Diagrams.Size
    import           Diagrams.TwoD.Types
    import           Diagrams.TwoD.Vector

    ------------------------------------------------------------
    -- Computing diagram sizes
    ------------------------------------------------------------

    -- | Compute the width of an enveloped object.
    --
    --   Note this is just @diameter unitX@.
    width :: (InSpace V2 n a, Enveloped a) => a -> n
    width :: forall n a. (InSpace V2 n a, Enveloped a) => a -> n
    width = V2 n -> a -> n
    forall a (v :: * -> *) n.
    (V a ~ v, N a ~ n, Enveloped a) =>
    v n -> a -> n
    diameter V2 n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unitX

    -- | Compute the height of an enveloped object.
    height :: (InSpace V2 n a, Enveloped a) => a -> n
    height :: forall n a. (InSpace V2 n a, Enveloped a) => a -> n
    height = V2 n -> a -> n
    forall a (v :: * -> *) n.
    (V a ~ v, N a ~ n, Enveloped a) =>
    v n -> a -> n
    diameter V2 n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unitY

    -- | Compute the absolute x-coordinate range of an enveloped object in
    --   the form @(lo,hi)@. Return @Nothing@ for objects with an empty
    --   envelope.
    --
    --   Note this is just @extent unitX@.
    extentX :: (InSpace v n a, R1 v, Enveloped a) => a -> Maybe (n, n)
    extentX :: forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Enveloped a) =>
    a -> Maybe (n, n)
    extentX = v n -> a -> Maybe (n, n)
    forall a (v :: * -> *) n.
    (V a ~ v, N a ~ n, Enveloped a) =>
    v n -> a -> Maybe (n, n)
    extent v n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unitX

    -- | Compute the absolute y-coordinate range of an enveloped object in
    --   the form @(lo,hi)@. Return @Nothing@ for objects with an empty
    --   envelope.
    extentY :: (InSpace v n a, R2 v, Enveloped a) => a -> Maybe (n, n)
    extentY :: forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Enveloped a) =>
    a -> Maybe (n, n)
    extentY = v n -> a -> Maybe (n, n)
    forall a (v :: * -> *) n.
    (V a ~ v, N a ~ n, Enveloped a) =>
    v n -> a -> Maybe (n, n)
    extent v n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unitY

    -- | Make a 'SizeSpec' from possibly-specified width and height.
    mkSizeSpec2D :: Num n => Maybe n -> Maybe n -> SizeSpec V2 n
    mkSizeSpec2D :: forall n. Num n => Maybe n -> Maybe n -> SizeSpec V2 n
    mkSizeSpec2D Maybe n
    x Maybe n
    y = V2 (Maybe n) -> SizeSpec V2 n
    forall (v :: * -> *) n.
    (Functor v, Num n) =>
    v (Maybe n) -> SizeSpec v n
    mkSizeSpec (Maybe n -> Maybe n -> V2 (Maybe n)
    forall a. a -> a -> V2 a
    V2 Maybe n
    x Maybe n
    y)

    -- | Make a 'SizeSpec' from a width and height.
    dims2D :: n -> n -> SizeSpec V2 n
    dims2D :: forall n. n -> n -> SizeSpec V2 n
    dims2D n
    x n
    y = V2 n -> SizeSpec V2 n
    forall (v :: * -> *) n. v n -> SizeSpec v n
    dims (n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2 n
    x n
    y)

    -- | Make a 'SizeSpec' with only width defined.
    mkWidth :: Num n => n -> SizeSpec V2 n
    mkWidth :: forall n. Num n => n -> SizeSpec V2 n
    mkWidth n
    w = V2 n -> SizeSpec V2 n
    forall (v :: * -> *) n. v n -> SizeSpec v n
    dims (n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2 n
    w n
    0)

    -- | Make a 'SizeSpec' with only height defined.
    mkHeight :: Num n => n -> SizeSpec V2 n
    mkHeight :: forall n. Num n => n -> SizeSpec V2 n
    mkHeight n
    h = V2 n -> SizeSpec V2 n
    forall (v :: * -> *) n. v n -> SizeSpec v n
    dims (n -> n -> V2 n
    forall a. a -> a -> V2 a
    V2 n
    0 n
    h)