module Language.LaTeX.Builder.Graphics ( -- * The main command includegraphics -- * The options ,IncludeGraphicsOpts(..) -- * The locations ,Loc, c, center, t, top, l, left, r, right, b, bottom, ba, baseline, tr, topRight ,tl, topLeft, bl, bottomLeft, br, bottomRight, baselineLeft, baselineRight -- * The package name , pkg) where import Language.LaTeX.Types hiding (Loc) import qualified Language.LaTeX.Builder.Internal as BI import Language.LaTeX.Builder.MonoidUtils ((⊕)) import Control.Arrow ((***)) import Data.Maybe import Data.String data Loc = C -- ^ Center | T -- ^ Top | L -- ^ Left | R -- ^ Right | B -- ^ Bottom | Ba -- ^ Baseline | TR -- ^ Top right | TL -- ^ Top left | BL -- ^ Bottom left (default) | BR -- ^ Bottom right | BaL -- ^ Baseline left | BaR -- ^ Baseline right deriving (Eq) c, center, t, top, l, left, r, right, b, bottom, ba, baseline, tr, topRight, tl, topLeft, bl, bottomLeft, br, bottomRight, baselineLeft, baselineRight :: Loc c = C center = C t = T top = T l = L left = L r = R right = R b = B bottom = B ba = Ba baseline = Ba tr = TR topRight = TR tl = TL topLeft = TL bl = BL bottomLeft = BL br = BR bottomRight = BR baselineLeft = BaL baselineRight = BaR showGrLoc :: Loc -> String showGrLoc loc = case loc of C -> "c" T -> "t" L -> "l" R -> "r" B -> "b" Ba -> "B" TR -> "tr" TL -> "tl" BL -> "bl" BR -> "br" BaL -> "Bl" BaR -> "Br" data IncludeGraphicsOpts = IncludeGraphicsOpts { scale :: Rational -- ^ the number by which the figure size should be magnified over its natural size , width :: Maybe LatexLength -- ^ specifies the width to which the figure should be scaled to; if height not given, -- it is scaled with the same factor as the width , height :: Maybe LatexLength -- ^ specifies the height to which the figure should be scaled to; if width is not given, -- it is scaled with the same factor as the height , totalheight :: Maybe LatexLength -- ^ like height but specifies the height plus depth of the figure; should always be used -- in place of height if the figure has been otated , keepaspectratio :: Bool -- ^ if both height and width are specified, this flag ensures that the original height/width -- ratio remains unchanged; the figure will not exceed either of the given dimensions , angle :: Rational -- ^ the angle by which the figure is to be rotated counterclockwise, in degrees; any height -- or width specifications coming before this key are also rotated, so that the height becomes -- the width, while the width becomes either the height (positive angle) or depth (negative angle) , origin :: Loc -- ^ determines the point about which the rotation occurs; default is bl for bottom left -- corner; also possible are c for center, t for top, r for right, and B for baseline; -- any sensible combination, such as tr, is allowed , draft :: Bool -- ^ like the draft package option but applied to the one graphics file; the figure is not -- imported, but rather a framed box of the correct size is printed containing the name of -- the file , clip :: Bool -- ^ suppresses the printing of any graphic outside the bounding box , bb :: Maybe (Coord, Coord) -- ^ ((llx, lly) (urx, ury)); enters the coordinates of the bounding box manually, -- if they are missing or incorrect in the graphics file, or to be deliberately altered; -- the specifications are four lengths separated by blanks; units may be given, but if -- omitted, big points (bp) are assumed , viewport :: Maybe (Coord, Coord) -- ^ ((llx, lly), (urx, ury)); specifies the bounding box but relative to the lower left -- corner of the existing one; useful for correcting the bounding box, or (with clip) to -- select only a portion of the whole figure , trim :: Maybe (Coord, Coord) -- ^ ((dllx, dlly), (durx, dury)); reduces the existing bounding box by the amounts specified , hiresbb :: Bool -- ^ like the hiresbb package option but applied to the one graphics file; reads bounding box -- information from the %%HiResBoundingBox line in the graphics file. } pkg :: PackageName pkg = PkgName "graphicx" -- | @includegraphics fopts fp@ -- The @fopts@ function will receive the defaults options and should modify options -- to suit your needs. -- -- This function is generally used like this: -- @ -- includegraphics (\\o -> o{ \ = \ ... }) fp -- @ includegraphics :: (IncludeGraphicsOpts -> IncludeGraphicsOpts) -> FilePath -> ParItem includegraphics f fp = BI.parCmdArgs "includegraphics" $ opt ++ [BI.packageDependency pkg, BI.mandatoryLatexItem $ fromString fp] where opts = includeGraphicsOpts $ f defaultOpts opt | null opts = [] | otherwise = [BI.namedOpts opts] defaultOpts :: IncludeGraphicsOpts defaultOpts = IncludeGraphicsOpts { scale = 1 , width = Nothing , height = Nothing , totalheight = Nothing , keepaspectratio = False , angle = 0 , origin = baselineLeft , draft = False , clip = False , bb = Nothing , viewport = Nothing , trim = Nothing , hiresbb = False -- I think that's the default. } includeGraphicsOpts :: IncludeGraphicsOpts -> [Named AnyItem] includeGraphicsOpts o = catMaybes [ f "scale" scale BI.rat , f "width" width (BI.texLength . fromJust) , f "height" height (BI.texLength . fromJust) , f "totalheight" totalheight (BI.texLength . fromJust) , f "keepaspectratio" keepaspectratio BI.bool , f "angle" angle BI.rat , f "origin" origin (BI.rawAnyTex . showGrLoc) , f "draft" draft BI.bool , f "clip" clip BI.bool , f "bb" bb maybeCoords , f "viewport" viewport maybeCoords , f "trim" trim maybeCoords , f "hiresbb" hiresbb BI.bool ] where f :: Eq a => String -> (IncludeGraphicsOpts -> a) -> (a -> AnyItem) -> Maybe (Named AnyItem) f name proj toAnyItem | proj defaultOpts == proj o = Nothing | otherwise = Just (Named name (toAnyItem $ proj o)) maybeCoords = g . (BI.coord *** BI.coord) . fromJust g (x, y) = BI.latexItem $ BI.latexCast x ⊕ BI.rawTex " " ⊕ BI.latexCast y