diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java b/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java index dce95ec0b..20547571f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java @@ -56,6 +56,10 @@ public class Notes extends Sheet // one of TextBytesAtom or TextCharsAtom, found inside // EscherTextboxWrapper's in the PPDrawing _runs = findTextRuns(_notes.getPPDrawing()); + + // Set the sheet on each TextRun + for (int i = 0; i < _runs.length; i++) + _runs[i].setSheet(this); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java index 3fd9c9525..99515198e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java @@ -170,7 +170,8 @@ public class RichTextRun Sheet sheet = parentRun.getSheet(); int txtype = parentRun.getRunType(); SlideMaster master = (SlideMaster)sheet.getMasterSheet(); - cftp = (CharFlagsTextProp)master.getStyleAttribute(txtype, getIndentLevel(), "char_flags", true); + if (master != null) + cftp = (CharFlagsTextProp)master.getStyleAttribute(txtype, getIndentLevel(), "char_flags", true); } return cftp == null ? false : cftp.getSubValue(index); @@ -223,7 +224,8 @@ public class RichTextRun Sheet sheet = parentRun.getSheet(); int txtype = parentRun.getRunType(); SlideMaster master = (SlideMaster)sheet.getMasterSheet(); - prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true); + if (master != null) + prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true); } return prop == null ? -1 : prop.getValue(); } @@ -242,7 +244,8 @@ public class RichTextRun Sheet sheet = parentRun.getSheet(); int txtype = parentRun.getRunType(); SlideMaster master = (SlideMaster)sheet.getMasterSheet(); - prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false); + if (master != null) + prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false); } return prop == null ? -1 : prop.getValue(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java index fdecb2bb0..7f201fb7b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java @@ -30,21 +30,10 @@ import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.hslf.*; import org.apache.poi.hslf.model.*; -import org.apache.poi.hslf.record.Document; -import org.apache.poi.hslf.record.DocumentAtom; -import org.apache.poi.hslf.record.FontCollection; -import org.apache.poi.hslf.record.ParentAwareRecord; -import org.apache.poi.hslf.record.PositionDependentRecordContainer; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.RecordContainer; -import org.apache.poi.hslf.record.RecordTypes; -import org.apache.poi.hslf.record.SlideAtom; -import org.apache.poi.hslf.record.SlideListWithText; -import org.apache.poi.hslf.record.SlidePersistAtom; -import org.apache.poi.hslf.record.UserEditAtom; +import org.apache.poi.hslf.model.Notes; +import org.apache.poi.hslf.model.Slide; import org.apache.poi.hslf.record.SlideListWithText.*; -import org.apache.poi.hslf.record.PersistPtrHolder; -import org.apache.poi.hslf.record.PositionDependentRecord; +import org.apache.poi.hslf.record.*; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.util.ArrayUtil; import org.apache.poi.util.POILogFactory; @@ -363,13 +352,14 @@ public class SlideShow Record r = getCoreRecordForSAS(notesSets[i]); // Ensure it really is a notes record - if(r != null && r instanceof org.apache.poi.hslf.record.Notes) { - notesRecordsL.add( (org.apache.poi.hslf.record.Notes)r ); + if(r instanceof org.apache.poi.hslf.record.Notes) { + org.apache.poi.hslf.record.Notes notesRecord = (org.apache.poi.hslf.record.Notes)r; + notesRecordsL.add( notesRecord ); // Record the match between slide id and these notes - SlidePersistAtom spa = notesSets[i].getSlidePersistAtom(); - Integer slideId = new Integer(spa.getSlideIdentifier()); - slideIdToNotes.put(slideId, new Integer(i)); + SlidePersistAtom spa = notesSets[i].getSlidePersistAtom(); + Integer slideId = new Integer(spa.getSlideIdentifier()); + slideIdToNotes.put(slideId, new Integer(i)); } else { logger.log(POILogger.ERROR, "A Notes SlideAtomSet at " + i + " said its record was at refID " + notesSets[i].getSlidePersistAtom().getRefID() + ", but that was actually a " + r); } @@ -397,7 +387,7 @@ public class SlideShow if(r instanceof org.apache.poi.hslf.record.Slide) { slidesRecords[i] = (org.apache.poi.hslf.record.Slide)r; } else { - System.err.println("A Slide SlideAtomSet at " + i + " said its record was at refID " + slidesSets[i].getSlidePersistAtom().getRefID() + ", but that was actually a " + r); + logger.log(POILogger.ERROR, "A Slide SlideAtomSet at " + i + " said its record was at refID " + slidesSets[i].getSlidePersistAtom().getRefID() + ", but that was actually a " + r); } } } @@ -422,15 +412,17 @@ public class SlideShow for(int i=0; i<_slides.length; i++) { SlideAtomsSet sas = slidesSets[i]; int slideIdentifier = sas.getSlidePersistAtom().getSlideIdentifier(); - Integer slideIdentifierI = new Integer(slideIdentifier); - + // Do we have a notes for this? Notes notes = null; - if(slideIdToNotes.containsKey(slideIdentifierI)) { - Integer notesPos = (Integer)slideIdToNotes.get(slideIdentifierI); - notes = _notes[notesPos.intValue()]; - } - + //Slide.SlideAtom.notesId references the corresponding notes slide. 0 if slide has no notes. + int noteId = slidesRecords[i].getSlideAtom().getNotesID(); + if (noteId != 0){ + Integer notesPos = (Integer)slideIdToNotes.get(new Integer(noteId)); + if (notesPos != null) notes = _notes[notesPos.intValue()]; + else logger.log(POILogger.ERROR, "Notes not found for noteId=" + noteId); + } + // Now, build our slide _slides[i] = new Slide(slidesRecords[i], notes, sas, slideIdentifier, (i+1)); _slides[i].setSlideShow(this); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-1.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-1.ppt new file mode 100644 index 000000000..15b654d26 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-1.ppt differ diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-2.ppt b/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-2.ppt new file mode 100644 index 000000000..5c6f8ca90 Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hslf/data/42474-2.ppt differ diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java index cfc3c9529..e79d05bc5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java @@ -20,8 +20,13 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.Slide; +import org.apache.poi.hslf.model.Notes; +import org.apache.poi.hslf.model.TextRun; import java.io.*; +import java.util.HashSet; +import java.util.HashMap; /** * Testcases for bugs entered in bugzilla @@ -50,4 +55,67 @@ public class TestBugs extends TestCase { assertEquals(Picture.JPEG, pict[0].getType()); assertEquals(Picture.JPEG, pict[1].getType()); } + + /** + * First fix from Bug 42474: NPE in RichTextRun.isBold() + * when the RichTextRun comes from a Notes model object + */ + public void test42474_1() throws Exception { + FileInputStream is = new FileInputStream(new File(cwd, "42474-1.ppt")); + HSLFSlideShow hslf = new HSLFSlideShow(is); + is.close(); + + SlideShow ppt = new SlideShow(hslf); + assertTrue("No Exceptions while reading file", true); + assertEquals(2, ppt.getSlides().length); + + TextRun txrun; + Notes notes; + + notes = ppt.getSlides()[0].getNotesSheet(); + assertNotNull(notes); + txrun = notes.getTextRuns()[0]; + assertEquals("Notes-1", txrun.getRawText()); + assertEquals(false, txrun.getRichTextRuns()[0].isBold()); + + //notes for the second slide are in bold + notes = ppt.getSlides()[1].getNotesSheet(); + assertNotNull(notes); + txrun = notes.getTextRuns()[0]; + assertEquals("Notes-2", txrun.getRawText()); + assertEquals(true, txrun.getRichTextRuns()[0].isBold()); + + } + + /** + * Second fix from Bug 42474: Incorrect matching of notes to slides + */ + public void test42474_2() throws Exception { + FileInputStream is = new FileInputStream(new File(cwd, "42474-2.ppt")); + HSLFSlideShow hslf = new HSLFSlideShow(is); + is.close(); + + SlideShow ppt = new SlideShow(hslf); + + //map slide number and starting phrase of its notes + HashMap notesMap = new HashMap(); + notesMap.put(new Integer(4), "For decades before calculators"); + notesMap.put(new Integer(5), "Several commercial applications"); + notesMap.put(new Integer(6), "There are three variations of LNS that are discussed here"); + notesMap.put(new Integer(7), "Although multiply and square root are easier"); + notesMap.put(new Integer(8), "The bus Z is split into Z_H and Z_L"); + + Slide[] slide = ppt.getSlides(); + for (int i = 0; i < slide.length; i++) { + Integer slideNumber = new Integer(slide[i].getSlideNumber()); + Notes notes = slide[i].getNotesSheet(); + if (notesMap.containsKey(slideNumber)){ + assertNotNull(notes); + String text = notes.getTextRuns()[0].getRawText(); + String startingPhrase = (String)notesMap.get(slideNumber); + assertTrue("Notes for slide " + slideNumber + " must start with " + + startingPhrase , text.startsWith(startingPhrase)); + } + } + } }