Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

TestTextRun.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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.usermodel;
  16. import static org.apache.poi.hslf.HSLFTestDataSamples.getSlideShow;
  17. import static org.junit.jupiter.api.Assertions.assertArrayEquals;
  18. import static org.junit.jupiter.api.Assertions.assertEquals;
  19. import static org.junit.jupiter.api.Assertions.assertFalse;
  20. import static org.junit.jupiter.api.Assertions.assertNotEquals;
  21. import static org.junit.jupiter.api.Assertions.assertNotNull;
  22. import static org.junit.jupiter.api.Assertions.assertNull;
  23. import static org.junit.jupiter.api.Assertions.assertSame;
  24. import static org.junit.jupiter.api.Assertions.assertTrue;
  25. import java.awt.Color;
  26. import java.io.IOException;
  27. import java.time.LocalDateTime;
  28. import java.util.HashMap;
  29. import java.util.List;
  30. import java.util.Locale;
  31. import java.util.Map;
  32. import java.util.stream.Collectors;
  33. import java.util.stream.Stream;
  34. import org.apache.poi.hslf.HSLFTestDataSamples;
  35. import org.apache.poi.hslf.model.textproperties.TextPropCollection;
  36. import org.apache.poi.hslf.record.DateTimeMCAtom;
  37. import org.apache.poi.hslf.record.TextBytesAtom;
  38. import org.apache.poi.hslf.record.TextCharsAtom;
  39. import org.apache.poi.sl.usermodel.BaseTestSlideShow;
  40. import org.apache.poi.sl.usermodel.PlaceholderDetails;
  41. import org.apache.poi.util.LocaleUtil;
  42. import org.junit.jupiter.api.Test;
  43. /**
  44. * Tests for TextRuns
  45. */
  46. @SuppressWarnings("UnusedAssignment")
  47. public final class TestTextRun {
  48. /**
  49. * Test to ensure that getting the text works correctly
  50. */
  51. @Test
  52. void testGetText() throws IOException {
  53. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  54. HSLFSlide slideOne = ppt.getSlides().get(0);
  55. List<List<HSLFTextParagraph>> textParas = slideOne.getTextParagraphs();
  56. // Get text works with \n
  57. String[] exp1 = { "This is a test title", "This is a test subtitle\nThis is on page 1" };
  58. String[] act1 = textParas.stream().map(HSLFTextParagraph::getText).toArray(String[]::new);
  59. assertArrayEquals(exp1, act1);
  60. // Raw text has \r instead
  61. String[] exp2 = { "This is a test title", "This is a test subtitle\rThis is on page 1" };
  62. String[] act2 = textParas.stream().map(HSLFTextParagraph::getRawText).toArray(String[]::new);
  63. assertArrayEquals(exp2, act2);
  64. }
  65. // Now check on a rich text run
  66. try (HSLFSlideShow ppt = getSlideShow("Single_Coloured_Page.ppt")) {
  67. List<List<HSLFTextParagraph>> textParas = ppt.getSlides().get(0).getTextParagraphs();
  68. String[] exp1 = { "This is a title, it\u2019s in black", "This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)" };
  69. String[] act1 = textParas.stream().map(HSLFTextParagraph::getText).toArray(String[]::new);
  70. assertArrayEquals(exp1, act1);
  71. String[] exp2 = { "This is a title, it\u2019s in black", "This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)" };
  72. String[] act2 = textParas.stream().map(HSLFTextParagraph::getRawText).toArray(String[]::new);
  73. assertArrayEquals(exp2, act2);
  74. }
  75. }
  76. /**
  77. * Test to ensure changing non rich text bytes->bytes works correctly
  78. */
  79. @Test
  80. void testSetText() throws IOException {
  81. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  82. List<List<HSLFTextParagraph>> textRuns = ppt.getSlides().get(0).getTextParagraphs();
  83. HSLFTextParagraph run = textRuns.get(0).get(0);
  84. HSLFTextRun tr = run.getTextRuns().get(0);
  85. // Check current text
  86. assertEquals("This is a test title", tr.getRawText());
  87. // Change
  88. String changeTo = "New test title";
  89. tr.setText(changeTo);
  90. assertEquals(changeTo, tr.getRawText());
  91. // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r'
  92. tr.setText(changeTo + "\n");
  93. assertEquals(changeTo + "\r", tr.getRawText());
  94. }
  95. }
  96. /**
  97. * Test to ensure that changing non rich text between bytes and
  98. * chars works correctly
  99. */
  100. @SuppressWarnings("unused")
  101. @Test
  102. void testAdvancedSetText() throws IOException {
  103. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  104. List<HSLFTextParagraph> paras = ppt.getSlides().get(0).getTextParagraphs().get(0);
  105. final HSLFTextParagraph para = paras.get(0);
  106. final TextBytesAtom[] tba = { null };
  107. final TextCharsAtom[] tca = { null };
  108. Runnable extract = () -> {
  109. tba[0] = null;
  110. tca[0] = null;
  111. Stream.of(para.getRecords()).forEach(r -> {
  112. if (r instanceof TextBytesAtom) tba[0] = (TextBytesAtom) r;
  113. else if (r instanceof TextCharsAtom) tca[0] = (TextCharsAtom) r;
  114. });
  115. };
  116. // Bytes -> Bytes
  117. extract.run();
  118. assertNull(tca[0]);
  119. assertNotNull(tba);
  120. // assertFalse(run._isUnicode);
  121. assertEquals("This is a test title", para.getTextRuns().get(0).getRawText());
  122. String changeBytesOnly = "New Test Title";
  123. HSLFTextParagraph.setText(paras, changeBytesOnly);
  124. extract.run();
  125. assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras));
  126. assertNull(tca[0]);
  127. assertNotNull(tba);
  128. // Bytes -> Chars
  129. String changeByteChar = "This is a test title with a '\u0121' g with a dot";
  130. HSLFTextParagraph.setText(paras, changeByteChar);
  131. extract.run();
  132. assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras));
  133. assertNotNull(tca[0]);
  134. assertNull(tba[0]);
  135. // Chars -> Chars
  136. String changeCharChar = "This is a test title with a '\u0147' N with a hat";
  137. HSLFTextParagraph.setText(paras, changeCharChar);
  138. extract.run();
  139. assertEquals(changeCharChar, HSLFTextParagraph.getRawText(paras));
  140. assertNotNull(tca[0]);
  141. assertNull(tba[0]);
  142. }
  143. }
  144. /**
  145. * Tests to ensure that non rich text has the right default rich text run
  146. * set up for it
  147. */
  148. @Test
  149. void testGetRichTextNonRich() throws IOException {
  150. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  151. List<List<HSLFTextParagraph>> textParass = ppt.getSlides().get(0).getTextParagraphs();
  152. assertEquals(2, textParass.size());
  153. List<HSLFTextParagraph> trA = textParass.get(0);
  154. List<HSLFTextParagraph> trB = textParass.get(1);
  155. assertEquals(1, trA.size());
  156. assertEquals(2, trB.size());
  157. HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0);
  158. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  159. assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText());
  160. assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
  161. }
  162. }
  163. /**
  164. * Tests to ensure that the rich text runs are built up correctly
  165. */
  166. @Test
  167. void testGetRichText() throws IOException {
  168. try (HSLFSlideShow ppt = getSlideShow("Single_Coloured_Page.ppt")) {
  169. List<List<HSLFTextParagraph>> textParass = ppt.getSlides().get(0).getTextParagraphs();
  170. assertEquals(2, textParass.size());
  171. List<HSLFTextParagraph> trA = textParass.get(0);
  172. List<HSLFTextParagraph> trB = textParass.get(1);
  173. assertEquals(1, trA.size());
  174. assertEquals(3, trB.size());
  175. HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0);
  176. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  177. HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
  178. HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
  179. assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText());
  180. String trBstr = HSLFTextParagraph.getRawText(trB);
  181. assertEquals(trBstr.substring(0, 30), rtrB.getRawText());
  182. assertEquals(trBstr.substring(30, 58), rtrC.getRawText());
  183. assertEquals(trBstr.substring(58, 82), rtrD.getRawText());
  184. // Same paragraph styles
  185. assertEquals(trB.get(0).getParagraphStyle(), trB.get(1).getParagraphStyle());
  186. assertEquals(trB.get(0).getParagraphStyle(), trB.get(2).getParagraphStyle());
  187. // Different char styles
  188. assertNotEquals(rtrB.getCharacterStyle(), rtrC.getCharacterStyle());
  189. assertNotEquals(rtrB.getCharacterStyle(), rtrD.getCharacterStyle());
  190. assertNotEquals(rtrC.getCharacterStyle(), rtrD.getCharacterStyle());
  191. }
  192. }
  193. /**
  194. * Tests to ensure that setting the text where the text isn't rich,
  195. * ensuring that everything stays with the same default styling
  196. */
  197. @Test
  198. void testSetTextWhereNotRich() throws IOException {
  199. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  200. List<HSLFTextParagraph> trB = ppt.getSlides().get(0).getTextParagraphs().get(0);
  201. assertEquals(1, trB.size());
  202. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  203. assertEquals(HSLFTextParagraph.getText(trB), rtrB.getRawText());
  204. // Change text via normal
  205. HSLFTextParagraph.setText(trB, "Test Foo Test");
  206. rtrB = trB.get(0).getTextRuns().get(0);
  207. assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB));
  208. assertEquals("Test Foo Test", rtrB.getRawText());
  209. }
  210. }
  211. /**
  212. * Tests to ensure that setting the text where the text is rich
  213. * sets everything to the same styling
  214. */
  215. @Test
  216. void testSetTextWhereRich() throws IOException {
  217. try (HSLFSlideShow ppt = getSlideShow("Single_Coloured_Page.ppt")) {
  218. List<HSLFTextParagraph> trB = ppt.getSlides().get(0).getTextParagraphs().get(1);
  219. assertEquals(3, trB.size());
  220. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  221. HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
  222. HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
  223. TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
  224. TextPropCollection tpBC = rtrB.getCharacterStyle();
  225. TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
  226. TextPropCollection tpCC = rtrC.getCharacterStyle();
  227. TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
  228. TextPropCollection tpDC = rtrD.getCharacterStyle();
  229. // assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
  230. assertNotNull(tpBP);
  231. assertNotNull(tpBC);
  232. assertNotNull(tpCP);
  233. assertNotNull(tpCC);
  234. assertNotNull(tpDP);
  235. assertNotNull(tpDC);
  236. assertEquals(tpBP, tpCP);
  237. assertEquals(tpBP, tpDP);
  238. assertEquals(tpCP, tpDP);
  239. assertNotEquals(tpBC, tpCC);
  240. assertNotEquals(tpBC, tpDC);
  241. assertNotEquals(tpCC, tpDC);
  242. // Change text via normal
  243. HSLFTextParagraph.setText(trB, "Test Foo Test");
  244. // Ensure now have first style
  245. assertEquals(1, trB.get(0).getTextRuns().size());
  246. rtrB = trB.get(0).getTextRuns().get(0);
  247. assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB));
  248. assertEquals("Test Foo Test", rtrB.getRawText());
  249. assertNotNull(rtrB.getCharacterStyle());
  250. assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
  251. assertEquals(tpBP, rtrB.getTextParagraph().getParagraphStyle());
  252. assertEquals(tpBC, rtrB.getCharacterStyle());
  253. }
  254. }
  255. /**
  256. * Test to ensure the right stuff happens if we change the text
  257. * in a rich text run, that doesn't happen to actually be rich
  258. */
  259. @Test
  260. void testChangeTextInRichTextRunNonRich() throws IOException {
  261. try (HSLFSlideShow ppt = getSlideShow("basic_test_ppt_file.ppt")) {
  262. List<List<HSLFTextParagraph>> textRuns = ppt.getSlides().get(0).getTextParagraphs();
  263. List<HSLFTextParagraph> trB = textRuns.get(1);
  264. assertEquals(1, trB.get(0).getTextRuns().size());
  265. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  266. assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
  267. assertNotNull(rtrB.getCharacterStyle());
  268. assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
  269. // Change text via rich
  270. rtrB.setText("Test Test Test");
  271. assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1)));
  272. assertEquals("Test Test Test", rtrB.getRawText());
  273. // Will now have dummy props
  274. assertNotNull(rtrB.getCharacterStyle());
  275. assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
  276. }
  277. }
  278. /**
  279. * Tests to ensure changing the text within rich text runs works
  280. * correctly
  281. */
  282. @Test
  283. void testChangeTextInRichTextRun() throws IOException {
  284. try (HSLFSlideShow ppt = getSlideShow("Single_Coloured_Page.ppt")) {
  285. HSLFSlide slideOne = ppt.getSlides().get(0);
  286. List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();
  287. List<HSLFTextParagraph> trB = textParass.get(1);
  288. assertEquals(3, trB.size());
  289. // We start with 3 text runs, each with their own set of styles,
  290. // but all sharing the same paragraph styles
  291. HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
  292. HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
  293. HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
  294. TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
  295. TextPropCollection tpBC = rtrB.getCharacterStyle();
  296. TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
  297. TextPropCollection tpCC = rtrC.getCharacterStyle();
  298. TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
  299. TextPropCollection tpDC = rtrD.getCharacterStyle();
  300. // Check text and stylings
  301. assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText());
  302. assertNotNull(tpBP);
  303. assertNotNull(tpBC);
  304. assertNotNull(tpCP);
  305. assertNotNull(tpCC);
  306. assertNotNull(tpDP);
  307. assertNotNull(tpDC);
  308. assertEquals(tpBP, tpCP);
  309. assertEquals(tpBP, tpDP);
  310. assertEquals(tpCP, tpDP);
  311. assertNotEquals(tpBC, tpCC);
  312. assertNotEquals(tpBC, tpDC);
  313. assertNotEquals(tpCC, tpDC);
  314. // Check text in the rich runs
  315. assertEquals("This is the subtitle, in bold\r", rtrB.getRawText());
  316. assertEquals("This bit is blue and italic\r", rtrC.getRawText());
  317. assertEquals("This bit is red (normal)", rtrD.getRawText());
  318. String newBText = "New Subtitle, will still be bold\n";
  319. String newCText = "New blue and italic text\n";
  320. String newDText = "Funky new normal red text";
  321. rtrB.setText(newBText);
  322. rtrC.setText(newCText);
  323. rtrD.setText(newDText);
  324. HSLFTextParagraph.storeText(trB);
  325. assertEquals(newBText.replace('\n', '\r'), rtrB.getRawText());
  326. assertEquals(newCText.replace('\n', '\r'), rtrC.getRawText());
  327. assertEquals(newDText.replace('\n', '\r'), rtrD.getRawText());
  328. assertEquals(newBText.replace('\n', '\r') + newCText.replace('\n', '\r') + newDText.replace('\n', '\r'), HSLFTextParagraph.getRawText(trB));
  329. // The styles should have been updated for the new sizes
  330. assertEquals(newBText.length(), tpBC.getCharactersCovered());
  331. assertEquals(newCText.length(), tpCC.getCharactersCovered());
  332. assertEquals(newDText.length() + 1, tpDC.getCharactersCovered()); // Last one is always one larger
  333. // Paragraph style should be sum of text length
  334. assertEquals(
  335. newBText.length() + newCText.length() + newDText.length() + 1,
  336. tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered()
  337. );
  338. // Check stylings still as expected
  339. TextPropCollection ntpBC = rtrB.getCharacterStyle();
  340. TextPropCollection ntpCC = rtrC.getCharacterStyle();
  341. TextPropCollection ntpDC = rtrD.getCharacterStyle();
  342. assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
  343. assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
  344. assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
  345. }
  346. }
  347. /**
  348. * Test case for Bug 41015.
  349. *
  350. * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because
  351. * of the wrong list of potential paragraph properties defined in StyleTextPropAtom.
  352. *
  353. */
  354. @Test
  355. void testBug41015() throws IOException {
  356. try (HSLFSlideShow ppt = getSlideShow("bug-41015.ppt")) {
  357. HSLFSlide sl = ppt.getSlides().get(0);
  358. List<List<HSLFTextParagraph>> textParass = sl.getTextParagraphs();
  359. assertEquals(2, textParass.size());
  360. List<HSLFTextParagraph> textParas = textParass.get(0);
  361. List<HSLFTextRun> rt = textParass.get(0).get(0).getTextRuns();
  362. assertEquals(1, rt.size());
  363. assertEquals(0, textParass.get(0).get(0).getIndentLevel());
  364. assertEquals("sdfsdfsdf", rt.get(0).getRawText());
  365. textParas = textParass.get(1);
  366. String[] texts = {"Sdfsdfsdf\r", "Dfgdfg\r", "Dfgdfgdfg\r", "Sdfsdfs\r", "Sdfsdf\r"};
  367. int[] indents = {0, 0, 0, 1, 1};
  368. int i = 0;
  369. for (HSLFTextParagraph p : textParas) {
  370. assertEquals(texts[i], p.getTextRuns().get(0).getRawText());
  371. assertEquals(indents[i], p.getIndentLevel());
  372. i++;
  373. }
  374. }
  375. }
  376. /**
  377. * Test creation of TextRun objects.
  378. */
  379. @Test
  380. void testAddTextRun() throws IOException {
  381. try (HSLFSlideShow ppt = new HSLFSlideShow()) {
  382. HSLFSlide slide = ppt.createSlide();
  383. assertEquals(0, slide.getTextParagraphs().size());
  384. HSLFTextBox shape1 = new HSLFTextBox();
  385. List<HSLFTextParagraph> run1 = shape1.getTextParagraphs();
  386. shape1.setText("Text 1");
  387. slide.addShape(shape1);
  388. //The array of Slide's text runs must be updated when new text shapes are added.
  389. List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs();
  390. assertNotNull(runs);
  391. assertSame(run1, runs.get(0));
  392. HSLFTextBox shape2 = new HSLFTextBox();
  393. List<HSLFTextParagraph> run2 = shape2.getTextParagraphs();
  394. shape2.setText("Text 2");
  395. slide.addShape(shape2);
  396. assertEquals(2, runs.size());
  397. assertSame(run1, runs.get(0));
  398. assertSame(run2, runs.get(1));
  399. // as getShapes()
  400. List<HSLFShape> sh = slide.getShapes();
  401. assertEquals(2, sh.size());
  402. assertTrue(sh.get(0) instanceof HSLFTextBox);
  403. HSLFTextBox box1 = (HSLFTextBox) sh.get(0);
  404. assertSame(run1, box1.getTextParagraphs());
  405. HSLFTextBox box2 = (HSLFTextBox) sh.get(1);
  406. assertSame(run2, box2.getTextParagraphs());
  407. // test Table - a complex group of shapes containing text objects
  408. HSLFSlide slide2 = ppt.createSlide();
  409. assertTrue(slide2.getTextParagraphs().isEmpty());
  410. HSLFTable table = new HSLFTable(2, 2);
  411. slide2.addShape(table);
  412. runs = slide2.getTextParagraphs();
  413. assertNotNull(runs);
  414. assertEquals(4, runs.size());
  415. }
  416. }
  417. @Test
  418. void test48916() throws IOException {
  419. try (HSLFSlideShow ppt1 = getSlideShow("SampleShow.ppt")) {
  420. List<HSLFSlide> slides = ppt1.getSlides();
  421. for (HSLFSlide slide : slides) {
  422. for (HSLFShape sh : slide.getShapes()) {
  423. if (!(sh instanceof HSLFTextShape)) continue;
  424. HSLFTextShape tx = (HSLFTextShape) sh;
  425. List<HSLFTextParagraph> paras = tx.getTextParagraphs();
  426. //verify that records cached in TextRun and EscherTextboxWrapper are the same
  427. org.apache.poi.hslf.record.Record[] runChildren = paras.get(0).getRecords();
  428. org.apache.poi.hslf.record.Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords();
  429. assertEquals(runChildren.length, txboxChildren.length);
  430. for (int i = 0; i < txboxChildren.length; i++) {
  431. assertSame(txboxChildren[i], runChildren[i]);
  432. }
  433. // caused NPE prior to fix of Bugzilla #48916
  434. for (HSLFTextParagraph p : paras) {
  435. for (HSLFTextRun rt : p.getTextRuns()) {
  436. rt.setBold(true);
  437. rt.setFontColor(Color.RED);
  438. }
  439. }
  440. // tx.storeText();
  441. }
  442. }
  443. try (HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1)) {
  444. List<HSLFTextRun> runs = ppt2.getSlides().stream()
  445. .flatMap(s -> s.getShapes().stream())
  446. .filter(s -> s instanceof HSLFTextShape)
  447. .map(s -> ((HSLFTextShape) s).getTextParagraphs().get(0).getTextRuns().get(0))
  448. .collect(Collectors.toList());
  449. assertFalse(runs.isEmpty());
  450. assertTrue(runs.stream().allMatch(HSLFTextRun::isBold));
  451. assertTrue(runs.stream().map(HSLFTextRun::getFontColor)
  452. .map(BaseTestSlideShow::getColor).allMatch(Color.RED::equals));
  453. }
  454. }
  455. }
  456. @Test
  457. void test52244() throws IOException {
  458. try (HSLFSlideShow ppt = getSlideShow("52244.ppt")) {
  459. HSLFSlide slide = ppt.getSlides().get(0);
  460. List<HSLFTextRun> runs = slide.getTextParagraphs().stream().map(tp -> tp.get(0).getTextRuns().get(0)).collect(Collectors.toList());
  461. assertTrue(runs.stream().map(HSLFTextRun::getFontFamily).allMatch("Arial"::equals));
  462. int[] exp = {36, 24, 12, 32, 12, 12};
  463. //noinspection ConstantConditions
  464. int[] act = runs.stream().map(HSLFTextRun::getFontSize).mapToInt(Double::intValue).toArray();
  465. assertArrayEquals(exp, act);
  466. }
  467. }
  468. @Test
  469. void testAppendEmpty() throws IOException {
  470. try (HSLFSlideShow ppt = new HSLFSlideShow()) {
  471. HSLFSlide s = ppt.createSlide();
  472. HSLFTextBox title = s.addTitle();
  473. title.setText("");
  474. title.appendText("\n", true);
  475. title.appendText("para", true);
  476. assertEquals("\npara", title.getText());
  477. }
  478. }
  479. @Test
  480. void datetimeFormats() throws IOException {
  481. LocalDateTime ldt = LocalDateTime.of(2012, 3, 4, 23, 45, 26);
  482. final Map<Locale, String[]> formats = new HashMap<>();
  483. formats.put(Locale.GERMANY, new String[]{
  484. "04.03.2012",
  485. "Sonntag, 4. M\u00e4rz 2012",
  486. "04/03/12",
  487. "4. M\u00e4rz 2012",
  488. "12-03-04",
  489. "M\u00e4rz 12",
  490. "M\u00e4r-12",
  491. "04.03.12 23:45",
  492. "04.03.12 23:45:26",
  493. "23:45",
  494. "23:45:26",
  495. "11:45",
  496. "11:45:26"
  497. });
  498. formats.put(Locale.US, new String[]{
  499. "03/04/2012",
  500. "Sunday, March 4, 2012",
  501. "4 March 2012",
  502. "March 04, 2012",
  503. "4-Mar-12",
  504. "March 12",
  505. "Mar-12",
  506. "3/4/12 11:45 PM",
  507. "3/4/12 11:45:26 PM",
  508. "23:45",
  509. "23:45:26",
  510. "11:45 PM",
  511. "11:45:26 PM"
  512. });
  513. try (HSLFSlideShow ppt = getSlideShow("datetime.ppt")) {
  514. List<HSLFTextShape> shapes = ppt.getSlides().get(0).getShapes()
  515. .stream().map(HSLFTextShape.class::cast).collect(Collectors.toList());
  516. int[] expFormatId = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
  517. int[] actFormatId = shapes.stream().flatMap(tp -> Stream.of(tp.getTextParagraphs().get(0).getRecords()))
  518. .filter(r -> r instanceof DateTimeMCAtom)
  519. .mapToInt(r -> ((DateTimeMCAtom)r).getIndex()).toArray();
  520. assertArrayEquals(expFormatId, actFormatId);
  521. List<HSLFShapePlaceholderDetails> phs =
  522. shapes.stream().map(HSLFSimpleShape::getPlaceholderDetails).collect(Collectors.toList());
  523. for (Map.Entry<Locale,String[]> me : formats.entrySet()) {
  524. LocaleUtil.setUserLocale(me.getKey());
  525. // refresh internal members
  526. phs.forEach(PlaceholderDetails::getPlaceholder);
  527. String[] actDate = phs.stream().map(PlaceholderDetails::getDateFormat).map(ldt::format).toArray(String[]::new);
  528. assertArrayEquals(me.getValue(), actDate,
  529. "While handling local " + me.getKey());
  530. }
  531. } finally {
  532. LocaleUtil.resetUserLocale();
  533. }
  534. }
  535. }