{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, CPP #-}
{- |
Module      : Text.Pandoc.Image
Copyright   : Copyright (C) 2020-2024 John MacFarlane
License     : GNU GPL, version 2 or above

Maintainer  : John MacFarlane <jgm@berkeley.edu>
Stability   : alpha
Portability : portable

Functions for converting images.
-}
module Text.Pandoc.Image ( svgToPng ) where
import Text.Pandoc.Process (pipeProcess)
import qualified Data.ByteString.Lazy as L
import System.Exit
import Data.Text (Text)
import Text.Pandoc.Shared (tshow)
import qualified Control.Exception as E
import Control.Monad.IO.Class (MonadIO(liftIO))

-- | Convert svg image to png. rsvg-convert
-- is used and must be available on the path.
svgToPng :: MonadIO m
         => Int           -- ^ DPI
         -> L.ByteString  -- ^ Input image as bytestring
         -> m (Either Text L.ByteString)
svgToPng :: forall (m :: * -> *).
MonadIO m =>
Int -> ByteString -> m (Either Text ByteString)
svgToPng Int
dpi ByteString
bs = do
  let dpi' :: String
dpi' = Int -> String
forall a. Show a => a -> String
show Int
dpi
  IO (Either Text ByteString) -> m (Either Text ByteString)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either Text ByteString) -> m (Either Text ByteString))
-> IO (Either Text ByteString) -> m (Either Text ByteString)
forall a b. (a -> b) -> a -> b
$ IO (Either Text ByteString)
-> (SomeException -> IO (Either Text ByteString))
-> IO (Either Text ByteString)
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
E.catch
       (do (ExitCode
exit, ByteString
out) <- Maybe [(String, String)]
-> String -> [String] -> ByteString -> IO (ExitCode, ByteString)
pipeProcess Maybe [(String, String)]
forall a. Maybe a
Nothing String
"rsvg-convert"
                          [String
"-f",String
"png",String
"-a",String
"--dpi-x",String
dpi',String
"--dpi-y",String
dpi']
                          ByteString
bs
           Either Text ByteString -> IO (Either Text ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Text ByteString -> IO (Either Text ByteString))
-> Either Text ByteString -> IO (Either Text ByteString)
forall a b. (a -> b) -> a -> b
$ if ExitCode
exit ExitCode -> ExitCode -> Bool
forall a. Eq a => a -> a -> Bool
== ExitCode
ExitSuccess
              then ByteString -> Either Text ByteString
forall a b. b -> Either a b
Right ByteString
out
              else Text -> Either Text ByteString
forall a b. a -> Either a b
Left Text
"conversion from SVG failed")
       (\(SomeException
e :: E.SomeException) -> Either Text ByteString -> IO (Either Text ByteString)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Either Text ByteString -> IO (Either Text ByteString))
-> Either Text ByteString -> IO (Either Text ByteString)
forall a b. (a -> b) -> a -> b
$ Text -> Either Text ByteString
forall a b. a -> Either a b
Left (Text -> Either Text ByteString) -> Text -> Either Text ByteString
forall a b. (a -> b) -> a -> b
$
           Text
"check that rsvg-convert is in path.\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SomeException -> Text
forall a. Show a => a -> Text
tshow SomeException
e)