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 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  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 junit.framework.TestCase.assertEquals;
  17. import static org.apache.poi.POITestCase.assertContains;
  18. import static org.junit.Assert.assertArrayEquals;
  19. import static org.junit.Assert.assertNotNull;
  20. import static org.junit.Assert.assertTrue;
  21. import static org.junit.Assert.fail;
  22. import java.awt.Color;
  23. import java.awt.Dimension;
  24. import java.awt.Graphics2D;
  25. import java.awt.RenderingHints;
  26. import java.awt.geom.AffineTransform;
  27. import java.awt.geom.Rectangle2D;
  28. import java.awt.image.BufferedImage;
  29. import java.io.File;
  30. import java.io.IOException;
  31. import java.net.URI;
  32. import java.util.Collection;
  33. import javax.imageio.ImageIO;
  34. import org.apache.poi.POIXMLDocumentPart;
  35. import org.apache.poi.POIXMLDocumentPart.RelationPart;
  36. import org.apache.poi.sl.usermodel.PaintStyle;
  37. import org.apache.poi.sl.usermodel.PictureData.PictureType;
  38. import org.apache.poi.xslf.usermodel.DrawingParagraph;
  39. import org.apache.poi.xslf.usermodel.DrawingTextBody;
  40. import org.apache.poi.xslf.usermodel.XMLSlideShow;
  41. import org.apache.poi.xslf.usermodel.XSLFPictureData;
  42. import org.apache.poi.xslf.usermodel.XSLFPictureShape;
  43. import org.apache.poi.xslf.usermodel.XSLFRelation;
  44. import org.apache.poi.xslf.usermodel.XSLFShape;
  45. import org.apache.poi.xslf.usermodel.XSLFSlide;
  46. import org.apache.poi.xslf.usermodel.XSLFSlideLayout;
  47. import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
  48. import org.junit.Ignore;
  49. import org.junit.Test;
  50. public class TestXSLFBugs {
  51. @Test
  52. public void bug51187() throws Exception {
  53. XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("51187.pptx");
  54. assertEquals(1, ss1.getSlides().size());
  55. // Check the relations on it
  56. // Note - rId3 is a self reference
  57. XSLFSlide slide0 = ss1.getSlides().get(0);
  58. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  59. assertRelation(slide0, "/ppt/slideLayouts/slideLayout12.xml", "rId1");
  60. assertRelation(slide0, "/ppt/notesSlides/notesSlide1.xml", "rId2");
  61. assertRelation(slide0, "/ppt/slides/slide1.xml", "rId3");
  62. assertRelation(slide0, "/ppt/media/image1.png", "rId4");
  63. // Save and re-load
  64. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss1);
  65. ss1.close();
  66. assertEquals(1, ss2.getSlides().size());
  67. slide0 = ss2.getSlides().get(0);
  68. assertRelation(slide0, "/ppt/slides/slide1.xml", null);
  69. assertRelation(slide0, "/ppt/slideLayouts/slideLayout12.xml", "rId1");
  70. assertRelation(slide0, "/ppt/notesSlides/notesSlide1.xml", "rId2");
  71. // TODO Fix this
  72. assertRelation(slide0, "/ppt/slides/slide1.xml", "rId3");
  73. assertRelation(slide0, "/ppt/media/image1.png", "rId4");
  74. ss2.close();
  75. }
  76. private static void assertRelation(XSLFSlide slide, String exp, String rId) {
  77. POIXMLDocumentPart pd = (rId != null) ? slide.getRelationById(rId) : slide;
  78. assertEquals(exp, pd.getPackagePart().getPartName().getName());
  79. }
  80. /**
  81. * Slide relations with anchors in them
  82. */
  83. @Test
  84. public void tika705() throws Exception {
  85. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
  86. // Should have one slide
  87. assertEquals(1, ss.getSlides().size());
  88. XSLFSlide slide = ss.getSlides().get(0);
  89. // Check the relations from this
  90. Collection<RelationPart> rels = slide.getRelationParts();
  91. // Should have 6 relations:
  92. // 1 external hyperlink (skipped from list)
  93. // 4 internal hyperlinks
  94. // 1 slide layout
  95. assertEquals(5, rels.size());
  96. int layouts = 0;
  97. int hyperlinks = 0;
  98. for(RelationPart p : rels) {
  99. if(p.getRelationship().getRelationshipType().equals(XSLFRelation.HYPERLINK.getRelation())) {
  100. hyperlinks++;
  101. } else if(p.getDocumentPart() instanceof XSLFSlideLayout) {
  102. layouts++;
  103. }
  104. }
  105. assertEquals(1, layouts);
  106. assertEquals(4, hyperlinks);
  107. // Hyperlinks should all be to #_ftn1 or #ftnref1
  108. for(RelationPart p : rels) {
  109. if(p.getRelationship().getRelationshipType().equals(XSLFRelation.HYPERLINK.getRelation())) {
  110. URI target = p.getRelationship().getTargetURI();
  111. if(target.getFragment().equals("_ftn1") ||
  112. target.getFragment().equals("_ftnref1")) {
  113. // Good
  114. } else {
  115. fail("Invalid target " + target.getFragment() + " on " + target);
  116. }
  117. }
  118. }
  119. ss.close();
  120. }
  121. /**
  122. * A slideshow can have more than one rID pointing to a given
  123. * slide, eg presentation.xml rID1 -> slide1.xml, but slide1.xml
  124. * rID2 -> slide3.xml
  125. */
  126. @Test
  127. public void bug54916() throws Exception {
  128. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("OverlappingRelations.pptx");
  129. XSLFSlide slide;
  130. // Should find 4 slides
  131. assertEquals(4, ss.getSlides().size());
  132. // Check the text, to see we got them in order
  133. slide = ss.getSlides().get(0);
  134. assertContains(getSlideText(slide), "POI cannot read this");
  135. slide = ss.getSlides().get(1);
  136. assertContains(getSlideText(slide), "POI can read this");
  137. assertContains(getSlideText(slide), "Has a relationship to another slide");
  138. slide = ss.getSlides().get(2);
  139. assertContains(getSlideText(slide), "POI can read this");
  140. slide = ss.getSlides().get(3);
  141. assertContains(getSlideText(slide), "POI can read this");
  142. ss.close();
  143. }
  144. /**
  145. * When the picture is not embedded but inserted only as a "link to file",
  146. * there is no data available and XSLFPictureShape.getPictureData()
  147. * gives a NPE, see bug #56812
  148. */
  149. @Test
  150. public void bug56812() throws Exception {
  151. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("56812.pptx");
  152. int internalPictures = 0;
  153. int externalPictures = 0;
  154. for (XSLFSlide slide : ppt.getSlides()){
  155. for (XSLFShape shape : slide.getShapes()){
  156. assertNotNull(shape);
  157. if (shape instanceof XSLFPictureShape) {
  158. XSLFPictureShape picture = (XSLFPictureShape)shape;
  159. if (picture.isExternalLinkedPicture()) {
  160. externalPictures++;
  161. assertNotNull(picture.getPictureLink());
  162. } else {
  163. internalPictures++;
  164. XSLFPictureData data = picture.getPictureData();
  165. assertNotNull(data);
  166. assertNotNull(data.getFileName());
  167. }
  168. }
  169. }
  170. }
  171. assertEquals(2, internalPictures);
  172. assertEquals(1, externalPictures);
  173. ppt.close();
  174. }
  175. @Test
  176. @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix")
  177. public void bug54542() throws Exception {
  178. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("54542_cropped_bitmap.pptx");
  179. Dimension pgsize = ss.getPageSize();
  180. XSLFSlide slide = ss.getSlides().get(0);
  181. // render it
  182. double zoom = 1;
  183. AffineTransform at = new AffineTransform();
  184. at.setToScale(zoom, zoom);
  185. BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR);
  186. Graphics2D graphics = imgActual.createGraphics();
  187. graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  188. graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  189. graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
  190. graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  191. graphics.setTransform(at);
  192. graphics.setPaint(Color.white);
  193. graphics.fill(new Rectangle2D.Float(0, 0, pgsize.width, pgsize.height));
  194. slide.draw(graphics);
  195. ImageIO.write(imgActual, "PNG", new File("bug54542.png"));
  196. ss.close();
  197. }
  198. protected String getSlideText(XSLFSlide slide) {
  199. StringBuffer text = new StringBuffer();
  200. for(DrawingTextBody textBody : slide.getCommonSlideData().getDrawingText()) {
  201. for (DrawingParagraph p : textBody.getParagraphs()) {
  202. text.append(p.getText());
  203. text.append("\n");
  204. }
  205. }
  206. return text.toString();
  207. }
  208. @Test
  209. public void bug57250() throws Exception {
  210. XMLSlideShow ss = new XMLSlideShow();
  211. for (String s : new String[]{"Slide1","Slide2"}) {
  212. ss.createSlide().createTextBox().setText(s);
  213. }
  214. validateSlides(ss, false, "Slide1","Slide2");
  215. XSLFSlide slide = ss.createSlide();
  216. slide.createTextBox().setText("New slide");
  217. validateSlides(ss, true, "Slide1","Slide2","New slide");
  218. // Move backward
  219. ss.setSlideOrder(slide, 0);
  220. validateSlides(ss, true, "New slide","Slide1","Slide2");
  221. // Move forward
  222. ss.setSlideOrder(slide, 1);
  223. validateSlides(ss, true, "Slide1","New slide","Slide2");
  224. // Move to end
  225. ss.setSlideOrder(slide, 0);
  226. ss.setSlideOrder(slide, 2);
  227. validateSlides(ss, true, "Slide1","Slide2","New slide");
  228. ss.close();
  229. }
  230. /**
  231. * When working with >9 images, make sure the sorting ensures
  232. * that image10.foo isn't between image1.foo and image2.foo
  233. */
  234. @Test
  235. public void test57552() throws Exception {
  236. XMLSlideShow ss = new XMLSlideShow();
  237. for (String s : new String[]{"Slide1","Slide2"}) {
  238. ss.createSlide().createTextBox().setText(s);
  239. }
  240. // Slide starts with just layout relation
  241. XSLFSlide slide = ss.getSlides().get(0);
  242. assertEquals(0, ss.getPictureData().size());
  243. assertEquals(1, slide.getShapes().size());
  244. assertEquals(1, slide.getRelations().size());
  245. assertRelationEquals(XSLFRelation.SLIDE_LAYOUT, slide.getRelations().get(0));
  246. // Some dummy pictures
  247. byte[][] pics = new byte[15][3];
  248. for (int i=0; i<pics.length; i++) {
  249. for (int j=0; j<pics[i].length; j++) {
  250. pics[i][j] = (byte)i;
  251. }
  252. }
  253. // Add a few pictures
  254. for (int i=0; i<10; i++) {
  255. XSLFPictureData data = ss.addPicture(pics[i], PictureType.JPEG);
  256. assertEquals(i, data.getIndex());
  257. assertEquals(i+1, ss.getPictureData().size());
  258. XSLFPictureShape shape = slide.createPicture(data);
  259. assertNotNull(shape.getPictureData());
  260. assertArrayEquals(pics[i], shape.getPictureData().getData());
  261. assertEquals(i+2, slide.getShapes().size());
  262. }
  263. // Re-fetch the pictures and check
  264. for (int i=0; i<10; i++) {
  265. XSLFPictureShape shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  266. assertNotNull(shape.getPictureData());
  267. assertArrayEquals(pics[i], shape.getPictureData().getData());
  268. }
  269. // Add past 10
  270. for (int i=10; i<15; i++) {
  271. XSLFPictureData data = ss.addPicture(pics[i], PictureType.JPEG);
  272. assertEquals(i, data.getIndex());
  273. assertEquals(i+1, ss.getPictureData().size());
  274. XSLFPictureShape shape = slide.createPicture(data);
  275. assertNotNull(shape.getPictureData());
  276. assertArrayEquals(pics[i], shape.getPictureData().getData());
  277. assertEquals(i+2, slide.getShapes().size());
  278. }
  279. // Check all pictures
  280. for (int i=0; i<15; i++) {
  281. XSLFPictureShape shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  282. assertNotNull(shape.getPictureData());
  283. assertArrayEquals(pics[i], shape.getPictureData().getData());
  284. }
  285. // Add a duplicate, check the right one is picked
  286. XSLFPictureData data = ss.addPicture(pics[3], PictureType.JPEG);
  287. assertEquals(3, data.getIndex());
  288. assertEquals(15, ss.getPictureData().size());
  289. XSLFPictureShape shape = slide.createPicture(data);
  290. assertNotNull(shape.getPictureData());
  291. assertArrayEquals(pics[3], shape.getPictureData().getData());
  292. assertEquals(17, slide.getShapes().size());
  293. // Save and re-load
  294. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss);
  295. slide = ss2.getSlides().get(0);
  296. // Check the 15 individual ones added
  297. for (int i=0; i<15; i++) {
  298. shape = (XSLFPictureShape)slide.getShapes().get(i+1);
  299. assertNotNull(shape.getPictureData());
  300. assertArrayEquals(pics[i], shape.getPictureData().getData());
  301. }
  302. // Check the duplicate
  303. shape = (XSLFPictureShape)slide.getShapes().get(16);
  304. assertNotNull(shape.getPictureData());
  305. assertArrayEquals(pics[3], shape.getPictureData().getData());
  306. // Add another duplicate
  307. data = ss2.addPicture(pics[5], PictureType.JPEG);
  308. assertEquals(5, data.getIndex());
  309. assertEquals(15, ss2.getPictureData().size());
  310. shape = slide.createPicture(data);
  311. assertNotNull(shape.getPictureData());
  312. assertArrayEquals(pics[5], shape.getPictureData().getData());
  313. assertEquals(18, slide.getShapes().size());
  314. ss2.close();
  315. ss.close();
  316. }
  317. private void validateSlides(XMLSlideShow ss, boolean saveAndReload, String... slideTexts) throws IOException {
  318. if (saveAndReload) {
  319. XMLSlideShow ss2 = XSLFTestDataSamples.writeOutAndReadBack(ss);
  320. validateSlides(ss, slideTexts);
  321. ss2.close();
  322. } else {
  323. validateSlides(ss, slideTexts);
  324. }
  325. }
  326. private void validateSlides(XMLSlideShow ss, String... slideTexts) throws IOException {
  327. assertEquals(slideTexts.length, ss.getSlides().size());
  328. for (int i = 0; i < slideTexts.length; i++) {
  329. XSLFSlide slide = ss.getSlides().get(i);
  330. assertContains(getSlideText(slide), slideTexts[i]);
  331. }
  332. }
  333. private void assertRelationEquals(XSLFRelation expected, POIXMLDocumentPart relation) {
  334. assertEquals(expected.getContentType(), relation.getPackagePart().getContentType());
  335. assertEquals(expected.getFileName(expected.getFileNameIndex(relation)), relation.getPackagePart().getPartName().getName());
  336. }
  337. @Test
  338. public void bug58205() throws IOException {
  339. XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("themes.pptx");
  340. int i = 1;
  341. for (XSLFSlideMaster sm : ss.getSlideMasters()) {
  342. assertEquals("rId"+(i++), ss.getRelationId(sm));
  343. }
  344. ss.close();
  345. }
  346. @Test
  347. public void bug55791a() {
  348. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("45541_Footer.pptx");
  349. removeAndCreateSlide(ppt);
  350. }
  351. @Test
  352. public void bug55791b() {
  353. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("SampleShow.pptx");
  354. removeAndCreateSlide(ppt);
  355. }
  356. private void removeAndCreateSlide(XMLSlideShow ppt) {
  357. assertTrue(ppt.getSlides().size() > 1);
  358. ppt.removeSlide(1);
  359. assertNotNull(ppt.createSlide());
  360. }
  361. @Test
  362. public void blibFillAlternateContent() throws IOException {
  363. XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("2411-Performance_Up.pptx");
  364. XSLFPictureShape ps = (XSLFPictureShape)ppt.getSlides().get(4).getShapes().get(0);
  365. assertNotNull(ps.getPictureData());
  366. ppt.close();
  367. }
  368. }