packages feed

HPDF 1.1 → 1.2

raw patch · 14 files changed

+1320/−709 lines, 14 filesdep ~encoding

Dependency ranges changed: encoding

Files

Graphics/PDF/Annotation.hs view
@@ -26,6 +26,8 @@ import qualified Data.Map as M import Graphics.PDF.Action import Graphics.PDF.Pages+import Control.Monad.State(gets)+--import Debug.Trace  data TextIcon = Note               | Paragraph@@ -37,11 +39,51 @@               deriving(Eq,Show)                        -data TextAnnotation = TextAnnotation PDFString [PDFFloat] TextIcon-data URLLink = URLLink PDFString [PDFFloat] String Bool-data PDFLink = PDFLink PDFString [PDFFloat] (PDFReference PDFPage) PDFFloat PDFFloat Bool+data TextAnnotation = TextAnnotation +   PDFString -- Content+   [PDFFloat] -- Rect+   TextIcon+data URLLink = URLLink +  PDFString -- Content+  [PDFFloat] -- Rect+  String -- URL+  Bool -- Border+data PDFLink = PDFLink +  PDFString -- Content+  [PDFFloat] -- Rect+  (PDFReference PDFPage) -- Page+  PDFFloat -- x+  PDFFloat -- y+  Bool -- Border --data Screen = Screen (PDFReference Rendition) PDFString [PDFFloat] (PDFReference PDFPage) (Maybe (PDFReference ControlMedia)) (Maybe (PDFReference ControlMedia))  +--det :: Matrix -> PDFFloat+--det (Matrix a b c d _ _) = a*d - b*c+--+--inverse :: Matrix -> Matrix+--inverse m@(Matrix a b c d e f) = (Matrix (d/de) (-b/de) (-c/de) (a/de) 0 0) * (Matrix 1 0 0 1 (-e) (-f))+--	where+--		de = det m+		+applyMatrixToRectangle :: Matrix -> [PDFFloat] -> [PDFFloat]+applyMatrixToRectangle m [xa,ya,xb,yb] = +    let (xa',ya') = m `applyTo` (xa,ya)+        (xa'',yb') = m `applyTo` (xa,yb)+        (xb',ya'') = m `applyTo` (xb,ya)+        (xb'',yb'') = m `applyTo` (xb,yb)+        x1 = minimum [xa',xa'',xb',xb'']+        x2 = maximum [xa',xa'',xb',xb'']+        y1 = minimum [ya',ya'',yb',yb'']+        y2 = maximum [ya',ya'',yb',yb'']+    in+    [x1,y1,x2,y2]+ where+     applyTo (Matrix a b c d e f) (x,y) = (a*x+c*y+e,b*x+d*y+f)+     +applyMatrixToRectangle _ a = a++    + -- | Get the border shqpe depending on the style getBorder :: Bool -> [PDFInteger] getBorder False = [0,0,0]@@ -82,6 +124,9 @@     annotationType _ = PDFName "Text"     annotationContent (TextAnnotation s _ _) = s     annotationRect (TextAnnotation _ r _) = r+    annotationToGlobalCoordinates (TextAnnotation a r b) = do+        gr <- transformAnnotRect r+        return $ TextAnnotation a gr b      instance PdfObject URLLink where     toPDF a@(URLLink _ _ url border) = toPDF . PDFDictionary . M.fromList $ @@ -95,7 +140,10 @@     annotationType _ = PDFName "Link"     annotationContent (URLLink s _ _ _) = s     annotationRect (URLLink _ r _ _) = r-    +    annotationToGlobalCoordinates (URLLink a r b c) = do+        gr <- transformAnnotRect r+        return $ URLLink a gr b c+         instance PdfObject PDFLink where     toPDF a@(PDFLink _ _ page x y border) = toPDF . PDFDictionary . M.fromList $                 standardAnnotationDict a ++ @@ -114,9 +162,19 @@     annotationType _ = PDFName "Link"     annotationContent (PDFLink s _ _ _ _ _) = s     annotationRect (PDFLink _ r _ _ _ _) = r+    annotationToGlobalCoordinates (PDFLink a r b c d e) = do+        gr <- transformAnnotRect r+        return $ PDFLink a gr b c d e+        +transformAnnotRect :: [PDFFloat] -> Draw [PDFFloat]+transformAnnotRect r = do+    l <- gets matrix+    let m = foldr (*) identity l+    return $ m `applyMatrixToRectangle` r      -- | Create a new annotation object newAnnotation :: (PdfObject a, AnnotationObject a) => a -> Draw () newAnnotation annot = do-    modifyStrict $ \s -> s {annots = (AnyAnnotation annot):(annots s)}+    annot' <- annotationToGlobalCoordinates annot+    modifyStrict $ \s -> s {annots = (AnyAnnotation annot'):(annots s)}     return ()
Graphics/PDF/Coordinates.hs view
@@ -33,41 +33,15 @@ data Angle = Degree PDFFloat -- ^ Angle in degrees            | Radian PDFFloat -- ^ Angle in radians --- | A transformation matrix. An affine transformation a b c d e f------ @--- a b e--- c d f--- 0 0 1--- @-       -data Matrix = Matrix !PDFFloat !PDFFloat !PDFFloat !PDFFloat !PDFFloat !PDFFloat deriving (Eq) --- | Identity matrix-identity :: Matrix-identity = Matrix 1.0 0 0 1.0 0 0 -instance Show Matrix where-  show (Matrix ma mb mc md me mf) = "Matrix " ++ (unwords [(show ma),(show mb),(show mc),(show md),(show me),(show mf)]) -instance Num Matrix where-    --  Matrix addition-    (+) (Matrix ma mb mc md me mf ) (Matrix na nb nc nd ne nf) = -         Matrix (ma+na)  (mb+nb)  (mc+nc)  (md+nd)  (me+ne)  (mf+nf)-    (*) (Matrix ma mb mc md me mf) (Matrix na nb nc nd ne nf) = -         Matrix (ma*na+mb*nc)  (ma*nb + mb*nd )  (mc*na+md*nc)  (mc*nb +md*nd)  (me*na+mf*nc+ne)  (me*nb+mf*nd+nf)-    negate (Matrix ma mb mc md me mf )  =-         Matrix (-ma)  (-mb)  (-mc)  (-md)  (-me)  (-mf)-    abs m = m-    signum _ = identity-    fromInteger i = Matrix r 0 0 r  0  0-                   where-                    r = fromInteger i   -- | Apply a transformation matrix to the current coordinate frame applyMatrix :: Matrix -> Draw ()-applyMatrix (Matrix a b c d e f)  = +applyMatrix m@(Matrix a b c d e f)  = do+    multiplyCurrentMatrixWith m     tell . mconcat $[ serialize '\n'                     , toPDF a                     , serialize ' '
Graphics/PDF/Draw.hs view
@@ -63,6 +63,10 @@  , PDFShading(..)  , getRgbColor  , emptyDrawState+ , Matrix(..)+ , identity+ , currentMatrix+ , multiplyCurrentMatrixWith  ) where   import Graphics.PDF.LowLevel.Types@@ -79,6 +83,37 @@ import Graphics.PDF.LowLevel.Serializer import Data.Monoid +-- | A transformation matrix. An affine transformation a b c d e f+--+-- @+-- a b 0+-- c d 0+-- e f 1+-- @+       +data Matrix = Matrix !PDFFloat !PDFFloat !PDFFloat !PDFFloat !PDFFloat !PDFFloat deriving (Eq)+		+-- | Identity matrix+identity :: Matrix+identity = Matrix 1.0 0 0 1.0 0 0++instance Show Matrix where+  show (Matrix ma mb mc md me mf) = "Matrix " ++ (unwords [(show ma),(show mb),(show mc),(show md),(show me),(show mf)])++instance Num Matrix where+    --  Matrix addition+    (+) (Matrix ma mb mc md me mf ) (Matrix na nb nc nd ne nf) = +         Matrix (ma+na)  (mb+nb)  (mc+nc)  (md+nd)  (me+ne)  (mf+nf)+    (*) (Matrix ma mb mc md me mf) (Matrix na nb nc nd ne nf) = +         Matrix (ma*na+mb*nc)  (ma*nb+mb*nd)  (mc*na+md*nc)  (mc*nb +md*nd)  (me*na+mf*nc+ne)  (me*nb+mf*nd+nf)+    negate (Matrix ma mb mc md me mf )  =+         Matrix (-ma)  (-mb)  (-mc)  (-md)  (-me)  (-mf)+    abs m = m+    signum _ = identity+    fromInteger i = Matrix r 0 0 r  0  0+                   where+                    r = fromInteger i+ data AnnotationStyle = AnnotationStyle !(Maybe Color)  class AnnotationObject a where@@ -86,6 +121,8 @@     annotationType :: a -> PDFName     annotationContent :: a -> PDFString     annotationRect :: a -> [PDFFloat]+    annotationToGlobalCoordinates :: a -> Draw a+    annotationToGlobalCoordinates = return      data AnyAnnotation = forall a.(PdfObject a,AnnotationObject a) => AnyAnnotation a @@ -118,6 +155,7 @@                 ,  patterns :: M.Map (PDFReference AnyPdfPattern) String                 ,  colorSpaces :: M.Map PDFColorSpace String                 ,  shadings :: M.Map PDFShading String+                ,  matrix :: [Matrix]                 } data DrawEnvironment = DrawEnvironment {                         streamId :: Int@@ -178,19 +216,36 @@ emptyDrawState :: Int -> DrawState emptyDrawState ref =      let names = (map (("O" ++ (show ref)) ++ ) $ [replicate k ['a'..'z'] | k <- [1..]] >>= sequence) in-    DrawState names emptyRsrc M.empty M.empty M.empty M.empty emptyDictionary []  M.empty M.empty M.empty+    DrawState names emptyRsrc M.empty M.empty M.empty M.empty emptyDictionary []  M.empty M.empty M.empty [identity]    -- | Execute the drawing commands to get a new state and an uncompressed PDF stream runDrawing :: Draw a -> DrawEnvironment -> DrawState -> (a,DrawState,BU.Builder) runDrawing drawing environment state = (runRWS . unDraw $ drawing) environment state       +pushMatrixStack :: Matrix -> Draw ()+pushMatrixStack m = do+    modifyStrict $ \s -> s {matrix = m : matrix s}+    +popMatrixStack :: Draw ()+popMatrixStack = do+    modifyStrict $ \s -> s {matrix = tail (matrix s)}+    ++multiplyCurrentMatrixWith :: Matrix -> Draw ()+multiplyCurrentMatrixWith m' = modifyStrict $ \s -> s {matrix = let (m:l) = matrix s in (m' * m ):l}++    +currentMatrix :: Draw Matrix+currentMatrix = gets matrix >>= return . head        -- | Draw in a new drawing context without perturbing the previous context -- that is restored after the draw        withNewContext :: Draw a -> Draw a withNewContext m = do     tell . serialize $ "\nq"+    pushMatrixStack identity     a <- m+    popMatrixStack     tell . serialize $ "\nQ"     return a     
Graphics/PDF/Image.hs view
@@ -18,6 +18,7 @@    -- ** Functions    , createPDFJpeg    , readJpegFile+   , jpegBounds  ) where       import Graphics.PDF.LowLevel.Types@@ -34,6 +35,7 @@ import Control.Monad.Error   import Graphics.PDF.Coordinates import Data.Binary.Builder(Builder,fromLazyByteString)+import Control.Exception as E  m_sof0 :: Int m_sof0 = 0xc0 @@ -240,21 +242,28 @@      --test = analyzePng "Test/logo.png"     -    +withFile :: String -> (Handle -> IO c) -> IO c    +withFile name = bracket (openBinaryFile name ReadMode) hClose+ -- | Read a JPEG file and return an abstract description of its content or an error+-- The read is not lazy. The whole image will be loaded into memory readJpegFile :: FilePath              -> IO (Either String JpegFile)-readJpegFile f = do-     h <- liftIO $ openBinaryFile f ReadMode-     r <- runFA (analyzeJpeg h)-     liftIO $ hClose h+readJpegFile f = catchJust ioErrors (do+     r <- liftIO $ withFile f $ \h -> do+             runFA (analyzeJpeg h)      case r of          Right (bits_per_component,height,width,color_space) -> do-                 img <- liftIO $ B.readFile f-                 return (Right $ JpegFile bits_per_component width height color_space (fromLazyByteString img)) -         Left s -> return $ Left s +                 img <- liftIO $ withFile f $ \h' -> do+                     nb <- hFileSize h'+                     B.hGet h' (fromIntegral nb)+                 return (Right $ JpegFile bits_per_component width height color_space (fromLazyByteString img))+         Left s -> return $ Left s) (\err -> return $ Left (show err))  -  +-- | Get the JPEG bounds+jpegBounds :: JpegFile -> (PDFFloat,PDFFloat)+jpegBounds (JpegFile _ w h _ _) = (w,h)+ -- | Use an abstract description of a Jpeg to return a PDFReference that can be used to manipulate the Jpeg in the context -- of the PDF document createPDFJpeg :: JpegFile  
Graphics/PDF/Shading.hs view
@@ -14,6 +14,7 @@   -- ** Type     PDFShading(..)   , paintWithShading+  , applyShading  ) where       import Graphics.PDF.Draw@@ -24,7 +25,7 @@ import Graphics.PDF.LowLevel.Serializer import Data.Monoid --- | Set alpha value for transparency+-- | Fill clipping region with a shading applyShading :: PDFShading -> Draw () applyShading shade = do     shadingMap <- gets shadings
Graphics/PDF/Typesetting.hs view
@@ -11,33 +11,56 @@ ---------------------------------------------------------  module Graphics.PDF.Typesetting(-  -- * Typesetting-  -- ** Types+  -- * Types+  -- ** Boxes     Box(..)   , DisplayableBox(..)+  , Letter(..)+  , BoxDimension+  -- ** Styles   , Style(..)   , TextStyle(..)   , StyleFunction(..)-  , AnyStyle   , ParagraphStyle(..)-  , AnyParagraphStyle   , MonadStyle(..)-  , Letter(..)-  , BoxDimension+  , ComparableStyle(..)+  -- ** Typesetting monads+  , Para+  , TM+  -- ** Containers+  , VBox+  , VerState(..)+  , Container+  , Justification(..)   -- * Functions   -- ** Text display   , displayFormattedText   -- ** Text construction operators-  , endParagraph+  , forceNewLine   , txt   , paragraph-  -- * Paragraph construction operators+  -- ** Paragraph construction operators   , kern   , addPenalty---  , nullChar   , mkLetter-  -- * Misc   , mkDrawBox+  -- ** Functions useful to change the paragraph style+  , getParaStyle+  , setParaStyle+  -- ** Container+  , mkContainer+  , fillContainer+  , defaultVerState+  , getBoxes+  , containerX+  , containerY+  , containerWidth+  , containerHeight+  , containerContentHeight+  , containerContentRightBorder+  , containerContentLeftBorder+  , containerCurrentHeight+  , containerContentRectangle   -- * Settings (similar to TeX ones)   -- ** Line breaking settings   , setFirstPassTolerance @@ -52,6 +75,7 @@   , getFitnessDemerit   , getHyphenDemerit   , getLinePenalty+  , setJustification   -- ** Vertical mode settings   , setBaseLineSkip   , setLineSkipLimit@@ -59,11 +83,7 @@   , getBaseLineSkip   , getLineSkipLimit   , getLineSkip-  -- * Styles-  -- ** Functions useful to change the paragraph style-  , getParaStyle-  , setParaStyle-  , getTextArea+  , module Graphics.PDF.Typesetting.StandardStyle   ) where    import Graphics.PDF.LowLevel.Types@@ -73,87 +93,81 @@ import Control.Monad.RWS import Graphics.PDF.Typesetting.Breaking import Graphics.PDF.Typesetting.Vertical+import Graphics.PDF.Typesetting.Layout import Graphics.PDF.Typesetting.Box+import Graphics.PDF.Typesetting.StandardStyle  -- | Display a formatted text in a given bounding rectangle with a given default paragraph style, a given default text style. No clipping -- is taking place. Drawing stop when the last line is crossing the bounding rectangle in vertical direction-displayFormattedText :: (Style s, ParagraphStyle s') => Rectangle -- ^ Text area-                     -> s' -- ^ default vertical style+displayFormattedText :: (ParagraphStyle ps s) => Rectangle -- ^ Text area+                     -> ps -- ^ default vertical style                      -> s -- ^ Default horizontal style-                     -> TM a -- ^ Typesetting monad+                     -> TM ps s a -- ^ Typesetting monad                      -> Draw a -- ^ Draw monad-displayFormattedText area@(Rectangle xa y' _ y'') defaultVStyle defaultHStyle t  = +displayFormattedText (Rectangle xa ya xb yb) defaultVStyle defaultHStyle t  =      do     --withNewContext $ do     --    addShape $ Rectangle (xa-1) y' (xb+1) y''     --    closePath     --    setAsClipPath-        let (a, s', boxes) = (runRWS . unTM $ t >>= \x' -> do {return x'} ) area (defaultTmState defaultVStyle defaultHStyle)-        strokeVBoxes (verticalPostProcess (pageSettings s') 0 area boxes) (xa,y',y'')+        let (a, s', boxes) = (runRWS . unTM $ t >>= \x' -> do {return x'} ) () (defaultTmState defaultVStyle defaultHStyle)+            c = mkContainer xa yb (xb-xa) (yb-ya)+            (d,_,_) = fillContainer (pageSettings s') c boxes+        d         return a  ---endParagraphBoxes :: [Letter]  ---endParagraphBoxes = [glueBox Nothing 0 10000.0 0,penalty (-infinity)]+-- | Return the list of Vboxes for a text+getBoxes :: (ParagraphStyle ps s) => ps -- ^ default vertical style+         -> s -- ^ Default horizontal style+         -> TM ps s a -- ^ Typesetting monad+         -> [VBox ps s] -- ^ List of boxes+getBoxes defaultVStyle defaultHStyle t  =+    let (_, _ , boxes) = (runRWS . unTM $ t >>= \x' -> do {return x'} ) () (defaultTmState defaultVStyle defaultHStyle)+    in boxes  -- | Add a penalty-addPenalty :: Int -> Para()+addPenalty :: Int -> Para s () addPenalty f = tell $ [penalty f]-  --- | End the current paragraph with or without using the same style-endParagraph :: Bool -- ^ True if we use the same style to end a paragraph. false for an invisible style-             -> Para ()-endParagraph r = do-    if r-        then-            glue 0 10000.0 0-        else-            tell $ [glueBox Nothing 0 10000.0 0]-    addPenalty (-infinity)     --- | Get the bounding rectangle containing the text-getTextArea :: TM Rectangle-getTextArea = ask--defaultTmState :: (Style s, ParagraphStyle s') => s' -> s -> TMState-defaultTmState s' s = TMState { tmStyle = AnyStyle s+defaultTmState :: (ParagraphStyle ps s) => ps -> s -> TMState ps s+defaultTmState s' s = TMState { tmStyle = s                               , paraSettings = defaultBreakingSettings                               , pageSettings = defaultVerState s'                               }     -data TMState = TMState { tmStyle :: !AnyStyle-                       , paraSettings :: !BRState-                       , pageSettings :: !VerState-                       }+data TMState ps s = TMState { tmStyle :: !s+                            , paraSettings :: !BRState+                            , pageSettings :: !(VerState ps)+                            }                        -newtype TM a = TM { unTM :: RWS Rectangle [VBox] TMState a} +newtype TM ps s a = TM { unTM :: RWS () [VBox ps s] (TMState ps s) a}  #ifndef __HADDOCK__-  deriving(Monad,MonadWriter [VBox], MonadState TMState, MonadReader Rectangle, Functor)+  deriving(Monad,MonadWriter [VBox ps s], MonadState (TMState ps s), Functor) #else instance Monad TM-instance MonadWriter [VBox] TM-instance MonadState TMState TM+instance MonadWriter [VBox ps s] TM+instance MonadState (TMState ps s) TM instance Functor TM-instance MonadReader Rectangle TM #endif -newtype Para a = Para { unPara :: RWS BRState [Letter] AnyStyle a} +newtype Para s a = Para { unPara :: RWS BRState [Letter s] s a}  #ifndef __HADDOCK__-  deriving(Monad,MonadWriter [Letter], MonadReader BRState, MonadState AnyStyle, Functor)+  deriving(Monad,MonadWriter [Letter s], MonadReader BRState, MonadState s, Functor) #else instance Monad Para-instance MonadWriter [Letter] Para-instance MonadState AnyStyle Para+instance MonadWriter [Letter s] Para+instance MonadState s Para instance Functor Para instance MonadReader BRState Para #endif  -- | A MonadStyle where some typesetting operators can be used-class Monad m => MonadStyle m where+class (Style s, Monad m) => MonadStyle s m | m -> s where     -- | Set the current text style-    setStyle :: Style a => a -> m ()+    setStyle :: s -> m ()          -- | Get the current text style-    currentStyle :: m AnyStyle+    currentStyle :: m s          -- | Add a box using the current mode (horizontal or vertical. The current style is always applied to the added box)     addBox :: (Show a, DisplayableBox a, Box a) => a @@ -175,9 +189,9 @@                  -> m ()          -instance MonadStyle TM where+instance Style s => MonadStyle s (TM ps s) where     --  Set style of text-    setStyle f = modifyStrict $ \s -> s {tmStyle = AnyStyle f}+    setStyle f = modifyStrict $ \s -> s {tmStyle = f}      --  Get current text style     currentStyle = gets tmStyle@@ -190,17 +204,15 @@     --  Add a glue     glue h y z = do         style <- getParaStyle-        Rectangle xa _ xb _ <- getTextArea-        tell $ [vglue (Just style) h y z (xb-xa) 0]+        tell $ [vglue (Just style) h y z 0 0]              --  Add a glue     unstyledGlue h y z = do-        Rectangle xa _ xb _ <- getTextArea-        tell $ [vglue Nothing h y z (xb-xa) 0]+        tell $ [vglue Nothing h y z 0 0]     -instance MonadStyle Para where+instance Style s => MonadStyle s (Para s) where     --  Set style of text-    setStyle f = put $! AnyStyle f+    setStyle f = put $! f      --  Get current text style     currentStyle = get@@ -218,37 +230,83 @@     --  Add a glue     unstyledGlue w y z = do         tell $ [glueBox Nothing w y z]+        +-- | For a newline and end the current paragraph+forceNewLine :: Style s => Para s ()+forceNewLine = do+    endPara+    startPara     +-- | End the current paragraph with or without using the same style+endFullyJustified :: Style s => Bool -- ^ True if we use the same style to end a paragraph. false for an invisible style+             -> Para s ()+endFullyJustified r = do+    if r+        then+            glue 0 10000.0 0+        else+            tell $ [glueBox Nothing 0 10000.0 0]+    addPenalty (-infinity)+     +endPara :: Style s => Para s ()+endPara = do+    style <- ask+    theStyle <- currentStyle+    let w = spaceWidth theStyle+    case centered style of+      Centered -> do+        addLetter (glueBox (Just theStyle) 0 (centeredDilatationFactor*w) 0)+        addLetter (penalty (-infinity))+      RightJustification -> addPenalty (-infinity) +      _ -> endFullyJustified False+      +startPara :: Style s => Para s ()+startPara = do+    style <- ask+    theStyle <- currentStyle+    let w = spaceWidth theStyle+    case (centered style) of+      Centered -> do+        addLetter (kernBox (theStyle) 0)+        addLetter $ penalty infinity+        addLetter (glueBox (Just theStyle) 0 (centeredDilatationFactor*w) 0)+      RightJustification -> do+        addLetter (kernBox (theStyle) 0)+        addLetter $ penalty infinity+        addLetter (glueBox (Just theStyle) 0 (rightDilatationFactor*w) 0)+      _ -> return ()+       -- | Run a paragraph. Style changes are local to the paragraph-runPara :: Para a -> TM a+runPara :: Style s => Para s a -> TM ps s a runPara m = do     TMState f settings pagesettings <- get-    let (a, s', boxes) = (runRWS . unPara $ closedPara ) settings f+    let (a, s', boxes) = (runRWS . unPara $ closedPara) settings f     put $! TMState s' settings pagesettings     style <- getParaStyle-    tell $ [Paragraph boxes (Just style) settings]+    tell $ [Paragraph 0 boxes (Just style) settings]     return a  where     closedPara = do+        startPara         x <- m-        endParagraph False+        endPara         return x      -- | Get the current paragraph style-getParaStyle :: TM AnyParagraphStyle-getParaStyle = gets pageSettings >>= TM . return . paraStyle+getParaStyle :: TM ps s ps+getParaStyle = gets pageSettings >>= TM . return . currentParagraphStyle  -- | Change the current paragraph style-setParaStyle :: ParagraphStyle s => s -> TM ()+setParaStyle :: ParagraphStyle ps s => ps -> TM ps s () setParaStyle style = do-    modifyStrict $ \s -> s {pageSettings = (pageSettings s){paraStyle = AnyParagraphStyle style}}+    modifyStrict $ \s -> s {pageSettings = (pageSettings s){currentParagraphStyle = style}}  -- | Add a letter to the paragraph-addLetter :: Letter -> Para ()+addLetter :: Letter s -> Para s () addLetter l = Para . tell $ [l]  -- | Add a new paragraph to the text-paragraph :: Para a -> TM a+paragraph :: Style s => Para s a -> TM ps s a paragraph = runPara  -- | Add a null char@@ -256,71 +314,74 @@ --nullChar = Para . tell $ [nullLetter]      -- | Add a text line-txt :: String -> Para ()+txt :: Style s => String -> Para s () txt t = do     f <- currentStyle     settings <- ask     tell $ splitText settings f (toPDFString t)  -- | add a kern (space that can be dilated or compressed and on which no line breaking can occur)-kern :: PDFFloat -> Para()+kern :: Style s => PDFFloat -> Para s () kern w  = do     f <- currentStyle     tell $ [kernBox f w] -setBaseLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ()+setBaseLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ps s () setBaseLineSkip w y z = modifyStrict $ \s -> s {pageSettings = (pageSettings s){baselineskip = (w,y,z)}}  -getBaseLineSkip :: TM (PDFFloat,PDFFloat,PDFFloat)+getBaseLineSkip :: TM ps s (PDFFloat,PDFFloat,PDFFloat) getBaseLineSkip = do     s <- gets pageSettings     return (baselineskip s)     -setLineSkipLimit :: PDFFloat  -> TM ()+setLineSkipLimit :: PDFFloat  -> TM ps s () setLineSkipLimit l = modifyStrict $ \s -> s {pageSettings = (pageSettings s){lineskiplimit=l}} -getLineSkipLimit :: TM PDFFloat+getLineSkipLimit :: TM ps s PDFFloat getLineSkipLimit = gets pageSettings >>= return . lineskiplimit -setLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ()+setLineSkip :: PDFFloat -> PDFFloat -> PDFFloat -> TM ps s () setLineSkip w y z = modifyStrict $ \s -> s {pageSettings = (pageSettings s){lineskip = (w,y,z)}} -getLineSkip :: TM (PDFFloat,PDFFloat,PDFFloat)+getLineSkip :: TM ps s (PDFFloat,PDFFloat,PDFFloat) getLineSkip = gets pageSettings >>= return . lineskip     -setFirstPassTolerance :: PDFFloat -> TM ()+setFirstPassTolerance :: PDFFloat -> TM ps s () setFirstPassTolerance x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){firstPassTolerance = x}} -getFirstPassTolerance :: TM PDFFloat+getFirstPassTolerance :: TM ps s PDFFloat getFirstPassTolerance = gets paraSettings >>= return . firstPassTolerance -setSecondPassTolerance :: PDFFloat -> TM ()+setSecondPassTolerance :: PDFFloat -> TM ps s () setSecondPassTolerance x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){secondPassTolerance = x}} -getSecondPassTolerance :: TM PDFFloat+getSecondPassTolerance :: TM ps s PDFFloat getSecondPassTolerance = gets paraSettings >>= return . secondPassTolerance -setHyphenPenaltyValue :: Int -> TM ()+setHyphenPenaltyValue :: Int -> TM ps s () setHyphenPenaltyValue x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){hyphenPenaltyValue = x}} -getHyphenPenaltyValue :: TM Int+getHyphenPenaltyValue :: TM ps s Int getHyphenPenaltyValue = gets paraSettings >>= return . hyphenPenaltyValue -setFitnessDemerit :: PDFFloat -> TM ()+setFitnessDemerit :: PDFFloat -> TM ps s () setFitnessDemerit x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){fitness_demerit = x}} -getFitnessDemerit :: TM PDFFloat+getFitnessDemerit :: TM ps s PDFFloat getFitnessDemerit = gets paraSettings >>= return . fitness_demerit -setHyphenDemerit :: PDFFloat -> TM ()+setHyphenDemerit :: PDFFloat -> TM ps s () setHyphenDemerit x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){flagged_demerit = x}} -getHyphenDemerit :: TM PDFFloat+getHyphenDemerit :: TM ps s PDFFloat getHyphenDemerit = gets paraSettings >>= return . flagged_demerit   -setLinePenalty :: PDFFloat -> TM ()+setLinePenalty :: PDFFloat -> TM ps s () setLinePenalty x = modifyStrict $ \s -> s {paraSettings = (paraSettings s){line_penalty = x}}                    -getLinePenalty :: TM PDFFloat+getLinePenalty :: TM ps s PDFFloat getLinePenalty = gets paraSettings >>= return . line_penalty +setJustification :: Justification -- ^ Centered, left or fully justified+                 -> TM ps s ()+setJustification j = modifyStrict $ \s -> s {paraSettings = (paraSettings s){centered = j}}
Graphics/PDF/Typesetting/Box.hs view
@@ -14,15 +14,13 @@     Box(..)   , DisplayableBox(..)   , AnyBox(..)-  , NullChar(..)-  , Overfull(..)   , Style(..)   , TextStyle(..)   , StyleFunction(..)-  , AnyStyle(..)   , BoxDimension   , DrawBox-   ,mkDrawBox+  , ComparableStyle(..)+  , mkDrawBox  ) where       import Graphics.PDF.LowLevel.Types@@ -71,10 +69,14 @@ -- when word styling is enabled               data StyleFunction = DrawWord -- ^ Must style a word                    | DrawGlue -- ^ Must style a glue-                   deriving(Eq)                          +                   deriving(Eq)  +                   +-- | Used to compare two style without taking into account the style state+class ComparableStyle a where   +    isSameStyleAs :: a -> a -> Bool                                        --- | Style of text  (sentences and words)       -class Style a where+-- | Style of text  (sentences and words). Minimum definition textStyle      +class ComparableStyle a => Style a where     -- ^ Modify the look of a sentence (sequence of words using the same style on a line)     sentenceStyle :: a -- ^ The style                   -> Maybe (Rectangle -> Draw b -> Draw ()) -- ^ Function receiving the bounding rectangle and the command for drawing the sentence@@ -84,34 +86,26 @@               -> Maybe (Rectangle -> StyleFunction -> Draw b -> Draw ()) -- ^ Word styling function     wordStyle _ = Nothing     textStyle :: a -> TextStyle-    -- | All styles used in a document must have different style codes-    styleCode :: a -> Int     -- | A style may contain data changed from word to word     updateStyle :: a -> a     updateStyle = id          -- | A style may change the height of words+    -- +    -- > Default implementation+    -- > styleHeight = getHeight . textFont . textStyle+    --      styleHeight :: a -> PDFFloat          -- | A style may change the descent of lines+    --+    -- > Default implementation+    -- > styleDescent = getDescent . textFont . textStyle+    --     styleDescent :: a -> PDFFloat     styleHeight = getHeight . textFont . textStyle      styleDescent = getDescent . textFont . textStyle -    --- | Any sentence style-data AnyStyle = forall a. (Style a) => AnyStyle a -instance Style AnyStyle where-    sentenceStyle (AnyStyle a) = sentenceStyle a-    wordStyle (AnyStyle a) = wordStyle a-    textStyle (AnyStyle a) = textStyle a-    styleCode (AnyStyle a) = styleCode a-    updateStyle (AnyStyle a) = AnyStyle $ updateStyle a-    styleHeight (AnyStyle a) = styleHeight a-    styleDescent (AnyStyle a) = styleDescent a--- -- | A box is an object with dimensions and used in the typesetting process class Box a where      -- | Box width@@ -138,26 +132,6 @@                -> PDFFloat -- ^ Horizontal position                -> PDFFloat -- ^ Vertical position (top of the box and NOT baseline)                -> Draw ()--data NullChar = NullChar deriving(Show)-data Overfull = Overfull AnyStyle--instance Box NullChar where-    boxWidth _  = 0-    boxHeight _ = 0-    boxDescent _ = 0-    -instance DisplayableBox NullChar where-    strokeBox _ _ _ = return ()-    -instance Box Overfull where-    boxWidth _  = 0-    boxHeight (Overfull s) = getHeight (textFont . textStyle $ s)-    boxDescent (Overfull s) = getDescent (textFont . textStyle $ s)-    -instance DisplayableBox Overfull where-    strokeBox a x y  = do-        stroke $ Line (x+2) (y - boxDescent a) (x+2) (y - boxDescent a + boxHeight a)      instance Box AnyBox where     boxWidth (AnyBox a)  = boxWidth a
Graphics/PDF/Typesetting/Breaking.hs view
@@ -20,14 +20,21 @@  , glueBox  , penalty  , spaceGlueBox- , nullLetter  , hyphenPenalty  , splitText  , MaybeGlue(..)  , defaultBreakingSettings  , BRState(..)- , glueWidth+ , glueSize  , mkLetter+ , spaceWidth+ , centeredDilatationFactor+ , leftDilatationFactor+ , rightDilatationFactor+ , dilatationRatio+ , badness+ , bigAdjustRatio+ , Justification(..)  ) where       import Graphics.PDF.LowLevel.Types@@ -37,52 +44,63 @@ import Graphics.PDF.Typesetting.Box import Data.Maybe(fromJust) --- | Create a null box-nullLetter :: Letter-nullLetter = mkLetter (0,0,0) Nothing NullChar+--import Debug.Trace +data Justification = FullJustification+                   | Centered+                   | LeftJustification+                   | RightJustification+                   deriving(Eq)+ -- | Make a letter from any box mkLetter :: (Show a, Box a, DisplayableBox a) => BoxDimension -- ^ Dimension of the box-         -> Maybe AnyStyle -- ^ Text style of the box (can use t)+         -> Maybe s -- ^ Text style of the box (can use t)          -> a  -- ^ Box-         -> Letter+         -> Letter s mkLetter d s a = Letter d (AnyBox a) s  -- | A letter which can be anything. Sizes are widths and for glue the dilation and compression factors -- For the generic letter, height and descent are also provided-data Letter  = Letter BoxDimension !AnyBox !(Maybe AnyStyle) -- ^ Any box as a letter-             | Glue !PDFFloat !PDFFloat !PDFFloat !(Maybe AnyStyle) -- ^ A glue with style to know if it is part of the same sentence-             | FlaggedPenalty !PDFFloat !Int !AnyStyle -- ^ Hyphen point-             | Penalty !Int -- ^ Penalty-             | AChar !AnyStyle !Char !PDFFloat -- ^ A char-             | Kern !PDFFloat !(Maybe AnyStyle) -- ^ A kern : non dilatable and non breakable glue+data Letter s = Letter BoxDimension !AnyBox !(Maybe s) -- ^ Any box as a letter+              | Glue !PDFFloat !PDFFloat !PDFFloat !(Maybe s) -- ^ A glue with style to know if it is part of the same sentence+              | FlaggedPenalty !PDFFloat !Int !s -- ^ Hyphen point+              | Penalty !Int -- ^ Penalty+              | AChar !s !Char !PDFFloat -- ^ A char+              | Kern !PDFFloat !(Maybe s) -- ^ A kern : non dilatable and non breakable glue               class MaybeGlue a where-    boxWidthWithRatio :: a -> PDFFloat -> PDFFloat+    glueY :: a -> PDFFloat+    glueZ :: a -> PDFFloat+    glueSizeWithRatio :: a -> PDFFloat -> PDFFloat     -instance MaybeGlue Letter where-    boxWidthWithRatio = letterWidth+instance MaybeGlue (Letter s) where+    glueSizeWithRatio = letterWidth+    glueY (Glue _ y _ _) = y+    glueY _ = 0+    glueZ (Glue _ _ z _) = z+    glueZ _ = 0+                 -- | Compute glue width with dilation-glueWidth :: PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat-glueWidth w y z r =   +glueSize :: PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat -> PDFFloat+glueSize w y z r =              if r >= 0                then                   r*y + w               else                   r*z + w                   -letterWidth :: Letter -- ^ letter+letterWidth :: Letter s -- ^ letter             -> PDFFloat -- ^ Adjustement ratio             -> PDFFloat -- ^ Width letterWidth (AChar _ _ w) _ = w letterWidth (Letter dim _ _) _ = boxWidth dim-letterWidth (Glue w yi zi _) r =  glueWidth w yi zi r+letterWidth (Glue w yi zi _) r =  glueSize w yi zi r letterWidth (FlaggedPenalty _ _ _) _ = 0 letterWidth (Penalty _) _ = 0 letterWidth (Kern w _) _ = w              -instance Show Letter where+instance Show (Letter s) where    show (Letter _ a _) = "(Letter " ++ show a ++ ")"    show (Glue a b c _) = "(Glue " ++ show a ++ " " ++ show b ++ " " ++ show c ++ ")"    show (FlaggedPenalty a b _) = "(FlaggedPenalty " ++ show a ++ " " ++ show b ++  ")"@@ -93,18 +111,18 @@ type CB a = (PDFFloat,PDFFloat,PDFFloat,Int,a)  -class PointedBox a where+class PointedBox s a | a -> s where     isFlagged :: a -> Bool     getPenalty :: a -> Int     isPenalty :: a -> Bool-    letter :: a -> Letter+    letter :: a -> Letter s     position :: a -> Int     cumulatedW :: a -> PDFFloat     cumulatedY :: a -> PDFFloat     cumulatedZ :: a -> PDFFloat     isForcedBreak :: a -> Bool     -instance PointedBox (PDFFloat,PDFFloat,PDFFloat,Int,Letter)  where+instance PointedBox s (PDFFloat,PDFFloat,PDFFloat,Int,Letter s)  where     isFlagged (_,_,_,_,FlaggedPenalty _ _ _) = True         isFlagged _ = False     isPenalty (_,_,_,_,FlaggedPenalty _ _ _) = True    @@ -123,7 +141,7 @@     isForcedBreak _ = False          -instance PointedBox ZList where+instance PointedBox s (ZList s) where     isPenalty (ZList _ b _) = isPenalty b     isFlagged (ZList _ b _) = isFlagged b     letter (ZList _ b _) = letter b@@ -135,7 +153,7 @@     isForcedBreak (ZList _ b _) = isForcedBreak b      -- A penalty has no width unless you break on it so it needs a special processing-penaltyWidth :: Letter  -> PDFFloat+penaltyWidth :: Letter s -> PDFFloat penaltyWidth (FlaggedPenalty w _ _) = w penaltyWidth _ = 0 @@ -151,8 +169,24 @@                             }                             deriving(Show)                             +                            +dilatationRatio :: PDFFloat -- ^ Maxw+                -> PDFFloat -- ^ Current w+                -> PDFFloat -- ^ y+                -> PDFFloat -- ^ z+                -> PDFFloat -- ^ Dilatation ratio+dilatationRatio maxw w y z =                 +                if w == maxw +                    then 0.0+                    else if w < maxw+                      then+                          if y > 0.0 then  ((maxw - w) / y) else bigAdjustRatio+                      else+                          if z > 0.0 then  ((maxw - w) / z) else bigAdjustRatio+               +                             adjustRatio :: BreakNode-            -> ZList+            -> ZList s             -> PDFFloat             -> PDFFloat adjustRatio a l maxw = @@ -160,13 +194,7 @@         y = cumulatedY l - totalDilatation a         z = cumulatedZ l - totalCompression a     in-  if w == maxw -    then 0.0-    else if w < maxw-      then-          if y > 0.0 then  ((maxw - w) / y) else bigAdjustRatio-      else-          if z > 0.0 then  ((maxw - w) / z) else bigAdjustRatio+    dilatationRatio maxw w y z  badness :: PDFFloat -> PDFFloat badness r = if r < (-1) then bigAdjustRatio else 100.0 * abs(r)**3.0@@ -193,10 +221,11 @@                        , fitness_demerit :: !PDFFloat -- ^ Default value 10000                        , flagged_demerit :: !PDFFloat -- ^ Default value 10000                        , line_penalty :: !PDFFloat -- ^ Default value 10+                       , centered :: !Justification -- ^ Default value false                        }                         defaultBreakingSettings :: BRState-defaultBreakingSettings = BRState 100 200 50 10000 10000 10+defaultBreakingSettings = BRState 100 200 50 10000 10000 10 FullJustification                     @@ -204,7 +233,7 @@                -> Bool                -> PDFFloat -- ^ adjust ratio                -> BreakNode -- ^ Flag for previous-               -> ZList -- ^ Flag for current+               -> ZList s -- ^ Flag for current                -> Maybe(PDFFloat,Int) -- ^ Demerit for the breakpoint computeDemerit settings sndPass r a z =     let b = badness r@@ -233,39 +262,52 @@                | OneCB !(CB a)                deriving(Show) -data ZList = ZList (MaybeCB Letter) (PDFFloat,PDFFloat,PDFFloat,Int,Letter) [Letter] deriving(Show)+data ZList s = ZList (MaybeCB (Letter s)) (PDFFloat,PDFFloat,PDFFloat,Int,Letter s) [Letter s] deriving(Show) +--currentLetter :: ZList s -> [Letter s]+--currentLetter (ZList (OneCB (_,_,_,_,s)) (_,_,_,_,a) _) = [s,a]+--currentLetter (ZList _ (_,_,_,_,a) _) = [a] -createZList :: [Letter] -> ZList+createZList :: [Letter s] -> ZList s createZList [] = error "List cannot be empty to create a zipper" createZList l = ZList NoCB (0,0,0,1,head l) (tail l) -theEnd :: ZList -> Bool+theEnd :: ZList s -> Bool theEnd (ZList _ _ []) = True theEnd _ = False  -- | We create a new breakpoint but we get the cumulated dimensions only at the next box following the break -- since glues and penalties are removed at the beginning of a line-createBreaknode :: Maybe (Int,Int,Int,BreakNode) -> ZList -> BreakNode-createBreaknode prev (ZList _ (w,y,z,_,FlaggedPenalty _ _ _) []) = BreakNode (w) (y) (z) 0.0 True 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,Penalty _) []) = BreakNode w (y) (z) 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,Glue w' y' z' _) []) = BreakNode (w + w') (y+y') (z+z') 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,a) []) = BreakNode (w + boxWidthWithRatio a 0.0) (y) (z) 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,FlaggedPenalty _ p _) _) | p <= infinity = BreakNode w y z 0.0 True 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,Penalty p) _) | p <= infinity = BreakNode w y z 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,Letter _ _ _) _) = BreakNode w y z 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,AChar _ _ _) _) = BreakNode w y z 0.0 False 0 0.0 prev -createBreaknode prev (ZList _ (w,y,z,_,Kern _ _) _) = BreakNode w y z 0.0 False 0 0.0 prev +createBreaknode :: Maybe (Int,Int,Int,BreakNode) -> ZList s -> BreakNode+createBreaknode prev a@(ZList _ (_,_,_,_,FlaggedPenalty _ _ _) []) = breakN prev  True a+createBreaknode prev a@(ZList _ (_,_,_,_,Penalty _) []) = breakN prev False a+createBreaknode prev a@(ZList _ (_,_,_,_,Glue _ _ _ _) []) = breakN prev False a+createBreaknode prev a@(ZList _ (_,_,_,_,_) []) = breakN prev False a+createBreaknode prev a@(ZList _ (_,_,_,_,FlaggedPenalty _ p _) _) | p <= infinity = breakN prev True a+createBreaknode prev a@(ZList _ (_,_,_,_,Letter _ _ _) _) = breakN prev False a+createBreaknode prev a@(ZList _ (_,_,_,_,AChar _ _ _) _) = breakN prev False a+createBreaknode prev a@(ZList _ (_,_,_,_,Kern _ _) _) = breakN prev False a createBreaknode prev z = createBreaknode prev (moveRight z) +breakN :: Maybe (Int,Int,Int,BreakNode)  -> Bool -> ZList s -> BreakNode+breakN prev t a =  let (w,y,z) = getDim a in BreakNode w y z 0.0 t 0 0.0 prev++-- | Get cumulated dimension for following box+getDim :: ZList s -> (PDFFloat,PDFFloat,PDFFloat)+getDim (ZList _ (w,y,z,_,Letter _ _ _) _) =  (w,y,z)+getDim (ZList _ (w,y,z,_,AChar _ _ _) _) =  (w,y,z)+getDim (ZList _ (w,y,z,_,Kern _ _) _) =  (w,y,z)+getDim (ZList _ (w,y,z,_,_) []) = (w,y,z)+getDim a = if theEnd a then error "Can't find end of paragraph" else getDim (moveRight a)+ -- | Create an hyphen penalty hyphenPenalty :: BRState-              -> AnyStyle -- ^ Style of future hyphen+              -> s -- ^ Style of future hyphen               -> PDFFloat -- ^ Size of hyphen taking into account the kerning that was perturbed by the hyphen introduction. The char before the hyphen is now bigger-              -> Letter+              -> Letter s hyphenPenalty settings s w = FlaggedPenalty w (hyphenPenaltyValue settings) s -moveRight :: ZList -> ZList+moveRight :: ZList s -> ZList s moveRight (ZList _ c@(w,y,z,p,Glue w' y' z' _) r) =      let w'' = w + w'         y''=y+y'@@ -273,13 +315,14 @@     in     ZList (OneCB c) (w'',y'',z'',p+1,head r) (tail r) moveRight (ZList _ c@(w,y,z,p,a) r) = -        let w' = boxWidthWithRatio a 0.0+        let w' = glueSizeWithRatio a 0.0             w'' = w + w'         in         ZList (OneCB c) (w'',y,z,p+1,head r) (tail r)+       isFeasibleBreakpoint :: Bool -- ^ Second pass-                     -> ZList -- ^ Current analyzed box+                     -> ZList s -- ^ Current analyzed box                      -> Bool -- ^ Result isFeasibleBreakpoint True (ZList _ (_,_,_,_,FlaggedPenalty _ p _) _) = p < infinity isFeasibleBreakpoint False (ZList _ (_,_,_,_,FlaggedPenalty _ _ _) _) = False@@ -306,7 +349,7 @@ -- we force a breakpoint updateWithNewRIfNoSolution :: Bool                            -> PDFFloat -- ^ Old r-                           -> ZList -- ^ Current+                           -> ZList s -- ^ Current                            -> (Int,Int,Int)                            -> PossibleBreak                            -> ActiveNodes-- ^ Actives@@ -325,9 +368,16 @@                     then                         f r (Map.delete key newmap)                     else-                        f r newmap                  +                        f r newmap   +                        +--debug b z = "(" +++--    show (cumulatedW z - totalWidth b + penaltyWidth (letter z)) ++ " " +++--    show (cumulatedY z - totalDilatation b) ++ " " +++--    show (cumulatedZ z - totalCompression b) ++ ")"   +--    +--breakTrace b z r' p = trace (debug b z ++ " " ++ show r' ++ " " ++ show (currentLetter z) ++ " " ++ show (position z) ++ " -> " ++ show p)           -getNewActiveBreakpoints ::  BRState -> Bool -> (Int -> PDFFloat) -> ActiveNodes -> ZList -> (PossibleBreak,ActiveNodes)+getNewActiveBreakpoints ::  BRState -> Bool -> (Int -> PDFFloat) -> ActiveNodes -> ZList s -> (PossibleBreak,ActiveNodes) getNewActiveBreakpoints settings sndPass fmaxw actives z =      if isFeasibleBreakpoint sndPass z     then@@ -362,7 +412,7 @@   -- Analyze the boxes to compute breaks-analyzeBoxes :: BRState -> Bool -> (Int -> PDFFloat) -> ActiveNodes -> ZList -> [(PDFFloat,Int,Bool)]+analyzeBoxes :: BRState -> Bool -> (Int -> PDFFloat) -> ActiveNodes -> ZList s -> [(PDFFloat,Int,Bool)] analyzeBoxes settings pass fmaxw actives z =      let getMinBreak b' = (\((xc,yc,zc),w) -> (xc,yc,zc,w)) . minimumBy (\(_,a) (_,b) -> compare (demerit a) (demerit b)) . Map.toList $ b'         (breaks',actives') = getNewActiveBreakpoints settings pass fmaxw actives z @@ -414,13 +464,13 @@                      analyzeBoxes settings pass fmaxw newActives (moveRight z)  -- | Create an hyphen box-hyphenBox :: AnyStyle -> Letter+hyphenBox :: Style s => s -> Letter s hyphenBox s = AChar s '-' (charWidth (textFont . textStyle $ s) '-')  -- Use a list of breakpoint and adjustement ratios to generate a list of lines. Bool means if the break was done on a flagged penalty (hyphen)-cutList :: [Letter] -> Int -> [(PDFFloat,Int,Bool)] -> [(PDFFloat,[Letter])]+cutList :: Style s => [Letter s] -> Int -> [(PDFFloat,Int,Bool)] -> [(PDFFloat,[Letter s],[Letter s])] cutList [] _ _ = []-cutList t _ [] = [(0.0,t)]+cutList t _ [] = [(0.0,[],t)] cutList t c ((ra,ba,fa):l) =     let (theLine,t') = splitAt (ba-c) t     in@@ -430,24 +480,24 @@       else           if null t'              then-                 [(ra,theLine)]+                 [(ra,theLine,t)]              else                  case head t' of                      FlaggedPenalty _ _ s -> if not fa                                                 then                                                   error $ "Breakpoint marked as not flagged but detected as flagged ! Send a bug report ! " ++ show (ra,ba,fa)                                                else-                                                 (ra,theLine ++ [hyphenBox s]) : cutList t' ba l+                                                 (ra,theLine ++ [hyphenBox s],t) : cutList t' ba l                      _ -> if fa                              then                                 error "Breakpoint marked as flagged but detected as not flagged ! Send a bug report !"                             else-                                (ra,theLine) : cutList t' ba l+                                (ra,theLine,t) : cutList t' ba l       -- Compute the breakpoints and generate a list of lines with the adjustement ratios -- The line are not interpreted. Some additional postprocessing is required -- for horizontal lines of vertical boxes-formatList :: BRState -> (Int -> PDFFloat) -> [Letter] -> [(PDFFloat,[Letter])]+formatList :: Style s => BRState -> (Int -> PDFFloat) -> [Letter s] -> [(PDFFloat,[Letter s],[Letter s])] formatList settings maxw boxes =      let active = Map.insert (0,0,1) (BreakNode 0 0 0 0 False 0 0.0 Nothing) Map.empty         theBreaks = analyzeBoxes settings False maxw active (createZList boxes)@@ -462,65 +512,104 @@ bigAdjustRatio = 10000.0  -- | Add a glue to the stream-glueBox :: Maybe AnyStyle+glueBox :: Maybe s         -> PDFFloat -- ^ Glue width         -> PDFFloat -- ^ Glue dilatation         -> PDFFloat -- ^ Glue compression-        -> Letter+        -> Letter s glueBox s w y z = Glue w y z s +-- | Return the standard space width+spaceWidth :: Style s => s -- ^ The style+           -> PDFFloat+spaceWidth  s =  +    let ws = (textWidth (textFont . textStyle $ s) (toPDFString " ") )+        h = scaleSpace . textStyle $ s+    in+      ws * h  +   +-- | How much dilatation is allowed compred to the space width   +centeredDilatationFactor :: PDFFloat+centeredDilatationFactor = 10.0       ++-- | How much dilatation is allowed compared to the space width   +leftDilatationFactor :: PDFFloat+leftDilatationFactor = 20.0++-- | How much dilatation is allowed compared to the space width   +rightDilatationFactor :: PDFFloat+rightDilatationFactor = 20.0+ -- | Add a glue to the stream-spaceGlueBox :: AnyStyle -- ^ The style-             -> Letter-spaceGlueBox s = +spaceGlueBox :: Style s => BRState -- ^ Paragraph settings+             -> s -- ^ The style+             -> PDFFloat+             -> [Letter s]+spaceGlueBox settings s f =       let ws = (textWidth (textFont . textStyle $ s) (toPDFString " ") )          h = scaleSpace . textStyle $ s          sy = scaleDilatation . textStyle $ s          sz = scaleCompression . textStyle $ s+         normalW = ws * h      in-     Glue (ws*h) (h*sy*ws/2.0) (h*sz*ws/3.0) (Just s)---- | Add a glue to the stream-punctuationGlue :: AnyStyle -- ^ The style-                -> Letter-punctuationGlue s = -  let ws = (textWidth (textFont . textStyle $ s) (toPDFString " ") )-      h = scaleSpace . textStyle $ s-      sy = scaleDilatation . textStyle $ s-      sz = scaleCompression . textStyle $ s-  in-  Glue (ws*h) (h*sy*ws) (h*sz*ws/3.0) (Just s)-  +     case (centered settings) of+        FullJustification -> [Glue (ws*h) (h*sy*ws/2.0*f) (h*sz*ws/3.0) (Just s)]+        Centered -> [ Glue 0 (centeredDilatationFactor*normalW) 0 (Just s)+                    , Penalty 0+                    , Glue normalW (-2*centeredDilatationFactor*normalW) 0 (Just s)+                    , Kern 0 (Just s)+                    , Penalty infinity+                    , Glue 0 (centeredDilatationFactor*normalW) 0 (Just s)+                    ]+        LeftJustification -> [ Glue 0 (leftDilatationFactor*normalW) 0 (Just s)+                             , Penalty 0+                             , Glue normalW (-leftDilatationFactor*normalW) 0 (Just s)+                             ] +        RightJustification -> [ Glue normalW (-rightDilatationFactor*normalW) 0 (Just s)+                              , Kern 0 (Just s)+                              , Penalty infinity+                              , Glue 0 (rightDilatationFactor*normalW) 0 (Just s)+                              ]                    +                           -- | Add a penalty to the stream penalty :: Int -- ^ Penalty value-        -> Letter+        -> Letter s penalty p = Penalty p  -- | Create a box containing text-createChar :: AnyStyle -- ^ Char style+createChar :: s -- ^ Char style            -> PDFFloat -- ^ Char width            -> Char -- ^ Char code-           -> Letter+           -> Letter s createChar s w t = AChar s t w   -- | Create boxes for the letters-createLetterBoxes :: BRState-                  -> AnyStyle -- ^ Letter style+createLetterBoxes :: Style s => BRState+                  -> s -- ^ Letter style                   -> [(PDFFloat,Char)] -- ^ Letter and size -                  -> [Letter] -- ^ Boxes+                  -> [Letter s] -- ^ Boxes createLetterBoxes _ _ [] = []  -createLetterBoxes settings s ((wa,'.'):b@(_,bc):l') | bc /= ' ' = (createChar s wa '.'): punctuationGlue s : createLetterBoxes settings s (b:l') -                                                    | otherwise = (createChar s wa '.') : punctuationGlue s : createLetterBoxes settings s l'+createLetterBoxes settings s ((wa,'.'):b@(_,bc):l') | bc /= ' ' = (createChar s wa '.') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa '.') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+createLetterBoxes settings s ((wa,','):b@(_,bc):l') | bc /= ' ' = (createChar s wa ',') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa ',') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+createLetterBoxes settings s ((wa,';'):b@(_,bc):l') | bc /= ' ' = (createChar s wa ';') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa ';') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+createLetterBoxes settings s ((wa,'!'):b@(_,bc):l') | bc /= ' ' = (createChar s wa '!') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa '!') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+createLetterBoxes settings s ((wa,'?'):b@(_,bc):l') | bc /= ' ' = (createChar s wa '?') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa '?') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+createLetterBoxes settings s ((wa,':'):b@(_,bc):l') | bc /= ' ' = (createChar s wa ':') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s (b:l') ))+                                                    | otherwise = (createChar s wa ':') : ((spaceGlueBox settings s 2.0) ++ (createLetterBoxes settings s l'))+ createLetterBoxes settings s ((_,'/'):(w,'-'):l) = hyphenPenalty settings s w : createLetterBoxes settings s l-createLetterBoxes settings s ((_,' '):l) = (spaceGlueBox s) : createLetterBoxes settings s l+createLetterBoxes settings s ((_,' '):l) = (spaceGlueBox settings s 1.0) ++ createLetterBoxes settings s l createLetterBoxes settings s ((w,t):l) = (createChar s w t) : createLetterBoxes settings s l-             --- WARNING : must generate a list of LETTERS--- word are created with the analysis of style just above+ -- | split a line into boxes-splitText :: BRState -> AnyStyle -> PDFString -> [Letter]+splitText :: Style s => BRState -> s -> PDFString -> [Letter s] splitText settings f t  = createLetterBoxes settings f . ripText (textFont . textStyle $ f) $ t -kernBox :: AnyStyle -> PDFFloat -> Letter+kernBox :: s -> PDFFloat -> Letter s kernBox s w = Kern w (Just s)
Graphics/PDF/Typesetting/Horizontal.hs view
@@ -38,10 +38,10 @@ -- WARNING -- According to splitText, PDFText to concatenate ARE letters so we can optimize the code -- Sentences are created when no word style is present, otherwise we just create words-createWords :: PDFFloat -- ^ Adjustement ratio-            -> Maybe (AnyStyle,String, PDFFloat) -- ^ Current word-            -> [Letter] -- ^ List of letters-            -> [HBox] -- ^ List of words or sentences+createWords :: ComparableStyle s => PDFFloat -- ^ Adjustement ratio+            -> Maybe (s,String, PDFFloat) -- ^ Current word+            -> [Letter s] -- ^ List of letters+            -> [HBox s] -- ^ List of words or sentences  createWords _ Nothing [] = [] -- Empty list, current word or sentence is added@@ -50,7 +50,7 @@ -- Start of a new word createWords r Nothing ((AChar s t w):l) = createWords r (Just (s,[t],w)) l -- New letter. Same style added to the word. Otherwise we start a new word-createWords r (Just (s,t,w)) ((AChar s' t' w'):l) | styleCode s == styleCode s' = createWords r (Just (s,t':t,w+w')) l+createWords r (Just (s,t,w)) ((AChar s' t' w'):l) | s `isSameStyleAs` s' = createWords r (Just (s,t':t,w+w')) l                                                   | otherwise = (createText s (saveCurrentword $ t) w):createWords r (Just (s',[t'],w')) l                                                                -- Glue close the word and start a new one because we want glues of different widths in the PDF@@ -72,37 +72,37 @@                -- Remove glues and penalties at the beginning of a line-simplify :: PDFFloat -- ^ Adjustement ratio-         -> [Letter] -- ^ List of letters-         -> [HBox] -- ^ List of words or sentence+simplify :: ComparableStyle s => PDFFloat -- ^ Adjustement ratio+         -> [Letter s] -- ^ List of letters+         -> [HBox s] -- ^ List of words or sentence simplify r ((Glue _ _ _ _):l) = simplify r l simplify r ((FlaggedPenalty _ _ _):l) = simplify r l simplify r ((Penalty _):l) = simplify r l simplify r l = createWords r Nothing l  -- | horizontalPostProcess-horizontalPostProcess :: [(PDFFloat,[Letter])] -- ^ adjust ratio, hyphen style, list of letters or boxes-                      -> [HBox] -- ^ List of lines+horizontalPostProcess :: (Style s) => [(PDFFloat,[Letter s],[Letter s])] -- ^ adjust ratio, hyphen style, list of letters or boxes+                      -> [(HBox s,[Letter s])] -- ^ List of lines horizontalPostProcess [] = []-horizontalPostProcess ((r,l'):l) = let l'' = simplify r l' in+horizontalPostProcess ((r,l',r'):l) = let l'' = simplify r l' in   if null l''       then           horizontalPostProcess l       else-          (mkHboxWithRatio r l''):horizontalPostProcess l +          ((mkHboxWithRatio r l''),r'):horizontalPostProcess l    -- | An horizontal Hbox (sentence or word) -- The width of the glue was computed with the adjustement ratio of the HLine containing the glue -- The width of the text is already taking into account the adjustement ratio of the HLine containing the Text -- Otherwise, HBox cannot dilate or compress. -data HBox  = HBox !PDFFloat !PDFFloat !PDFFloat ![HBox]-           | HGlue !PDFFloat !(Maybe (PDFFloat,PDFFloat)) !(Maybe AnyStyle)-           | Text !AnyStyle !PDFString !PDFFloat-           | SomeHBox !BoxDimension !AnyBox !(Maybe AnyStyle)+data HBox s = HBox !PDFFloat !PDFFloat !PDFFloat ![HBox s]+            | HGlue !PDFFloat !(Maybe (PDFFloat,PDFFloat)) !(Maybe s)+            | Text !s !PDFString !PDFFloat+            | SomeHBox !BoxDimension !AnyBox !(Maybe s)       -- | Change the style of the box      -withNewStyle :: AnyStyle -> HBox -> HBox+withNewStyle :: s -> HBox s -> HBox s withNewStyle _ a@(HBox _ _ _ _) = a withNewStyle s (HGlue a b _) = HGlue a b (Just s) withNewStyle s (Text _ a b) = Text s a b@@ -111,44 +111,47 @@ -- | A line of hboxes with an adjustement ratio required to display the text (generate the PDF command to increase space size)        --data HLine = HLine !PDFFloat ![HBox] deriving(Show) -mkHboxWithRatio :: PDFFloat -- ^ Adjustement ratio-                -> [HBox]-                -> HBox-mkHboxWithRatio _ [] = SomeHBox (0,0,0) (AnyBox NullChar) Nothing+mkHboxWithRatio :: Style s => PDFFloat -- ^ Adjustement ratio+                -> [HBox s]+                -> HBox s+mkHboxWithRatio _ [] = error "Cannot create an empty horizontal box" mkHboxWithRatio r l = -    let w = foldl' (\x y -> x + boxWidthWithRatio y r) 0.0 l+    let w = foldl' (\x y -> x + glueSizeWithRatio y r) 0.0 l         --h = maximum . map boxHeight $ l         ascent = maximum . map boxAscent $ l         d = maximum . map boxDescent $ l         h = ascent + d-        addBox (HGlue gw (Just(y,z)) s) (HBox w' h' d' l') = HBox w' h' d' (HGlue (glueWidth gw y z r) Nothing s:l')+        addBox (HGlue gw (Just(y,z)) s) (HBox w' h' d' l') = HBox w' h' d' (HGlue (glueSize gw y z r) Nothing s:l')         addBox a (HBox w' h' d' l') = HBox w' h' d' (a:l')         addBox _ _ = error "We can add boxes only to an horizontal list"     in     -- Add boxes and dilate glues when needing fixing their dimensions after dilatation     foldr addBox (HBox w h d []) l     -instance MaybeGlue HBox where-    boxWidthWithRatio (HGlue w (Just(y,z)) _) r = glueWidth w y z r-    boxWidthWithRatio a _ = boxWidth a-                        -  +instance Style s => MaybeGlue (HBox s) where+    glueSizeWithRatio (HGlue w (Just(y,z)) _) r = glueSize w y z r+    glueSizeWithRatio a _ = boxWidth a+    glueY (HGlue _ (Just(y,_)) _)  = y+    glueY _ = 0+    glueZ (HGlue _ (Just(_,z)) _)  = z+    glueZ _ = 0+     -- | Create an HBox           -createText :: Style s => s -- ^ Style+createText :: s -- ^ Style            -> PDFString -- ^ String            -> PDFFloat -- ^ Width-           -> HBox-createText s t w = Text (AnyStyle s) t w+           -> HBox s+createText s t w = Text s t w  -instance Show HBox where+instance Show (HBox s) where    show (HBox _ _ _ a) = "(HBox " ++ show a ++ ")"    show (HGlue a _ _) = "(HGlue " ++ show a ++ ")"    show (Text _ t _) = "(Text " ++ show t ++ ")"    show (SomeHBox _ t _) = "(SomeHBox " ++ show t ++ ")"  -- | Draw a line of words and glue using the word style-drawTextLine :: AnyStyle -> [HBox] -> PDFFloat -> PDFFloat -> Draw ()+drawTextLine :: (Style s) => s -> [HBox s] -> PDFFloat -> PDFFloat -> Draw () drawTextLine  _ [] _ _ = return () drawTextLine  style l@(a:l') x y | (isJust . wordStyle $ style) =  do     let  h = boxHeight a@@ -159,7 +162,7 @@                                  | otherwise = drawWords style l x y      -- | Draw a line of words, glue, or any box without word style-drawWords :: AnyStyle -> [HBox] -> PDFFloat -> PDFFloat -> Draw ()+drawWords :: (Style s) => s -> [HBox s] -> PDFFloat -> PDFFloat -> Draw () drawWords _ [] _ _ = return ()  drawWords s ((Text _ t w):l) x y = do@@ -185,7 +188,7 @@ drawWords _ _ _ _ = return ()  -- | Draw only words and glues using PDF text commands-drawPureWords :: AnyStyle -> [HBox] -> PDFFloat -> PDFFloat -> PDFText ([HBox],PDFFloat)  +drawPureWords :: Style s => s -> [HBox s] -> PDFFloat -> PDFFloat -> PDFText ([HBox s],PDFFloat)    drawPureWords s [] x y = do     drawTheTextBox StopText s x y Nothing@@ -206,7 +209,7 @@ drawPureWords s (_:l) x y = drawPureWords s l x y     -- When a start of line is detected by drawLineOfHBoxes, we start the drawing-startDrawingNewLineOfText :: PDFFloat -> PDFFloat -> [HBox] -> PDFFloat -> PDFFloat -> AnyStyle -> Draw ()+startDrawingNewLineOfText :: (Style s) => PDFFloat -> PDFFloat -> [HBox s] -> PDFFloat -> PDFFloat -> s -> Draw () startDrawingNewLineOfText hl dl l x y style =      do            -- Position of draw line based upon the whole line and not just this word@@ -221,9 +224,9 @@        drawLineOfHboxes hl dl l'' (x + w') y      -drawLineOfHboxes :: PDFFloat -- ^ Height of the total line first time this function is called+drawLineOfHboxes :: (Style s) => PDFFloat -- ^ Height of the total line first time this function is called                  -> PDFFloat -- ^ Descent of the total line first time this function is called-                 -> [HBox] -- ^ Remaining box to display+                 -> [HBox s] -- ^ Remaining box to display                  -> PDFFloat -- ^ x for the remaining boxes                  -> PDFFloat -- ^ y for the whole line                  -> Draw ()@@ -240,7 +243,7 @@       strokeBox a x y'       drawLineOfHboxes hl dl l (x + boxWidth a) y -instance Box HBox where+instance Style s => Box (HBox s) where      boxWidth (Text _ _ w) = w      boxWidth (HBox w _ _ _) = w      boxWidth (SomeHBox d _ _)  = boxWidth d@@ -272,6 +275,7 @@      strokeColor (textStrokeColor . textStyle $ style)      fillColor (textFillColor . textStyle $ style)      renderMode (textMode . textStyle $ style)+     setWidth (penWidth . textStyle $ style)      textStart x y      tell $ mconcat [newline,lbracket])   -- Here we need to dilate the space to take into account r and the font setting@@ -302,7 +306,7 @@                       | OneBlock -- ^ One block of text                       deriving(Eq)               -instance DisplayableBox HBox where+instance (Style s) => DisplayableBox (HBox s) where      strokeBox a@(HBox _ _ _ l) x y = do          let he = boxHeight a              de = boxDescent a@@ -336,10 +340,10 @@      strokeBox (HGlue _ _ _) _ _ = return ()        -- Test is a box has same style-isSameStyle :: Style s => s -         -> HBox+isSameStyle :: (Style s) => s +         -> HBox s          -> Bool-isSameStyle s (Text style _ _) = styleCode s == styleCode style-isSameStyle s (HGlue _ _ (Just style)) = styleCode s == styleCode style-isSameStyle s (SomeHBox _ _ (Just style)) = styleCode s == styleCode style+isSameStyle s (Text style _ _) = s `isSameStyleAs` style+isSameStyle s (HGlue _ _ (Just style)) = s `isSameStyleAs` style+isSameStyle s (SomeHBox _ _ (Just style)) = s `isSameStyleAs` style isSameStyle _ _ = False
+ Graphics/PDF/Typesetting/Layout.hs view
@@ -0,0 +1,334 @@+---------------------------------------------------------+-- |+-- Copyright   : (c) alpha 2006+-- 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+ ) where++import Graphics.PDF.LowLevel.Types+import Graphics.PDF.Typesetting.Breaking+import Graphics.PDF.Draw+import Graphics.PDF.Shapes(Rectangle(..))+import Graphics.PDF.Typesetting.Box+import Data.List(foldl')+import Data.Maybe(isJust,fromJust)+++data VerState s = VerState { baselineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (12,0.17,0.0)+                           , lineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (3.0,0.33,0.0)+                           , lineskiplimit :: !PDFFloat -- ^ Default value 2+                           , 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 (VGlue _ _ _ _ _) = False+notGlue (Paragraph _ _ _ _) = False+notGlue _ = 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 s h y z width delta = VGlue h width delta (Just(y,z)) s++instance Show (VBox ps s) where+ show (VBox _ a _ l _) = "(VBox " ++ show a ++ " " ++ show l ++ ")"+ show (VGlue a _ _ _ _) = "(VGlue " ++ show a ++ ")"+ show (Paragraph _ _ _ _) = "(Paragraph)"+ show (SomeVBox _ d t _) = "(SomeVBox " ++ show (boxHeight d) ++ " " ++ show t ++ ")"++instance MaybeGlue (VBox ps s) where+  glueSizeWithRatio (VGlue w _ _ (Just(y,z)) _) r = glueSize w y z r+  glueSizeWithRatio a _ = boxHeight a+  +  glueY (VGlue _ _ _ (Just(y,_)) _)  = y+  glueY _ = 0+  glueZ (VGlue _ _ _ (Just(_,z)) _)  = z+  glueZ _ = 0++instance Box (VBox ps s) where+   boxWidth (Paragraph _ _ _ _) = 0+   boxWidth (VBox w _ _ _ _) = w+   boxWidth (SomeVBox _ d _ _)  = boxWidth d+   boxWidth (VGlue _ w _ _ _)  = w++   boxHeight (Paragraph _ _ _ _) = 0+   boxHeight (VBox _ h _ _ _) = h+   boxHeight (SomeVBox _ d _ _) = boxHeight d+   boxHeight (VGlue h _ _ _ _) = h++   boxDescent (Paragraph _ _ _ _) = 0+   boxDescent (VBox _ _ d _ _) = d+   boxDescent (SomeVBox _ d _ _) = boxDescent d+   boxDescent (VGlue _ _ _ _ _) = 0++instance (ParagraphStyle ps s) => DisplayableBox (VBox ps s) where+        strokeBox (Paragraph _ _ _ _) _ _ = return ()+        strokeBox b@(VBox _ _ _ l _) x y'' = strokeVBoxes l x y'+          where+              y' = y'' - boxHeight b+        strokeBox (VGlue h w delta _ (Just style)) x y = +            if (isJust . interline $ style)+                then+                    (fromJust . interline $ style) $ Rectangle (x+delta) (y-h) (x+w+delta) y+                else+                   return()+        strokeBox (VGlue _ _ _ _ _) _ _ = return ()++        strokeBox (SomeVBox delta _ a _) x y = strokeBox a (x+delta) y+                +type Width = PDFFloat+type Height = PDFFloat++-- | Container for vboxes (x,y,width,maxheight,height,currenty,current z)+data Container ps s = Container PDFFloat PDFFloat Width 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+            -> Container ps s -- ^ New container+mkContainer x y width height  = Container x y width height 0 0 0 []            ++-- | Get the width of the container+containerWidth :: Container ps s -> PDFFloat+containerWidth (Container _ _ w _ _ _ _ _) = w++-- | Get the height of the container+containerHeight :: Container ps s -> PDFFloat+containerHeight (Container _ _ _ h _ _ _ _) = h++-- | Get the current height of the container without glue dilatation+containerCurrentHeight :: Container ps s -> PDFFloat+containerCurrentHeight (Container _ _ _ _ ch _ _ _) = ch++-- | Get the content height of the container with glue dilatation+containerContentHeight :: Container ps s -> PDFFloat+containerContentHeight (Container _ _ _ maxh h y z _) = let r = min (dilatationRatio maxh h y z) 2.0 in+ glueSize h y z r+ +-- | Get the minimum left border of the container content+containerContentLeftBorder :: Container ps s -> PDFFloat+containerContentLeftBorder (Container _ _ _ _ _ _ _ []) = 0.0+containerContentLeftBorder (Container _ _ _ _ _ _ _ l) = minimum . map getBoxDelta $ 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 (Container _ _ _ _ _ _ _ []) = 0.0+containerContentRightBorder (Container _ _ _ _ _ _ _ l) = + let xmax = maximum . map rightBorder $ l+     rightBorder x = getBoxDelta x + boxWidth x+ in+  xmax++-- | Container horizontal position+containerX :: Container ps s -> PDFFloat+containerX (Container x _ _ _ _ _ _ _) = x++-- | Container vertical position+containerY :: Container ps s -> PDFFloat+containerY (Container _ y _ _ _ _ _ _) = y++-- | Return the rectangle containing the text after formatting and glue dilatation+containerContentRectangle :: Container ps s -> Rectangle+containerContentRectangle c = Rectangle (x+l) (y-th) (x+r) y + where+    x = containerX c+    y = containerY c+    th = containerContentHeight c+    l = containerContentLeftBorder c+    r = containerContentRightBorder c+++-- | Get the required style for the interline glue+getInterlineStyle :: ComparableStyle ps => VBox ps s -> VBox ps s -> Maybe ps+getInterlineStyle (VBox _ _ _ _ (Just s)) (SomeVBox _ _ _ (Just s')) | s `isSameStyleAs` s' = Just s+                                                                     | otherwise = Nothing++getInterlineStyle (VBox _ _ _ _ (Just s)) (VBox _ _ _ _ (Just s')) |  s `isSameStyleAs`  s' = Just s+                                                                   | otherwise = Nothing++getInterlineStyle (SomeVBox _ _ _ (Just s)) (SomeVBox _ _ _ (Just s')) |  s `isSameStyleAs`  s' = Just s+                                                                       | otherwise = Nothing++getInterlineStyle (SomeVBox _ _ _ (Just s)) (VBox _ _ _ _ (Just s')) |  s `isSameStyleAs`  s' = Just s+                                                                     | otherwise = Nothing++getInterlineStyle _ _ = Nothing++-- | Interline glue required+interlineGlue :: ComparableStyle ps => VerState ps -> VBox ps s -> VBox ps s -> Maybe (VBox ps s, PDFFloat, PDFFloat)+interlineGlue settings a b | notGlue a && notGlue b = +    let p = boxDescent a+        h = boxHeight b - boxDescent b+        (ba,by,bz) = baselineskip settings+        (lw,ly,lz) = lineskip settings+        li = lineskiplimit settings+        istyle = getInterlineStyle a b+        theWidth = boxWidth a+        theDelta = getBoxDelta a+    in+    if p <= -1000 +        then+            Nothing+        else+            if ba - p - h >= li+                then+                    Just $ (vglue istyle (ba-p-h) by bz theWidth theDelta,by,bz)+                else+                    Just $ (vglue istyle lw ly lz theWidth theDelta,ly,lz)+                                  | otherwise = Nothing++addTo :: ComparableStyle ps => VerState ps -> VBox ps s -> Container ps s -> Container ps s+addTo _ line (Container px py w maxh h y z []) = Container px py w maxh ((boxHeight line)+h) y z [line]+addTo settings line (Container px py w maxh h y z l@(a:_)) = +    case interlineGlue settings a line of+        Nothing ->+          let h' = boxHeight line + h +              y' = y + glueY line+              z' = z + glueZ line+          in+          Container px py w maxh h' y' z' (line:l)+        Just (v,ny,nz) ->+          let h' = boxHeight line + h + boxHeight v+              y' = y + ny + glueY line+              z' = z + nz + glueZ line+          in+          Container px py w maxh h' y' z' (line:v:l)+          +isOverfull :: Container ps s -> Bool+isOverfull (Container _ _ _ maxh h y z _) = let r = dilatationRatio maxh h y z+ in+   if r >= bigAdjustRatio then h > maxh else r <= -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 _ = Nothing+    lineWidth _ w _ = w+    linePosition _ _ = const 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+               -> [Letter s] -- ^ List of letters in the paragraph+               -> (a,[Letter s]) -- ^ Update style and list of letters+    paragraphChange a l = (a,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 _ = Nothing++-- | Get the delta used to position a box with non rectangular shapes+getBoxDelta :: VBox ps s -> PDFFloat+getBoxDelta (Paragraph _ _ _ _) = 0.0+getBoxDelta (VBox _ _ _ _ _) = 0.0+getBoxDelta (VGlue _ _ delta _ _) = delta+getBoxDelta (SomeVBox delta _ _ _) = delta+++++isSameParaStyle :: ComparableStyle ps => ps -> VBox ps s -> Bool+isSameParaStyle s (Paragraph _ _ (Just s') _) =  s `isSameStyleAs`  s'+isSameParaStyle s (VBox _ _ _ _ (Just s')) =  s `isSameStyleAs`  s'+isSameParaStyle s (VGlue _ _ _ _ (Just s')) =  s `isSameStyleAs`  s'+isSameParaStyle s (SomeVBox _ _ _ (Just s'))  =  s `isSameStyleAs`  s'     +isSameParaStyle _ _ = False++recurseStrokeVBoxes :: (ParagraphStyle ps s) => Int -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()+recurseStrokeVBoxes _ [] _ _  = return ()+recurseStrokeVBoxes _ (Paragraph _ _ _ _:_) _ _ = return ()+recurseStrokeVBoxes nb (a@(VGlue _ _ _ _ _):l) xa y  = do+    let h = boxHeight a+    strokeBox a xa y+    recurseStrokeVBoxes nb l xa (y-h)++recurseStrokeVBoxes nb (a:l) xa y = do+    let h = boxHeight a+    strokeBox a xa y+    recurseStrokeVBoxes (nb+1) l xa (y-h)++drawWithParaStyle :: (ParagraphStyle ps s) => ps -> [VBox ps s] -> PDFFloat -> PDFFloat -> Draw ()   +drawWithParaStyle style b xa y' = do+    let  (l',l'') = span (isSameParaStyle style) b+         h' = foldl' (\x' ny -> x' + boxHeight ny) 0.0 l'+    if (isJust . paragraphStyle $ style)+      then do+          let xleft = (minimum $ 100000:map getBoxDelta l' ) + xa+              xright = (maximum $ 0:(map (\x -> boxWidth x + getBoxDelta x) l')) + xa+          (fromJust . paragraphStyle $ style) (Rectangle xleft (y'- h') xright (y')) (recurseStrokeVBoxes 1 l' xa y')+      else+         recurseStrokeVBoxes 1 l' xa y'+    strokeVBoxes l'' xa (y' - h')++-- | Stroke the VBoxes+strokeVBoxes :: (ParagraphStyle ps s) => [VBox ps s] -- ^ List of boxes+             -> PDFFloat -- ^ X pos+             -> PDFFloat -- ^ Y pos+             -> Draw ()+strokeVBoxes [] _ _ = return ()+strokeVBoxes b@((Paragraph _ _ (Just s') _):_) xa y = drawWithParaStyle s' b xa y +strokeVBoxes b@((VBox _ _ _ _ (Just s')):_) xa y = drawWithParaStyle s' b xa y +strokeVBoxes b@((VGlue _ _ _ _ (Just s')):_) xa y = drawWithParaStyle s' b xa y+strokeVBoxes b@((SomeVBox _ _ _ (Just s')):_) xa y = drawWithParaStyle s' b xa y+strokeVBoxes (a:l) xa y = +    do+        let h = boxHeight a+        strokeBox a xa y+        strokeVBoxes l xa (y-h)+        
+ Graphics/PDF/Typesetting/StandardStyle.hs view
@@ -0,0 +1,41 @@+---------------------------------------------------------+-- |+-- Copyright   : (c) alpha 2007+-- License     : BSD-style+--+-- Maintainer  : misc@NOSPAMalpheccar.org+-- Stability   : experimental+-- Portability : portable+--+-- Standard styles for typesettings+---------------------------------------------------------+-- #hide+module Graphics.PDF.Typesetting.StandardStyle(+ -- * Styles+   StandardStyle(..)+ , StandardParagraphStyle(..)+ ) where+     +import Graphics.PDF.Colors+import Graphics.PDF.Text+import Graphics.PDF.Typesetting.Vertical+import Graphics.PDF.Typesetting.Box+     +-- | Standard styles for sentences+data StandardStyle = Font PDFFont Color Color++-- | Standard styles for paragraphs+data StandardParagraphStyle = NormalParagraph+++instance ComparableStyle StandardStyle where+  isSameStyleAs (Font a sca fca) (Font b scb fcb) = a == b && sca == scb && fca == fcb+  --isSameStyleAs _ _ = False+    +instance ComparableStyle StandardParagraphStyle where+  isSameStyleAs NormalParagraph NormalParagraph = True +  +instance Style StandardStyle where+    textStyle (Font a sc fc) = TextStyle a sc fc FillText 1.0 1.0 1.0 1.0    ++instance ParagraphStyle StandardParagraphStyle StandardStyle       
Graphics/PDF/Typesetting/Vertical.hs view
@@ -11,306 +11,149 @@ --------------------------------------------------------- -- #hide module Graphics.PDF.Typesetting.Vertical (-    VBox(..)-  , VerState(..)-  , verticalPostProcess-  , mkVboxWithRatio-  , strokeVBoxes+    mkVboxWithRatio   , vglue   , defaultVerState   , ParagraphStyle(..)-  , AnyParagraphStyle(..)+  , VerState(..)+  , fillContainer+  , mkContainer+  , VBox(..)  ) where   import Graphics.PDF.LowLevel.Types import Graphics.PDF.Typesetting.Breaking import Graphics.PDF.Typesetting.Horizontal(horizontalPostProcess,HBox) import Graphics.PDF.Draw-import Graphics.PDF.Shapes(Rectangle(..)) import Graphics.PDF.Typesetting.Box import Data.List(foldl')-import Data.Maybe(isJust,fromJust)--data VerState = VerState { baselineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (12,0.17,0.0)-                         , lineskip :: !(PDFFloat,PDFFloat,PDFFloat) -- ^ Default value (3.0,0.33,0.0)-                         , lineskiplimit :: !PDFFloat -- ^ Default value 2-                         , paraStyle :: !AnyParagraphStyle-                         }+import Graphics.PDF.Typesetting.Layout         -defaultVerState :: ParagraphStyle s => s -> VerState                 +-- | Default vertical state+--+-- > Default values+-- > baselineskip = (12,0.17,0.0)+-- > lineskip = (3.0,0.33,0.0)+-- > lineskiplimit = 2+--+defaultVerState :: s -> VerState s                 defaultVerState s = VerState { baselineskip = (12,0.17,0.0)                              , lineskip = (3.0,0.33,0.0)                              , lineskiplimit = 2-                             , paraStyle = AnyParagraphStyle s+                             , currentParagraphStyle = s                              }  -- | Pair of functions describing the shape of a text areas : horizontal position of each line, vertical top of the area, width of each line -- First line is 1 -data VBox  = Paragraph [Letter] !(Maybe AnyParagraphStyle) !BRState-           | VBox !PDFFloat !PDFFloat !PDFFloat ![VBox] !(Maybe AnyParagraphStyle)-           | VGlue !PDFFloat !PDFFloat !PDFFloat !(Maybe (PDFFloat,PDFFloat)) !(Maybe AnyParagraphStyle)-           | SomeVBox !PDFFloat !BoxDimension !AnyBox !(Maybe AnyParagraphStyle)+            -vglue :: Maybe AnyParagraphStyle-      -> PDFFloat -- ^ Glue height-      -> PDFFloat -- ^ Glue dilatation factor-      -> PDFFloat -- ^ Glue compression factor-      -> PDFFloat -- ^ Glue width-      -> PDFFloat -- ^ Glue delta-      -> VBox-vglue s h y z width delta = VGlue h width delta (Just(y,z)) s -instance Show VBox where-  show (VBox _ _ _ a _) = "(HBox " ++ show a ++ ")"-  show (VGlue a _ _ _ _) = "(HGlue " ++ show a ++ ")"-  show (Paragraph _ _ _) = "(Paragraph)"-  show (SomeVBox _ _ t _) = "(SomeHBox " ++ show t ++ ")"                           -- | A line of hboxes with an adjustement ratio required to display the text (generate the PDF command to increase space size)        --data HLine = HLine !PDFFloat ![HBox] deriving(Show)  mkVboxWithRatio :: PDFFloat -- ^ Adjustement ratio-                -> [VBox]-                -> VBox-mkVboxWithRatio _ [] = SomeVBox 0.0 (0,0,0) (AnyBox NullChar) Nothing+                -> [VBox ps s]+                -> VBox ps s+mkVboxWithRatio _ [] = error "Cannot make an empty vbox" mkVboxWithRatio r l = -   let w = foldl' (\x y -> x + boxWidthWithRatio y r) 0.0 l+   let w = foldl' (\x y -> x + glueSizeWithRatio y r) 0.0 l        h = maximum . map boxHeight $ l        d = maximum . map boxDescent $ l-       addBox (VGlue gw gh gdelta (Just(y,z)) s) (VBox w' h' d' l' s') = VBox w' h' d' (VGlue (glueWidth gw y z r) gh gdelta Nothing s:l') s'+       addBox (VGlue gw gh gdelta (Just(y,z)) s) (VBox w' h' d' l' s') = VBox w' h' d' (VGlue (glueSize gw y z r) gh gdelta Nothing s:l') s'        addBox a (VBox w' h' d' l' s') = VBox w' h' d' (a:l') s'        addBox _ _ = error "We can add boxes only to an horizontal list"    in    -- Add boxes and dilate glues when needing fixing their dimensions after dilatation    foldr addBox (VBox w h d [] Nothing) l -instance MaybeGlue VBox where-   boxWidthWithRatio (VGlue w _ _ (Just(y,z)) _) r = glueWidth w y z r-   boxWidthWithRatio a _ = boxWidth a -        --- | Convert pure lines to VBoxes-toVBoxes :: Maybe AnyParagraphStyle-         -> PDFFloat -- ^ Max width-         -> [HBox] -- ^ List of lines-         -> [VBox] -- ^ List of VBoxes-toVBoxes Nothing _ l = map createVBox l- where-    createVBox a =  SomeVBox 0.0 (boxWidth a,boxHeight a,boxDescent a) (AnyBox a) Nothing -toVBoxes s@(Just style) w l = map createVBoxAndAddKern $ zip [1..] (l )- where-      createVBoxAndAddKern (nb,a) = -          let delta = (linePosition style) w nb-          in-          SomeVBox delta (boxWidth a,boxHeight a,boxDescent a) (AnyBox a) s --- | Create VBoxes. Paragraphs are analyzed and cut into VBoxes. The pragraph style is updated and used--- to transform the list of letters-verticalPostProcess :: VerState-             -> Int -- ^ Line offset for the text area-             -> Rectangle -- ^ Text area-             -> [VBox] -- ^ List of VBox with paragraphs-             -> [VBox] -- ^ List of VBox where paragraphs have been line broken-verticalPostProcess _ _ _ [] = []-verticalPostProcess pageSettings o rect@(Rectangle xa _ xb _) ((Paragraph l style paraSettings):l') = -    let (fl,newStyle) = case style of-              Nothing -> (formatList paraSettings (const $ xb-xa) l,Nothing) -              Just aStyle -> let (style',nl) = paraChange aStyle l -               in-               (formatList paraSettings (\nb -> (lineWidth style') (xb-xa) nb ) nl,Just style')-    in-    (addInterlineGlue pageSettings . toVBoxes newStyle (xb - xa) . horizontalPostProcess $ fl) ++ verticalPostProcess pageSettings (o + length fl) rect l'-verticalPostProcess pageSettings o rect (a:l') = a:verticalPostProcess pageSettings (o+1) rect l'  -notGlue :: VBox -> Bool-notGlue (VGlue _ _ _ _ _) = False-notGlue (Paragraph _ _ _) = False-notGlue _ = True --- | Get the required style for the interline glue-getInterlineStyle :: VBox -> VBox -> Maybe AnyParagraphStyle-getInterlineStyle (VBox _ _ _ _ (Just s)) (SomeVBox _ _ _ (Just s')) | paraStyleCode s == paraStyleCode s' = Just s-                                                                     | otherwise = Nothing--getInterlineStyle (VBox _ _ _ _ (Just s)) (VBox _ _ _ _ (Just s')) | paraStyleCode s == paraStyleCode s' = Just s-                                                                   | otherwise = Nothing--getInterlineStyle (SomeVBox _ _ _ (Just s)) (SomeVBox _ _ _ (Just s')) | paraStyleCode s == paraStyleCode s' = Just s-                                                                       | otherwise = Nothing--getInterlineStyle (SomeVBox _ _ _ (Just s)) (VBox _ _ _ _ (Just s')) | paraStyleCode s == paraStyleCode s' = Just s-                                                                     | otherwise = Nothing+    +dilateVboxes :: PDFFloat -> VBox ps s -> VBox ps s+dilateVboxes r g@(VGlue _ w l (Just(_,_)) s) = +    let h' = glueSizeWithRatio g r+    in+      VGlue h' w l Nothing s+dilateVboxes _ g@(VGlue _ _ _ Nothing _) = g+dilateVboxes _ a = a               -getInterlineStyle _ _ = Nothing+drawContainer :: ParagraphStyle ps s => Container ps s -- ^ Container+              -> Draw ()+drawContainer (Container px py _ maxh h y z oldl) = +    let l' = reverse oldl+        r = min (dilatationRatio maxh h y z) 2.0+        l'' = map (dilateVboxes r) l'+    in+      strokeVBoxes l'' px py+      +-- | Create a new paragraph from the remaining letters+createPara :: Int+           -> Maybe ps+           -> BRState+           -> [Letter s] +           -> [VBox ps s]+createPara _ _ _ [] = []+createPara lineOffset style paraSettings l = [Paragraph lineOffset l style paraSettings] --- | Get the delta used to position a box with non rectangular shapes-getBoxDelta :: VBox -> PDFFloat-getBoxDelta (Paragraph _ _ _) = 0.0-getBoxDelta (VBox _ _ _ _ _) = 0.0-getBoxDelta (VGlue _ _ delta _ _) = delta-getBoxDelta (SomeVBox delta _ _ _) = delta-           -addInterlineGlue :: VerState -> [VBox] -> [VBox]-addInterlineGlue _ [] = []-addInterlineGlue _ [a] = [a]-addInterlineGlue settings (a:b:l) | notGlue a && notGlue b = -    let p = boxDescent a-        h = boxHeight b - boxDescent b-        (ba,by,bz) = baselineskip settings-        (lw,ly,lz) = lineskip settings-        li = lineskiplimit settings-        istyle = getInterlineStyle a b-        theWidth = boxWidth a-        theDelta = getBoxDelta a+-- | Add paragraph lines to a container+addParaLine :: (ParagraphStyle ps s, ComparableStyle ps) => VerState ps+            -> Maybe ps+            -> BRState +            -> Container ps s -- ^ Container+            -> [((HBox s,[Letter s]),Int)]+            -> Either (Draw (),Container ps s,[VBox ps s]) (Container ps s)+addParaLine _ _ _ c  [] = Right c+addParaLine verstate style paraSettings c (((line,remainingPar),lineNb):l) = +    let c' = addTo verstate (toVBoxes style (containerWidth c) line lineNb) c      in-    if p <= -1000 +    if isOverfull c'         then-            a:addInterlineGlue settings (b:l)+         Left (drawContainer c,c,createPara lineNb style paraSettings remainingPar)         else-            if ba - p - h >= li-                then-                    a:(vglue istyle (ba-p-h) by bz theWidth theDelta):addInterlineGlue settings (b:l)-                else-                    a:(vglue istyle lw ly lz theWidth theDelta):addInterlineGlue settings (b:l)-                                  | otherwise = a:addInterlineGlue settings (b:l)+         addParaLine verstate style paraSettings c' l -instance Box VBox where-     boxWidth (Paragraph _ _ _) = 0-     boxWidth (VBox w _ _ _ _) = w-     boxWidth (SomeVBox _ d _ _)  = boxWidth d-     boxWidth (VGlue _ w _ _ _)  = w-                  -     boxHeight (Paragraph _ _ _) = 0-     boxHeight (VBox _ h _ _ _) = h-     boxHeight (SomeVBox _ d _ _) = boxHeight d-     boxHeight (VGlue h _ _ _ _) = h+-- | Fill a container with lines+fillContainer :: (ParagraphStyle ps s, ComparableStyle ps) => VerState ps -- ^ Vertical style for interline glues+              -> Container ps s -- ^ Container+              -> [VBox ps s] -- ^ VBox to add+              -> (Draw(),Container ps s,[VBox ps s]) -- ^ Component to draw, new container and remaining VBoxes due to overfull container+fillContainer _ c [] = (drawContainer c,c,[])+fillContainer verstate c (Paragraph lineOffset l style paraSettings:l') = +    let (fl,newStyle) = case style of+                Nothing -> (formatList paraSettings (const $ containerWidth c) l,Nothing) +                Just aStyle -> let (style',nl) = paragraphChange aStyle l +                               in+                               (formatList paraSettings (\nb -> (lineWidth style') (containerWidth c) (nb+lineOffset) ) nl,Just style')+        newLines = horizontalPostProcess fl+        r = addParaLine verstate newStyle paraSettings c (zip newLines [1..])+    in+      case r of+          Left (d,c',remPara) -> (d,c',remPara ++ l')+          Right c' -> fillContainer verstate c' l'     -     boxDescent (Paragraph _ _ _) = 0-     boxDescent (VBox _ _ d _ _) = d-     boxDescent (SomeVBox _ d _ _) = boxDescent d-     boxDescent (VGlue _ _ _ _ _) = 0--instance DisplayableBox VBox where-          strokeBox (Paragraph _ _ _) _ _ = return ()-          strokeBox b@(VBox _ _ _ l _) x y'' = strokeVBoxes l (x,y',y'')-            where-                y' = y'' - boxHeight b-          strokeBox (VGlue h w delta _ (Just style)) x y = -              if (isJust . interline $ style)-                  then-                      (fromJust . interline $ style) $ Rectangle (x+delta) (y-h) (x+w+delta) y-                  else-                     return()-          strokeBox (VGlue _ _ _ _ _) _ _ = return ()-          -          strokeBox (SomeVBox delta _ a _) x y = strokeBox a (x+delta) y- -isSameParaStyle :: AnyParagraphStyle -> VBox -> Bool-isSameParaStyle s (Paragraph _ (Just s') _) = paraStyleCode s == paraStyleCode s'-isSameParaStyle s (VBox _ _ _ _ (Just s')) = paraStyleCode s == paraStyleCode s'-isSameParaStyle s (VGlue _ _ _ _ (Just s')) = paraStyleCode s == paraStyleCode s'-isSameParaStyle s (SomeVBox _ _ _ (Just s'))  = paraStyleCode s == paraStyleCode s'     -isSameParaStyle _ _ = False-     -recurseStrokeVBoxes :: Int -> [VBox] -> (PDFFloat,PDFFloat,PDFFloat) -> Draw ()-recurseStrokeVBoxes _ [] _  = return ()-recurseStrokeVBoxes _ (Paragraph _ _ _:_) _  = return ()-recurseStrokeVBoxes nb (a@(VGlue _ _ _ _ _):l) (xa,y',y)  = do-    let h = boxHeight a-    strokeBox a xa y-    if y - h >= y'+fillContainer verstate c oldl@(a:l) = +    let c' = addTo verstate a c+    in+    if isOverfull c'        then-        recurseStrokeVBoxes nb l (xa,y',(y-h))-      else-        return ()-    -recurseStrokeVBoxes nb (a:l) (xa,y',y) = do-    let h = boxHeight a-    strokeBox a xa y-    if y - h >= y'-     then-       recurseStrokeVBoxes (nb+1) l (xa,y',(y-h))-     else-       return ()           -               -drawWithParaStyle :: AnyParagraphStyle -> [VBox] -> (PDFFloat,PDFFloat,PDFFloat) -> Draw ()   -drawWithParaStyle style b (xa,y',y'') = do-    let  (l',l'') = span (isSameParaStyle style) b-         h' = foldl' (\x' ny -> x' + boxHeight ny) 0.0 l'-    if (isJust . paragraphStyle $ style)-      then do-          let xleft = (minimum $ 100000:map getBoxDelta l' ) + xa-              xright = (maximum $ 0:(map (\x -> boxWidth x + getBoxDelta x) l')) + xa-          (fromJust . paragraphStyle $ style) (Rectangle xleft (y''- h') xright (y'')) (recurseStrokeVBoxes 1 l' (xa,y',y''))+          (drawContainer c,c,oldl)       else-         recurseStrokeVBoxes 1 l' (xa,y',y'')-    strokeVBoxes l'' (xa,y',y''-h')-               --- | Stroke the VBoxes-strokeVBoxes :: [VBox] -- ^ List of boxes-             -> (PDFFloat,PDFFloat,PDFFloat)-             -> Draw ()-strokeVBoxes [] (_,_,_) = return ()-strokeVBoxes b@((Paragraph _ (Just s') _):_) (xa,y',y'') = drawWithParaStyle s' b (xa,y',y'')-strokeVBoxes b@((VBox _ _ _ _ (Just s')):_) (xa,y',y'') = drawWithParaStyle s' b (xa,y',y'')-strokeVBoxes b@((VGlue _ _ _ _ (Just s')):_) (xa,y',y'') = drawWithParaStyle s' b (xa,y',y'')-strokeVBoxes b@((SomeVBox _ _ _ (Just s')):_) (xa,y',y'') = drawWithParaStyle s' b (xa,y',y'')-strokeVBoxes (a:l) (xa,y',y'') = -    do-        let h = boxHeight a-        strokeBox a xa y''-        if y'' - h >= y'-          then-             strokeVBoxes l (xa,y',(y''-h))-          else-             return ()---- | Paragraph style-class ParagraphStyle a 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-    -    -- | All paragraph styles used in a document must have different codes-    paraStyleCode :: a -- ^ The style -                  -> Int -- ^ Code identifying the style-    -    -- | 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 _ = Nothing-    lineWidth _ w _ = w-    linePosition _ _ = const 0.0-    -    -- | Change the content of a paragraph before the line breaking algorithm is run. It may also change the style-    paraChange :: a -- ^ The style-               -> [Letter] -- ^ List of letters in the paragraph-               -> (a,[Letter]) -- ^ Update style and list of letters-    paraChange a l = (a,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 _ = Nothing-    --- | Any paragraph style-data AnyParagraphStyle = forall a . ParagraphStyle a => AnyParagraphStyle a+          fillContainer verstate c' l+          +-- | Convert pure lines to VBoxes+toVBoxes :: (ParagraphStyle ps s) => Maybe ps+       -> PDFFloat -- ^ Max width+       -> HBox s -- ^ List of lines+       -> Int -- ^ Line number+       -> VBox ps s -- ^ List of VBoxes+toVBoxes Nothing _ a _ = SomeVBox 0.0 (boxWidth a,boxHeight a,boxDescent a) (AnyBox a) Nothing+toVBoxes s@(Just style) w a nb = +        let delta = (linePosition style) w nb in+        SomeVBox delta (boxWidth a,boxHeight a,boxDescent a) (AnyBox a) s -instance ParagraphStyle AnyParagraphStyle where-    lineWidth (AnyParagraphStyle a) = lineWidth a-    linePosition (AnyParagraphStyle a) = linePosition a-    paraStyleCode (AnyParagraphStyle a) = paraStyleCode a-    interline (AnyParagraphStyle a) = interline a-    paraChange (AnyParagraphStyle a) l = let (a',l') = paraChange a l in (AnyParagraphStyle a',l')-    paragraphStyle (AnyParagraphStyle a) = paragraphStyle a
HPDF.cabal view
@@ -1,5 +1,5 @@ Name: HPDF-Version: 1.1+Version: 1.2 License: LGPL License-file:LICENSE Copyright: Copyright (c) 2007, alpheccar@@ -7,8 +7,8 @@ synopsis: Generation of PDF documents maintainer: misc@NOSPAMalpheccar.org tested-with: GHC==6.6-homepage: http://www.alpheccar.org/en/posts/show/82-build-depends: base, haskell98,mtl,encoding >= 0.1 ,zlib >= 0.3, binary >= 0.3+homepage: http://www.alpheccar.org/en/posts/show/84+build-depends: base, haskell98,mtl,encoding >= 0.2 ,zlib >= 0.3, binary >= 0.3 ghc-options: -Wall -funbox-strict-fields  -fglasgow-exts  -O2 extensions: ForeignFunctionInterface, CPP description: A PDF library with support for several pages, page transitions, outlines, annotations, compression, colors, shapes, patterns, jpegs, fonts, typesetting ...@@ -54,4 +54,6 @@    Graphics.PDF.Typesetting.Horizontal    Graphics.PDF.Typesetting.Vertical    Graphics.PDF.Typesetting.Box+   Graphics.PDF.Typesetting.Layout    Graphics.PDF.LowLevel.Serializer+   Graphics.PDF.Typesetting.StandardStyle
Test/test.hs view
@@ -75,13 +75,46 @@            strokeColor (Rgb 0 0 1)            stroke (Ellipse 0 0 100 50)             -testAnnotation :: Draw ()-testAnnotation = do-    strokeColor red-    newAnnotation (URLLink (toPDFString "Go to my blog") [0,0,100,100] "http://www.alpheccar.org" True)-    drawText $ text (PDFFont Times_Roman 12) 10 30 (toPDFString "Go to my blog")-    stroke $ Rectangle 0 0 100 100-    newAnnotation (TextAnnotation (toPDFString "Key annotation") [100,100,130,130] Key)+testAnnotation ::PDFReference PDFPage -> PDF ()+testAnnotation p = do+    drawWithPage p $ do+      r+   +    p1 <- addPage Nothing+    drawWithPage p1 $ do+      withNewContext $ do+        applyMatrix $ translate 50 0+        r+    p2 <- addPage Nothing+    drawWithPage p2 $ do+      strokeColor red+      stroke $ Line 0 0 100 0+      applyMatrix $ translate 100 0+      strokeColor green+      stroke $ Line 0 0 100 0+      withNewContext $ do+          applyMatrix $ rotate (Degree (-20))+          strokeColor $ Rgb 1 1 0+          stroke $ Line 0 0 100 0+          applyMatrix $ translate 50 50+          strokeColor blue+          stroke $ Line 0 0 100 0+          withNewContext $ do+            applyMatrix $ rotate (Degree 45)+            r+            strokeColor black+            stroke $ Line 0 0 100 0+    p3 <- addPage Nothing+    drawWithPage p3 $ do+     withNewContext $ do+        applyMatrix $ scale 3 1+        r+ where r = do+        strokeColor red+        newAnnotation (URLLink (toPDFString "Go to my blog") [0,0,200,100] "http://www.alpheccar.org" True)+        drawText $ text (PDFFont Times_Roman 12) 10 30 (toPDFString "Go to my blog")+        stroke $ Rectangle 0 0 200 100+        newAnnotation (TextAnnotation (toPDFString "Key annotation") [100,100,130,130] Key)   textTest :: Draw () textTest = do@@ -103,72 +136,59 @@            applyMatrix $ scale 2 2            drawXObject jpg            -data Normal = Normal deriving(Eq)-data Bold = Bold deriving(Eq)-data Crazy = Crazy deriving(Eq)-data SuperCrazy = SuperCrazy !([Int],[PDFFloat]) deriving(Eq)-data DebugStyle = DebugStyle deriving(Eq)-data RedRectStyle = RedRectStyle deriving(Eq)-data BlueStyle = BlueStyle deriving(Eq) -instance Style Normal where-    textStyle _ = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0-    styleCode _ = 1+data MyParaStyles = Normal+                  | Bold+                  | Crazy+                  | SuperCrazy [Int] [PDFFloat]+                  | DebugStyle+                  | RedRectStyle+                  | BlueStyle+                  +instance ComparableStyle MyParaStyles where+  isSameStyleAs Normal Normal = True+  isSameStyleAs Bold Bold = True+  isSameStyleAs Crazy Crazy = True+  isSameStyleAs (SuperCrazy _ _) (SuperCrazy _ _) = True+  isSameStyleAs DebugStyle DebugStyle = True+  isSameStyleAs RedRectStyle RedRectStyle = True+  isSameStyleAs BlueStyle BlueStyle = True+  isSameStyleAs _ _ = False+  +                  +instance Style MyParaStyles where+    textStyle Normal = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0+    textStyle Bold = TextStyle (PDFFont Times_Bold 12) black black FillText 1.0 1.0 1.0 1.0+    textStyle RedRectStyle = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0+    textStyle DebugStyle = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0+    textStyle Crazy = TextStyle (PDFFont Times_Roman 10) red red FillText 1.0 1.0 1.0 1.0+    textStyle (SuperCrazy _ _) = TextStyle (PDFFont Times_Roman 12) black black FillText 1.0 2.0 0.5 0.5+    textStyle BlueStyle = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0     -instance Style Bold where-    textStyle _ = TextStyle (PDFFont Times_Bold 12) black black FillText 1.0 1.0 1.0 1.0-    styleCode _ = 2 +    sentenceStyle BlueStyle = Just $ \r d -> do+        fillColor $ Rgb 0.6 0.6 1+        strokeColor $ Rgb 0.6 0.6 1+        fillAndStroke r+        d+        return()     -instance Style RedRectStyle where-    sentenceStyle _ = Just $ \r d -> do+    sentenceStyle RedRectStyle = Just $ \r d -> do         strokeColor red         stroke r         d         return()-    textStyle _ = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0-    styleCode _ = 5-        -instance Style DebugStyle where-    wordStyle _ = Just $ \r m d ->+    sentenceStyle Crazy = Just $ \r d -> do+       d+       strokeColor blue+       stroke r+    sentenceStyle _ = Nothing+           +    wordStyle DebugStyle = Just $ \r m d ->       case m of           DrawWord -> d >> return ()           DrawGlue -> d >> stroke r-    textStyle _ = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0-    styleCode _ = 5 -            -crazyWord :: Rectangle -> StyleFunction -> Draw a -> Draw ()-crazyWord r@(Rectangle xa ya xb yb) DrawWord d = do-    fillColor $ Rgb 0.6 1 0.6 -    fill r-    d-    strokeColor $ Rgb 0 0 1-    let m = (ya+yb)/2.0-    stroke $ Line xa m xb m -crazyWord (Rectangle xa ya xb yb) DrawGlue _ = do-    fillColor $ Rgb 0 0 1-    fill (Circle ((xa+xb)/2.0) ((ya+yb)/2.0) ((xb-xa)/2.0))-    -instance Style Crazy where-    sentenceStyle _ = Just $ \r d -> do-        d-        strokeColor blue-        stroke r-    wordStyle _ = Just crazyWord-    textStyle _ = TextStyle (PDFFont Times_Roman 10) red red FillText 1.0 1.0 1.0 1.0-    styleCode _ = 3   -    -    -superCrazy :: SuperCrazy-superCrazy = SuperCrazy (randomRs (0,32) (mkStdGen 0),randomRs (-10.0,10.0) (mkStdGen 10000))--instance Style SuperCrazy where-    styleCode _ = 4-    updateStyle (SuperCrazy (a,b)) = SuperCrazy $ (drop 8 a,tail b)-    textStyle _ = TextStyle (PDFFont Times_Roman 12) black black FillText 1.0 2.0 0.5 0.5-    styleHeight r = (getHeight . textFont . textStyle $ r) + 4.0-    styleDescent r = (getDescent . textFont . textStyle $ r) + 2-    -    wordStyle (SuperCrazy (l,_)) = Just ws +    wordStyle Crazy = Just crazyWord+    wordStyle (SuperCrazy l _) = Just ws       where         ws _ DrawGlue _ = return ()         ws (Rectangle xa ya xb yb) DrawWord drawWord = do@@ -189,22 +209,69 @@               drawWord             return () -instance ParagraphStyle Normal where-    paraStyleCode _ = 1+    wordStyle _ = Nothing     -data CirclePara = CirclePara deriving(Eq)-data BluePara = BluePara PDFFloat deriving(Eq)+    updateStyle (SuperCrazy a b) = SuperCrazy (drop 8 a) (tail b)+    updateStyle a = a+    +    styleHeight r@(SuperCrazy _ _) = (getHeight . textFont . textStyle $ r) + 4.0+    styleHeight r = getHeight . textFont . textStyle $ r+    +    styleDescent r@(SuperCrazy _ _) = (getDescent . textFont . textStyle $ r) + 2+    styleDescent r = getDescent . textFont . textStyle $ r+     -instance ParagraphStyle BluePara where-    paraStyleCode _ = 3+             +crazyWord :: Rectangle -> StyleFunction -> Draw a -> Draw ()+crazyWord r@(Rectangle xa ya xb yb) DrawWord d = do+    fillColor $ Rgb 0.6 1 0.6 +    fill r+    d+    strokeColor $ Rgb 0 0 1+    let m = (ya+yb)/2.0+    stroke $ Line xa m xb m +crazyWord (Rectangle xa ya xb yb) DrawGlue _ = do+    fillColor $ Rgb 0 0 1+    fill (Circle ((xa+xb)/2.0) ((ya+yb)/2.0) ((xb-xa)/2.0))+    +   +    +superCrazy :: MyParaStyles+superCrazy = SuperCrazy (randomRs (0,32) (mkStdGen 0)) (randomRs (-10.0,10.0) (mkStdGen 10000))+    +data MyVertStyles = NormalPara+                  | CirclePara+                  | BluePara !PDFFloat++instance ComparableStyle MyVertStyles where+    isSameStyleAs NormalPara NormalPara = True+    isSameStyleAs CirclePara CirclePara = True+    isSameStyleAs (BluePara _) (BluePara _) = True+    isSameStyleAs _ _ = False+    +    +instance ParagraphStyle MyVertStyles MyParaStyles  where     lineWidth (BluePara a) w nb = (if nb > 3 then w else w-a) - 20.0+    lineWidth CirclePara _ nb = +           let nbLines = 15.0+               r = nbLines * (getHeight . textFont . textStyle $ Normal)+               pasin x' = if x' >= 1.0 then pi/2 else if x' <= -1.0 then (-pi/2) else asin x'+               angle l = pasin $ (nbLines - (fromIntegral l)  ) / nbLines+           in+           abs(2*r*cos (angle nb))+    lineWidth _ w _ = w+                linePosition (BluePara a) _ nb = (if nb > 3 then 0.0 else a) + 10.0-    interline _ = Just $ \r -> do+    linePosition a@(CirclePara) w nb = max 0 ((w - lineWidth a w nb) / 2.0)+    linePosition _ _ _ = 0.0+    +    interline (BluePara _) = Just $ \r -> do         fillColor $ Rgb 0.6 0.6 1         strokeColor $ Rgb 0.6 0.6 1         fillAndStroke r-    paraChange s [] = (s,[])-    paraChange _ (AChar st c _:l) = +    interline _ = Nothing+        +    paragraphChange (BluePara _) (AChar st c _:l) =          let f = PDFFont Helvetica_Bold 45             w' = charWidth f c              charRect = Rectangle 0 (- getDescent f) w' (getHeight f - getDescent f)@@ -223,8 +290,10 @@                     paintWithShading (AxialShading 0 (- getDescent f) w' (getHeight f - getDescent f) (Rgb 1 0 0) (Rgb 0 0 1)) (addShape charRect)         in         (BluePara w', c':l)-    paraChange s l = (s,l)-    paragraphStyle _ = Just $ \(Rectangle xa ya xb yb) b -> do+    +    paragraphChange s l = (s,l)+    +    paragraphStyle (BluePara _) = Just $ \(Rectangle xa ya xb yb) b -> do         let f = Rectangle (xa-3) (ya-3) (xb+3) (yb+3)         fillColor $ Rgb 0.6 0.6 1         fill f@@ -232,46 +301,70 @@         strokeColor red         stroke f         return ()-        -instance ParagraphStyle CirclePara where-    lineWidth _ _ nb = -        let nbLines = 15.0-            r = nbLines * (getHeight . textFont . textStyle $ Normal)-            pasin x' = if x' >= 1.0 then pi/2 else if x' <= -1.0 then (-pi/2) else asin x'-            angle l = pasin $ (nbLines - (fromIntegral l)  ) / nbLines-        in-        abs(2*r*cos (angle nb))-    linePosition a w nb = max 0 ((w - lineWidth a w nb) / 2.0)-    paraStyleCode _ = 2--instance Style BlueStyle where-    sentenceStyle _ = Just $ \r d -> do-        fillColor $ Rgb 0.6 0.6 1-        strokeColor $ Rgb 0.6 0.6 1-        fillAndStroke r-        d-        return()-    textStyle _ = TextStyle (PDFFont Times_Roman 10) black black FillText 1.0 1.0 1.0 1.0-    styleCode _ = 7+    paragraphStyle _ = Nothing     +containerTest :: PDFReference PDFPage -> PDF ()+containerTest p = +    let c = mkContainer 10 300 200 90+        (d,c',r) = fillContainer (defaultVerState NormalParagraph) c . getBoxes NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ testText+        cb = mkContainer 10 210 200 210+        (d',c'',_) = fillContainer (defaultVerState NormalParagraph) cb r+    in drawWithPage p $ do+      d+      d'+      let x = containerX c'+          y = containerY c'+          w = containerWidth c'+          h = containerHeight c'+      strokeColor red+      stroke $ Rectangle x y (x+w) (y-h)+      strokeColor blue+      stroke $ containerContentRectangle c'+      stroke $ containerContentRectangle c''+      +    +standardStyleTest :: TM StandardParagraphStyle StandardStyle ()+standardStyleTest = do+    paragraph $ do+        txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut "+        txt $ "labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris "+        setStyle $ Font (PDFFont Times_Bold 10) black black+        txt $ "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "+        txt $ "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non "+        txt $ "proident, sunt in culpa qui officia deserunt mollit anim id est laborum."+ +testText :: TM StandardParagraphStyle StandardStyle ()      +testText = do+        paragraph $ do+            txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor "+            txt $ "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "+            txt $ "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute "+            txt $ "irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "+            txt $ "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia "+            txt $ "deserunt mollit anim id est laborum."+            +testBreakText :: TM StandardParagraphStyle StandardStyle ()      +testBreakText = do+        paragraph $ do+            txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor "+            txt $ "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "+            txt $ "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute "+            txt $ "irure dolor"+            forceNewLine+            txt $ " in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "+            txt $ "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia "+            txt $ "deserunt mollit anim id est laborum."+                     typesetTest :: Int -> PDFReference PDFPage -> PDF () typesetTest test page = do-    let --symbol = mkDrawBox $ do-        --  applyMatrix $ translate 0 (-4)-        --  strokeColor red-        --  fillColor red-        --  fillAndStroke $ Polygon [ (0,0)-        --                          , (5,5)-        --                          , (10,0)-        --                          , (0,0)-        --                          ]-        --  strokeColor blue-        --  fillColor blue-        --  fillAndStroke $ Polygon [ (0,0)-        --                          , (5,-5)-        --                          , (10,0)-        --                          , (0,0)-        --                          ]+    let simpleText = do+            paragraph $ do+                txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor "+                txt $ "incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "+                txt $ "exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute "+                txt $ "irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "+                txt $ "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia "+                txt $ "deserunt mollit anim id est laborum."         debugText = do             paragraph $ do                 txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor "@@ -296,11 +389,13 @@                 setStyle Crazy                 par                 setStyle Normal+        par :: Para MyParaStyles ()         par = do               txt $ "Lor/-em ip/-sum do/-lor sit am/-et, con/-se/-cte/-tur adi/-pi/-si/-cing el/-it, sed do eius/-mod tem/-por inci/-di/-dunt ut lab/-ore et do/-lo/-re ma/-gna ali/-qua. "               txt $ "Ut en/-im ad mi/-nim ven/-iam, quis no/-strud ex/-er/-ci/-ta/-tion ul/-lam/-co labo/-ris ni/-si ut ali/-quip ex ea com/-mo/-do con/-se/-quat. Duis au/-te ir/-ure "               txt $ "do/-lor in re/-pre/-hen/-der/-it in vo/-lup/-ta/-te ve/-lit es/-se cil/-lum do/-lo/-re eu fu/-giat nul/-la pa/-ria/-tur. Ex/-cep/-teur sint oc/-cae/-cat cu/-pi/-da/-tat non "               txt $ "pro/-id/-ent, sunt in cul/-pa qui of/-fi/-cia de/-se/-runt mol/-lit anim id est la/-bo/-rum."+        normalPar :: Para MyParaStyles ()         normalPar = do               txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "               txt $ "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor "@@ -309,27 +404,27 @@         myText = do               -- Duplicate paragraph several times               paragraph normalPar-              glue 3 0 0+              glue 6 0.33 0               setStyle BlueStyle               setParaStyle (BluePara 0)-              setFirstPassTolerance 5000-              setSecondPassTolerance 10000-              unstyledGlue 3 0 0+              setFirstPassTolerance 500+              --setSecondPassTolerance 10000+              unstyledGlue 6 0.33 0               paragraph $ do                     txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "-                    txt $ "Ut enim ad minim veniam, quis nostrud exercitation ullamco "+                    txt $ "Ut enim ad minim veniam, quis nostrud exercitation ullamco"                     --addBox symbol 10 10 5                     txt $ " laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor "                     txt $ "in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, "                     txt $ "sunt in culpa qui officia deserunt mollit anim id est laborum."-              unstyledGlue 3 0 0+              unstyledGlue 6 0.33 0               setFirstPassTolerance 100               setSecondPassTolerance 200               setStyle Normal-              setParaStyle Normal-              glue 3 0 0+              setParaStyle NormalPara+              glue 6 0.33 0               paragraph normalPar-              glue 3 0 0+              glue 6 0.33 0               paragraph normalPar         --textStart = 300 - getHeight f + getDescent f         maxw = 400@@ -340,30 +435,86 @@       --stroke $ Line 10 textStart (10+maxw) textStart       strokeColor black       case test of+          0 -> do+                strokeColor red+                stroke $ Line 10 300 (10+maxw) 300+                displayFormattedText (Rectangle 10 0 (10+maxw) 300) NormalPara Normal simpleText           1 -> do               strokeColor red-              stroke $ Line 10 300 (10+maxw) 300-              displayFormattedText (Rectangle 10 0 (10+maxw) 300) Normal Normal myText+              stroke $ Line 10 400 (10+maxw) 400+              displayFormattedText (Rectangle 10 0 (10+maxw) 400) NormalPara Normal myText           2 -> do               strokeColor red               stroke $ Line 10 300 (10+maxw) 300-              displayFormattedText (Rectangle 10 0 (10+maxw) 300) Normal Normal debugText+              displayFormattedText (Rectangle 10 0 (10+maxw) 300) NormalPara Normal debugText           3 -> do               let r = (Rectangle 10 200 (10+maxw) 300)               displayFormattedText r CirclePara Normal $ do                    setStyle Normal                    setFirstPassTolerance 5000                    setSecondPassTolerance 5000-                   setLineSkip 0 0 0-                   setBaseLineSkip 0 0 0-                   setLineSkipLimit 0+                   --setLineSkip 0 0 0+                   --setBaseLineSkip 0 0 0+                   --setLineSkipLimit 0                    paragraph $ do                        mapM_ (const normalPar) ([1..3]::[Int])                        txt $ "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "                        txt $ "Ut enim ad minim"               strokeColor red               stroke r-          _ -> displayFormattedText ((Rectangle 0 300 (10+maxw) 300)) Normal Normal myText+          4 -> displayFormattedText ((Rectangle 10 0 (10+maxw) 300)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) standardStyleTest+          5 -> do+              strokeColor red+              stroke $ Rectangle 10 300 (10+maxw) 400+              displayFormattedText ((Rectangle 10 300 (10+maxw) 400)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                  setJustification Centered+                  testText+                  +              strokeColor red+              stroke $ Rectangle 10 200 (10+maxw) 300+              displayFormattedText ((Rectangle 10 200 (10+maxw) 300)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                  setJustification LeftJustification+                  testText+              +              strokeColor red+              stroke $ Rectangle 10 100 (10+maxw) 200+              displayFormattedText ((Rectangle 10 100 (10+maxw) 200)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                  setJustification RightJustification+                  testText+              strokeColor red+              stroke $ Rectangle 10 0 (10+maxw) 100+              drawText $ text (PDFFont Helvetica_Bold 24) 10 100 (toPDFString "Lorem ipsum")+              stroke $ Line 10 120 (10 + textWidth (PDFFont Helvetica_Bold 24) (toPDFString "Lorem ipsum") ) 120 +              displayFormattedText ((Rectangle 10 0 (10+maxw) 100)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                  setJustification LeftJustification+                  paragraph $ do+                      setStyle (Font (PDFFont Helvetica_Bold 24) black black)+                      txt $ "Lorem ipsum"+          6 -> do+                strokeColor red+                stroke $ Rectangle 10 300 (10+maxw) 400+                displayFormattedText ((Rectangle 10 300 (10+maxw) 400)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                    setJustification Centered+                    testBreakText++                strokeColor red+                stroke $ Rectangle 10 200 (10+maxw) 300+                displayFormattedText ((Rectangle 10 200 (10+maxw) 300)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                    setJustification LeftJustification+                    testBreakText++                strokeColor red+                stroke $ Rectangle 10 100 (10+maxw) 200+                displayFormattedText ((Rectangle 10 100 (10+maxw) 200)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                    setJustification RightJustification+                    testBreakText+                    +                strokeColor red+                stroke $ Rectangle 10 0 (10+maxw) 100+                displayFormattedText ((Rectangle 10 0 (10+maxw) 100)) NormalParagraph (Font (PDFFont Times_Roman 10) black black) $ do+                    setJustification FullJustification+                    testBreakText+          _ -> displayFormattedText ((Rectangle 0 300 (10+maxw) 300)) NormalPara Normal myText                                                testAll :: JpegFile -> PDF ()@@ -376,10 +527,26 @@      page2 <- addPage Nothing      newSection (toPDFString "Debug text") Nothing Nothing $ do             typesetTest 2 page2-            +                page3 <- addPage Nothing      newSection (toPDFString "Circle text") Nothing Nothing $ do             typesetTest 3 page3+          +     page3a <- addPage Nothing+     newSection (toPDFString "Standard styles") Nothing Nothing $ do+            typesetTest 4 page3a+            +     page3b <- addPage Nothing+     newSection (toPDFString "Justifications") Nothing Nothing $ do+            typesetTest 5 page3b+            +     page3d <- addPage Nothing+     newSection (toPDFString "New lines") Nothing Nothing $ do+            typesetTest 6 page3d+            +     page3c <- addPage Nothing+     newSection (toPDFString "Container") Nothing Nothing $ do+            containerTest page3c              page4 <- addPage Nothing     newSection (toPDFString "Shapes") Nothing Nothing $ do@@ -416,8 +583,7 @@                 page10 <- addPage Nothing     newSection (toPDFString "Annotations") Nothing Nothing $ do-        drawWithPage page10 $ do-          testAnnotation +          testAnnotation page10                page11 <- addPage Nothing     newSection (toPDFString "Text encoding") Nothing Nothing $ do@@ -432,6 +598,6 @@ main = do     let rect = PDFRect 0 0 600 400     Right jpg <- readJpegFile "logo.jpg"  -    runPdf "demo.pdf" (standardDocInfo { author=toPDFString "alpheccar", compressed = True}) rect $ do+    runPdf "demo.pdf" (standardDocInfo { author=toPDFString "alpheccar", compressed = False}) rect $ do         testAll jpg