Skip to content

Commit 6483e2f

Browse files
committed
refactor(svgToPng): introduce PandocMonad.svgToPng
This will be needed to run the conversion inside the PandocMonad, where we know the desired image size. The arguments are: (dpi, width, height). The width and height is optional to more easily convert existing code. [API change] Signed-off-by: Edwin Török <[email protected]>
1 parent 99ba09c commit 6483e2f

File tree

7 files changed

+26
-6
lines changed

7 files changed

+26
-6
lines changed

pandoc-lua-engine/src/Text/Pandoc/Lua/PandocLua.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ instance PandocMonad PandocLua where
7070
readFileLazy = IO.readFileLazy
7171
readFileStrict = IO.readFileStrict
7272
readStdinStrict = IO.readStdinStrict
73+
svgToPng = IO.svgToPng
7374

7475
glob = IO.glob
7576
fileExists = IO.fileExists

src/Text/Pandoc/App.hs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ import qualified System.IO as IO (Newline (..))
5050
import Text.Pandoc
5151
import Text.Pandoc.Builder (setMeta)
5252
import Text.Pandoc.MediaBag (mediaItems)
53-
import Text.Pandoc.Image (svgToPng)
5453
import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,
5554
IpynbOutput (..), OptInfo(..))
5655
import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,
@@ -368,14 +367,14 @@ readAbbreviations mbfilepath =
368367
>>= fmap (Set.fromList . filter (not . T.null) . T.lines) .
369368
toTextM (fromMaybe mempty mbfilepath)
370369

371-
createPngFallbacks :: (PandocMonad m, MonadIO m) => Int -> m ()
370+
createPngFallbacks :: (PandocMonad m) => Int -> m ()
372371
createPngFallbacks dpi = do
373372
-- create fallback pngs for svgs
374373
items <- mediaItems <$> getMediaBag
375374
forM_ items $ \(fp, mt, bs) ->
376375
case T.takeWhile (/=';') mt of
377376
"image/svg+xml" -> do
378-
res <- svgToPng dpi bs
377+
res <- svgToPng dpi Nothing Nothing bs
379378
case res of
380379
Right bs' -> do
381380
let fp' = fp <> ".png"

src/Text/Pandoc/Class/IO.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module Text.Pandoc.Class.IO
3131
, readFileLazy
3232
, readFileStrict
3333
, readStdinStrict
34+
, svgToPng
3435
, extractMedia
3536
, writeMedia
3637
) where
@@ -84,6 +85,7 @@ import qualified System.Random
8485
import qualified Text.Pandoc.UTF8 as UTF8
8586
import Data.Default (def)
8687
import System.X509 (getSystemCertificateStore)
88+
import Text.Pandoc.Image (svgToPngIO)
8789
#ifndef EMBED_DATA_FILES
8890
import qualified Paths_pandoc as Paths
8991
#endif
@@ -184,6 +186,11 @@ readFileStrict s = liftIOError B.readFile s
184186
readStdinStrict :: (PandocMonad m, MonadIO m) => m B.ByteString
185187
readStdinStrict = liftIOError (const B.getContents) "stdin"
186188

189+
-- | Runs an image conversion step, returning an error on failure.
190+
-- Not available when sandboxed.
191+
svgToPng :: (PandocMonad m, MonadIO m) => Int -> Maybe Double -> Maybe Double -> BL.ByteString -> m (Either T.Text BL.ByteString)
192+
svgToPng = svgToPngIO
193+
187194
-- | Return a list of paths that match a glob, relative to the working
188195
-- directory. See 'System.FilePath.Glob' for the glob syntax.
189196
glob :: (PandocMonad m, MonadIO m) => String -> m [FilePath]

src/Text/Pandoc/Class/PandocIO.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ instance PandocMonad PandocIO where
6363
readFileLazy = IO.readFileLazy
6464
readFileStrict = IO.readFileStrict
6565
readStdinStrict = IO.readStdinStrict
66+
svgToPng = IO.svgToPng
6667

6768
glob = IO.glob
6869
fileExists = IO.fileExists

src/Text/Pandoc/Class/PandocMonad.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ class (Functor m, Applicative m, Monad m, MonadError PandocError m)
120120
-- | Read the contents of stdin as a strict ByteString, raising
121121
-- an error on failure.
122122
readStdinStrict :: m B.ByteString
123+
-- | Converts an SVG to a PNG (dpiX, widthPoints, heightPoints, svgBlob)
124+
-- Not called when sandboxed.
125+
svgToPng :: Int -> Maybe Double -> Maybe Double -> BL.ByteString -> m (Either T.Text BL.ByteString)
123126
-- | Return a list of paths that match a glob, relative to
124127
-- the working directory. See 'System.FilePath.Glob' for
125128
-- the glob syntax.
@@ -529,6 +532,7 @@ instance (MonadTrans t, PandocMonad m, Functor (t m),
529532
readFileLazy = lift . readFileLazy
530533
readFileStrict = lift . readFileStrict
531534
readStdinStrict = lift readStdinStrict
535+
svgToPng dpi width height bs = lift $ svgToPng dpi width height bs
532536
glob = lift . glob
533537
fileExists = lift . fileExists
534538
getDataFileName = lift . getDataFileName
@@ -547,6 +551,7 @@ instance {-# OVERLAPS #-} PandocMonad m => PandocMonad (ParsecT s st m) where
547551
readFileLazy = lift . readFileLazy
548552
readFileStrict = lift . readFileStrict
549553
readStdinStrict = lift readStdinStrict
554+
svgToPng dpi width height bs = lift $ svgToPng dpi width height bs
550555
glob = lift . glob
551556
fileExists = lift . fileExists
552557
getDataFileName = lift . getDataFileName

src/Text/Pandoc/Class/PandocPure.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ instance PandocMonad PandocPure where
205205
Nothing -> throwError $ PandocResourceNotFound $ T.pack fp
206206

207207
readStdinStrict = getsPureState stStdin
208+
209+
svgToPng _ _ _ _ = return $ Left "SVG conversion not available in PandocPure"
208210

209211
glob s = do
210212
FileTree ftmap <- getsPureState stFiles

src/Text/Pandoc/Image.hs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Portability : portable
1010
1111
Functions for converting images.
1212
-}
13-
module Text.Pandoc.Image ( svgToPng ) where
13+
module Text.Pandoc.Image ( svgToPngIO ) where
1414
import Text.Pandoc.Process (pipeProcess)
1515
import qualified Data.ByteString.Lazy as L
1616
import System.Exit
@@ -20,16 +20,20 @@ import qualified Control.Exception as E
2020
import Control.Monad.IO.Class (MonadIO(liftIO))
2121
import Text.Pandoc.Class.PandocMonad
2222
import qualified Data.Text as T
23+
import Text.Printf (printf)
2324

2425
-- | Convert svg image to png. rsvg-convert
2526
-- is used and must be available on the path.
26-
svgToPng :: (PandocMonad m, MonadIO m)
27+
svgToPngIO :: (PandocMonad m, MonadIO m)
2728
=> Int -- ^ DPI
29+
-> Maybe Double -- ^ width in Points
30+
-> Maybe Double -- ^ height in Points
2831
-> L.ByteString -- ^ Input image as bytestring
2932
-> m (Either Text L.ByteString)
30-
svgToPng dpi bs = do
33+
svgToPngIO dpi widthPt heightPt bs = do
3134
let dpi' = show dpi
3235
let args = ["-f","png","-a","--dpi-x",dpi',"--dpi-y",dpi']
36+
++ pt "width" widthPt ++ pt "height" heightPt
3337
trace (T.intercalate " " $ map T.pack $ "rsvg-convert" : args)
3438
liftIO $ E.catch
3539
(do (exit, out) <- pipeProcess Nothing "rsvg-convert"
@@ -40,3 +44,4 @@ svgToPng dpi bs = do
4044
else Left "conversion from SVG failed")
4145
(\(e :: E.SomeException) -> return $ Left $
4246
"check that rsvg-convert is in path.\n" <> tshow e)
47+
where pt name = maybe [] $ \points -> ["--" <> name, printf "%.6fpt" points]

0 commit comments

Comments
 (0)