hps-0.16: Graphics/PS/Paper.hs
-- | Paper and BBox.
module Graphics.PS.Paper where
import Graphics.PS.Unit
-- | Enumeration type for Units.
data Units = MM | PT deriving (Eq,Show)
-- | Paper size data type, the units are specified in the type.
-- The units in postscript are points, we often work in millimeters.
data Paper = Paper {units :: Units
,width :: Int
,height :: Int}
deriving (Eq,Show)
-- | Translate 'Paper' from mm to points.
--
-- > let a4 = Paper MM 210 297
-- > paper_size_pt a4 == (595,841)
paper_size_pt :: Paper -> (Int,Int)
paper_size_pt (Paper unit w h) =
case unit of
MM -> (mm_pt_int w,mm_pt_int h)
PT -> (w,h)
-- | BoundingBox for an EPSF file with an optional HiResBoundingBox
data BBox = BBox {llx :: Int -- ^ lower left x (x-min)
,lly :: Int -- ^ lower left y (y-min)
,urx :: Int -- ^ upper right x (x-max)
,ury :: Int -- ^ upper right y (y-max)
}
| HRBBox {llx :: Int
,lly :: Int
,urx :: Int
,ury :: Int
,hrllx :: Double -- ^ high resolution 'llx'
,hrlly :: Double -- ^ high resolution 'lly'
,hrurx :: Double -- ^ high resolution 'urx'
,hrury :: Double -- ^ high resolution 'ury'
}
deriving (Eq,Show)
-- | Swap width and height of 'Paper'.
landscape :: Paper -> Paper
landscape (Paper u w h) = Paper u h w
-- | Proportion of 'Paper'.
--
-- > import Graphics.PS.Paper.Names
-- > proportion broadsheet == 1.25
-- > map (round . (* 1e3) . proportion) [a0,b0,c0] == [1414,1414,1414]
-- > map proportion [usLetter,berliner,tabloid]
proportion :: Paper -> Double
proportion (Paper _ w h) = i_to_d h / i_to_d w
-- | The margin given by placing paper size /p/ within /q/.
inset_margin :: Paper -> Paper -> (Units,Int,Int)
inset_margin (Paper u1 w1 h1) (Paper u2 w2 h2) =
if u1 /= u2
then error "inset_margin: unequal units"
else (u2,(w2 - w1) `div` 2,(h2 - h1) `div` 2)
-- * BBox
-- | Sum of 'BBox'.
--
-- > bbox_sum (BBox 5 5 10 10) (BBox 0 0 2 20) == BBox 0 0 10 20
bbox_sum :: BBox -> BBox -> BBox
bbox_sum p q =
case (p,q) of
(BBox x0 y0 x1 y1,BBox x2 y2 x3 y3) ->
BBox (min x0 x2) (min y0 y2) (max x1 x3) (max y1 y3)
_ -> error "bbox_sum: HR not handled"
-- | Translate 'BBox' from mm to points.
bbox_mm_to_pt :: BBox -> BBox
bbox_mm_to_pt bb =
case bb of
BBox x y x' y' ->
BBox (mm_pt_int x) (mm_pt_int y) (mm_pt_int x') (mm_pt_int y')
HRBBox x y x' y' hx hy hx' hy' ->
HRBBox (mm_pt_int x) (mm_pt_int y) (mm_pt_int x') (mm_pt_int y')
(mm_pt hx) (mm_pt hy) (mm_pt hx') (mm_pt hy')
{- | A 'div' variant that rounds rather than truncates.
> let f (Paper _ h _) = h `div` 2 == h `divRound` 2
> in all id (map f [b0,b1,b2,b3,b4,b5,b6,b7,b8,b9]) == False
-}
divRound :: Int -> Int -> Int
divRound x y =
let x' = (fromIntegral x)::Double
y' = (fromIntegral y)::Double
in round (x' / y')