You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TestXSLFBugs.java 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.xslf;
  16. import static org.apache.poi.POITestCase.assertContains;
  17. import static org.junit.Assert.*;
  18. import java.awt.Color;
  19. import java.awt.Dimension;
  20. import java.awt.Graphics2D;
  21. import java.awt.RenderingHints;
  22. import java.awt.geom.AffineTransform;
  23. import java.awt.geom.Rectangle2D;
  24. import java.awt.image.BufferedImage;
  25. import java.io.ByteArrayInputStream;
  26. import java.io.ByteArrayOutputStream;
  27. import java.io.File;
  28. import java.io.IOException;
  29. import java.io.InputStream;
  30. import java.net.URI;
  31. import java.util.ArrayList;
  32. import java.util.Collection;
  33. import java.util.List;
  34. import java.util.Optional;
  35. import java.util.function.Function;
  36. import java.util.stream.Collectors;
  37. import javax.imageio.ImageIO;
  38. import org.apache.poi.POIDataSamples;
  39. import org.apache.poi.ooxml.POIXMLDocumentPart;
  40. import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
  41. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  42. import org.apache.poi.openxml4j.opc.OPCPackage;
  43. import org.apache.poi.openxml4j.opc.PackagePartName;
  44. import org.apache.poi.openxml4j.opc.PackagingURIHelper;
  45. import org.apache.poi.sl.draw.DrawPaint;
  46. import org.apache.poi.sl.extractor.SlideShowExtractor;
  47. import org.apache.poi.sl.usermodel.PaintStyle;
  48. import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
  49. import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;
  50. import org.apache.poi.sl.usermodel.PictureData;
  51. import org.apache.poi.sl.usermodel.PictureData.PictureType;
  52. import org.apache.poi.sl.usermodel.PictureShape;
  53. import org.apache.poi.sl.usermodel.Shape;
  54. import org.apache.poi.sl.usermodel.ShapeType;
  55. import org.apache.poi.sl.usermodel.Slide;
  56. import org.apache.poi.sl.usermodel.VerticalAlignment;
  57. import org.apache.poi.util.IOUtils;
  58. import org.apache.poi.xslf.usermodel.XMLSlideShow;
  59. import org.apache.poi.xslf.usermodel.XSLFAutoShape;
  60. import org.apache.poi.xslf.usermodel.XSLFGroupShape;
  61. import org.apache.poi.xslf.usermodel.XSLFHyperlink;
  62. import org.apache.poi.xslf.usermodel.XSLFNotes;
  63. import org.apache.poi.xslf.usermodel.XSLFPictureData;
  64. import org.apache.poi.xslf.usermodel.XSLFPictureShape;
  65. import org.apache.poi.xslf.usermodel.XSLFRelation;
  66. import org.apache.poi.xslf.usermodel.XSLFShape;
  67. import org.apache.poi.xslf.usermodel.XSLFSlide;
  68. import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
  69. import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
  70. import org.apache.poi.xslf.usermodel.XSLFTable;
  71. import org.apache.poi.xslf.usermodel.XSLFTableCell;
  72. import org.apache.poi.xslf.usermodel.XSLFTableRow;
  73. import org.apache.poi.xslf.usermodel.XSLFTextBox;
  74. import org.apache.poi.xslf.usermodel.XSLFTextParagraph;
  75. import org.apache.poi.xslf.usermodel.XSLFTextRun;
  76. import org.junit.Ignore;
  77. import org.junit.Test;
  78. import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
  79. import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
  80. public class TestXSLFBugs {
  81. private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
  82. @Test
  83. public void bug62929() throws Exception {
  84. try(XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("missing-blip-fill.pptx")) {
  85. assertEquals(1, ss1.getSlides().size());
  86. XSLFSlide slide = ss1.getSlides().get(0);
  87. assertEquals(slide.getShapes().size(), 1);
  88. XSLFPictureShape picture = (XSLFPictureShape)slide.getShapes().get(0);
  89. assertEquals(picture.getShapeId(), 662);
  90. assertFalse(picture.isExternalLinkedPicture());
  91. assertNull(picture.getPictureData());
  92. assertNull(picture.getPictureLink());
  93. assertNull(picture.getClipping());
  94. }
  95. }
  96. @Test
  97. public void bug62736() throws Exception {
  98. XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx");
  99. assertEquals(1, ss1.getSlides().size());
  100. XSLFSlide slide0 = ss1.getSlides().get(0);
  101. assertEquals(slide0.getShapes().size(), 4);
  102. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  103. assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
  104. assertRelation(slide0, "/ppt/media/image1.png", "rId2");
  105. assertEquals(slide0.getRelations().size(), 2);
  106. List<XSLFPictureShape> pictures = new ArrayList<>();
  107. for (XSLFShape shape : slide0.getShapes()) {
  108. if (shape instanceof XSLFPictureShape) {
  109. pictures.add((XSLFPictureShape) shape);
  110. }
  111. }
  112. assertEquals(pictures.size(), 2);
  113. assertEquals(pictures.get(0).getPictureData().getFileName(), "image1.png");
  114. assertEquals(pictures.get(1).getPictureData().getFileName(), "image1.png");
  115. // blipId is rId2 of both pictures
  116. // remove just the first picture
  117. slide0.removeShape(pictures.get(0));
  118. assertEquals(slide0.getShapes().size(), 3);
  119. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  120. assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
  121. // the bug is that the following relation is gone
  122. assertRelation(slide0, "/ppt/media/image1.png", "rId2");
  123. assertEquals(slide0.getRelations().size(), 2);
  124. // Save and re-load
  125. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss1);
  126. ss1.close();
  127. assertEquals(1, ss2.getSlides().size());
  128. slide0 = ss2.getSlides().get(0);
  129. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  130. assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
  131. assertRelation(slide0, "/ppt/media/image1.png", "rId2");
  132. assertEquals(slide0.getRelations().size(), 2);
  133. pictures.clear();
  134. for (XSLFShape shape : slide0.getShapes()) {
  135. if (shape instanceof XSLFPictureShape) {
  136. pictures.add((XSLFPictureShape) shape);
  137. }
  138. }
  139. assertEquals(pictures.size(), 1);
  140. assertEquals(pictures.get(0).getPictureData().getFileName(), "image1.png");
  141. slide0.removeShape(pictures.get(0));
  142. assertEquals(slide0.getShapes().size(), 2);
  143. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  144. assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
  145. assertNull(slide0.getRelationById("rId2"));
  146. assertEquals(slide0.getRelations().size(), 1);
  147. // Save and re-load
  148. XMLSlideShow ss3 = XSLFTestDataSamples.writeOutAndReadBack(ss2);
  149. ss2.close();
  150. assertEquals(1, ss3.getSlides().size());
  151. slide0 = ss3.getSlides().get(0);
  152. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  153. assertRelation(slide0, "/ppt/slideLayouts/slideLayout1.xml", "rId1");
  154. assertEquals(slide0.getShapes().size(), 2);
  155. ss3.close();
  156. }
  157. @Test
  158. public void bug61589() throws IOException {
  159. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  160. try (XMLSlideShow src = new XMLSlideShow();
  161. XMLSlideShow dest = new XMLSlideShow()) {
  162. XSLFSlide slide = src.createSlide();
  163. XSLFSlide slide2 = src.createSlide();
  164. XSLFTextBox shape = slide.createTextBox();
  165. shape.setAnchor(new Rectangle2D.Double(100,100,400,100));
  166. XSLFTextParagraph p = shape.addNewTextParagraph();
  167. XSLFTextRun r = p.addNewTextRun();
  168. p.addLineBreak();
  169. r.setText("Apache POI");
  170. r.createHyperlink().setAddress("http://poi.apache.org");
  171. // create hyperlink pointing to a page, which isn't available at the time of importing the content
  172. r = p.addNewTextRun();
  173. r.setText("Slide 2");
  174. r.createHyperlink().linkToSlide(slide2);
  175. shape = slide2.createTextBox();
  176. shape.setAnchor(new Rectangle2D.Double(100,100,400,100));
  177. shape.setText("slide 2");
  178. dest.createSlide().importContent(slide);
  179. dest.createSlide().importContent(slide2);
  180. dest.write(bos);
  181. }
  182. try (XMLSlideShow ppt = new XMLSlideShow(new ByteArrayInputStream(bos.toByteArray()))) {
  183. XSLFSlide slide = ppt.getSlides().get(0);
  184. XSLFTextBox shape = (XSLFTextBox)slide.getShapes().get(0);
  185. XSLFTextParagraph p = shape.getTextParagraphs().get(1);
  186. XSLFHyperlink h1 = p.getTextRuns().get(0).getHyperlink();
  187. assertNotNull(h1);
  188. assertEquals("http://poi.apache.org", h1.getAddress());
  189. XSLFHyperlink h2 = p.getTextRuns().get(2).getHyperlink();
  190. assertNotNull(h2);
  191. // relative url will be resolved to an absolute url, therefore this doesn't equals to "slide2.xml"
  192. assertEquals("/ppt/slides/slide2.xml", h2.getAddress());
  193. RelationPart sldRef = slide.getRelationPartById(h2.getXmlObject().getId());
  194. assertTrue(sldRef.getDocumentPart() instanceof XSLFSlide);
  195. }
  196. }
  197. @Test
  198. public void bug62587() throws IOException {
  199. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  200. try (XMLSlideShow ppt = new XMLSlideShow()) {
  201. Slide slide = ppt.createSlide();
  202. XSLFPictureData pd = ppt.addPicture(slTests.getFile("wrench.emf"), PictureType.EMF);
  203. PictureShape ps = slide.createPicture(pd);
  204. ps.setAnchor(new Rectangle2D.Double(100,100,100,100));
  205. ppt.write(bos);
  206. }
  207. Object[][] pics = {
  208. {"santa.wmf", PictureType.WMF, XSLFRelation.IMAGE_WMF},
  209. {"tomcat.png",PictureType.PNG, XSLFRelation.IMAGE_PNG},
  210. {"clock.jpg", PictureType.JPEG, XSLFRelation.IMAGE_JPEG}
  211. };
  212. try (XMLSlideShow ppt = new XMLSlideShow(new ByteArrayInputStream(bos.toByteArray()))) {
  213. XSLFSlide s1 = ppt.getSlides().get(0);
  214. for (Object[] p : pics) {
  215. XSLFSlide s2 = ppt.createSlide();
  216. s2.importContent(s1);
  217. XSLFPictureData pd = ppt.addPicture(slTests.getFile((String)p[0]), (PictureType)p[1]);
  218. XSLFPictureShape ps = (XSLFPictureShape) s2.getShapes().get(0);
  219. Rectangle2D anchor = ps.getAnchor();
  220. s2.removeShape(ps);
  221. ps = s2.createPicture(pd);
  222. ps.setAnchor(anchor);
  223. }
  224. bos.reset();
  225. ppt.write(bos);
  226. }
  227. try (XMLSlideShow ppt = new XMLSlideShow(new ByteArrayInputStream(bos.toByteArray()))) {
  228. for (XSLFSlide sl : ppt.getSlides()) {
  229. List<RelationPart> rels = sl.getRelationParts();
  230. assertEquals(2, rels.size());
  231. RelationPart rel0 = rels.get(0);
  232. assertEquals("rId1", rel0.getRelationship().getId());
  233. assertEquals(XSLFRelation.SLIDE_LAYOUT.getRelation(), rel0.getRelationship().getRelationshipType());
  234. RelationPart rel1 = rels.get(1);
  235. assertEquals("rId2", rel1.getRelationship().getId());
  236. assertEquals(XSLFRelation.IMAGES.getRelation(), rel1.getRelationship().getRelationshipType());
  237. }
  238. }
  239. }
  240. @Test
  241. public void bug60499() throws IOException, InvalidFormatException {
  242. InputStream is = slTests.openResourceAsStream("bug60499.pptx");
  243. byte[] buf = IOUtils.toByteArray(is);
  244. is.close();
  245. PackagePartName ppn = PackagingURIHelper.createPartName("/ppt/media/image1.png");
  246. XMLSlideShow ppt1 = new XMLSlideShow(new ByteArrayInputStream(buf));
  247. XSLFSlide slide1 = ppt1.getSlides().get(0);
  248. Optional<XSLFShape> shapeToDelete1 =
  249. slide1.getShapes().stream().filter(s -> s instanceof XSLFPictureShape).findFirst();
  250. assertTrue(shapeToDelete1.isPresent());
  251. slide1.removeShape(shapeToDelete1.get());
  252. assertTrue(slide1.getRelationParts().stream()
  253. .allMatch(rp -> "rId1,rId3".contains(rp.getRelationship().getId()) ));
  254. assertNotNull(ppt1.getPackage().getPart(ppn));
  255. ppt1.close();
  256. XMLSlideShow ppt2 = new XMLSlideShow(new ByteArrayInputStream(buf));
  257. XSLFSlide slide2 = ppt2.getSlides().get(0);
  258. Optional<XSLFShape> shapeToDelete2 =
  259. slide2.getShapes().stream().filter(s -> s instanceof XSLFPictureShape).skip(1).findFirst();
  260. assertTrue(shapeToDelete2.isPresent());
  261. slide2.removeShape(shapeToDelete2.get());
  262. assertTrue(slide2.getRelationParts().stream()
  263. .allMatch(rp -> "rId1,rId2".contains(rp.getRelationship().getId()) ));
  264. assertNotNull(ppt2.getPackage().getPart(ppn));
  265. ppt2.close();
  266. XMLSlideShow ppt3 = new XMLSlideShow(new ByteArrayInputStream(buf));
  267. XSLFSlide slide3 = ppt3.getSlides().get(0);
  268. slide3.getShapes().stream()
  269. .filter(s -> s instanceof XSLFPictureShape)
  270. .collect(Collectors.toList())
  271. .forEach(slide3::removeShape);
  272. assertNull(ppt3.getPackage().getPart(ppn));
  273. ppt3.close();
  274. }
  275. @Test
  276. public void bug51187() throws Exception {
  277. XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("51187.pptx");
  278. assertEquals(1, ss1.getSlides().size());
  279. // Check the relations on it
  280. // Note - rId3 is a self reference
  281. XSLFSlide slide0 = ss1.getSlides().get(0);
  282. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  283. assertRelation(slide0, "/ppt/slideLayouts/slideLayout12.xml", "rId1");
  284. assertRelation(slide0, "/ppt/notesSlides/notesSlide1.xml", "rId2");
  285. assertRelation(slide0, "/ppt/slides/slide1.xml", "rId3");
  286. assertRelation(slide0, "/ppt/media/image1.png", "rId4");
  287. // Save and re-load
  288. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss1);
  289. ss1.close();
  290. assertEquals(1, ss2.getSlides().size());
  291. slide0 = ss2.getSlides().get(0);
  292. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  293. assertRelation(slide0, "/ppt/slideLayouts/slideLayout12.xml", "rId1");
  294. assertRelation(slide0, "/ppt/notesSlides/notesSlide1.xml", "rId2");
  295. // TODO Fix this
  296. assertRelation(slide0, "/ppt/slides/slide1.xml", "rId3");
  297. assertRelation(slide0, "/ppt/media/image1.png", "rId4");
  298. ss2.close();
  299. }
  300. private static void assertRelation(XSLFSlide slide, String exp, String rId) {
  301. POIXMLDocumentPart pd = (rId != null) ? slide.getRelationById(rId) : slide;
  302. assertNotNull(pd);
  303. assertEquals(exp, pd.getPackagePart().getPartName().getName());
  304. }
  305. /**
  306. * Slide relations with anchors in them
  307. */
  308. @Test
  309. public void tika705() throws Exception {
  310. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
  311. // Should have one slide
  312. assertEquals(1, ss.getSlides().size());
  313. XSLFSlide slide = ss.getSlides().get(0);
  314. // Check the relations from this
  315. Collection<RelationPart> rels = slide.getRelationParts();
  316. // Should have 6 relations:
  317. // 1 external hyperlink (skipped from list)
  318. // 4 internal hyperlinks
  319. // 1 slide layout
  320. assertEquals(5, rels.size());
  321. int layouts = 0;
  322. int hyperlinks = 0;
  323. for(RelationPart p : rels) {
  324. if(p.getRelationship().getRelationshipType().equals(XSLFRelation.HYPERLINK.getRelation())) {
  325. hyperlinks++;
  326. } else if(p.getDocumentPart() instanceof XSLFSlideLayout) {
  327. layouts++;
  328. }
  329. }
  330. assertEquals(1, layouts);
  331. assertEquals(4, hyperlinks);
  332. // Hyperlinks should all be to #_ftn1 or #ftnref1
  333. for(RelationPart p : rels) {
  334. if(p.getRelationship().getRelationshipType().equals(XSLFRelation.HYPERLINK.getRelation())) {
  335. URI target = p.getRelationship().getTargetURI();
  336. //noinspection StatementWithEmptyBody
  337. if(target.getFragment().equals("_ftn1") ||
  338. target.getFragment().equals("_ftnref1")) {
  339. // Good
  340. } else {
  341. fail("Invalid target " + target.getFragment() + " on " + target);
  342. }
  343. }
  344. }
  345. ss.close();
  346. }
  347. /**
  348. * A slideshow can have more than one rID pointing to a given
  349. * slide, eg presentation.xml rID1 -> slide1.xml, but slide1.xml
  350. * rID2 -> slide3.xml
  351. */
  352. @Test
  353. public void bug54916() throws IOException {
  354. try (XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("OverlappingRelations.pptx")) {
  355. XSLFSlide slide;
  356. // Should find 4 slides
  357. assertEquals(4, ss.getSlides().size());
  358. // Check the text, to see we got them in order
  359. slide = ss.getSlides().get(0);
  360. assertContains(getSlideText(ss, slide), "POI cannot read this");
  361. slide = ss.getSlides().get(1);
  362. assertContains(getSlideText(ss, slide), "POI can read this");
  363. assertContains(getSlideText(ss, slide), "Has a relationship to another slide");
  364. slide = ss.getSlides().get(2);
  365. assertContains(getSlideText(ss, slide), "POI can read this");
  366. slide = ss.getSlides().get(3);
  367. assertContains(getSlideText(ss, slide), "POI can read this");
  368. }
  369. }
  370. /**
  371. * When the picture is not embedded but inserted only as a "link to file",
  372. * there is no data available and XSLFPictureShape.getPictureData()
  373. * gives a NPE, see bug #56812
  374. */
  375. @Test
  376. public void bug56812() throws Exception {
  377. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("56812.pptx");
  378. int internalPictures = 0;
  379. int externalPictures = 0;
  380. for (XSLFSlide slide : ppt.getSlides()){
  381. for (XSLFShape shape : slide.getShapes()){
  382. assertNotNull(shape);
  383. if (shape instanceof XSLFPictureShape) {
  384. XSLFPictureShape picture = (XSLFPictureShape)shape;
  385. if (picture.isExternalLinkedPicture()) {
  386. externalPictures++;
  387. assertNotNull(picture.getPictureLink());
  388. } else {
  389. internalPictures++;
  390. XSLFPictureData data = picture.getPictureData();
  391. assertNotNull(data);
  392. assertNotNull(data.getFileName());
  393. }
  394. }
  395. }
  396. }
  397. assertEquals(2, internalPictures);
  398. assertEquals(1, externalPictures);
  399. ppt.close();
  400. }
  401. @Test
  402. @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix")
  403. public void bug54542() throws Exception {
  404. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("54542_cropped_bitmap.pptx");
  405. Dimension pgsize = ss.getPageSize();
  406. XSLFSlide slide = ss.getSlides().get(0);
  407. // render it
  408. double zoom = 1;
  409. AffineTransform at = new AffineTransform();
  410. at.setToScale(zoom, zoom);
  411. BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR);
  412. Graphics2D graphics = imgActual.createGraphics();
  413. graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  414. graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  415. graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
  416. graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  417. graphics.setTransform(at);
  418. graphics.setPaint(Color.white);
  419. graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
  420. slide.draw(graphics);
  421. ImageIO.write(imgActual, "PNG", new File("bug54542.png"));
  422. ss.close();
  423. }
  424. private String getSlideText(XMLSlideShow ppt, XSLFSlide slide) throws IOException {
  425. try (SlideShowExtractor<XSLFShape,XSLFTextParagraph> extr = new SlideShowExtractor<>(ppt)) {
  426. // do not auto-close the slideshow
  427. extr.setFilesystem(null);
  428. extr.setSlidesByDefault(true);
  429. extr.setNotesByDefault(false);
  430. extr.setMasterByDefault(false);
  431. return extr.getText(slide);
  432. }
  433. }
  434. @Test
  435. public void bug57250() throws Exception {
  436. XMLSlideShow ss = new XMLSlideShow();
  437. for (String s : new String[]{"Slide1","Slide2"}) {
  438. ss.createSlide().createTextBox().setText(s);
  439. }
  440. validateSlides(ss, false, "Slide1","Slide2");
  441. XSLFSlide slide = ss.createSlide();
  442. slide.createTextBox().setText("New slide");
  443. validateSlides(ss, true, "Slide1","Slide2","New slide");
  444. // Move backward
  445. ss.setSlideOrder(slide, 0);
  446. validateSlides(ss, true, "New slide","Slide1","Slide2");
  447. // Move forward
  448. ss.setSlideOrder(slide, 1);
  449. validateSlides(ss, true, "Slide1","New slide","Slide2");
  450. // Move to end
  451. ss.setSlideOrder(slide, 0);
  452. ss.setSlideOrder(slide, 2);
  453. validateSlides(ss, true, "Slide1","Slide2","New slide");
  454. ss.close();
  455. }
  456. /**
  457. * When working with >9 images, make sure the sorting ensures
  458. * that image10.foo isn't between image1.foo and image2.foo
  459. */
  460. @Test
  461. public void test57552() throws Exception {
  462. XMLSlideShow ss = new XMLSlideShow();
  463. for (String s : new String[]{"Slide1","Slide2"}) {
  464. ss.createSlide().createTextBox().setText(s);
  465. }
  466. // Slide starts with just layout relation
  467. XSLFSlide slide = ss.getSlides().get(0);
  468. assertEquals(0, ss.getPictureData().size());
  469. assertEquals(1, slide.getShapes().size());
  470. assertEquals(1, slide.getRelations().size());
  471. final XSLFRelation expected = XSLFRelation.SLIDE_LAYOUT;
  472. final POIXMLDocumentPart relation = slide.getRelations().get(0);
  473. assertEquals(expected.getContentType(), relation.getPackagePart().getContentType());
  474. assertEquals(expected.getFileName(expected.getFileNameIndex(relation)), relation.getPackagePart().getPartName().getName());
  475. // Some dummy pictures
  476. byte[][] pics = new byte[15][3];
  477. for (int i=0; i<pics.length; i++) {
  478. for (int j=0; j<pics[i].length; j++) {
  479. pics[i][j] = (byte)i;
  480. }
  481. }
  482. // Add a few pictures
  483. addPictures(ss, slide, pics, 0, 10);
  484. // Re-fetch the pictures and check
  485. for (int i=0; i<10; i++) {
  486. XSLFPictureShape shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  487. assertNotNull(shape.getPictureData());
  488. assertArrayEquals(pics[i], shape.getPictureData().getData());
  489. }
  490. // Add past 10
  491. addPictures(ss, slide, pics, 10, 15);
  492. // Check all pictures
  493. for (int i=0; i<15; i++) {
  494. XSLFPictureShape shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  495. assertNotNull(shape.getPictureData());
  496. assertArrayEquals(pics[i], shape.getPictureData().getData());
  497. }
  498. // Add a duplicate, check the right one is picked
  499. XSLFPictureData data = ss.addPicture(pics[3], PictureType.JPEG);
  500. assertEquals(3, data.getIndex());
  501. assertEquals(15, ss.getPictureData().size());
  502. XSLFPictureShape shape = slide.createPicture(data);
  503. assertNotNull(shape.getPictureData());
  504. assertArrayEquals(pics[3], shape.getPictureData().getData());
  505. assertEquals(17, slide.getShapes().size());
  506. // Save and re-load
  507. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss);
  508. slide = ss2.getSlides().get(0);
  509. // Check the 15 individual ones added
  510. for (int i=0; i<15; i++) {
  511. shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  512. assertNotNull(shape.getPictureData());
  513. assertArrayEquals(pics[i], shape.getPictureData().getData());
  514. }
  515. // Check the duplicate
  516. shape = (XSLFPictureShape)slide.getShapes().get(16);
  517. assertNotNull(shape.getPictureData());
  518. assertArrayEquals(pics[3], shape.getPictureData().getData());
  519. // Add another duplicate
  520. data = ss2.addPicture(pics[5], PictureType.JPEG);
  521. assertEquals(5, data.getIndex());
  522. assertEquals(15, ss2.getPictureData().size());
  523. shape = slide.createPicture(data);
  524. assertNotNull(shape.getPictureData());
  525. assertArrayEquals(pics[5], shape.getPictureData().getData());
  526. assertEquals(18, slide.getShapes().size());
  527. ss2.close();
  528. ss.close();
  529. }
  530. private void addPictures(XMLSlideShow ss, XSLFSlide slide, byte[][] pics, int start, int end) {
  531. for (int i = start; i< end; i++) {
  532. XSLFPictureData data = ss.addPicture(pics[i], PictureType.JPEG);
  533. assertEquals(i, data.getIndex());
  534. assertEquals(i+1, ss.getPictureData().size());
  535. XSLFPictureShape shape = slide.createPicture(data);
  536. assertNotNull(shape.getPictureData());
  537. assertArrayEquals(pics[i], shape.getPictureData().getData());
  538. assertEquals(i+2, slide.getShapes().size());
  539. }
  540. }
  541. private void validateSlides(XMLSlideShow ss, boolean saveAndReload, String... slideTexts) throws IOException {
  542. if (saveAndReload) {
  543. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss);
  544. validateSlides(ss, slideTexts);
  545. ss2.close();
  546. } else {
  547. validateSlides(ss, slideTexts);
  548. }
  549. }
  550. private void validateSlides(XMLSlideShow ss, String... slideTexts) throws IOException {
  551. assertEquals(slideTexts.length, ss.getSlides().size());
  552. for (int i = 0; i < slideTexts.length; i++) {
  553. XSLFSlide slide = ss.getSlides().get(i);
  554. assertContains(getSlideText(ss, slide), slideTexts[i]);
  555. }
  556. }
  557. @Test
  558. public void bug58205() throws IOException {
  559. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("themes.pptx");
  560. int i = 1;
  561. for (XSLFSlideMaster sm : ss.getSlideMasters()) {
  562. assertEquals("rId"+(i++), ss.getRelationId(sm));
  563. }
  564. ss.close();
  565. }
  566. @Test
  567. public void bug55791a() throws IOException {
  568. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("45541_Footer.pptx");
  569. removeAndCreateSlide(ppt);
  570. ppt.close();
  571. }
  572. @Test
  573. public void bug55791b() throws IOException {
  574. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("SampleShow.pptx");
  575. removeAndCreateSlide(ppt);
  576. ppt.close();
  577. }
  578. private void removeAndCreateSlide(XMLSlideShow ppt) {
  579. assertTrue(ppt.getSlides().size() > 1);
  580. ppt.removeSlide(1);
  581. assertNotNull(ppt.createSlide());
  582. }
  583. @Test
  584. public void blibFillAlternateContent() throws IOException {
  585. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("2411-Performance_Up.pptx");
  586. XSLFPictureShape ps = (XSLFPictureShape)ppt.getSlides().get(4).getShapes().get(0);
  587. assertNotNull(ps.getPictureData());
  588. ppt.close();
  589. }
  590. @Test
  591. public void bug59434() throws IOException {
  592. String url1 = "http://poi.apache.org/changes.html";
  593. String url2 = "http://poi.apache.org/faq.html";
  594. XMLSlideShow ppt1 = new XMLSlideShow();
  595. PictureData pd1 = ppt1.addPicture(slTests.readFile("tomcat.png"), PictureType.PNG);
  596. PictureData pd2 = ppt1.addPicture(slTests.readFile("santa.wmf"), PictureType.WMF);
  597. XSLFSlide slide = ppt1.createSlide();
  598. XSLFPictureShape ps1 = slide.createPicture(pd1);
  599. ps1.setAnchor(new Rectangle2D.Double(20, 20, 100, 100));
  600. XSLFHyperlink hl1 = ps1.createHyperlink();
  601. hl1.linkToUrl(url1);
  602. XSLFPictureShape ps2 = slide.createPicture(pd2);
  603. ps2.setAnchor(new Rectangle2D.Double(120, 120, 100, 100));
  604. XSLFHyperlink hl2 = ps2.createHyperlink();
  605. hl2.linkToUrl(url2);
  606. XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
  607. ppt1.close();
  608. slide = ppt2.getSlides().get(0);
  609. ps1 = (XSLFPictureShape)slide.getShapes().get(0);
  610. ps2 = (XSLFPictureShape)slide.getShapes().get(1);
  611. assertEquals(url1, ps1.getHyperlink().getAddress());
  612. assertEquals(url2, ps2.getHyperlink().getAddress());
  613. ppt2.close();
  614. }
  615. @Test
  616. public void bug58217() throws IOException {
  617. Color fillColor = new Color(1f,1f,0f,0.1f);
  618. Color lineColor = new Color(25.3f/255f,1f,0f,0.4f);
  619. Color textColor = new Color(1f,1f,0f,0.6f);
  620. XMLSlideShow ppt1 = new XMLSlideShow();
  621. XSLFSlide sl = ppt1.createSlide();
  622. XSLFAutoShape as = sl.createAutoShape();
  623. as.setShapeType(ShapeType.STAR_10);
  624. as.setAnchor(new Rectangle2D.Double(100,100,300,300));
  625. as.setFillColor(fillColor);
  626. as.setLineColor(lineColor);
  627. as.setText("Alpha");
  628. as.setVerticalAlignment(VerticalAlignment.MIDDLE);
  629. as.setHorizontalCentered(true);
  630. XSLFTextRun tr = as.getTextParagraphs().get(0).getTextRuns().get(0);
  631. tr.setFontSize(32d);
  632. tr.setFontColor(textColor);
  633. XMLSlideShow ppt2 = XSLFTestDataSamples.writeOutAndReadBack(ppt1);
  634. ppt1.close();
  635. sl = ppt2.getSlides().get(0);
  636. as = (XSLFAutoShape)sl.getShapes().get(0);
  637. checkColor(fillColor, as.getFillStyle().getPaint());
  638. checkColor(lineColor, as.getStrokeStyle().getPaint());
  639. checkColor(textColor, as.getTextParagraphs().get(0).getTextRuns().get(0).getFontColor());
  640. ppt2.close();
  641. }
  642. private static void checkColor(Color expected, PaintStyle actualStyle) {
  643. assertTrue(actualStyle instanceof SolidPaint);
  644. SolidPaint ps = (SolidPaint)actualStyle;
  645. Color actual = DrawPaint.applyColorTransform(ps.getSolidColor());
  646. float[] expRGB = expected.getRGBComponents(null);
  647. float[] actRGB = actual.getRGBComponents(null);
  648. assertArrayEquals(expRGB, actRGB, 0.0001f);
  649. }
  650. @Test
  651. public void bug55714() throws IOException {
  652. XMLSlideShow srcPptx = XSLFTestDataSamples.openSampleDocument("pptx2svg.pptx");
  653. XMLSlideShow newPptx = new XMLSlideShow();
  654. XSLFSlide srcSlide = srcPptx.getSlides().get(0);
  655. XSLFSlide newSlide = newPptx.createSlide();
  656. XSLFSlideLayout srcSlideLayout = srcSlide.getSlideLayout();
  657. XSLFSlideLayout newSlideLayout = newSlide.getSlideLayout();
  658. newSlideLayout.importContent(srcSlideLayout);
  659. XSLFSlideMaster srcSlideMaster = srcSlide.getSlideMaster();
  660. XSLFSlideMaster newSlideMaster = newSlide.getSlideMaster();
  661. newSlideMaster.importContent(srcSlideMaster);
  662. newSlide.importContent(srcSlide);
  663. XMLSlideShow rwPptx = XSLFTestDataSamples.writeOutAndReadBack(newPptx);
  664. PaintStyle ps = rwPptx.getSlides().get(0).getBackground().getFillStyle().getPaint();
  665. assertTrue(ps instanceof TexturePaint);
  666. rwPptx.close();
  667. newPptx.close();
  668. srcPptx.close();
  669. }
  670. @Test
  671. public void bug59273() throws IOException {
  672. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("bug59273.potx");
  673. ppt.getPackage().replaceContentType(
  674. XSLFRelation.PRESENTATIONML_TEMPLATE.getContentType(),
  675. XSLFRelation.MAIN.getContentType()
  676. );
  677. XMLSlideShow rwPptx = XSLFTestDataSamples.writeOutAndReadBack(ppt);
  678. OPCPackage pkg = rwPptx.getPackage();
  679. int size = pkg.getPartsByContentType(XSLFRelation.MAIN.getContentType()).size();
  680. assertEquals(1, size);
  681. size = pkg.getPartsByContentType(XSLFRelation.PRESENTATIONML_TEMPLATE.getContentType()).size();
  682. assertEquals(0, size);
  683. rwPptx.close();
  684. ppt.close();
  685. }
  686. @Test
  687. public void bug60373() throws IOException {
  688. XMLSlideShow ppt = new XMLSlideShow();
  689. XSLFSlide sl = ppt.createSlide();
  690. XSLFTable t = sl.createTable();
  691. XSLFTableRow r = t.addRow();
  692. bug60373_addCell(r);
  693. bug60373_addCell(r);
  694. r = t.addRow();
  695. XSLFTableCell c = bug60373_addCell(r);
  696. // call getTextHeight, when table is not fully populated
  697. double th = c.getTextHeight();
  698. assertTrue(th > 10);
  699. ppt.close();
  700. }
  701. private static XSLFTableCell bug60373_addCell(XSLFTableRow r) {
  702. XSLFTableCell cell = r.addCell();
  703. XSLFTextParagraph p = cell.addNewTextParagraph();
  704. XSLFTextRun tr = p.addNewTextRun();
  705. tr.setText("t");
  706. return cell;
  707. }
  708. @Test
  709. public void bug60715() throws IOException {
  710. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("bug60715.pptx");
  711. ppt.createSlide();
  712. ppt.close();
  713. }
  714. @Test
  715. public void bug60662() throws IOException {
  716. XMLSlideShow src = new XMLSlideShow();
  717. XSLFSlide sl = src.createSlide();
  718. XSLFGroupShape gs = sl.createGroup();
  719. gs.setAnchor(new Rectangle2D.Double(100,100,100,100));
  720. gs.setInteriorAnchor(new Rectangle2D.Double(0,0,100,100));
  721. XSLFAutoShape as = gs.createAutoShape();
  722. as.setAnchor(new Rectangle2D.Double(0,0,100,100));
  723. as.setShapeType(ShapeType.STAR_24);
  724. as.setFillColor(Color.YELLOW);
  725. CTShape csh = (CTShape)as.getXmlObject();
  726. CTOuterShadowEffect shadow = csh.getSpPr().addNewEffectLst().addNewOuterShdw();
  727. shadow.setDir(270000);
  728. shadow.setDist(100000);
  729. shadow.addNewSrgbClr().setVal(new byte[] {0x00, (byte)0xFF, 0x00});
  730. XMLSlideShow dst = new XMLSlideShow();
  731. XSLFSlide sl2 = dst.createSlide();
  732. sl2.importContent(sl);
  733. XSLFGroupShape gs2 = (XSLFGroupShape)sl2.getShapes().get(0);
  734. XSLFAutoShape as2 = (XSLFAutoShape)gs2.getShapes().get(0);
  735. CTShape csh2 = (CTShape)as2.getXmlObject();
  736. assertTrue(csh2.getSpPr().isSetEffectLst());
  737. dst.close();
  738. src.close();
  739. }
  740. @Test
  741. public void test60810() throws IOException {
  742. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("60810.pptx");
  743. for(XSLFSlide slide : ppt.getSlides()) {
  744. XSLFNotes notesSlide = ppt.getNotesSlide(slide);
  745. assertNotNull(notesSlide);
  746. }
  747. ppt.close();
  748. }
  749. @Test
  750. public void test60042() throws IOException {
  751. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("60042.pptx");
  752. ppt.removeSlide(0);
  753. ppt.createSlide();
  754. ppt.close();
  755. }
  756. @Test
  757. public void test61515() throws IOException {
  758. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("61515.pptx");
  759. ppt.removeSlide(0);
  760. assertEquals(1, ppt.createSlide().getRelations().size());
  761. try {
  762. XMLSlideShow saved = XSLFTestDataSamples.writeOutAndReadBack(ppt);
  763. assertEquals(1, saved.getSlides().size());
  764. XSLFSlide slide = saved.getSlides().get(0);
  765. assertEquals(1, slide.getRelations().size());
  766. saved.close();
  767. } catch (IOException e) {
  768. fail("Could not read back saved presentation.");
  769. }
  770. ppt.close();
  771. }
  772. @Test
  773. public void testAptia() throws IOException {
  774. try (XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("aptia.pptx");
  775. XMLSlideShow saved = XSLFTestDataSamples.writeOutAndReadBack(ppt)) {
  776. assertEquals(ppt.getSlides().size(), saved.getSlides().size());
  777. }
  778. }
  779. @Ignore
  780. @Test
  781. public void testDivinoRevelado() throws IOException {
  782. try (XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("Divino_Revelado.pptx");
  783. XMLSlideShow saved = XSLFTestDataSamples.writeOutAndReadBack(ppt)){
  784. assertEquals(ppt.getSlides().size(), saved.getSlides().size());
  785. }
  786. }
  787. @Test
  788. public void bug62051() throws IOException {
  789. final Function<List<XSLFShape>, int[]> ids = (shapes) ->
  790. shapes.stream().mapToInt(Shape::getShapeId).toArray();
  791. try (final XMLSlideShow ppt = new XMLSlideShow()) {
  792. final XSLFSlide slide = ppt.createSlide();
  793. final List<XSLFShape> shapes = new ArrayList<>();
  794. shapes.add(slide.createAutoShape());
  795. final XSLFGroupShape g1 = slide.createGroup();
  796. shapes.add(g1);
  797. final XSLFGroupShape g2 = g1.createGroup();
  798. shapes.add(g2);
  799. shapes.add(g2.createAutoShape());
  800. shapes.add(slide.createAutoShape());
  801. shapes.add(g2.createAutoShape());
  802. shapes.add(g1.createAutoShape());
  803. assertArrayEquals(new int[]{ 2,3,4,5,6,7,8 }, ids.apply(shapes));
  804. g1.removeShape(g2);
  805. shapes.remove(5);
  806. shapes.remove(3);
  807. shapes.remove(2);
  808. shapes.add(g1.createAutoShape());
  809. assertArrayEquals(new int[]{ 2,3,6,8,4 }, ids.apply(shapes));
  810. }
  811. }
  812. @Test
  813. public void bug63200() throws Exception {
  814. try (XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("63200.pptx")) {
  815. assertEquals(1, ss1.getSlides().size());
  816. XSLFSlide slide = ss1.getSlides().get(0);
  817. assertEquals(slide.getShapes().size(), 1);
  818. XSLFGroupShape group = (XSLFGroupShape) slide.getShapes().get(0);
  819. assertEquals(group.getShapes().size(), 2);
  820. XSLFAutoShape oval = (XSLFAutoShape) group.getShapes().get(0);
  821. XSLFAutoShape arrow = (XSLFAutoShape) group.getShapes().get(1);
  822. assertNull(oval.getFillColor());
  823. assertNull(arrow.getFillColor());
  824. }
  825. }
  826. }