{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE DeriveAnyClass #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  Ipe.IpeToIpe
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Use 'ipetoipe' to generate pdf files.
--
-- Note that all functions in this module require that 'ipetoipe' is
-- installed (it is bundled with ipe) and available on the path.

--------------------------------------------------------------------------------
module Ipe.IpeToIpe where

import           HGeometry.Interval
import           Ipe.Types (IpeFile)
import           Ipe.Writer (writeIpeFile, IpeWriteText)
import           System.Directory.OsPath (getTemporaryDirectory, removeFile)
import           System.OsPath
import qualified System.Process.Typed as Process
import           System.Random
import           GHC.Generics (Generic)
import           Data.Finitary

--------------------------------------------------------------------------------

-- | Call 'ipetoipe' to produce an image of the specified type.
ipeToIpeWith                          :: Options -- ^ the options to use
                                      -> FileType -- ^ output file type
                                      -> OsPath -- ^ input file path
                                      -> OsPath -- ^ output file path
                                      -> IO ()
ipeToIpeWith :: Options -> FileType -> OsPath -> OsPath -> IO ()
ipeToIpeWith Options
options FileType
fType OsPath
inFp OsPath
outFp =
    do
      inFp'  <- OsPath -> IO String
decodeFS OsPath
inFp
      outFp' <- decodeFS outFp
      Process.withProcessWait (Process.proc "ipetoipe" $ args inFp' outFp') $ \Process () () ()
_iperenderProc ->
        () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  where
    args :: String -> String -> [String]
args String
inFp' String
outFp' =
           [ String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> FileType -> String
forall a. Show a => a -> String
show FileType
fType ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [ String
"-pages", ClosedInterval PageNumber -> String
forall {a}. Show a => ClosedInterval a -> String
pageRange ClosedInterval PageNumber
r ] | PageRange ClosedInterval PageNumber
r <- [Options -> PageRange
pages Options
options] ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [ String
"-view", PageNumber -> PageNumber -> String
forall {a} {a}. (Show a, Show a) => a -> a -> String
pageView PageNumber
p PageNumber
v ] | Just (PageNumber
p,PageNumber
v) <- [Options -> Maybe (PageNumber, PageNumber)
singleView Options
options] ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-export" | Export
Export Export -> Export -> Bool
forall a. Eq a => a -> a -> Bool
== Options -> Export
export Options
options ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-runlatex" | Options -> Bool
runLatex Options
options] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-nozip"    | NoZip
NoZip NoZip -> NoZip -> Bool
forall a. Eq a => a -> a -> Bool
== Options -> NoZip
nozip Options
options ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
inFp'
           , String
outFp'
           ]
    pageRange :: ClosedInterval a -> String
pageRange (ClosedInterval a
l a
u) = a -> String
forall a. Show a => a -> String
show a
l String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
u
    pageView :: a -> a -> String
pageView a
p a
v = a -> String
forall a. Show a => a -> String
show a
p String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
v


-- | Call 'ipetoipe' with the default options.
ipeToIpe :: FileType -> OsPath -> OsPath -> IO ()
ipeToIpe :: FileType -> OsPath -> OsPath -> IO ()
ipeToIpe = Options -> FileType -> OsPath -> OsPath -> IO ()
ipeToIpeWith Options
defaultOptions

-- | Write an ipe file to disk as an ipe readable pdf file.
--
-- Note that like all other functions in this module, this requires
-- 'ipetoipe' to be installed (it is bundled with ipe) and available
-- on the path.
--
-- Note this will write soem intermediate file to your system temp dir.
writeIpeFileAsPdf      :: IpeWriteText r => OsPath -> IpeFile r -> IO ()
writeIpeFileAsPdf :: forall r. IpeWriteText r => OsPath -> IpeFile r -> IO ()
writeIpeFileAsPdf OsPath
fp IpeFile r
f = do num    <- forall a (m :: * -> *). (Random a, MonadIO m) => m a
randomIO @Int
                            tempDir <- getTemporaryDirectory
                            num' <- encodeUtf $ show num
                            let xmlFp = OsPath
tempDir OsPath -> OsPath -> OsPath
</> [osp|writeipepdf|] OsPath -> OsPath -> OsPath
forall a. Semigroup a => a -> a -> a
<> OsPath
num' OsPath -> OsPath -> OsPath
<.> [osp|ipe|]
                            writeIpeFile xmlFp f
                            ipeToIpe PDF xmlFp fp
                            removeFile xmlFp


data FileType = PDF | XML
  deriving (FileType -> FileType -> Bool
(FileType -> FileType -> Bool)
-> (FileType -> FileType -> Bool) -> Eq FileType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileType -> FileType -> Bool
== :: FileType -> FileType -> Bool
$c/= :: FileType -> FileType -> Bool
/= :: FileType -> FileType -> Bool
Eq,(forall x. FileType -> Rep FileType x)
-> (forall x. Rep FileType x -> FileType) -> Generic FileType
forall x. Rep FileType x -> FileType
forall x. FileType -> Rep FileType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FileType -> Rep FileType x
from :: forall x. FileType -> Rep FileType x
$cto :: forall x. Rep FileType x -> FileType
to :: forall x. Rep FileType x -> FileType
Generic)
  deriving anyclass (Eq FileType
KnownNat (Cardinality FileType)
(Eq FileType, KnownNat (Cardinality FileType)) =>
(Finite (Cardinality FileType) -> FileType)
-> (FileType -> Finite (Cardinality FileType))
-> ((1 <= Cardinality FileType) => FileType)
-> ((1 <= Cardinality FileType) => FileType)
-> (FileType -> Maybe FileType)
-> (FileType -> Maybe FileType)
-> Finitary FileType
(1 <= Cardinality FileType) => FileType
Finite (Cardinality FileType) -> FileType
FileType -> Maybe FileType
FileType -> Finite (Cardinality FileType)
forall a.
(Eq a, KnownNat (Cardinality a)) =>
(Finite (Cardinality a) -> a)
-> (a -> Finite (Cardinality a))
-> ((1 <= Cardinality a) => a)
-> ((1 <= Cardinality a) => a)
-> (a -> Maybe a)
-> (a -> Maybe a)
-> Finitary a
$cfromFinite :: Finite (Cardinality FileType) -> FileType
fromFinite :: Finite (Cardinality FileType) -> FileType
$ctoFinite :: FileType -> Finite (Cardinality FileType)
toFinite :: FileType -> Finite (Cardinality FileType)
$cstart :: (1 <= Cardinality FileType) => FileType
start :: (1 <= Cardinality FileType) => FileType
$cend :: (1 <= Cardinality FileType) => FileType
end :: (1 <= Cardinality FileType) => FileType
$cprevious :: FileType -> Maybe FileType
previous :: FileType -> Maybe FileType
$cnext :: FileType -> Maybe FileType
next :: FileType -> Maybe FileType
Finitary)

instance Show FileType where
  show :: FileType -> String
show = \case
    FileType
PDF -> String
"pdf"
    FileType
XML -> String
"xml"

data Export = RetainIpeInfo | Export
  deriving (PageNumber -> Export -> String -> String
[Export] -> String -> String
Export -> String
(PageNumber -> Export -> String -> String)
-> (Export -> String)
-> ([Export] -> String -> String)
-> Show Export
forall a.
(PageNumber -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: PageNumber -> Export -> String -> String
showsPrec :: PageNumber -> Export -> String -> String
$cshow :: Export -> String
show :: Export -> String
$cshowList :: [Export] -> String -> String
showList :: [Export] -> String -> String
Show,Export -> Export -> Bool
(Export -> Export -> Bool)
-> (Export -> Export -> Bool) -> Eq Export
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Export -> Export -> Bool
== :: Export -> Export -> Bool
$c/= :: Export -> Export -> Bool
/= :: Export -> Export -> Bool
Eq,(forall x. Export -> Rep Export x)
-> (forall x. Rep Export x -> Export) -> Generic Export
forall x. Rep Export x -> Export
forall x. Export -> Rep Export x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Export -> Rep Export x
from :: forall x. Export -> Rep Export x
$cto :: forall x. Rep Export x -> Export
to :: forall x. Rep Export x -> Export
Generic)
  deriving anyclass (Eq Export
KnownNat (Cardinality Export)
(Eq Export, KnownNat (Cardinality Export)) =>
(Finite (Cardinality Export) -> Export)
-> (Export -> Finite (Cardinality Export))
-> ((1 <= Cardinality Export) => Export)
-> ((1 <= Cardinality Export) => Export)
-> (Export -> Maybe Export)
-> (Export -> Maybe Export)
-> Finitary Export
(1 <= Cardinality Export) => Export
Finite (Cardinality Export) -> Export
Export -> Maybe Export
Export -> Finite (Cardinality Export)
forall a.
(Eq a, KnownNat (Cardinality a)) =>
(Finite (Cardinality a) -> a)
-> (a -> Finite (Cardinality a))
-> ((1 <= Cardinality a) => a)
-> ((1 <= Cardinality a) => a)
-> (a -> Maybe a)
-> (a -> Maybe a)
-> Finitary a
$cfromFinite :: Finite (Cardinality Export) -> Export
fromFinite :: Finite (Cardinality Export) -> Export
$ctoFinite :: Export -> Finite (Cardinality Export)
toFinite :: Export -> Finite (Cardinality Export)
$cstart :: (1 <= Cardinality Export) => Export
start :: (1 <= Cardinality Export) => Export
$cend :: (1 <= Cardinality Export) => Export
end :: (1 <= Cardinality Export) => Export
$cprevious :: Export -> Maybe Export
previous :: Export -> Maybe Export
$cnext :: Export -> Maybe Export
next :: Export -> Maybe Export
Finitary)

type PageNumber = Int
type ViewNumber = Int

data MarkedView = All | OnlyMarkedViews
  deriving (PageNumber -> MarkedView -> String -> String
[MarkedView] -> String -> String
MarkedView -> String
(PageNumber -> MarkedView -> String -> String)
-> (MarkedView -> String)
-> ([MarkedView] -> String -> String)
-> Show MarkedView
forall a.
(PageNumber -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: PageNumber -> MarkedView -> String -> String
showsPrec :: PageNumber -> MarkedView -> String -> String
$cshow :: MarkedView -> String
show :: MarkedView -> String
$cshowList :: [MarkedView] -> String -> String
showList :: [MarkedView] -> String -> String
Show,MarkedView -> MarkedView -> Bool
(MarkedView -> MarkedView -> Bool)
-> (MarkedView -> MarkedView -> Bool) -> Eq MarkedView
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MarkedView -> MarkedView -> Bool
== :: MarkedView -> MarkedView -> Bool
$c/= :: MarkedView -> MarkedView -> Bool
/= :: MarkedView -> MarkedView -> Bool
Eq,(forall x. MarkedView -> Rep MarkedView x)
-> (forall x. Rep MarkedView x -> MarkedView) -> Generic MarkedView
forall x. Rep MarkedView x -> MarkedView
forall x. MarkedView -> Rep MarkedView x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. MarkedView -> Rep MarkedView x
from :: forall x. MarkedView -> Rep MarkedView x
$cto :: forall x. Rep MarkedView x -> MarkedView
to :: forall x. Rep MarkedView x -> MarkedView
Generic)
  deriving anyclass (Eq MarkedView
KnownNat (Cardinality MarkedView)
(Eq MarkedView, KnownNat (Cardinality MarkedView)) =>
(Finite (Cardinality MarkedView) -> MarkedView)
-> (MarkedView -> Finite (Cardinality MarkedView))
-> ((1 <= Cardinality MarkedView) => MarkedView)
-> ((1 <= Cardinality MarkedView) => MarkedView)
-> (MarkedView -> Maybe MarkedView)
-> (MarkedView -> Maybe MarkedView)
-> Finitary MarkedView
(1 <= Cardinality MarkedView) => MarkedView
Finite (Cardinality MarkedView) -> MarkedView
MarkedView -> Maybe MarkedView
MarkedView -> Finite (Cardinality MarkedView)
forall a.
(Eq a, KnownNat (Cardinality a)) =>
(Finite (Cardinality a) -> a)
-> (a -> Finite (Cardinality a))
-> ((1 <= Cardinality a) => a)
-> ((1 <= Cardinality a) => a)
-> (a -> Maybe a)
-> (a -> Maybe a)
-> Finitary a
$cfromFinite :: Finite (Cardinality MarkedView) -> MarkedView
fromFinite :: Finite (Cardinality MarkedView) -> MarkedView
$ctoFinite :: MarkedView -> Finite (Cardinality MarkedView)
toFinite :: MarkedView -> Finite (Cardinality MarkedView)
$cstart :: (1 <= Cardinality MarkedView) => MarkedView
start :: (1 <= Cardinality MarkedView) => MarkedView
$cend :: (1 <= Cardinality MarkedView) => MarkedView
end :: (1 <= Cardinality MarkedView) => MarkedView
$cprevious :: MarkedView -> Maybe MarkedView
previous :: MarkedView -> Maybe MarkedView
$cnext :: MarkedView -> Maybe MarkedView
next :: MarkedView -> Maybe MarkedView
Finitary)

data NoZip = NoZip | Zip
  deriving (PageNumber -> NoZip -> String -> String
[NoZip] -> String -> String
NoZip -> String
(PageNumber -> NoZip -> String -> String)
-> (NoZip -> String) -> ([NoZip] -> String -> String) -> Show NoZip
forall a.
(PageNumber -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: PageNumber -> NoZip -> String -> String
showsPrec :: PageNumber -> NoZip -> String -> String
$cshow :: NoZip -> String
show :: NoZip -> String
$cshowList :: [NoZip] -> String -> String
showList :: [NoZip] -> String -> String
Show,NoZip -> NoZip -> Bool
(NoZip -> NoZip -> Bool) -> (NoZip -> NoZip -> Bool) -> Eq NoZip
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NoZip -> NoZip -> Bool
== :: NoZip -> NoZip -> Bool
$c/= :: NoZip -> NoZip -> Bool
/= :: NoZip -> NoZip -> Bool
Eq,(forall x. NoZip -> Rep NoZip x)
-> (forall x. Rep NoZip x -> NoZip) -> Generic NoZip
forall x. Rep NoZip x -> NoZip
forall x. NoZip -> Rep NoZip x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. NoZip -> Rep NoZip x
from :: forall x. NoZip -> Rep NoZip x
$cto :: forall x. Rep NoZip x -> NoZip
to :: forall x. Rep NoZip x -> NoZip
Generic)
  deriving anyclass (Eq NoZip
KnownNat (Cardinality NoZip)
(Eq NoZip, KnownNat (Cardinality NoZip)) =>
(Finite (Cardinality NoZip) -> NoZip)
-> (NoZip -> Finite (Cardinality NoZip))
-> ((1 <= Cardinality NoZip) => NoZip)
-> ((1 <= Cardinality NoZip) => NoZip)
-> (NoZip -> Maybe NoZip)
-> (NoZip -> Maybe NoZip)
-> Finitary NoZip
(1 <= Cardinality NoZip) => NoZip
Finite (Cardinality NoZip) -> NoZip
NoZip -> Maybe NoZip
NoZip -> Finite (Cardinality NoZip)
forall a.
(Eq a, KnownNat (Cardinality a)) =>
(Finite (Cardinality a) -> a)
-> (a -> Finite (Cardinality a))
-> ((1 <= Cardinality a) => a)
-> ((1 <= Cardinality a) => a)
-> (a -> Maybe a)
-> (a -> Maybe a)
-> Finitary a
$cfromFinite :: Finite (Cardinality NoZip) -> NoZip
fromFinite :: Finite (Cardinality NoZip) -> NoZip
$ctoFinite :: NoZip -> Finite (Cardinality NoZip)
toFinite :: NoZip -> Finite (Cardinality NoZip)
$cstart :: (1 <= Cardinality NoZip) => NoZip
start :: (1 <= Cardinality NoZip) => NoZip
$cend :: (1 <= Cardinality NoZip) => NoZip
end :: (1 <= Cardinality NoZip) => NoZip
$cprevious :: NoZip -> Maybe NoZip
previous :: NoZip -> Maybe NoZip
$cnext :: NoZip -> Maybe NoZip
next :: NoZip -> Maybe NoZip
Finitary)

data PageRange = EntireFile
               | PageRange (ClosedInterval PageNumber)
               deriving (PageNumber -> PageRange -> String -> String
[PageRange] -> String -> String
PageRange -> String
(PageNumber -> PageRange -> String -> String)
-> (PageRange -> String)
-> ([PageRange] -> String -> String)
-> Show PageRange
forall a.
(PageNumber -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: PageNumber -> PageRange -> String -> String
showsPrec :: PageNumber -> PageRange -> String -> String
$cshow :: PageRange -> String
show :: PageRange -> String
$cshowList :: [PageRange] -> String -> String
showList :: [PageRange] -> String -> String
Show,PageRange -> PageRange -> Bool
(PageRange -> PageRange -> Bool)
-> (PageRange -> PageRange -> Bool) -> Eq PageRange
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PageRange -> PageRange -> Bool
== :: PageRange -> PageRange -> Bool
$c/= :: PageRange -> PageRange -> Bool
/= :: PageRange -> PageRange -> Bool
Eq)

data Options = Options { Options -> Export
export     :: Export
                       , Options -> PageRange
pages      :: PageRange
                       , Options -> Maybe (PageNumber, PageNumber)
singleView :: Maybe (PageNumber,ViewNumber)
                       , Options -> MarkedView
markedView :: MarkedView
                       , Options -> Bool
runLatex   :: Bool
                       , Options -> NoZip
nozip      :: NoZip
                       } deriving (PageNumber -> Options -> String -> String
[Options] -> String -> String
Options -> String
(PageNumber -> Options -> String -> String)
-> (Options -> String)
-> ([Options] -> String -> String)
-> Show Options
forall a.
(PageNumber -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: PageNumber -> Options -> String -> String
showsPrec :: PageNumber -> Options -> String -> String
$cshow :: Options -> String
show :: Options -> String
$cshowList :: [Options] -> String -> String
showList :: [Options] -> String -> String
Show,Options -> Options -> Bool
(Options -> Options -> Bool)
-> (Options -> Options -> Bool) -> Eq Options
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
/= :: Options -> Options -> Bool
Eq)

defaultOptions :: Options
defaultOptions :: Options
defaultOptions = Export
-> PageRange
-> Maybe (PageNumber, PageNumber)
-> MarkedView
-> Bool
-> NoZip
-> Options
Options Export
RetainIpeInfo
                         PageRange
EntireFile
                         Maybe (PageNumber, PageNumber)
forall a. Maybe a
Nothing -- default : entire file
                         MarkedView
All
                         Bool
False
                         NoZip
Zip