From c5f019048086235761e39809548c84d456238b34 Mon Sep 17 00:00:00 2001 From: Evan Silberman Date: Fri, 15 Nov 2024 11:40:43 -0800 Subject: [PATCH] Flip and rotate images in ODT output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extensive experimentation with LibreOffice 24.8.3.2 on Mac didn't come up with a way to create an ODT with an image that is displayed uncropped, at the correct aspect ratio, with the correct size of bounding box, after rotating 90° or 270°, while anchored "as character". As of this commit, if the EXIF orientation says an image needs to be quarter-rotated, the solution chosen has a bounding box the original, unrotated size of the image, which displays the image correctly rotated and with the correct aspect ratio, but cropped. It is unknown to this author if this looks correct in other software than LibreOffice. Pandoc doesn't currently pull in any dependencies capable of rotating the actual pixels in image data. Document authors needing to mitigate this issue will have to edit their images themselves. --- src/Text/Pandoc/Writers/ODT.hs | 12 ++++++++++-- src/Text/Pandoc/Writers/OpenDocument.hs | 14 +++++++++++++- test/command/6792.md | 2 ++ test/command/8256.md | 2 ++ test/writer.opendocument | 2 ++ 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs index 29ee3bd47b86..eb3a1b058246 100644 --- a/src/Text/Pandoc/Writers/ODT.hs +++ b/src/Text/Pandoc/Writers/ODT.hs @@ -257,11 +257,19 @@ transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = catchError Left msg -> do report $ CouldNotDetermineImageSize src msg return (100, 100) + let (ImageTransform flp rot) = imageTransform img + let xflip NoFlip = ("mirror", "none") + xflip FlipH = ("mirror", "horizontal") + xflip FlipV = ("mirror", "vertical") + let xrotate R0 = ("rotate", "rotate(0)") + xrotate R90 = ("rotate", "rotate(" <> showFl (3*(pi :: Double)/2) <> ")") + xrotate R180 = ("rotate", "rotate(" <> showFl (pi :: Double) <> ")") + xrotate R270 = ("rotate", "rotate(" <> showFl ((pi :: Double) /2) <> ")") let dims = case (getDim Width, getDim Height) of (Just w, Just h) -> [("width", tshow w), ("height", tshow h)] (Just w@(Percent _), Nothing) -> [("rel-width", tshow w),("rel-height", "scale"),("width", tshow ptX <> "pt"),("height", tshow ptY <> "pt")] - (Nothing, Just h@(Percent _)) -> [("rel-width", "scale"),("rel-height", tshow h),("width", tshow ptX <> "pt"),("height", tshow ptY <> "pt")] + (Nothing, Just h@(Percent _)) -> [("rel-width", "scale"),("rel-height", tshow h),("width", tshow ptY <> "pt"),("height", tshow ptY <> "pt")] (Just w@(Inch i), Nothing) -> [("width", tshow w), ("height", tshow (i / ratio) <> "in")] (Nothing, Just h@(Inch i)) -> [("width", tshow (i * ratio) <> "in"), ("height", tshow h)] _ -> [("width", tshow ptX <> "pt"), ("height", tshow ptY <> "pt")] @@ -271,7 +279,7 @@ transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = catchError Just (Percent i) -> Just $ Percent i Just dim -> Just $ Inch $ inInch opts dim Nothing -> Nothing - let newattr = (id', cls, dims) + let newattr = (id', cls, (xflip flp):(xrotate rot):dims) src' <- if writerLinkImages opts then case T.unpack src of diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs index 85df9c70131e..2e2accb32f78 100644 --- a/src/Text/Pandoc/Writers/OpenDocument.hs +++ b/src/Text/Pandoc/Writers/OpenDocument.hs @@ -198,6 +198,15 @@ formulaStyle mt = inTags False "style:style" ,("style:horizontal-rel", "paragraph-content") ,("style:wrap", "none")] +imageStyles :: [Doc Text] +imageStyles = [mirror "horizontal", mirror "vertical"] + where + mirror hv = inTags False "style:style" + [("style:name", "mirror-" <> hv) + ,("style:family", "graphic") + ,("style:parent-style-name", "Graphics")] + $ selfClosingTag "style:graphic-properties" [("style:mirror", hv)] + inBookmarkTags :: Text -> Doc Text -> Doc Text inBookmarkTags ident d = selfClosingTag "text:bookmark-start" [ ("text:name", ident) ] @@ -260,7 +269,7 @@ writeOpenDocument opts (Pandoc meta blocks) = do meta' b <- blocksToOpenDocument opts blocks return (b, m) - let styles = stTableStyles s ++ stParaStyles s ++ formulaStyles ++ + let styles = stTableStyles s ++ stParaStyles s ++ formulaStyles ++ imageStyles ++ map snd (sortBy (flip (comparing fst)) ( Map.elems (stTextStyles s))) listStyle (n,l) = inTags True "text:list-style" @@ -659,6 +668,9 @@ inlineToOpenDocument o ils id' <- gets stImageId modify (\st -> st{ stImageId = id' + 1 }) let getDims [] = [] + getDims (("mirror", "none") :xs) = getDims xs + getDims (("mirror", t) :xs) = ("draw:style-name", "mirror-" <> t) : getDims xs + getDims (("rotate", t) :xs) = ("draw:transform", t) : getDims xs getDims (("width", w) :xs) = ("svg:width", w) : getDims xs getDims (("rel-width", w):xs) = ("style:rel-width", w) : getDims xs getDims (("height", h):xs) = ("svg:height", h) : getDims xs diff --git a/test/command/6792.md b/test/command/6792.md index d0d284f5dfd6..f477fc3e6db7 100644 --- a/test/command/6792.md +++ b/test/command/6792.md @@ -22,6 +22,8 @@ + + diff --git a/test/command/8256.md b/test/command/8256.md index 76398f607ae6..e0cbe8b02a11 100644 --- a/test/command/8256.md +++ b/test/command/8256.md @@ -17,6 +17,8 @@ Testing. + + diff --git a/test/writer.opendocument b/test/writer.opendocument index f10f3be2a0ce..4e5d00622c43 100644 --- a/test/writer.opendocument +++ b/test/writer.opendocument @@ -1017,6 +1017,8 @@ + +