diff options
author | Mauro Bieg <mb21@users.noreply.github.com> | 2017-02-22 18:32:02 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-22 18:32:02 +0100 |
commit | e51b32a475ac9f1633ac996121df7a6c10e05283 (patch) | |
tree | f65850505f1c7696f1de82dc62113a47d0f480b7 /src | |
parent | c2e4ea10b39431f260e615c8fc1d23c72c835169 (diff) | |
parent | 3f6b50e525255feda59ba44d4e094766bd87e0a9 (diff) | |
download | pandoc-e51b32a475ac9f1633ac996121df7a6c10e05283.tar.gz |
Merge pull request #3464 from mb21/determine-svg-size
make imageSize recognize basic SVG dimensions, see #3462
Diffstat (limited to 'src')
-rw-r--r-- | src/Text/Pandoc/ImageSize.hs | 67 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/Docx.hs | 3 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/ICML.hs | 2 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/ODT.hs | 2 | ||||
-rw-r--r-- | src/Text/Pandoc/Writers/RTF.hs | 2 |
5 files changed, 54 insertions, 22 deletions
diff --git a/src/Text/Pandoc/ImageSize.hs b/src/Text/Pandoc/ImageSize.hs index cc22c06ca..b698535ce 100644 --- a/src/Text/Pandoc/ImageSize.hs +++ b/src/Text/Pandoc/ImageSize.hs @@ -39,6 +39,7 @@ module Text.Pandoc.ImageSize ( ImageType(..) , Direction(..) , dimension , inInch + , inPixel , inPoints , numUnit , showInInch @@ -58,6 +59,8 @@ import Data.Default (Default) import Numeric (showFFloat) import Text.Pandoc.Definition import Text.Pandoc.Options +import qualified Text.Pandoc.UTF8 as UTF8 +import qualified Text.XML.Light as Xml import qualified Data.Map as M import Control.Monad.Except import Data.Maybe (fromMaybe) @@ -65,7 +68,7 @@ import Data.Maybe (fromMaybe) -- quick and dirty functions to get image sizes -- algorithms borrowed from wwwis.pl -data ImageType = Png | Gif | Jpeg | Pdf | Eps deriving Show +data ImageType = Png | Gif | Jpeg | Svg | Pdf | Eps deriving Show data Direction = Width | Height instance Show Direction where show Width = "width" @@ -100,17 +103,25 @@ imageType img = case B.take 4 img of "\xff\xd8\xff\xe0" -> return Jpeg -- JFIF "\xff\xd8\xff\xe1" -> return Jpeg -- Exif "%PDF" -> return Pdf + "<svg" -> return Svg + "<?xm" + | "<svg " == (B.take 5 $ last $ B.groupBy openingTag $ B.drop 7 img) + -> return Svg "%!PS" | (B.take 4 $ B.drop 1 $ B.dropWhile (/=' ') img) == "EPSF" -> return Eps _ -> mzero + where + -- B.groupBy openingTag matches first "<svg" or "<html" but not "<!--" + openingTag x y = x == '<' && y /= '!' -imageSize :: ByteString -> Either String ImageSize -imageSize img = +imageSize :: WriterOptions -> ByteString -> Either String ImageSize +imageSize opts img = case imageType img of Just Png -> mbToEither "could not determine PNG size" $ pngSize img Just Gif -> mbToEither "could not determine GIF size" $ gifSize img Just Jpeg -> jpegSize img + Just Svg -> mbToEither "could not determine SVG size" $ svgSize opts img Just Eps -> mbToEither "could not determine EPS size" $ epsSize img Just Pdf -> Left "could not determine PDF size" -- TODO Nothing -> Left "could not determine image type" @@ -161,6 +172,16 @@ inInch opts dim = (Inch a) -> a (Percent _) -> 0 +inPixel :: WriterOptions -> Dimension -> Integer +inPixel opts dim = + case dim of + (Pixel a) -> a + (Centimeter a) -> floor $ dpi * a * 0.3937007874 :: Integer + (Inch a) -> floor $ dpi * a :: Integer + _ -> 0 + where + dpi = fromIntegral $ writerDpi opts + -- | Convert a Dimension to a String denoting its equivalent in inches, for example "2.00000". -- Note: Dimensions in percentages are converted to the empty string. showInInch :: WriterOptions -> Dimension -> String @@ -170,14 +191,8 @@ showInInch opts dim = showFl $ inInch opts dim -- | Convert a Dimension to a String denoting its equivalent in pixels, for example "600". -- Note: Dimensions in percentages are converted to the empty string. showInPixel :: WriterOptions -> Dimension -> String -showInPixel opts dim = - case dim of - (Pixel a) -> show a - (Centimeter a) -> show (floor $ dpi * a * 0.3937007874 :: Int) - (Inch a) -> show (floor $ dpi * a :: Int) - (Percent _) -> "" - where - dpi = fromIntegral $ writerDpi opts +showInPixel _ (Percent _) = "" +showInPixel opts dim = show $ inPixel opts dim -- | Maybe split a string into a leading number and trailing unit, e.g. "3cm" to Just (3.0, "cm") numUnit :: String -> Maybe (Double, String) @@ -195,13 +210,11 @@ dimension dir (_, _, kvs) = Width -> extractDim "width" Height -> extractDim "height" where - extractDim key = - case lookup key kvs of - Just str -> - case numUnit str of - Just (num, unit) -> toDim num unit - Nothing -> Nothing - Nothing -> Nothing + extractDim key = lookup key kvs >>= lengthToDim + +lengthToDim :: String -> Maybe Dimension +lengthToDim s = numUnit s >>= uncurry toDim + where toDim a "cm" = Just $ Centimeter a toDim a "mm" = Just $ Centimeter (a / 10) toDim a "in" = Just $ Inch a @@ -209,6 +222,8 @@ dimension dir (_, _, kvs) = toDim a "%" = Just $ Percent a toDim a "px" = Just $ Pixel (floor a::Integer) toDim a "" = Just $ Pixel (floor a::Integer) + toDim a "pt" = Just $ Inch (a / 72) + toDim a "pc" = Just $ Inch (a / 6) toDim _ _ = Nothing epsSize :: ByteString -> Maybe ImageSize @@ -271,6 +286,22 @@ gifSize img = do } _ -> Nothing -- "GIF parse error" +svgSize :: WriterOptions -> ByteString -> Maybe ImageSize +svgSize opts img = do + doc <- Xml.parseXMLDoc $ UTF8.toString img + let dpi = fromIntegral $ writerDpi opts + let dirToInt dir = do + dim <- Xml.findAttrBy (== Xml.QName dir Nothing Nothing) doc >>= lengthToDim + return $ inPixel opts dim + w <- dirToInt "width" + h <- dirToInt "height" + return ImageSize { + pxX = w + , pxY = h + , dpiX = dpi + , dpiY = dpi + } + jpegSize :: ByteString -> Either String ImageSize jpegSize img = let (hdr, rest) = B.splitAt 4 img diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index 56aa29211..1c19c9fa6 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -1184,7 +1184,7 @@ inlineToOpenXML' opts (Image attr alt (src, title)) = do Right (img, mt) -> do ident <- ("rId"++) `fmap` ((lift . lift) getUniqueId) let (xpt,ypt) = desiredSizeInPoints opts attr - (either (const def) id (imageSize img)) + (either (const def) id (imageSize opts img)) -- 12700 emu = 1 pt let (xemu,yemu) = fitToPage (xpt * 12700, ypt * 12700) (pageWidth * 12700) let cNvPicPr = mknode "pic:cNvPicPr" [] $ @@ -1228,6 +1228,7 @@ inlineToOpenXML' opts (Image attr alt (src, title)) = do Just Gif -> ".gif" Just Pdf -> ".pdf" Just Eps -> ".eps" + Just Svg -> ".svg" Nothing -> "" if null imgext then -- without an extension there is no rule for content type diff --git a/src/Text/Pandoc/Writers/ICML.hs b/src/Text/Pandoc/Writers/ICML.hs index efec17d26..3b7d3c4da 100644 --- a/src/Text/Pandoc/Writers/ICML.hs +++ b/src/Text/Pandoc/Writers/ICML.hs @@ -546,7 +546,7 @@ imageICML opts style attr (src, _) = do report $ CouldNotFetchResource src "" return def Right (img, _) -> do - case imageSize img of + case imageSize opts img of Right size -> return size Left msg -> do report $ CouldNotDetermineImageSize src msg diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs index ee5fa4c24..61bb63d9b 100644 --- a/src/Text/Pandoc/Writers/ODT.hs +++ b/src/Text/Pandoc/Writers/ODT.hs @@ -153,7 +153,7 @@ transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = do report $ CouldNotFetchResource src "" return $ Emph lab Right (img, mbMimeType) -> do - (ptX, ptY) <- case imageSize img of + (ptX, ptY) <- case imageSize opts img of Right s -> return $ sizeInPoints s Left msg -> do report $ CouldNotDetermineImageSize src msg diff --git a/src/Text/Pandoc/Writers/RTF.hs b/src/Text/Pandoc/Writers/RTF.hs index ef012e58e..5172a0ddd 100644 --- a/src/Text/Pandoc/Writers/RTF.hs +++ b/src/Text/Pandoc/Writers/RTF.hs @@ -63,7 +63,7 @@ rtfEmbedImage opts x@(Image attr _ (src,_)) = do "image/jpeg" -> return "\\jpegblip" "image/png" -> return "\\pngblip" _ -> throwError $ PandocSomeError "Unknown file type" - sizeSpec <- case imageSize imgdata of + sizeSpec <- case imageSize opts imgdata of Left msg -> do report $ CouldNotDetermineImageSize src msg return "" |