{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
---------------------------------------------------------
-- |
-- Copyright   : (c) 2006-2016, alpheccar.org
-- License     : BSD-style
--
-- Maintainer  : misc@NOSPAMalpheccar.org
-- Stability   : experimental
-- Portability : portable
--
-- Box
---------------------------------------------------------
-- #hide
module Graphics.PDF.Typesetting.Layout (

   Container(..)
 , Width
 , Height
 , VBox(..)
 , ParagraphStyle(..)
 , VerState(..)
 , vglue
 , addTo
 , isOverfull
 , mkContainer
 , strokeVBoxes
 , containerX
 , containerY
 , containerWidth
 , containerHeight
 , containerContentHeight
 , containerContentRightBorder
 , containerContentLeftBorder
 , containerCurrentHeight
 , containerContentRectangle
 , containerParaTolerance
 ) where

import Graphics.PDF.LowLevel.Types
import Graphics.PDF.Typesetting.Breaking
import Graphics.PDF.Draw
import Graphics.PDF.Coordinates
import Graphics.PDF.Shapes(Rectangle(..))
import Graphics.PDF.Typesetting.Box
import Data.List(foldl')
import Data.Maybe(isJust,fromJust)


data VerState s = VerState { forall s. VerState s -> (PDFFloat, PDFFloat, PDFFloat)
baselineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (12,0.17,0.0)
                           , forall s. VerState s -> (PDFFloat, PDFFloat, PDFFloat)
lineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (3.0,0.33,0.0)
                           , forall s. VerState s -> PDFFloat
lineskiplimit :: !PDFFloat -- ^ Default value 2
                           , forall s. VerState s -> s
currentParagraphStyle :: !s
                           }
                           
data VBox ps s = Paragraph Int [Letter s] !(Maybe ps) !BRState
               | VBox !PDFFloat !PDFFloat !PDFFloat ![VBox ps s] !(Maybe ps)
               | VGlue !PDFFloat !PDFFloat !PDFFloat !(Maybe (PDFFloat,PDFFloat)) !(Maybe ps)
               | SomeVBox !PDFFloat !BoxDimension !AnyBox !(Maybe ps)

notGlue :: VBox ps s -> Bool
notGlue :: forall ps s. VBox ps s -> Bool
notGlue (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) = Bool
False
notGlue (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = Bool
False
notGlue VBox ps s
_ = Bool
True
                              
vglue :: Maybe ps
     -> PDFFloat -- ^ Glue height
     -> PDFFloat -- ^ Glue dilatation factor
     -> PDFFloat -- ^ Glue compression factor
     -> PDFFloat -- ^ Glue width
     -> PDFFloat -- ^ Glue delta
     -> VBox ps s
vglue :: forall ps s.
Maybe ps
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> VBox ps s
vglue Maybe ps
s PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
width PDFFloat
delta = forall ps s.
PDFFloat
-> PDFFloat
-> PDFFloat
-> Maybe (PDFFloat, PDFFloat)
-> Maybe ps
-> VBox ps s
VGlue PDFFloat
h PDFFloat
width PDFFloat
delta (forall a. a -> Maybe a
Just(PDFFloat
y,PDFFloat
z)) Maybe ps
s

instance Show (VBox ps s) where
 show :: VBox ps s -> String
show (VBox PDFFloat
_ PDFFloat
a PDFFloat
_ [VBox ps s]
l Maybe ps
_) = String
"(VBox " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show PDFFloat
a forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [VBox ps s]
l forall a. [a] -> [a] -> [a]
++ String
")"
 show (VGlue PDFFloat
a PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) = String
"(VGlue " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show PDFFloat
a forall a. [a] -> [a] -> [a]
++ String
")"
 show (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = String
"(Paragraph)"
 show (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
d AnyBox
t Maybe ps
_) = String
"(SomeVBox " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show (forall a. Box a => a -> PDFFloat
boxHeight (PDFFloat, PDFFloat, PDFFloat)
d) forall a. [a] -> [a] -> [a]
++ String
" " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show AnyBox
t forall a. [a] -> [a] -> [a]
++ String
")"

instance MaybeGlue (VBox ps s) where
  glueSizeWithRatio :: VBox ps s -> PDFFloat -> PDFFloat
glueSizeWithRatio (VGlue PDFFloat
w PDFFloat
_ PDFFloat
_ (Just(PDFFloat
y,PDFFloat
z)) Maybe ps
_) PDFFloat
r = PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat
glueSize PDFFloat
w PDFFloat
y PDFFloat
z PDFFloat
r
  glueSizeWithRatio VBox ps s
a PDFFloat
_ = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
a
  
  glueY :: VBox ps s -> PDFFloat
glueY (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ (Just(PDFFloat
y,PDFFloat
_)) Maybe ps
_)  = PDFFloat
y
  glueY VBox ps s
_ = PDFFloat
0
  glueZ :: VBox ps s -> PDFFloat
glueZ (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ (Just(PDFFloat
_,PDFFloat
z)) Maybe ps
_)  = PDFFloat
z
  glueZ VBox ps s
_ = PDFFloat
0

instance Box (VBox ps s) where
   boxWidth :: VBox ps s -> PDFFloat
boxWidth (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = PDFFloat
0
   boxWidth (VBox PDFFloat
w PDFFloat
_ PDFFloat
_ [VBox ps s]
_ Maybe ps
_) = PDFFloat
w
   boxWidth (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
d AnyBox
_ Maybe ps
_)  = forall a. Box a => a -> PDFFloat
boxWidth (PDFFloat, PDFFloat, PDFFloat)
d
   boxWidth (VGlue PDFFloat
_ PDFFloat
w PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_)  = PDFFloat
w

   boxHeight :: VBox ps s -> PDFFloat
boxHeight (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = PDFFloat
0
   boxHeight (VBox PDFFloat
_ PDFFloat
h PDFFloat
_ [VBox ps s]
_ Maybe ps
_) = PDFFloat
h
   boxHeight (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
d AnyBox
_ Maybe ps
_) = forall a. Box a => a -> PDFFloat
boxHeight (PDFFloat, PDFFloat, PDFFloat)
d
   boxHeight (VGlue PDFFloat
h PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) = PDFFloat
h

   boxDescent :: VBox ps s -> PDFFloat
boxDescent (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = PDFFloat
0
   boxDescent (VBox PDFFloat
_ PDFFloat
_ PDFFloat
d [VBox ps s]
_ Maybe ps
_) = PDFFloat
d
   boxDescent (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
d AnyBox
_ Maybe ps
_) = forall a. Box a => a -> PDFFloat
boxDescent (PDFFloat, PDFFloat, PDFFloat)
d
   boxDescent (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) = PDFFloat
0

instance (ParagraphStyle ps s) => DisplayableBox (VBox ps s) where
        strokeBox :: VBox ps s -> PDFFloat -> PDFFloat -> Draw ()
strokeBox (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) PDFFloat
_ PDFFloat
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
        strokeBox b :: VBox ps s
b@(VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
l Maybe ps
_) PDFFloat
x PDFFloat
y'' = forall ps s.
ParagraphStyle ps s =>
[VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
strokeVBoxes [VBox ps s]
l PDFFloat
x PDFFloat
y'
          where
              y' :: PDFFloat
y' = PDFFloat
y'' forall a. Num a => a -> a -> a
- forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
b
        strokeBox (VGlue PDFFloat
h PDFFloat
w PDFFloat
delta Maybe (PDFFloat, PDFFloat)
_ (Just ps
style)) PDFFloat
x PDFFloat
y = 
            if (forall a. Maybe a -> Bool
isJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. ParagraphStyle a s => a -> Maybe (Rectangle -> Draw ())
interline forall a b. (a -> b) -> a -> b
$ ps
style)
                then
                    (forall a. HasCallStack => Maybe a -> a
fromJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. ParagraphStyle a s => a -> Maybe (Rectangle -> Draw ())
interline forall a b. (a -> b) -> a -> b
$ ps
style) forall a b. (a -> b) -> a -> b
$ Point -> Point -> Rectangle
Rectangle ((PDFFloat
xforall a. Num a => a -> a -> a
+PDFFloat
delta) forall a. a -> a -> Complex a
:+ (PDFFloat
yforall a. Num a => a -> a -> a
-PDFFloat
h)) ((PDFFloat
xforall a. Num a => a -> a -> a
+PDFFloat
wforall a. Num a => a -> a -> a
+PDFFloat
delta) forall a. a -> a -> Complex a
:+ PDFFloat
y)
                else
                   forall (m :: * -> *) a. Monad m => a -> m a
return()
        strokeBox (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) PDFFloat
_ PDFFloat
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()

        strokeBox (SomeVBox PDFFloat
delta (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
a Maybe ps
_) PDFFloat
x PDFFloat
y = forall a. DisplayableBox a => a -> PDFFloat -> PDFFloat -> Draw ()
strokeBox AnyBox
a (PDFFloat
xforall a. Num a => a -> a -> a
+PDFFloat
delta) PDFFloat
y
                
type Width = PDFFloat
type Height = PDFFloat

-- | Container for vboxes (x,y,width,maxheight,height,currenty,current z, tolerance para)
-- tolerance para means a paragraph is not started if too close from the bottom edge of the box
data Container ps s = Container PDFFloat PDFFloat Width PDFFloat PDFFloat PDFFloat PDFFloat PDFFloat [VBox ps s]

-- | Create a empty container to constraint the amount of line that can be displayed
mkContainer :: PDFFloat -- ^ x
            -> PDFFloat -- ^ y
            -> PDFFloat -- ^ width
            -> PDFFloat -- ^ height
            -> PDFFloat -- ^ Pargraph tolerance
            -> Container ps s -- ^ New container
mkContainer :: forall ps s.
PDFFloat
-> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> Container ps s
mkContainer PDFFloat
x PDFFloat
y PDFFloat
width PDFFloat
height PDFFloat
tol = forall ps s.
PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> [VBox ps s]
-> Container ps s
Container PDFFloat
x PDFFloat
y PDFFloat
width PDFFloat
height PDFFloat
0 PDFFloat
0 PDFFloat
0 PDFFloat
tol []            

-- | Get the width of the container
containerWidth :: Container ps s -> PDFFloat
containerWidth :: forall ps s. Container ps s -> PDFFloat
containerWidth (Container PDFFloat
_ PDFFloat
_ PDFFloat
w PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_) = PDFFloat
w

-- | Get the width of the container
containerParaTolerance :: Container ps s -> PDFFloat
containerParaTolerance :: forall ps s. Container ps s -> PDFFloat
containerParaTolerance (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
t [VBox ps s]
_) = PDFFloat
t

-- | Get the height of the container
containerHeight :: Container ps s -> PDFFloat
containerHeight :: forall ps s. Container ps s -> PDFFloat
containerHeight (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
h PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_) = PDFFloat
h

-- | Get the current height of the container without glue dilatation
containerCurrentHeight :: Container ps s -> PDFFloat
containerCurrentHeight :: forall ps s. Container ps s -> PDFFloat
containerCurrentHeight (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
ch PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_) = PDFFloat
ch

-- | Get the content height of the container with glue dilatation
containerContentHeight :: Container ps s -> PDFFloat
containerContentHeight :: forall ps s. Container ps s -> PDFFloat
containerContentHeight (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
_ [VBox ps s]
_) = let r :: PDFFloat
r = forall a. Ord a => a -> a -> a
min (PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat
dilatationRatio PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z) PDFFloat
2.0 in
 PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat
glueSize PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
r
 
-- | Get the minimum left border of the container content
containerContentLeftBorder :: Container ps s -> PDFFloat
containerContentLeftBorder :: forall ps s. Container ps s -> PDFFloat
containerContentLeftBorder (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ []) = PDFFloat
0.0
containerContentLeftBorder (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
l) = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall ps s. VBox ps s -> PDFFloat
getBoxDelta forall a b. (a -> b) -> a -> b
$ [VBox ps s]
l
   
-- | Get the maximum right border of the container content (maybe bigger than container width due to overfull lines)
containerContentRightBorder :: Container ps s -> PDFFloat
containerContentRightBorder :: forall ps s. Container ps s -> PDFFloat
containerContentRightBorder (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ []) = PDFFloat
0.0
containerContentRightBorder (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
l) = 
 let xmax :: PDFFloat
xmax = forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall ps s. VBox ps s -> PDFFloat
rightBorder forall a b. (a -> b) -> a -> b
$ [VBox ps s]
l
     rightBorder :: VBox ps s -> PDFFloat
rightBorder VBox ps s
x = forall ps s. VBox ps s -> PDFFloat
getBoxDelta VBox ps s
x forall a. Num a => a -> a -> a
+ forall a. Box a => a -> PDFFloat
boxWidth VBox ps s
x
 in
  PDFFloat
xmax

-- | Container horizontal position
containerX :: Container ps s -> PDFFloat
containerX :: forall ps s. Container ps s -> PDFFloat
containerX (Container PDFFloat
x PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_) = PDFFloat
x

-- | Container vertical position
containerY :: Container ps s -> PDFFloat
containerY :: forall ps s. Container ps s -> PDFFloat
containerY (Container PDFFloat
_ PDFFloat
y PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_) = PDFFloat
y

-- | Return the rectangle containing the text after formatting and glue dilatation
containerContentRectangle :: Container ps s -> Rectangle
containerContentRectangle :: forall ps s. Container ps s -> Rectangle
containerContentRectangle Container ps s
c = Point -> Point -> Rectangle
Rectangle ((PDFFloat
xforall a. Num a => a -> a -> a
+PDFFloat
l) forall a. a -> a -> Complex a
:+ (PDFFloat
yforall a. Num a => a -> a -> a
-PDFFloat
th)) ((PDFFloat
xforall a. Num a => a -> a -> a
+PDFFloat
r) forall a. a -> a -> Complex a
:+ PDFFloat
y)
 where
    x :: PDFFloat
x = forall ps s. Container ps s -> PDFFloat
containerX Container ps s
c
    y :: PDFFloat
y = forall ps s. Container ps s -> PDFFloat
containerY Container ps s
c
    th :: PDFFloat
th = forall ps s. Container ps s -> PDFFloat
containerContentHeight Container ps s
c
    l :: PDFFloat
l = forall ps s. Container ps s -> PDFFloat
containerContentLeftBorder Container ps s
c
    r :: PDFFloat
r = forall ps s. Container ps s -> PDFFloat
containerContentRightBorder Container ps s
c


-- | Get the required style for the interline glue
getInterlineStyle :: ComparableStyle ps => VBox ps s -> VBox ps s -> Maybe ps
getInterlineStyle :: forall ps s.
ComparableStyle ps =>
VBox ps s -> VBox ps s -> Maybe ps
getInterlineStyle (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s)) (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s')) | ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs` ps
s' = forall a. a -> Maybe a
Just ps
s
                                                                     | Bool
otherwise = forall a. Maybe a
Nothing

getInterlineStyle (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s)) (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s')) |  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s' = forall a. a -> Maybe a
Just ps
s
                                                                   | Bool
otherwise = forall a. Maybe a
Nothing

getInterlineStyle (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s)) (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s')) |  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s' = forall a. a -> Maybe a
Just ps
s
                                                                       | Bool
otherwise = forall a. Maybe a
Nothing

getInterlineStyle (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s)) (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s')) |  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s' = forall a. a -> Maybe a
Just ps
s
                                                                     | Bool
otherwise = forall a. Maybe a
Nothing

getInterlineStyle VBox ps s
_ VBox ps s
_ = forall a. Maybe a
Nothing

-- | Interline glue required
interlineGlue :: ComparableStyle ps => VerState ps -> VBox ps s -> VBox ps s -> Maybe (VBox ps s, PDFFloat, PDFFloat)
interlineGlue :: forall ps s.
ComparableStyle ps =>
VerState ps
-> VBox ps s -> VBox ps s -> Maybe (VBox ps s, PDFFloat, PDFFloat)
interlineGlue VerState ps
settings VBox ps s
a VBox ps s
b | forall ps s. VBox ps s -> Bool
notGlue VBox ps s
a Bool -> Bool -> Bool
&& forall ps s. VBox ps s -> Bool
notGlue VBox ps s
b = 
    let p :: PDFFloat
p = forall a. Box a => a -> PDFFloat
boxDescent VBox ps s
a
        h :: PDFFloat
h = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
b forall a. Num a => a -> a -> a
- forall a. Box a => a -> PDFFloat
boxDescent VBox ps s
b
        (PDFFloat
ba,PDFFloat
by,PDFFloat
bz) = forall s. VerState s -> (PDFFloat, PDFFloat, PDFFloat)
baselineskip VerState ps
settings
        (PDFFloat
lw,PDFFloat
ly,PDFFloat
lz) = forall s. VerState s -> (PDFFloat, PDFFloat, PDFFloat)
lineskip VerState ps
settings
        li :: PDFFloat
li = forall s. VerState s -> PDFFloat
lineskiplimit VerState ps
settings
        istyle :: Maybe ps
istyle = forall ps s.
ComparableStyle ps =>
VBox ps s -> VBox ps s -> Maybe ps
getInterlineStyle VBox ps s
a VBox ps s
b
        theWidth :: PDFFloat
theWidth = forall a. Box a => a -> PDFFloat
boxWidth VBox ps s
a
        theDelta :: PDFFloat
theDelta = forall ps s. VBox ps s -> PDFFloat
getBoxDelta VBox ps s
a
    in
    if PDFFloat
p forall a. Ord a => a -> a -> Bool
<= -PDFFloat
1000 
        then
            forall a. Maybe a
Nothing
        else
            if PDFFloat
ba forall a. Num a => a -> a -> a
- PDFFloat
p forall a. Num a => a -> a -> a
- PDFFloat
h forall a. Ord a => a -> a -> Bool
>= PDFFloat
li
                then
                    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ (forall ps s.
Maybe ps
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> VBox ps s
vglue Maybe ps
istyle (PDFFloat
baforall a. Num a => a -> a -> a
-PDFFloat
pforall a. Num a => a -> a -> a
-PDFFloat
h) PDFFloat
by PDFFloat
bz PDFFloat
theWidth PDFFloat
theDelta,PDFFloat
by,PDFFloat
bz)
                else
                    forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ (forall ps s.
Maybe ps
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> VBox ps s
vglue Maybe ps
istyle PDFFloat
lw PDFFloat
ly PDFFloat
lz PDFFloat
theWidth PDFFloat
theDelta,PDFFloat
ly,PDFFloat
lz)
                                  | Bool
otherwise = forall a. Maybe a
Nothing

addTo :: ComparableStyle ps => VerState ps -> VBox ps s -> Container ps s -> Container ps s
addTo :: forall ps s.
ComparableStyle ps =>
VerState ps -> VBox ps s -> Container ps s -> Container ps s
addTo VerState ps
_ VBox ps s
line (Container PDFFloat
px PDFFloat
py PDFFloat
w PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
t []) = forall ps s.
PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> [VBox ps s]
-> Container ps s
Container PDFFloat
px PDFFloat
py PDFFloat
w PDFFloat
maxh ((forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
line)forall a. Num a => a -> a -> a
+PDFFloat
h) PDFFloat
y PDFFloat
z PDFFloat
t [VBox ps s
line]
addTo VerState ps
settings VBox ps s
line (Container PDFFloat
px PDFFloat
py PDFFloat
w PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
t l :: [VBox ps s]
l@(VBox ps s
a:[VBox ps s]
_)) = 
    case forall ps s.
ComparableStyle ps =>
VerState ps
-> VBox ps s -> VBox ps s -> Maybe (VBox ps s, PDFFloat, PDFFloat)
interlineGlue VerState ps
settings VBox ps s
a VBox ps s
line of
        Maybe (VBox ps s, PDFFloat, PDFFloat)
Nothing ->
          let h' :: PDFFloat
h' = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
line forall a. Num a => a -> a -> a
+ PDFFloat
h 
              y' :: PDFFloat
y' = PDFFloat
y forall a. Num a => a -> a -> a
+ forall a. MaybeGlue a => a -> PDFFloat
glueY VBox ps s
line
              z' :: PDFFloat
z' = PDFFloat
z forall a. Num a => a -> a -> a
+ forall a. MaybeGlue a => a -> PDFFloat
glueZ VBox ps s
line
          in
          forall ps s.
PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> [VBox ps s]
-> Container ps s
Container PDFFloat
px PDFFloat
py PDFFloat
w PDFFloat
maxh PDFFloat
h' PDFFloat
y' PDFFloat
z' PDFFloat
t (VBox ps s
lineforall a. a -> [a] -> [a]
:[VBox ps s]
l)
        Just (VBox ps s
v,PDFFloat
ny,PDFFloat
nz) ->
          let h' :: PDFFloat
h' = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
line forall a. Num a => a -> a -> a
+ PDFFloat
h forall a. Num a => a -> a -> a
+ forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
v
              y' :: PDFFloat
y' = PDFFloat
y forall a. Num a => a -> a -> a
+ PDFFloat
ny forall a. Num a => a -> a -> a
+ forall a. MaybeGlue a => a -> PDFFloat
glueY VBox ps s
line
              z' :: PDFFloat
z' = PDFFloat
z forall a. Num a => a -> a -> a
+ PDFFloat
nz forall a. Num a => a -> a -> a
+ forall a. MaybeGlue a => a -> PDFFloat
glueZ VBox ps s
line
          in
          forall ps s.
PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> [VBox ps s]
-> Container ps s
Container PDFFloat
px PDFFloat
py PDFFloat
w PDFFloat
maxh PDFFloat
h' PDFFloat
y' PDFFloat
z' PDFFloat
t (VBox ps s
lineforall a. a -> [a] -> [a]
:VBox ps s
vforall a. a -> [a] -> [a]
:[VBox ps s]
l)
          
isOverfull :: Container ps s -> Bool
isOverfull :: forall ps s. Container ps s -> Bool
isOverfull (Container PDFFloat
_ PDFFloat
_ PDFFloat
_ PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z PDFFloat
_ [VBox ps s]
_) = let r :: PDFFloat
r = PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat
dilatationRatio PDFFloat
maxh PDFFloat
h PDFFloat
y PDFFloat
z
 in
   if PDFFloat
r forall a. Ord a => a -> a -> Bool
>= PDFFloat
bigAdjustRatio then PDFFloat
h forall a. Ord a => a -> a -> Bool
> PDFFloat
maxh else PDFFloat
r forall a. Ord a => a -> a -> Bool
<= -PDFFloat
1



-- | Paragraph style
class (ComparableStyle a, Style s) => ParagraphStyle a s | a -> s where
    -- | Width of the line of the paragraph
    lineWidth :: a -- ^ The style
               -> PDFFloat -- ^ Width of the text area used by the typesetting algorithm
               -> Int -- ^ Line number
               -> PDFFloat -- ^ Line width
    
    -- | Horizontal shift of the line position relatively to the left egde of the paragraph bounding box
    linePosition :: a -- ^ The style 
                  -> PDFFloat -- ^ Width of the text area used by the typesetting algorithm
                  -> Int -- ^ Line number 
                  -> PDFFloat -- ^ Horizontal offset from the left edge of the text area
    
    -- | How to style the interline glues added in a paragraph by the line breaking algorithm
    interline :: a -- ^ The style 
              -> Maybe (Rectangle -> Draw ()) -- ^ Function used to style interline glues
    interline a
_ = forall a. Maybe a
Nothing
    lineWidth a
_ PDFFloat
w Int
_ = PDFFloat
w
    linePosition a
_ PDFFloat
_ = forall a b. a -> b -> a
const PDFFloat
0.0
    
    -- | Change the content of a paragraph before the line breaking algorithm is run. It may also change the style
    paragraphChange :: a -- ^ The style
               -> Int -- ^ Line offset different from 0 when a paragraph has been broken
               -> [Letter s] -- ^ List of letters in the paragraph
               -> (a,[Letter s]) -- ^ Update style and list of letters
    paragraphChange a
a Int
_ [Letter s]
l = (a
a,[Letter s]
l)
    
    -- | Get the paragraph bounding box and the paragraph draw command to apply additional effects
    paragraphStyle :: a -- ^ The style 
                   -> Maybe (Rectangle -> Draw b -> Draw ()) -- ^ Function used to style a paragraph
    paragraphStyle a
_ = forall a. Maybe a
Nothing


-- | Get the delta used to position a box with non rectangular shapes
getBoxDelta :: VBox ps s -> PDFFloat
getBoxDelta :: forall ps s. VBox ps s -> PDFFloat
getBoxDelta (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_) = PDFFloat
0.0
getBoxDelta (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ Maybe ps
_) = PDFFloat
0.0
getBoxDelta (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
delta Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_) = PDFFloat
delta
getBoxDelta (SomeVBox PDFFloat
delta (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ Maybe ps
_) = PDFFloat
delta




isSameParaStyle :: ComparableStyle ps => ps -> VBox ps s -> Bool
isSameParaStyle :: forall ps s. ComparableStyle ps => ps -> VBox ps s -> Bool
isSameParaStyle ps
s (Paragraph Int
_ [Letter s]
_ (Just ps
s') BRState
_) =  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s'
isSameParaStyle ps
s (VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s')) =  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s'
isSameParaStyle ps
s (VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ (Just ps
s')) =  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s'
isSameParaStyle ps
s (SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s'))  =  ps
s forall a. ComparableStyle a => a -> a -> Bool
`isSameStyleAs`  ps
s'     
isSameParaStyle ps
_ VBox ps s
_ = Bool
False

recurseStrokeVBoxes :: (ParagraphStyle ps s) => Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes :: forall ps s.
ParagraphStyle ps s =>
Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes Int
_ [] PDFFloat
_ PDFFloat
_  = forall (m :: * -> *) a. Monad m => a -> m a
return ()
recurseStrokeVBoxes Int
_ (Paragraph Int
_ [Letter s]
_ Maybe ps
_ BRState
_:[VBox ps s]
_) PDFFloat
_ PDFFloat
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
recurseStrokeVBoxes Int
nb (a :: VBox ps s
a@(VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ Maybe ps
_):[VBox ps s]
l) PDFFloat
xa PDFFloat
y  = do
    let h :: PDFFloat
h = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
a
    forall a. DisplayableBox a => a -> PDFFloat -> PDFFloat -> Draw ()
strokeBox VBox ps s
a PDFFloat
xa PDFFloat
y
    forall ps s.
ParagraphStyle ps s =>
Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes Int
nb [VBox ps s]
l PDFFloat
xa (PDFFloat
yforall a. Num a => a -> a -> a
-PDFFloat
h)

recurseStrokeVBoxes Int
nb (VBox ps s
a:[VBox ps s]
l) PDFFloat
xa PDFFloat
y = do
    let h :: PDFFloat
h = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
a
    forall a. DisplayableBox a => a -> PDFFloat -> PDFFloat -> Draw ()
strokeBox VBox ps s
a PDFFloat
xa PDFFloat
y
    forall ps s.
ParagraphStyle ps s =>
Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes (Int
nbforall a. Num a => a -> a -> a
+Int
1) [VBox ps s]
l PDFFloat
xa (PDFFloat
yforall a. Num a => a -> a -> a
-PDFFloat
h)

drawWithParaStyle :: (ParagraphStyle ps s) => ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()   
drawWithParaStyle :: forall ps s.
ParagraphStyle ps s =>
ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
drawWithParaStyle ps
style [VBox ps s]
b PDFFloat
xa PDFFloat
y' = do
    let  ([VBox ps s]
l',[VBox ps s]
l'') = forall a. (a -> Bool) -> [a] -> ([a], [a])
span (forall ps s. ComparableStyle ps => ps -> VBox ps s -> Bool
isSameParaStyle ps
style) [VBox ps s]
b
         h' :: PDFFloat
h' = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\PDFFloat
x' VBox ps s
ny -> PDFFloat
x' forall a. Num a => a -> a -> a
+ forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
ny) PDFFloat
0.0 [VBox ps s]
l'
    if (forall a. Maybe a -> Bool
isJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s b.
ParagraphStyle a s =>
a -> Maybe (Rectangle -> Draw b -> Draw ())
paragraphStyle forall a b. (a -> b) -> a -> b
$ ps
style)
      then do
          let xleft :: PDFFloat
xleft = (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum forall a b. (a -> b) -> a -> b
$ PDFFloat
100000forall a. a -> [a] -> [a]
:forall a b. (a -> b) -> [a] -> [b]
map forall ps s. VBox ps s -> PDFFloat
getBoxDelta [VBox ps s]
l' ) forall a. Num a => a -> a -> a
+ PDFFloat
xa
              xright :: PDFFloat
xright = (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum forall a b. (a -> b) -> a -> b
$ PDFFloat
0forall a. a -> [a] -> [a]
:(forall a b. (a -> b) -> [a] -> [b]
map (\VBox ps s
x -> forall a. Box a => a -> PDFFloat
boxWidth VBox ps s
x forall a. Num a => a -> a -> a
+ forall ps s. VBox ps s -> PDFFloat
getBoxDelta VBox ps s
x) [VBox ps s]
l')) forall a. Num a => a -> a -> a
+ PDFFloat
xa
          (forall a. HasCallStack => Maybe a -> a
fromJust forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s b.
ParagraphStyle a s =>
a -> Maybe (Rectangle -> Draw b -> Draw ())
paragraphStyle forall a b. (a -> b) -> a -> b
$ ps
style) (Point -> Point -> Rectangle
Rectangle (PDFFloat
xleft forall a. a -> a -> Complex a
:+ (PDFFloat
y'forall a. Num a => a -> a -> a
- PDFFloat
h')) (PDFFloat
xright forall a. a -> a -> Complex a
:+ PDFFloat
y')) (forall ps s.
ParagraphStyle ps s =>
Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes Int
1 [VBox ps s]
l' PDFFloat
xa PDFFloat
y')
      else
         forall ps s.
ParagraphStyle ps s =>
Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
recurseStrokeVBoxes Int
1 [VBox ps s]
l' PDFFloat
xa PDFFloat
y'
    forall ps s.
ParagraphStyle ps s =>
[VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
strokeVBoxes [VBox ps s]
l'' PDFFloat
xa (PDFFloat
y' forall a. Num a => a -> a -> a
- PDFFloat
h')

-- | Stroke the VBoxes
strokeVBoxes :: (ParagraphStyle ps s) => [VBox ps s] -- ^ List of boxes
             -> PDFFloat -- ^ X pos
             -> PDFFloat -- ^ Y pos
             -> Draw ()
strokeVBoxes :: forall ps s.
ParagraphStyle ps s =>
[VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
strokeVBoxes [] PDFFloat
_ PDFFloat
_ = forall (m :: * -> *) a. Monad m => a -> m a
return ()
strokeVBoxes b :: [VBox ps s]
b@((Paragraph Int
_ [Letter s]
_ (Just ps
s') BRState
_):[VBox ps s]
_) PDFFloat
xa PDFFloat
y = forall ps s.
ParagraphStyle ps s =>
ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
drawWithParaStyle ps
s' [VBox ps s]
b PDFFloat
xa PDFFloat
y 
strokeVBoxes b :: [VBox ps s]
b@((VBox PDFFloat
_ PDFFloat
_ PDFFloat
_ [VBox ps s]
_ (Just ps
s')):[VBox ps s]
_) PDFFloat
xa PDFFloat
y = forall ps s.
ParagraphStyle ps s =>
ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
drawWithParaStyle ps
s' [VBox ps s]
b PDFFloat
xa PDFFloat
y 
strokeVBoxes b :: [VBox ps s]
b@((VGlue PDFFloat
_ PDFFloat
_ PDFFloat
_ Maybe (PDFFloat, PDFFloat)
_ (Just ps
s')):[VBox ps s]
_) PDFFloat
xa PDFFloat
y = forall ps s.
ParagraphStyle ps s =>
ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
drawWithParaStyle ps
s' [VBox ps s]
b PDFFloat
xa PDFFloat
y
strokeVBoxes b :: [VBox ps s]
b@((SomeVBox PDFFloat
_ (PDFFloat, PDFFloat, PDFFloat)
_ AnyBox
_ (Just ps
s')):[VBox ps s]
_) PDFFloat
xa PDFFloat
y = forall ps s.
ParagraphStyle ps s =>
ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
drawWithParaStyle ps
s' [VBox ps s]
b PDFFloat
xa PDFFloat
y
strokeVBoxes (VBox ps s
a:[VBox ps s]
l) PDFFloat
xa PDFFloat
y = 
    do
        let h :: PDFFloat
h = forall a. Box a => a -> PDFFloat
boxHeight VBox ps s
a
        forall a. DisplayableBox a => a -> PDFFloat -> PDFFloat -> Draw ()
strokeBox VBox ps s
a PDFFloat
xa PDFFloat
y
        forall ps s.
ParagraphStyle ps s =>
[VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()
strokeVBoxes [VBox ps s]
l PDFFloat
xa (PDFFloat
yforall a. Num a => a -> a -> a
-PDFFloat
h)