{-# LANGUAGE CPP #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveFunctor #-}
---------------------------------------------------------
-- |
-- Copyright   : (c) 2006-2016, alpheccar.org
-- License     : BSD-style
--
-- Maintainer  : misc@NOSPAMalpheccar.org
-- Stability   : experimental
-- Portability : portable
--
-- PDF Text
---------------------------------------------------------
{-# LANGUAGE FlexibleContexts #-}
module Graphics.PDF.Text(
   -- * Text
   -- ** Types
     PDFFont(..)
   , FontName(..)
   , TextMode(..)
   , PDFText
   , UnscaledUnit
   -- ** Functions
   , drawText
   , text
   , startNewLine
   , displayGlyphs
   , displayText
   , textStart
   , setFont
   , leading
   , charSpace
   , wordSpace
   , textScale
   , renderMode
   , rise
   , setTextMatrix
   , textWidth
   , pdfGlyph
   , glyph
 ) where

import Graphics.PDF.LowLevel.Types
import Graphics.PDF.Draw
import Control.Monad.State
import Graphics.PDF.Resources
import Control.Monad.Writer
import qualified Data.Set as Set
import Data.List(foldl')
import Data.Binary.Builder(Builder)
import Graphics.PDF.LowLevel.Serializer
import qualified Data.ByteString as S
import qualified Data.Text as T
import Graphics.PDF.Fonts.Font
import Graphics.PDF.Fonts.StandardFont


glyphStreamWidth :: PDFFont
                 -> PDFGlyph 
                 -> PDFFloat
glyphStreamWidth :: PDFFont -> PDFGlyph -> PDFFloat
glyphStreamWidth (PDFFont AnyFont
f Int
s) (PDFGlyph ByteString
t) = 
 let w :: PDFFloat
w = (PDFFloat -> Word8 -> PDFFloat) -> PDFFloat -> [Word8] -> PDFFloat
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\PDFFloat
a Word8
b -> PDFFloat
a PDFFloat -> PDFFloat -> PDFFloat
forall a. Num a => a -> a -> a
+ AnyFont -> Int -> GlyphCode -> PDFFloat
forall f. IsFont f => f -> Int -> GlyphCode -> PDFFloat
glyphWidth AnyFont
f Int
s (Word8 -> GlyphCode
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b)) PDFFloat
0 ([Word8] -> PDFFloat)
-> (ByteString -> [Word8]) -> ByteString -> PDFFloat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [Word8]
S.unpack (ByteString -> PDFFloat) -> ByteString -> PDFFloat
forall a b. (a -> b) -> a -> b
$ ByteString
t
 in
  PDFFloat
w PDFFloat -> PDFFloat -> PDFFloat
forall a. Num a => a -> a -> a
+ ((PDFFloat -> (GlyphCode, GlyphCode) -> PDFFloat)
-> PDFFloat -> [(GlyphCode, GlyphCode)] -> PDFFloat
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\PDFFloat
a (GlyphCode
x,GlyphCode
y) -> PDFFloat
a PDFFloat -> PDFFloat -> PDFFloat
forall a. Num a => a -> a -> a
+ AnyFont -> Int -> GlyphCode -> GlyphCode -> PDFFloat
forall f.
IsFont f =>
f -> Int -> GlyphCode -> GlyphCode -> PDFFloat
getKern AnyFont
f Int
s GlyphCode
x GlyphCode
y) PDFFloat
0 ([(GlyphCode, GlyphCode)] -> PDFFloat)
-> [(GlyphCode, GlyphCode)] -> PDFFloat
forall a b. (a -> b) -> a -> b
$ [(Word8 -> GlyphCode
GlyphCode Word8
ca,Word8 -> GlyphCode
GlyphCode Word8
cb) | (Word8
ca,Word8
cb) <- ByteString -> ByteString -> [(Word8, Word8)]
S.zip ByteString
t (HasCallStack => ByteString -> ByteString
ByteString -> ByteString
S.tail ByteString
t)])

textWidth :: PDFFont -> T.Text -> PDFFloat
textWidth :: PDFFont -> Text -> PDFFloat
textWidth PDFFont
f Text
t = PDFFont -> PDFGlyph -> PDFFloat
glyphStreamWidth PDFFont
f (PDFGlyph -> PDFFloat) -> (Text -> PDFGlyph) -> Text -> PDFFloat
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PDFFont -> Text -> PDFGlyph
pdfGlyph PDFFont
f (Text -> PDFFloat) -> Text -> PDFFloat
forall a b. (a -> b) -> a -> b
$ Text
t
      
pdfGlyph :: PDFFont
         -> T.Text 
         -> PDFGlyph 
pdfGlyph :: PDFFont -> Text -> PDFGlyph
pdfGlyph (PDFFont AnyFont
f Int
_) Text
t = ByteString -> PDFGlyph
PDFGlyph (ByteString -> PDFGlyph)
-> (Text -> ByteString) -> Text -> PDFGlyph
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> ByteString
S.pack ([Word8] -> ByteString) -> (Text -> [Word8]) -> Text -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Word8) -> String -> [Word8]
forall a b. (a -> b) -> [a] -> [b]
map (GlyphCode -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (GlyphCode -> Word8) -> (Char -> GlyphCode) -> Char -> Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AnyFont -> Char -> GlyphCode
forall f. IsFont f => f -> Char -> GlyphCode
charGlyph AnyFont
f) (String -> [Word8]) -> (Text -> String) -> Text -> [Word8]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> PDFGlyph) -> Text -> PDFGlyph
forall a b. (a -> b) -> a -> b
$ Text
t 


type FontState = (Set.Set AnyFont)

data TextParameter = TextParameter { TextParameter -> PDFFloat
tc :: !PDFFloat
                                   , TextParameter -> PDFFloat
tw :: !PDFFloat
                                   , TextParameter -> PDFFloat
tz :: !PDFFloat
                                   , TextParameter -> PDFFloat
tl :: !PDFFloat
                                   , TextParameter -> PDFFloat
ts :: !PDFFloat
                                   , TextParameter -> FontState
fontState :: FontState
                                   , TextParameter -> Maybe PDFFont
currentFont :: Maybe PDFFont
                                   }
defaultParameters ::  TextParameter
defaultParameters :: TextParameter
defaultParameters = PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> PDFFloat
-> FontState
-> Maybe PDFFont
-> TextParameter
TextParameter PDFFloat
0 PDFFloat
0 PDFFloat
100 PDFFloat
0 PDFFloat
0 (FontState
forall a. Set a
Set.empty) Maybe PDFFont
forall a. Maybe a
Nothing

     
-- | The text monad 
newtype PDFText a = PDFText {forall a. PDFText a -> WriterT Builder (State TextParameter) a
unText :: WriterT Builder (State TextParameter) a}          
#ifndef __HADDOCK__                    
  deriving(Applicative PDFText
Applicative PDFText =>
(forall a b. PDFText a -> (a -> PDFText b) -> PDFText b)
-> (forall a b. PDFText a -> PDFText b -> PDFText b)
-> (forall a. a -> PDFText a)
-> Monad PDFText
forall a. a -> PDFText a
forall a b. PDFText a -> PDFText b -> PDFText b
forall a b. PDFText a -> (a -> PDFText b) -> PDFText b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. PDFText a -> (a -> PDFText b) -> PDFText b
>>= :: forall a b. PDFText a -> (a -> PDFText b) -> PDFText b
$c>> :: forall a b. PDFText a -> PDFText b -> PDFText b
>> :: forall a b. PDFText a -> PDFText b -> PDFText b
$creturn :: forall a. a -> PDFText a
return :: forall a. a -> PDFText a
Monad,Functor PDFText
Functor PDFText =>
(forall a. a -> PDFText a)
-> (forall a b. PDFText (a -> b) -> PDFText a -> PDFText b)
-> (forall a b c.
    (a -> b -> c) -> PDFText a -> PDFText b -> PDFText c)
-> (forall a b. PDFText a -> PDFText b -> PDFText b)
-> (forall a b. PDFText a -> PDFText b -> PDFText a)
-> Applicative PDFText
forall a. a -> PDFText a
forall a b. PDFText a -> PDFText b -> PDFText a
forall a b. PDFText a -> PDFText b -> PDFText b
forall a b. PDFText (a -> b) -> PDFText a -> PDFText b
forall a b c. (a -> b -> c) -> PDFText a -> PDFText b -> PDFText c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> PDFText a
pure :: forall a. a -> PDFText a
$c<*> :: forall a b. PDFText (a -> b) -> PDFText a -> PDFText b
<*> :: forall a b. PDFText (a -> b) -> PDFText a -> PDFText b
$cliftA2 :: forall a b c. (a -> b -> c) -> PDFText a -> PDFText b -> PDFText c
liftA2 :: forall a b c. (a -> b -> c) -> PDFText a -> PDFText b -> PDFText c
$c*> :: forall a b. PDFText a -> PDFText b -> PDFText b
*> :: forall a b. PDFText a -> PDFText b -> PDFText b
$c<* :: forall a b. PDFText a -> PDFText b -> PDFText a
<* :: forall a b. PDFText a -> PDFText b -> PDFText a
Applicative,(forall a b. (a -> b) -> PDFText a -> PDFText b)
-> (forall a b. a -> PDFText b -> PDFText a) -> Functor PDFText
forall a b. a -> PDFText b -> PDFText a
forall a b. (a -> b) -> PDFText a -> PDFText b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> PDFText a -> PDFText b
fmap :: forall a b. (a -> b) -> PDFText a -> PDFText b
$c<$ :: forall a b. a -> PDFText b -> PDFText a
<$ :: forall a b. a -> PDFText b -> PDFText a
Functor,MonadWriter Builder,MonadState TextParameter)
#else
instance Monad PDFText
instance Functor PDFText
instance MonadWriter Builder PDFText
instance MonadState TextParameter PDFText
#endif
    
instance MonadPath PDFText

-- | Unscaled unit (not scaled by the font size)
type UnscaledUnit = PDFFloat  

-- | Rendering mode for text display
data TextMode = FillText
              | StrokeText
              | FillAndStrokeText
              | InvisibleText
              | FillTextAndAddToClip
              | StrokeTextAndAddToClip
              | FillAndStrokeTextAndAddToClip
              | AddToClip
              deriving(TextMode -> TextMode -> Bool
(TextMode -> TextMode -> Bool)
-> (TextMode -> TextMode -> Bool) -> Eq TextMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TextMode -> TextMode -> Bool
== :: TextMode -> TextMode -> Bool
$c/= :: TextMode -> TextMode -> Bool
/= :: TextMode -> TextMode -> Bool
Eq,Eq TextMode
Eq TextMode =>
(TextMode -> TextMode -> Ordering)
-> (TextMode -> TextMode -> Bool)
-> (TextMode -> TextMode -> Bool)
-> (TextMode -> TextMode -> Bool)
-> (TextMode -> TextMode -> Bool)
-> (TextMode -> TextMode -> TextMode)
-> (TextMode -> TextMode -> TextMode)
-> Ord TextMode
TextMode -> TextMode -> Bool
TextMode -> TextMode -> Ordering
TextMode -> TextMode -> TextMode
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: TextMode -> TextMode -> Ordering
compare :: TextMode -> TextMode -> Ordering
$c< :: TextMode -> TextMode -> Bool
< :: TextMode -> TextMode -> Bool
$c<= :: TextMode -> TextMode -> Bool
<= :: TextMode -> TextMode -> Bool
$c> :: TextMode -> TextMode -> Bool
> :: TextMode -> TextMode -> Bool
$c>= :: TextMode -> TextMode -> Bool
>= :: TextMode -> TextMode -> Bool
$cmax :: TextMode -> TextMode -> TextMode
max :: TextMode -> TextMode -> TextMode
$cmin :: TextMode -> TextMode -> TextMode
min :: TextMode -> TextMode -> TextMode
Ord,Int -> TextMode
TextMode -> Int
TextMode -> [TextMode]
TextMode -> TextMode
TextMode -> TextMode -> [TextMode]
TextMode -> TextMode -> TextMode -> [TextMode]
(TextMode -> TextMode)
-> (TextMode -> TextMode)
-> (Int -> TextMode)
-> (TextMode -> Int)
-> (TextMode -> [TextMode])
-> (TextMode -> TextMode -> [TextMode])
-> (TextMode -> TextMode -> [TextMode])
-> (TextMode -> TextMode -> TextMode -> [TextMode])
-> Enum TextMode
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: TextMode -> TextMode
succ :: TextMode -> TextMode
$cpred :: TextMode -> TextMode
pred :: TextMode -> TextMode
$ctoEnum :: Int -> TextMode
toEnum :: Int -> TextMode
$cfromEnum :: TextMode -> Int
fromEnum :: TextMode -> Int
$cenumFrom :: TextMode -> [TextMode]
enumFrom :: TextMode -> [TextMode]
$cenumFromThen :: TextMode -> TextMode -> [TextMode]
enumFromThen :: TextMode -> TextMode -> [TextMode]
$cenumFromTo :: TextMode -> TextMode -> [TextMode]
enumFromTo :: TextMode -> TextMode -> [TextMode]
$cenumFromThenTo :: TextMode -> TextMode -> TextMode -> [TextMode]
enumFromThenTo :: TextMode -> TextMode -> TextMode -> [TextMode]
Enum)

-- | Select a font to use
setFont :: PDFFont -> PDFText ()
setFont :: PDFFont -> PDFText ()
setFont f :: PDFFont
f@(PDFFont AnyFont
n Int
size) = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {fontState = Set.insert n (fontState s), currentFont = Just f})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$ [ String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
"\n/" 
                    , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize (AnyFont -> String
forall f. IsFont f => f -> String
name AnyFont
n)
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , Int -> Builder
forall a. PdfObject a => a -> Builder
toPDF Int
size
                    , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tf"
                    ]
                    
  
-- | Draw a text in the draw monad
drawText :: PDFText a
         -> Draw a
drawText :: forall a. PDFText a -> Draw a
drawText PDFText a
t = do
    let ((a
a,Builder
w),TextParameter
s) = (State TextParameter (a, Builder)
-> TextParameter -> ((a, Builder), TextParameter)
forall s a. State s a -> s -> (a, s)
runState (State TextParameter (a, Builder)
 -> TextParameter -> ((a, Builder), TextParameter))
-> (PDFText a -> State TextParameter (a, Builder))
-> PDFText a
-> TextParameter
-> ((a, Builder), TextParameter)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WriterT Builder (State TextParameter) a
-> State TextParameter (a, Builder)
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT (WriterT Builder (State TextParameter) a
 -> State TextParameter (a, Builder))
-> (PDFText a -> WriterT Builder (State TextParameter) a)
-> PDFText a
-> State TextParameter (a, Builder)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PDFText a -> WriterT Builder (State TextParameter) a
forall a. PDFText a -> WriterT Builder (State TextParameter) a
unText (PDFText a -> TextParameter -> ((a, Builder), TextParameter))
-> PDFText a -> TextParameter -> ((a, Builder), TextParameter)
forall a b. (a -> b) -> a -> b
$ PDFText a
t) TextParameter
defaultParameters
    (AnyFont -> Draw ()) -> [AnyFont] -> Draw ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ AnyFont -> Draw ()
forall {m :: * -> *} {a}.
(MonadState DrawState m, IsFont a, PdfResourceObject a) =>
a -> m ()
addFontRsrc (FontState -> [AnyFont]
forall a. Set a -> [a]
Set.elems (TextParameter -> FontState
fontState TextParameter
s))
    Builder -> Draw ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> Draw ()) -> (String -> Builder) -> String -> Draw ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
forall s a. SerializeValue s a => a -> s
serialize (String -> Draw ()) -> String -> Draw ()
forall a b. (a -> b) -> a -> b
$ String
"\nBT"
    Builder -> Draw ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
w
    Builder -> Draw ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> Draw ()) -> (String -> Builder) -> String -> Draw ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
forall s a. SerializeValue s a => a -> s
serialize (String -> Draw ()) -> String -> Draw ()
forall a b. (a -> b) -> a -> b
$ String
"\nET"
    a -> Draw a
forall a. a -> Draw a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
 where
   addFontRsrc :: a -> m ()
addFontRsrc a
font = (DrawState -> DrawState) -> m ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((DrawState -> DrawState) -> m ())
-> (DrawState -> DrawState) -> m ()
forall a b. (a -> b) -> a -> b
$ \DrawState
s ->
       DrawState
s { rsrc = addResource (PDFName "Font") (PDFName (name font)) (toRsrc font) (rsrc s)}
   
-- | Set position for the text beginning
textStart :: PDFFloat
          -> PDFFloat
          -> PDFText ()
textStart :: PDFFloat -> PDFFloat -> PDFText ()
textStart PDFFloat
x PDFFloat
y = Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> ([Builder] -> Builder) -> [Builder] -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat  ([Builder] -> PDFText ()) -> [Builder] -> PDFText ()
forall a b. (a -> b) -> a -> b
$ [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                                  , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
x
                                  , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                                  , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
y
                                  , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Td"
                                  ]
 --writeCmd $ "\n" ++ (show x) ++ " " ++ (show y) ++ " Td"         


glyph :: GlyphCode -> PDFGlyph 
glyph :: GlyphCode -> PDFGlyph
glyph GlyphCode
c = ByteString -> PDFGlyph
PDFGlyph (ByteString -> PDFGlyph)
-> (Word8 -> ByteString) -> Word8 -> PDFGlyph
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> ByteString
S.singleton (Word8 -> PDFGlyph) -> Word8 -> PDFGlyph
forall a b. (a -> b) -> a -> b
$ (GlyphCode -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral GlyphCode
c)

-- | Display glyphs
displayGlyphs :: PDFGlyph
              -> PDFText ()
displayGlyphs :: PDFGlyph -> PDFText ()
displayGlyphs PDFGlyph
t = do
    Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ()) -> Builder -> PDFText ()
forall a b. (a -> b) -> a -> b
$ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
    Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> (PDFGlyph -> Builder) -> PDFGlyph -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PDFGlyph -> Builder
forall a. PdfObject a => a -> Builder
toPDF (PDFGlyph -> PDFText ()) -> PDFGlyph -> PDFText ()
forall a b. (a -> b) -> a -> b
$ PDFGlyph
t
    Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> (String -> Builder) -> String -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
forall s a. SerializeValue s a => a -> s
serialize (String -> PDFText ()) -> String -> PDFText ()
forall a b. (a -> b) -> a -> b
$ String
" Tj"

-- | Display text
displayText :: T.Text
            -> PDFText ()
displayText :: Text -> PDFText ()
displayText Text
t = do
    Maybe PDFFont
f <- (TextParameter -> Maybe PDFFont) -> PDFText (Maybe PDFFont)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets TextParameter -> Maybe PDFFont
currentFont
    case Maybe PDFFont
f of 
      Maybe PDFFont
Nothing -> () -> PDFText ()
forall a. a -> PDFText a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      Just PDFFont
aFont -> do
         let g :: PDFGlyph
g = PDFFont -> Text -> PDFGlyph
pdfGlyph PDFFont
aFont Text
t
         PDFGlyph -> PDFText ()
displayGlyphs PDFGlyph
g


--    f <- gets currentFont
--    let rt = ripText f t
--    tell . serialize $ '\n'
--    tell lbracket
--    mapM_ displayGlyphs rt
--    tell rbracket
--    tell $ serialize " TJ"
-- where
-- 	displayGlyphs (w,c) = do
-- 		tell $ toPDF (toPDFString $ c:[])
-- 		tell bspace
-- 		tell . toPDF $ w
-- 		tell bspace

 
-- | Start a new line (leading value must have been set)
startNewLine :: PDFText ()
startNewLine :: PDFText ()
startNewLine = Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> (String -> Builder) -> String -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Builder
forall s a. SerializeValue s a => a -> s
serialize (String -> PDFText ()) -> String -> PDFText ()
forall a b. (a -> b) -> a -> b
$ String
"\nT*"    

-- | Set leading value
leading :: UnscaledUnit -> PDFText ()
leading :: PDFFloat -> PDFText ()
leading PDFFloat
v = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {tl = v})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$  [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
v
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" TL"
                      ]

-- | Set the additional char space
charSpace :: UnscaledUnit -> PDFText ()
charSpace :: PDFFloat -> PDFText ()
charSpace PDFFloat
v = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {tc = v})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat  ([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$ [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
v
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tc"
                      ]

-- | Set the additional word space
wordSpace :: UnscaledUnit -> PDFText ()
wordSpace :: PDFFloat -> PDFText ()
wordSpace PDFFloat
v = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {tw = v})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$ [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
v
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tw"
                      ]

-- | Set scaling factor for text
textScale :: PDFFloat -> PDFText ()
textScale :: PDFFloat -> PDFText ()
textScale PDFFloat
v = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {tz = v})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat  ([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$ [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
v
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tz"
                      ]

-- | Choose the text rendering mode
renderMode :: TextMode -> PDFText ()
renderMode :: TextMode -> PDFText ()
renderMode TextMode
v = 
    Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> ([Builder] -> Builder) -> [Builder] -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> PDFText ()) -> [Builder] -> PDFText ()
forall a b. (a -> b) -> a -> b
$  [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , Int -> Builder
forall a. PdfObject a => a -> Builder
toPDF (TextMode -> Int
forall a. Enum a => a -> Int
fromEnum TextMode
v)
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tr"
                      ]

-- | Set the rise value
rise :: UnscaledUnit -> PDFText ()
rise :: PDFFloat -> PDFText ()
rise PDFFloat
v = WriterT Builder (State TextParameter) () -> PDFText ()
forall a. WriterT Builder (State TextParameter) a -> PDFText a
PDFText (WriterT Builder (State TextParameter) () -> PDFText ())
-> WriterT Builder (State TextParameter) () -> PDFText ()
forall a b. (a -> b) -> a -> b
$ do
    State TextParameter () -> WriterT Builder (State TextParameter) ()
forall (m :: * -> *) a. Monad m => m a -> WriterT Builder m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((TextParameter -> TextParameter) -> State TextParameter ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modifyStrict ((TextParameter -> TextParameter) -> State TextParameter ())
-> (TextParameter -> TextParameter) -> State TextParameter ()
forall a b. (a -> b) -> a -> b
$ \TextParameter
s -> TextParameter
s {ts = v})
    Builder -> WriterT Builder (State TextParameter) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> WriterT Builder (State TextParameter) ())
-> ([Builder] -> Builder)
-> [Builder]
-> WriterT Builder (State TextParameter) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> WriterT Builder (State TextParameter) ())
-> [Builder] -> WriterT Builder (State TextParameter) ()
forall a b. (a -> b) -> a -> b
$  [ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                      , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
v
                      , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Ts"
                      ]

-- | Set the text transformation matrix
setTextMatrix :: Matrix -> PDFText()
setTextMatrix :: Matrix -> PDFText ()
setTextMatrix (Matrix PDFFloat
a PDFFloat
b PDFFloat
c PDFFloat
d PDFFloat
e PDFFloat
f) = 
    Builder -> PDFText ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> PDFText ())
-> ([Builder] -> Builder) -> [Builder] -> PDFText ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> PDFText ()) -> [Builder] -> PDFText ()
forall a b. (a -> b) -> a -> b
$[ Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
'\n'
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
a
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
b
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
c
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
d
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
e
                    , Char -> Builder
forall s a. SerializeValue s a => a -> s
serialize Char
' '
                    , PDFFloat -> Builder
forall a. PdfObject a => a -> Builder
toPDF PDFFloat
f
                    , String -> Builder
forall s a. SerializeValue s a => a -> s
serialize String
" Tm"
                    ]
    
-- | Utility function to quickly display one line of text
text :: PDFFont
     -> PDFFloat
     -> PDFFloat
     -> T.Text
     -> PDFText ()
text :: PDFFont -> PDFFloat -> PDFFloat -> Text -> PDFText ()
text PDFFont
f PDFFloat
x PDFFloat
y Text
t = do
    PDFFont -> PDFText ()
setFont PDFFont
f
    let g :: PDFGlyph
g = PDFFont -> Text -> PDFGlyph
pdfGlyph PDFFont
f Text
t
    PDFFloat -> PDFFloat -> PDFText ()
textStart PDFFloat
x PDFFloat
y
    PDFGlyph -> PDFText ()
displayGlyphs PDFGlyph
g