git.iko.soy/typeable/pandoc
on master help sign in
Powerpoint writer: Make content shape retrieval environment-aware

We put `getContentShape` and `getContentShapeSize` inside the P monad, so that we can (in the future) make use of knowledge of what slide environment we're in to get the correct shape. This will allow us, for example, to get individual columns for a two-column layout, and place images in them appropriately.

commit15772896720f082cbaa44e5e556e6db1c9229756 authorJesse Rosenthal <jrosenthal@jhu.edu> dateSun 14 Jan 2018, 01:10 (9 years ago) parente7d95ca
1 file changed+48−28
src/Text/Pandoc/Writers/Powerpoint.hs+48−28
src/Text/Pandoc/Writers/Powerpoint.hs+48−28
@@ -32,7 +32,7 @@ Conversion of 'Pandoc' documents to powerpoint (pptx).
3232
3333module Text.Pandoc.Writers.Powerpoint (writePowerpoint) where
3434
35−import Control.Monad.Except (throwError)
35+import Control.Monad.Except (throwError, catchError)
3636import Control.Monad.Reader
3737import Control.Monad.State
3838import Codec.Archive.Zip
@@ -126,6 +126,7 @@ data WriterEnv = WriterEnv { envMetadata :: Meta
126126 -- the end of the slide file name and
127127 -- the rId number
128128 , envSlideIdOffset :: Int
129+ , envColumnNumber :: Maybe Int
129130 }
130131 deriving (Show)
131132
@@ -144,6 +145,7 @@ instance Default WriterEnv where
144145 , envInNoteSlide = False
145146 , envCurSlideId = 1
146147 , envSlideIdOffset = 1
148+ , envColumnNumber = Nothing
147149 }
148150
149151data MediaInfo = MediaInfo { mInfoFilePath :: FilePath
@@ -905,11 +907,23 @@ shapeHasId ns ident element
905907 nm == ident
906908 | otherwise = False
907909
908−getContentShape :: NameSpaces -> Element -> Maybe Element
910+-- The content shape in slideLayout2 (Title/Content) has id=3 In
911+-- slideLayout4 (two column) the left column is id=3, and the right
912+-- column is id=4.
913+getContentShape :: PandocMonad m => NameSpaces -> Element -> P m Element
909914getContentShape ns spTreeElem
910915 | isElem ns "p" "spTree" spTreeElem =
911− filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns "Content Placeholder 2" e)) spTreeElem
912− | otherwise = Nothing
916+ case filterChild
917+ (\e -> (isElem ns "p" "sp" e) && (shapeHasId ns "3" e))
918+ spTreeElem
919+ of
920+ Just e -> return e
921+ Nothing -> throwError $
922+ PandocSomeError $
923+ "Could not find shape for Powerpoint content"
924+getContentShape _ _ = throwError $
925+ PandocSomeError $
926+ "Attempted to find content on non shapeTree"
913927
914928getShapeDimensions :: NameSpaces
915929 -> Element
@@ -942,25 +956,31 @@ getMasterShapeDimensionsById ident master = do
942956 sp <- filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasId ns ident e)) spTree
943957 getShapeDimensions ns sp
944958
945−getContentShapeSize :: NameSpaces
959+getContentShapeSize :: PandocMonad m
960+ => NameSpaces
946961 -> Element
947962 -> Element
948− -> Maybe ((Integer, Integer), (Integer, Integer))
963+ -> P m ((Integer, Integer), (Integer, Integer))
949964getContentShapeSize ns layout master
950965 | isElem ns "p" "sldLayout" layout
951966 , Just cSld <- findChild (elemName ns "p" "cSld") layout
952− , Just spTree <- findChild (elemName ns "p" "spTree") cSld
953− , Just sp <- getContentShape ns spTree
954− , Just sz <- getShapeDimensions ns sp = Just sz
955− | isElem ns "p" "sldLayout" layout
956− , Just cSld <- findChild (elemName ns "p" "cSld") layout
957− , Just spTree <- findChild (elemName ns "p" "spTree") cSld
958− , Just sp <- getContentShape ns spTree
959− , Just ident <- findChild (elemName ns "p" "nvSpPr") sp >>=
960− findChild (elemName ns "p" "cNvPr") >>=
961− findAttr (QName "id" Nothing Nothing)
962− , Just sz <- getMasterShapeDimensionsById ident master = Just sz
963− | otherwise = Nothing
967+ , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
968+ sp <- getContentShape ns spTree
969+ case getShapeDimensions ns sp of
970+ Just sz -> return sz
971+ Nothing -> do let mbSz =
972+ findChild (elemName ns "p" "nvSpPr") sp >>=
973+ findChild (elemName ns "p" "cNvPr") >>=
974+ findAttr (QName "id" Nothing Nothing) >>=
975+ flip getMasterShapeDimensionsById master
976+ case mbSz of
977+ Just sz' -> return sz'
978+ Nothing -> throwError $
979+ PandocSomeError $
980+ "Couldn't find necessary content shape size"
981+getContentShapeSize _ _ _ = throwError $
982+ PandocSomeError $
983+ "Attempted to find content shape size in non-layout"
964984
965985replaceNamedChildren :: NameSpaces
966986 -> String
@@ -1198,11 +1218,11 @@ makePicElements layout picProps mInfo _ alt = do
11981218 Left _ -> sizeInPixels $ def
11991219 master <- getMaster
12001220 let ns = elemToNameSpaces layout
1201− let ((x, y), (cx, cytmp)) = case getContentShapeSize ns layout master of
1202− Just dims -> dims
1203− Nothing -> ((0, 0), (pageWidth, pageHeight))
1221+ ((x, y), (cx, cytmp)) <- getContentShapeSize ns layout master
1222+ `catchError`
1223+ (\_ -> return ((0, 0), (pageWidth, pageHeight)))
12041224
1205− cy = if hasCaption then cytmp - captionHeight else cytmp
1225+ let cy = if hasCaption then cytmp - captionHeight else cytmp
12061226
12071227 let imgRatio = fromIntegral pxX / fromIntegral pxY :: Double
12081228 boxRatio = fromIntegral cx / fromIntegral cy :: Double
@@ -1390,8 +1410,8 @@ shapeToElement :: PandocMonad m => Element -> Shape -> P m Element
13901410shapeToElement layout (TextBox paras)
13911411 | ns <- elemToNameSpaces layout
13921412 , Just cSld <- findChild (elemName ns "p" "cSld") layout
1393− , Just spTree <- findChild (elemName ns "p" "spTree") cSld
1394− , Just sp <- getContentShape ns spTree = do
1413+ , Just spTree <- findChild (elemName ns "p" "spTree") cSld = do
1414+ sp <- getContentShape ns spTree
13951415 elements <- mapM paragraphToElement paras
13961416 let txBody = mknode "p:txBody" [] $
13971417 [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] ++ elements
@@ -1430,11 +1450,11 @@ graphicFrameToElements layout tbls caption = do
14301450 master <- getMaster
14311451 (pageWidth, pageHeight) <- asks envPresentationSize
14321452 let ns = elemToNameSpaces layout
1433− let ((x, y), (cx, cytmp)) = case getContentShapeSize ns layout master of
1434− Just dims -> dims
1435− Nothing -> ((0, 0), (pageWidth, pageHeight))
1453+ ((x, y), (cx, cytmp)) <- getContentShapeSize ns layout master
1454+ `catchError`
1455+ (\_ -> return ((0, 0), (pageWidth, pageHeight)))
14361456
1437− cy = if (not $ null caption) then cytmp - captionHeight else cytmp
1457+ let cy = if (not $ null caption) then cytmp - captionHeight else cytmp
14381458
14391459 elements <- mapM graphicToElement tbls
14401460 let graphicFrameElts =