{-# LANGUAGE ConstraintKinds            #-}
{-# LANGUAGE DeriveDataTypeable         #-}
{-# LANGUAGE FlexibleContexts           #-}
{-# LANGUAGE FlexibleInstances          #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE TypeOperators              #-}
{-# LANGUAGE UndecidableInstances       #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Diagrams.TwoD.Text
-- Copyright   :  (c) 2011-2015 diagrams-lib team (see LICENSE)
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  diagrams-discuss@googlegroups.com
--
-- Very basic text primitives along with associated attributes.
--
-----------------------------------------------------------------------------

module Diagrams.TwoD.Text (
  -- * Creating text diagrams
    Text(..), TextAlignment(..)
  , text, topLeftText, alignedText, baselineText
  , mkText, mkText'

  -- * Text attributes

  -- ** Font family
  , Font(..), _Font
  , getFont, font, _font

  -- ** Font size
  , FontSize(..), _FontSize
  , fontSize, recommendFontSize
  , fontSizeN, fontSizeO, fontSizeL, fontSizeG
  , getFontSize, fontSizeM
  , _fontSizeR, _fontSize, _fontSizeU

  -- ** Font slant
  , FontSlant(..)
  , getFontSlant, fontSlant, italic, oblique, _fontSlant

  -- ** Font weight
  , FontWeight(..)
  , getFontWeight, fontWeight, bold, bolder, lighter, _fontWeight
  , thinWeight, ultraLight, light, mediumWeight, heavy, semiBold, ultraBold

  ) where

import           Control.Lens             hiding (transform)
import           Diagrams.Attributes      (committed)
import           Diagrams.Core
import           Diagrams.Core.Envelope   (pointEnvelope)
import           Diagrams.TwoD.Attributes (recommendFillColor)
import           Diagrams.TwoD.Types

import           Data.Colour              hiding (over)
import           Data.Default.Class
import           Data.Monoid.Recommend
import           Data.Semigroup
import           Data.Typeable

import           Linear.Affine

------------------------------------------------------------
-- Text diagrams
------------------------------------------------------------

-- | A 'Text' primitive consists of the string contents, text alignment
--   and the transformation to be applied. The transformation is scale
--   invarient, the average scale of the transform should always be 1.
--   All text scaling is obtained from the 'FontSize' attribute.
--
--   This constructor should not be used directly. Use 'text',
--   'alignedText' or 'baselineText'.
data Text n = Text (T2 n) (TextAlignment n) String
  deriving Typeable

type instance V (Text n) = V2
type instance N (Text n) = n

instance Floating n => Transformable (Text n) where
  transform :: Transformation (V (Text n)) (N (Text n)) -> Text n -> Text n
transform Transformation (V (Text n)) (N (Text n))
t (Text T2 n
tt TextAlignment n
a String
s) = forall n. T2 n -> TextAlignment n -> String -> Text n
Text (Transformation (V (Text n)) (N (Text n))
t forall a. Semigroup a => a -> a -> a
<> T2 n
tt forall a. Semigroup a => a -> a -> a
<> T2 n
t') TextAlignment n
a String
s
    where t' :: T2 n
t' = forall (v :: * -> *) n.
(Additive v, Fractional n) =>
n -> Transformation v n
scaling (n
1 forall a. Fractional a => a -> a -> a
/ forall (v :: * -> *) n.
(Additive v, Traversable v, Floating n) =>
Transformation v n -> n
avgScale Transformation (V (Text n)) (N (Text n))
t)

instance Floating n => HasOrigin (Text n) where
  moveOriginTo :: Point (V (Text n)) (N (Text n)) -> Text n -> Text n
moveOriginTo Point (V (Text n)) (N (Text n))
p = forall t. Transformable t => Vn t -> t -> t
translate (forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin forall (p :: * -> *) a. (Affine p, Num a) => p a -> p a -> Diff p a
.-. Point (V (Text n)) (N (Text n))
p)

instance Floating n => Renderable (Text n) NullBackend where
  render :: NullBackend
-> Text n -> Render NullBackend (V (Text n)) (N (Text n))
render NullBackend
_ Text n
_ = forall a. Monoid a => a
mempty

-- | @TextAlignment@ specifies the alignment of the text's origin.
data TextAlignment n = BaselineText | BoxAlignedText n n

-- | Make a text from a 'TextAlignment', recommending a fill colour of
--   'black' and 'fontSize' of @'local' 1@.
mkText :: (TypeableFloat n, Renderable (Text n) b)
  => TextAlignment n -> String -> QDiagram b V2 n Any
mkText :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText TextAlignment n
a = forall n a c.
(InSpace V2 n a, Color c, Typeable n, Floating n, HasStyle a) =>
c -> a -> a
recommendFillColor forall a. Num a => Colour a
black
           -- See Note [recommendFillColor]
         forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
recommendFontSize (forall n. Num n => n -> Measure n
local n
1)
           -- See Note [recommendFontSize]
         forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText' TextAlignment n
a

-- | Make a text from a 'TextAlignment' without any default size or fill
--   colour. This is useful is you want to recommend your own using
--   'recommendFillColor' or 'recommendFontSize'.
mkText' :: (TypeableFloat n, Renderable (Text n) b)
  => TextAlignment n -> String -> QDiagram b V2 n Any
mkText' :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText' TextAlignment n
a String
t = forall b (v :: * -> *) n m.
Prim b v n
-> Envelope v n
-> Trace v n
-> SubMap b v n m
-> Query v n m
-> QDiagram b v n m
mkQD (forall p b.
(Transformable p, Typeable p, Renderable p b) =>
p -> Prim b (V p) (N p)
Prim forall a b. (a -> b) -> a -> b
$ forall n. T2 n -> TextAlignment n -> String -> Text n
Text forall a. Monoid a => a
mempty TextAlignment n
a String
t)
                   (forall n (v :: * -> *).
(Fractional n, Metric v) =>
Point v n -> Envelope v n
pointEnvelope forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin)
                   forall a. Monoid a => a
mempty
                   forall a. Monoid a => a
mempty
                   forall a. Monoid a => a
mempty


-- ~~~~ Note [recommendFillColor]

-- The reason we "recommend" a fill color of black instead of setting
-- it directly (or instead of simply not specifying a fill color at
-- all) was originally to support the SVG backend, though it is
-- actually in some sense the "right thing" to do, and other backends
-- we add later may conceivably need it as well.  The cairo backend
-- defaults happen to be to use a transparent fill for paths and a
-- black fill for text.  The SVG standard, however, specifies a
-- default fill of black for everything (both text and paths).  In
-- order to correctly render paths with no fill set, the SVG backend
-- must therefore explicitly set the fill to transparent -- but this
-- meant that it was also drawing text with a transparent fill.  The
-- solution is that we now explicitly inform all backends that the
-- *default* ("recommended") fill color for text should be black; an
-- absence of fill specification now consistently means to use a
-- "transparent" fill no matter what the primitive.  The reason we
-- need the special recommend/commit distinction is because if the
-- user explicitly sets a fill color later it should override this
-- recommendation; normally, the innermost occurrence of an attribute
-- would override all outer occurrences.

-- ~~~~ Note [recommendFontSize]
-- The reason we "recommend" a font size is so any local scales get
-- recorded.

-- | Create a primitive text diagram from the given string, with center
--   alignment, equivalent to @'alignedText' 0.5 0.5@.
--
--   Note that it /takes up no space/, as text size information is not
--   available.
text :: (TypeableFloat n, Renderable (Text n) b) => String -> QDiagram b V2 n Any
text :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
String -> QDiagram b V2 n Any
text = forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
n -> n -> String -> QDiagram b V2 n Any
alignedText n
0.5 n
0.5

-- | Create a primitive text diagram from the given string, origin at
--   the top left corner of the text's bounding box, equivalent to
--   @'alignedText' 0 1@.
--
--   Note that it /takes up no space/.
topLeftText :: (TypeableFloat n, Renderable (Text n) b) => String -> QDiagram b V2 n Any
topLeftText :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
String -> QDiagram b V2 n Any
topLeftText = forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
n -> n -> String -> QDiagram b V2 n Any
alignedText n
0 n
1

-- | Create a primitive text diagram from the given string, with the
--   origin set to a point interpolated within the bounding box.  The
--   first parameter varies from 0 (left) to 1 (right), and the second
--   parameter from 0 (bottom) to 1 (top). Some backends do not
--   implement this and instead snap to closest corner or the center.
--
--   The height of this box is determined by the font's potential ascent
--   and descent, rather than the height of the particular string.
--
--   Note that it /takes up no space/.
alignedText :: (TypeableFloat n, Renderable (Text n) b)
  => n -> n -> String -> QDiagram b V2 n Any
alignedText :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
n -> n -> String -> QDiagram b V2 n Any
alignedText n
w n
h = forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText (forall n. n -> n -> TextAlignment n
BoxAlignedText n
w n
h)

-- | Create a primitive text diagram from the given string, with the
--   origin set to be on the baseline, at the beginning (although not
--   bounding).  This is the reference point of showText in the Cairo
--   graphics library.
--
--   Note that it /takes up no space/.
baselineText :: (TypeableFloat n, Renderable (Text n) b)
  => String -> QDiagram b V2 n Any
baselineText :: forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
String -> QDiagram b V2 n Any
baselineText = forall n b.
(TypeableFloat n, Renderable (Text n) b) =>
TextAlignment n -> String -> QDiagram b V2 n Any
mkText forall n. TextAlignment n
BaselineText

------------------------------------------------------------
-- Text attributes
------------------------------------------------------------

--------------------------------------------------
-- Font family

-- | The @Font@ attribute specifies the name of a font family.  Inner
--   @Font@ attributes override outer ones.
newtype Font = Font (Last String)
  deriving (Typeable, NonEmpty Font -> Font
Font -> Font -> Font
forall b. Integral b => b -> Font -> Font
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
stimes :: forall b. Integral b => b -> Font -> Font
$cstimes :: forall b. Integral b => b -> Font -> Font
sconcat :: NonEmpty Font -> Font
$csconcat :: NonEmpty Font -> Font
<> :: Font -> Font -> Font
$c<> :: Font -> Font -> Font
Semigroup, Font -> Font -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Font -> Font -> Bool
$c/= :: Font -> Font -> Bool
== :: Font -> Font -> Bool
$c== :: Font -> Font -> Bool
Eq)

_Font :: Iso' Font String
_Font :: Iso' Font String
_Font = forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Font -> String
getFont (Last String -> Font
Font forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Last a
Last)

instance AttributeClass Font

-- | Extract the font family name from a @Font@ attribute.
getFont :: Font -> String
getFont :: Font -> String
getFont (Font (Last String
f)) = String
f

-- | Specify a font family to be used for all text within a diagram.
font :: HasStyle a => String -> a -> a
font :: forall a. HasStyle a => String -> a -> a
font = forall a d. (AttributeClass a, HasStyle d) => a -> d -> d
applyAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. Last String -> Font
Font forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Last a
Last

-- | Lens onto the font name of a style.
_font :: Lens' (Style v n) (Maybe String)
_font :: forall (v :: * -> *) n. Lens' (Style v n) (Maybe String)
_font = forall a (v :: * -> *) n.
AttributeClass a =>
Lens' (Style v n) (Maybe a)
atAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping Iso' Font String
_Font

--------------------------------------------------
-- Font size

-- | The @FontSize@ attribute specifies the size of a font's
--   em-square.  Inner @FontSize@ attributes override outer ones.
newtype FontSize n = FontSize (Recommend (Last n))
  deriving (Typeable, NonEmpty (FontSize n) -> FontSize n
FontSize n -> FontSize n -> FontSize n
forall b. Integral b => b -> FontSize n -> FontSize n
forall n. NonEmpty (FontSize n) -> FontSize n
forall n. FontSize n -> FontSize n -> FontSize n
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall n b. Integral b => b -> FontSize n -> FontSize n
stimes :: forall b. Integral b => b -> FontSize n -> FontSize n
$cstimes :: forall n b. Integral b => b -> FontSize n -> FontSize n
sconcat :: NonEmpty (FontSize n) -> FontSize n
$csconcat :: forall n. NonEmpty (FontSize n) -> FontSize n
<> :: FontSize n -> FontSize n -> FontSize n
$c<> :: forall n. FontSize n -> FontSize n -> FontSize n
Semigroup)

-- not sure why this can't be derived
instance Functor FontSize where
  fmap :: forall a b. (a -> b) -> FontSize a -> FontSize b
fmap a -> b
f (FontSize (Recommend (Last a
a))) = forall n. Recommend (Last n) -> FontSize n
FontSize (forall a. a -> Recommend a
Recommend (forall a. a -> Last a
Last (a -> b
f a
a)))
  fmap a -> b
f (FontSize (Commit (Last a
a)))    = forall n. Recommend (Last n) -> FontSize n
FontSize (forall a. a -> Recommend a
Commit (forall a. a -> Last a
Last (a -> b
f a
a)))

_FontSize :: Iso' (FontSize n) (Recommend n)
_FontSize :: forall n. Iso' (FontSize n) (Recommend n)
_FontSize = forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso forall {a}. FontSize a -> Recommend a
getter forall {n}. Recommend n -> FontSize n
setter
  where getter :: FontSize a -> Recommend a
getter (FontSize (Recommend (Last a
a))) = forall a. a -> Recommend a
Recommend a
a
        getter (FontSize (Commit    (Last a
a))) = forall a. a -> Recommend a
Commit a
a
        setter :: Recommend n -> FontSize n
setter (Recommend n
a) = forall n. Recommend (Last n) -> FontSize n
FontSize forall a b. (a -> b) -> a -> b
$ forall a. a -> Recommend a
Recommend (forall a. a -> Last a
Last n
a)
        setter (Commit    n
a) = forall n. Recommend (Last n) -> FontSize n
FontSize forall a b. (a -> b) -> a -> b
$ forall a. a -> Recommend a
Commit (forall a. a -> Last a
Last n
a)
      -- = iso (\(FontSize a) -> a) FontSize . mapping _Wrapped
      -- once we depend on monoid-extras-0.4

_FontSizeM :: Iso' (FontSizeM n) (Measured n (Recommend n))
_FontSizeM :: forall n. Iso' (FontSizeM n) (Measured n (Recommend n))
_FontSizeM = forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping forall n. Iso' (FontSize n) (Recommend n)
_FontSize

type FontSizeM n = Measured n (FontSize n)

instance Typeable n => AttributeClass (FontSize n)

instance Num n => Default (FontSizeM n) where
  def :: FontSizeM n
def = forall n. Recommend (Last n) -> FontSize n
FontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Recommend a
Recommend forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Last a
Last forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall n. Num n => n -> Measure n
local n
1

-- | Extract the size from a @FontSize@ attribute.
getFontSize :: FontSize n -> n
getFontSize :: forall n. FontSize n -> n
getFontSize (FontSize (Recommend (Last n
s))) = n
s
getFontSize (FontSize (Commit (Last n
s)))    = n
s

-- | Set the font size, that is, the size of the font's em-square as
--   measured within the current local vector space. The default size
--   is @local 1@ (which is applied by 'recommendFontSize').
fontSize :: (N a ~ n, Typeable n, HasStyle a) => Measure n -> a -> a
fontSize :: forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize = forall a d n.
(AttributeClass a, N d ~ n, HasStyle d) =>
Measured n a -> d -> d
applyMAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall n. Recommend (Last n) -> FontSize n
FontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Recommend a
Commit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Last a
Last)

-- | 'Recommend' a font size. Any use of 'fontSize' above this will
--   overwrite any recommended size. This should only be used with
--   'mkText'', other text functions already has a recommended font
--   size so this will be ignored.
recommendFontSize :: (N a ~ n, Typeable n, HasStyle a) => Measure n -> a -> a
recommendFontSize :: forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
recommendFontSize = forall a d n.
(AttributeClass a, N d ~ n, HasStyle d) =>
Measured n a -> d -> d
applyMAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall n. Recommend (Last n) -> FontSize n
FontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Recommend a
Recommend forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Last a
Last)

-- | A convenient synonym for 'fontSize (Global w)'.
fontSizeG :: (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeG :: forall a n. (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeG = forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Num n => n -> Measure n
global

-- | A convenient synonym for 'fontSize (Normalized w)'.
fontSizeN :: (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeN :: forall a n. (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeN = forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Num n => n -> Measure n
normalized

-- | A convenient synonym for 'fontSize (Output w)'.
fontSizeO :: (N a ~ n, Typeable n, HasStyle a) => n -> a -> a
fontSizeO :: forall a n. (N a ~ n, Typeable n, HasStyle a) => n -> a -> a
fontSizeO = forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. n -> Measure n
output

-- | A convenient sysnonym for 'fontSize (Local w)'.
fontSizeL :: (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeL :: forall a n. (N a ~ n, Typeable n, Num n, HasStyle a) => n -> a -> a
fontSizeL = forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
Measure n -> a -> a
fontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Num n => n -> Measure n
local

-- | Apply a 'FontSize' attribute.
fontSizeM :: (N a ~ n, Typeable n, HasStyle a) => FontSizeM n -> a -> a
fontSizeM :: forall a n.
(N a ~ n, Typeable n, HasStyle a) =>
FontSizeM n -> a -> a
fontSizeM = forall a d n.
(AttributeClass a, N d ~ n, HasStyle d) =>
Measured n a -> d -> d
applyMAttr

_fontSizeR :: (Typeable n, OrderedField n) => Lens' (Style v n) (Measured n (Recommend n))
_fontSizeR :: forall n (v :: * -> *).
(Typeable n, OrderedField n) =>
Lens' (Style v n) (Measured n (Recommend n))
_fontSizeR = forall a n (v :: * -> *).
(AttributeClass a, Typeable n) =>
Lens' (Style v n) (Maybe (Measured n a))
atMAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> (a -> Bool) -> Iso' (Maybe a) a
anon forall a. Default a => a
def (forall a b. a -> b -> a
const Bool
False) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. Iso' (FontSizeM n) (Measured n (Recommend n))
_FontSizeM

-- | Lens to commit a font size. This is *not* a valid lens (see
--   'commited'.
_fontSize :: (Typeable n, OrderedField n) => Lens' (Style v n) (Measure n)
_fontSize :: forall n (v :: * -> *).
(Typeable n, OrderedField n) =>
Lens' (Style v n) (Measure n)
_fontSize = forall n (v :: * -> *).
(Typeable n, OrderedField n) =>
Lens' (Style v n) (Measured n (Recommend n))
_fontSizeR forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping forall a b. Iso (Recommend a) (Recommend b) a b
committed

_fontSizeU :: (Typeable n) => Lens' (Style v n) (Maybe n)
_fontSizeU :: forall n (v :: * -> *). Typeable n => Lens' (Style v n) (Maybe n)
_fontSizeU = forall a (v :: * -> *) n.
AttributeClass a =>
Lens' (Style v n) (Maybe a)
atAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) (g :: * -> *) s t a b.
(Functor f, Functor g) =>
AnIso s t a b -> Iso (f s) (g t) (f a) (g b)
mapping (forall n. Iso' (FontSize n) (Recommend n)
_FontSize forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Iso (Recommend a) (Recommend b) a b
committed)

--------------------------------------------------
-- Font slant

-- | The @FontSlantA@ attribute specifies the slant (normal, italic,
--   or oblique) that should be used for all text within a diagram.
--   Inner @FontSlantA@ attributes override outer ones.
data FontSlant = FontSlantNormal
               | FontSlantItalic
               | FontSlantOblique
  deriving (FontSlant -> FontSlant -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FontSlant -> FontSlant -> Bool
$c/= :: FontSlant -> FontSlant -> Bool
== :: FontSlant -> FontSlant -> Bool
$c== :: FontSlant -> FontSlant -> Bool
Eq, Int -> FontSlant -> ShowS
[FontSlant] -> ShowS
FontSlant -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FontSlant] -> ShowS
$cshowList :: [FontSlant] -> ShowS
show :: FontSlant -> String
$cshow :: FontSlant -> String
showsPrec :: Int -> FontSlant -> ShowS
$cshowsPrec :: Int -> FontSlant -> ShowS
Show, Typeable, Eq FontSlant
FontSlant -> FontSlant -> Bool
FontSlant -> FontSlant -> Ordering
FontSlant -> FontSlant -> FontSlant
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
min :: FontSlant -> FontSlant -> FontSlant
$cmin :: FontSlant -> FontSlant -> FontSlant
max :: FontSlant -> FontSlant -> FontSlant
$cmax :: FontSlant -> FontSlant -> FontSlant
>= :: FontSlant -> FontSlant -> Bool
$c>= :: FontSlant -> FontSlant -> Bool
> :: FontSlant -> FontSlant -> Bool
$c> :: FontSlant -> FontSlant -> Bool
<= :: FontSlant -> FontSlant -> Bool
$c<= :: FontSlant -> FontSlant -> Bool
< :: FontSlant -> FontSlant -> Bool
$c< :: FontSlant -> FontSlant -> Bool
compare :: FontSlant -> FontSlant -> Ordering
$ccompare :: FontSlant -> FontSlant -> Ordering
Ord)

instance AttributeClass FontSlant where
instance Semigroup FontSlant where
  FontSlant
_ <> :: FontSlant -> FontSlant -> FontSlant
<> FontSlant
b = FontSlant
b

instance Default FontSlant where
  def :: FontSlant
def = FontSlant
FontSlantNormal

-- | Extract the font slant from a 'FontSlantA' attribute.
getFontSlant :: FontSlant -> FontSlant
getFontSlant :: FontSlant -> FontSlant
getFontSlant = forall a. a -> a
id

-- | Specify the slant (normal, italic, or oblique) that should be
--   used for all text within a diagram.  See also 'italic' and
--   'oblique' for useful special cases.
fontSlant :: HasStyle a => FontSlant -> a -> a
fontSlant :: forall a. HasStyle a => FontSlant -> a -> a
fontSlant = forall a d. (AttributeClass a, HasStyle d) => a -> d -> d
applyAttr

-- | Lens onto the font slant in a style.
_fontSlant :: Lens' (Style v n) FontSlant
_fontSlant :: forall (v :: * -> *) n. Lens' (Style v n) FontSlant
_fontSlant = forall a (v :: * -> *) n.
AttributeClass a =>
Lens' (Style v n) (Maybe a)
atAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => a -> Iso' (Maybe a) a
non forall a. Default a => a
def

-- | Set all text in italics.
italic :: HasStyle a => a -> a
italic :: forall a. HasStyle a => a -> a
italic = forall a. HasStyle a => FontSlant -> a -> a
fontSlant FontSlant
FontSlantItalic

-- | Set all text using an oblique slant.
oblique :: HasStyle a => a -> a
oblique :: forall a. HasStyle a => a -> a
oblique = forall a. HasStyle a => FontSlant -> a -> a
fontSlant FontSlant
FontSlantOblique

--------------------------------------------------
-- Font weight

-- | The @FontWeightA@ attribute specifies the weight (normal or bold)
--   that should be used for all text within a diagram.  Inner
--   @FontWeightA@ attributes override outer ones.
data FontWeight = FontWeightNormal
                | FontWeightBold
                | FontWeightBolder
                | FontWeightLighter
                | FontWeightThin
                | FontWeightUltraLight
                | FontWeightLight
                | FontWeightMedium
                | FontWeightSemiBold
                | FontWeightUltraBold
                | FontWeightHeavy
    deriving (FontWeight -> FontWeight -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FontWeight -> FontWeight -> Bool
$c/= :: FontWeight -> FontWeight -> Bool
== :: FontWeight -> FontWeight -> Bool
$c== :: FontWeight -> FontWeight -> Bool
Eq,
              Eq FontWeight
FontWeight -> FontWeight -> Bool
FontWeight -> FontWeight -> Ordering
FontWeight -> FontWeight -> FontWeight
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
min :: FontWeight -> FontWeight -> FontWeight
$cmin :: FontWeight -> FontWeight -> FontWeight
max :: FontWeight -> FontWeight -> FontWeight
$cmax :: FontWeight -> FontWeight -> FontWeight
>= :: FontWeight -> FontWeight -> Bool
$c>= :: FontWeight -> FontWeight -> Bool
> :: FontWeight -> FontWeight -> Bool
$c> :: FontWeight -> FontWeight -> Bool
<= :: FontWeight -> FontWeight -> Bool
$c<= :: FontWeight -> FontWeight -> Bool
< :: FontWeight -> FontWeight -> Bool
$c< :: FontWeight -> FontWeight -> Bool
compare :: FontWeight -> FontWeight -> Ordering
$ccompare :: FontWeight -> FontWeight -> Ordering
Ord, Int -> FontWeight -> ShowS
[FontWeight] -> ShowS
FontWeight -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FontWeight] -> ShowS
$cshowList :: [FontWeight] -> ShowS
show :: FontWeight -> String
$cshow :: FontWeight -> String
showsPrec :: Int -> FontWeight -> ShowS
$cshowsPrec :: Int -> FontWeight -> ShowS
Show, Typeable)

instance AttributeClass FontWeight

-- | Last semigroup structure
instance Semigroup FontWeight where
  FontWeight
_ <> :: FontWeight -> FontWeight -> FontWeight
<> FontWeight
b = FontWeight
b

instance Default FontWeight where
  def :: FontWeight
def = FontWeight
FontWeightNormal

-- | Extract the font weight.
getFontWeight :: FontWeight -> FontWeight
getFontWeight :: FontWeight -> FontWeight
getFontWeight = forall a. a -> a
id

-- | Specify the weight (normal, bolder, lighter or bold) that should be
--   used for all text within a diagram.  See also 'bold'
--   for a useful special case.
fontWeight :: HasStyle a => FontWeight -> a -> a
fontWeight :: forall a. HasStyle a => FontWeight -> a -> a
fontWeight = forall a d. (AttributeClass a, HasStyle d) => a -> d -> d
applyAttr

-- | Set all text using a bold font weight.
bold :: HasStyle a => a -> a
bold :: forall a. HasStyle a => a -> a
bold = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightBold

-- | Set all text using a thin font weight.
thinWeight :: HasStyle a => a -> a
thinWeight :: forall a. HasStyle a => a -> a
thinWeight = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightThin

-- | Set all text using a extra light font weight.
ultraLight :: HasStyle a => a -> a
ultraLight :: forall a. HasStyle a => a -> a
ultraLight = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightUltraLight

-- | Set all text using a light font weight.
light :: HasStyle a => a -> a
light :: forall a. HasStyle a => a -> a
light = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightLight

-- | Set all text using a medium font weight.
mediumWeight :: HasStyle a => a -> a
mediumWeight :: forall a. HasStyle a => a -> a
mediumWeight = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightMedium

-- | Set all text using a semi-bold font weight.
semiBold :: HasStyle a => a -> a
semiBold :: forall a. HasStyle a => a -> a
semiBold = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightSemiBold

-- | Set all text using an ultra-bold font weight.
ultraBold :: HasStyle a => a -> a
ultraBold :: forall a. HasStyle a => a -> a
ultraBold = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightUltraBold

-- | Set all text using a heavy/black font weight.
heavy :: HasStyle a => a -> a
heavy :: forall a. HasStyle a => a -> a
heavy = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightHeavy

-- | Set all text to be bolder than the inherited font weight.
bolder :: HasStyle a => a -> a
bolder :: forall a. HasStyle a => a -> a
bolder = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightBolder

-- | Set all text to be lighter than the inherited font weight.
lighter :: HasStyle a => a -> a
lighter :: forall a. HasStyle a => a -> a
lighter = forall a. HasStyle a => FontWeight -> a -> a
fontWeight FontWeight
FontWeightLighter

-- | Lens onto the font weight in a style.
_fontWeight :: Lens' (Style v n) FontWeight
_fontWeight :: forall (v :: * -> *) n. Lens' (Style v n) FontWeight
_fontWeight = forall a (v :: * -> *) n.
AttributeClass a =>
Lens' (Style v n) (Maybe a)
atAttr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => a -> Iso' (Maybe a) a
non forall a. Default a => a
def