{-# LANGUAGE OverloadedStrings, CPP #-}

-- | This module allows you to use the LaTeX /graphicx/ library in order to
--   insert graphics in a document and perform some transformations.
--
--   CTAN page for graphicx: <http://ctan.org/pkg/graphicx>.
module Text.LaTeX.Packages.Graphicx
 ( -- * Graphicx package
   graphicx
   -- * Package options
 , dvips
 , dvipdfm
 , pdftex
   -- * Including graphics
 , IGOption (..)
 , includegraphics
   -- * Transformations
 , rotatebox
 , scalebox
 , reflectbox
 , resizebox
   ) where

import Text.LaTeX.Base.Syntax
import Text.LaTeX.Base.Class
import Text.LaTeX.Base.Render
import Text.LaTeX.Base.Types
--
import Data.Char (toLower)
#if !MIN_VERSION_base(4,8,0)
import Data.Functor ((<$>))
#endif

-- | The 'graphicx' package.
--
-- > usepackage [] graphicx
graphicx :: PackageName
graphicx :: PackageName
graphicx = PackageName
"graphicx"

-- Package options

-- | Package option of the 'graphicx' package.
dvips, dvipdfm, pdftex :: LaTeXC l => l
dvips :: l
dvips = l
"dvips"
dvipdfm :: l
dvipdfm = l
"dvipdfm"
pdftex :: l
pdftex = l
"pdftex"

-- Including graphics

-- | Include Graphics Option. These options can be passed as arguments to the 'includegraphics' function.
data IGOption =
   IGWidth Measure -- ^ Specify the preferred width of the imported image.
 | IGHeight Measure -- ^ Specify the preferred height of the imported image.
 | KeepAspectRatio Bool -- ^ When 'True', it will scale the image according to both 'IGWidth' and 'IGHeight'
                        -- , but will not distort the image, so that neither 'IGWidth' nor 'IGHeight' are exceeded.
 | IGScale Float -- ^ Scales the image by the desired scale factor.
 | IGAngle Int -- ^ Rotate the image by given degrees.
 | IGTrim Measure Measure Measure Measure -- ^ This option will crop the imported image. Arguments are from-left
                                          -- , from-bottom, from-right and from-top respectively.
 | IGClip Bool -- ^ For the 'IGTrim' option to work, you must set 'IGClip' to 'True'.
 | IGPage Int -- ^ If the image file is a pdf file with multiple pages,
              --   this parameter allows you to use a different page than the first.
   deriving Int -> IGOption -> ShowS
[IGOption] -> ShowS
IGOption -> PackageName
(Int -> IGOption -> ShowS)
-> (IGOption -> PackageName)
-> ([IGOption] -> ShowS)
-> Show IGOption
forall a.
(Int -> a -> ShowS)
-> (a -> PackageName) -> ([a] -> ShowS) -> Show a
showList :: [IGOption] -> ShowS
$cshowList :: [IGOption] -> ShowS
show :: IGOption -> PackageName
$cshow :: IGOption -> PackageName
showsPrec :: Int -> IGOption -> ShowS
$cshowsPrec :: Int -> IGOption -> ShowS
Show

instance Render IGOption where
 render :: IGOption -> Text
render (IGWidth Measure
m) = Text
"width=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Measure -> Text
forall a. Render a => a -> Text
render Measure
m
 render (IGHeight Measure
m) = Text
"height=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Measure -> Text
forall a. Render a => a -> Text
render Measure
m
 render (KeepAspectRatio Bool
b) = Text
"keepaspectratio=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PackageName -> Text
forall a. IsString a => PackageName -> a
fromString (Char -> Char
toLower (Char -> Char) -> ShowS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> PackageName
forall a. Show a => a -> PackageName
show Bool
b)
 render (IGScale Float
r) = Text
"scale=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Float -> Text
forall a. Render a => a -> Text
render Float
r
 render (IGAngle Int
a) = Text
"angle=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Render a => a -> Text
render Int
a
 render (IGTrim Measure
l Measure
b Measure
r Measure
t) = Text
"trim=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Char -> [Measure] -> Text
forall a. Render a => Char -> [a] -> Text
renderChars Char
' ' [Measure
l,Measure
b,Measure
r,Measure
t]
 render (IGClip Bool
b) = Text
"clip=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> PackageName -> Text
forall a. IsString a => PackageName -> a
fromString (Char -> Char
toLower (Char -> Char) -> ShowS
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool -> PackageName
forall a. Show a => a -> PackageName
show Bool
b)
 render (IGPage Int
p) = Text
"page=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Render a => a -> Text
render Int
p

-- | Include an image in the document.
includegraphics :: LaTeXC l =>
                  [IGOption] -- ^ Options
                -> FilePath  -- ^ Image file
                -> l
includegraphics :: [IGOption] -> PackageName -> l
includegraphics [IGOption]
opts PackageName
fp = LaTeX -> l
forall l. LaTeXC l => LaTeX -> l
fromLaTeX (LaTeX -> l) -> LaTeX -> l
forall a b. (a -> b) -> a -> b
$ PackageName -> [TeXArg] -> LaTeX
TeXComm PackageName
"includegraphics"
 [ [LaTeX] -> TeXArg
MOptArg ([LaTeX] -> TeXArg) -> [LaTeX] -> TeXArg
forall a b. (a -> b) -> a -> b
$ (IGOption -> LaTeX) -> [IGOption] -> [LaTeX]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap IGOption -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex [IGOption]
opts, LaTeX -> TeXArg
FixArg (LaTeX -> TeXArg) -> LaTeX -> TeXArg
forall a b. (a -> b) -> a -> b
$ Text -> LaTeX
TeXRaw (Text -> LaTeX) -> Text -> LaTeX
forall a b. (a -> b) -> a -> b
$ PackageName -> Text
forall a. IsString a => PackageName -> a
fromString PackageName
fp ]

-- | Rotate the content by the given angle in degrees.
rotatebox :: LaTeXC l => Float -> l -> l
rotatebox :: Float -> l -> l
rotatebox Float
a = (LaTeX -> LaTeX) -> l -> l
forall l. LaTeXC l => (LaTeX -> LaTeX) -> l -> l
liftL ((LaTeX -> LaTeX) -> l -> l) -> (LaTeX -> LaTeX) -> l -> l
forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> PackageName -> [TeXArg] -> LaTeX
TeXComm PackageName
"rotatebox" [LaTeX -> TeXArg
FixArg (LaTeX -> TeXArg) -> LaTeX -> TeXArg
forall a b. (a -> b) -> a -> b
$ Float -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex Float
a , LaTeX -> TeXArg
FixArg LaTeX
l]

-- | Scale the content by the given factor. If only the horizontal scale is supplied,
--   the vertical scaling will be the same.
scalebox :: LaTeXC l =>
     Float       -- ^ Horizontal scale.
  -> Maybe Float -- ^ Vertical scale.
  -> l
  -> l
scalebox :: Float -> Maybe Float -> l -> l
scalebox Float
h Maybe Float
mv = (LaTeX -> LaTeX) -> l -> l
forall l. LaTeXC l => (LaTeX -> LaTeX) -> l -> l
liftL ((LaTeX -> LaTeX) -> l -> l) -> (LaTeX -> LaTeX) -> l -> l
forall a b. (a -> b) -> a -> b
$ \LaTeX
l ->
  PackageName -> [TeXArg] -> LaTeX
TeXComm PackageName
"rotatebox" ([TeXArg] -> LaTeX) -> [TeXArg] -> LaTeX
forall a b. (a -> b) -> a -> b
$ [LaTeX -> TeXArg
FixArg (LaTeX -> TeXArg) -> LaTeX -> TeXArg
forall a b. (a -> b) -> a -> b
$ Float -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex Float
h]
                     [TeXArg] -> [TeXArg] -> [TeXArg]
forall a. [a] -> [a] -> [a]
++  [TeXArg] -> (Float -> [TeXArg]) -> Maybe Float -> [TeXArg]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ((TeXArg -> [TeXArg] -> [TeXArg]
forall a. a -> [a] -> [a]
:[]) (TeXArg -> [TeXArg]) -> (Float -> TeXArg) -> Float -> [TeXArg]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LaTeX -> TeXArg
OptArg (LaTeX -> TeXArg) -> (Float -> LaTeX) -> Float -> TeXArg
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex) Maybe Float
mv
                     [TeXArg] -> [TeXArg] -> [TeXArg]
forall a. [a] -> [a] -> [a]
++ [LaTeX -> TeXArg
FixArg LaTeX
l]

-- | Reflect horizontally the content.
reflectbox :: LaTeXC l => l -> l
reflectbox :: l -> l
reflectbox = (LaTeX -> LaTeX) -> l -> l
forall l. LaTeXC l => (LaTeX -> LaTeX) -> l -> l
liftL ((LaTeX -> LaTeX) -> l -> l) -> (LaTeX -> LaTeX) -> l -> l
forall a b. (a -> b) -> a -> b
$ \LaTeX
l -> PackageName -> [TeXArg] -> LaTeX
TeXComm PackageName
"reflectbox" [LaTeX -> TeXArg
FixArg LaTeX
l]

-- | Resize the content to match the given dimensions.
resizebox :: LaTeXC l =>
     Measure -- ^ Horizontal size.
  -> Measure -- ^ Vertical size.
  -> l
  -> l
resizebox :: Measure -> Measure -> l -> l
resizebox Measure
h Measure
v = (LaTeX -> LaTeX) -> l -> l
forall l. LaTeXC l => (LaTeX -> LaTeX) -> l -> l
liftL ((LaTeX -> LaTeX) -> l -> l) -> (LaTeX -> LaTeX) -> l -> l
forall a b. (a -> b) -> a -> b
$ \LaTeX
l ->
  PackageName -> [TeXArg] -> LaTeX
TeXComm PackageName
"resizebox" [LaTeX -> TeXArg
FixArg (LaTeX -> TeXArg) -> LaTeX -> TeXArg
forall a b. (a -> b) -> a -> b
$ Measure -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex Measure
h,LaTeX -> TeXArg
FixArg (LaTeX -> TeXArg) -> LaTeX -> TeXArg
forall a b. (a -> b) -> a -> b
$ Measure -> LaTeX
forall a l. (Render a, LaTeXC l) => a -> l
rendertex Measure
v,LaTeX -> TeXArg
FixArg LaTeX
l]