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.

TestShapes.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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.hslf.model;
  16. import static org.apache.poi.sl.TestCommonSL.sameColor;
  17. import static org.junit.Assert.assertEquals;
  18. import static org.junit.Assert.assertFalse;
  19. import static org.junit.Assert.assertNotNull;
  20. import static org.junit.Assert.assertNull;
  21. import static org.junit.Assert.assertTrue;
  22. import java.awt.Color;
  23. import java.awt.Dimension;
  24. import java.awt.geom.Rectangle2D;
  25. import java.io.ByteArrayInputStream;
  26. import java.io.ByteArrayOutputStream;
  27. import java.io.IOException;
  28. import java.io.InputStream;
  29. import java.util.ArrayList;
  30. import java.util.List;
  31. import org.apache.poi.POIDataSamples;
  32. import org.apache.poi.ddf.AbstractEscherOptRecord;
  33. import org.apache.poi.ddf.EscherDgRecord;
  34. import org.apache.poi.ddf.EscherDggRecord;
  35. import org.apache.poi.ddf.EscherProperties;
  36. import org.apache.poi.ddf.EscherSimpleProperty;
  37. import org.apache.poi.hslf.usermodel.HSLFAutoShape;
  38. import org.apache.poi.hslf.usermodel.HSLFGroupShape;
  39. import org.apache.poi.hslf.usermodel.HSLFLine;
  40. import org.apache.poi.hslf.usermodel.HSLFPictureData;
  41. import org.apache.poi.hslf.usermodel.HSLFPictureShape;
  42. import org.apache.poi.hslf.usermodel.HSLFShape;
  43. import org.apache.poi.hslf.usermodel.HSLFSimpleShape;
  44. import org.apache.poi.hslf.usermodel.HSLFSlide;
  45. import org.apache.poi.hslf.usermodel.HSLFSlideShow;
  46. import org.apache.poi.hslf.usermodel.HSLFTextBox;
  47. import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
  48. import org.apache.poi.hslf.usermodel.HSLFTextRun;
  49. import org.apache.poi.hslf.usermodel.HSLFTextShape;
  50. import org.apache.poi.sl.usermodel.PictureData.PictureType;
  51. import org.apache.poi.sl.usermodel.ShapeType;
  52. import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
  53. import org.junit.Before;
  54. import org.junit.Test;
  55. /**
  56. * Test drawing shapes via Graphics2D
  57. */
  58. public final class TestShapes {
  59. private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
  60. private HSLFSlideShow ppt;
  61. private HSLFSlideShow pptB;
  62. @Before
  63. public void setUp() throws Exception {
  64. InputStream is1 = null, is2 = null;
  65. try {
  66. is1 = _slTests.openResourceAsStream("empty.ppt");
  67. ppt = new HSLFSlideShow(is1);
  68. is2 = _slTests.openResourceAsStream("empty_textbox.ppt");
  69. pptB = new HSLFSlideShow(is2);
  70. } finally {
  71. is1.close();
  72. is2.close();
  73. }
  74. }
  75. @Test
  76. public void graphics() throws IOException {
  77. HSLFSlide slide = ppt.createSlide();
  78. HSLFLine line = new HSLFLine();
  79. java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60);
  80. line.setAnchor(lineAnchor);
  81. line.setLineWidth(3);
  82. line.setLineDash(LineDash.DASH);
  83. line.setLineColor(Color.red);
  84. slide.addShape(line);
  85. HSLFAutoShape ellipse = new HSLFAutoShape(ShapeType.ELLIPSE);
  86. Rectangle2D ellipseAnchor = new Rectangle2D.Double(320, 154, 55, 111);
  87. ellipse.setAnchor(ellipseAnchor);
  88. ellipse.setLineWidth(2);
  89. ellipse.setLineDash(LineDash.SOLID);
  90. ellipse.setLineColor(Color.green);
  91. ellipse.setFillColor(Color.lightGray);
  92. slide.addShape(ellipse);
  93. ByteArrayOutputStream out = new ByteArrayOutputStream();
  94. ppt.write(out);
  95. out.close();
  96. //read ppt from byte array
  97. HSLFSlideShow ppt2 = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
  98. assertEquals(1, ppt2.getSlides().size());
  99. slide = ppt2.getSlides().get(0);
  100. List<HSLFShape> shape = slide.getShapes();
  101. assertEquals(2, shape.size());
  102. assertTrue(shape.get(0) instanceof HSLFLine); //group shape
  103. assertEquals(lineAnchor, shape.get(0).getAnchor()); //group shape
  104. assertTrue(shape.get(1) instanceof HSLFAutoShape); //group shape
  105. assertEquals(ellipseAnchor, shape.get(1).getAnchor()); //group shape
  106. ppt2.close();
  107. }
  108. /**
  109. * Verify that we can read TextBox shapes
  110. * @throws Exception
  111. */
  112. @Test
  113. public void textBoxRead() throws IOException {
  114. ppt = new HSLFSlideShow(_slTests.openResourceAsStream("with_textbox.ppt"));
  115. HSLFSlide sl = ppt.getSlides().get(0);
  116. for (HSLFShape sh : sl.getShapes()) {
  117. assertTrue(sh instanceof HSLFTextBox);
  118. HSLFTextBox txtbox = (HSLFTextBox)sh;
  119. String text = txtbox.getText();
  120. assertNotNull(text);
  121. assertEquals(txtbox.getTextParagraphs().get(0).getTextRuns().size(), 1);
  122. HSLFTextRun rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
  123. if (text.equals("Hello, World!!!")){
  124. assertEquals(32, rt.getFontSize(), 0);
  125. assertTrue(rt.isBold());
  126. assertTrue(rt.isItalic());
  127. } else if (text.equals("I am just a poor boy")){
  128. assertEquals(44, rt.getFontSize(), 0);
  129. assertTrue(rt.isBold());
  130. } else if (text.equals("This is Times New Roman")){
  131. assertEquals(16, rt.getFontSize(), 0);
  132. assertTrue(rt.isBold());
  133. assertTrue(rt.isItalic());
  134. assertTrue(rt.isUnderlined());
  135. } else if (text.equals("Plain Text")){
  136. assertEquals(18, rt.getFontSize(), 0);
  137. }
  138. }
  139. }
  140. @SuppressWarnings("unused")
  141. @Test
  142. public void testParagraphs() throws IOException {
  143. HSLFSlideShow ss = new HSLFSlideShow();
  144. HSLFSlide slide = ss.createSlide();
  145. HSLFTextBox shape = new HSLFTextBox();
  146. HSLFTextRun p1r1 = shape.setText("para 1 run 1. ");
  147. HSLFTextRun p1r2 = shape.appendText("para 1 run 2.", false);
  148. HSLFTextRun p2r1 = shape.appendText("para 2 run 1. ", true);
  149. HSLFTextRun p2r2 = shape.appendText("para 2 run 2. ", false);
  150. p1r1.setFontColor(Color.black);
  151. p1r2.setFontColor(Color.red);
  152. p2r1.setFontColor(Color.yellow);
  153. p2r2.setStrikethrough(true);
  154. // run 3 has same text properties as run 2 and will be merged when saving
  155. HSLFTextRun p2r3 = shape.appendText("para 2 run 3.", false);
  156. shape.setAnchor(new Rectangle2D.Double(100,100,100,10));
  157. slide.addShape(shape);
  158. shape.resizeToFitText();
  159. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  160. ss.write(bos);
  161. ss = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
  162. slide = ss.getSlides().get(0);
  163. HSLFTextBox tb = (HSLFTextBox)slide.getShapes().get(0);
  164. List<HSLFTextParagraph> para = tb.getTextParagraphs();
  165. HSLFTextRun tr = para.get(0).getTextRuns().get(0);
  166. assertEquals("para 1 run 1. ", tr.getRawText());
  167. assertTrue(sameColor(Color.black, tr.getFontColor()));
  168. tr = para.get(0).getTextRuns().get(1);
  169. assertEquals("para 1 run 2.\r", tr.getRawText());
  170. assertTrue(sameColor(Color.red, tr.getFontColor()));
  171. tr = para.get(1).getTextRuns().get(0);
  172. assertEquals("para 2 run 1. ", tr.getRawText());
  173. assertTrue(sameColor(Color.yellow, tr.getFontColor()));
  174. tr = para.get(1).getTextRuns().get(1);
  175. assertEquals("para 2 run 2. para 2 run 3.", tr.getRawText());
  176. assertTrue(sameColor(Color.black, tr.getFontColor()));
  177. assertTrue(tr.isStrikethrough());
  178. }
  179. /**
  180. * Verify that we can add TextBox shapes to a slide
  181. * and set some of the style attributes
  182. */
  183. @Test
  184. public void textBoxWriteBytes() throws IOException {
  185. ppt = new HSLFSlideShow();
  186. HSLFSlide sl = ppt.createSlide();
  187. HSLFTextRun rt;
  188. String val = "Hello, World!";
  189. // Create a new textbox, and give it lots of properties
  190. HSLFTextBox txtbox = new HSLFTextBox();
  191. rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
  192. txtbox.setText(val);
  193. rt.setFontFamily("Arial");
  194. rt.setFontSize(42d);
  195. rt.setBold(true);
  196. rt.setItalic(true);
  197. rt.setUnderlined(false);
  198. rt.setFontColor(Color.red);
  199. sl.addShape(txtbox);
  200. // Check it before save
  201. rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
  202. assertEquals(val, rt.getRawText());
  203. assertEquals(42, rt.getFontSize(), 0);
  204. assertTrue(rt.isBold());
  205. assertTrue(rt.isItalic());
  206. assertFalse(rt.isUnderlined());
  207. assertEquals("Arial", rt.getFontFamily());
  208. assertTrue(sameColor(Color.red, rt.getFontColor()));
  209. // Serialize and read again
  210. ByteArrayOutputStream out = new ByteArrayOutputStream();
  211. ppt.write(out);
  212. out.close();
  213. HSLFSlideShow ppt2 = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
  214. sl = ppt2.getSlides().get(0);
  215. txtbox = (HSLFTextBox)sl.getShapes().get(0);
  216. rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
  217. // Check after save
  218. assertEquals(val, rt.getRawText());
  219. assertEquals(42, rt.getFontSize(), 0);
  220. assertTrue(rt.isBold());
  221. assertTrue(rt.isItalic());
  222. assertFalse(rt.isUnderlined());
  223. assertEquals("Arial", rt.getFontFamily());
  224. assertTrue(sameColor(Color.red, rt.getFontColor()));
  225. ppt2.close();
  226. }
  227. /**
  228. * Test with an empty text box
  229. */
  230. @Test
  231. public void emptyTextBox() {
  232. assertEquals(2, pptB.getSlides().size());
  233. HSLFSlide s1 = pptB.getSlides().get(0);
  234. HSLFSlide s2 = pptB.getSlides().get(1);
  235. // Check we can get the shapes count
  236. assertEquals(2, s1.getShapes().size());
  237. assertEquals(2, s2.getShapes().size());
  238. }
  239. /**
  240. * If you iterate over text shapes in a slide and collect them in a set
  241. * it must be the same as returned by Slide.getTextRuns().
  242. */
  243. @Test
  244. public void textBoxSet() throws IOException {
  245. textBoxSet("with_textbox.ppt");
  246. textBoxSet("basic_test_ppt_file.ppt");
  247. textBoxSet("next_test_ppt_file.ppt");
  248. textBoxSet("Single_Coloured_Page.ppt");
  249. textBoxSet("Single_Coloured_Page_With_Fonts_and_Alignments.ppt");
  250. textBoxSet("incorrect_slide_order.ppt");
  251. }
  252. private void textBoxSet(String filename) throws IOException {
  253. HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(filename));
  254. for (HSLFSlide sld : ss.getSlides()) {
  255. ArrayList<String> lst1 = new ArrayList<String>();
  256. for (List<HSLFTextParagraph> txt : sld.getTextParagraphs()) {
  257. for (HSLFTextParagraph p : txt) {
  258. for (HSLFTextRun r : p) {
  259. lst1.add(r.getRawText());
  260. }
  261. }
  262. }
  263. ArrayList<String> lst2 = new ArrayList<String>();
  264. for (HSLFShape sh : sld.getShapes()) {
  265. if (sh instanceof HSLFTextShape){
  266. HSLFTextShape tbox = (HSLFTextShape)sh;
  267. for (HSLFTextParagraph p : tbox.getTextParagraphs()) {
  268. for (HSLFTextRun r : p) {
  269. lst2.add(r.getRawText());
  270. }
  271. }
  272. }
  273. }
  274. assertTrue(lst1.containsAll(lst2));
  275. assertTrue(lst2.containsAll(lst1));
  276. }
  277. ss.close();
  278. }
  279. /**
  280. * Test adding shapes to <code>ShapeGroup</code>
  281. */
  282. @Test
  283. public void shapeGroup() throws IOException {
  284. HSLFSlideShow ss = new HSLFSlideShow();
  285. HSLFSlide slide = ss.createSlide();
  286. Dimension pgsize = ss.getPageSize();
  287. HSLFGroupShape group = new HSLFGroupShape();
  288. group.setAnchor(new Rectangle2D.Double(0, 0, pgsize.getWidth(), pgsize.getHeight()));
  289. slide.addShape(group);
  290. HSLFPictureData data = ss.addPicture(_slTests.readFile("clock.jpg"), PictureType.JPEG);
  291. HSLFPictureShape pict = new HSLFPictureShape(data, group);
  292. pict.setAnchor(new Rectangle2D.Double(0, 0, 200, 200));
  293. group.addShape(pict);
  294. HSLFLine line = new HSLFLine(group);
  295. line.setAnchor(new Rectangle2D.Double(300, 300, 500, 0));
  296. group.addShape(line);
  297. //serialize and read again.
  298. ByteArrayOutputStream out = new ByteArrayOutputStream();
  299. ss.write(out);
  300. out.close();
  301. ss.close();
  302. ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray());
  303. ss = new HSLFSlideShow(is);
  304. is.close();
  305. slide = ss.getSlides().get(0);
  306. List<HSLFShape> shape = slide.getShapes();
  307. assertEquals(1, shape.size());
  308. assertTrue(shape.get(0) instanceof HSLFGroupShape);
  309. group = (HSLFGroupShape)shape.get(0);
  310. List<HSLFShape> grshape = group.getShapes();
  311. assertEquals(2, grshape.size());
  312. assertTrue(grshape.get(0) instanceof HSLFPictureShape);
  313. assertTrue(grshape.get(1) instanceof HSLFLine);
  314. pict = (HSLFPictureShape)grshape.get(0);
  315. assertEquals(new Rectangle2D.Double(0, 0, 200, 200), pict.getAnchor());
  316. line = (HSLFLine)grshape.get(1);
  317. assertEquals(new Rectangle2D.Double(300, 300, 500, 0), line.getAnchor());
  318. ss.close();
  319. }
  320. /**
  321. * Test functionality of Sheet.removeShape(Shape shape)
  322. */
  323. @Test
  324. public void removeShapes() throws IOException {
  325. String file = "with_textbox.ppt";
  326. HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream(file));
  327. HSLFSlide sl = ss.getSlides().get(0);
  328. List<HSLFShape> sh = sl.getShapes();
  329. assertEquals("expected four shaped in " + file, 4, sh.size());
  330. //remove all
  331. for (int i = 0; i < sh.size(); i++) {
  332. boolean ok = sl.removeShape(sh.get(i));
  333. assertTrue("Failed to delete shape #" + i, ok);
  334. }
  335. //now Slide.getShapes() should return an empty array
  336. assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size());
  337. //serialize and read again. The file should be readable and contain no shapes
  338. ByteArrayOutputStream out = new ByteArrayOutputStream();
  339. ss.write(out);
  340. out.close();
  341. ss.close();
  342. ss = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
  343. sl = ss.getSlides().get(0);
  344. assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size());
  345. ss.close();
  346. }
  347. @Test
  348. public void lineWidth() {
  349. HSLFSimpleShape sh = new HSLFAutoShape(ShapeType.RT_TRIANGLE);
  350. AbstractEscherOptRecord opt = sh.getEscherOptRecord();
  351. EscherSimpleProperty prop = HSLFSimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH);
  352. assertNull(prop);
  353. assertEquals(HSLFSimpleShape.DEFAULT_LINE_WIDTH, sh.getLineWidth(), 0);
  354. sh.setLineWidth(1.0);
  355. prop = HSLFSimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH);
  356. assertNotNull(prop);
  357. assertEquals(1.0, sh.getLineWidth(), 0);
  358. }
  359. @Test
  360. public void shapeId() throws IOException {
  361. HSLFSlideShow ss = new HSLFSlideShow();
  362. HSLFSlide slide = ss.createSlide();
  363. HSLFShape shape = null;
  364. //EscherDgg is a document-level record which keeps track of the drawing groups
  365. EscherDggRecord dgg = ss.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord();
  366. EscherDgRecord dg = slide.getSheetContainer().getPPDrawing().getEscherDgRecord();
  367. int dggShapesUsed = dgg.getNumShapesSaved(); //total number of shapes in the ppt
  368. int dggMaxId = dgg.getShapeIdMax(); //max number of shapeId
  369. int dgMaxId = dg.getLastMSOSPID(); //max shapeId in the slide
  370. int dgShapesUsed = dg.getNumShapes(); // number of shapes in the slide
  371. //insert 3 shapes and make sure the Ids are properly incremented
  372. for (int i = 0; i < 3; i++) {
  373. shape = new HSLFLine();
  374. assertEquals(0, shape.getShapeId());
  375. slide.addShape(shape);
  376. assertTrue(shape.getShapeId() > 0);
  377. //check that EscherDgRecord is updated
  378. assertEquals(shape.getShapeId(), dg.getLastMSOSPID());
  379. assertEquals(dgMaxId + 1, dg.getLastMSOSPID());
  380. assertEquals(dgShapesUsed + 1, dg.getNumShapes());
  381. //check that EscherDggRecord is updated
  382. assertEquals(shape.getShapeId() + 1, dgg.getShapeIdMax());
  383. assertEquals(dggMaxId + 1, dgg.getShapeIdMax());
  384. assertEquals(dggShapesUsed + 1, dgg.getNumShapesSaved());
  385. dggShapesUsed = dgg.getNumShapesSaved();
  386. dggMaxId = dgg.getShapeIdMax();
  387. dgMaxId = dg.getLastMSOSPID();
  388. dgShapesUsed = dg.getNumShapes();
  389. }
  390. //For each drawing group PPT allocates clusters with size=1024
  391. //if the number of shapes is greater that 1024 a new cluster is allocated
  392. //make sure it is so
  393. int numClusters = dgg.getNumIdClusters();
  394. for (int i = 0; i < 1025; i++) {
  395. shape = new HSLFLine();
  396. slide.addShape(shape);
  397. }
  398. assertEquals(numClusters + 1, dgg.getNumIdClusters());
  399. ss.close();
  400. }
  401. @Test
  402. public void lineColor() throws IOException {
  403. HSLFSlideShow ss = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt"));
  404. List<HSLFShape> shape = ss.getSlides().get(0).getShapes();
  405. assertEquals(4, shape.size());
  406. HSLFTextShape sh1 = (HSLFTextShape)shape.get(0);
  407. assertEquals("Hello Apache POI", sh1.getText());
  408. assertNull(sh1.getLineColor());
  409. HSLFTextShape sh2 = (HSLFTextShape)shape.get(1);
  410. assertEquals("Why are you showing this border?", sh2.getText());
  411. assertNull(sh2.getLineColor());
  412. HSLFTextShape sh3 = (HSLFTextShape)shape.get(2);
  413. assertEquals("Text in a black border", sh3.getText());
  414. assertEquals(Color.black, sh3.getLineColor());
  415. assertEquals(0.75, sh3.getLineWidth(), 0);
  416. HSLFTextShape sh4 = (HSLFTextShape)shape.get(3);
  417. assertEquals("Border width is 5 pt", sh4.getText());
  418. assertEquals(Color.black, sh4.getLineColor());
  419. assertEquals(5.0, sh4.getLineWidth(), 0);
  420. ss.close();
  421. }
  422. }