Skip to content

Commit 0892709

Browse files
committed
fix(docx): use proper DPI when creating fallback images
Introduce getOrCreateFallback, and pass the desired size in points to rsvg-convert. Otherwise it'll guess the size based on the SVG's viewbox and completely ignore the DPI argument. Signed-off-by: Edwin Török <[email protected]>
1 parent fc2ed1f commit 0892709

File tree

3 files changed

+50
-36
lines changed

3 files changed

+50
-36
lines changed

src/Text/Pandoc/App.hs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module Text.Pandoc.App (
2828
, applyFilters
2929
) where
3030
import qualified Control.Exception as E
31-
import Control.Monad ( (>=>), when, forM, forM_ )
31+
import Control.Monad ( (>=>), when, forM )
3232
import Control.Monad.Trans ( MonadIO(..) )
3333
import Control.Monad.Catch ( MonadMask )
3434
import Control.Monad.Except (throwError)
@@ -49,8 +49,6 @@ import System.IO (nativeNewline, stdout)
4949
import qualified System.IO as IO (Newline (..))
5050
import Text.Pandoc
5151
import Text.Pandoc.Builder (setMeta)
52-
import Text.Pandoc.MediaBag (mediaItems)
53-
import Text.Pandoc.Image (svgToPng)
5452
import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,
5553
IpynbOutput (..), OptInfo(..))
5654
import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,
@@ -65,7 +63,7 @@ import Text.Pandoc.PDF (makePDF)
6563
import Text.Pandoc.Scripting (ScriptingEngine (..), CustomComponents(..))
6664
import Text.Pandoc.SelfContained (makeSelfContained)
6765
import Text.Pandoc.Shared (eastAsianLineBreakFilter,
68-
headerShift, filterIpynbOutput, tshow)
66+
headerShift, filterIpynbOutput)
6967
import Text.Pandoc.URI (isURI)
7068
import Text.Pandoc.Writers.Shared (lookupMetaString)
7169
import Text.Pandoc.Readers.Markdown (yamlToMeta)
@@ -307,9 +305,6 @@ convertWithOpts' scriptingEngine istty datadir opts = do
307305
>=> maybe return extractMedia (optExtractMedia opts)
308306
)
309307

310-
when (format == "docx" && not (optSandbox opts)) $ do
311-
createPngFallbacks (writerDpi writerOptions)
312-
313308
output <- case writer of
314309
ByteStringWriter f
315310
| format == "chunkedhtml" -> ZipOutput <$> f writerOptions doc
@@ -372,21 +367,6 @@ readAbbreviations mbfilepath =
372367
>>= fmap (Set.fromList . filter (not . T.null) . T.lines) .
373368
toTextM (fromMaybe mempty mbfilepath)
374369

375-
createPngFallbacks :: (PandocMonad m) => Int -> m ()
376-
createPngFallbacks dpi = do
377-
-- create fallback pngs for svgs
378-
items <- mediaItems <$> getMediaBag
379-
forM_ items $ \(fp, mt, bs) ->
380-
case T.takeWhile (/=';') mt of
381-
"image/svg+xml" -> do
382-
res <- svgToPng dpi bs
383-
case res of
384-
Right bs' -> do
385-
let fp' = fp <> ".png"
386-
insertMedia fp' (Just "image/png") bs'
387-
Left e -> report $ CouldNotConvertImage (T.pack fp) (tshow e)
388-
_ -> return ()
389-
390370
getMetadataFromFiles :: PandocMonad m
391371
=> Text -> ReaderOptions -> [FilePath] -> m Meta
392372
getMetadataFromFiles readerFormat readerOpts = \case

src/Text/Pandoc/Image.hs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,38 @@ Portability : portable
1010
1111
Functions for converting images.
1212
-}
13-
module Text.Pandoc.Image ( svgToPng ) where
13+
module Text.Pandoc.Image ( createPngFallback, svgToPng ) where
1414
import qualified Data.ByteString.Lazy as L
1515
import Data.Text (Text)
1616
import Text.Pandoc.Class.PandocMonad
17+
import qualified Data.Text as T
18+
import Text.Pandoc.Logging (LogMessage(CouldNotConvertImage))
19+
import Text.Pandoc.Shared (tshow)
20+
import Data.ByteString.Lazy (ByteString)
21+
import Text.Pandoc.MediaBag (MediaItem, lookupMedia)
22+
import Text.Printf (printf)
1723

1824
-- | Convert svg image to png. rsvg-convert
1925
-- is used and must be available on the path.
2026
svgToPng :: (PandocMonad m)
2127
=> Int -- ^ DPI
28+
-> (Double, Double) -- ^ desired size in Points
2229
-> L.ByteString -- ^ Input image as bytestring
2330
-> m (Either Text L.ByteString)
24-
svgToPng dpi bs = do
31+
svgToPng dpi (xPt, yPt) bs = do
2532
let dpi' = show dpi
26-
let args = ["-f","png","-a","--dpi-x",dpi',"--dpi-y",dpi']
27-
runConversion ("rsvg-convert", args, bs)
33+
let args = ["-f","png","-a","--dpi-x",dpi',"--dpi-y",dpi',"--width", pt xPt, "--height", pt yPt]
34+
runConversion ("rsvg-convert", args, bs)
35+
where pt points = printf "%.6fpt" points
36+
37+
createPngFallback :: (PandocMonad m) => Int -> (Double, Double) -> FilePath -> ByteString -> m (Maybe MediaItem)
38+
createPngFallback dpi xyPt fp bs = do
39+
-- create fallback pngs for svgs
40+
res <- svgToPng dpi xyPt bs
41+
case res of
42+
Right bs' -> do
43+
insertMedia fp (Just "image/png") bs'
44+
lookupMedia fp <$> getMediaBag
45+
Left e -> do
46+
report $ CouldNotConvertImage (T.pack fp) (tshow e)
47+
return Nothing

src/Text/Pandoc/Writers/Docx.hs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ import Text.Pandoc.Writers.OOXML
7777
import Text.Pandoc.XML.Light as XML
7878
import Data.Generics (mkT, everywhere)
7979
import Text.Collate.Lang (renderLang, Lang(..))
80+
import Text.Pandoc.Image (createPngFallback)
81+
import Data.ByteString (ByteString)
82+
import Text.Printf (printf)
8083

8184
-- from wml.xsd EG_RPrBase
8285
rPrTagOrder :: M.Map Text Int
@@ -1321,6 +1324,15 @@ formattedRun els = do
13211324
props <- getTextProps
13221325
return [ mknode "w:r" [] $ props ++ els ]
13231326

1327+
getOrCreateFallback :: PandocMonad m => Int -> (Integer, Integer) -> FilePath -> ByteString -> m (Maybe MediaItem)
1328+
getOrCreateFallback dpi (xemu, yemu) src' img = do
1329+
mediabag <- getMediaBag
1330+
let src = printf "%s_%d_%d.png" src' xemu yemu
1331+
let xyPt = (fromIntegral xemu / 12700.0, fromIntegral yemu / 12700.0)
1332+
case lookupMedia src mediabag of
1333+
Just item -> return $ Just item
1334+
Nothing -> createPngFallback dpi xyPt src $ BL.fromStrict img
1335+
13241336
-- | Convert an inline element to OpenXML.
13251337
inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Content]
13261338
inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il
@@ -1522,17 +1534,26 @@ inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do
15221534
imgs <- gets stImages
15231535
let
15241536
stImage = M.lookup (T.unpack src) imgs
1525-
generateImgElt (ident, _fp, mt, img) = do
1537+
generateImgElt (ident, fp, mt, img) = do
15261538
docprid <- getUniqueId
15271539
nvpicprid <- getUniqueId
1540+
let
1541+
(xpt,ypt) = desiredSizeInPoints opts attr
1542+
(either (const def) id (imageSize opts img))
1543+
-- 12700 emu = 1 pt
1544+
pageWidthPt = case dimension Width attr of
1545+
Just (Percent a) -> pageWidth * floor (a * 127)
1546+
_ -> pageWidth * 12700
1547+
(xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt
15281548
(blipAttrs, blipContents) <-
15291549
case T.takeWhile (/=';') <$> mt of
15301550
Just "image/svg+xml" -> do
15311551
-- get fallback png
1532-
mediabag <- getMediaBag
1552+
fallback <- getOrCreateFallback (writerDpi opts) (xemu, yemu) fp img
15331553
mbFallback <-
1534-
case lookupMedia (T.unpack (src <> ".png")) mediabag of
1554+
case fallback of
15351555
Just item -> do
1556+
P.trace $ "Found fallback " <> tshow (mediaPath item)
15361557
id' <- T.unpack . ("rId" <>) <$> getUniqueId
15371558
let fp' = "media/" <> id' <> ".png"
15381559
let imgdata = (id',
@@ -1559,13 +1580,6 @@ inlineToOpenXML' opts (Image attr@(imgident, _, _) alt (src, title)) = do
15591580
[extLst])
15601581
_ -> return ([("r:embed", T.pack ident)], [])
15611582
let
1562-
(xpt,ypt) = desiredSizeInPoints opts attr
1563-
(either (const def) id (imageSize opts img))
1564-
-- 12700 emu = 1 pt
1565-
pageWidthPt = case dimension Width attr of
1566-
Just (Percent a) -> pageWidth * floor (a * 127)
1567-
_ -> pageWidth * 12700
1568-
(xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) pageWidthPt
15691583
cNvPicPr = mknode "pic:cNvPicPr" [] $
15701584
mknode "a:picLocks" [("noChangeArrowheads","1")
15711585
,("noChangeAspect","1")] ()

0 commit comments

Comments
 (0)