001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.poi.hslf.usermodel;
018:
019: import java.io.*;
020: import java.awt.*;
021:
022: import org.apache.poi.hslf.HSLFSlideShow;
023: import org.apache.poi.hslf.model.*;
024: import org.apache.poi.hslf.record.Record;
025: import org.apache.poi.hslf.record.SlideListWithText;
026:
027: import junit.framework.TestCase;
028:
029: /**
030: * Test that the friendly getters and setters on RichTextRun
031: * behave as expected.
032: * (model.TestTextRun tests the other functionality)
033: * @author Nick Burch (nick at torchbox dot com)
034: */
035: public class TestRichTextRun extends TestCase {
036: // SlideShow primed on the test data
037: private SlideShow ss;
038: private SlideShow ssRichA;
039: private SlideShow ssRichB;
040: private SlideShow ssRichC;
041: private HSLFSlideShow hss;
042: private HSLFSlideShow hssRichA;
043: private HSLFSlideShow hssRichB;
044: private HSLFSlideShow hssRichC;
045: private String filenameC;
046:
047: protected void setUp() throws Exception {
048: String dirname = System.getProperty("HSLF.testdata.path");
049:
050: // Basic (non rich) test file
051: String filename = dirname + "/basic_test_ppt_file.ppt";
052: hss = new HSLFSlideShow(filename);
053: ss = new SlideShow(hss);
054:
055: // Rich test file A
056: filename = dirname + "/Single_Coloured_Page.ppt";
057: hssRichA = new HSLFSlideShow(filename);
058: ssRichA = new SlideShow(hssRichA);
059:
060: // Rich test file B
061: filename = dirname
062: + "/Single_Coloured_Page_With_Fonts_and_Alignments.ppt";
063: hssRichB = new HSLFSlideShow(filename);
064: ssRichB = new SlideShow(hssRichB);
065:
066: // Rich test file C - has paragraph styles that run out before
067: // the character ones do
068: filenameC = dirname
069: + "/ParagraphStylesShorterThanCharStyles.ppt";
070: hssRichC = new HSLFSlideShow(filenameC);
071: ssRichC = new SlideShow(hssRichC);
072: }
073:
074: /**
075: * Test the stuff about getting/setting bold
076: * on a non rich text run
077: */
078: public void testBoldNonRich() throws Exception {
079: Slide slideOne = ss.getSlides()[0];
080: TextRun[] textRuns = slideOne.getTextRuns();
081: RichTextRun rtr = textRuns[0].getRichTextRuns()[0];
082:
083: assertNull(rtr._getRawCharacterStyle());
084: assertNull(rtr._getRawParagraphStyle());
085: assertFalse(rtr.isBold());
086:
087: // Now set it to not bold
088: rtr.setBold(false);
089: assertNotNull(rtr._getRawCharacterStyle());
090: assertNotNull(rtr._getRawParagraphStyle());
091: assertFalse(rtr.isBold());
092:
093: // And now make it bold
094: rtr.setBold(true);
095: assertNotNull(rtr._getRawCharacterStyle());
096: assertNotNull(rtr._getRawParagraphStyle());
097: assertTrue(rtr.isBold());
098: }
099:
100: /**
101: * Test the stuff about getting/setting bold
102: * on a rich text run
103: */
104: public void testBoldRich() throws Exception {
105: Slide slideOneR = ssRichA.getSlides()[0];
106: TextRun[] textRunsR = slideOneR.getTextRuns();
107: RichTextRun[] rtrs = textRunsR[1].getRichTextRuns();
108: assertEquals(3, rtrs.length);
109:
110: assertTrue(rtrs[0].isBold());
111: assertFalse(rtrs[1].isBold());
112: assertFalse(rtrs[2].isBold());
113:
114: rtrs[0].setBold(true);
115: rtrs[1].setBold(true);
116:
117: assertTrue(rtrs[0].isBold());
118: assertTrue(rtrs[1].isBold());
119:
120: rtrs[0].setBold(false);
121: rtrs[1].setBold(false);
122:
123: assertFalse(rtrs[0].isBold());
124: assertFalse(rtrs[1].isBold());
125: }
126:
127: /**
128: * Tests getting and setting the font size on rich and non
129: * rich text runs
130: */
131: public void testFontSize() throws Exception {
132: SlideMaster master;
133: Slide slideOne = ss.getSlides()[0];
134: TextRun[] textRuns = slideOne.getTextRuns();
135: RichTextRun rtr = textRuns[0].getRichTextRuns()[0];
136:
137: Slide slideOneR = ssRichB.getSlides()[0];
138: TextRun[] textRunsR = slideOneR.getTextRuns();
139: RichTextRun rtrRa = textRunsR[0].getRichTextRuns()[0];
140: RichTextRun rtrRb = textRunsR[1].getRichTextRuns()[0];
141: RichTextRun rtrRc = textRunsR[1].getRichTextRuns()[3];
142:
143: String defaultFont = "Arial";
144:
145: // Start off with rich one
146: // First run has defaults
147: assertEquals(44, rtrRa.getFontSize());
148: assertEquals(defaultFont, rtrRa.getFontName());
149:
150: // Second is size 20, default font
151: assertEquals(20, rtrRb.getFontSize());
152: assertEquals(defaultFont, rtrRb.getFontName());
153: // Third is size 24, alt font
154: assertEquals(24, rtrRc.getFontSize());
155: assertEquals("Times New Roman", rtrRc.getFontName());
156:
157: // Change 2nd to different size and font
158: assertEquals(2,
159: ssRichB.getFontCollection().getChildRecords().length); // Default + TNR
160: rtrRb.setFontSize(18);
161: rtrRb.setFontName("Courier");
162: assertEquals(3,
163: ssRichB.getFontCollection().getChildRecords().length); // Default + TNR + Courier
164: assertEquals(18, rtrRb.getFontSize());
165: assertEquals("Courier", rtrRb.getFontName());
166:
167: // Now do non rich one
168: assertEquals(44, rtr.getFontSize());
169: assertEquals(defaultFont, rtr.getFontName());
170: assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default
171: assertNull(rtr._getRawCharacterStyle());
172: assertNull(rtr._getRawParagraphStyle());
173:
174: // Change Font size
175: rtr.setFontSize(99);
176: assertEquals(99, rtr.getFontSize());
177: assertEquals(defaultFont, rtr.getFontName());
178: assertNotNull(rtr._getRawCharacterStyle());
179: assertNotNull(rtr._getRawParagraphStyle());
180: assertEquals(1, ss.getFontCollection().getChildRecords().length); // Default
181:
182: // Change Font size and name
183: rtr.setFontSize(25);
184: rtr.setFontName("Times New Roman");
185: assertEquals(25, rtr.getFontSize());
186: assertEquals("Times New Roman", rtr.getFontName());
187: assertNotNull(rtr._getRawCharacterStyle());
188: assertNotNull(rtr._getRawParagraphStyle());
189: assertEquals(2, ss.getFontCollection().getChildRecords().length);
190: }
191:
192: public void testChangeWriteRead() throws Exception {
193: HSLFSlideShow[] h = new HSLFSlideShow[] { hss, hssRichA,
194: hssRichB };
195: Slide[] s = new Slide[] { ss.getSlides()[0],
196: ssRichA.getSlides()[0], ssRichB.getSlides()[0] };
197:
198: for (int i = 0; i < h.length; i++) {
199: // Change
200: Slide slideOne = s[i];
201: TextRun[] textRuns = slideOne.getTextRuns();
202: RichTextRun rtr = textRuns[0].getRichTextRuns()[0];
203:
204: rtr.setBold(true);
205: rtr.setFontSize(18);
206: rtr.setFontName("Courier");
207:
208: // Check it took those
209: assertEquals(true, rtr.isBold());
210: assertEquals(18, rtr.getFontSize());
211: assertEquals("Courier", rtr.getFontName());
212:
213: // Write out and back in
214: ByteArrayOutputStream baos = new ByteArrayOutputStream();
215: h[i].write(baos);
216: ByteArrayInputStream bais = new ByteArrayInputStream(baos
217: .toByteArray());
218:
219: HSLFSlideShow readHSLF = new HSLFSlideShow(bais);
220: SlideShow readS = new SlideShow(readHSLF);
221:
222: // Tweak existing one again, to ensure really worked
223: rtr.setBold(false);
224: rtr.setFontSize(17);
225: rtr.setFontName("CourierZZ");
226:
227: // Check it took those changes
228: assertEquals(false, rtr.isBold());
229: assertEquals(17, rtr.getFontSize());
230: assertEquals("CourierZZ", rtr.getFontName());
231:
232: // Now, look at the one we changed, wrote out, and read back in
233: // Ensure it does contain our original modifications
234: Slide slideOneRR = readS.getSlides()[0];
235: TextRun[] textRunsRR = slideOneRR.getTextRuns();
236: RichTextRun rtrRRa = textRunsRR[0].getRichTextRuns()[0];
237:
238: assertEquals(true, rtrRRa.isBold());
239: assertEquals(18, rtrRRa.getFontSize());
240: assertEquals("Courier", rtrRRa.getFontName());
241: }
242: }
243:
244: /**
245: * Test that we can do the right things when the paragraph styles
246: * run out before the character styles do
247: */
248: public void testParagraphStylesShorterTheCharStyles() {
249: // Check we have the right number of sheets
250: Slide[] slides = ssRichC.getSlides();
251: assertEquals(14, slides.length);
252:
253: // Check the number of text runs on interesting sheets
254: Slide slideThreeC = ssRichC.getSlides()[2];
255: Slide slideSevenC = ssRichC.getSlides()[6];
256: assertEquals(3, slideThreeC.getTextRuns().length);
257: assertEquals(5, slideSevenC.getTextRuns().length);
258:
259: // On slide three, we should have:
260: // TR:
261: // You are an important supplier of various items that I need
262: // .
263: // TR:
264: // Source: Internal focus groups
265: // TR:
266: // Illustrative Example
267: // .
268:
269: TextRun[] s3tr = slideThreeC.getTextRuns();
270: RichTextRun[] s3rtr0 = s3tr[0].getRichTextRuns();
271: RichTextRun[] s3rtr1 = s3tr[1].getRichTextRuns();
272: RichTextRun[] s3rtr2 = s3tr[2].getRichTextRuns();
273:
274: assertEquals(2, s3rtr0.length);
275: assertEquals(1, s3rtr1.length);
276: assertEquals(2, s3rtr2.length);
277:
278: assertEquals(
279: "You are an important supplier of various items that I need",
280: s3rtr0[0].getText());
281: assertEquals("", s3rtr0[1].getText());
282: assertEquals("Source: Internal focus groups", s3rtr1[0]
283: .getText());
284: assertEquals("Illustrative Example", s3rtr2[0].getText());
285: assertEquals("", s3rtr2[1].getText());
286:
287: assertTrue(s3rtr0[0]._isParagraphStyleShared());
288: assertTrue(s3rtr0[1]._isParagraphStyleShared());
289: assertFalse(s3rtr1[0]._isParagraphStyleShared());
290: assertTrue(s3rtr2[0]._isParagraphStyleShared());
291: assertTrue(s3rtr2[1]._isParagraphStyleShared());
292:
293: assertFalse(s3rtr0[0]._isCharacterStyleShared());
294: assertFalse(s3rtr0[1]._isCharacterStyleShared());
295: assertFalse(s3rtr1[0]._isCharacterStyleShared());
296: assertFalse(s3rtr2[0]._isCharacterStyleShared());
297: assertFalse(s3rtr2[1]._isCharacterStyleShared());
298:
299: // On slide seven, we have:
300: // TR:
301: // (text)
302: // TR:
303: // <ps>(text a)</ps><ps>(text a)(text b)</ps>
304: // TR:
305: // (text)
306: TextRun[] s7tr = slideSevenC.getTextRuns();
307: RichTextRun[] s7rtr0 = s7tr[0].getRichTextRuns();
308: RichTextRun[] s7rtr1 = s7tr[1].getRichTextRuns();
309: RichTextRun[] s7rtr2 = s7tr[2].getRichTextRuns();
310:
311: assertEquals(1, s7rtr0.length);
312: assertEquals(3, s7rtr1.length);
313: assertEquals(1, s7rtr2.length);
314:
315: assertFalse(s7rtr0[0]._isParagraphStyleShared());
316: assertFalse(s7rtr1[0]._isParagraphStyleShared());
317: assertTrue(s7rtr1[1]._isParagraphStyleShared());
318: assertTrue(s7rtr1[2]._isParagraphStyleShared());
319: assertFalse(s7rtr2[0]._isParagraphStyleShared());
320:
321: assertFalse(s7rtr0[0]._isCharacterStyleShared());
322: assertTrue(s7rtr1[0]._isCharacterStyleShared());
323: assertTrue(s7rtr1[1]._isCharacterStyleShared());
324: assertFalse(s7rtr1[2]._isCharacterStyleShared());
325: assertFalse(s7rtr2[0]._isCharacterStyleShared());
326: }
327:
328: /**
329: * Test that we can do the right things when the paragraph styles
330: * run out before the character styles do, when we tweak something
331: * and write back out.
332: */
333: public void testParagraphStylesShorterTheCharStylesWrite()
334: throws Exception {
335: assertMatchesSLTWC(ssRichC);
336: assertMatchesFileC(ssRichC);
337:
338: Slide slideSevenC = ssRichC.getSlides()[6];
339: TextRun[] s7tr = slideSevenC.getTextRuns();
340: RichTextRun[] s7rtr0 = s7tr[0].getRichTextRuns();
341: RichTextRun[] s7rtr1 = s7tr[1].getRichTextRuns();
342: RichTextRun[] s7rtr2 = s7tr[2].getRichTextRuns();
343:
344: String oldText;
345:
346: // Reset the text on the last run
347: // Need to ensure it's a run that really has styles!
348: oldText = s7rtr2[0].getRawText();
349: s7rtr2[0].setText(oldText);
350: assertEquals(oldText, s7rtr2[0].getText());
351: assertEquals(oldText, s7tr[2].getText());
352: assertEquals(oldText.length() + 1, s7rtr2[0]
353: ._getRawCharacterStyle().getCharactersCovered());
354: assertEquals(oldText.length() + 1, s7rtr2[0]
355: ._getRawParagraphStyle().getCharactersCovered());
356: assertMatchesSLTWC(ssRichC);
357: assertMatchesFileC(ssRichC);
358:
359: // Reset the text on a shared paragraph
360: oldText = s7rtr1[2].getRawText();
361: s7rtr1[2].setText(oldText);
362: assertEquals(oldText, s7rtr1[2].getText());
363: assertEquals(oldText.length() + 1, s7rtr1[2]
364: ._getRawCharacterStyle().getCharactersCovered());
365: assertMatchesSLTWC(ssRichC);
366: assertMatchesFileC(ssRichC);
367:
368: // Reset the text on a shared paragraph+character
369: s7rtr1[1].setText(s7rtr1[1].getRawText());
370: assertMatchesSLTWC(ssRichC);
371: assertMatchesFileC(ssRichC);
372: }
373:
374: /**
375: * Opens a new copy of SlideShow C, writes the active
376: * SlideListWithText out, and compares it to the write
377: * out of the supplied SlideShow. Also compares the
378: * contents.
379: * @param s
380: */
381: private void assertMatchesSLTWC(SlideShow s) throws Exception {
382: // Grab a new copy of slideshow C
383: SlideShow refC = new SlideShow(new HSLFSlideShow(filenameC));
384:
385: // Write out the 2nd SLWT in the active document
386: SlideListWithText refSLWT = refC.getDocumentRecord()
387: .getSlideListWithTexts()[1];
388: byte[] raw_slwt = writeRecord(refSLWT);
389:
390: // Write out the same for the supplied slideshow
391: SlideListWithText s_SLWT = s.getDocumentRecord()
392: .getSlideListWithTexts()[1];
393: byte[] s_slwt = writeRecord(s_SLWT);
394:
395: // Check the records are the same
396: assertEquals(refSLWT.getChildRecords().length, s_SLWT
397: .getChildRecords().length);
398: for (int i = 0; i < refSLWT.getChildRecords().length; i++) {
399: Record ref_r = refSLWT.getChildRecords()[i];
400: Record s_r = s_SLWT.getChildRecords()[i];
401:
402: byte[] r_rb = writeRecord(ref_r);
403: byte[] s_rb = writeRecord(s_r);
404: assertEquals(r_rb.length, s_rb.length);
405: for (int j = 0; j < r_rb.length; j++) {
406: assertEquals(r_rb[j], s_rb[j]);
407: }
408: }
409:
410: // Check the bytes are the same
411: assertEquals(raw_slwt.length, s_slwt.length);
412: for (int i = 0; i < raw_slwt.length; i++) {
413: assertEquals(raw_slwt[i], s_slwt[i]);
414: }
415: }
416:
417: /**
418: * Checks that the supplied slideshow still matches the bytes
419: * of slideshow c
420: */
421: private void assertMatchesFileC(SlideShow s) throws Exception {
422: // Disabled, pending fix of bug #39800
423: System.err
424: .println("Skipping test, as would be marked as failed due to bug #39800");
425: if (false) {
426: // Grab the bytes of the file
427: FileInputStream fin = new FileInputStream(filenameC);
428: ByteArrayOutputStream fb = new ByteArrayOutputStream();
429: byte[] b = new byte[4096];
430: int read = 0;
431: while (read != -1) {
432: read = fin.read(b);
433: if (read > 0) {
434: fb.write(b, 0, read);
435: }
436: }
437: byte[] raw_file = fb.toByteArray();
438:
439: // Now write out the slideshow
440: ByteArrayOutputStream baos = new ByteArrayOutputStream();
441: s.write(baos);
442: byte[] raw_ss = baos.toByteArray();
443:
444: // Ensure they're the same
445: assertEquals(raw_file.length, raw_ss.length);
446: for (int i = 0; i < raw_file.length; i++) {
447: assertEquals(raw_file[i], raw_ss[i]);
448: }
449: }
450: }
451:
452: private byte[] writeRecord(Record r) throws Exception {
453: ByteArrayOutputStream baos = new ByteArrayOutputStream();
454: r.writeOut(baos);
455: return baos.toByteArray();
456: }
457:
458: public void testIndentationLevel() throws Exception {
459: SlideShow ppt = new SlideShow(new HSLFSlideShow(new File(System
460: .getProperty("HSLF.testdata.path"),
461: "ParagraphStylesShorterThanCharStyles.ppt").getPath()));
462: Slide[] sl = ppt.getSlides();
463: for (int i = 0; i < sl.length; i++) {
464: TextRun[] txt = sl[i].getTextRuns();
465: for (int j = 0; j < txt.length; j++) {
466: RichTextRun[] rt = txt[j].getRichTextRuns();
467: for (int k = 0; k < rt.length; k++) {
468: int indent = rt[k].getIndentLevel();
469: assertTrue(indent >= 0 && indent <= 4);
470: }
471:
472: }
473: }
474: }
475:
476: public void testReadParagraphStyles() throws Exception {
477: FileInputStream is = new FileInputStream(new File(System
478: .getProperty("HSLF.testdata.path"), "bullets.ppt"));
479: SlideShow ppt = new SlideShow(is);
480: is.close();
481: assertTrue("No Exceptions while reading file", true);
482:
483: RichTextRun rt;
484: TextRun[] txt;
485: Slide[] slide = ppt.getSlides();
486: assertEquals(2, slide.length);
487:
488: txt = slide[0].getTextRuns();
489: assertEquals(2, txt.length);
490:
491: assertEquals("Title text", txt[0].getRawText());
492: assertEquals(1, txt[0].getRichTextRuns().length);
493: rt = txt[0].getRichTextRuns()[0];
494: assertFalse(rt.isBullet());
495:
496: assertEquals("This is a text placeholder that \r"
497: + "follows the design pattern\r"
498: + "Defined in the slide master\r"
499: + "and has bullets by default", txt[1].getRawText());
500: assertEquals(1, txt[1].getRichTextRuns().length);
501: rt = txt[1].getRichTextRuns()[0];
502: assertEquals('\u2022', rt.getBulletChar());
503: assertTrue(rt.isBullet());
504:
505: txt = slide[1].getTextRuns();
506: assertEquals(2, txt.length);
507:
508: assertEquals("I\u2019m a text box\r" + "With bullets\r"
509: + "That follow the design pattern\r"
510: + "From the slide master", txt[0].getRawText());
511: assertEquals(1, txt[0].getRichTextRuns().length);
512: rt = txt[0].getRichTextRuns()[0];
513: assertTrue(rt.isBullet());
514: assertEquals('\u2022', rt.getBulletChar());
515:
516: assertEquals("I\u2019m a text box with user-defined\r"
517: + "bullet character", txt[1].getRawText());
518: assertEquals(1, txt[1].getRichTextRuns().length);
519: rt = txt[1].getRichTextRuns()[0];
520: assertTrue(rt.isBullet());
521: assertEquals('\u263A', rt.getBulletChar());
522: }
523:
524: public void testSetParagraphStyles() throws Exception {
525: SlideShow ppt = new SlideShow();
526:
527: Slide slide = ppt.createSlide();
528:
529: TextBox shape = new TextBox();
530: RichTextRun rt = shape.getTextRun().getRichTextRuns()[0];
531: shape.setText("Hello, World!\r" + "This should be\r"
532: + "Multiline text");
533: rt.setFontSize(42);
534: rt.setBullet(true);
535: rt.setTextOffset(50);
536: rt.setBulletOffset(0);
537: rt.setBulletChar('\u263A');
538: slide.addShape(shape);
539:
540: assertEquals(42, rt.getFontSize());
541: assertEquals(true, rt.isBullet());
542: assertEquals(50, rt.getTextOffset());
543: assertEquals(0, rt.getBulletOffset());
544: assertEquals('\u263A', rt.getBulletChar());
545:
546: shape.setAnchor(new java.awt.Rectangle(50, 50, 500, 300));
547: slide.addShape(shape);
548:
549: //serialize and read again
550: ByteArrayOutputStream out = new ByteArrayOutputStream();
551: ppt.write(out);
552: out.close();
553:
554: ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray()));
555: slide = ppt.getSlides()[0];
556: shape = (TextBox) slide.getShapes()[0];
557: rt = shape.getTextRun().getRichTextRuns()[0];
558: assertEquals(42, rt.getFontSize());
559: assertEquals(true, rt.isBullet());
560: assertEquals(50, rt.getTextOffset());
561: assertEquals(0, rt.getBulletOffset());
562: assertEquals('\u263A', rt.getBulletChar());
563: }
564: }
|