Skip to content

Commit 682f972

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 0c88562 commit 682f972

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,
@@ -372,14 +371,14 @@ readAbbreviations mbfilepath =
372371
>>= fmap (Set.fromList . filter (not . T.null) . T.lines) .
373372
toTextM (fromMaybe mempty mbfilepath)
374373

375-
createPngFallbacks :: (PandocMonad m, MonadIO m) => Int -> m ()
374+
createPngFallbacks :: (PandocMonad m) => Int -> m ()
376375
createPngFallbacks dpi = do
377376
-- create fallback pngs for svgs
378377
items <- mediaItems <$> getMediaBag
379378
forM_ items $ \(fp, mt, bs) ->
380379
case T.takeWhile (/=';') mt of
381380
"image/svg+xml" -> do
382-
res <- svgToPng dpi bs
381+
res <- svgToPng (dpi, Nothing, Nothing, bs)
383382
case res of
384383
Right bs' -> do
385384
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
@@ -80,6 +81,7 @@ import qualified System.Environment as Env
8081
import qualified System.FilePath.Glob
8182
import qualified System.Random
8283
import qualified Text.Pandoc.UTF8 as UTF8
84+
import Text.Pandoc.Image (svgToPngIO)
8385
#ifndef EMBED_DATA_FILES
8486
import qualified Paths_pandoc as Paths
8587
#endif
@@ -170,6 +172,11 @@ readFileStrict s = liftIOError B.readFile s
170172
readStdinStrict :: (PandocMonad m, MonadIO m) => m B.ByteString
171173
readStdinStrict = liftIOError (const B.getContents) "stdin"
172174

175+
-- | Runs an image conversion step, returning an error on failure.
176+
-- Not available when sandboxed.
177+
svgToPng :: (PandocMonad m, MonadIO m) => (Int, Maybe Double, Maybe Double, BL.ByteString) -> m (Either T.Text BL.ByteString)
178+
svgToPng (dpi, xPt, yPt, bs) = svgToPngIO dpi xPt yPt bs
179+
173180
-- | Return a list of paths that match a glob, relative to the working
174181
-- directory. See 'System.FilePath.Glob' for the glob syntax.
175182
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
@@ -116,6 +116,9 @@ class (Functor m, Applicative m, Monad m, MonadError PandocError m)
116116
-- | Read the contents of stdin as a strict ByteString, raising
117117
-- an error on failure.
118118
readStdinStrict :: m B.ByteString
119+
-- | Converts an SVG to a PNG (dpiX, widthPoints, heightPoints, svgBlob)
120+
-- Not called when sandboxed.
121+
svgToPng :: (Int, Maybe Double, Maybe Double, BL.ByteString) -> m (Either T.Text BL.ByteString)
119122
-- | Return a list of paths that match a glob, relative to
120123
-- the working directory. See 'System.FilePath.Glob' for
121124
-- the glob syntax.
@@ -505,6 +508,7 @@ instance (MonadTrans t, PandocMonad m, Functor (t m),
505508
readFileLazy = lift . readFileLazy
506509
readFileStrict = lift . readFileStrict
507510
readStdinStrict = lift readStdinStrict
511+
svgToPng = lift . svgToPng
508512
glob = lift . glob
509513
fileExists = lift . fileExists
510514
getDataFileName = lift . getDataFileName
@@ -523,6 +527,7 @@ instance {-# OVERLAPS #-} PandocMonad m => PandocMonad (ParsecT s st m) where
523527
readFileLazy = lift . readFileLazy
524528
readFileStrict = lift . readFileStrict
525529
readStdinStrict = lift readStdinStrict
530+
svgToPng = lift . svgToPng
526531
glob = lift . glob
527532
fileExists = lift . fileExists
528533
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)