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

    {-# OPTIONS_GHC -fno-warn-unused-imports #-}
      -- for Data.Semigroup

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Diagrams.TwoD.Adjust
    -- Copyright   :  (c) 2011 diagrams-lib team (see LICENSE)
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  diagrams-discuss@googlegroups.com
    --
    -- A default diagram-adjustment implementation for two-dimensional
    -- diagrams, useful for backend implementors.
    --
    -----------------------------------------------------------------------------

    module Diagrams.TwoD.Adjust
        ( setDefault2DAttributes
        , adjustSize2D
        , adjustDia2D
        ) where

    import           Diagrams.Attributes
    import           Diagrams.BoundingBox
    import           Diagrams.Core
    import           Diagrams.Size
    import           Diagrams.TwoD.Attributes (lineTextureA)
    import           Diagrams.TwoD.Types
    import           Diagrams.Util            (( # ))

    import           Control.Lens             (Lens', set, (^.))
    import           Data.Default.Class
    import           Data.Semigroup

    -- | Set default attributes of a 2D diagram (in case they have not
    --   been set):
    --
    --       * 'LineWidth':  0.01
    --
    --       * 'LineTexture': solid black
    --
    --       * 'LineCap': LineCapButt
    --
    --       * 'LineJoin': miter
    --
    --       * 'MiterLimit': 10
    setDefault2DAttributes :: (TypeableFloat n, Semigroup m)
      => QDiagram b V2 n m -> QDiagram b V2 n m
    setDefault2DAttributes :: QDiagram b V2 n m -> QDiagram b V2 n m
    setDefault2DAttributes d :: QDiagram b V2 n m
    d
      = QDiagram b V2 n m
    d QDiagram b V2 n m
    -> (QDiagram b V2 n m -> QDiagram b V2 n m) -> QDiagram b V2 n m
    forall a b. a -> (a -> b) -> b
    # LineWidthM n -> QDiagram b V2 n m -> QDiagram b V2 n m
    forall a n.
    (N a ~ n, HasStyle a, Typeable n) =>
    LineWidthM n -> a -> a
    lineWidthM LineWidthM n
    forall a. Default a => a
    def
          # lineTextureA def
          # lineCap def
          # lineJoin def
          # lineMiterLimitA def

    -- | Adjust the size and position of a 2D diagram to fit within the
    --   requested size. The first argument is a lens into the output
    --   size contained in the rendering options.  Returns an updated
    --   options record, any transformation applied to the diagram (the
    --   inverse of which can be used, say, to translate output/device
    --   coordinates back into local diagram coordinates), and the
    --   modified diagram itself.
    adjustSize2D
      :: (TypeableFloat n, Monoid' m)
      => Lens' (Options b V2 n) (SizeSpec V2 n)
      -> b
      -> Options b V2 n
      -> QDiagram b V2 n m
      -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    adjustSize2D :: Lens' (Options b V2 n) (SizeSpec V2 n)
    -> b
    -> Options b V2 n
    -> QDiagram b V2 n m
    -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    adjustSize2D szL :: Lens' (Options b V2 n) (SizeSpec V2 n)
    szL _ opts :: Options b V2 n
    opts d :: QDiagram b V2 n m
    d = (ASetter
      (Options b V2 n) (Options b V2 n) (SizeSpec V2 n) (SizeSpec V2 n)
    -> SizeSpec V2 n -> Options b V2 n -> Options b V2 n
    forall s t a b. ASetter s t a b -> b -> s -> t
    set ASetter
      (Options b V2 n) (Options b V2 n) (SizeSpec V2 n) (SizeSpec V2 n)
    Lens' (Options b V2 n) (SizeSpec V2 n)
    szL SizeSpec V2 n
    spec Options b V2 n
    opts, Transformation V2 n
    t, QDiagram b V2 n m
    d QDiagram b V2 n m
    -> (QDiagram b V2 n m -> QDiagram b V2 n m) -> QDiagram b V2 n m
    forall a b. a -> (a -> b) -> b
    # Transformation (V (QDiagram b V2 n m)) (N (QDiagram b V2 n m))
    -> QDiagram b V2 n m -> QDiagram b V2 n m
    forall t. Transformable t => Transformation (V t) (N t) -> t -> t
    transform Transformation (V (QDiagram b V2 n m)) (N (QDiagram b V2 n m))
    Transformation V2 n
    t)
      where
        spec :: SizeSpec V2 n
    spec    = V2 n -> SizeSpec V2 n
    forall (v :: * -> *) n. v n -> SizeSpec v n
    dims V2 n
    sz
        (sz :: V2 n
    sz, t :: Transformation V2 n
    t) = SizeSpec V2 n -> BoundingBox V2 n -> (V2 n, Transformation V2 n)
    forall (v :: * -> *) n.
    (Additive v, Foldable v, OrderedField n) =>
    SizeSpec v n -> BoundingBox v n -> (v n, Transformation v n)
    sizeAdjustment (Options b V2 n
    opts Options b V2 n
    -> Getting (SizeSpec V2 n) (Options b V2 n) (SizeSpec V2 n)
    -> SizeSpec V2 n
    forall s a. s -> Getting a s a -> a
    ^. Getting (SizeSpec V2 n) (Options b V2 n) (SizeSpec V2 n)
    Lens' (Options b V2 n) (SizeSpec V2 n)
    szL) (QDiagram b V2 n m -> BoundingBox V2 n
    forall (v :: * -> *) n a.
    (InSpace v n a, HasBasis v, Enveloped a) =>
    a -> BoundingBox v n
    boundingBox QDiagram b V2 n m
    d)

    -- | @adjustDia2D@ provides a useful default implementation of
    --   the 'adjustDia' method from the 'Backend' type class.
    --
    --   As its first argument it requires a lens into the output size
    --   contained in the rendering options.
    --
    --   It then performs the following adjustments:
    --
    --   * Set default attributes (see 'setDefault2DAttributes')
    --
    --   * Scale and translate the diagram to fit within the requested
    --     size (see 'adjustDiaSize2D')
    --
    --   It returns an updated options record, any transformation applied
    --   to the diagram (the inverse of which can be used, say, to
    --   translate output/device coordinates back into local diagram
    --   coordinates), and the modified diagram itself.
    adjustDia2D :: (TypeableFloat n, Monoid' m)
                => Lens' (Options b V2 n) (SizeSpec V2 n)
                -> b -> Options b V2 n -> QDiagram b V2 n m
                -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    adjustDia2D :: Lens' (Options b V2 n) (SizeSpec V2 n)
    -> b
    -> Options b V2 n
    -> QDiagram b V2 n m
    -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    adjustDia2D szL :: Lens' (Options b V2 n) (SizeSpec V2 n)
    szL b :: b
    b opts :: Options b V2 n
    opts d :: QDiagram b V2 n m
    d
      = Lens' (Options b V2 n) (SizeSpec V2 n)
    -> b
    -> Options b V2 n
    -> QDiagram b V2 n m
    -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    forall n m b.
    (TypeableFloat n, Monoid' m) =>
    Lens' (Options b V2 n) (SizeSpec V2 n)
    -> b
    -> Options b V2 n
    -> QDiagram b V2 n m
    -> (Options b V2 n, Transformation V2 n, QDiagram b V2 n m)
    adjustSize2D Lens' (Options b V2 n) (SizeSpec V2 n)
    szL b
    b Options b V2 n
    opts (QDiagram b V2 n m
    d QDiagram b V2 n m
    -> (QDiagram b V2 n m -> QDiagram b V2 n m) -> QDiagram b V2 n m
    forall a b. a -> (a -> b) -> b
    # QDiagram b V2 n m -> QDiagram b V2 n m
    forall n m b.
    (TypeableFloat n, Semigroup m) =>
    QDiagram b V2 n m -> QDiagram b V2 n m
    setDefault2DAttributes)