From: Andreas Beeker Date: Thu, 19 Mar 2015 23:44:23 +0000 (+0000) Subject: Snapshot commit - still lots of errors, xslf rendering works, started work on hslf X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=652211b8d24a830dc8e5596b832c254c87489583;p=poi.git Snapshot commit - still lots of errors, xslf rendering works, started work on hslf git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1667902 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java b/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java index 7d013237ff..7a4b20c187 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java +++ b/src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java @@ -34,7 +34,7 @@ import java.awt.*; public final class ApacheconEU08 { public static void main(String[] args) throws IOException { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); ppt.setPageSize(new Dimension(720, 540)); slide1(ppt); @@ -56,27 +56,27 @@ public final class ApacheconEU08 { } - public static void slide1(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide1(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE); tr1.setText("POI-HSLF"); box1.setAnchor(new Rectangle(54, 78, 612, 115)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE); tr2.setText("Java API To Access Microsoft PowerPoint Format Files"); box2.setAnchor(new Rectangle(108, 204, 504, 138)); slide.addShape(box2); - TextBox box3 = new TextBox(); - TextRun tr3 = box3.getTextRun(); + HSLFTextBox box3 = new HSLFTextBox(); + HSLFTextParagraph tr3 = box3.getTextParagraph(); tr3.getRichTextRuns()[0].setFontSize(32); - box3.setHorizontalAlignment(TextBox.AlignCenter); + box3.setHorizontalAlignment(HSLFTextBox.AlignCenter); tr3.setText( "Yegor Kozlov\r" + "yegor - apache - org"); @@ -84,18 +84,18 @@ public final class ApacheconEU08 { slide.addShape(box3); } - public static void slide2(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide2(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("What is HSLF?"); box1.setAnchor(new Rectangle(36, 21, 648, 90)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); tr2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " + "of the Powerpoint binary file format. \r" + @@ -107,18 +107,18 @@ public final class ApacheconEU08 { } - public static void slide3(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide3(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("HSLF in a Nutshell"); box1.setAnchor(new Rectangle(36, 15, 648, 65)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); tr2.setText( "HSLF provides a way to read, create and modify MS PowerPoint presentations\r" + @@ -128,8 +128,8 @@ public final class ApacheconEU08 { box2.setAnchor(new Rectangle(36, 80, 648, 200)); slide.addShape(box2); - TextBox box3 = new TextBox(); - TextRun tr3 = box3.getTextRun(); + HSLFTextBox box3 = new HSLFTextBox(); + HSLFTextParagraph tr3 = box3.getTextParagraph(); tr3.setRunType(TextHeaderAtom.BODY_TYPE); tr3.setText( "Rich text\r" + @@ -142,16 +142,16 @@ public final class ApacheconEU08 { box3.setAnchor(new Rectangle(36, 265, 648, 150)); slide.addShape(box3); - TextBox box4 = new TextBox(); - TextRun tr4 = box4.getTextRun(); + HSLFTextBox box4 = new HSLFTextBox(); + HSLFTextParagraph tr4 = box4.getTextParagraph(); tr4.setRunType(TextHeaderAtom.BODY_TYPE); tr4.setText("Access to low level data structures"); box4.setAnchor(new Rectangle(36, 430, 648, 50)); slide.addShape(box4); } - public static void slide4(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide4(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); String[][] txt1 = { {"Note"}, @@ -162,8 +162,8 @@ public final class ApacheconEU08 { for (int j = 0; j < txt1[i].length; j++) { TableCell cell = table1.getCell(i, j); cell.setText(txt1[i][j]); - cell.getTextRun().getRichTextRuns()[0].setFontSize(10); - RichTextRun rt = cell.getTextRun().getRichTextRuns()[0]; + cell.getTextParagraph().getRichTextRuns()[0].setFontSize(10); + HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0]; rt.setFontName("Arial"); rt.setBold(true); if(i == 0){ @@ -174,7 +174,7 @@ public final class ApacheconEU08 { rt.setFontSize(28); cell.getFill().setForegroundColor(new Color(235, 239, 241)); } - cell.setVerticalAlignment(TextBox.AnchorMiddle); + cell.setVerticalAlignment(HSLFTextBox.AnchorMiddle); } } @@ -195,30 +195,30 @@ public final class ApacheconEU08 { table1.moveTo(100, 100); - TextBox box1 = new TextBox(); - box1.setHorizontalAlignment(TextBox.AlignCenter); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + box1.setHorizontalAlignment(HSLFTextBox.AlignCenter); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setText("The source code is available at\r" + "http://people.apache.org/~yegor/apachecon_eu08/"); - RichTextRun rt = tr1.getRichTextRuns()[0]; + HSLFTextRun rt = tr1.getRichTextRuns()[0]; rt.setFontSize(24); box1.setAnchor(new Rectangle(80, 356, 553, 65)); slide.addShape(box1); } - public static void slide5(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide5(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("HSLF in Action - 1\rData Extraction"); box1.setAnchor(new Rectangle(36, 21, 648, 100)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); tr2.setText( "Text from slides and notes\r" + @@ -230,26 +230,26 @@ public final class ApacheconEU08 { } - public static void slide6(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide6(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("HSLF in Action - 2"); box1.setAnchor(new Rectangle(36, 20, 648, 90)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.getRichTextRuns()[0].setFontSize(18); tr2.setText("Creating a simple presentation from scratch"); box2.setAnchor(new Rectangle(170, 100, 364, 30)); slide.addShape(box2); - TextBox box3 = new TextBox(); - TextRun tr3 = box3.getTextRun(); - RichTextRun rt3 = tr3.getRichTextRuns()[0]; + HSLFTextBox box3 = new HSLFTextBox(); + HSLFTextParagraph tr3 = box3.getTextParagraph(); + HSLFTextRun rt3 = tr3.getRichTextRuns()[0]; rt3.setFontName("Courier New"); rt3.setFontSize(8); tr3.setText( @@ -290,30 +290,30 @@ public final class ApacheconEU08 { slide.addShape(box3); } - public static void slide7(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide7(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box2 = new TextBox(); - box2.setHorizontalAlignment(TextBox.AlignCenter); - box2.setVerticalAlignment(TextBox.AnchorMiddle); - box2.getTextRun().setText("Java Code"); + HSLFTextBox box2 = new HSLFTextBox(); + box2.setHorizontalAlignment(HSLFTextBox.AlignCenter); + box2.setVerticalAlignment(HSLFTextBox.AnchorMiddle); + box2.getTextParagraph().setText("Java Code"); box2.getFill().setForegroundColor(new Color(187, 224, 227)); box2.setLineColor(Color.black); box2.setLineWidth(0.75); box2.setAnchor(new Rectangle(66, 243, 170, 170)); slide.addShape(box2); - TextBox box3 = new TextBox(); - box3.setHorizontalAlignment(TextBox.AlignCenter); - box3.setVerticalAlignment(TextBox.AnchorMiddle); - box3.getTextRun().setText("*.ppt file"); + HSLFTextBox box3 = new HSLFTextBox(); + box3.setHorizontalAlignment(HSLFTextBox.AlignCenter); + box3.setVerticalAlignment(HSLFTextBox.AnchorMiddle); + box3.getTextParagraph().setText("*.ppt file"); box3.setLineWidth(0.75); box3.setLineColor(Color.black); box3.getFill().setForegroundColor(new Color(187, 224, 227)); box3.setAnchor(new Rectangle(473, 243, 170, 170)); slide.addShape(box3); - AutoShape box4 = new AutoShape(ShapeType.RIGHT_ARROW); + HSLFAutoShape box4 = new HSLFAutoShape(ShapeType.RIGHT_ARROW); box4.getFill().setForegroundColor(new Color(187, 224, 227)); box4.setLineWidth(0.75); box4.setLineColor(Color.black); @@ -321,18 +321,18 @@ public final class ApacheconEU08 { slide.addShape(box4); } - public static void slide8(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide8(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("Wait, there is more!"); box1.setAnchor(new Rectangle(36, 21, 648, 90)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); tr2.setText( "Rich text\r" + @@ -343,26 +343,26 @@ public final class ApacheconEU08 { slide.addShape(box2); } - public static void slide9(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide9(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("HSLF in Action - 3"); box1.setAnchor(new Rectangle(36, 20, 648, 50)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.getRichTextRuns()[0].setFontSize(18); tr2.setText("PPGraphics2D: PowerPoint Graphics2D driver"); box2.setAnchor(new Rectangle(178, 70, 387, 30)); slide.addShape(box2); - TextBox box3 = new TextBox(); - TextRun tr3 = box3.getTextRun(); - RichTextRun rt3 = tr3.getRichTextRuns()[0]; + HSLFTextBox box3 = new HSLFTextBox(); + HSLFTextParagraph tr3 = box3.getTextParagraph(); + HSLFTextRun rt3 = tr3.getRichTextRuns()[0]; rt3.setFontName("Courier New"); rt3.setFontSize(8); tr3.setText( @@ -408,7 +408,7 @@ public final class ApacheconEU08 { slide.addShape(box3); } - public static void slide10(SlideShow ppt) throws IOException { + public static void slide10(HSLFSlideShow ppt) throws IOException { //bar chart data. The first value is the bar color, the second is the width Object[] def = new Object[]{ Color.yellow, new Integer(100), @@ -417,7 +417,7 @@ public final class ApacheconEU08 { Color.red, new Integer(200), }; - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); HSLFGroupShape group = new HSLFGroupShape(); //define position of the drawing in the slide @@ -445,18 +445,18 @@ public final class ApacheconEU08 { } - public static void slide11(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide11(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.TITLE_TYPE); tr1.setText("HSLF Development Plans"); box1.setAnchor(new Rectangle(36, 21, 648, 90)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.BODY_TYPE); tr2.getRichTextRuns()[0].setFontSize(32); tr2.setText( @@ -465,8 +465,8 @@ public final class ApacheconEU08 { box2.setAnchor(new Rectangle(36, 126, 648, 100)); slide.addShape(box2); - TextBox box3 = new TextBox(); - TextRun tr3 = box3.getTextRun(); + HSLFTextBox box3 = new HSLFTextBox(); + HSLFTextParagraph tr3 = box3.getTextParagraph(); tr3.setRunType(TextHeaderAtom.BODY_TYPE); tr3.getRichTextRuns()[0].setIndentLevel(1); tr3.setText( @@ -474,8 +474,8 @@ public final class ApacheconEU08 { box3.setAnchor(new Rectangle(36, 220, 648, 70)); slide.addShape(box3); - TextBox box4 = new TextBox(); - TextRun tr4 = box4.getTextRun(); + HSLFTextBox box4 = new HSLFTextBox(); + HSLFTextParagraph tr4 = box4.getTextParagraph(); tr4.setRunType(TextHeaderAtom.BODY_TYPE); tr4.getRichTextRuns()[0].setFontSize(32); tr4.setText( @@ -483,8 +483,8 @@ public final class ApacheconEU08 { box4.setAnchor(new Rectangle(36, 290, 648, 90)); slide.addShape(box4); - TextBox box5 = new TextBox(); - TextRun tr5 = box5.getTextRun(); + HSLFTextBox box5 = new HSLFTextBox(); + HSLFTextParagraph tr5 = box5.getTextParagraph(); tr5.setRunType(TextHeaderAtom.BODY_TYPE); tr5.getRichTextRuns()[0].setIndentLevel(1); tr5.setText( @@ -494,18 +494,18 @@ public final class ApacheconEU08 { slide.addShape(box5); } - public static void slide12(SlideShow ppt) throws IOException { - Slide slide = ppt.createSlide(); + public static void slide12(HSLFSlideShow ppt) throws IOException { + HSLFSlide slide = ppt.createSlide(); - TextBox box1 = new TextBox(); - TextRun tr1 = box1.getTextRun(); + HSLFTextBox box1 = new HSLFTextBox(); + HSLFTextParagraph tr1 = box1.getTextParagraph(); tr1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE); tr1.setText("Questions?"); box1.setAnchor(new Rectangle(54, 167, 612, 115)); slide.addShape(box1); - TextBox box2 = new TextBox(); - TextRun tr2 = box2.getTextRun(); + HSLFTextBox box2 = new HSLFTextBox(); + HSLFTextParagraph tr2 = box2.getTextParagraph(); tr2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE); tr2.setText( "http://poi.apache.org/hslf/\r" + diff --git a/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java b/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java index 3a97b61aa0..ed6dd1231d 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java +++ b/src/examples/src/org/apache/poi/hslf/examples/BulletsDemo.java @@ -17,10 +17,10 @@ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.TextBox; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.model.HSLFSlide; +import org.apache.poi.hslf.model.HSLFTextBox; import java.io.FileOutputStream; @@ -34,12 +34,12 @@ public final class BulletsDemo { public static void main(String[] args) throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); - TextBox shape = new TextBox(); - RichTextRun rt = shape.getTextRun().getRichTextRuns()[0]; + HSLFTextBox shape = new HSLFTextBox(); + HSLFTextRun rt = shape.getTextParagraph().getRichTextRuns()[0]; shape.setText( "January\r" + "February\r" + diff --git a/src/examples/src/org/apache/poi/hslf/examples/CreateHyperlink.java b/src/examples/src/org/apache/poi/hslf/examples/CreateHyperlink.java index 0aa8db32de..99c5d7d31f 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/CreateHyperlink.java +++ b/src/examples/src/org/apache/poi/hslf/examples/CreateHyperlink.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hslf.model.*; import java.io.FileOutputStream; @@ -31,14 +31,14 @@ import java.awt.*; public final class CreateHyperlink { public static void main(String[] args) throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slideA = ppt.createSlide(); - Slide slideB = ppt.createSlide(); - Slide slideC = ppt.createSlide(); + HSLFSlide slideA = ppt.createSlide(); + HSLFSlide slideB = ppt.createSlide(); + HSLFSlide slideC = ppt.createSlide(); // link to a URL - TextBox textBox1 = new TextBox(); + HSLFTextBox textBox1 = new HSLFTextBox(); textBox1.setText("Apache POI"); textBox1.setAnchor(new Rectangle(100, 100, 200, 50)); @@ -54,7 +54,7 @@ public final class CreateHyperlink { slideA.addShape(textBox1); // link to another slide - TextBox textBox2 = new TextBox(); + HSLFTextBox textBox2 = new HSLFTextBox(); textBox2.setText("Go to slide #3"); textBox2.setAnchor(new Rectangle(100, 300, 200, 50)); diff --git a/src/examples/src/org/apache/poi/hslf/examples/DataExtraction.java b/src/examples/src/org/apache/poi/hslf/examples/DataExtraction.java index e0f58741e1..d4028d7c67 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/DataExtraction.java +++ b/src/examples/src/org/apache/poi/hslf/examples/DataExtraction.java @@ -41,11 +41,11 @@ public final class DataExtraction { } FileInputStream is = new FileInputStream(args[0]); - SlideShow ppt = new SlideShow(is); + HSLFSlideShow ppt = new HSLFSlideShow(is); is.close(); //extract all sound files embedded in this presentation - SoundData[] sound = ppt.getSoundData(); + HSLFSoundData[] sound = ppt.getSoundData(); for (int i = 0; i < sound.length; i++) { String type = sound[i].getSoundType(); //*.wav String name = sound[i].getSoundName(); //typically file name @@ -58,13 +58,13 @@ public final class DataExtraction { } //extract embedded OLE documents - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { HSLFShape[] shape = slide[i].getShapes(); for (int j = 0; j < shape.length; j++) { if (shape[j] instanceof OLEShape) { OLEShape ole = (OLEShape) shape[j]; - ObjectData data = ole.getObjectData(); + HSLFObjectData data = ole.getObjectData(); String name = ole.getInstanceName(); if ("Worksheet".equals(name)) { @@ -104,29 +104,29 @@ public final class DataExtraction { for (int i = 0; i < slide.length; i++) { HSLFShape[] shape = slide[i].getShapes(); for (int j = 0; j < shape.length; j++) { - if (shape[j] instanceof Picture) { - Picture p = (Picture) shape[j]; - PictureData data = p.getPictureData(); + if (shape[j] instanceof HSLFPictureShape) { + HSLFPictureShape p = (HSLFPictureShape) shape[j]; + HSLFPictureData data = p.getPictureData(); String name = p.getPictureName(); int type = data.getType(); String ext; switch (type) { - case Picture.JPEG: + case HSLFPictureShape.JPEG: ext = ".jpg"; break; - case Picture.PNG: + case HSLFPictureShape.PNG: ext = ".png"; break; - case Picture.WMF: + case HSLFPictureShape.WMF: ext = ".wmf"; break; - case Picture.EMF: + case HSLFPictureShape.EMF: ext = ".emf"; break; - case Picture.PICT: + case HSLFPictureShape.PICT: ext = ".pict"; break; - case Picture.DIB: + case HSLFPictureShape.DIB: ext = ".dib"; break; default: diff --git a/src/examples/src/org/apache/poi/hslf/examples/Graphics2DDemo.java b/src/examples/src/org/apache/poi/hslf/examples/Graphics2DDemo.java index a2f14ac41b..4e678ba64d 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/Graphics2DDemo.java +++ b/src/examples/src/org/apache/poi/hslf/examples/Graphics2DDemo.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hslf.model.*; import java.awt.*; @@ -34,7 +34,7 @@ public final class Graphics2DDemo { * A simple bar chart demo */ public static void main(String[] args) throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); //bar chart data. The first value is the bar color, the second is the width Object[] def = new Object[]{ @@ -44,7 +44,7 @@ public final class Graphics2DDemo { Color.red, new Integer(80), }; - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); HSLFGroupShape group = new HSLFGroupShape(); //define position of the drawing in the slide diff --git a/src/examples/src/org/apache/poi/hslf/examples/HeadersFootersDemo.java b/src/examples/src/org/apache/poi/hslf/examples/HeadersFootersDemo.java index 3ebcecc90f..068d675347 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/HeadersFootersDemo.java +++ b/src/examples/src/org/apache/poi/hslf/examples/HeadersFootersDemo.java @@ -16,9 +16,9 @@ ==================================================================== */ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hslf.model.HeadersFooters; -import org.apache.poi.hslf.model.Slide; +import org.apache.poi.hslf.model.HSLFSlide; import java.io.FileOutputStream; @@ -29,7 +29,7 @@ import java.io.FileOutputStream; */ public class HeadersFootersDemo { public static void main(String[] args) throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); HeadersFooters slideHeaders = ppt.getSlideHeadersFooters(); slideHeaders.setFootersText("Created by POI-HSLF"); @@ -40,7 +40,7 @@ public class HeadersFootersDemo { notesHeaders.setFootersText("My notes footers"); notesHeaders.setHeaderText("My notes header"); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); FileOutputStream out = new FileOutputStream("headers_footers.ppt"); ppt.write(out); diff --git a/src/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java b/src/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java index a90b6a1df0..89dcb636af 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java +++ b/src/examples/src/org/apache/poi/hslf/examples/Hyperlinks.java @@ -17,9 +17,9 @@ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.TextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlide; +import org.apache.poi.hslf.model.HSLFTextParagraph; import org.apache.poi.hslf.model.Hyperlink; import org.apache.poi.hslf.model.HSLFShape; @@ -35,16 +35,16 @@ public final class Hyperlinks { public static void main(String[] args) throws Exception { for (int i = 0; i < args.length; i++) { FileInputStream is = new FileInputStream(args[i]); - SlideShow ppt = new SlideShow(is); + HSLFSlideShow ppt = new HSLFSlideShow(is); is.close(); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int j = 0; j < slide.length; j++) { System.out.println("slide " + slide[j].getSlideNumber()); //read hyperlinks from the slide's text runs System.out.println("reading hyperlinks from the text runs"); - TextRun[] txt = slide[j].getTextRuns(); + HSLFTextParagraph[] txt = slide[j].getTextRuns(); for (int k = 0; k < txt.length; k++) { String text = txt[k].getText(); Hyperlink[] links = txt[k].getHyperlinks(); diff --git a/src/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java b/src/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java index 99037d3264..373f942844 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java +++ b/src/examples/src/org/apache/poi/hslf/examples/PPT2PNG.java @@ -62,14 +62,14 @@ public final class PPT2PNG { } FileInputStream is = new FileInputStream(file); - SlideShow ppt = new SlideShow(is); + HSLFSlideShow ppt = new HSLFSlideShow(is); is.close(); Dimension pgsize = ppt.getPageSize(); int width = (int)(pgsize.width*scale); int height = (int)(pgsize.height*scale); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { if (slidenum != -1 && slidenum != (i+1)) continue; diff --git a/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java b/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java index 571c86a425..765ba3ef49 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java +++ b/src/examples/src/org/apache/poi/hslf/examples/SoundFinder.java @@ -32,10 +32,10 @@ import java.util.List; */ public class SoundFinder { public static void main(String[] args) throws Exception { - SlideShow ppt = new SlideShow(new FileInputStream(args[0])); - SoundData[] sounds = ppt.getSoundData(); + HSLFSlideShow ppt = new HSLFSlideShow(new FileInputStream(args[0])); + HSLFSoundData[] sounds = ppt.getSoundData(); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { HSLFShape[] shape = slide[i].getShapes(); for (int j = 0; j < shape.length; j++) { diff --git a/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java b/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java index 44935c05ac..5dd1edea06 100644 --- a/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java +++ b/src/examples/src/org/apache/poi/hslf/examples/TableDemo.java @@ -17,8 +17,8 @@ package org.apache.poi.hslf.examples; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.usermodel.RichTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; import org.apache.poi.hslf.model.*; import java.awt.*; @@ -43,9 +43,9 @@ public final class TableDemo { {"Total PO History Spend", "$10,172,038"} }; - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); //six rows, two columns Table table1 = new Table(6, 2); @@ -53,7 +53,7 @@ public final class TableDemo { for (int j = 0; j < txt1[i].length; j++) { TableCell cell = table1.getCell(i, j); cell.setText(txt1[i][j]); - RichTextRun rt = cell.getTextRun().getRichTextRuns()[0]; + HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0]; rt.setFontName("Arial"); rt.setFontSize(10); if(i == 0){ @@ -61,8 +61,8 @@ public final class TableDemo { } else { rt.setBold(true); } - cell.setVerticalAlignment(TextBox.AnchorMiddle); - cell.setHorizontalAlignment(TextBox.AlignCenter); + cell.setVerticalAlignment(HSLFTextBox.AnchorMiddle); + cell.setHorizontalAlignment(HSLFTextBox.AlignCenter); } } @@ -92,7 +92,7 @@ public final class TableDemo { for (int j = 0; j < txt2[i].length; j++) { TableCell cell = table2.getCell(i, j); cell.setText(txt2[i][j]); - RichTextRun rt = cell.getTextRun().getRichTextRuns()[0]; + HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0]; rt.setFontSize(10); rt.setFontName("Arial"); if(i == 0){ @@ -100,13 +100,13 @@ public final class TableDemo { rt.setFontColor(Color.white); rt.setBold(true); rt.setFontSize(14); - cell.setHorizontalAlignment(TextBox.AlignCenter); + cell.setHorizontalAlignment(HSLFTextBox.AlignCenter); } else { rt.setBullet(true); rt.setFontSize(12); - cell.setHorizontalAlignment(TextBox.AlignLeft); + cell.setHorizontalAlignment(HSLFTextBox.AlignLeft); } - cell.setVerticalAlignment(TextBox.AnchorMiddle); + cell.setVerticalAlignment(HSLFTextBox.AnchorMiddle); } } table2.setColumnWidth(0, 300); diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmeddedObjects.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmeddedObjects.java index bb6f19d0a5..caf96a84c8 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmeddedObjects.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/EmeddedObjects.java @@ -21,8 +21,8 @@ import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.Entry; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.hwpf.HWPFDocument; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import java.io.FileInputStream; import java.util.Iterator; @@ -47,7 +47,7 @@ public class EmeddedObjects { //System.out.println(entry.getName() + ": " + embeddedWordDocument.getRange().text()); } else if (oleName.equals("Presentation")) { DirectoryNode dn = (DirectoryNode) obj.getDirectory(); - SlideShow embeddedPowerPointDocument = new SlideShow(new HSLFSlideShow(dn)); + HSLFSlideShow embeddedPowerPointDocument = new HSLFSlideShow(new HSLFSlideShowImpl(dn)); //System.out.println(entry.getName() + ": " + embeddedPowerPointDocument.getSlides().length); } else { if(obj.hasDirectoryEntry()){ diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java index b7e08fc6f1..5437b5dea4 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/DataExtraction.java @@ -76,7 +76,6 @@ public final class DataExtraction { Dimension pageSize = ppt.getPageSize(); // size of the canvas in points for(XSLFSlide slide : ppt.getSlides()) { for(XSLFShape shape : slide){ - Rectangle2D anchor = shape.getAnchor(); // position on the canvas if(shape instanceof XSLFTextShape) { XSLFTextShape txShape = (XSLFTextShape)shape; System.out.println(txShape.getText()); diff --git a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java index 2e810e1d45..926bc0d4bf 100644 --- a/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java +++ b/src/examples/src/org/apache/poi/xslf/usermodel/Tutorial4.java @@ -19,12 +19,12 @@ package org.apache.poi.xslf.usermodel; -import java.awt.*; +import java.awt.Color; import java.awt.geom.Rectangle2D; import java.io.FileOutputStream; import java.io.IOException; -import org.apache.poi.sl.usermodel.TextAlign; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; /** * PPTX Tables diff --git a/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java b/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java index b50e959460..ea3a5b28e1 100644 --- a/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java +++ b/src/examples/src/org/apache/poi/xssf/usermodel/examples/EmbeddedObjects.java @@ -20,7 +20,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.xslf.XSLFSlideShow; import org.apache.poi.hssf.usermodel.HSSFWorkbook; @@ -54,7 +54,7 @@ public class EmbeddedObjects { } // PowerPoint Document - binary file format else if (contentType.equals("application/vnd.ms-powerpoint")) { - HSLFSlideShow slideShow = new HSLFSlideShow(pPart.getInputStream()); + HSLFSlideShowImpl slideShow = new HSLFSlideShowImpl(pPart.getInputStream()); } // PowerPoint Document - OpenXML file format else if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) { diff --git a/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java b/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java index 51e54f6eb2..6b2ee5f09e 100644 --- a/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java +++ b/src/integrationtest/org/apache/poi/stress/HSLFFileHandler.java @@ -22,14 +22,14 @@ import static org.junit.Assert.assertTrue; import java.io.FileInputStream; import java.io.InputStream; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.Record; import org.junit.Test; public class HSLFFileHandler extends POIFSFileHandler { @Override public void handleFile(InputStream stream) throws Exception { - HSLFSlideShow slide = new HSLFSlideShow(stream); + HSLFSlideShowImpl slide = new HSLFSlideShowImpl(stream); assertNotNull(slide.getCurrentUserAtom()); assertNotNull(slide.getEmbeddedObjects()); assertNotNull(slide.getUnderlyingBytes()); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java index 57e96f8ee5..9a58a5128a 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java @@ -19,25 +19,19 @@ package org.apache.poi.xslf.usermodel; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; -import org.apache.poi.openxml4j.opc.PackagePart; -import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.openxml4j.opc.TargetMode; -import org.apache.poi.sl.usermodel.*; +import org.apache.poi.openxml4j.opc.*; +import org.apache.poi.sl.usermodel.PlaceableShape; +import org.apache.poi.sl.usermodel.ShapeGroup; import org.apache.poi.util.Beta; import org.apache.poi.util.Units; import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.drawingml.x2006.main.*; -import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShape; -import org.openxmlformats.schemas.presentationml.x2006.main.CTGroupShapeNonVisual; -import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; +import org.openxmlformats.schemas.presentationml.x2006.main.*; /** * Represents a group shape that consists of many shapes grouped together. @@ -45,7 +39,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape; * @author Yegor Kozlov */ @Beta -public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, PlaceableShape { +public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, ShapeGroup { private final List _shapes; private final CTGroupShapeProperties _grpSpPr; private XSLFDrawing _drawing; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java index 62f9cc4ad6..a953e2013e 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotes.java @@ -17,20 +17,19 @@ package org.apache.poi.xslf.usermodel; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.sl.usermodel.Notes; -import org.apache.poi.sl.usermodel.TextRun; import org.apache.poi.util.Beta; import org.apache.xmlbeans.XmlException; -import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData; -import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesSlide; -import org.openxmlformats.schemas.presentationml.x2006.main.NotesDocument; +import org.openxmlformats.schemas.presentationml.x2006.main.*; @Beta -public final class XSLFNotes extends XSLFSheet implements Notes { +public final class XSLFNotes extends XSLFSheet implements Notes { private CTNotesSlide _notes; /** @@ -91,19 +90,15 @@ public final class XSLFNotes extends XSLFSheet implements Notes { return null; } - public TextRun getTextRun() { + @Override + public List getTextParagraphs() { + List tp = new ArrayList(); for (XSLFShape sh : super.getShapes()) { if (sh instanceof XSLFTextShape) { XSLFTextShape txt = (XSLFTextShape)sh; - for (XSLFTextParagraph p : txt.getTextParagraphs()) { - for (XSLFTextRun r : p.getTextRuns()) { - return r; - } - } + tp.addAll(txt.getTextParagraphs()); } } - return null; + return tp; } - - } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java index c5de537677..aeea5cc521 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFNotesMaster.java @@ -47,7 +47,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; * @author Yegor Kozlov */ @Beta - public class XSLFNotesMaster extends XSLFSheet implements MasterSheet { + public class XSLFNotesMaster extends XSLFSheet implements MasterSheet { private CTNotesMaster _slide; private XSLFTheme _theme; @@ -94,7 +94,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.NotesMasterDocument; } @Override - public MasterSheet getMasterSheet() { + public MasterSheet getMasterSheet() { return null; } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index d0f75e0535..b815e00d42 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -19,7 +19,6 @@ package org.apache.poi.xslf.usermodel; -import java.awt.Graphics2D; import java.awt.Insets; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; @@ -32,27 +31,18 @@ import javax.xml.namespace.QName; import org.apache.poi.POIXMLException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.sl.usermodel.PictureShape; import org.apache.poi.util.Beta; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip; -import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtension; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOfficeArtExtensionList; -import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D; -import org.openxmlformats.schemas.drawingml.x2006.main.CTRelativeRect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType; -import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; -import org.openxmlformats.schemas.presentationml.x2006.main.CTPictureNonVisual; +import org.openxmlformats.schemas.drawingml.x2006.main.*; +import org.openxmlformats.schemas.presentationml.x2006.main.*; /** * Represents a picture shape */ @Beta -public class XSLFPictureShape extends XSLFSimpleShape { +public class XSLFPictureShape extends XSLFSimpleShape implements PictureShape { private XSLFPictureData _data; /*package*/ XSLFPictureShape(CTPicture shape, XSLFSheet sheet) { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java index 9004a6be5f..0b0e4f0aad 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java @@ -88,7 +88,7 @@ public class XSLFShadow extends XSLFShape implements Shadow { */ public Color getFillColor() { SolidPaint ps = getFillStyle(); - if (ps == TRANSPARENT_PAINT) return null; + if (ps == PaintStyle.TRANSPARENT_PAINT) return null; Color col = DrawPaint.applyColorTransform(ps.getSolidColor()); return col; } @@ -97,7 +97,7 @@ public class XSLFShadow extends XSLFShape implements Shadow { public SolidPaint getFillStyle() { XSLFTheme theme = getSheet().getTheme(); CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); - if(ct == null) return TRANSPARENT_PAINT; + if(ct == null) return PaintStyle.TRANSPARENT_PAINT; CTSchemeColor phClr = ct.getSchemeClr(); final XSLFColor xc = new XSLFColor(ct, theme, phClr); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 5634838302..0f2ba25834 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -19,7 +19,6 @@ package org.apache.poi.xslf.usermodel; -import java.awt.Color; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; @@ -28,7 +27,6 @@ import java.util.Comparator; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.usermodel.*; import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; @@ -56,19 +54,6 @@ public abstract class XSLFShape implements Shape { private CTNonVisualDrawingProps _nvPr; private CTPlaceholder _ph; - protected static final SolidPaint TRANSPARENT_PAINT = new SolidPaint() { - public ColorStyle getSolidColor() { - return new ColorStyle(){ - public Color getColor() { return DrawPaint.NO_PAINT; } - public int getAlpha() { return -1; } - public int getLumOff() { return -1; } - public int getLumMod() { return -1; } - public int getShade() { return -1; } - public int getTint() { return -1; } - }; - } - }; - protected XSLFShape(XmlObject shape, XSLFSheet sheet) { _shape = shape; _sheet = sheet; @@ -146,7 +131,7 @@ public abstract class XSLFShape implements Shape { try { pr = shape.getSpPr(); if (((CTShapeProperties)pr).isSetNoFill()) { - setValue(TRANSPARENT_PAINT); + setValue(PaintStyle.TRANSPARENT_PAINT); return true; } } catch (IllegalStateException e) {} @@ -158,7 +143,7 @@ public abstract class XSLFShape implements Shape { pr = shape.getGrpSpPr(); } if (pr == null) { - setValue(TRANSPARENT_PAINT); + setValue(PaintStyle.TRANSPARENT_PAINT); return true; } @@ -190,7 +175,7 @@ public abstract class XSLFShape implements Shape { fillRef = getBgRef(); } if (fillRef == null) { - return TRANSPARENT_PAINT; + return PaintStyle.TRANSPARENT_PAINT; } // The idx attribute refers to the index of a fill style or @@ -213,21 +198,21 @@ public abstract class XSLFShape implements Shape { paint = selectPaint(fillProps, phClr, sheet.getPackagePart()); } - return paint == null ? TRANSPARENT_PAINT : paint; + return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint; } protected CTBackgroundProperties getBgPr() { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:bgPr"; + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' p:bgPr"; return selectProperty(CTBackgroundProperties.class, xquery); } protected CTStyleMatrixReference getBgRef() { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:bgRef"; + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' p:bgRef"; return selectProperty(CTStyleMatrixReference.class, xquery); } protected CTGroupShapeProperties getGrpSpPr() { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:grpSpPr"; + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' p:grpSpPr"; return selectProperty(CTGroupShapeProperties.class, xquery); } @@ -241,7 +226,7 @@ public abstract class XSLFShape implements Shape { protected CTShapeProperties getSpPr() { if (_spPr == null) { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:spPr"; + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' p:spPr"; _spPr = selectProperty(CTShapeProperties.class, xquery); } if (_spPr == null) { @@ -252,7 +237,7 @@ public abstract class XSLFShape implements Shape { protected CTShapeStyle getSpStyle() { if (_spStyle == null) { - String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:style"; + String xquery = "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' p:style"; _spStyle = selectProperty(CTShapeStyle.class, xquery); } return _spStyle; @@ -348,7 +333,7 @@ public abstract class XSLFShape implements Shape { paint = selectPaint(obj, phClr, pp); if(paint != null) break; } - return paint == null ? TRANSPARENT_PAINT : paint; + return paint == null ? PaintStyle.TRANSPARENT_PAINT : paint; } /** @@ -373,7 +358,7 @@ public abstract class XSLFShape implements Shape { */ protected PaintStyle selectPaint(XmlObject obj, final CTSchemeColor phClr, final PackagePart parentPart) { if (obj instanceof CTNoFillProperties) { - return TRANSPARENT_PAINT; + return PaintStyle.TRANSPARENT_PAINT; } else if (obj instanceof CTSolidColorFillProperties) { return selectPaint((CTSolidColorFillProperties)obj, phClr, parentPart); } else if (obj instanceof CTBlipFillProperties) { diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java index 163d8a65aa..38dea1b462 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java @@ -37,7 +37,7 @@ import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelations import org.openxmlformats.schemas.presentationml.x2006.main.*; @Beta -public abstract class XSLFSheet extends POIXMLDocumentPart implements XSLFShapeContainer, Sheet { +public abstract class XSLFSheet extends POIXMLDocumentPart implements XSLFShapeContainer, Sheet { private XSLFCommonSlideData _commonSlideData; private XSLFDrawing _drawing; private List _shapes; @@ -516,25 +516,26 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements XSLFShapeC * Import a package part into this sheet. */ PackagePart importPart(PackageRelationship srcRel, PackagePart srcPafrt) { - - OPCPackage pkg = getPackagePart().getPackage(); - if(!pkg.containPart(srcPafrt.getPartName())){ - PackageRelationship rel = getPackagePart().addRelationship( - srcPafrt.getPartName(), TargetMode.INTERNAL, srcRel.getRelationshipType()); - - PackagePart part = pkg.createPart(srcPafrt.getPartName(), srcPafrt.getContentType()); - OutputStream out = part.getOutputStream(); - try { - InputStream is = srcPafrt.getInputStream(); - IOUtils.copy(is, out); - out.close(); - } catch (IOException e){ - throw new POIXMLException(e); - } - return part; - } else { + PackagePart destPP = getPackagePart(); + PackagePartName srcPPName = srcPafrt.getPartName(); + + OPCPackage pkg = destPP.getPackage(); + if(pkg.containPart(srcPPName)){ // already exists - return pkg.getPart(srcPafrt.getPartName()); + return pkg.getPart(srcPPName); + } + + destPP.addRelationship(srcPPName, TargetMode.INTERNAL, srcRel.getRelationshipType()); + + PackagePart part = pkg.createPart(srcPPName, srcPafrt.getContentType()); + OutputStream out = part.getOutputStream(); + try { + InputStream is = srcPafrt.getInputStream(); + IOUtils.copy(is, out); + out.close(); + } catch (IOException e){ + throw new POIXMLException(e); } + return part; } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index ffe0fc823d..fb97180605 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -19,19 +19,21 @@ package org.apache.poi.xslf.usermodel; +import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT; + import java.awt.Color; import java.awt.geom.Rectangle2D; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; -import org.apache.poi.sl.draw.DrawPaint; import org.apache.poi.sl.draw.geom.*; import org.apache.poi.sl.usermodel.*; import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound; import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; import org.apache.poi.util.Beta; import org.apache.poi.util.Units; @@ -208,8 +210,7 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { PaintStyle ps = getLinePaint(); if (ps == null || ps == TRANSPARENT_PAINT) return null; if (ps instanceof SolidPaint) { - Color col = ((SolidPaint)ps).getSolidColor().getColor(); - return (col == DrawPaint.NO_PAINT) ? null : col; + return ((SolidPaint)ps).getSolidColor().getColor(); } return null; } @@ -273,7 +274,6 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { } /** - * * @return line width in points. 0 means no line. */ public double getLineWidth() { @@ -310,6 +310,54 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { return lineWidth; } + /** + * @return the line compound + */ + public LineCompound getLineCompound() { + PropertyFetcher fetcher = new PropertyFetcher() { + public boolean fetch(XSLFShape shape) { + CTShapeProperties spPr = shape.getSpPr(); + CTLineProperties ln = spPr.getLn(); + if (ln != null) { + STCompoundLine.Enum stCmpd = ln.getCmpd(); + if (stCmpd != null) { + setValue(stCmpd.intValue()); + return true; + } + } + return false; + } + }; + fetchShapeProperty(fetcher); + + Integer cmpd = fetcher.getValue(); + if (cmpd == null) { + CTLineProperties defaultLn = getDefaultLineProperties(); + if (defaultLn != null) { + STCompoundLine.Enum stCmpd = defaultLn.getCmpd(); + if (stCmpd != null) { + cmpd = stCmpd.intValue(); + } + } + } + + if (cmpd == null) return null; + + switch (cmpd) { + default: + case STCompoundLine.INT_SNG: + return LineCompound.SINGLE; + case STCompoundLine.INT_DBL: + return LineCompound.DOUBLE; + case STCompoundLine.INT_THICK_THIN: + return LineCompound.THICK_THIN; + case STCompoundLine.INT_THIN_THICK: + return LineCompound.THIN_THICK; + case STCompoundLine.INT_TRI: + return LineCompound.TRIPLE; + } + } + /** * * @param dash a preset line dashing scheme to stroke thr shape outline @@ -453,8 +501,7 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { PaintStyle ps = getFillPaint(); if (ps == null || ps == TRANSPARENT_PAINT) return null; if (ps instanceof SolidPaint) { - Color col = ((SolidPaint)ps).getSolidColor().getColor(); - return (col == DrawPaint.NO_PAINT) ? null : col; + return ((SolidPaint)ps).getSolidColor().getColor(); } return null; } @@ -769,6 +816,10 @@ public abstract class XSLFSimpleShape extends XSLFShape implements SimpleShape { public double getLineWidth() { return XSLFSimpleShape.this.getLineWidth(); } + + public LineCompound getLineCompound() { + return XSLFSimpleShape.this.getLineCompound(); + } }; } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java index 795daa30b5..ee62ee9d79 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java @@ -29,7 +29,7 @@ import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.openxmlformats.schemas.presentationml.x2006.main.*; @Beta -public final class XSLFSlide extends XSLFSheet implements Slide { +public final class XSLFSlide extends XSLFSheet implements Slide { private final CTSlide _slide; private XSLFSlideLayout _layout; private XSLFComments _comments; @@ -245,7 +245,7 @@ public final class XSLFSlide extends XSLFSheet implements Slide { throw new UnsupportedOperationException(); } - public void setNotes(Notes notes) { + public void setNotes(Notes notes) { // TODO Auto-generated method stub } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java index bd6c38ca46..65487bd45b 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideLayout.java @@ -31,7 +31,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.SldLayoutDocument; import java.io.IOException; @Beta -public class XSLFSlideLayout extends XSLFSheet implements MasterSheet { +public class XSLFSlideLayout extends XSLFSheet implements MasterSheet { private CTSlideLayout _layout; private XSLFSlideMaster _master; diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java index 0b64306fd1..830a531a24 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlideMaster.java @@ -54,7 +54,7 @@ import java.util.Map; * @author Yegor Kozlov */ @Beta - public class XSLFSlideMaster extends XSLFSheet implements MasterSheet { + public class XSLFSlideMaster extends XSLFSheet implements MasterSheet { private CTSlideMaster _slide; private Map _layouts; private XSLFTheme _theme; @@ -83,7 +83,7 @@ import java.util.Map; } @Override - public MasterSheet getMasterSheet() { + public MasterSheet getMasterSheet() { return null; } diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java index e3dad561b6..5b7109059f 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFAutoShape.java @@ -18,9 +18,10 @@ package org.apache.poi.xslf.usermodel; import junit.framework.TestCase; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.sl.usermodel.TextAlign; -import org.apache.poi.sl.usermodel.VerticalAlignment; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.sl.usermodel.TextShape.TextAutofit; +import org.apache.poi.sl.usermodel.TextShape.TextDirection; import org.apache.poi.util.Units; import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType; import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType; diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java index ae7de8d5c0..0dc9c4d6f7 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java @@ -16,14 +16,17 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; +import java.awt.Color; +import java.awt.Rectangle; + import junit.framework.TestCase; -import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape; +import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; +import org.apache.poi.sl.usermodel.*; import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; -import java.awt.*; - /** * @author Yegor Kozlov */ @@ -40,70 +43,70 @@ public class TestXSLFConnectorShape extends TestCase { assertFalse(shape.getSpPr().getLn().isSetTailEnd()); // line decorations - assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration()); - assertEquals(LineDecoration.NONE, shape.getLineTailDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); shape.setLineHeadDecoration(null); shape.setLineTailDecoration(null); - assertEquals(LineDecoration.NONE, shape.getLineHeadDecoration()); - assertEquals(LineDecoration.NONE, shape.getLineTailDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.NONE, shape.getLineTailDecoration()); assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetType()); assertFalse(shape.getSpPr().getLn().getTailEnd().isSetType()); - shape.setLineHeadDecoration(LineDecoration.ARROW); - shape.setLineTailDecoration(LineDecoration.DIAMOND); - assertEquals(LineDecoration.ARROW, shape.getLineHeadDecoration()); - assertEquals(LineDecoration.DIAMOND, shape.getLineTailDecoration()); + shape.setLineHeadDecoration(DecorationShape.ARROW); + shape.setLineTailDecoration(DecorationShape.DIAMOND); + assertEquals(DecorationShape.ARROW, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.DIAMOND, shape.getLineTailDecoration()); assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getHeadEnd().getType()); assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getTailEnd().getType()); - shape.setLineHeadDecoration(LineDecoration.DIAMOND); - shape.setLineTailDecoration(LineDecoration.ARROW); - assertEquals(LineDecoration.DIAMOND, shape.getLineHeadDecoration()); - assertEquals(LineDecoration.ARROW, shape.getLineTailDecoration()); + shape.setLineHeadDecoration(DecorationShape.DIAMOND); + shape.setLineTailDecoration(DecorationShape.ARROW); + assertEquals(DecorationShape.DIAMOND, shape.getLineHeadDecoration()); + assertEquals(DecorationShape.ARROW, shape.getLineTailDecoration()); assertEquals(STLineEndType.DIAMOND, shape.getSpPr().getLn().getHeadEnd().getType()); assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getTailEnd().getType()); // line end width - assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); - assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); shape.setLineHeadWidth(null); shape.setLineHeadWidth(null); - assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); - assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetW()); assertFalse(shape.getSpPr().getLn().getTailEnd().isSetW()); - shape.setLineHeadWidth(LineEndWidth.LARGE); - shape.setLineTailWidth(LineEndWidth.MEDIUM); - assertEquals(LineEndWidth.LARGE, shape.getLineHeadWidth()); - assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); + shape.setLineHeadWidth(DecorationSize.LARGE); + shape.setLineTailWidth(DecorationSize.MEDIUM); + assertEquals(DecorationSize.LARGE, shape.getLineHeadWidth()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailWidth()); assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getHeadEnd().getW()); assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getTailEnd().getW()); - shape.setLineHeadWidth(LineEndWidth.MEDIUM); - shape.setLineTailWidth(LineEndWidth.LARGE); - assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); - assertEquals(LineEndWidth.LARGE, shape.getLineTailWidth()); + shape.setLineHeadWidth(DecorationSize.MEDIUM); + shape.setLineTailWidth(DecorationSize.LARGE); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadWidth()); + assertEquals(DecorationSize.LARGE, shape.getLineTailWidth()); assertEquals(STLineEndWidth.MED, shape.getSpPr().getLn().getHeadEnd().getW()); assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getTailEnd().getW()); // line end length - assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); - assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); shape.setLineHeadLength(null); shape.setLineTailLength(null); - assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); - assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetLen()); assertFalse(shape.getSpPr().getLn().getTailEnd().isSetLen()); - shape.setLineHeadLength(LineEndLength.LARGE); - shape.setLineTailLength(LineEndLength.MEDIUM); - assertEquals(LineEndLength.LARGE, shape.getLineHeadLength()); - assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); + shape.setLineHeadLength(DecorationSize.LARGE); + shape.setLineTailLength(DecorationSize.MEDIUM); + assertEquals(DecorationSize.LARGE, shape.getLineHeadLength()); + assertEquals(DecorationSize.MEDIUM, shape.getLineTailLength()); assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getHeadEnd().getLen()); assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getTailEnd().getLen()); - shape.setLineHeadLength(LineEndLength.MEDIUM); - shape.setLineTailLength(LineEndLength.LARGE); - assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); - assertEquals(LineEndLength.LARGE, shape.getLineTailLength()); + shape.setLineHeadLength(DecorationSize.MEDIUM); + shape.setLineTailLength(DecorationSize.LARGE); + assertEquals(DecorationSize.MEDIUM, shape.getLineHeadLength()); + assertEquals(DecorationSize.LARGE, shape.getLineTailLength()); assertEquals(STLineEndLength.MED, shape.getSpPr().getLn().getHeadEnd().getLen()); assertEquals(STLineEndLength.LG, shape.getSpPr().getLn().getTailEnd().getLen()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java index 2153ceb26f..b3a5fc211e 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSimpleShape.java @@ -20,17 +20,11 @@ import java.awt.Color; import junit.framework.TestCase; -import org.apache.poi.sl.usermodel.LineCap; -import org.apache.poi.sl.usermodel.LineDash; +import org.apache.poi.sl.usermodel.StrokeStyle.LineCap; +import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; import org.apache.poi.util.Units; import org.apache.poi.xslf.XSLFTestDataSamples; -import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem; -import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleList; -import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect; -import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor; -import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix; -import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap; -import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal; +import org.openxmlformats.schemas.drawingml.x2006.main.*; /** * @author Yegor Kozlov diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java index 505703bcaa..80a52fd2cc 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTable.java @@ -20,6 +20,7 @@ import junit.framework.TestCase; import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.xslf.XSLFTestDataSamples; +import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell; import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; import java.awt.Color; @@ -99,10 +100,11 @@ public class TestXSLFTable extends TestCase { XSLFTableCell cell0 = row0.addCell(); assertNotNull(cell0.getXmlObject()); // by default table cell has no borders - assertTrue(cell0.getXmlObject().getTcPr().getLnB().isSetNoFill()); - assertTrue(cell0.getXmlObject().getTcPr().getLnT().isSetNoFill()); - assertTrue(cell0.getXmlObject().getTcPr().getLnL().isSetNoFill()); - assertTrue(cell0.getXmlObject().getTcPr().getLnR().isSetNoFill()); + CTTableCell tc = (CTTableCell)cell0.getXmlObject(); + assertTrue(tc.getTcPr().getLnB().isSetNoFill()); + assertTrue(tc.getTcPr().getLnT().isSetNoFill()); + assertTrue(tc.getTcPr().getLnL().isSetNoFill()); + assertTrue(tc.getTcPr().getLnR().isSetNoFill()); assertSame(cell0, row0.getCells().get(0)); assertEquals(1, tbl.getNumberOfColumns()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java index 45bc30286e..fb906ed3a1 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextParagraph.java @@ -16,25 +16,46 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; -import junit.framework.TestCase; - -import org.apache.poi.sl.draw.TextFragment; -import org.apache.poi.sl.usermodel.TextAlign; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; -import org.apache.poi.xslf.XSLFTestDataSamples; +import static org.junit.Assert.*; import java.awt.*; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.List; +import org.apache.poi.sl.draw.DrawTextFragment; +import org.apache.poi.sl.draw.DrawTextParagraph; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; +import org.apache.poi.xslf.XSLFTestDataSamples; +import org.junit.Test; + /** * @author Yegor Kozlov */ -public class TestXSLFTextParagraph extends TestCase { +public class TestXSLFTextParagraph { private static POILogger _logger = POILogFactory.getLogger(XSLFTextParagraph.class); + static class DrawTextParagraphProxy extends DrawTextParagraph { + DrawTextParagraphProxy(XSLFTextParagraph p) { + super(p); + } + + public void breakText(Graphics2D graphics) { + super.breakText(graphics); + } + + public double getWrappingWidth(boolean firstLine, Graphics2D graphics) { + return super.getWrappingWidth(firstLine, graphics); + } + + public List getLines() { + return lines; + } + } + + @Test public void testWrappingWidth() throws Exception { XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); @@ -49,45 +70,47 @@ public class TestXSLFTextParagraph extends TestCase { Rectangle2D anchor = new Rectangle(50, 50, 300, 200); sh.setAnchor(anchor); + + DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); double leftInset = sh.getLeftInset(); double rightInset = sh.getRightInset(); - assertEquals(7.2, leftInset); - assertEquals(7.2, rightInset); + assertEquals(7.2, leftInset, 0); + assertEquals(7.2, rightInset, 0); double leftMargin = p.getLeftMargin(); - assertEquals(0.0, leftMargin); + assertEquals(0.0, leftMargin, 0); double indent = p.getIndent(); - assertEquals(0.0, indent); // default + assertEquals(0.0, indent, 0); // default double expectedWidth; // Case 1: bullet=false, leftMargin=0, indent=0. expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(285.6, expectedWidth); // 300 - 7.2 - 7.2 - 0 - assertEquals(expectedWidth, p.getWrappingWidth(true, null)); - assertEquals(expectedWidth, p.getWrappingWidth(false, null)); + assertEquals(285.6, expectedWidth, 0); // 300 - 7.2 - 7.2 - 0 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); p.setLeftMargin(36); // 0.5" leftMargin = p.getLeftMargin(); - assertEquals(36.0, leftMargin); + assertEquals(36.0, leftMargin, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; assertEquals(249.6, expectedWidth, 1E-5); // 300 - 7.2 - 7.2 - 36 - assertEquals(expectedWidth, p.getWrappingWidth(true, null)); - assertEquals(expectedWidth, p.getWrappingWidth(false, null)); + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); // increase insets, the wrapping width should get smaller sh.setLeftInset(10); sh.setRightInset(10); leftInset = sh.getLeftInset(); rightInset = sh.getRightInset(); - assertEquals(10.0, leftInset); - assertEquals(10.0, rightInset); + assertEquals(10.0, leftInset, 0); + assertEquals(10.0, rightInset, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, p.getWrappingWidth(true, null)); - assertEquals(expectedWidth, p.getWrappingWidth(false, null)); + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); // set a positive indent of a 0.5 inch. This means "First Line" indentation: // |<--- indent -->|Here goes first line of the text @@ -95,34 +118,35 @@ public class TestXSLFTextParagraph extends TestCase { p.setIndent(36.0); // 0.5" indent = p.getIndent(); - assertEquals(36.0, indent); + assertEquals(36.0, indent, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin - indent; - assertEquals(208.0, expectedWidth); // 300 - 10 - 10 - 36 - 6.4 - assertEquals(expectedWidth, p.getWrappingWidth(true, null)); // first line is indented + assertEquals(208.0, expectedWidth, 0); // 300 - 10 - 10 - 36 - 6.4 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is indented // other lines are not indented expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, p.getWrappingWidth(false, null)); + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); // set a negative indent of a 1 inch. This means "Hanging" indentation: // Here goes first line of the text // |<--- indent -->|Here go other lines (second and subsequent) p.setIndent(-72.0); // 1" indent = p.getIndent(); - assertEquals(-72.0, indent); + assertEquals(-72.0, indent, 0); expectedWidth = anchor.getWidth() - leftInset - rightInset; - assertEquals(280.0, expectedWidth); // 300 - 10 - 10 - assertEquals(expectedWidth, p.getWrappingWidth(true, null)); // first line is NOT indented + assertEquals(280.0, expectedWidth, 0); // 300 - 10 - 10 + assertEquals(expectedWidth, dtp.getWrappingWidth(true, null), 0); // first line is NOT indented // other lines are indented by leftMargin (the value of indent is not used) expectedWidth = anchor.getWidth() - leftInset - rightInset - leftMargin; - assertEquals(244.0, expectedWidth); // 300 - 10 - 10 - 36 - assertEquals(expectedWidth, p.getWrappingWidth(false, null)); + assertEquals(244.0, expectedWidth, 0); // 300 - 10 - 10 - 36 + assertEquals(expectedWidth, dtp.getWrappingWidth(false, null), 0); } /** * test breaking test into lines. * This test requires that the Arial font is available and will run only on windows */ + @Test public void testBreakLines(){ String os = System.getProperty("os.name"); if(os == null || !os.contains("Windows")) { @@ -144,44 +168,52 @@ public class TestXSLFTextParagraph extends TestCase { "residing within the corresponding paragraph."); sh.setAnchor(new Rectangle(50, 50, 300, 200)); + DrawTextParagraphProxy dtp = new DrawTextParagraphProxy(p); BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); - List lines; - lines = p.breakText(graphics); + List lines; + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(4, lines.size()); // descrease the shape width from 300 pt to 100 pt sh.setAnchor(new Rectangle(50, 50, 100, 200)); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(12, lines.size()); // descrease the shape width from 300 pt to 100 pt sh.setAnchor(new Rectangle(50, 50, 600, 200)); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(2, lines.size()); // set left and right margins to 200pt. This leaves 200pt for wrapping text sh.setLeftInset(200); sh.setRightInset(200); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(5, lines.size()); r.setText("Apache POI"); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(1, lines.size()); assertEquals("Apache POI", lines.get(0).getString()); r.setText("Apache\nPOI"); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(2, lines.size()); assertEquals("Apache", lines.get(0).getString()); assertEquals("POI", lines.get(1).getString()); // trailing newlines are ignored r.setText("Apache\nPOI\n"); - lines = p.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(2, lines.size()); assertEquals("Apache", lines.get(0).getString()); assertEquals("POI", lines.get(1).getString()); @@ -197,7 +229,8 @@ public class TestXSLFTextParagraph extends TestCase { r3.setFontFamily("serif"); // this should always be available r3.setFontSize(10); r3.setText("POI"); - lines = p2.breakText(graphics); + dtp.breakText(graphics); + lines = dtp.getLines(); assertEquals(2, lines.size()); assertEquals("Apache", lines.get(0).getString()); assertEquals("POI", lines.get(1).getString()); @@ -206,6 +239,7 @@ public class TestXSLFTextParagraph extends TestCase { } + @Test public void testThemeInheritance(){ XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx"); XSLFShape[] shapes = ppt.getSlides()[0].getShapes(); @@ -220,6 +254,7 @@ public class TestXSLFTextParagraph extends TestCase { assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign()); } + @Test public void testParagraphProperties(){ XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); @@ -242,25 +277,25 @@ public class TestXSLFTextParagraph extends TestCase { p.setBulletFontColor(Color.red); assertEquals(Color.red, p.getBulletFontColor()); - assertEquals(100.0, p.getBulletFontSize()); + assertEquals(100.0, p.getBulletFontSize(), 0); p.setBulletFontSize(200.); - assertEquals(200., p.getBulletFontSize()); + assertEquals(200., p.getBulletFontSize(), 0); p.setBulletFontSize(-20.); - assertEquals(-20.0, p.getBulletFontSize()); + assertEquals(-20.0, p.getBulletFontSize(), 0); - assertEquals(72.0, p.getDefaultTabSize()); + assertEquals(72.0, p.getDefaultTabSize(), 0); - assertEquals(0.0, p.getIndent()); + assertEquals(0.0, p.getIndent(), 0); p.setIndent(72.0); - assertEquals(72.0, p.getIndent()); + assertEquals(72.0, p.getIndent(), 0); p.setIndent(-1.0); // the value of -1.0 resets to the defaults - assertEquals(0.0, p.getIndent()); + assertEquals(0.0, p.getIndent(), 0); - assertEquals(0.0, p.getLeftMargin()); + assertEquals(0.0, p.getLeftMargin(), 0); p.setLeftMargin(72.0); - assertEquals(72.0, p.getLeftMargin()); + assertEquals(72.0, p.getLeftMargin(), 0); p.setLeftMargin(-1.0); // the value of -1.0 resets to the defaults - assertEquals(0.0, p.getLeftMargin()); + assertEquals(0.0, p.getLeftMargin(), 0); assertEquals(0, p.getLevel()); p.setLevel(1); @@ -268,23 +303,23 @@ public class TestXSLFTextParagraph extends TestCase { p.setLevel(2); assertEquals(2, p.getLevel()); - assertEquals(100., p.getLineSpacing()); + assertEquals(100., p.getLineSpacing(), 0); p.setLineSpacing(200.); - assertEquals(200.0, p.getLineSpacing()); + assertEquals(200.0, p.getLineSpacing(), 0); p.setLineSpacing(-15.); - assertEquals(-15.0, p.getLineSpacing()); + assertEquals(-15.0, p.getLineSpacing(), 0); - assertEquals(0., p.getSpaceAfter()); + assertEquals(0., p.getSpaceAfter(), 0); p.setSpaceAfter(200.); - assertEquals(200.0, p.getSpaceAfter()); + assertEquals(200.0, p.getSpaceAfter(), 0); p.setSpaceAfter(-15.); - assertEquals(-15.0, p.getSpaceAfter()); + assertEquals(-15.0, p.getSpaceAfter(), 0); - assertEquals(0., p.getSpaceBefore()); + assertEquals(0., p.getSpaceBefore(), 0); p.setSpaceBefore(200.); - assertEquals(200.0, p.getSpaceBefore()); + assertEquals(200.0, p.getSpaceBefore(), 0); p.setSpaceBefore(-15.); - assertEquals(-15.0, p.getSpaceBefore()); + assertEquals(-15.0, p.getSpaceBefore(), 0); assertEquals(TextAlign.LEFT, p.getTextAlign()); p.setTextAlign(TextAlign.RIGHT); @@ -296,15 +331,16 @@ public class TestXSLFTextParagraph extends TestCase { p.setBulletAutoNumber(ListAutoNumber.ALPHA_LC_PARENT_BOTH, 1); double tabStop = p.getTabStop(0); - assertEquals(0.0, tabStop); + assertEquals(0.0, tabStop, 0); p.addTabStop(100.); - assertEquals(100., p.getTabStop(0)); + assertEquals(100., p.getTabStop(0), 0); - assertEquals(72.0, p.getDefaultTabSize()); + assertEquals(72.0, p.getDefaultTabSize(), 0); } + @Test public void testLineBreak(){ XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); @@ -316,12 +352,12 @@ public class TestXSLFTextParagraph extends TestCase { XSLFTextRun r2 = p.addLineBreak(); assertEquals("\n", r2.getText()); r2.setFontSize(10.0); - assertEquals(10.0, r2.getFontSize()); + assertEquals(10.0, r2.getFontSize(), 0); XSLFTextRun r3 = p.addNewTextRun(); r3.setText("World!"); r3.setFontSize(20.0); XSLFTextRun r4 = p.addLineBreak(); - assertEquals(20.0, r4.getFontSize()); + assertEquals(20.0, r4.getFontSize(), 0); assertEquals("Hello,\nWorld!\n",sh.getText()); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java index f217c58278..f9232a1733 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFTextShape.java @@ -16,20 +16,17 @@ ==================================================================== */ package org.apache.poi.xslf.usermodel; +import java.awt.Color; + import junit.framework.TestCase; -import org.apache.poi.sl.usermodel.TextAlign; +import org.apache.poi.sl.usermodel.TextParagraph.TextAlign; import org.apache.poi.sl.usermodel.VerticalAlignment; import org.apache.poi.xslf.XSLFTestDataSamples; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBodyProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties; -import org.openxmlformats.schemas.drawingml.x2006.main.STTextAlignType; +import org.openxmlformats.schemas.drawingml.x2006.main.*; import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder; import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType; -import java.awt.Color; - /** * @author Yegor Kozlov */ diff --git a/src/resources/scratchpad/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml b/src/resources/scratchpad/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml new file mode 100644 index 0000000000..4a3a0701d3 --- /dev/null +++ b/src/resources/scratchpad/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml @@ -0,0 +1,19906 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources/scratchpad/org/apache/poi/sl/draw/presetShapeDefinitions.xml b/src/resources/scratchpad/org/apache/poi/sl/draw/presetShapeDefinitions.xml deleted file mode 100644 index 4a3a0701d3..0000000000 --- a/src/resources/scratchpad/org/apache/poi/sl/draw/presetShapeDefinitions.xml +++ /dev/null @@ -1,19906 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java deleted file mode 100644 index 07a01aa244..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/EncryptedSlideShow.java +++ /dev/null @@ -1,494 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf; - -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; -import java.util.TreeMap; - -import javax.crypto.Cipher; -import javax.crypto.CipherOutputStream; - -import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; -import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; -import org.apache.poi.hslf.record.DocumentEncryptionAtom; -import org.apache.poi.hslf.record.PersistPtrHolder; -import org.apache.poi.hslf.record.PositionDependentRecord; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.UserEditAtom; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.crypt.EncryptionInfo; -import org.apache.poi.poifs.crypt.Encryptor; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor; -import org.apache.poi.util.BitField; -import org.apache.poi.util.Internal; -import org.apache.poi.util.LittleEndian; - -/** - * This class provides helper functions for encrypted PowerPoint documents. - */ -@Internal -public class EncryptedSlideShow { - DocumentEncryptionAtom dea; - CryptoAPIEncryptor enc = null; - CryptoAPIDecryptor dec = null; - Cipher cipher = null; - CipherOutputStream cyos = null; - - private static final BitField fieldRecInst = new BitField(0xFFF0); - - protected EncryptedSlideShow(DocumentEncryptionAtom dea) { - this.dea = dea; - } - - protected EncryptedSlideShow(byte[] docstream, NavigableMap recordMap) { - // check for DocumentEncryptionAtom, which would be at the last offset - // need to ignore already set UserEdit and PersistAtoms - UserEditAtom userEditAtomWithEncryption = null; - for (Map.Entry me : recordMap.descendingMap().entrySet()) { - Record r = me.getValue(); - if (!(r instanceof UserEditAtom)) continue; - UserEditAtom uea = (UserEditAtom)r; - if (uea.getEncryptSessionPersistIdRef() != -1) { - userEditAtomWithEncryption = uea; - break; - } - } - - if (userEditAtomWithEncryption == null) { - dea = null; - return; - } - - Record r = recordMap.get(userEditAtomWithEncryption.getPersistPointersOffset()); - assert(r instanceof PersistPtrHolder); - PersistPtrHolder ptr = (PersistPtrHolder)r; - - Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef()); - assert(encOffset != null); - - r = recordMap.get(encOffset); - if (r == null) { - r = Record.buildRecordAtOffset(docstream, encOffset); - recordMap.put(encOffset, r); - } - assert(r instanceof DocumentEncryptionAtom); - this.dea = (DocumentEncryptionAtom)r; - - CryptoAPIDecryptor dec = (CryptoAPIDecryptor)dea.getEncryptionInfo().getDecryptor(); - String pass = Biff8EncryptionKey.getCurrentUserPassword(); - if(!dec.verifyPassword(pass != null ? pass : Decryptor.DEFAULT_PASSWORD)) { - throw new EncryptedPowerPointFileException("PowerPoint file is encrypted. The correct password needs to be set via Biff8EncryptionKey.setCurrentUserPassword()"); - } - } - - public DocumentEncryptionAtom getDocumentEncryptionAtom() { - return dea; - } - - protected void setPersistId(int persistId) { - if (enc != null && dec != null) { - throw new EncryptedPowerPointFileException("Use instance either for en- or decryption"); - } - - try { - if (enc != null) cipher = enc.initCipherForBlock(cipher, persistId); - if (dec != null) cipher = dec.initCipherForBlock(cipher, persistId); - } catch (GeneralSecurityException e) { - throw new EncryptedPowerPointFileException(e); - } - } - - protected void decryptInit() { - if (dec != null) return; - EncryptionInfo ei = dea.getEncryptionInfo(); - dec = (CryptoAPIDecryptor)ei.getDecryptor(); - } - - protected void encryptInit() { - if (enc != null) return; - EncryptionInfo ei = dea.getEncryptionInfo(); - enc = (CryptoAPIEncryptor)ei.getEncryptor(); - } - - - - protected OutputStream encryptRecord(OutputStream plainStream, int persistId, Record record) { - boolean isPlain = (dea == null - || record instanceof UserEditAtom - || record instanceof PersistPtrHolder - || record instanceof DocumentEncryptionAtom - ); - if (isPlain) return plainStream; - - encryptInit(); - setPersistId(persistId); - - if (cyos == null) { - cyos = new CipherOutputStream(plainStream, cipher); - } - return cyos; - } - - protected void decryptRecord(byte[] docstream, int persistId, int offset) { - if (dea == null) return; - - decryptInit(); - setPersistId(persistId); - - try { - // decrypt header and read length to be decrypted - cipher.update(docstream, offset, 8, docstream, offset); - // decrypt the rest of the record - int rlen = (int)LittleEndian.getUInt(docstream, offset+4); - cipher.update(docstream, offset+8, rlen, docstream, offset+8); - } catch (GeneralSecurityException e) { - throw new CorruptPowerPointFileException(e); - } - } - - protected void decryptPicture(byte[] pictstream, int offset) { - if (dea == null) return; - - decryptInit(); - setPersistId(0); - - try { - // decrypt header and read length to be decrypted - cipher.doFinal(pictstream, offset, 8, pictstream, offset); - int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); - int recType = LittleEndian.getUShort(pictstream, offset+2); - int rlen = (int)LittleEndian.getUInt(pictstream, offset+4); - offset += 8; - int endOffset = offset + rlen; - - if (recType == 0xF007) { - // TOOD: get a real example file ... to actual test the FBSE entry - // not sure where the foDelay block is - - // File BLIP Store Entry (FBSE) - cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32 - offset++; - cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS - offset++; - cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid - offset += 16; - cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag - offset += 2; - cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size - offset += 4; - cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef - offset += 4; - cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay - offset += 4; - cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1 - cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName - cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2 - cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3 - int cbName = LittleEndian.getUShort(pictstream, offset+1); - offset += 4; - if (cbName > 0) { - cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData - offset += cbName; - } - if (offset == endOffset) { - return; // no embedded blip - } - // fall through, read embedded blip now - - // update header data - cipher.doFinal(pictstream, offset, 8, pictstream, offset); - recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); - recType = LittleEndian.getUShort(pictstream, offset+2); - rlen = (int)LittleEndian.getUInt(pictstream, offset+4); - offset += 8; - } - - int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 || - recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1; - - for (int i=0; i 0) { - cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData - offset += cbName; - } - if (offset == endOffset) { - return; // no embedded blip - } - // fall through, read embedded blip now - - // update header data - recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); - recType = LittleEndian.getUShort(pictstream, offset+2); - rlen = (int)LittleEndian.getUInt(pictstream, offset+4); - cipher.doFinal(pictstream, offset, 8, pictstream, offset); - offset += 8; - } - - int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 || - recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1; - - for (int i=0; i done - return records; - } else { - // need to remove password data - dea = null; - return removeEncryptionRecord(records); - } - } else { - // create password record - if (dea == null) { - dea = new DocumentEncryptionAtom(); - } - EncryptionInfo ei = dea.getEncryptionInfo(); - byte salt[] = ei.getVerifier().getSalt(); - Encryptor enc = ei.getEncryptor(); - if (salt == null) { - enc.confirmPassword(password); - } else { - byte verifier[] = ei.getDecryptor().getVerifier(); - enc.confirmPassword(password, null, null, verifier, salt, null); - } - - // move EncryptionRecord to last slide position - records = normalizeRecords(records); - return addEncryptionRecord(records, dea); - } - } - - /** - * remove duplicated UserEditAtoms and merge PersistPtrHolder. - * Before this method is called, make sure that the offsets are correct, - * i.e. call {@link HSLFSlideShow#updateAndWriteDependantRecords(OutputStream, Map)} - */ - protected static Record[] normalizeRecords(Record records[]) { - // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx - // repeated slideIds can be overwritten, i.e. ignored - - UserEditAtom uea = null; - PersistPtrHolder pph = null; - TreeMap slideLocations = new TreeMap(); - TreeMap recordMap = new TreeMap(); - List obsoleteOffsets = new ArrayList(); - int duplicatedCount = 0; - for (Record r : records) { - assert(r instanceof PositionDependentRecord); - PositionDependentRecord pdr = (PositionDependentRecord)r; - if (pdr instanceof UserEditAtom) { - uea = (UserEditAtom)pdr; - continue; - } - - if (pdr instanceof PersistPtrHolder) { - if (pph != null) { - duplicatedCount++; - } - pph = (PersistPtrHolder)pdr; - for (Map.Entry me : pph.getSlideLocationsLookup().entrySet()) { - Integer oldOffset = slideLocations.put(me.getKey(), me.getValue()); - if (oldOffset != null) obsoleteOffsets.add(oldOffset); - } - continue; - } - - recordMap.put(pdr.getLastOnDiskOffset(), r); - } - recordMap.put(pph.getLastOnDiskOffset(), pph); - recordMap.put(uea.getLastOnDiskOffset(), uea); - - assert(uea != null && pph != null && uea.getPersistPointersOffset() == pph.getLastOnDiskOffset()); - - if (duplicatedCount == 0 && obsoleteOffsets.isEmpty()) { - return records; - } - - uea.setLastUserEditAtomOffset(0); - pph.clear(); - for (Map.Entry me : slideLocations.entrySet()) { - pph.addSlideLookup(me.getKey(), me.getValue()); - } - - for (Integer oldOffset : obsoleteOffsets) { - recordMap.remove(oldOffset); - } - - return recordMap.values().toArray(new Record[recordMap.size()]); - } - - - protected static Record[] removeEncryptionRecord(Record records[]) { - int deaSlideId = -1; - int deaOffset = -1; - PersistPtrHolder ptr = null; - UserEditAtom uea = null; - List recordList = new ArrayList(); - for (Record r : records) { - if (r instanceof DocumentEncryptionAtom) { - deaOffset = ((DocumentEncryptionAtom)r).getLastOnDiskOffset(); - continue; - } else if (r instanceof UserEditAtom) { - uea = (UserEditAtom)r; - deaSlideId = uea.getEncryptSessionPersistIdRef(); - uea.setEncryptSessionPersistIdRef(-1); - } else if (r instanceof PersistPtrHolder) { - ptr = (PersistPtrHolder)r; - } - recordList.add(r); - } - - assert(ptr != null); - if (deaSlideId == -1 && deaOffset == -1) return records; - - TreeMap tm = new TreeMap(ptr.getSlideLocationsLookup()); - ptr.clear(); - int maxSlideId = -1; - for (Map.Entry me : tm.entrySet()) { - if (me.getKey() == deaSlideId || me.getValue() == deaOffset) continue; - ptr.addSlideLookup(me.getKey(), me.getValue()); - maxSlideId = Math.max(me.getKey(), maxSlideId); - } - - uea.setMaxPersistWritten(maxSlideId); - - records = recordList.toArray(new Record[recordList.size()]); - - return records; - } - - - protected static Record[] addEncryptionRecord(Record records[], DocumentEncryptionAtom dea) { - assert(dea != null); - int ueaIdx = -1, ptrIdx = -1, deaIdx = -1, idx = -1; - for (Record r : records) { - idx++; - if (r instanceof UserEditAtom) ueaIdx = idx; - else if (r instanceof PersistPtrHolder) ptrIdx = idx; - else if (r instanceof DocumentEncryptionAtom) deaIdx = idx; - } - assert(ueaIdx != -1 && ptrIdx != -1 && ptrIdx < ueaIdx); - if (deaIdx != -1) { - DocumentEncryptionAtom deaOld = (DocumentEncryptionAtom)records[deaIdx]; - dea.setLastOnDiskOffset(deaOld.getLastOnDiskOffset()); - records[deaIdx] = dea; - return records; - } else { - PersistPtrHolder ptr = (PersistPtrHolder)records[ptrIdx]; - UserEditAtom uea = ((UserEditAtom)records[ueaIdx]); - dea.setLastOnDiskOffset(ptr.getLastOnDiskOffset()-1); - int nextSlideId = uea.getMaxPersistWritten()+1; - ptr.addSlideLookup(nextSlideId, ptr.getLastOnDiskOffset()-1); - uea.setEncryptSessionPersistIdRef(nextSlideId); - uea.setMaxPersistWritten(nextSlideId); - - Record newRecords[] = new Record[records.length+1]; - if (ptrIdx > 0) System.arraycopy(records, 0, newRecords, 0, ptrIdx); - if (ptrIdx < records.length-1) System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx); - newRecords[ptrIdx] = dea; - return newRecords; - } - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java deleted file mode 100644 index 55c3f6f876..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java +++ /dev/null @@ -1,808 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.security.GeneralSecurityException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; -import java.util.TreeMap; - -import org.apache.poi.POIDocument; -import org.apache.poi.hpsf.PropertySet; -import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.CurrentUserAtom; -import org.apache.poi.hslf.record.DocumentEncryptionAtom; -import org.apache.poi.hslf.record.ExOleObjStg; -import org.apache.poi.hslf.record.PersistPtrHolder; -import org.apache.poi.hslf.record.PersistRecord; -import org.apache.poi.hslf.record.PositionDependentRecord; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.RecordTypes; -import org.apache.poi.hslf.record.UserEditAtom; -import org.apache.poi.hslf.usermodel.ObjectData; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.EntryUtils; -import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * This class contains the main functionality for the Powerpoint file - * "reader". It is only a very basic class for now - * - * @author Nick Burch - */ -public final class HSLFSlideShow extends POIDocument { - public static final int UNSET_OFFSET = -1; - - // For logging - private POILogger logger = POILogFactory.getLogger(this.getClass()); - - // Holds metadata on where things are in our document - private CurrentUserAtom currentUser; - - // Low level contents of the file - private byte[] _docstream; - - // Low level contents - private Record[] _records; - - // Raw Pictures contained in the pictures stream - private List _pictures; - - // Embedded objects stored in storage records in the document stream, lazily populated. - private ObjectData[] _objects; - - /** - * Returns the underlying POIFSFileSystem for the document - * that is open. - */ - protected POIFSFileSystem getPOIFSFileSystem() { - return directory.getFileSystem(); - } - - /** - * Returns the directory in the underlying POIFSFileSystem for the - * document that is open. - */ - protected DirectoryNode getPOIFSDirectory() { - return directory; - } - - /** - * Constructs a Powerpoint document from fileName. Parses the document - * and places all the important stuff into data structures. - * - * @param fileName The name of the file to read. - * @throws IOException if there is a problem while parsing the document. - */ - public HSLFSlideShow(String fileName) throws IOException - { - this(new FileInputStream(fileName)); - } - - /** - * Constructs a Powerpoint document from an input stream. Parses the - * document and places all the important stuff into data structures. - * - * @param inputStream the source of the data - * @throws IOException if there is a problem while parsing the document. - */ - public HSLFSlideShow(InputStream inputStream) throws IOException { - //do Ole stuff - this(new POIFSFileSystem(inputStream)); - } - - /** - * Constructs a Powerpoint document from a POIFS Filesystem. Parses the - * document and places all the important stuff into data structures. - * - * @param filesystem the POIFS FileSystem to read from - * @throws IOException if there is a problem while parsing the document. - */ - public HSLFSlideShow(POIFSFileSystem filesystem) throws IOException - { - this(filesystem.getRoot()); - } - - /** - * Constructs a Powerpoint document from a POIFS Filesystem. Parses the - * document and places all the important stuff into data structures. - * - * @param filesystem the POIFS FileSystem to read from - * @throws IOException if there is a problem while parsing the document. - */ - public HSLFSlideShow(NPOIFSFileSystem filesystem) throws IOException - { - this(filesystem.getRoot()); - } - - /** - * Constructs a Powerpoint document from a specific point in a - * POIFS Filesystem. Parses the document and places all the - * important stuff into data structures. - * - * @deprecated Use {@link #HSLFSlideShow(DirectoryNode)} instead - * @param dir the POIFS directory to read from - * @param filesystem the POIFS FileSystem to read from - * @throws IOException if there is a problem while parsing the document. - */ - @Deprecated - public HSLFSlideShow(DirectoryNode dir, POIFSFileSystem filesystem) throws IOException - { - this(dir); - } - - /** - * Constructs a Powerpoint document from a specific point in a - * POIFS Filesystem. Parses the document and places all the - * important stuff into data structures. - * - * @param dir the POIFS directory to read from - * @throws IOException if there is a problem while parsing the document. - */ - public HSLFSlideShow(DirectoryNode dir) throws IOException { - super(handleDualStorage(dir)); - - // First up, grab the "Current User" stream - // We need this before we can detect Encrypted Documents - readCurrentUserStream(); - - // Next up, grab the data that makes up the - // PowerPoint stream - readPowerPointStream(); - - // Now, build records based on the PowerPoint stream - buildRecords(); - - // Look for any other streams - readOtherStreams(); - } - - private static DirectoryNode handleDualStorage(DirectoryNode dir) throws IOException { - // when there's a dual storage entry, use it, as the outer document can't be read quite probably ... - String dualName = "PP97_DUALSTORAGE"; - if (!dir.hasEntry(dualName)) return dir; - dir = (DirectoryNode)dir.getEntry(dualName); - return dir; - } - - /** - * Constructs a new, empty, Powerpoint document. - */ - public static final HSLFSlideShow create() { - InputStream is = HSLFSlideShow.class.getResourceAsStream("data/empty.ppt"); - if (is == null) { - throw new RuntimeException("Missing resource 'empty.ppt'"); - } - try { - return new HSLFSlideShow(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Extracts the main PowerPoint document stream from the - * POI file, ready to be passed - * - * @throws IOException - */ - private void readPowerPointStream() throws IOException - { - // Get the main document stream - DocumentEntry docProps = - (DocumentEntry)directory.getEntry("PowerPoint Document"); - - // Grab the document stream - _docstream = new byte[docProps.getSize()]; - directory.createDocumentInputStream("PowerPoint Document").read(_docstream); - } - - /** - * Builds the list of records, based on the contents - * of the PowerPoint stream - */ - private void buildRecords() - { - // The format of records in a powerpoint file are: - // - // - // - // If it has a zero length, following it will be another record - // - // If it has a length, depending on its type it may have children or data - // If it has children, these will follow straight away - // > - // If it has data, this will come straigh after, and run for the length - // - // All lengths given exclude the 8 byte record header - // (Data records are known as Atoms) - - // Document should start with: - // 0F 00 E8 03 ## ## ## ## - // (type 1000 = document, info 00 0f is normal, rest is document length) - // 01 00 E9 03 28 00 00 00 - // (type 1001 = document atom, info 00 01 normal, 28 bytes long) - // 80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx - // 05 00 00 00 0A 00 00 00 xx xx xx - // (the contents of the document atom, not sure what it means yet) - // (records then follow) - - // When parsing a document, look to see if you know about that type - // of the current record. If you know it's a type that has children, - // process the record's data area looking for more records - // If you know about the type and it doesn't have children, either do - // something with the data (eg TextRun) or skip over it - // If you don't know about the type, play safe and skip over it (using - // its length to know where the next record will start) - // - - _records = read(_docstream, (int)currentUser.getCurrentEditOffset()); - } - - private Record[] read(byte[] docstream, int usrOffset){ - //sort found records by offset. - //(it is not necessary but SlideShow.findMostRecentCoreRecords() expects them sorted) - NavigableMap records = new TreeMap(); // offset -> record - Map persistIds = new HashMap(); // offset -> persistId - initRecordOffsets(docstream, usrOffset, records, persistIds); - EncryptedSlideShow decryptData = new EncryptedSlideShow(docstream, records); - - for (Map.Entry entry : records.entrySet()) { - Integer offset = entry.getKey(); - Record record = entry.getValue(); - Integer persistId = persistIds.get(offset); - if (record == null) { - // all plain records have been already added, - // only new records need to be decrypted (tbd #35897) - decryptData.decryptRecord(docstream, persistId, offset); - record = Record.buildRecordAtOffset(docstream, offset); - entry.setValue(record); - } - - if (record instanceof PersistRecord) { - ((PersistRecord)record).setPersistId(persistId); - } - } - - return records.values().toArray(new Record[records.size()]); - } - - private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap recordMap, Map offset2id) { - while (usrOffset != 0){ - UserEditAtom usr = (UserEditAtom) Record.buildRecordAtOffset(docstream, usrOffset); - recordMap.put(usrOffset, usr); - - int psrOffset = usr.getPersistPointersOffset(); - PersistPtrHolder ptr = (PersistPtrHolder)Record.buildRecordAtOffset(docstream, psrOffset); - recordMap.put(psrOffset, ptr); - - for(Map.Entry entry : ptr.getSlideLocationsLookup().entrySet()) { - Integer offset = entry.getValue(); - Integer id = entry.getKey(); - recordMap.put(offset, null); // reserve a slot for the record - offset2id.put(offset, id); - } - - usrOffset = usr.getLastUserEditAtomOffset(); - - // check for corrupted user edit atom and try to repair it - // if the next user edit atom offset is already known, we would go into an endless loop - if (usrOffset > 0 && recordMap.containsKey(usrOffset)) { - // a user edit atom is usually located 36 byte before the smallest known record offset - usrOffset = recordMap.firstKey()-36; - // check that we really are located on a user edit atom - int ver_inst = LittleEndian.getUShort(docstream, usrOffset); - int type = LittleEndian.getUShort(docstream, usrOffset+2); - int len = LittleEndian.getInt(docstream, usrOffset+4); - if (ver_inst == 0 && type == 4085 && (len == 0x1C || len == 0x20)) { - logger.log(POILogger.WARN, "Repairing invalid user edit atom"); - usr.setLastUserEditAtomOffset(usrOffset); - } else { - throw new CorruptPowerPointFileException("Powerpoint document contains invalid user edit atom"); - } - } - } - } - - public DocumentEncryptionAtom getDocumentEncryptionAtom() { - for (Record r : _records) { - if (r instanceof DocumentEncryptionAtom) { - return (DocumentEncryptionAtom)r; - } - } - return null; - } - - - /** - * Find the "Current User" stream, and load it - */ - private void readCurrentUserStream() { - try { - currentUser = new CurrentUserAtom(directory); - } catch(IOException ie) { - logger.log(POILogger.ERROR, "Error finding Current User Atom:\n" + ie); - currentUser = new CurrentUserAtom(); - } - } - - /** - * Find any other streams from the filesystem, and load them - */ - private void readOtherStreams() { - // Currently, there aren't any - } - - /** - * Find and read in pictures contained in this presentation. - * This is lazily called as and when we want to touch pictures. - */ - @SuppressWarnings("unused") - private void readPictures() throws IOException { - _pictures = new ArrayList(); - - // if the presentation doesn't contain pictures - will use a null set instead - if (!directory.hasEntry("Pictures")) return; - - EncryptedSlideShow decryptData = new EncryptedSlideShow(getDocumentEncryptionAtom()); - - DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures"); - byte[] pictstream = new byte[entry.getSize()]; - DocumentInputStream is = directory.createDocumentInputStream(entry); - is.read(pictstream); - is.close(); - - - int pos = 0; - // An empty picture record (length 0) will take up 8 bytes - while (pos <= (pictstream.length-8)) { - int offset = pos; - - decryptData.decryptPicture(pictstream, offset); - - // Image signature - int signature = LittleEndian.getUShort(pictstream, pos); - pos += LittleEndian.SHORT_SIZE; - // Image type + 0xF018 - int type = LittleEndian.getUShort(pictstream, pos); - pos += LittleEndian.SHORT_SIZE; - // Image size (excluding the 8 byte header) - int imgsize = LittleEndian.getInt(pictstream, pos); - pos += LittleEndian.INT_SIZE; - - // When parsing the BStoreDelay stream, [MS-ODRAW] says that we - // should terminate if the type isn't 0xf007 or 0xf018->0xf117 - if (!((type == 0xf007) || (type >= 0xf018 && type <= 0xf117))) - break; - - // The image size must be 0 or greater - // (0 is allowed, but odd, since we do wind on by the header each - // time, so we won't get stuck) - if(imgsize < 0) { - throw new CorruptPowerPointFileException("The file contains a picture, at position " + _pictures.size() + ", which has a negatively sized data length, so we can't trust any of the picture data"); - } - - // If they type (including the bonus 0xF018) is 0, skip it - if(type == 0) { - logger.log(POILogger.ERROR, "Problem reading picture: Invalid image type 0, on picture with length " + imgsize + ".\nYou document will probably become corrupted if you save it!"); - logger.log(POILogger.ERROR, "" + pos); - } else { - // Build the PictureData object from the data - try { - PictureData pict = PictureData.create(type - 0xF018); - - // Copy the data, ready to pass to PictureData - byte[] imgdata = new byte[imgsize]; - System.arraycopy(pictstream, pos, imgdata, 0, imgdata.length); - pict.setRawData(imgdata); - - pict.setOffset(offset); - _pictures.add(pict); - } catch(IllegalArgumentException e) { - logger.log(POILogger.ERROR, "Problem reading picture: " + e + "\nYou document will probably become corrupted if you save it!"); - } - } - - pos += imgsize; - } - } - - /** - * remove duplicated UserEditAtoms and merge PersistPtrHolder, i.e. - * remove document edit history - */ - public void normalizeRecords() { - try { - updateAndWriteDependantRecords(null, null); - } catch (IOException e) { - throw new CorruptPowerPointFileException(e); - } - _records = EncryptedSlideShow.normalizeRecords(_records); - } - - - /** - * This is a helper functions, which is needed for adding new position dependent records - * or finally write the slideshow to a file. - * - * @param os the stream to write to, if null only the references are updated - * @param interestingRecords a map of interesting records (PersistPtrHolder and UserEditAtom) - * referenced by their RecordType. Only the very last of each type will be saved to the map. - * May be null, if not needed. - * @throws IOException - */ - public void updateAndWriteDependantRecords(OutputStream os, Map interestingRecords) - throws IOException { - // For position dependent records, hold where they were and now are - // As we go along, update, and hand over, to any Position Dependent - // records we happen across - Hashtable oldToNewPositions = new Hashtable(); - - // First pass - figure out where all the position dependent - // records are going to end up, in the new scheme - // (Annoyingly, some powerpoint files have PersistPtrHolders - // that reference slides after the PersistPtrHolder) - UserEditAtom usr = null; - PersistPtrHolder ptr = null; - CountingOS cos = new CountingOS(); - for (Record record : _records) { - // all top level records are position dependent - assert(record instanceof PositionDependentRecord); - PositionDependentRecord pdr = (PositionDependentRecord)record; - int oldPos = pdr.getLastOnDiskOffset(); - int newPos = cos.size(); - pdr.setLastOnDiskOffset(newPos); - if (oldPos != UNSET_OFFSET) { - // new records don't need a mapping, as they aren't in a relation yet - oldToNewPositions.put(oldPos,newPos); - } - - // Grab interesting records as they come past - // this will only save the very last record of each type - RecordTypes.Type saveme = null; - int recordType = (int)record.getRecordType(); - if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) { - saveme = RecordTypes.PersistPtrIncrementalBlock; - ptr = (PersistPtrHolder)pdr; - } else if (recordType == RecordTypes.UserEditAtom.typeID) { - saveme = RecordTypes.UserEditAtom; - usr = (UserEditAtom)pdr; - } - if (interestingRecords != null && saveme != null) { - interestingRecords.put(saveme,pdr); - } - - // Dummy write out, so the position winds on properly - record.writeOut(cos); - } - - assert(usr != null && ptr != null); - - Map persistIds = new HashMap(); - for (Map.Entry entry : ptr.getSlideLocationsLookup().entrySet()) { - persistIds.put(oldToNewPositions.get(entry.getValue()), entry.getKey()); - } - - EncryptedSlideShow encData = new EncryptedSlideShow(getDocumentEncryptionAtom()); - - for (Record record : _records) { - assert(record instanceof PositionDependentRecord); - // We've already figured out their new location, and - // told them that - // Tell them of the positions of the other records though - PositionDependentRecord pdr = (PositionDependentRecord)record; - Integer persistId = persistIds.get(pdr.getLastOnDiskOffset()); - if (persistId == null) persistId = 0; - - // For now, we're only handling PositionDependentRecord's that - // happen at the top level. - // In future, we'll need the handle them everywhere, but that's - // a bit trickier - pdr.updateOtherRecordReferences(oldToNewPositions); - - // Whatever happens, write out that record tree - if (os != null) { - record.writeOut(encData.encryptRecord(os, persistId, record)); - } - } - - // Update and write out the Current User atom - int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset(); - Integer newLastUserEditAtomPos = oldToNewPositions.get(oldLastUserEditAtomPos); - if(usr == null || newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) { - throw new HSLFException("Couldn't find the new location of the last UserEditAtom that used to be at " + oldLastUserEditAtomPos); - } - currentUser.setCurrentEditOffset(usr.getLastOnDiskOffset()); - } - - /** - * Writes out the slideshow file the is represented by an instance - * of this class. - * It will write out the common OLE2 streams. If you require all - * streams to be written out, pass in preserveNodes - * @param out The OutputStream to write to. - * @throws IOException If there is an unexpected IOException from - * the passed in OutputStream - */ - public void write(OutputStream out) throws IOException { - // Write out, but only the common streams - write(out,false); - } - /** - * Writes out the slideshow file the is represented by an instance - * of this class. - * If you require all streams to be written out (eg Marcos, embeded - * documents), then set preserveNodes to true - * @param out The OutputStream to write to. - * @param preserveNodes Should all OLE2 streams be written back out, or only the common ones? - * @throws IOException If there is an unexpected IOException from - * the passed in OutputStream - */ - public void write(OutputStream out, boolean preserveNodes) throws IOException { - // read properties and pictures, with old encryption settings where appropriate - if(_pictures == null) { - readPictures(); - } - getDocumentSummaryInformation(); - - // set new encryption settings - EncryptedSlideShow encryptedSS = new EncryptedSlideShow(getDocumentEncryptionAtom()); - _records = encryptedSS.updateEncryptionRecord(_records); - - // Get a new Filesystem to write into - POIFSFileSystem outFS = new POIFSFileSystem(); - - // The list of entries we've written out - List writtenEntries = new ArrayList(1); - - // Write out the Property Streams - writeProperties(outFS, writtenEntries); - - BufAccessBAOS baos = new BufAccessBAOS(); - - // For position dependent records, hold where they were and now are - // As we go along, update, and hand over, to any Position Dependent - // records we happen across - updateAndWriteDependantRecords(baos, null); - - // Update our cached copy of the bytes that make up the PPT stream - _docstream = new byte[baos.size()]; - System.arraycopy(baos.getBuf(), 0, _docstream, 0, baos.size()); - - // Write the PPT stream into the POIFS layer - ByteArrayInputStream bais = new ByteArrayInputStream(_docstream); - outFS.createDocument(bais,"PowerPoint Document"); - writtenEntries.add("PowerPoint Document"); - - currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null); - currentUser.writeToFS(outFS); - writtenEntries.add("Current User"); - - - if (_pictures.size() > 0) { - BufAccessBAOS pict = new BufAccessBAOS(); - for (PictureData p : _pictures) { - int offset = pict.size(); - p.write(pict); - encryptedSS.encryptPicture(pict.getBuf(), offset); - } - outFS.createDocument( - new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures" - ); - writtenEntries.add("Pictures"); - } - - // If requested, write out any other streams we spot - if(preserveNodes) { - EntryUtils.copyNodes(directory.getFileSystem(), outFS, writtenEntries); - } - - // Send the POIFSFileSystem object out to the underlying stream - outFS.writeFilesystem(out); - } - - /** - * For a given named property entry, either return it or null if - * if it wasn't found - * - * @param setName The property to read - * @return The value of the given property or null if it wasn't found. - */ - protected PropertySet getPropertySet(String setName) { - DocumentEncryptionAtom dea = getDocumentEncryptionAtom(); - return (dea == null) - ? super.getPropertySet(setName) - : super.getPropertySet(setName, dea.getEncryptionInfo()); - } - - /** - * Writes out the standard Documment Information Properties (HPSF) - * @param outFS the POIFSFileSystem to write the properties into - * @param writtenEntries a list of POIFS entries to add the property names too - * - * @throws IOException if an error when writing to the - * {@link POIFSFileSystem} occurs - */ - protected void writeProperties(POIFSFileSystem outFS, List writtenEntries) throws IOException { - super.writeProperties(outFS, writtenEntries); - DocumentEncryptionAtom dea = getDocumentEncryptionAtom(); - if (dea != null) { - CryptoAPIEncryptor enc = (CryptoAPIEncryptor)dea.getEncryptionInfo().getEncryptor(); - try { - enc.getDataStream(outFS.getRoot()); // ignore OutputStream - } catch (IOException e) { - throw e; - } catch (GeneralSecurityException e) { - throw new IOException(e); - } - } - } - - /* ******************* adding methods follow ********************* */ - - /** - * Adds a new root level record, at the end, but before the last - * PersistPtrIncrementalBlock. - */ - public synchronized int appendRootLevelRecord(Record newRecord) { - int addedAt = -1; - Record[] r = new Record[_records.length+1]; - boolean added = false; - for(int i=(_records.length-1); i>=0; i--) { - if(added) { - // Just copy over - r[i] = _records[i]; - } else { - r[(i+1)] = _records[i]; - if(_records[i] instanceof PersistPtrHolder) { - r[i] = newRecord; - added = true; - addedAt = i; - } - } - } - _records = r; - return addedAt; - } - - /** - * Add a new picture to this presentation. - * - * @return offset of this picture in the Pictures stream - */ - public int addPicture(PictureData img) { - // Process any existing pictures if we haven't yet - if(_pictures == null) { - try { - readPictures(); - } catch(IOException e) { - throw new CorruptPowerPointFileException(e.getMessage()); - } - } - - // Add the new picture in - int offset = 0; - if(_pictures.size() > 0) { - PictureData prev = _pictures.get(_pictures.size() - 1); - offset = prev.getOffset() + prev.getRawData().length + 8; - } - img.setOffset(offset); - _pictures.add(img); - return offset; - } - - /* ******************* fetching methods follow ********************* */ - - - /** - * Returns an array of all the records found in the slideshow - */ - public Record[] getRecords() { return _records; } - - /** - * Returns an array of the bytes of the file. Only correct after a - * call to open or write - at all other times might be wrong! - */ - public byte[] getUnderlyingBytes() { return _docstream; } - - /** - * Fetch the Current User Atom of the document - */ - public CurrentUserAtom getCurrentUserAtom() { return currentUser; } - - /** - * Return array of pictures contained in this presentation - * - * @return array with the read pictures or null if the - * presentation doesn't contain pictures. - */ - public PictureData[] getPictures() { - if(_pictures == null) { - try { - readPictures(); - } catch(IOException e) { - throw new CorruptPowerPointFileException(e.getMessage()); - } - } - - return _pictures.toArray(new PictureData[_pictures.size()]); - } - - /** - * Gets embedded object data from the slide show. - * - * @return the embedded objects. - */ - public ObjectData[] getEmbeddedObjects() { - if (_objects == null) { - List objects = new ArrayList(); - for (Record r : _records) { - if (r instanceof ExOleObjStg) { - objects.add(new ObjectData((ExOleObjStg)r)); - } - } - _objects = objects.toArray(new ObjectData[objects.size()]); - } - return _objects; - } - - - private static class BufAccessBAOS extends ByteArrayOutputStream { - public byte[] getBuf() { - return buf; - } - } - - private static class CountingOS extends OutputStream { - int count = 0; - public void write(int b) throws IOException { - count++; - } - - public void write(byte[] b) throws IOException { - count += b.length; - } - - public void write(byte[] b, int off, int len) throws IOException { - count += len; - } - - public int size() { - return count; - } - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java index 9f59de4a86..4c9e9ceaf6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Bitmap.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; import java.io.IOException; import java.io.ByteArrayOutputStream; @@ -28,7 +28,7 @@ import java.io.ByteArrayOutputStream; * * @author Yegor Kozlov */ -public abstract class Bitmap extends PictureData { +public abstract class Bitmap extends HSLFPictureData { public byte[] getData(){ byte[] rawdata = getRawData(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java index aae83bf6e1..6795601a6c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java @@ -17,8 +17,8 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogFactory; @@ -56,7 +56,7 @@ import java.io.ByteArrayInputStream; public final class BitmapPainter implements ImagePainter { protected POILogger logger = POILogFactory.getLogger(this.getClass()); - public void paint(Graphics2D graphics, PictureData pict, Picture parent) { + public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent) { BufferedImage img; try { img = ImageIO.read(new ByteArrayInputStream(pict.getData())); diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/DIB.java b/src/scratchpad/src/org/apache/poi/hslf/blip/DIB.java index 21ea072ff7..401ac43476 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/DIB.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/DIB.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.util.LittleEndian; import java.io.IOException; @@ -35,10 +35,10 @@ public final class DIB extends Bitmap { /** * @return type of this picture - * @see org.apache.poi.hslf.model.Picture#DIB + * @see org.apache.poi.hslf.model.HSLFPictureShape#DIB */ public int getType(){ - return Picture.DIB; + return HSLFPictureShape.DIB; } /** @@ -89,4 +89,8 @@ public final class DIB extends Bitmap { System.arraycopy(data, HEADER_SIZE, dib, 0, dib.length); super.setData(dib); } + + public String getContentType() { + return "image/bmp"; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java index 7ad569aa8d..5fe55f1819 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/EMF.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.hslf.model.HSLFShape; import org.apache.poi.hslf.exceptions.HSLFException; @@ -80,7 +80,7 @@ public final class EMF extends Metafile { } public int getType(){ - return Picture.EMF; + return HSLFPictureShape.EMF; } /** @@ -91,4 +91,8 @@ public final class EMF extends Metafile { public int getSignature(){ return 0x3D40; } + + public String getContentType() { + return "image/x-emf"; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java index 2c35007048..0f1afecb98 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java @@ -17,8 +17,8 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.model.HSLFPictureShape; +import org.apache.poi.hslf.usermodel.HSLFPictureData; import java.awt.*; @@ -68,5 +68,5 @@ public interface ImagePainter { * @param pict the data to paint * @param parent the shapes that owns the picture data */ - public void paint(Graphics2D graphics, PictureData pict, Picture parent); + public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java b/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java index 65ade3ee38..567fc996ee 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/JPEG.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.blip; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.HSLFPictureShape; /** * Represents a JPEG picture data in a PPT file @@ -28,10 +28,10 @@ public final class JPEG extends Bitmap { /** * @return type of this picture - * @see org.apache.poi.hslf.model.Picture#JPEG + * @see org.apache.poi.hslf.model.HSLFPictureShape#JPEG */ public int getType(){ - return Picture.JPEG; + return HSLFPictureShape.JPEG; } /** @@ -42,4 +42,8 @@ public final class JPEG extends Bitmap { public int getSignature(){ return 0x46A0; } + + public String getContentType() { + return "image/jpeg"; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java index c05d19acb0..535e206410 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/Metafile.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.blip; import org.apache.poi.util.LittleEndian; -import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; import java.awt.*; import java.io.*; @@ -30,7 +30,7 @@ import java.util.zip.DeflaterOutputStream; * * @author Yegor Kozlov */ -public abstract class Metafile extends PictureData { +public abstract class Metafile extends HSLFPictureData { /** * A structure which represents a 34-byte header preceeding the compressed metafile data diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java index 4b401518ee..9b2df64262 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PICT.java @@ -23,7 +23,7 @@ import java.io.IOException; import java.util.zip.InflaterInputStream; import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.hslf.model.HSLFShape; /** @@ -102,10 +102,10 @@ public final class PICT extends Metafile { } /** - * @see org.apache.poi.hslf.model.Picture#PICT + * @see org.apache.poi.hslf.model.HSLFPictureShape#PICT */ public int getType(){ - return Picture.PICT; + return HSLFPictureShape.PICT; } /** @@ -117,4 +117,8 @@ public final class PICT extends Metafile { return 0x5430; } + public String getContentType() { + return "image/x-pict"; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java b/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java index 12b98f1802..a1d9aa50a9 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/PNG.java @@ -17,14 +17,8 @@ package org.apache.poi.hslf.blip; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.util.PngUtils; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.hslf.exceptions.HSLFException; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; /** * Represents a PNG picture data in a PPT file @@ -52,10 +46,10 @@ public final class PNG extends Bitmap { /** * @return type of this picture - * @see org.apache.poi.hslf.model.Picture#PNG + * @see org.apache.poi.hslf.model.HSLFPictureShape#PNG */ public int getType(){ - return Picture.PNG; + return HSLFPictureShape.PNG; } /** @@ -66,4 +60,8 @@ public final class PNG extends Bitmap { public int getSignature(){ return 0x6E00; } + + public String getContentType() { + return "image/png"; + } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java index 76f680eafd..3270b32596 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java +++ b/src/scratchpad/src/org/apache/poi/hslf/blip/WMF.java @@ -19,7 +19,7 @@ package org.apache.poi.hslf.blip; import org.apache.poi.util.LittleEndian; import org.apache.poi.util.POILogger; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.model.HSLFPictureShape; import org.apache.poi.hslf.model.HSLFShape; import org.apache.poi.hslf.exceptions.HSLFException; @@ -95,7 +95,7 @@ public final class WMF extends Metafile { * We are of type Picture.WMF */ public int getType(){ - return Picture.WMF; + return HSLFPictureShape.WMF; } /** @@ -188,4 +188,9 @@ public final class WMF extends Metafile { } } + + public String getContentType() { + return "image/x-wmf"; + } + } diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/PPDrawingTextListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/PPDrawingTextListing.java index f46906f73c..e437f9504e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/PPDrawingTextListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/PPDrawingTextListing.java @@ -18,6 +18,7 @@ package org.apache.poi.hslf.dev; import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; @@ -33,7 +34,7 @@ public final class PPDrawingTextListing { System.exit(1); } - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); // Find PPDrawings at any second level position Record[] records = ss.getRecords(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java index 490e3e2055..d0ab5ec98f 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTListing.java @@ -17,7 +17,7 @@ package org.apache.poi.hslf.dev; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.Document; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.RecordTypes; @@ -35,7 +35,7 @@ public final class SLWTListing { System.exit(1); } - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); // Find the documents, and then their SLWT Record[] records = ss.getRecords(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTTextListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTTextListing.java index 16858aa3db..fc9b224801 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTTextListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SLWTTextListing.java @@ -18,6 +18,7 @@ package org.apache.poi.hslf.dev; import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; /** @@ -32,7 +33,7 @@ public final class SLWTTextListing { System.exit(1); } - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); // Find the documents, and then their SLWT Record[] records = ss.getRecords(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java index 2dd32a4af0..2a69c17d81 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideAndNotesAtomListing.java @@ -18,6 +18,7 @@ package org.apache.poi.hslf.dev; import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; @@ -34,7 +35,7 @@ public final class SlideAndNotesAtomListing { System.exit(1); } - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); System.out.println(""); // Find either Slides or Notes diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideIdListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideIdListing.java index 010f424c33..b4f487ab8a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideIdListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideIdListing.java @@ -20,7 +20,7 @@ package org.apache.poi.hslf.dev; import java.io.ByteArrayOutputStream; import java.util.Map; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.Document; import org.apache.poi.hslf.record.Notes; import org.apache.poi.hslf.record.NotesAtom; @@ -31,7 +31,7 @@ import org.apache.poi.hslf.record.Slide; 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.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.util.LittleEndian; /** @@ -50,8 +50,8 @@ public final class SlideIdListing { // Create the slideshow object, for normal working with - HSLFSlideShow hss = new HSLFSlideShow(args[0]); - SlideShow ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(args[0]); + HSLFSlideShow ss = new HSLFSlideShow(hss); // Grab the base contents fileContents = hss.getUnderlyingBytes(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java index f2e7b36dc2..77415ff2dc 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/SlideShowRecordDumper.java @@ -19,10 +19,9 @@ package org.apache.poi.hslf.dev; import java.io.ByteArrayOutputStream; import java.io.IOException; - import java.util.Iterator; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.Record; import org.apache.poi.util.HexDump; import org.apache.poi.ddf.DefaultEscherRecordFactory; @@ -44,7 +43,7 @@ import org.apache.poi.hslf.record.StyleTextPropAtom; public final class SlideShowRecordDumper { private boolean optVerbose; private boolean optEscher; - private HSLFSlideShow doc; + private HSLFSlideShowImpl doc; /** * right now this function takes one parameter: a ppt file, and outputs @@ -103,7 +102,7 @@ public final class SlideShowRecordDumper { { optVerbose = verbose; optEscher = escher; - doc = new HSLFSlideShow(fileName); + doc = new HSLFSlideShowImpl(fileName); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/TextStyleListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/TextStyleListing.java index a919f61cdd..d7fcbc6fd1 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/TextStyleListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/TextStyleListing.java @@ -18,6 +18,7 @@ package org.apache.poi.hslf.dev; import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.model.textproperties.BitMaskTextProp; import org.apache.poi.hslf.model.textproperties.TextProp; import org.apache.poi.hslf.model.textproperties.TextPropCollection; @@ -36,7 +37,7 @@ public final class TextStyleListing { System.exit(1); } - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); // Find the documents, and then their SLWT Record[] records = ss.getRecords(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/dev/UserEditAndPersistListing.java b/src/scratchpad/src/org/apache/poi/hslf/dev/UserEditAndPersistListing.java index 749cfa9484..c7c8057171 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/dev/UserEditAndPersistListing.java +++ b/src/scratchpad/src/org/apache/poi/hslf/dev/UserEditAndPersistListing.java @@ -20,7 +20,7 @@ package org.apache.poi.hslf.dev; import java.io.ByteArrayOutputStream; import java.util.Map; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.CurrentUserAtom; import org.apache.poi.hslf.record.PersistPtrHolder; import org.apache.poi.hslf.record.PositionDependentRecord; @@ -44,7 +44,7 @@ public final class UserEditAndPersistListing { // Create the slideshow object, for normal working with - HSLFSlideShow ss = new HSLFSlideShow(args[0]); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(args[0]); fileContents = ss.getUnderlyingBytes(); System.out.println(""); diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java index 24d6d9096e..268eb3b2fb 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/ImageExtractor.java @@ -17,10 +17,10 @@ package org.apache.poi.hslf.extractor; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.model.Picture; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.model.HSLFPictureShape; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import java.io.IOException; import java.io.FileOutputStream; @@ -37,12 +37,12 @@ public final class ImageExtractor { System.err.println("\tImageExtractor "); return; } - SlideShow ppt = new SlideShow(new HSLFSlideShow(args[0])); + HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl(args[0])); //extract all pictures contained in the presentation - PictureData[] pdata = ppt.getPictureData(); + HSLFPictureData[] pdata = ppt.getPictureData(); for (int i = 0; i < pdata.length; i++) { - PictureData pict = pdata[i]; + HSLFPictureData pict = pdata[i]; // picture data byte[] data = pict.getData(); @@ -50,22 +50,22 @@ public final class ImageExtractor { int type = pict.getType(); String ext; switch (type) { - case Picture.JPEG: + case HSLFPictureShape.JPEG: ext = ".jpg"; break; - case Picture.PNG: + case HSLFPictureShape.PNG: ext = ".png"; break; - case Picture.WMF: + case HSLFPictureShape.WMF: ext = ".wmf"; break; - case Picture.EMF: + case HSLFPictureShape.EMF: ext = ".emf"; break; - case Picture.PICT: + case HSLFPictureShape.PICT: ext = ".pict"; break; - case Picture.DIB: + case HSLFPictureShape.DIB: ext = ".dib"; break; default: diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java index e870e5d0f8..621d2b6fcd 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java @@ -25,9 +25,8 @@ import java.util.List; import java.util.ArrayList; import org.apache.poi.POIOLE2TextExtractor; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model.*; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -39,9 +38,9 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * @author Nick Burch */ public final class PowerPointExtractor extends POIOLE2TextExtractor { - private HSLFSlideShow _hslfshow; - private SlideShow _show; - private Slide[] _slides; + private HSLFSlideShowImpl _hslfshow; + private HSLFSlideShow _show; + private HSLFSlide[] _slides; private boolean _slidesByDefault = true; private boolean _notesByDefault = false; @@ -120,7 +119,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { * @param dir the POIFS Directory containing the PowerPoint document */ public PowerPointExtractor(DirectoryNode dir) throws IOException { - this(new HSLFSlideShow(dir)); + this(new HSLFSlideShowImpl(dir)); } /** @@ -128,7 +127,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { */ @Deprecated public PowerPointExtractor(DirectoryNode dir, POIFSFileSystem fs) throws IOException { - this(new HSLFSlideShow(dir, fs)); + this(new HSLFSlideShowImpl(dir, fs)); } /** @@ -136,10 +135,10 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { * * @param ss the HSLFSlideShow to extract text from */ - public PowerPointExtractor(HSLFSlideShow ss) { + public PowerPointExtractor(HSLFSlideShowImpl ss) { super(ss); _hslfshow = ss; - _show = new SlideShow(_hslfshow); + _show = new HSLFSlideShow(_hslfshow); _slides = _show.getSlides(); } @@ -190,7 +189,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { List list = new ArrayList(); for (int i = 0; i < _slides.length; i++) { - Slide slide = _slides[i]; + HSLFSlide slide = _slides[i]; HSLFShape[] shapes = slide.getShapes(); for (int j = 0; j < shapes.length; j++) { @@ -222,14 +221,14 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { if (getMasterText) { for (SlideMaster master : _show.getSlidesMasters()) { for(HSLFShape sh : master.getShapes()){ - if(sh instanceof TextShape){ - if(MasterSheet.isPlaceholder(sh)) { + if(sh instanceof HSLFTextShape){ + if(HSLFMasterSheet.isPlaceholder(sh)) { // don't bother about boiler // plate text on master // sheets continue; } - TextShape tsh = (TextShape)sh; + HSLFTextShape tsh = (HSLFTextShape)sh; String text = tsh.getText(); if (text != null){ ret.append(text); @@ -243,7 +242,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { } for (int i = 0; i < _slides.length; i++) { - Slide slide = _slides[i]; + HSLFSlide slide = _slides[i]; // Slide header, if set HeadersFooters hf = slide.getHeadersFooters(); @@ -286,7 +285,7 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { HeadersFooters hf = _show.getNotesHeadersFooters(); for (int i = 0; i < _slides.length; i++) { - Notes notes = _slides[i].getNotesSheet(); + HSLFNotes notes = _slides[i].getNotesSheet(); if (notes == null) { continue; } @@ -331,13 +330,13 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor { ret.append('\n'); } } - private void textRunsToText(StringBuffer ret, TextRun[] runs) { + private void textRunsToText(StringBuffer ret, HSLFTextParagraph[] runs) { if (runs==null) { return; } for (int j = 0; j < runs.length; j++) { - TextRun run = runs[j]; + HSLFTextParagraph run = runs[j]; if (run != null) { String text = run.getText(); ret.append(text); diff --git a/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java b/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java index e449a555e8..9c92c5c591 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java +++ b/src/scratchpad/src/org/apache/poi/hslf/extractor/QuickButCruddyTextExtractor.java @@ -23,7 +23,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import org.apache.poi.hslf.model.TextRun; +import org.apache.poi.hslf.model.HSLFTextParagraph; import org.apache.poi.hslf.record.CString; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.RecordTypes; @@ -175,17 +175,17 @@ public final class QuickButCruddyTextExtractor { // Otherwise, check the type to see if it's text long type = LittleEndian.getUShort(pptContents,startPos+2); - TextRun trun = null; + HSLFTextParagraph trun = null; // TextBytesAtom if(type == RecordTypes.TextBytesAtom.typeID) { TextBytesAtom tba = (TextBytesAtom)Record.createRecordForType(type, pptContents, startPos, len+8); - trun = new TextRun((TextHeaderAtom)null,tba,(StyleTextPropAtom)null); + trun = new HSLFTextParagraph((TextHeaderAtom)null,tba,(StyleTextPropAtom)null); } // TextCharsAtom if(type == RecordTypes.TextCharsAtom.typeID) { TextCharsAtom tca = (TextCharsAtom)Record.createRecordForType(type, pptContents, startPos, len+8); - trun = new TextRun((TextHeaderAtom)null,tca,(StyleTextPropAtom)null); + trun = new HSLFTextParagraph((TextHeaderAtom)null,tca,(StyleTextPropAtom)null); } // CString (doesn't go via a TextRun) diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java index f1c90130db..95f83a3834 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ActiveXShape.java @@ -45,7 +45,7 @@ import org.apache.poi.util.StringUtil; * TODO: finish * @author Yegor Kozlov */ -public final class ActiveXShape extends Picture { +public final class ActiveXShape extends HSLFPictureShape { public static final int DEFAULT_ACTIVEX_THUMBNAIL = -1; /** @@ -108,7 +108,7 @@ public final class ActiveXShape extends Picture { /** * Assign a control to this shape * - * @see org.apache.poi.hslf.usermodel.SlideShow#addMovie(String, int) + * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int) * @param idx the index of the movie */ public void setActiveXIndex(int idx){ @@ -164,7 +164,7 @@ public final class ActiveXShape extends Picture { return ctrl; } - protected void afterInsert(Sheet sheet){ + protected void afterInsert(HSLFSheet sheet){ ExControl ctrl = getExControl(); ctrl.getExControlAtom().setSlideId(sheet._getSheetNumber()); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java deleted file mode 100644 index 0cadd7c0d9..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/AutoShape.java +++ /dev/null @@ -1,122 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import org.apache.poi.ddf.*; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.util.POILogger; - -import java.awt.geom.Rectangle2D; - -/** - * Represents an AutoShape. - *

- * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments. - * See {@link ShapeTypes} - *

- * - * @author Yegor Kozlov - */ -public class AutoShape extends TextShape { - - protected AutoShape(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - } - - public AutoShape(ShapeType type, ShapeContainer parent){ - super(null, parent); - _escherContainer = createSpContainer(type, parent instanceof HSLFGroupShape); - } - - public AutoShape(ShapeType type){ - this(type, null); - } - - protected EscherContainerRecord createSpContainer(ShapeType shapeType, boolean isChild){ - _escherContainer = super.createSpContainer(isChild); - - setShapeType(shapeType); - - //set default properties for an autoshape - setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000); - setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); - setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); - setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000); - setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010); - setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001); - setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008); - setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); - - return _escherContainer; - } - - protected void setDefaultTextProperties(TextRun _txtrun){ - setVerticalAlignment(TextBox.AnchorMiddle); - setHorizontalAlignment(TextBox.AlignCenter); - setWordWrap(TextBox.WrapNone); - } - - /** - * Gets adjust value which controls smart resizing of the auto-shape. - * - *

- * The adjustment values are given in shape coordinates: - * the origin is at the top-left, positive-x is to the right, positive-y is down. - * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). - *

- * - * @param idx the adjust index in the [0, 9] range - * @return the adjustment value - */ - public int getAdjustmentValue(int idx){ - if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); - - return getEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx)); - } - - /** - * Sets adjust value which controls smart resizing of the auto-shape. - * - *

- * The adjustment values are given in shape coordinates: - * the origin is at the top-left, positive-x is to the right, positive-y is down. - * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). - *

- * - * @param idx the adjust index in the [0, 9] range - * @param val the adjustment value - */ - public void setAdjustmentValue(int idx, int val){ - if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); - - setEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx), val); - } - - public java.awt.Shape getOutline(){ - ShapeOutline outline = AutoShapes.getShapeOutline(getShapeType()); - Rectangle2D anchor = getLogicalAnchor2D(); - if(outline == null){ - logger.log(POILogger.WARN, "Outline not found for " + getShapeType().nativeName); - return anchor; - } - java.awt.Shape shape = outline.getOutline(this); - return AutoShapes.transform(shape, anchor); - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Background.java b/src/scratchpad/src/org/apache/poi/hslf/model/Background.java deleted file mode 100644 index 1b172bdb8f..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Background.java +++ /dev/null @@ -1,81 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Rectangle; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; - -import javax.imageio.ImageIO; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.hslf.blip.Bitmap; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.POILogger; - -/** - * Background shape - * - * @author Yegor Kozlov - */ -public final class Background extends HSLFShape { - - protected Background(EscherContainerRecord escherRecord, ShapeContainer parent) { - super(escherRecord, parent); - } - - protected EscherContainerRecord createSpContainer(boolean isChild) { - return null; - } - - public void draw(Graphics2D graphics) { - Fill f = getFill(); - Dimension pg = getSheet().getSlideShow().getPageSize(); - Rectangle anchor = new Rectangle(0, 0, pg.width, pg.height); - switch (f.getFillType()) { - case Fill.FILL_SOLID: - Color color = f.getForegroundColor(); - graphics.setPaint(color); - graphics.fill(anchor); - break; - case Fill.FILL_PICTURE: - PictureData data = f.getPictureData(); - if (data instanceof Bitmap) { - BufferedImage img = null; - try { - img = ImageIO.read(new ByteArrayInputStream(data.getData())); - } catch (Exception e) { - logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + data.getType()); - return; - } - Image scaledImg = img.getScaledInstance(anchor.width, anchor.height, Image.SCALE_SMOOTH); - graphics.drawImage(scaledImg, anchor.x, anchor.y, null); - - } - break; - default: - logger.log(POILogger.WARN, "unsuported fill type: " + f.getFillType()); - break; - } - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java b/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java deleted file mode 100644 index a394cac474..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Fill.java +++ /dev/null @@ -1,267 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Color; -import java.util.List; - -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.hslf.record.Document; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * Represents functionality provided by the 'Fill Effects' dialog in PowerPoint. - * - * @author Yegor Kozlov - */ -public final class Fill { - // For logging - protected POILogger logger = POILogFactory.getLogger(this.getClass()); - - /** - * Fill with a solid color - */ - public static final int FILL_SOLID = 0; - - /** - * Fill with a pattern (bitmap) - */ - public static final int FILL_PATTERN = 1; - - /** - * A texture (pattern with its own color map) - */ - public static final int FILL_TEXTURE = 2; - - /** - * Center a picture in the shape - */ - public static final int FILL_PICTURE = 3; - - /** - * Shade from start to end points - */ - public static final int FILL_SHADE = 4; - - /** - * Shade from bounding rectangle to end point - */ - public static final int FILL_SHADE_CENTER = 5; - - /** - * Shade from shape outline to end point - */ - public static final int FILL_SHADE_SHAPE = 6; - - /** - * Similar to FILL_SHADE, but the fill angle - * is additionally scaled by the aspect ratio of - * the shape. If shape is square, it is the same as FILL_SHADE - */ - public static final int FILL_SHADE_SCALE = 7; - - /** - * shade to title - */ - public static final int FILL_SHADE_TITLE = 8; - - /** - * Use the background fill color/pattern - */ - public static final int FILL_BACKGROUND = 9; - - - - /** - * The shape this background applies to - */ - protected HSLFShape shape; - - /** - * Construct a Fill object for a shape. - * Fill information will be read from shape's escher properties. - * - * @param shape the shape this background applies to - */ - public Fill(HSLFShape shape){ - this.shape = shape; - } - - /** - * Returns fill type. - * Must be one of the FILL_* constants defined in this class. - * - * @return type of fill - */ - public int getFillType(){ - EscherOptRecord opt = shape.getEscherOptRecord(); - EscherSimpleProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__FILLTYPE); - return prop == null ? FILL_SOLID : prop.getPropertyValue(); - } - - /** - */ - protected void afterInsert(Sheet sh){ - EscherOptRecord opt = shape.getEscherOptRecord(); - EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); - if(p != null) { - int idx = p.getPropertyValue(); - EscherBSERecord bse = getEscherBSERecord(idx); - bse.setRef(bse.getRef() + 1); - } - } - - protected EscherBSERecord getEscherBSERecord(int idx){ - Sheet sheet = shape.getSheet(); - if(sheet == null) { - logger.log(POILogger.DEBUG, "Fill has not yet been assigned to a sheet"); - return null; - } - SlideShow ppt = sheet.getSlideShow(); - Document doc = ppt.getDocumentRecord(); - EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); - EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); - if(bstore == null) { - logger.log(POILogger.DEBUG, "EscherContainerRecord.BSTORE_CONTAINER was not found "); - return null; - } - List lst = bstore.getChildRecords(); - return (EscherBSERecord)lst.get(idx-1); - } - - /** - * Sets fill type. - * Must be one of the FILL_* constants defined in this class. - * - * @param type type of the fill - */ - public void setFillType(int type){ - EscherOptRecord opt = shape.getEscherOptRecord(); - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLTYPE, type); - } - - /** - * Foreground color - */ - public Color getForegroundColor(){ - EscherOptRecord opt = shape.getEscherOptRecord(); - EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); - - if(p != null && (p.getPropertyValue() & 0x10) == 0) return null; - - return shape.getColor(EscherProperties.FILL__FILLCOLOR, EscherProperties.FILL__FILLOPACITY, -1); - - } - - /** - * Foreground color - */ - public void setForegroundColor(Color color){ - EscherOptRecord opt = shape.getEscherOptRecord(); - if (color == null) { - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150000); - } - else { - int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb); - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011); - } - } - - /** - * Background color - */ - public Color getBackgroundColor(){ - EscherOptRecord opt = shape.getEscherOptRecord(); - EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); - - if(p != null && (p.getPropertyValue() & 0x10) == 0) return null; - - return shape.getColor(EscherProperties.FILL__FILLBACKCOLOR, EscherProperties.FILL__FILLOPACITY, -1); - } - - /** - * Background color - */ - public void setBackgroundColor(Color color){ - EscherOptRecord opt = shape.getEscherOptRecord(); - if (color == null) { - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, -1); - } - else { - int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); - HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb); - } - } - - /** - * PictureData object used in a texture, pattern of picture fill. - */ - public PictureData getPictureData(){ - EscherOptRecord opt = shape.getEscherOptRecord(); - EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); - if (p == null) return null; - - SlideShow ppt = shape.getSheet().getSlideShow(); - PictureData[] pict = ppt.getPictureData(); - Document doc = ppt.getDocumentRecord(); - - EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); - EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); - - java.util.List lst = bstore.getChildRecords(); - int idx = p.getPropertyValue(); - if (idx == 0){ - logger.log(POILogger.WARN, "no reference to picture data found "); - } else { - EscherBSERecord bse = (EscherBSERecord)lst.get(idx - 1); - for ( int i = 0; i < pict.length; i++ ) { - if (pict[i].getOffset() == bse.getOffset()){ - return pict[i]; - } - } - } - - return null; - } - - /** - * Assign picture used to fill the underlying shape. - * - * @param idx 0-based index of the picture added to this ppt by SlideShow.addPicture method. - */ - public void setPictureData(int idx){ - EscherOptRecord opt = shape.getEscherOptRecord(); - HSLFShape.setEscherProperty(opt, (short)(EscherProperties.FILL__PATTERNTEXTURE + 0x4000), idx); - if( idx != 0 ) { - if( shape.getSheet() != null ) { - EscherBSERecord bse = getEscherBSERecord(idx); - bse.setRef(bse.getRef() + 1); - } - } - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java b/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java deleted file mode 100644 index 6bf232af46..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Freeform.java +++ /dev/null @@ -1,264 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.geom.AffineTransform; -import java.awt.geom.GeneralPath; -import java.awt.geom.PathIterator; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.poi.ddf.EscherArrayProperty; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogger; - -/** - * A "Freeform" shape. - * - *

- * Shapes drawn with the "Freeform" tool have cubic bezier curve segments in the smooth sections - * and straight-line segments in the straight sections. This object closely corresponds to java.awt.geom.GeneralPath. - *

- * @author Yegor Kozlov - */ -public final class Freeform extends AutoShape { - - public static final byte[] SEGMENTINFO_MOVETO = new byte[]{0x00, 0x40}; - public static final byte[] SEGMENTINFO_LINETO = new byte[]{0x00, (byte)0xAC}; - public static final byte[] SEGMENTINFO_ESCAPE = new byte[]{0x01, 0x00}; - public static final byte[] SEGMENTINFO_ESCAPE2 = new byte[]{0x01, 0x20}; - public static final byte[] SEGMENTINFO_CUBICTO = new byte[]{0x00, (byte)0xAD}; - public static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3}; //OpenOffice inserts 0xB3 instead of 0xAD. - public static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60}; - public static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80}; - - /** - * Create a Freeform object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected Freeform(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - - } - - /** - * Create a new Freeform. This constructor is used when a new shape is created. - * - * @param parent the parent of this Shape. For example, if this text box is a cell - * in a table then the parent is Table. - */ - public Freeform(ShapeContainer parent){ - super((EscherContainerRecord)null, parent); - _escherContainer = createSpContainer(ShapeType.NOT_PRIMITIVE, parent instanceof HSLFGroupShape); - } - - /** - * Create a new Freeform. This constructor is used when a new shape is created. - * - */ - public Freeform(){ - this(null); - } - - /** - * Set the shape path - * - * @param path - */ - public void setPath(GeneralPath path) - { - Rectangle2D bounds = path.getBounds2D(); - PathIterator it = path.getPathIterator(new AffineTransform()); - - List segInfo = new ArrayList(); - List pntInfo = new ArrayList(); - boolean isClosed = false; - while (!it.isDone()) { - double[] vals = new double[6]; - int type = it.currentSegment(vals); - switch (type) { - case PathIterator.SEG_MOVETO: - pntInfo.add(new Point2D.Double(vals[0], vals[1])); - segInfo.add(SEGMENTINFO_MOVETO); - break; - case PathIterator.SEG_LINETO: - pntInfo.add(new Point2D.Double(vals[0], vals[1])); - segInfo.add(SEGMENTINFO_LINETO); - segInfo.add(SEGMENTINFO_ESCAPE); - break; - case PathIterator.SEG_CUBICTO: - pntInfo.add(new Point2D.Double(vals[0], vals[1])); - pntInfo.add(new Point2D.Double(vals[2], vals[3])); - pntInfo.add(new Point2D.Double(vals[4], vals[5])); - segInfo.add(SEGMENTINFO_CUBICTO); - segInfo.add(SEGMENTINFO_ESCAPE2); - break; - case PathIterator.SEG_QUADTO: - //TODO: figure out how to convert SEG_QUADTO into SEG_CUBICTO - logger.log(POILogger.WARN, "SEG_QUADTO is not supported"); - break; - case PathIterator.SEG_CLOSE: - pntInfo.add(pntInfo.get(0)); - segInfo.add(SEGMENTINFO_LINETO); - segInfo.add(SEGMENTINFO_ESCAPE); - segInfo.add(SEGMENTINFO_LINETO); - segInfo.add(SEGMENTINFO_CLOSE); - isClosed = true; - break; - } - - it.next(); - } - if(!isClosed) segInfo.add(SEGMENTINFO_LINETO); - segInfo.add(new byte[]{0x00, (byte)0x80}); - - EscherOptRecord opt = getEscherOptRecord(); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 0x4)); - - EscherArrayProperty verticesProp = new EscherArrayProperty((short)(EscherProperties.GEOMETRY__VERTICES + 0x4000), false, null); - verticesProp.setNumberOfElementsInArray(pntInfo.size()); - verticesProp.setNumberOfElementsInMemory(pntInfo.size()); - verticesProp.setSizeOfElements(0xFFF0); - for (int i = 0; i < pntInfo.size(); i++) { - Point2D.Double pnt = pntInfo.get(i); - byte[] data = new byte[4]; - LittleEndian.putShort(data, 0, (short)((pnt.getX() - bounds.getX())*MASTER_DPI/POINT_DPI)); - LittleEndian.putShort(data, 2, (short)((pnt.getY() - bounds.getY())*MASTER_DPI/POINT_DPI)); - verticesProp.setElement(i, data); - } - opt.addEscherProperty(verticesProp); - - EscherArrayProperty segmentsProp = new EscherArrayProperty((short)(EscherProperties.GEOMETRY__SEGMENTINFO + 0x4000), false, null); - segmentsProp.setNumberOfElementsInArray(segInfo.size()); - segmentsProp.setNumberOfElementsInMemory(segInfo.size()); - segmentsProp.setSizeOfElements(0x2); - for (int i = 0; i < segInfo.size(); i++) { - byte[] seg = segInfo.get(i); - segmentsProp.setElement(i, seg); - } - opt.addEscherProperty(segmentsProp); - - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, (int)(bounds.getWidth()*MASTER_DPI/POINT_DPI))); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, (int)(bounds.getHeight()*MASTER_DPI/POINT_DPI))); - - opt.sortProperties(); - - setAnchor(bounds); - } - - /** - * Gets the freeform path - * - * @return the freeform path - */ - public GeneralPath getPath(){ - EscherOptRecord opt = getEscherOptRecord(); - opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 0x4)); - - EscherArrayProperty verticesProp = getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__VERTICES + 0x4000)); - if(verticesProp == null) verticesProp = getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES); - - EscherArrayProperty segmentsProp = getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__SEGMENTINFO + 0x4000)); - if(segmentsProp == null) segmentsProp = getEscherProperty(opt, EscherProperties.GEOMETRY__SEGMENTINFO); - - //sanity check - if(verticesProp == null) { - logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__VERTICES "); - return null; - } - if(segmentsProp == null) { - logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__SEGMENTINFO "); - return null; - } - - GeneralPath path = new GeneralPath(); - int numPoints = verticesProp.getNumberOfElementsInArray(); - int numSegments = segmentsProp.getNumberOfElementsInArray(); - for (int i = 0, j = 0; i < numSegments && j < numPoints; i++) { - byte[] elem = segmentsProp.getElement(i); - if(Arrays.equals(elem, SEGMENTINFO_MOVETO)){ - byte[] p = verticesProp.getElement(j++); - short x = LittleEndian.getShort(p, 0); - short y = LittleEndian.getShort(p, 2); - path.moveTo( - ((float)x*POINT_DPI/MASTER_DPI), - ((float)y*POINT_DPI/MASTER_DPI)); - } else if (Arrays.equals(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){ - i++; - byte[] p1 = verticesProp.getElement(j++); - short x1 = LittleEndian.getShort(p1, 0); - short y1 = LittleEndian.getShort(p1, 2); - byte[] p2 = verticesProp.getElement(j++); - short x2 = LittleEndian.getShort(p2, 0); - short y2 = LittleEndian.getShort(p2, 2); - byte[] p3 = verticesProp.getElement(j++); - short x3 = LittleEndian.getShort(p3, 0); - short y3 = LittleEndian.getShort(p3, 2); - path.curveTo( - ((float)x1*POINT_DPI/MASTER_DPI), ((float)y1*POINT_DPI/MASTER_DPI), - ((float)x2*POINT_DPI/MASTER_DPI), ((float)y2*POINT_DPI/MASTER_DPI), - ((float)x3*POINT_DPI/MASTER_DPI), ((float)y3*POINT_DPI/MASTER_DPI)); - - } else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){ - i++; - byte[] pnext = segmentsProp.getElement(i); - if(Arrays.equals(pnext, SEGMENTINFO_ESCAPE)){ - if(j + 1 < numPoints){ - byte[] p = verticesProp.getElement(j++); - short x = LittleEndian.getShort(p, 0); - short y = LittleEndian.getShort(p, 2); - path.lineTo( - ((float)x*POINT_DPI/MASTER_DPI), ((float)y*POINT_DPI/MASTER_DPI)); - } - } else if (Arrays.equals(pnext, SEGMENTINFO_CLOSE)){ - path.closePath(); - } - } - } - return path; - } - - public java.awt.Shape getOutline(){ - GeneralPath path = getPath(); - if(path == null) { - // return empty path if either GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188 - return new GeneralPath(); - } - - Rectangle2D anchor = getAnchor2D(); - Rectangle2D bounds = path.getBounds2D(); - AffineTransform at = new AffineTransform(); - at.translate(anchor.getX(), anchor.getY()); - at.scale( - anchor.getWidth()/bounds.getWidth(), - anchor.getHeight()/bounds.getHeight() - ); - return at.createTransformedShape(path); - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFAutoShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFAutoShape.java new file mode 100644 index 0000000000..1f74f2ceb5 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFAutoShape.java @@ -0,0 +1,123 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import org.apache.poi.ddf.*; +import org.apache.poi.sl.draw.geom.CustomGeometry; +import org.apache.poi.sl.draw.geom.Guide; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.util.POILogger; + +import java.awt.geom.Rectangle2D; +import java.util.Iterator; + +/** + * Represents an AutoShape. + *

+ * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments. + * See {@link ShapeTypes} + *

+ * + * @author Yegor Kozlov + */ +public class HSLFAutoShape extends HSLFTextShape implements AutoShape { + + protected HSLFAutoShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + } + + public HSLFAutoShape(ShapeType type, ShapeContainer parent){ + super(null, parent); + _escherContainer = createSpContainer(type, parent instanceof HSLFGroupShape); + } + + public HSLFAutoShape(ShapeType type){ + this(type, null); + } + + protected EscherContainerRecord createSpContainer(ShapeType shapeType, boolean isChild){ + _escherContainer = super.createSpContainer(isChild); + + setShapeType(shapeType); + + //set default properties for an autoshape + setEscherProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000); + setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); + setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); + setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000); + setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100010); + setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001); + setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80008); + setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); + + return _escherContainer; + } + + protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){ + setVerticalAlignment(HSLFTextBox.AnchorMiddle); + setHorizontalAlignment(HSLFTextBox.AlignCenter); + setWordWrap(HSLFTextBox.WrapNone); + } + + /** + * Gets adjust value which controls smart resizing of the auto-shape. + * + *

+ * The adjustment values are given in shape coordinates: + * the origin is at the top-left, positive-x is to the right, positive-y is down. + * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). + *

+ * + * @param idx the adjust index in the [0, 9] range + * @return the adjustment value + */ + public int getAdjustmentValue(int idx){ + if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); + + return getEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx)); + } + + /** + * Sets adjust value which controls smart resizing of the auto-shape. + * + *

+ * The adjustment values are given in shape coordinates: + * the origin is at the top-left, positive-x is to the right, positive-y is down. + * The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant). + *

+ * + * @param idx the adjust index in the [0, 9] range + * @param val the adjustment value + */ + public void setAdjustmentValue(int idx, int val){ + if(idx < 0 || idx > 9) throw new IllegalArgumentException("The index of an adjustment value must be in the [0, 9] range"); + + setEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx), val); + } + + public java.awt.Shape getOutline(){ + ShapeOutline outline = AutoShapes.getShapeOutline(getShapeType()); + Rectangle2D anchor = getLogicalAnchor2D(); + if(outline == null){ + logger.log(POILogger.WARN, "Outline not found for " + getShapeType().nativeName); + return anchor; + } + java.awt.Shape shape = outline.getOutline(this); + return AutoShapes.transform(shape, anchor); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFBackground.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFBackground.java new file mode 100644 index 0000000000..8d581f5f35 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFBackground.java @@ -0,0 +1,38 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.sl.usermodel.Background; +import org.apache.poi.sl.usermodel.ShapeContainer; + +/** + * Background shape + * + * @author Yegor Kozlov + */ +public final class HSLFBackground extends HSLFShape implements Background { + + protected HSLFBackground(EscherContainerRecord escherRecord, ShapeContainer parent) { + super(escherRecord, parent); + } + + protected EscherContainerRecord createSpContainer(boolean isChild) { + return null; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFill.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFill.java new file mode 100644 index 0000000000..14846e1ea0 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFill.java @@ -0,0 +1,312 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.Color; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.List; + +import org.apache.poi.ddf.*; +import org.apache.poi.hslf.record.Document; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; +import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * Represents functionality provided by the 'Fill Effects' dialog in PowerPoint. + * + * @author Yegor Kozlov + */ +public final class HSLFFill { + // For logging + protected POILogger logger = POILogFactory.getLogger(this.getClass()); + + /** + * Fill with a solid color + */ + public static final int FILL_SOLID = 0; + + /** + * Fill with a pattern (bitmap) + */ + public static final int FILL_PATTERN = 1; + + /** + * A texture (pattern with its own color map) + */ + public static final int FILL_TEXTURE = 2; + + /** + * Center a picture in the shape + */ + public static final int FILL_PICTURE = 3; + + /** + * Shade from start to end points + */ + public static final int FILL_SHADE = 4; + + /** + * Shade from bounding rectangle to end point + */ + public static final int FILL_SHADE_CENTER = 5; + + /** + * Shade from shape outline to end point + */ + public static final int FILL_SHADE_SHAPE = 6; + + /** + * Similar to FILL_SHADE, but the fill angle + * is additionally scaled by the aspect ratio of + * the shape. If shape is square, it is the same as FILL_SHADE + */ + public static final int FILL_SHADE_SCALE = 7; + + /** + * shade to title + */ + public static final int FILL_SHADE_TITLE = 8; + + /** + * Use the background fill color/pattern + */ + public static final int FILL_BACKGROUND = 9; + + + + /** + * The shape this background applies to + */ + protected HSLFShape shape; + + /** + * Construct a Fill object for a shape. + * Fill information will be read from shape's escher properties. + * + * @param shape the shape this background applies to + */ + public HSLFFill(HSLFShape shape){ + this.shape = shape; + } + + + public FillStyle getFillStyle() { + return new FillStyle() { + public PaintStyle getPaint() { + switch (getFillType()) { + case FILL_SOLID: { + return new SolidPaint() { + public ColorStyle getSolidColor() { + return new ColorStyle() { + public Color getColor() { return getForegroundColor(); } + public int getAlpha() { return -1; } + public int getLumOff() { return -1; } + public int getLumMod() { return -1; } + public int getShade() { return -1; } + public int getTint() { return -1; } + }; + } + }; + } + case FILL_PICTURE: { + return new TexturePaint() { + final HSLFPictureData pd = getPictureData(); + + public InputStream getImageData() { + return new ByteArrayInputStream(pd.getData()); + } + + public String getContentType() { + return pd.getContentType(); + } + + public int getAlpha() { + return (int)(shape.getAlpha(EscherProperties.FILL__FILLOPACITY)*100000.0); + } + }; + } + default: + logger.log(POILogger.WARN, "unsuported fill type: " + getFillType()); + break; + } + return PaintStyle.TRANSPARENT_PAINT; + } + }; + } + + /** + * Returns fill type. + * Must be one of the FILL_* constants defined in this class. + * + * @return type of fill + */ + public int getFillType(){ + EscherOptRecord opt = shape.getEscherOptRecord(); + EscherSimpleProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__FILLTYPE); + return prop == null ? FILL_SOLID : prop.getPropertyValue(); + } + + /** + */ + protected void afterInsert(HSLFSheet sh){ + EscherOptRecord opt = shape.getEscherOptRecord(); + EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); + if(p != null) { + int idx = p.getPropertyValue(); + EscherBSERecord bse = getEscherBSERecord(idx); + bse.setRef(bse.getRef() + 1); + } + } + + protected EscherBSERecord getEscherBSERecord(int idx){ + HSLFSheet sheet = shape.getSheet(); + if(sheet == null) { + logger.log(POILogger.DEBUG, "Fill has not yet been assigned to a sheet"); + return null; + } + HSLFSlideShow ppt = sheet.getSlideShow(); + Document doc = ppt.getDocumentRecord(); + EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); + EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); + if(bstore == null) { + logger.log(POILogger.DEBUG, "EscherContainerRecord.BSTORE_CONTAINER was not found "); + return null; + } + List lst = bstore.getChildRecords(); + return (EscherBSERecord)lst.get(idx-1); + } + + /** + * Sets fill type. + * Must be one of the FILL_* constants defined in this class. + * + * @param type type of the fill + */ + public void setFillType(int type){ + EscherOptRecord opt = shape.getEscherOptRecord(); + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLTYPE, type); + } + + /** + * Foreground color + */ + public Color getForegroundColor(){ + EscherOptRecord opt = shape.getEscherOptRecord(); + EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); + + if(p != null && (p.getPropertyValue() & 0x10) == 0) return null; + + return shape.getColor(EscherProperties.FILL__FILLCOLOR, EscherProperties.FILL__FILLOPACITY, -1); + + } + + /** + * Foreground color + */ + public void setForegroundColor(Color color){ + EscherOptRecord opt = shape.getEscherOptRecord(); + if (color == null) { + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150000); + } + else { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb); + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150011); + } + } + + /** + * Background color + */ + public Color getBackgroundColor(){ + EscherOptRecord opt = shape.getEscherOptRecord(); + EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST); + + if(p != null && (p.getPropertyValue() & 0x10) == 0) return null; + + return shape.getColor(EscherProperties.FILL__FILLBACKCOLOR, EscherProperties.FILL__FILLOPACITY, -1); + } + + /** + * Background color + */ + public void setBackgroundColor(Color color){ + EscherOptRecord opt = shape.getEscherOptRecord(); + if (color == null) { + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, -1); + } + else { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); + HSLFShape.setEscherProperty(opt, EscherProperties.FILL__FILLBACKCOLOR, rgb); + } + } + + /** + * PictureData object used in a texture, pattern of picture fill. + */ + public HSLFPictureData getPictureData(){ + EscherOptRecord opt = shape.getEscherOptRecord(); + EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); + if (p == null) return null; + + HSLFSlideShow ppt = shape.getSheet().getSlideShow(); + HSLFPictureData[] pict = ppt.getPictureData(); + Document doc = ppt.getDocumentRecord(); + + EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); + EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); + + java.util.List lst = bstore.getChildRecords(); + int idx = p.getPropertyValue(); + if (idx == 0){ + logger.log(POILogger.WARN, "no reference to picture data found "); + } else { + EscherBSERecord bse = (EscherBSERecord)lst.get(idx - 1); + for ( int i = 0; i < pict.length; i++ ) { + if (pict[i].getOffset() == bse.getOffset()){ + return pict[i]; + } + } + } + + return null; + } + + /** + * Assign picture used to fill the underlying shape. + * + * @param idx 0-based index of the picture added to this ppt by SlideShow.addPicture method. + */ + public void setPictureData(int idx){ + EscherOptRecord opt = shape.getEscherOptRecord(); + HSLFShape.setEscherProperty(opt, (short)(EscherProperties.FILL__PATTERNTEXTURE + 0x4000), idx); + if( idx != 0 ) { + if( shape.getSheet() != null ) { + EscherBSERecord bse = getEscherBSERecord(idx); + bse.setRef(bse.getRef() + 1); + } + } + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFreeformShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFreeformShape.java new file mode 100644 index 0000000000..685e2dad2f --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFFreeformShape.java @@ -0,0 +1,264 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.geom.AffineTransform; +import java.awt.geom.GeneralPath; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.poi.ddf.EscherArrayProperty; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogger; + +/** + * A "Freeform" shape. + * + *

+ * Shapes drawn with the "Freeform" tool have cubic bezier curve segments in the smooth sections + * and straight-line segments in the straight sections. This object closely corresponds to java.awt.geom.GeneralPath. + *

+ * @author Yegor Kozlov + */ +public final class HSLFFreeformShape extends HSLFAutoShape { + + public static final byte[] SEGMENTINFO_MOVETO = new byte[]{0x00, 0x40}; + public static final byte[] SEGMENTINFO_LINETO = new byte[]{0x00, (byte)0xAC}; + public static final byte[] SEGMENTINFO_ESCAPE = new byte[]{0x01, 0x00}; + public static final byte[] SEGMENTINFO_ESCAPE2 = new byte[]{0x01, 0x20}; + public static final byte[] SEGMENTINFO_CUBICTO = new byte[]{0x00, (byte)0xAD}; + public static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3}; //OpenOffice inserts 0xB3 instead of 0xAD. + public static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60}; + public static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80}; + + /** + * Create a Freeform object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected HSLFFreeformShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + + } + + /** + * Create a new Freeform. This constructor is used when a new shape is created. + * + * @param parent the parent of this Shape. For example, if this text box is a cell + * in a table then the parent is Table. + */ + public HSLFFreeformShape(ShapeContainer parent){ + super((EscherContainerRecord)null, parent); + _escherContainer = createSpContainer(ShapeType.NOT_PRIMITIVE, parent instanceof HSLFGroupShape); + } + + /** + * Create a new Freeform. This constructor is used when a new shape is created. + * + */ + public HSLFFreeformShape(){ + this(null); + } + + /** + * Set the shape path + * + * @param path + */ + public void setPath(GeneralPath path) + { + Rectangle2D bounds = path.getBounds2D(); + PathIterator it = path.getPathIterator(new AffineTransform()); + + List segInfo = new ArrayList(); + List pntInfo = new ArrayList(); + boolean isClosed = false; + while (!it.isDone()) { + double[] vals = new double[6]; + int type = it.currentSegment(vals); + switch (type) { + case PathIterator.SEG_MOVETO: + pntInfo.add(new Point2D.Double(vals[0], vals[1])); + segInfo.add(SEGMENTINFO_MOVETO); + break; + case PathIterator.SEG_LINETO: + pntInfo.add(new Point2D.Double(vals[0], vals[1])); + segInfo.add(SEGMENTINFO_LINETO); + segInfo.add(SEGMENTINFO_ESCAPE); + break; + case PathIterator.SEG_CUBICTO: + pntInfo.add(new Point2D.Double(vals[0], vals[1])); + pntInfo.add(new Point2D.Double(vals[2], vals[3])); + pntInfo.add(new Point2D.Double(vals[4], vals[5])); + segInfo.add(SEGMENTINFO_CUBICTO); + segInfo.add(SEGMENTINFO_ESCAPE2); + break; + case PathIterator.SEG_QUADTO: + //TODO: figure out how to convert SEG_QUADTO into SEG_CUBICTO + logger.log(POILogger.WARN, "SEG_QUADTO is not supported"); + break; + case PathIterator.SEG_CLOSE: + pntInfo.add(pntInfo.get(0)); + segInfo.add(SEGMENTINFO_LINETO); + segInfo.add(SEGMENTINFO_ESCAPE); + segInfo.add(SEGMENTINFO_LINETO); + segInfo.add(SEGMENTINFO_CLOSE); + isClosed = true; + break; + } + + it.next(); + } + if(!isClosed) segInfo.add(SEGMENTINFO_LINETO); + segInfo.add(new byte[]{0x00, (byte)0x80}); + + EscherOptRecord opt = getEscherOptRecord(); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 0x4)); + + EscherArrayProperty verticesProp = new EscherArrayProperty((short)(EscherProperties.GEOMETRY__VERTICES + 0x4000), false, null); + verticesProp.setNumberOfElementsInArray(pntInfo.size()); + verticesProp.setNumberOfElementsInMemory(pntInfo.size()); + verticesProp.setSizeOfElements(0xFFF0); + for (int i = 0; i < pntInfo.size(); i++) { + Point2D.Double pnt = pntInfo.get(i); + byte[] data = new byte[4]; + LittleEndian.putShort(data, 0, (short)((pnt.getX() - bounds.getX())*MASTER_DPI/POINT_DPI)); + LittleEndian.putShort(data, 2, (short)((pnt.getY() - bounds.getY())*MASTER_DPI/POINT_DPI)); + verticesProp.setElement(i, data); + } + opt.addEscherProperty(verticesProp); + + EscherArrayProperty segmentsProp = new EscherArrayProperty((short)(EscherProperties.GEOMETRY__SEGMENTINFO + 0x4000), false, null); + segmentsProp.setNumberOfElementsInArray(segInfo.size()); + segmentsProp.setNumberOfElementsInMemory(segInfo.size()); + segmentsProp.setSizeOfElements(0x2); + for (int i = 0; i < segInfo.size(); i++) { + byte[] seg = segInfo.get(i); + segmentsProp.setElement(i, seg); + } + opt.addEscherProperty(segmentsProp); + + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__RIGHT, (int)(bounds.getWidth()*MASTER_DPI/POINT_DPI))); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__BOTTOM, (int)(bounds.getHeight()*MASTER_DPI/POINT_DPI))); + + opt.sortProperties(); + + setAnchor(bounds); + } + + /** + * Gets the freeform path + * + * @return the freeform path + */ + public GeneralPath getPath(){ + EscherOptRecord opt = getEscherOptRecord(); + opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 0x4)); + + EscherArrayProperty verticesProp = getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__VERTICES + 0x4000)); + if(verticesProp == null) verticesProp = getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES); + + EscherArrayProperty segmentsProp = getEscherProperty(opt, (short)(EscherProperties.GEOMETRY__SEGMENTINFO + 0x4000)); + if(segmentsProp == null) segmentsProp = getEscherProperty(opt, EscherProperties.GEOMETRY__SEGMENTINFO); + + //sanity check + if(verticesProp == null) { + logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__VERTICES "); + return null; + } + if(segmentsProp == null) { + logger.log(POILogger.WARN, "Freeform is missing GEOMETRY__SEGMENTINFO "); + return null; + } + + GeneralPath path = new GeneralPath(); + int numPoints = verticesProp.getNumberOfElementsInArray(); + int numSegments = segmentsProp.getNumberOfElementsInArray(); + for (int i = 0, j = 0; i < numSegments && j < numPoints; i++) { + byte[] elem = segmentsProp.getElement(i); + if(Arrays.equals(elem, SEGMENTINFO_MOVETO)){ + byte[] p = verticesProp.getElement(j++); + short x = LittleEndian.getShort(p, 0); + short y = LittleEndian.getShort(p, 2); + path.moveTo( + ((float)x*POINT_DPI/MASTER_DPI), + ((float)y*POINT_DPI/MASTER_DPI)); + } else if (Arrays.equals(elem, SEGMENTINFO_CUBICTO) || Arrays.equals(elem, SEGMENTINFO_CUBICTO2)){ + i++; + byte[] p1 = verticesProp.getElement(j++); + short x1 = LittleEndian.getShort(p1, 0); + short y1 = LittleEndian.getShort(p1, 2); + byte[] p2 = verticesProp.getElement(j++); + short x2 = LittleEndian.getShort(p2, 0); + short y2 = LittleEndian.getShort(p2, 2); + byte[] p3 = verticesProp.getElement(j++); + short x3 = LittleEndian.getShort(p3, 0); + short y3 = LittleEndian.getShort(p3, 2); + path.curveTo( + ((float)x1*POINT_DPI/MASTER_DPI), ((float)y1*POINT_DPI/MASTER_DPI), + ((float)x2*POINT_DPI/MASTER_DPI), ((float)y2*POINT_DPI/MASTER_DPI), + ((float)x3*POINT_DPI/MASTER_DPI), ((float)y3*POINT_DPI/MASTER_DPI)); + + } else if (Arrays.equals(elem, SEGMENTINFO_LINETO)){ + i++; + byte[] pnext = segmentsProp.getElement(i); + if(Arrays.equals(pnext, SEGMENTINFO_ESCAPE)){ + if(j + 1 < numPoints){ + byte[] p = verticesProp.getElement(j++); + short x = LittleEndian.getShort(p, 0); + short y = LittleEndian.getShort(p, 2); + path.lineTo( + ((float)x*POINT_DPI/MASTER_DPI), ((float)y*POINT_DPI/MASTER_DPI)); + } + } else if (Arrays.equals(pnext, SEGMENTINFO_CLOSE)){ + path.closePath(); + } + } + } + return path; + } + + public java.awt.Shape getOutline(){ + GeneralPath path = getPath(); + if(path == null) { + // return empty path if either GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188 + return new GeneralPath(); + } + + Rectangle2D anchor = getAnchor2D(); + Rectangle2D bounds = path.getBounds2D(); + AffineTransform at = new AffineTransform(); + at.translate(anchor.getX(), anchor.getY()); + at.scale( + anchor.getWidth()/bounds.getWidth(), + anchor.getHeight()/bounds.getHeight() + ); + return at.createTransformedShape(path); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFGroupShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFGroupShape.java index 336f11743a..64d4de28b4 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFGroupShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFGroupShape.java @@ -177,7 +177,7 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer { + public HSLFMasterSheet(SheetContainer container, int sheetNo){ + super(container, sheetNo); + } + + /** + * Pickup a style attribute from the master. + * This is the "workhorse" which returns the default style attrubutes. + */ + public abstract TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) ; + + + /** + * Checks if the shape is a placeholder. + * (placeholders aren't normal shapes, they are visible only in the Edit Master mode) + * + * + * @return true if the shape is a placeholder + */ + public static boolean isPlaceholder(HSLFShape shape){ + if(!(shape instanceof HSLFTextShape)) return false; + + HSLFTextShape tx = (HSLFTextShape)shape; + return tx.getPlaceholderAtom() != null; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFNotes.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFNotes.java new file mode 100644 index 0000000000..2a7698d21c --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFNotes.java @@ -0,0 +1,75 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.util.Arrays; +import java.util.List; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.Notes; + +/** + * This class represents a slide's notes in a PowerPoint Document. It + * allows access to the text within, and the layout. For now, it only + * does the text side of things though + * + * @author Nick Burch + */ + +public final class HSLFNotes extends HSLFSheet implements Notes { + private HSLFTextParagraph[] _runs; + + /** + * Constructs a Notes Sheet from the given Notes record. + * Initialises TextRuns, to provide easier access to the text + * + * @param notes the Notes record to read from + */ + public HSLFNotes(org.apache.poi.hslf.record.Notes notes) { + super(notes, notes.getNotesAtom().getSlideID()); + + // Now, build up TextRuns from pairs of TextHeaderAtom and + // one of TextBytesAtom or TextCharsAtom, found inside + // EscherTextboxWrapper's in the PPDrawing + _runs = findTextRuns(getPPDrawing()); + + // Set the sheet on each TextRun + for (HSLFTextParagraph tp : _runs) { + tp.supplySheet(this); + } + } + + /** + * Returns an array of all the TextRuns found + */ + public HSLFTextParagraph[] getTextRuns() { + return _runs; + } + + @Override + public List getTextParagraphs() { + return Arrays.asList(_runs); + } + + /** + * Return null - Notes Masters are not yet supported + */ + public HSLFMasterSheet getMasterSheet() { + return null; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFPictureShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFPictureShape.java new file mode 100644 index 0000000000..e6b72a60fb --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFPictureShape.java @@ -0,0 +1,302 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.List; + +import javax.imageio.ImageIO; + +import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.ddf.EscherComplexProperty; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hslf.blip.Bitmap; +import org.apache.poi.hslf.record.Document; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.util.POILogger; +import org.apache.poi.util.StringUtil; +import org.apache.poi.util.Units; + + +/** + * Represents a picture in a PowerPoint document. + * + * @author Yegor Kozlov + */ +public class HSLFPictureShape extends HSLFSimpleShape { + + /** + * Windows Enhanced Metafile (EMF) + */ + public static final int EMF = 2; + + /** + * Windows Metafile (WMF) + */ + public static final int WMF = 3; + + /** + * Macintosh PICT + */ + public static final int PICT = 4; + + /** + * JPEG + */ + public static final int JPEG = 5; + + /** + * PNG + */ + public static final int PNG = 6; + + /** + * Windows DIB (BMP) + */ + public static final byte DIB = 7; + + /** + * Create a new Picture + * + * @param idx the index of the picture + */ + public HSLFPictureShape(int idx){ + this(idx, null); + } + + /** + * Create a new Picture + * + * @param idx the index of the picture + * @param parent the parent shape + */ + public HSLFPictureShape(int idx, ShapeContainer parent) { + super(null, parent); + _escherContainer = createSpContainer(idx, parent instanceof HSLFGroupShape); + } + + /** + * Create a Picture object + * + * @param escherRecord the EscherSpContainer record which holds information about + * this picture in the Slide + * @param parent the parent shape of this picture + */ + protected HSLFPictureShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + } + + /** + * Returns index associated with this picture. + * Index starts with 1 and points to a EscherBSE record which + * holds information about this picture. + * + * @return the index to this picture (1 based). + */ + public int getPictureIndex(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.BLIP__BLIPTODISPLAY); + return prop == null ? 0 : prop.getPropertyValue(); + } + + /** + * Create a new Picture and populate the inital structure of the EscherSp record which holds information about this picture. + + * @param idx the index of the picture which refers to EscherBSE container. + * @return the create Picture object + */ + protected EscherContainerRecord createSpContainer(int idx, boolean isChild) { + _escherContainer = super.createSpContainer(isChild); + _escherContainer.setOptions((short)15); + + EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); + spRecord.setOptions((short)((ShapeType.FRAME.nativeId << 4) | 0x2)); + + //set default properties for a picture + EscherOptRecord opt = getEscherOptRecord(); + setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x800080); + + //another weird feature of powerpoint: for picture id we must add 0x4000. + setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx); + + return _escherContainer; + } + + /** + * Resize this picture to the default size. + * For PNG and JPEG resizes the image to 100%, + * for other types sets the default size of 200x200 pixels. + */ + public void setDefaultSize(){ + HSLFPictureData pict = getPictureData(); + if (pict instanceof Bitmap){ + BufferedImage img = null; + try { + img = ImageIO.read(new ByteArrayInputStream(pict.getData())); + } + catch (IOException e){} + catch (NegativeArraySizeException ne) {} + + if(img != null) { + // Valid image, set anchor from it + setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()*POINT_DPI/PIXEL_DPI, img.getHeight()*POINT_DPI/PIXEL_DPI)); + } else { + // Invalid image, go with the default metafile size + setAnchor(new java.awt.Rectangle(0, 0, 200, 200)); + } + } else { + //default size of a metafile picture is 200x200 + setAnchor(new java.awt.Rectangle(50, 50, 200, 200)); + } + } + + /** + * Returns the picture data for this picture. + * + * @return the picture data for this picture. + */ + public HSLFPictureData getPictureData(){ + HSLFSlideShow ppt = getSheet().getSlideShow(); + HSLFPictureData[] pict = ppt.getPictureData(); + + EscherBSERecord bse = getEscherBSERecord(); + if (bse == null){ + logger.log(POILogger.ERROR, "no reference to picture data found "); + } else { + for ( int i = 0; i < pict.length; i++ ) { + if (pict[i].getOffset() == bse.getOffset()){ + return pict[i]; + } + } + logger.log(POILogger.ERROR, "no picture found for our BSE offset " + bse.getOffset()); + } + return null; + } + + protected EscherBSERecord getEscherBSERecord(){ + HSLFSlideShow ppt = getSheet().getSlideShow(); + Document doc = ppt.getDocumentRecord(); + EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); + EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); + if(bstore == null) { + logger.log(POILogger.DEBUG, "EscherContainerRecord.BSTORE_CONTAINER was not found "); + return null; + } + List lst = bstore.getChildRecords(); + int idx = getPictureIndex(); + if (idx == 0){ + logger.log(POILogger.DEBUG, "picture index was not found, returning "); + return null; + } + return (EscherBSERecord)lst.get(idx-1); + } + + /** + * Name of this picture. + * + * @return name of this picture + */ + public String getPictureName(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherComplexProperty prop = getEscherProperty(opt, EscherProperties.BLIP__BLIPFILENAME); + if (prop == null) return null; + String name = StringUtil.getFromUnicodeLE(prop.getComplexData()); + return name.trim(); + } + + /** + * Name of this picture. + * + * @param name of this picture + */ + public void setPictureName(String name){ + EscherOptRecord opt = getEscherOptRecord(); + byte[] data = StringUtil.getToUnicodeLE(name + '\u0000'); + EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, false, data); + opt.addEscherProperty(prop); + } + + /** + * By default set the orininal image size + */ + protected void afterInsert(HSLFSheet sh){ + super.afterInsert(sh); + + EscherBSERecord bse = getEscherBSERecord(); + bse.setRef(bse.getRef() + 1); + + java.awt.Rectangle anchor = getAnchor(); + if (anchor.equals(new java.awt.Rectangle())){ + setDefaultSize(); + } + } + + public void draw(Graphics2D graphics){ + AffineTransform at = graphics.getTransform(); + ShapePainter.paint(this, graphics); + + HSLFPictureData data = getPictureData(); + if(data != null) data.draw(graphics, this); + + graphics.setTransform(at); + } + + /** + * Returns the clipping values as percent ratio relatively to the image size. + * The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, + * i.e. the size of the already clipped image + * + * @return the clipping as insets converted/scaled to 100000 (=100%) + */ + public Insets getBlipClip() { + EscherOptRecord opt = getEscherOptRecord(); + + double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); + double bottom = getFractProp(opt, EscherProperties.BLIP__CROPFROMBOTTOM); + double left = getFractProp(opt, EscherProperties.BLIP__CROPFROMLEFT); + double right = getFractProp(opt, EscherProperties.BLIP__CROPFROMRIGHT); + + // if all crop values are zero (the default) then no crop rectangle is set, return null + return (top==0 && bottom==0 && left==0 && right==0) + ? null + : new Insets((int)(top*100000), (int)(left*100000), (int)(bottom*100000), (int)(right*100000)); + } + + /** + * @return the fractional property or 0 if not defined + */ + private static double getFractProp(EscherOptRecord opt, short propertyId) { + EscherSimpleProperty prop = getEscherProperty(opt, propertyId); + if (prop == null) return 0; + int fixedPoint = prop.getPropertyValue(); + return Units.fixedPointToDouble(fixedPoint); + } +} \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFShape.java index c673cae2de..4e2229982e 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFShape.java @@ -17,17 +17,15 @@ package org.apache.poi.hslf.model; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.util.Iterator; + import org.apache.poi.ddf.*; import org.apache.poi.hslf.record.ColorSchemeAtom; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.Units; - -import java.util.*; -import java.awt.*; -import java.awt.geom.Rectangle2D; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.util.*; /** *

@@ -45,7 +43,7 @@ import java.awt.geom.Rectangle2D; * * @author Yegor Kozlov */ -public abstract class HSLFShape implements org.apache.poi.sl.usermodel.Shape { +public abstract class HSLFShape implements Shape { // For logging protected POILogger logger = POILogFactory.getLogger(this.getClass()); @@ -90,12 +88,12 @@ public abstract class HSLFShape implements org.apache.poi.sl.usermodel.ShapeSheet this shape belongs to */ - protected Sheet _sheet; + protected HSLFSheet _sheet; /** * Fill */ - protected Fill _fill; + protected HSLFFill _fill; /** * Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document. @@ -336,7 +334,7 @@ public abstract class HSLFShape implements org.apache.poi.sl.usermodel.ShapeSlideShow this shape belongs to */ - public Sheet getSheet(){ + public HSLFSheet getSheet(){ return _sheet; } @@ -354,7 +352,7 @@ public abstract class HSLFShape implements org.apache.poi.sl.usermodel.Shape> 24) & 0xFF; int b = (val >> 16) & 0xFF; @@ -446,11 +449,16 @@ public abstract class HSLFShape implements org.apache.poi.sl.usermodel.Shape { + private static POILogger logger = POILogFactory.getLogger(HSLFSheet.class); + + /** + * The SlideShow we belong to + */ + private HSLFSlideShow _slideShow; + + /** + * Sheet background + */ + private HSLFBackground _background; + + /** + * Record container that holds sheet data. + * For slides it is org.apache.poi.hslf.record.Slide, + * for notes it is org.apache.poi.hslf.record.Notes, + * for slide masters it is org.apache.poi.hslf.record.SlideMaster, etc. + */ + private SheetContainer _container; + + private int _sheetNo; + + public HSLFSheet(SheetContainer container, int sheetNo) { + _container = container; + _sheetNo = sheetNo; + } + + /** + * Returns an array of all the TextRuns in the sheet. + */ + public abstract HSLFTextParagraph[] getTextRuns(); + + /** + * Returns the (internal, RefID based) sheet number, as used + * to in PersistPtr stuff. + */ + public int _getSheetRefId() { + return _container.getSheetId(); + } + + /** + * Returns the (internal, SlideIdentifier based) sheet number, as used + * to reference this sheet from other records. + */ + public int _getSheetNumber() { + return _sheetNo; + } + + /** + * Fetch the PPDrawing from the underlying record + */ + protected PPDrawing getPPDrawing() { + return _container.getPPDrawing(); + } + + /** + * Fetch the SlideShow we're attached to + */ + public HSLFSlideShow getSlideShow() { + return _slideShow; + } + + /** + * Return record container for this sheet + */ + public SheetContainer getSheetContainer() { + return _container; + } + + /** + * Set the SlideShow we're attached to. + * Also passes it on to our child RichTextRuns + */ + public void setSlideShow(HSLFSlideShow ss) { + _slideShow = ss; + HSLFTextParagraph[] trs = getTextRuns(); + if (trs == null) return; + for (HSLFTextParagraph tp : trs) { + tp.supplySheet(this); + } + } + + + /** + * For a given PPDrawing, grab all the TextRuns + */ + public static HSLFTextParagraph[] findTextRuns(PPDrawing ppdrawing) { + final List runsV = new ArrayList(); + final EscherTextboxWrapper[] wrappers = ppdrawing.getTextboxWrappers(); + for (int i = 0; i < wrappers.length; i++) { + int s1 = runsV.size(); + + // propagate parents to parent-aware records + RecordContainer.handleParentAwareRecords(wrappers[i]); + findTextRuns(wrappers[i], runsV); + int s2 = runsV.size(); + if (s2 != s1){ + HSLFTextParagraph t = runsV.get(runsV.size()-1); + t.setShapeId(wrappers[i].getShapeId()); + } + } + return runsV.toArray(new HSLFTextParagraph[runsV.size()]); + } + /** + * Scans through the supplied record array, looking for + * a TextHeaderAtom followed by one of a TextBytesAtom or + * a TextCharsAtom. Builds up TextRuns from these + * + * @param records the records to build from + * @param found vector to add any found to + */ + protected static void findTextParagraphs(final Record[] records, final List found) { + findTextRuns(records, found, null); + } + /** + * Scans through the supplied record array, looking for + * a TextHeaderAtom followed by one of a TextBytesAtom or + * a TextCharsAtom. Builds up TextRuns from these + * + * @param wrapper an EscherTextboxWrapper + * @param found vector to add any found to + */ + protected static void findTextRuns(final EscherTextboxWrapper wrapper, final List found) { + findTextRuns(wrapper.getChildRecords(), found, wrapper.getStyleTextProp9Atom()); + } + /** + * Scans through the supplied record array, looking for + * a TextHeaderAtom followed by one of a TextBytesAtom or + * a TextCharsAtom. Builds up TextRuns from these + * + * @param records the records to build from + * @param found vector to add any found to + * @param styleTextProp9Atom a StyleTextProp9Atom with numbered lists info + */ + protected static void findTextRuns(final Record[] records, final List found, final StyleTextProp9Atom styleTextProp9Atom) { + for (int i = 0, slwtIndex=0; i < (records.length - 1); i++) { + if (records[i] instanceof TextHeaderAtom) { + TextHeaderAtom tha = (TextHeaderAtom) records[i]; + StyleTextPropAtom stpa = null; + HSLFTextParagraph trun = null; + Record next = null; + Record subs = null; + + // See what follows the TextHeaderAtom + next = records[i+1]; + if (i < records.length - 2) { + subs = records[i+2]; + } + + // Is the next record one we need to skip over? + if (subs != null) { + if (next instanceof TextRulerAtom || + next instanceof MasterTextPropAtom || + next instanceof TextSpecInfoAtom) { + // Ignore this one, check the one after + next = subs; + if (i < records.length - 3) { + subs = records[i+3]; + } else { + subs = null; + } + } + } + + // Is the subsequent record a style one? + if (subs != null && subs instanceof StyleTextPropAtom) { + stpa = (StyleTextPropAtom)subs; + } + + // Now, check if the next record is one to record + if (next instanceof TextCharsAtom) { + TextCharsAtom tca = (TextCharsAtom)next; + trun = new HSLFTextParagraph(tha, tca, stpa); + } else if (next instanceof TextBytesAtom) { + TextBytesAtom tba = (TextBytesAtom)next; + trun = new HSLFTextParagraph(tha, tba, stpa); + } else if (next instanceof StyleTextPropAtom) { + stpa = (StyleTextPropAtom)next; + } else if (next instanceof TextHeaderAtom) { + // Seems to be a mostly, but not completely deleted block of + // text. Only the header remains, which isn't useful alone + // Skip on to the next TextHeaderAtom + continue; + } else { + logger.log(POILogger.ERROR, "Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + next.getRecordType()); + } + + if (trun != null) { + List lst = new ArrayList(); + for (int j = i; j < records.length; j++) { + if(j > i && records[j] instanceof TextHeaderAtom) break; + lst.add(records[j]); + } + Record[] recs = new Record[lst.size()]; + lst.toArray(recs); + trun._records = recs; + trun.setIndex(slwtIndex); + trun.setStyleTextProp9Atom(styleTextProp9Atom); + found.add(trun); + i++; + } else { + // Not a valid one, so skip on to next and look again + } + slwtIndex++; + } + } + } + + /** + * Returns all shapes contained in this Sheet + * + * @return all shapes contained in this Sheet (Slide or Notes) + */ + public HSLFShape[] getShapes() { + List shapeList = getShapeList(); + return shapeList.toArray(new HSLFShape[shapeList.size()]); + } + + /** + * Add a new Shape to this Slide + * + * @param shape - the Shape to add + */ + public void addShape(HSLFShape shape) { + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER); + spgr.addChildRecord(shape.getSpContainer()); + + shape.setSheet(this); + shape.setShapeId(allocateShapeId()); + shape.afterInsert(this); + } + + /** + * Allocates new shape id for the new drawing group id. + * + * @return a new shape id. + */ + public int allocateShapeId() + { + EscherDggRecord dgg = _slideShow.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); + EscherDgRecord dg = _container.getPPDrawing().getEscherDgRecord(); + + dgg.setNumShapesSaved( dgg.getNumShapesSaved() + 1 ); + + // Add to existing cluster if space available + for (int i = 0; i < dgg.getFileIdClusters().length; i++) + { + EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i]; + if (c.getDrawingGroupId() == dg.getDrawingGroupId() && c.getNumShapeIdsUsed() != 1024) + { + int result = c.getNumShapeIdsUsed() + (1024 * (i+1)); + c.incrementShapeId(); + dg.setNumShapes( dg.getNumShapes() + 1 ); + dg.setLastMSOSPID( result ); + if (result >= dgg.getShapeIdMax()) + dgg.setShapeIdMax( result + 1 ); + return result; + } + } + + // Create new cluster + dgg.addCluster( dg.getDrawingGroupId(), 0, false ); + dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId(); + dg.setNumShapes( dg.getNumShapes() + 1 ); + int result = (1024 * dgg.getFileIdClusters().length); + dg.setLastMSOSPID( result ); + if (result >= dgg.getShapeIdMax()) + dgg.setShapeIdMax( result + 1 ); + return result; + } + + /** + * Removes the specified shape from this sheet. + * + * @param shape shape to be removed from this sheet, if present. + * @return true if the shape was deleted. + */ + public boolean removeShape(HSLFShape shape) { + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spgr = null; + + for (Iterator it = dg.getChildIterator(); it.hasNext();) { + EscherRecord rec = it.next(); + if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + spgr = (EscherContainerRecord) rec; + break; + } + } + if(spgr == null) { + return false; + } + + List lst = spgr.getChildRecords(); + boolean result = lst.remove(shape.getSpContainer()); + spgr.setChildRecords(lst); + return result; + } + + /** + * Called by SlideShow ater a new sheet is created + */ + public void onCreate(){ + + } + + /** + * Return the master sheet . + */ + public abstract HSLFMasterSheet getMasterSheet(); + + /** + * Color scheme for this sheet. + */ + public ColorSchemeAtom getColorScheme() { + return _container.getColorScheme(); + } + + /** + * Returns the background shape for this sheet. + * + * @return the background shape for this sheet. + */ + public HSLFBackground getBackground() { + if (_background == null) { + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spContainer = null; + + for (Iterator it = dg.getChildIterator(); it.hasNext();) { + EscherRecord rec = it.next(); + if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER) { + spContainer = (EscherContainerRecord) rec; + break; + } + } + _background = new HSLFBackground(spContainer, null); + _background.setSheet(this); + } + return _background; + } + + public void draw(Graphics2D graphics){ + + } + + /** + * Subclasses should call this method and update the array of text runs + * when a text shape is added + * + * @param shape + */ + protected void onAddTextShape(HSLFTextShape shape) { + + } + + /** + * Return placeholder by text type + * + * @param type type of text, See {@link org.apache.poi.hslf.record.TextHeaderAtom} + * @return TextShape or null + */ + public HSLFTextShape getPlaceholderByTextType(int type){ + HSLFShape[] shape = getShapes(); + for (int i = 0; i < shape.length; i++) { + if(shape[i] instanceof HSLFTextShape){ + HSLFTextShape tx = (HSLFTextShape)shape[i]; + HSLFTextParagraph run = tx.getTextParagraph(); + if(run != null && run.getRunType() == type){ + return tx; + } + } + } + return null; + } + + /** + * Search text placeholer by its type + * + * @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom} + * @return TextShape or null + */ + public HSLFTextShape getPlaceholder(int type){ + HSLFShape[] shape = getShapes(); + for (int i = 0; i < shape.length; i++) { + if(shape[i] instanceof HSLFTextShape){ + HSLFTextShape tx = (HSLFTextShape)shape[i]; + int placeholderId = 0; + OEPlaceholderAtom oep = tx.getPlaceholderAtom(); + if(oep != null) { + placeholderId = oep.getPlaceholderId(); + } else { + //special case for files saved in Office 2007 + RoundTripHFPlaceholder12 hldr = tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID); + if(hldr != null) placeholderId = hldr.getPlaceholderId(); + } + if(placeholderId == type){ + return tx; + } + } + } + return null; + } + + /** + * Return programmable tag associated with this sheet, e.g. ___PPT12. + * + * @return programmable tag associated with this sheet. + */ + public String getProgrammableTag(){ + String tag = null; + RecordContainer progTags = (RecordContainer) + getSheetContainer().findFirstOfType( + RecordTypes.ProgTags.typeID + ); + if(progTags != null) { + RecordContainer progBinaryTag = (RecordContainer) + progTags.findFirstOfType( + RecordTypes.ProgBinaryTag.typeID + ); + if(progBinaryTag != null) { + CString binaryTag = (CString) + progBinaryTag.findFirstOfType( + RecordTypes.CString.typeID + ); + if(binaryTag != null) tag = binaryTag.getText(); + } + } + + return tag; + + } + + public Iterator iterator() { + return getShapeList().iterator(); + } + + + /** + * Returns all shapes contained in this Sheet + * + * @return all shapes contained in this Sheet (Slide or Notes) + */ + protected List getShapeList() { + PPDrawing ppdrawing = getPPDrawing(); + + EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; + EscherContainerRecord spgr = null; + + for (Iterator it = dg.getChildIterator(); it.hasNext();) { + EscherRecord rec = it.next(); + if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { + spgr = (EscherContainerRecord) rec; + break; + } + } + if (spgr == null) { + throw new IllegalStateException("spgr not found"); + } + + List shapeList = new ArrayList(); + Iterator it = spgr.getChildIterator(); + if (it.hasNext()) { + // skip first item + it.next(); + } + for (; it.hasNext();) { + EscherContainerRecord sp = (EscherContainerRecord) it.next(); + HSLFShape sh = ShapeFactory.createShape(sp, null); + sh.setSheet(this); + shapeList.add(sh); + } + + return shapeList; + } + + /** + * @return whether shapes on the master sheet should be shown. By default master graphics is turned off. + * Sheets that support the notion of master (slide, slideLayout) should override it and + * check this setting + */ + public boolean getFollowMasterGraphics() { + return false; + } + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSimpleShape.java new file mode 100644 index 0000000000..71c3c34d77 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSimpleShape.java @@ -0,0 +1,420 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; + +import org.apache.poi.ddf.DefaultEscherRecordFactory; +import org.apache.poi.ddf.EscherChildAnchorRecord; +import org.apache.poi.ddf.EscherClientAnchorRecord; +import org.apache.poi.ddf.EscherClientDataRecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.sl.usermodel.*; +import org.apache.poi.sl.usermodel.StrokeStyle.*; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.Units; + +/** + * An abstract simple (non-group) shape. + * This is the parent class for all primitive shapes like Line, Rectangle, etc. + * + * @author Yegor Kozlov + */ +public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape { + + public final static double DEFAULT_LINE_WIDTH = 0.75; + + /** + * Records stored in EscherClientDataRecord + */ + protected Record[] _clientRecords; + protected EscherClientDataRecord _clientData; + + /** + * Create a SimpleShape object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected HSLFSimpleShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + } + + /** + * Create a new Shape + * + * @param isChild true if the Line is inside a group, false otherwise + * @return the record container which holds this shape + */ + protected EscherContainerRecord createSpContainer(boolean isChild) { + _escherContainer = new EscherContainerRecord(); + _escherContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); + _escherContainer.setOptions((short)15); + + EscherSpRecord sp = new EscherSpRecord(); + int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE; + if (isChild) flags |= EscherSpRecord.FLAG_CHILD; + sp.setFlags(flags); + _escherContainer.addChildRecord(sp); + + EscherOptRecord opt = new EscherOptRecord(); + opt.setRecordId(EscherOptRecord.RECORD_ID); + _escherContainer.addChildRecord(opt); + + EscherRecord anchor; + if(isChild) anchor = new EscherChildAnchorRecord(); + else { + anchor = new EscherClientAnchorRecord(); + + //hack. internal variable EscherClientAnchorRecord.shortRecord can be + //initialized only in fillFields(). We need to set shortRecord=false; + byte[] header = new byte[16]; + LittleEndian.putUShort(header, 0, 0); + LittleEndian.putUShort(header, 2, 0); + LittleEndian.putInt(header, 4, 8); + anchor.fillFields(header, 0, null); + } + _escherContainer.addChildRecord(anchor); + + return _escherContainer; + } + + /** + * Returns width of the line in in points + */ + public double getLineWidth(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); + double width = (prop == null) ? DEFAULT_LINE_WIDTH : Units.toPoints(prop.getPropertyValue()); + return width; + } + + /** + * Sets the width of line in in points + * @param width the width of line in in points + */ + public void setLineWidth(double width){ + EscherOptRecord opt = getEscherOptRecord(); + setEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH, Units.toEMU(width)); + } + + /** + * Sets the color of line + * + * @param color new color of the line + */ + public void setLineColor(Color color){ + EscherOptRecord opt = getEscherOptRecord(); + if (color == null) { + setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000); + } else { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); + setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb); + setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, color == null ? 0x180010 : 0x180018); + } + } + + /** + * @return color of the line. If color is not set returns java.awt.Color.black + */ + public Color getLineColor(){ + EscherOptRecord opt = getEscherOptRecord(); + + EscherSimpleProperty p = getEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH); + if(p != null && (p.getPropertyValue() & 0x8) == 0) return null; + + Color clr = getColor(EscherProperties.LINESTYLE__COLOR, EscherProperties.LINESTYLE__OPACITY, -1); + return clr == null ? Color.black : clr; + } + + /** + * Gets line dashing. + * + * @return dashing of the line. + */ + public LineDash getLineDashing(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); + return (prop == null) ? LineDash.SOLID : LineDash.fromNativeId(prop.getPropertyValue()); + } + + /** + * Sets line dashing. + * + * @param pen new style of the line. + */ + public void setLineDashing(LineDash pen){ + EscherOptRecord opt = getEscherOptRecord(); + setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, pen == LineDash.SOLID ? -1 : pen.nativeId); + } + + /** + * Gets the line compound style + * + * @return the compound style of the line. + */ + public LineCompound getLineCompound() { + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE); + return (prop == null) ? LineCompound.SINGLE : LineCompound.fromNativeId(prop.getPropertyValue()); + } + + /** + * Sets the line compound style + * + * @param style new compound style of the line. + */ + public void setLineCompound(LineCompound style){ + EscherOptRecord opt = getEscherOptRecord(); + setEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE, style == LineCompound.SINGLE ? -1 : style.nativeId); + } + + /** + * Returns line style. One of the constants defined in this class. + * + * @return style of the line. + */ + public StrokeStyle getStrokeStyle(){ + return new StrokeStyle() { + public PaintStyle getPaint() { + return null; + } + + public LineCap getLineCap() { + return null; + } + + public LineDash getLineDash() { + return null; + } + + public LineCompound getLineCompound() { + return null; + } + + public double getLineWidth() { + return 0; + } + + }; + } + + /** + * The color used to fill this shape. + */ + public Color getFillColor(){ + return getFill().getForegroundColor(); + } + + /** + * The color used to fill this shape. + * + * @param color the background color + */ + public void setFillColor(Color color){ + getFill().setForegroundColor(color); + } + + /** + * + * @return 'absolute' anchor of this shape relative to the parent sheet + */ + public Rectangle2D getLogicalAnchor2D(){ + Rectangle2D anchor = getAnchor2D(); + + //if it is a groupped shape see if we need to transform the coordinates + if (getParent() != null){ + ArrayList lst = new ArrayList(); + for (ShapeContainer parent=this.getParent(); + parent instanceof HSLFGroupShape; + parent = ((HSLFGroupShape)parent).getParent()) { + lst.add(0, (HSLFGroupShape)parent); + } + + AffineTransform tx = new AffineTransform(); + for(HSLFGroupShape prnt : lst) { + Rectangle2D exterior = prnt.getAnchor2D(); + Rectangle2D interior = prnt.getCoordinates(); + + double scaleX = exterior.getWidth() / interior.getWidth(); + double scaleY = exterior.getHeight() / interior.getHeight(); + + tx.translate(exterior.getX(), exterior.getY()); + tx.scale(scaleX, scaleY); + tx.translate(-interior.getX(), -interior.getY()); + + } + anchor = tx.createTransformedShape(anchor).getBounds2D(); + } + + double angle = getRotation(); + if(angle != 0.){ + double centerX = anchor.getX() + anchor.getWidth()/2; + double centerY = anchor.getY() + anchor.getHeight()/2; + + AffineTransform trans = new AffineTransform(); + trans.translate(centerX, centerY); + trans.rotate(Math.toRadians(angle)); + trans.translate(-centerX, -centerY); + + Rectangle2D rect = trans.createTransformedShape(anchor).getBounds2D(); + if((anchor.getWidth() < anchor.getHeight() && rect.getWidth() > rect.getHeight()) || + (anchor.getWidth() > anchor.getHeight() && rect.getWidth() < rect.getHeight()) ){ + trans = new AffineTransform(); + trans.translate(centerX, centerY); + trans.rotate(Math.PI/2); + trans.translate(-centerX, -centerY); + anchor = trans.createTransformedShape(anchor).getBounds2D(); + } + } + return anchor; + } + + public void draw(Graphics2D graphics){ + AffineTransform at = graphics.getTransform(); + ShapePainter.paint(this, graphics); + graphics.setTransform(at); + } + + /** + * Find a record in the underlying EscherClientDataRecord + * + * @param recordType type of the record to search + */ + @SuppressWarnings("unchecked") + protected T getClientDataRecord(int recordType) { + + Record[] records = getClientRecords(); + if(records != null) for (int i = 0; i < records.length; i++) { + if(records[i].getRecordType() == recordType){ + return (T)records[i]; + } + } + return null; + } + + /** + * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records + * + * @return an array of HSLF records contained in the shape's EscherClientDataRecord or null + */ + protected Record[] getClientRecords() { + if(_clientData == null){ + EscherRecord r = getEscherChild(EscherClientDataRecord.RECORD_ID); + //ddf can return EscherContainerRecord with recordId=EscherClientDataRecord.RECORD_ID + //convert in to EscherClientDataRecord on the fly + if(r != null && !(r instanceof EscherClientDataRecord)){ + byte[] data = r.serialize(); + r = new EscherClientDataRecord(); + r.fillFields(data, 0, new DefaultEscherRecordFactory()); + } + _clientData = (EscherClientDataRecord)r; + } + if(_clientData != null && _clientRecords == null){ + byte[] data = _clientData.getRemainingData(); + _clientRecords = Record.findChildRecords(data, 0, data.length); + } + return _clientRecords; + } + + protected void updateClientData() { + if(_clientData != null && _clientRecords != null){ + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + for (int i = 0; i < _clientRecords.length; i++) { + _clientRecords[i].writeOut(out); + } + } catch(Exception e){ + throw new HSLFException(e); + } + _clientData.setRemainingData(out.toByteArray()); + } + } + + public void setHyperlink(Hyperlink link){ + if(link.getId() == -1){ + throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first"); + } + + EscherClientDataRecord cldata = new EscherClientDataRecord(); + cldata.setOptions((short)0xF); + getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong + + InteractiveInfo info = new InteractiveInfo(); + InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); + + switch(link.getType()){ + case Hyperlink.LINK_FIRSTSLIDE: + infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); + infoAtom.setJump(InteractiveInfoAtom.JUMP_FIRSTSLIDE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_FirstSlide); + break; + case Hyperlink.LINK_LASTSLIDE: + infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); + infoAtom.setJump(InteractiveInfoAtom.JUMP_LASTSLIDE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_LastSlide); + break; + case Hyperlink.LINK_NEXTSLIDE: + infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); + infoAtom.setJump(InteractiveInfoAtom.JUMP_NEXTSLIDE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_NextSlide); + break; + case Hyperlink.LINK_PREVIOUSSLIDE: + infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); + infoAtom.setJump(InteractiveInfoAtom.JUMP_PREVIOUSSLIDE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_PreviousSlide); + break; + case Hyperlink.LINK_URL: + infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); + infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url); + break; + case Hyperlink.LINK_SLIDENUMBER: + infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); + infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_SlideNumber); + break; + } + + infoAtom.setHyperlinkID(link.getId()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + try { + info.writeOut(out); + } catch(Exception e){ + throw new HSLFException(e); + } + cldata.setRemainingData(out.toByteArray()); + + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlide.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlide.java new file mode 100644 index 0000000000..7030ce73e1 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlide.java @@ -0,0 +1,515 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.Graphics2D; +import java.util.LinkedList; +import java.util.List; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherDgRecord; +import org.apache.poi.ddf.EscherDggRecord; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.hslf.record.ColorSchemeAtom; +import org.apache.poi.hslf.record.Comment2000; +import org.apache.poi.hslf.record.EscherTextboxWrapper; +import org.apache.poi.hslf.record.HeadersFootersContainer; +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.SSSlideInfoAtom; +import org.apache.poi.hslf.record.SlideAtom; +import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; +import org.apache.poi.hslf.record.StyleTextProp9Atom; +import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.ShapeType; +import org.apache.poi.sl.usermodel.Slide; + +/** + * This class represents a slide in a PowerPoint Document. It allows + * access to the text within, and the layout. For now, it only does + * the text side of things though + * + * @author Nick Burch + * @author Yegor Kozlov + */ + +public final class HSLFSlide extends HSLFSheet implements Slide { + private int _slideNo; + private SlideAtomsSet _atomSet; + private HSLFTextParagraph[] _runs; + private HSLFNotes _notes; // usermodel needs to set this + + /** + * Constructs a Slide from the Slide record, and the SlideAtomsSet + * containing the text. + * Initializes TextRuns, to provide easier access to the text + * + * @param slide the Slide record we're based on + * @param notes the Notes sheet attached to us + * @param atomSet the SlideAtomsSet to get the text from + */ + public HSLFSlide(org.apache.poi.hslf.record.Slide slide, HSLFNotes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) { + super(slide, slideIdentifier); + + _notes = notes; + _atomSet = atomSet; + _slideNo = slideNumber; + + // Grab the TextRuns from the PPDrawing + HSLFTextParagraph[] _otherRuns = findTextRuns(getPPDrawing()); + + // For the text coming in from the SlideAtomsSet: + // Build up TextRuns from pairs of TextHeaderAtom and + // one of TextBytesAtom or TextCharsAtom + final List textParagraphs = new LinkedList(); + if(_atomSet != null) { + findTextParagraphs(_atomSet.getSlideRecords(),textParagraphs); + } else { + // No text on the slide, must just be pictures + } + + // Build an array, more useful than a vector + _runs = new HSLFTextParagraph[textParagraphs.size()+_otherRuns.length]; + // Grab text from SlideListWithTexts entries + int i=0; + for(HSLFTextParagraph tp : textParagraphs) { + _runs[i++] = tp; + tp.supplySheet(this); + } + // Grab text from slide's PPDrawing + for(HSLFTextParagraph tp : _otherRuns) { + _runs[i++] = tp; + tp.supplySheet(this); + tp.setIndex(-1); // runs found in PPDrawing are not linked with SlideListWithTexts + } + } + + /** + * Create a new Slide instance + * @param sheetNumber The internal number of the sheet, as used by PersistPtrHolder + * @param slideNumber The user facing number of the sheet + */ + public HSLFSlide(int sheetNumber, int sheetRefId, int slideNumber){ + super(new org.apache.poi.hslf.record.Slide(), sheetNumber); + _slideNo = slideNumber; + getSheetContainer().setSheetId(sheetRefId); + } + + /** + * Sets the Notes that are associated with this. Updates the + * references in the records to point to the new ID + */ + public void setNotes(HSLFNotes notes) { + _notes = notes; + + // Update the Slide Atom's ID of where to point to + SlideAtom sa = getSlideRecord().getSlideAtom(); + + if(notes == null) { + // Set to 0 + sa.setNotesID(0); + } else { + // Set to the value from the notes' sheet id + sa.setNotesID(notes._getSheetNumber()); + } + } + + /** + * Changes the Slide's (external facing) page number. + * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#reorderSlide(int, int) + */ + public void setSlideNumber(int newSlideNumber) { + _slideNo = newSlideNumber; + } + + /** + * Called by SlideShow ater a new slide is created. + *

+ * For Slide we need to do the following: + *

  • set id of the drawing group. + *
  • set shapeId for the container descriptor and background + *

    + */ + public void onCreate(){ + //initialize drawing group id + EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); + EscherContainerRecord dgContainer = (EscherContainerRecord)getSheetContainer().getPPDrawing().getEscherRecords()[0]; + EscherDgRecord dg = (EscherDgRecord) HSLFShape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID); + int dgId = dgg.getMaxDrawingGroupId() + 1; + dg.setOptions((short)(dgId << 4)); + dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1); + dgg.setMaxDrawingGroupId(dgId); + + for (EscherContainerRecord c : dgContainer.getChildContainers()) { + EscherSpRecord spr = null; + switch(c.getRecordId()){ + case EscherContainerRecord.SPGR_CONTAINER: + EscherContainerRecord dc = (EscherContainerRecord)c.getChild(0); + spr = dc.getChildById(EscherSpRecord.RECORD_ID); + break; + case EscherContainerRecord.SP_CONTAINER: + spr = c.getChildById(EscherSpRecord.RECORD_ID); + break; + } + if(spr != null) spr.setShapeId(allocateShapeId()); + } + + //PPT doen't increment the number of saved shapes for group descriptor and background + dg.setNumShapes(1); + } + + /** + * Create a TextBox object that represents the slide's title. + * + * @return TextBox object that represents the slide's title. + */ + public HSLFTextBox addTitle() { + Placeholder pl = new Placeholder(); + pl.setShapeType(ShapeType.RECT); + pl.getTextParagraph().setRunType(TextHeaderAtom.TITLE_TYPE); + pl.setText("Click to edit title"); + pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90)); + addShape(pl); + return pl; + } + + + // Complex Accesser methods follow + + /** + * Return title of this slide or null if the slide does not have title. + *

    + * The title is a run of text of type TextHeaderAtom.CENTER_TITLE_TYPE or + * TextHeaderAtom.TITLE_TYPE + *

    + * + * @see TextHeaderAtom + * + * @return title of this slide + */ + public String getTitle(){ + HSLFTextParagraph[] txt = getTextRuns(); + for (int i = 0; i < txt.length; i++) { + int type = txt[i].getRunType(); + if (type == TextHeaderAtom.CENTER_TITLE_TYPE || + type == TextHeaderAtom.TITLE_TYPE ){ + String title = txt[i].getText(); + return title; + } + } + return null; + } + + // Simple Accesser methods follow + + /** + * Returns an array of all the TextRuns found + */ + public HSLFTextParagraph[] getTextRuns() { return _runs; } + + /** + * Returns the (public facing) page number of this slide + */ + public int getSlideNumber() { return _slideNo; } + + /** + * Returns the underlying slide record + */ + public org.apache.poi.hslf.record.Slide getSlideRecord() { + return (org.apache.poi.hslf.record.Slide)getSheetContainer(); + } + + /** + * Returns the Notes Sheet for this slide, or null if there isn't one + */ + public HSLFNotes getNotesSheet() { return _notes; } + + /** + * @return set of records inside SlideListWithtext container + * which hold text data for this slide (typically for placeholders). + */ + protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } + + /** + * Returns master sheet associated with this slide. + * It can be either SlideMaster or TitleMaster objects. + * + * @return the master sheet associated with this slide. + */ + public HSLFMasterSheet getMasterSheet(){ + SlideMaster[] master = getSlideShow().getSlidesMasters(); + SlideAtom sa = getSlideRecord().getSlideAtom(); + int masterId = sa.getMasterID(); + HSLFMasterSheet sheet = null; + for (int i = 0; i < master.length; i++) { + if (masterId == master[i]._getSheetNumber()) { + sheet = master[i]; + break; + } + } + if (sheet == null){ + TitleMaster[] titleMaster = getSlideShow().getTitleMasters(); + if(titleMaster != null) for (int i = 0; i < titleMaster.length; i++) { + if (masterId == titleMaster[i]._getSheetNumber()) { + sheet = titleMaster[i]; + break; + } + } + } + return sheet; + } + + /** + * Change Master of this slide. + */ + public void setMasterSheet(HSLFMasterSheet master){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + int sheetNo = master._getSheetNumber(); + sa.setMasterID(sheetNo); + } + + /** + * Sets whether this slide follows master background + * + * @param flag true if the slide follows master, + * false otherwise + */ + public void setFollowMasterBackground(boolean flag){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + sa.setFollowMasterBackground(flag); + } + + /** + * Whether this slide follows master sheet background + * + * @return true if the slide follows master background, + * false otherwise + */ + public boolean getFollowMasterBackground(){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + return sa.getFollowMasterBackground(); + } + + /** + * Sets whether this slide draws master sheet objects + * + * @param flag true if the slide draws master sheet objects, + * false otherwise + */ + public void setFollowMasterObjects(boolean flag){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + sa.setFollowMasterObjects(flag); + } + + /** + * Whether this slide follows master color scheme + * + * @return true if the slide follows master color scheme, + * false otherwise + */ + public boolean getFollowMasterScheme(){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + return sa.getFollowMasterScheme(); + } + + /** + * Sets whether this slide draws master color scheme + * + * @param flag true if the slide draws master color scheme, + * false otherwise + */ + public void setFollowMasterScheme(boolean flag){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + sa.setFollowMasterScheme(flag); + } + + /** + * Whether this slide draws master sheet objects + * + * @return true if the slide draws master sheet objects, + * false otherwise + */ + public boolean getFollowMasterObjects(){ + SlideAtom sa = getSlideRecord().getSlideAtom(); + return sa.getFollowMasterObjects(); + } + + /** + * Background for this slide. + */ + public HSLFBackground getBackground() { + if(getFollowMasterBackground()) { + return getMasterSheet().getBackground(); + } + return super.getBackground(); + } + + /** + * Color scheme for this slide. + */ + public ColorSchemeAtom getColorScheme() { + if(getFollowMasterScheme()){ + return getMasterSheet().getColorScheme(); + } + return super.getColorScheme(); + } + + /** + * Get the comment(s) for this slide. + * Note - for now, only works on PPT 2000 and + * PPT 2003 files. Doesn't work for PPT 97 + * ones, as they do their comments oddly. + */ + public Comment[] getComments() { + // If there are any, they're in + // ProgTags -> ProgBinaryTag -> BinaryTagData + RecordContainer progTags = (RecordContainer) + getSheetContainer().findFirstOfType( + RecordTypes.ProgTags.typeID + ); + if(progTags != null) { + RecordContainer progBinaryTag = (RecordContainer) + progTags.findFirstOfType( + RecordTypes.ProgBinaryTag.typeID + ); + if(progBinaryTag != null) { + RecordContainer binaryTags = (RecordContainer) + progBinaryTag.findFirstOfType( + RecordTypes.BinaryTagData.typeID + ); + if(binaryTags != null) { + // This is where they'll be + int count = 0; + for(int i=0; i recordMap) { + // check for DocumentEncryptionAtom, which would be at the last offset + // need to ignore already set UserEdit and PersistAtoms + UserEditAtom userEditAtomWithEncryption = null; + for (Map.Entry me : recordMap.descendingMap().entrySet()) { + Record r = me.getValue(); + if (!(r instanceof UserEditAtom)) continue; + UserEditAtom uea = (UserEditAtom)r; + if (uea.getEncryptSessionPersistIdRef() != -1) { + userEditAtomWithEncryption = uea; + break; + } + } + + if (userEditAtomWithEncryption == null) { + dea = null; + return; + } + + Record r = recordMap.get(userEditAtomWithEncryption.getPersistPointersOffset()); + assert(r instanceof PersistPtrHolder); + PersistPtrHolder ptr = (PersistPtrHolder)r; + + Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef()); + assert(encOffset != null); + + r = recordMap.get(encOffset); + if (r == null) { + r = Record.buildRecordAtOffset(docstream, encOffset); + recordMap.put(encOffset, r); + } + assert(r instanceof DocumentEncryptionAtom); + this.dea = (DocumentEncryptionAtom)r; + + CryptoAPIDecryptor dec = (CryptoAPIDecryptor)dea.getEncryptionInfo().getDecryptor(); + String pass = Biff8EncryptionKey.getCurrentUserPassword(); + if(!dec.verifyPassword(pass != null ? pass : Decryptor.DEFAULT_PASSWORD)) { + throw new EncryptedPowerPointFileException("PowerPoint file is encrypted. The correct password needs to be set via Biff8EncryptionKey.setCurrentUserPassword()"); + } + } + + public DocumentEncryptionAtom getDocumentEncryptionAtom() { + return dea; + } + + protected void setPersistId(int persistId) { + if (enc != null && dec != null) { + throw new EncryptedPowerPointFileException("Use instance either for en- or decryption"); + } + + try { + if (enc != null) cipher = enc.initCipherForBlock(cipher, persistId); + if (dec != null) cipher = dec.initCipherForBlock(cipher, persistId); + } catch (GeneralSecurityException e) { + throw new EncryptedPowerPointFileException(e); + } + } + + protected void decryptInit() { + if (dec != null) return; + EncryptionInfo ei = dea.getEncryptionInfo(); + dec = (CryptoAPIDecryptor)ei.getDecryptor(); + } + + protected void encryptInit() { + if (enc != null) return; + EncryptionInfo ei = dea.getEncryptionInfo(); + enc = (CryptoAPIEncryptor)ei.getEncryptor(); + } + + + + protected OutputStream encryptRecord(OutputStream plainStream, int persistId, Record record) { + boolean isPlain = (dea == null + || record instanceof UserEditAtom + || record instanceof PersistPtrHolder + || record instanceof DocumentEncryptionAtom + ); + if (isPlain) return plainStream; + + encryptInit(); + setPersistId(persistId); + + if (cyos == null) { + cyos = new CipherOutputStream(plainStream, cipher); + } + return cyos; + } + + protected void decryptRecord(byte[] docstream, int persistId, int offset) { + if (dea == null) return; + + decryptInit(); + setPersistId(persistId); + + try { + // decrypt header and read length to be decrypted + cipher.update(docstream, offset, 8, docstream, offset); + // decrypt the rest of the record + int rlen = (int)LittleEndian.getUInt(docstream, offset+4); + cipher.update(docstream, offset+8, rlen, docstream, offset+8); + } catch (GeneralSecurityException e) { + throw new CorruptPowerPointFileException(e); + } + } + + protected void decryptPicture(byte[] pictstream, int offset) { + if (dea == null) return; + + decryptInit(); + setPersistId(0); + + try { + // decrypt header and read length to be decrypted + cipher.doFinal(pictstream, offset, 8, pictstream, offset); + int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); + int recType = LittleEndian.getUShort(pictstream, offset+2); + int rlen = (int)LittleEndian.getUInt(pictstream, offset+4); + offset += 8; + int endOffset = offset + rlen; + + if (recType == 0xF007) { + // TOOD: get a real example file ... to actual test the FBSE entry + // not sure where the foDelay block is + + // File BLIP Store Entry (FBSE) + cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btWin32 + offset++; + cipher.doFinal(pictstream, offset, 1, pictstream, offset); // btMacOS + offset++; + cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid + offset += 16; + cipher.doFinal(pictstream, offset, 2, pictstream, offset); // tag + offset += 2; + cipher.doFinal(pictstream, offset, 4, pictstream, offset); // size + offset += 4; + cipher.doFinal(pictstream, offset, 4, pictstream, offset); // cRef + offset += 4; + cipher.doFinal(pictstream, offset, 4, pictstream, offset); // foDelay + offset += 4; + cipher.doFinal(pictstream, offset+0, 1, pictstream, offset+0); // unused1 + cipher.doFinal(pictstream, offset+1, 1, pictstream, offset+1); // cbName + cipher.doFinal(pictstream, offset+2, 1, pictstream, offset+2); // unused2 + cipher.doFinal(pictstream, offset+3, 1, pictstream, offset+3); // unused3 + int cbName = LittleEndian.getUShort(pictstream, offset+1); + offset += 4; + if (cbName > 0) { + cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData + offset += cbName; + } + if (offset == endOffset) { + return; // no embedded blip + } + // fall through, read embedded blip now + + // update header data + cipher.doFinal(pictstream, offset, 8, pictstream, offset); + recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); + recType = LittleEndian.getUShort(pictstream, offset+2); + rlen = (int)LittleEndian.getUInt(pictstream, offset+4); + offset += 8; + } + + int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 || + recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1; + + for (int i=0; i 0) { + cipher.doFinal(pictstream, offset, cbName, pictstream, offset); // nameData + offset += cbName; + } + if (offset == endOffset) { + return; // no embedded blip + } + // fall through, read embedded blip now + + // update header data + recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset)); + recType = LittleEndian.getUShort(pictstream, offset+2); + rlen = (int)LittleEndian.getUInt(pictstream, offset+4); + cipher.doFinal(pictstream, offset, 8, pictstream, offset); + offset += 8; + } + + int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 || + recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1; + + for (int i=0; i done + return records; + } else { + // need to remove password data + dea = null; + return removeEncryptionRecord(records); + } + } else { + // create password record + if (dea == null) { + dea = new DocumentEncryptionAtom(); + } + EncryptionInfo ei = dea.getEncryptionInfo(); + byte salt[] = ei.getVerifier().getSalt(); + Encryptor enc = ei.getEncryptor(); + if (salt == null) { + enc.confirmPassword(password); + } else { + byte verifier[] = ei.getDecryptor().getVerifier(); + enc.confirmPassword(password, null, null, verifier, salt, null); + } + + // move EncryptionRecord to last slide position + records = normalizeRecords(records); + return addEncryptionRecord(records, dea); + } + } + + /** + * remove duplicated UserEditAtoms and merge PersistPtrHolder. + * Before this method is called, make sure that the offsets are correct, + * i.e. call {@link HSLFSlideShowImpl#updateAndWriteDependantRecords(OutputStream, Map)} + */ + protected static Record[] normalizeRecords(Record records[]) { + // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx + // repeated slideIds can be overwritten, i.e. ignored + + UserEditAtom uea = null; + PersistPtrHolder pph = null; + TreeMap slideLocations = new TreeMap(); + TreeMap recordMap = new TreeMap(); + List obsoleteOffsets = new ArrayList(); + int duplicatedCount = 0; + for (Record r : records) { + assert(r instanceof PositionDependentRecord); + PositionDependentRecord pdr = (PositionDependentRecord)r; + if (pdr instanceof UserEditAtom) { + uea = (UserEditAtom)pdr; + continue; + } + + if (pdr instanceof PersistPtrHolder) { + if (pph != null) { + duplicatedCount++; + } + pph = (PersistPtrHolder)pdr; + for (Map.Entry me : pph.getSlideLocationsLookup().entrySet()) { + Integer oldOffset = slideLocations.put(me.getKey(), me.getValue()); + if (oldOffset != null) obsoleteOffsets.add(oldOffset); + } + continue; + } + + recordMap.put(pdr.getLastOnDiskOffset(), r); + } + recordMap.put(pph.getLastOnDiskOffset(), pph); + recordMap.put(uea.getLastOnDiskOffset(), uea); + + assert(uea != null && pph != null && uea.getPersistPointersOffset() == pph.getLastOnDiskOffset()); + + if (duplicatedCount == 0 && obsoleteOffsets.isEmpty()) { + return records; + } + + uea.setLastUserEditAtomOffset(0); + pph.clear(); + for (Map.Entry me : slideLocations.entrySet()) { + pph.addSlideLookup(me.getKey(), me.getValue()); + } + + for (Integer oldOffset : obsoleteOffsets) { + recordMap.remove(oldOffset); + } + + return recordMap.values().toArray(new Record[recordMap.size()]); + } + + + protected static Record[] removeEncryptionRecord(Record records[]) { + int deaSlideId = -1; + int deaOffset = -1; + PersistPtrHolder ptr = null; + UserEditAtom uea = null; + List recordList = new ArrayList(); + for (Record r : records) { + if (r instanceof DocumentEncryptionAtom) { + deaOffset = ((DocumentEncryptionAtom)r).getLastOnDiskOffset(); + continue; + } else if (r instanceof UserEditAtom) { + uea = (UserEditAtom)r; + deaSlideId = uea.getEncryptSessionPersistIdRef(); + uea.setEncryptSessionPersistIdRef(-1); + } else if (r instanceof PersistPtrHolder) { + ptr = (PersistPtrHolder)r; + } + recordList.add(r); + } + + assert(ptr != null); + if (deaSlideId == -1 && deaOffset == -1) return records; + + TreeMap tm = new TreeMap(ptr.getSlideLocationsLookup()); + ptr.clear(); + int maxSlideId = -1; + for (Map.Entry me : tm.entrySet()) { + if (me.getKey() == deaSlideId || me.getValue() == deaOffset) continue; + ptr.addSlideLookup(me.getKey(), me.getValue()); + maxSlideId = Math.max(me.getKey(), maxSlideId); + } + + uea.setMaxPersistWritten(maxSlideId); + + records = recordList.toArray(new Record[recordList.size()]); + + return records; + } + + + protected static Record[] addEncryptionRecord(Record records[], DocumentEncryptionAtom dea) { + assert(dea != null); + int ueaIdx = -1, ptrIdx = -1, deaIdx = -1, idx = -1; + for (Record r : records) { + idx++; + if (r instanceof UserEditAtom) ueaIdx = idx; + else if (r instanceof PersistPtrHolder) ptrIdx = idx; + else if (r instanceof DocumentEncryptionAtom) deaIdx = idx; + } + assert(ueaIdx != -1 && ptrIdx != -1 && ptrIdx < ueaIdx); + if (deaIdx != -1) { + DocumentEncryptionAtom deaOld = (DocumentEncryptionAtom)records[deaIdx]; + dea.setLastOnDiskOffset(deaOld.getLastOnDiskOffset()); + records[deaIdx] = dea; + return records; + } else { + PersistPtrHolder ptr = (PersistPtrHolder)records[ptrIdx]; + UserEditAtom uea = ((UserEditAtom)records[ueaIdx]); + dea.setLastOnDiskOffset(ptr.getLastOnDiskOffset()-1); + int nextSlideId = uea.getMaxPersistWritten()+1; + ptr.addSlideLookup(nextSlideId, ptr.getLastOnDiskOffset()-1); + uea.setEncryptSessionPersistIdRef(nextSlideId); + uea.setMaxPersistWritten(nextSlideId); + + Record newRecords[] = new Record[records.length+1]; + if (ptrIdx > 0) System.arraycopy(records, 0, newRecords, 0, ptrIdx); + if (ptrIdx < records.length-1) System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx); + newRecords[ptrIdx] = dea; + return newRecords; + } + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlideShowImpl.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlideShowImpl.java new file mode 100644 index 0000000000..48e52da65c --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFSlideShowImpl.java @@ -0,0 +1,808 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.TreeMap; + +import org.apache.poi.POIDocument; +import org.apache.poi.hpsf.PropertySet; +import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hslf.record.CurrentUserAtom; +import org.apache.poi.hslf.record.DocumentEncryptionAtom; +import org.apache.poi.hslf.record.ExOleObjStg; +import org.apache.poi.hslf.record.PersistPtrHolder; +import org.apache.poi.hslf.record.PersistRecord; +import org.apache.poi.hslf.record.PositionDependentRecord; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.record.UserEditAtom; +import org.apache.poi.hslf.usermodel.HSLFObjectData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.DocumentEntry; +import org.apache.poi.poifs.filesystem.DocumentInputStream; +import org.apache.poi.poifs.filesystem.EntryUtils; +import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * This class contains the main functionality for the Powerpoint file + * "reader". It is only a very basic class for now + * + * @author Nick Burch + */ +public final class HSLFSlideShowImpl extends POIDocument { + public static final int UNSET_OFFSET = -1; + + // For logging + private POILogger logger = POILogFactory.getLogger(this.getClass()); + + // Holds metadata on where things are in our document + private CurrentUserAtom currentUser; + + // Low level contents of the file + private byte[] _docstream; + + // Low level contents + private Record[] _records; + + // Raw Pictures contained in the pictures stream + private List _pictures; + + // Embedded objects stored in storage records in the document stream, lazily populated. + private HSLFObjectData[] _objects; + + /** + * Returns the underlying POIFSFileSystem for the document + * that is open. + */ + protected POIFSFileSystem getPOIFSFileSystem() { + return directory.getFileSystem(); + } + + /** + * Returns the directory in the underlying POIFSFileSystem for the + * document that is open. + */ + protected DirectoryNode getPOIFSDirectory() { + return directory; + } + + /** + * Constructs a Powerpoint document from fileName. Parses the document + * and places all the important stuff into data structures. + * + * @param fileName The name of the file to read. + * @throws IOException if there is a problem while parsing the document. + */ + public HSLFSlideShowImpl(String fileName) throws IOException + { + this(new FileInputStream(fileName)); + } + + /** + * Constructs a Powerpoint document from an input stream. Parses the + * document and places all the important stuff into data structures. + * + * @param inputStream the source of the data + * @throws IOException if there is a problem while parsing the document. + */ + public HSLFSlideShowImpl(InputStream inputStream) throws IOException { + //do Ole stuff + this(new POIFSFileSystem(inputStream)); + } + + /** + * Constructs a Powerpoint document from a POIFS Filesystem. Parses the + * document and places all the important stuff into data structures. + * + * @param filesystem the POIFS FileSystem to read from + * @throws IOException if there is a problem while parsing the document. + */ + public HSLFSlideShowImpl(POIFSFileSystem filesystem) throws IOException + { + this(filesystem.getRoot()); + } + + /** + * Constructs a Powerpoint document from a POIFS Filesystem. Parses the + * document and places all the important stuff into data structures. + * + * @param filesystem the POIFS FileSystem to read from + * @throws IOException if there is a problem while parsing the document. + */ + public HSLFSlideShowImpl(NPOIFSFileSystem filesystem) throws IOException + { + this(filesystem.getRoot()); + } + + /** + * Constructs a Powerpoint document from a specific point in a + * POIFS Filesystem. Parses the document and places all the + * important stuff into data structures. + * + * @deprecated Use {@link #HSLFSlideShow(DirectoryNode)} instead + * @param dir the POIFS directory to read from + * @param filesystem the POIFS FileSystem to read from + * @throws IOException if there is a problem while parsing the document. + */ + @Deprecated + public HSLFSlideShowImpl(DirectoryNode dir, POIFSFileSystem filesystem) throws IOException + { + this(dir); + } + + /** + * Constructs a Powerpoint document from a specific point in a + * POIFS Filesystem. Parses the document and places all the + * important stuff into data structures. + * + * @param dir the POIFS directory to read from + * @throws IOException if there is a problem while parsing the document. + */ + public HSLFSlideShowImpl(DirectoryNode dir) throws IOException { + super(handleDualStorage(dir)); + + // First up, grab the "Current User" stream + // We need this before we can detect Encrypted Documents + readCurrentUserStream(); + + // Next up, grab the data that makes up the + // PowerPoint stream + readPowerPointStream(); + + // Now, build records based on the PowerPoint stream + buildRecords(); + + // Look for any other streams + readOtherStreams(); + } + + private static DirectoryNode handleDualStorage(DirectoryNode dir) throws IOException { + // when there's a dual storage entry, use it, as the outer document can't be read quite probably ... + String dualName = "PP97_DUALSTORAGE"; + if (!dir.hasEntry(dualName)) return dir; + dir = (DirectoryNode)dir.getEntry(dualName); + return dir; + } + + /** + * Constructs a new, empty, Powerpoint document. + */ + public static final HSLFSlideShowImpl create() { + InputStream is = HSLFSlideShowImpl.class.getResourceAsStream("data/empty.ppt"); + if (is == null) { + throw new RuntimeException("Missing resource 'empty.ppt'"); + } + try { + return new HSLFSlideShowImpl(is); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Extracts the main PowerPoint document stream from the + * POI file, ready to be passed + * + * @throws IOException + */ + private void readPowerPointStream() throws IOException + { + // Get the main document stream + DocumentEntry docProps = + (DocumentEntry)directory.getEntry("PowerPoint Document"); + + // Grab the document stream + _docstream = new byte[docProps.getSize()]; + directory.createDocumentInputStream("PowerPoint Document").read(_docstream); + } + + /** + * Builds the list of records, based on the contents + * of the PowerPoint stream + */ + private void buildRecords() + { + // The format of records in a powerpoint file are: + // + // + // + // If it has a zero length, following it will be another record + // + // If it has a length, depending on its type it may have children or data + // If it has children, these will follow straight away + // > + // If it has data, this will come straigh after, and run for the length + // + // All lengths given exclude the 8 byte record header + // (Data records are known as Atoms) + + // Document should start with: + // 0F 00 E8 03 ## ## ## ## + // (type 1000 = document, info 00 0f is normal, rest is document length) + // 01 00 E9 03 28 00 00 00 + // (type 1001 = document atom, info 00 01 normal, 28 bytes long) + // 80 16 00 00 E0 10 00 00 xx xx xx xx xx xx xx xx + // 05 00 00 00 0A 00 00 00 xx xx xx + // (the contents of the document atom, not sure what it means yet) + // (records then follow) + + // When parsing a document, look to see if you know about that type + // of the current record. If you know it's a type that has children, + // process the record's data area looking for more records + // If you know about the type and it doesn't have children, either do + // something with the data (eg TextRun) or skip over it + // If you don't know about the type, play safe and skip over it (using + // its length to know where the next record will start) + // + + _records = read(_docstream, (int)currentUser.getCurrentEditOffset()); + } + + private Record[] read(byte[] docstream, int usrOffset){ + //sort found records by offset. + //(it is not necessary but SlideShow.findMostRecentCoreRecords() expects them sorted) + NavigableMap records = new TreeMap(); // offset -> record + Map persistIds = new HashMap(); // offset -> persistId + initRecordOffsets(docstream, usrOffset, records, persistIds); + HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(docstream, records); + + for (Map.Entry entry : records.entrySet()) { + Integer offset = entry.getKey(); + Record record = entry.getValue(); + Integer persistId = persistIds.get(offset); + if (record == null) { + // all plain records have been already added, + // only new records need to be decrypted (tbd #35897) + decryptData.decryptRecord(docstream, persistId, offset); + record = Record.buildRecordAtOffset(docstream, offset); + entry.setValue(record); + } + + if (record instanceof PersistRecord) { + ((PersistRecord)record).setPersistId(persistId); + } + } + + return records.values().toArray(new Record[records.size()]); + } + + private void initRecordOffsets(byte[] docstream, int usrOffset, NavigableMap recordMap, Map offset2id) { + while (usrOffset != 0){ + UserEditAtom usr = (UserEditAtom) Record.buildRecordAtOffset(docstream, usrOffset); + recordMap.put(usrOffset, usr); + + int psrOffset = usr.getPersistPointersOffset(); + PersistPtrHolder ptr = (PersistPtrHolder)Record.buildRecordAtOffset(docstream, psrOffset); + recordMap.put(psrOffset, ptr); + + for(Map.Entry entry : ptr.getSlideLocationsLookup().entrySet()) { + Integer offset = entry.getValue(); + Integer id = entry.getKey(); + recordMap.put(offset, null); // reserve a slot for the record + offset2id.put(offset, id); + } + + usrOffset = usr.getLastUserEditAtomOffset(); + + // check for corrupted user edit atom and try to repair it + // if the next user edit atom offset is already known, we would go into an endless loop + if (usrOffset > 0 && recordMap.containsKey(usrOffset)) { + // a user edit atom is usually located 36 byte before the smallest known record offset + usrOffset = recordMap.firstKey()-36; + // check that we really are located on a user edit atom + int ver_inst = LittleEndian.getUShort(docstream, usrOffset); + int type = LittleEndian.getUShort(docstream, usrOffset+2); + int len = LittleEndian.getInt(docstream, usrOffset+4); + if (ver_inst == 0 && type == 4085 && (len == 0x1C || len == 0x20)) { + logger.log(POILogger.WARN, "Repairing invalid user edit atom"); + usr.setLastUserEditAtomOffset(usrOffset); + } else { + throw new CorruptPowerPointFileException("Powerpoint document contains invalid user edit atom"); + } + } + } + } + + public DocumentEncryptionAtom getDocumentEncryptionAtom() { + for (Record r : _records) { + if (r instanceof DocumentEncryptionAtom) { + return (DocumentEncryptionAtom)r; + } + } + return null; + } + + + /** + * Find the "Current User" stream, and load it + */ + private void readCurrentUserStream() { + try { + currentUser = new CurrentUserAtom(directory); + } catch(IOException ie) { + logger.log(POILogger.ERROR, "Error finding Current User Atom:\n" + ie); + currentUser = new CurrentUserAtom(); + } + } + + /** + * Find any other streams from the filesystem, and load them + */ + private void readOtherStreams() { + // Currently, there aren't any + } + + /** + * Find and read in pictures contained in this presentation. + * This is lazily called as and when we want to touch pictures. + */ + @SuppressWarnings("unused") + private void readPictures() throws IOException { + _pictures = new ArrayList(); + + // if the presentation doesn't contain pictures - will use a null set instead + if (!directory.hasEntry("Pictures")) return; + + HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom()); + + DocumentEntry entry = (DocumentEntry)directory.getEntry("Pictures"); + byte[] pictstream = new byte[entry.getSize()]; + DocumentInputStream is = directory.createDocumentInputStream(entry); + is.read(pictstream); + is.close(); + + + int pos = 0; + // An empty picture record (length 0) will take up 8 bytes + while (pos <= (pictstream.length-8)) { + int offset = pos; + + decryptData.decryptPicture(pictstream, offset); + + // Image signature + int signature = LittleEndian.getUShort(pictstream, pos); + pos += LittleEndian.SHORT_SIZE; + // Image type + 0xF018 + int type = LittleEndian.getUShort(pictstream, pos); + pos += LittleEndian.SHORT_SIZE; + // Image size (excluding the 8 byte header) + int imgsize = LittleEndian.getInt(pictstream, pos); + pos += LittleEndian.INT_SIZE; + + // When parsing the BStoreDelay stream, [MS-ODRAW] says that we + // should terminate if the type isn't 0xf007 or 0xf018->0xf117 + if (!((type == 0xf007) || (type >= 0xf018 && type <= 0xf117))) + break; + + // The image size must be 0 or greater + // (0 is allowed, but odd, since we do wind on by the header each + // time, so we won't get stuck) + if(imgsize < 0) { + throw new CorruptPowerPointFileException("The file contains a picture, at position " + _pictures.size() + ", which has a negatively sized data length, so we can't trust any of the picture data"); + } + + // If they type (including the bonus 0xF018) is 0, skip it + if(type == 0) { + logger.log(POILogger.ERROR, "Problem reading picture: Invalid image type 0, on picture with length " + imgsize + ".\nYou document will probably become corrupted if you save it!"); + logger.log(POILogger.ERROR, "" + pos); + } else { + // Build the PictureData object from the data + try { + HSLFPictureData pict = HSLFPictureData.create(type - 0xF018); + + // Copy the data, ready to pass to PictureData + byte[] imgdata = new byte[imgsize]; + System.arraycopy(pictstream, pos, imgdata, 0, imgdata.length); + pict.setRawData(imgdata); + + pict.setOffset(offset); + _pictures.add(pict); + } catch(IllegalArgumentException e) { + logger.log(POILogger.ERROR, "Problem reading picture: " + e + "\nYou document will probably become corrupted if you save it!"); + } + } + + pos += imgsize; + } + } + + /** + * remove duplicated UserEditAtoms and merge PersistPtrHolder, i.e. + * remove document edit history + */ + public void normalizeRecords() { + try { + updateAndWriteDependantRecords(null, null); + } catch (IOException e) { + throw new CorruptPowerPointFileException(e); + } + _records = HSLFSlideShowEncrypted.normalizeRecords(_records); + } + + + /** + * This is a helper functions, which is needed for adding new position dependent records + * or finally write the slideshow to a file. + * + * @param os the stream to write to, if null only the references are updated + * @param interestingRecords a map of interesting records (PersistPtrHolder and UserEditAtom) + * referenced by their RecordType. Only the very last of each type will be saved to the map. + * May be null, if not needed. + * @throws IOException + */ + public void updateAndWriteDependantRecords(OutputStream os, Map interestingRecords) + throws IOException { + // For position dependent records, hold where they were and now are + // As we go along, update, and hand over, to any Position Dependent + // records we happen across + Hashtable oldToNewPositions = new Hashtable(); + + // First pass - figure out where all the position dependent + // records are going to end up, in the new scheme + // (Annoyingly, some powerpoint files have PersistPtrHolders + // that reference slides after the PersistPtrHolder) + UserEditAtom usr = null; + PersistPtrHolder ptr = null; + CountingOS cos = new CountingOS(); + for (Record record : _records) { + // all top level records are position dependent + assert(record instanceof PositionDependentRecord); + PositionDependentRecord pdr = (PositionDependentRecord)record; + int oldPos = pdr.getLastOnDiskOffset(); + int newPos = cos.size(); + pdr.setLastOnDiskOffset(newPos); + if (oldPos != UNSET_OFFSET) { + // new records don't need a mapping, as they aren't in a relation yet + oldToNewPositions.put(oldPos,newPos); + } + + // Grab interesting records as they come past + // this will only save the very last record of each type + RecordTypes.Type saveme = null; + int recordType = (int)record.getRecordType(); + if (recordType == RecordTypes.PersistPtrIncrementalBlock.typeID) { + saveme = RecordTypes.PersistPtrIncrementalBlock; + ptr = (PersistPtrHolder)pdr; + } else if (recordType == RecordTypes.UserEditAtom.typeID) { + saveme = RecordTypes.UserEditAtom; + usr = (UserEditAtom)pdr; + } + if (interestingRecords != null && saveme != null) { + interestingRecords.put(saveme,pdr); + } + + // Dummy write out, so the position winds on properly + record.writeOut(cos); + } + + assert(usr != null && ptr != null); + + Map persistIds = new HashMap(); + for (Map.Entry entry : ptr.getSlideLocationsLookup().entrySet()) { + persistIds.put(oldToNewPositions.get(entry.getValue()), entry.getKey()); + } + + HSLFSlideShowEncrypted encData = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom()); + + for (Record record : _records) { + assert(record instanceof PositionDependentRecord); + // We've already figured out their new location, and + // told them that + // Tell them of the positions of the other records though + PositionDependentRecord pdr = (PositionDependentRecord)record; + Integer persistId = persistIds.get(pdr.getLastOnDiskOffset()); + if (persistId == null) persistId = 0; + + // For now, we're only handling PositionDependentRecord's that + // happen at the top level. + // In future, we'll need the handle them everywhere, but that's + // a bit trickier + pdr.updateOtherRecordReferences(oldToNewPositions); + + // Whatever happens, write out that record tree + if (os != null) { + record.writeOut(encData.encryptRecord(os, persistId, record)); + } + } + + // Update and write out the Current User atom + int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset(); + Integer newLastUserEditAtomPos = oldToNewPositions.get(oldLastUserEditAtomPos); + if(usr == null || newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) { + throw new HSLFException("Couldn't find the new location of the last UserEditAtom that used to be at " + oldLastUserEditAtomPos); + } + currentUser.setCurrentEditOffset(usr.getLastOnDiskOffset()); + } + + /** + * Writes out the slideshow file the is represented by an instance + * of this class. + * It will write out the common OLE2 streams. If you require all + * streams to be written out, pass in preserveNodes + * @param out The OutputStream to write to. + * @throws IOException If there is an unexpected IOException from + * the passed in OutputStream + */ + public void write(OutputStream out) throws IOException { + // Write out, but only the common streams + write(out,false); + } + /** + * Writes out the slideshow file the is represented by an instance + * of this class. + * If you require all streams to be written out (eg Marcos, embeded + * documents), then set preserveNodes to true + * @param out The OutputStream to write to. + * @param preserveNodes Should all OLE2 streams be written back out, or only the common ones? + * @throws IOException If there is an unexpected IOException from + * the passed in OutputStream + */ + public void write(OutputStream out, boolean preserveNodes) throws IOException { + // read properties and pictures, with old encryption settings where appropriate + if(_pictures == null) { + readPictures(); + } + getDocumentSummaryInformation(); + + // set new encryption settings + HSLFSlideShowEncrypted encryptedSS = new HSLFSlideShowEncrypted(getDocumentEncryptionAtom()); + _records = encryptedSS.updateEncryptionRecord(_records); + + // Get a new Filesystem to write into + POIFSFileSystem outFS = new POIFSFileSystem(); + + // The list of entries we've written out + List writtenEntries = new ArrayList(1); + + // Write out the Property Streams + writeProperties(outFS, writtenEntries); + + BufAccessBAOS baos = new BufAccessBAOS(); + + // For position dependent records, hold where they were and now are + // As we go along, update, and hand over, to any Position Dependent + // records we happen across + updateAndWriteDependantRecords(baos, null); + + // Update our cached copy of the bytes that make up the PPT stream + _docstream = new byte[baos.size()]; + System.arraycopy(baos.getBuf(), 0, _docstream, 0, baos.size()); + + // Write the PPT stream into the POIFS layer + ByteArrayInputStream bais = new ByteArrayInputStream(_docstream); + outFS.createDocument(bais,"PowerPoint Document"); + writtenEntries.add("PowerPoint Document"); + + currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null); + currentUser.writeToFS(outFS); + writtenEntries.add("Current User"); + + + if (_pictures.size() > 0) { + BufAccessBAOS pict = new BufAccessBAOS(); + for (HSLFPictureData p : _pictures) { + int offset = pict.size(); + p.write(pict); + encryptedSS.encryptPicture(pict.getBuf(), offset); + } + outFS.createDocument( + new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures" + ); + writtenEntries.add("Pictures"); + } + + // If requested, write out any other streams we spot + if(preserveNodes) { + EntryUtils.copyNodes(directory.getFileSystem(), outFS, writtenEntries); + } + + // Send the POIFSFileSystem object out to the underlying stream + outFS.writeFilesystem(out); + } + + /** + * For a given named property entry, either return it or null if + * if it wasn't found + * + * @param setName The property to read + * @return The value of the given property or null if it wasn't found. + */ + protected PropertySet getPropertySet(String setName) { + DocumentEncryptionAtom dea = getDocumentEncryptionAtom(); + return (dea == null) + ? super.getPropertySet(setName) + : super.getPropertySet(setName, dea.getEncryptionInfo()); + } + + /** + * Writes out the standard Documment Information Properties (HPSF) + * @param outFS the POIFSFileSystem to write the properties into + * @param writtenEntries a list of POIFS entries to add the property names too + * + * @throws IOException if an error when writing to the + * {@link POIFSFileSystem} occurs + */ + protected void writeProperties(POIFSFileSystem outFS, List writtenEntries) throws IOException { + super.writeProperties(outFS, writtenEntries); + DocumentEncryptionAtom dea = getDocumentEncryptionAtom(); + if (dea != null) { + CryptoAPIEncryptor enc = (CryptoAPIEncryptor)dea.getEncryptionInfo().getEncryptor(); + try { + enc.getDataStream(outFS.getRoot()); // ignore OutputStream + } catch (IOException e) { + throw e; + } catch (GeneralSecurityException e) { + throw new IOException(e); + } + } + } + + /* ******************* adding methods follow ********************* */ + + /** + * Adds a new root level record, at the end, but before the last + * PersistPtrIncrementalBlock. + */ + public synchronized int appendRootLevelRecord(Record newRecord) { + int addedAt = -1; + Record[] r = new Record[_records.length+1]; + boolean added = false; + for(int i=(_records.length-1); i>=0; i--) { + if(added) { + // Just copy over + r[i] = _records[i]; + } else { + r[(i+1)] = _records[i]; + if(_records[i] instanceof PersistPtrHolder) { + r[i] = newRecord; + added = true; + addedAt = i; + } + } + } + _records = r; + return addedAt; + } + + /** + * Add a new picture to this presentation. + * + * @return offset of this picture in the Pictures stream + */ + public int addPicture(HSLFPictureData img) { + // Process any existing pictures if we haven't yet + if(_pictures == null) { + try { + readPictures(); + } catch(IOException e) { + throw new CorruptPowerPointFileException(e.getMessage()); + } + } + + // Add the new picture in + int offset = 0; + if(_pictures.size() > 0) { + HSLFPictureData prev = _pictures.get(_pictures.size() - 1); + offset = prev.getOffset() + prev.getRawData().length + 8; + } + img.setOffset(offset); + _pictures.add(img); + return offset; + } + + /* ******************* fetching methods follow ********************* */ + + + /** + * Returns an array of all the records found in the slideshow + */ + public Record[] getRecords() { return _records; } + + /** + * Returns an array of the bytes of the file. Only correct after a + * call to open or write - at all other times might be wrong! + */ + public byte[] getUnderlyingBytes() { return _docstream; } + + /** + * Fetch the Current User Atom of the document + */ + public CurrentUserAtom getCurrentUserAtom() { return currentUser; } + + /** + * Return array of pictures contained in this presentation + * + * @return array with the read pictures or null if the + * presentation doesn't contain pictures. + */ + public HSLFPictureData[] getPictures() { + if(_pictures == null) { + try { + readPictures(); + } catch(IOException e) { + throw new CorruptPowerPointFileException(e.getMessage()); + } + } + + return _pictures.toArray(new HSLFPictureData[_pictures.size()]); + } + + /** + * Gets embedded object data from the slide show. + * + * @return the embedded objects. + */ + public HSLFObjectData[] getEmbeddedObjects() { + if (_objects == null) { + List objects = new ArrayList(); + for (Record r : _records) { + if (r instanceof ExOleObjStg) { + objects.add(new HSLFObjectData((ExOleObjStg)r)); + } + } + _objects = objects.toArray(new HSLFObjectData[objects.size()]); + } + return _objects; + } + + + private static class BufAccessBAOS extends ByteArrayOutputStream { + public byte[] getBuf() { + return buf; + } + } + + private static class CountingOS extends OutputStream { + int count = 0; + public void write(int b) throws IOException { + count++; + } + + public void write(byte[] b) throws IOException { + count += b.length; + } + + public void write(byte[] b, int off, int len) throws IOException { + count += len; + } + + public int size() { + return count; + } + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextBox.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextBox.java new file mode 100644 index 0000000000..25ea585c95 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextBox.java @@ -0,0 +1,92 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import org.apache.poi.ddf.*; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.sl.usermodel.ShapeType; + +/** + * Represents a TextFrame shape in PowerPoint. + *

    + * Contains the text in a text frame as well as the properties and methods + * that control alignment and anchoring of the text. + *

    + * + * @author Yegor Kozlov + */ +public class HSLFTextBox extends HSLFTextShape { + + /** + * Create a TextBox object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected HSLFTextBox(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + * @param parent the parent of this Shape. For example, if this text box is a cell + * in a table then the parent is Table. + */ + public HSLFTextBox(ShapeContainer parent){ + super(parent); + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + */ + public HSLFTextBox(){ + this(null); + } + + /** + * Create a new TextBox and initialize its internal structures + * + * @return the created EscherContainerRecord which holds shape data + */ + protected EscherContainerRecord createSpContainer(boolean isChild){ + _escherContainer = super.createSpContainer(isChild); + + setShapeType(ShapeType.TEXT_BOX); + + //set default properties for a TextBox + setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); + setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000); + setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100000); + setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001); + setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000); + setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); + + _txtrun = createTextRun(); + + return _escherContainer; + } + + protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){ + setVerticalAlignment(HSLFTextBox.AnchorTop); + setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002); + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextParagraph.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextParagraph.java new file mode 100644 index 0000000000..b23c997dbe --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextParagraph.java @@ -0,0 +1,744 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.apache.poi.hslf.model.textproperties.TextPropCollection; +import org.apache.poi.hslf.record.PPDrawing; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordContainer; +import org.apache.poi.hslf.record.SlideListWithText; +import org.apache.poi.hslf.record.StyleTextProp9Atom; +import org.apache.poi.hslf.record.StyleTextPropAtom; +import org.apache.poi.hslf.record.TextBytesAtom; +import org.apache.poi.hslf.record.TextCharsAtom; +import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.record.TextRulerAtom; +import org.apache.poi.hslf.record.TextSpecInfoAtom; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.sl.usermodel.TextParagraph; +import org.apache.poi.util.StringUtil; + +/** + * This class represents a run of text in a powerpoint document. That + * run could be text on a sheet, or text in a note. + * It is only a very basic class for now + * + * @author Nick Burch + */ + +public final class HSLFTextParagraph implements TextParagraph +{ + // Note: These fields are protected to help with unit testing + // Other classes shouldn't really go playing with them! + protected TextHeaderAtom _headerAtom; + protected TextBytesAtom _byteAtom; + protected TextCharsAtom _charAtom; + protected StyleTextPropAtom _styleAtom; + protected TextRulerAtom _ruler; + protected boolean _isUnicode; + protected HSLFTextRun[] _rtRuns; + protected HSLFTextShape _parentShape; + // private SlideShow slideShow; + private HSLFSheet _sheet; + private int shapeId; + private int slwtIndex = -1; //position in the owning SlideListWithText + /** + * all text run records that follow TextHeaderAtom. + * (there can be misc InteractiveInfo, TxInteractiveInfo and other records) + */ + protected Record[] _records; + // private StyleTextPropAtom styleTextPropAtom; + private StyleTextProp9Atom styleTextProp9Atom; + + /** + * Constructs a Text Run from a Unicode text block + * + * @param tha the TextHeaderAtom that defines what's what + * @param tca the TextCharsAtom containing the text + * @param sta the StyleTextPropAtom which defines the character stylings + */ + public HSLFTextParagraph(TextHeaderAtom tha, TextCharsAtom tca, StyleTextPropAtom sta) { + this(tha,null,tca,sta); + } + + /** + * Constructs a Text Run from a Ascii text block + * + * @param tha the TextHeaderAtom that defines what's what + * @param tba the TextBytesAtom containing the text + * @param sta the StyleTextPropAtom which defines the character stylings + */ + public HSLFTextParagraph(TextHeaderAtom tha, TextBytesAtom tba, StyleTextPropAtom sta) { + this(tha,tba,null,sta); + } + + /** + * Internal constructor and initializer + */ + private HSLFTextParagraph(TextHeaderAtom tha, TextBytesAtom tba, TextCharsAtom tca, StyleTextPropAtom sta) { + _headerAtom = tha; + _styleAtom = sta; + if(tba != null) { + _byteAtom = tba; + _isUnicode = false; + } else { + _charAtom = tca; + _isUnicode = true; + } + String runRawText = getText(); + + // Figure out the rich text runs + LinkedList pStyles = new LinkedList(); + LinkedList cStyles = new LinkedList(); + if(_styleAtom != null) { + // Get the style atom to grok itself + _styleAtom.setParentTextSize(runRawText.length()); + pStyles = _styleAtom.getParagraphStyles(); + cStyles = _styleAtom.getCharacterStyles(); + } + buildRichTextRuns(pStyles, cStyles, runRawText); + } + + public void buildRichTextRuns(LinkedList pStyles, LinkedList cStyles, String runRawText){ + + // Handle case of no current style, with a default + if(pStyles.size() == 0 || cStyles.size() == 0) { + _rtRuns = new HSLFTextRun[1]; + _rtRuns[0] = new HSLFTextRun(this, 0, runRawText.length()); + } else { + // Build up Rich Text Runs, one for each + // character/paragraph style pair + List rtrs = new ArrayList(); + + int pos = 0; + + int curP = 0; + int curC = 0; + int pLenRemain = -1; + int cLenRemain = -1; + + // Build one for each run with the same style + while(pos <= runRawText.length() && curP < pStyles.size() && curC < cStyles.size()) { + // Get the Props to use + TextPropCollection pProps = pStyles.get(curP); + TextPropCollection cProps = cStyles.get(curC); + + int pLen = pProps.getCharactersCovered(); + int cLen = cProps.getCharactersCovered(); + + // Handle new pass + boolean freshSet = false; + if(pLenRemain == -1 && cLenRemain == -1) { freshSet = true; } + if(pLenRemain == -1) { pLenRemain = pLen; } + if(cLenRemain == -1) { cLenRemain = cLen; } + + // So we know how to build the eventual run + int runLen = -1; + boolean pShared = false; + boolean cShared = false; + + // Same size, new styles - neither shared + if(pLen == cLen && freshSet) { + runLen = cLen; + pShared = false; + cShared = false; + curP++; + curC++; + pLenRemain = -1; + cLenRemain = -1; + } else { + // Some sharing + + // See if we are already in a shared block + if(pLenRemain < pLen) { + // Existing shared p block + pShared = true; + + // Do we end with the c block, or either side of it? + if(pLenRemain == cLenRemain) { + // We end at the same time + cShared = false; + runLen = pLenRemain; + curP++; + curC++; + pLenRemain = -1; + cLenRemain = -1; + } else if(pLenRemain < cLenRemain) { + // We end before the c block + cShared = true; + runLen = pLenRemain; + curP++; + cLenRemain -= pLenRemain; + pLenRemain = -1; + } else { + // We end after the c block + cShared = false; + runLen = cLenRemain; + curC++; + pLenRemain -= cLenRemain; + cLenRemain = -1; + } + } else if(cLenRemain < cLen) { + // Existing shared c block + cShared = true; + + // Do we end with the p block, or either side of it? + if(pLenRemain == cLenRemain) { + // We end at the same time + pShared = false; + runLen = cLenRemain; + curP++; + curC++; + pLenRemain = -1; + cLenRemain = -1; + } else if(cLenRemain < pLenRemain) { + // We end before the p block + pShared = true; + runLen = cLenRemain; + curC++; + pLenRemain -= cLenRemain; + cLenRemain = -1; + } else { + // We end after the p block + pShared = false; + runLen = pLenRemain; + curP++; + cLenRemain -= pLenRemain; + pLenRemain = -1; + } + } else { + // Start of a shared block + if(pLenRemain < cLenRemain) { + // Shared c block + pShared = false; + cShared = true; + runLen = pLenRemain; + curP++; + cLenRemain -= pLenRemain; + pLenRemain = -1; + } else { + // Shared p block + pShared = true; + cShared = false; + runLen = cLenRemain; + curC++; + pLenRemain -= cLenRemain; + cLenRemain = -1; + } + } + } + + // Wind on + int prevPos = pos; + pos += runLen; + // Adjust for end-of-run extra 1 length + if(pos > runRawText.length()) { + runLen--; + } + + // Save + HSLFTextRun rtr = new HSLFTextRun(this, prevPos, runLen, pProps, cProps, pShared, cShared); + rtrs.add(rtr); + } + + // Build the array + _rtRuns = rtrs.toArray(new HSLFTextRun[rtrs.size()]); + } + + } + + // Update methods follow + + /** + * Adds the supplied text onto the end of the TextRun, + * creating a new RichTextRun (returned) for it to + * sit in. + * In many cases, before calling this, you'll want to add + * a newline onto the end of your last RichTextRun + */ + public HSLFTextRun appendText(String s) { + // We will need a StyleTextProp atom + ensureStyleAtomPresent(); + + // First up, append the text to the + // underlying text atom + int oldSize = getRawText().length(); + storeText( + getRawText() + s + ); + + // If either of the previous styles overran + // the text by one, we need to shuffle that + // extra character onto the new ones + int pOverRun = _styleAtom.getParagraphTextLengthCovered() - oldSize; + int cOverRun = _styleAtom.getCharacterTextLengthCovered() - oldSize; + if(pOverRun > 0) { + TextPropCollection tpc = _styleAtom.getParagraphStyles().getLast(); + tpc.updateTextSize( + tpc.getCharactersCovered() - pOverRun + ); + } + if(cOverRun > 0) { + TextPropCollection tpc = _styleAtom.getCharacterStyles().getLast(); + tpc.updateTextSize( + tpc.getCharactersCovered() - cOverRun + ); + } + + // Next, add the styles for its paragraph and characters + TextPropCollection newPTP = + _styleAtom.addParagraphTextPropCollection(s.length()+pOverRun); + TextPropCollection newCTP = + _styleAtom.addCharacterTextPropCollection(s.length()+cOverRun); + + // Now, create the new RichTextRun + HSLFTextRun nr = new HSLFTextRun( + this, oldSize, s.length(), + newPTP, newCTP, false, false + ); + + // Add the new RichTextRun onto our list + HSLFTextRun[] newRuns = new HSLFTextRun[_rtRuns.length+1]; + System.arraycopy(_rtRuns, 0, newRuns, 0, _rtRuns.length); + newRuns[newRuns.length-1] = nr; + _rtRuns = newRuns; + + // And return the new run to the caller + return nr; + } + + /** + * Saves the given string to the records. Doesn't + * touch the stylings. + */ + private void storeText(String s) { + // Store in the appropriate record + if(_isUnicode) { + // The atom can safely convert to unicode + _charAtom.setText(s); + } else { + // Will it fit in a 8 bit atom? + boolean hasMultibyte = StringUtil.hasMultibyte(s); + if(! hasMultibyte) { + // Fine to go into 8 bit atom + byte[] text = new byte[s.length()]; + StringUtil.putCompressedUnicode(s,text,0); + _byteAtom.setText(text); + } else { + // Need to swap a TextBytesAtom for a TextCharsAtom + + // Build the new TextCharsAtom + _charAtom = new TextCharsAtom(); + _charAtom.setText(s); + + // Use the TextHeaderAtom to do the swap on the parent + RecordContainer parent = _headerAtom.getParentRecord(); + Record[] cr = parent.getChildRecords(); + for(int i=0; i pStyles = _styleAtom.getParagraphStyles(); + while(pStyles.size() > 1) { pStyles.removeLast(); } + + if (!pStyles.isEmpty()) { + pStyles.getFirst().updateTextSize( s.length()+1 ); + } + + LinkedList cStyles = _styleAtom.getCharacterStyles(); + while(cStyles.size() > 1) { cStyles.removeLast(); } + + if (!cStyles.isEmpty()) { + cStyles.getFirst().updateTextSize( s.length()+1 ); + } + + _rtRuns[0].setText(s); + } else { + // Recreate rich text run with no styling + _rtRuns[0] = new HSLFTextRun(this,0,s.length()); + } + + } + + /** + * Changes the text. + * Converts '\r' into '\n' + */ + public void setText(String s) { + String text = normalize(s); + setRawText(text); + } + + /** + * Ensure a StyleTextPropAtom is present for this run, + * by adding if required. Normally for internal TextRun use. + */ + public void ensureStyleAtomPresent() { + if(_styleAtom != null) { + // All there + return; + } + + // Create a new one at the right size + _styleAtom = new StyleTextPropAtom(getRawText().length() + 1); + + // Use the TextHeader atom to get at the parent + RecordContainer runAtomsParent = _headerAtom.getParentRecord(); + + // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom + Record addAfter = _byteAtom; + if(_byteAtom == null) { addAfter = _charAtom; } + runAtomsParent.addChildAfter(_styleAtom, addAfter); + + // Feed this to our sole rich text run + if(_rtRuns.length != 1) { + throw new IllegalStateException("Needed to add StyleTextPropAtom when had many rich text runs"); + } + // These are the only styles for now + _rtRuns[0].supplyTextProps( + _styleAtom.getParagraphStyles().get(0), + _styleAtom.getCharacterStyles().get(0), + false, + false + ); + } + + // Accesser methods follow + + /** + * Returns the text content of the run, which has been made safe + * for printing and other use. + */ + public String getText() { + String rawText = getRawText(); + + // PowerPoint seems to store files with \r as the line break + // The messes things up on everything but a Mac, so translate + // them to \n + String text = rawText.replace('\r','\n'); + + int type = _headerAtom == null ? 0 : _headerAtom.getTextType(); + if(type == TextHeaderAtom.TITLE_TYPE || type == TextHeaderAtom.CENTER_TITLE_TYPE){ + //0xB acts like cariage return in page titles and like blank in the others + text = text.replace((char) 0x0B, '\n'); + } else { + text = text.replace((char) 0x0B, ' '); + } + return text; + } + + /** + * Returns the raw text content of the run. This hasn't had any + * changes applied to it, and so is probably unlikely to print + * out nicely. + */ + public String getRawText() { + if(_isUnicode) { + return _charAtom.getText(); + } + return _byteAtom.getText(); + } + + /** + * Fetch the rich text runs (runs of text with the same styling) that + * are contained within this block of text + */ + public HSLFTextRun[] getRichTextRuns() { + return _rtRuns; + } + + /** + * Returns the type of the text, from the TextHeaderAtom. + * Possible values can be seen from TextHeaderAtom + * @see org.apache.poi.hslf.record.TextHeaderAtom + */ + public int getRunType() { + return _headerAtom.getTextType(); + } + + /** + * Changes the type of the text. Values should be taken + * from TextHeaderAtom. No checking is done to ensure you + * set this to a valid value! + * @see org.apache.poi.hslf.record.TextHeaderAtom + */ + public void setRunType(int type) { + _headerAtom.setTextType(type); + } + + /** + * Supply the Sheet we belong to, which might have an assigned SlideShow + * Also passes it on to our child RichTextRuns + */ + public void supplySheet(HSLFSheet sheet){ + this._sheet = sheet; + + if (_rtRuns == null) return; + for(HSLFTextRun rt : _rtRuns) { + rt.updateSheet(); + } + } + + public HSLFSheet getSheet(){ + return this._sheet; + } + + /** + * @return Shape ID + */ + protected int getShapeId(){ + return shapeId; + } + + /** + * @param id Shape ID + */ + protected void setShapeId(int id){ + shapeId = id; + } + + /** + * @return 0-based index of the text run in the SLWT container + */ + protected int getIndex(){ + return slwtIndex; + } + + /** + * @param id 0-based index of the text run in the SLWT container + */ + protected void setIndex(int id){ + slwtIndex = id; + } + + /** + * Is this Text Run one from a {@link PPDrawing}, or is it + * one from the {@link SlideListWithText}? + */ + public boolean isDrawingBased() { + return (slwtIndex == -1); + } + + /** + * Returns the array of all hyperlinks in this text run + * + * @return the array of all hyperlinks in this text run + * or null if not found. + */ + public Hyperlink[] getHyperlinks(){ + return Hyperlink.find(this); + } + + /** + * Fetch RichTextRun at a given position + * + * @param pos 0-based index in the text + * @return RichTextRun or null if not found + */ + public HSLFTextRun getRichTextRunAt(int pos){ + for (int i = 0; i < _rtRuns.length; i++) { + int start = _rtRuns[i].getStartIndex(); + int end = _rtRuns[i].getEndIndex(); + if(pos >= start && pos < end) return _rtRuns[i]; + } + return null; + } + + public TextRulerAtom getTextRuler(){ + if(_ruler == null){ + if(_records != null) for (int i = 0; i < _records.length; i++) { + if(_records[i] instanceof TextRulerAtom) { + _ruler = (TextRulerAtom)_records[i]; + break; + } + } + + } + return _ruler; + + } + + public TextRulerAtom createTextRuler(){ + _ruler = getTextRuler(); + if(_ruler == null){ + _ruler = TextRulerAtom.getParagraphInstance(); + _headerAtom.getParentRecord().appendChildRecord(_ruler); + } + return _ruler; + } + + /** + * Returns a new string with line breaks converted into internal ppt representation + */ + public String normalize(String s){ + String ns = s.replaceAll("\\r?\\n", "\r"); + return ns; + } + + /** + * Returns records that make up this text run + * + * @return text run records + */ + public Record[] getRecords(){ + return _records; + } + /** Numbered List info */ + public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { + this.styleTextProp9Atom = styleTextProp9Atom; + } + /** Numbered List info */ + public StyleTextProp9Atom getStyleTextProp9Atom() { + return this.styleTextProp9Atom; + } + + /** Characters covered */ + public StyleTextPropAtom getStyleTextPropAtom() { + return this._styleAtom; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextShape.java new file mode 100644 index 0000000000..17e8b81d21 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HSLFTextShape.java @@ -0,0 +1,639 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.model; + +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherProperties; +import org.apache.poi.ddf.EscherSimpleProperty; +import org.apache.poi.ddf.EscherSpRecord; +import org.apache.poi.ddf.EscherTextboxRecord; +import org.apache.poi.hslf.exceptions.HSLFException; +import org.apache.poi.hslf.record.EscherTextboxWrapper; +import org.apache.poi.hslf.record.InteractiveInfo; +import org.apache.poi.hslf.record.InteractiveInfoAtom; +import org.apache.poi.hslf.record.OEPlaceholderAtom; +import org.apache.poi.hslf.record.OutlineTextRefAtom; +import org.apache.poi.hslf.record.PPDrawing; +import org.apache.poi.hslf.record.Record; +import org.apache.poi.hslf.record.RecordTypes; +import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; +import org.apache.poi.hslf.record.StyleTextPropAtom; +import org.apache.poi.hslf.record.TextBytesAtom; +import org.apache.poi.hslf.record.TextCharsAtom; +import org.apache.poi.hslf.record.TextHeaderAtom; +import org.apache.poi.hslf.record.TxInteractiveInfoAtom; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.sl.usermodel.ShapeContainer; +import org.apache.poi.util.POILogger; + +/** + * A common superclass of all shapes that can hold text. + * + * @author Yegor Kozlov + */ +public abstract class HSLFTextShape extends HSLFSimpleShape { + + /** + * How to anchor the text + */ + public static final int AnchorTop = 0; + public static final int AnchorMiddle = 1; + public static final int AnchorBottom = 2; + public static final int AnchorTopCentered = 3; + public static final int AnchorMiddleCentered = 4; + public static final int AnchorBottomCentered = 5; + public static final int AnchorTopBaseline = 6; + public static final int AnchorBottomBaseline = 7; + public static final int AnchorTopCenteredBaseline = 8; + public static final int AnchorBottomCenteredBaseline = 9; + + /** + * How to wrap the text + */ + public static final int WrapSquare = 0; + public static final int WrapByPoints = 1; + public static final int WrapNone = 2; + public static final int WrapTopBottom = 3; + public static final int WrapThrough = 4; + + /** + * How to align the text + */ + public static final int AlignLeft = 0; + public static final int AlignCenter = 1; + public static final int AlignRight = 2; + public static final int AlignJustify = 3; + + /** + * TextRun object which holds actual text and format data + */ + protected HSLFTextParagraph _txtrun; + + /** + * Escher container which holds text attributes such as + * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc. + */ + protected EscherTextboxWrapper _txtbox; + + /** + * Used to calculate text bounds + */ + protected static final FontRenderContext _frc = new FontRenderContext(null, true, true); + + /** + * Create a TextBox object and initialize it from the supplied Record container. + * + * @param escherRecord EscherSpContainer container which holds information about this shape + * @param parent the parent of the shape + */ + protected HSLFTextShape(EscherContainerRecord escherRecord, ShapeContainer parent){ + super(escherRecord, parent); + + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + * @param parent the parent of this Shape. For example, if this text box is a cell + * in a table then the parent is Table. + */ + public HSLFTextShape(ShapeContainer parent){ + super(null, parent); + _escherContainer = createSpContainer(parent instanceof HSLFGroupShape); + } + + /** + * Create a new TextBox. This constructor is used when a new shape is created. + * + */ + public HSLFTextShape(){ + this(null); + } + + public HSLFTextParagraph createTextRun(){ + _txtbox = getEscherTextboxWrapper(); + if(_txtbox == null) _txtbox = new EscherTextboxWrapper(); + + _txtrun = getTextParagraph(); + if(_txtrun == null){ + TextHeaderAtom tha = new TextHeaderAtom(); + tha.setParentRecord(_txtbox); + _txtbox.appendChildRecord(tha); + + TextCharsAtom tca = new TextCharsAtom(); + _txtbox.appendChildRecord(tca); + + StyleTextPropAtom sta = new StyleTextPropAtom(0); + _txtbox.appendChildRecord(sta); + + _txtrun = new HSLFTextParagraph(tha,tca,sta); + _txtrun._records = new Record[]{tha, tca, sta}; + _txtrun.setText(""); + + _escherContainer.addChildRecord(_txtbox.getEscherRecord()); + + setDefaultTextProperties(_txtrun); + } + + return _txtrun; + } + + /** + * Set default properties for the TextRun. + * Depending on the text and shape type the defaults are different: + * TextBox: align=left, valign=top + * AutoShape: align=center, valign=middle + * + */ + protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){ + + } + + /** + * Returns the text contained in this text frame. + * + * @return the text string for this textbox. + */ + public String getText(){ + HSLFTextParagraph tx = getTextParagraph(); + return tx == null ? null : tx.getText(); + } + + /** + * Sets the text contained in this text frame. + * + * @param text the text string used by this object. + */ + public void setText(String text){ + HSLFTextParagraph tx = getTextParagraph(); + if(tx == null){ + tx = createTextRun(); + } + tx.setText(text); + setTextId(text.hashCode()); + } + + /** + * When a textbox is added to a sheet we need to tell upper-level + * PPDrawing about it. + * + * @param sh the sheet we are adding to + */ + protected void afterInsert(HSLFSheet sh){ + super.afterInsert(sh); + + EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); + if(_txtbox != null){ + PPDrawing ppdrawing = sh.getPPDrawing(); + ppdrawing.addTextboxWrapper(_txtbox); + // Ensure the escher layer knows about the added records + try { + _txtbox.writeOut(null); + } catch (IOException e){ + throw new HSLFException(e); + } + if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText(); + } + if(_txtrun != null) { + _txtrun.setShapeId(getShapeId()); + sh.onAddTextShape(this); + } + } + + protected EscherTextboxWrapper getEscherTextboxWrapper(){ + if(_txtbox == null){ + EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID); + if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord); + } + return _txtbox; + } + /** + * Adjust the size of the TextShape so it encompasses the text inside it. + * + * @return a Rectangle2D that is the bounds of this TextShape. + */ + public Rectangle2D resizeToFitText(){ + String txt = getText(); + if(txt == null || txt.length() == 0) return new Rectangle2D.Float(); + + HSLFTextRun rt = getTextParagraph().getRichTextRuns()[0]; + int size = rt.getFontSize(); + int style = 0; + if (rt.isBold()) style |= Font.BOLD; + if (rt.isItalic()) style |= Font.ITALIC; + String fntname = rt.getFontName(); + Font font = new Font(fntname, style, size); + + float width = 0, height = 0, leading = 0; + String[] lines = txt.split("\n"); + for (int i = 0; i < lines.length; i++) { + if(lines[i].length() == 0) continue; + + TextLayout layout = new TextLayout(lines[i], font, _frc); + + leading = Math.max(leading, layout.getLeading()); + width = Math.max(width, layout.getAdvance()); + height = Math.max(height, (height + (layout.getDescent() + layout.getAscent()))); + } + + // add one character to width + Rectangle2D charBounds = font.getMaxCharBounds(_frc); + width += getMarginLeft() + getMarginRight() + charBounds.getWidth(); + + // add leading to height + height += getMarginTop() + getMarginBottom() + leading; + + Rectangle2D anchor = getAnchor2D(); + anchor.setRect(anchor.getX(), anchor.getY(), width, height); + setAnchor(anchor); + + return anchor; + } + + /** + * Returns the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @return the type of alignment + */ + public int getVerticalAlignment(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT); + int valign = HSLFTextShape.AnchorTop; + if (prop == null){ + /** + * If vertical alignment was not found in the shape properties then try to + * fetch the master shape and search for the align property there. + */ + int type = getTextParagraph().getRunType(); + HSLFMasterSheet master = getSheet().getMasterSheet(); + if(master != null){ + HSLFTextShape masterShape = master.getPlaceholderByTextType(type); + if(masterShape != null) valign = masterShape.getVerticalAlignment(); + } else { + //not found in the master sheet. Use the hardcoded defaults. + switch (type){ + case TextHeaderAtom.TITLE_TYPE: + case TextHeaderAtom.CENTER_TITLE_TYPE: + valign = HSLFTextShape.AnchorMiddle; + break; + default: + valign = HSLFTextShape.AnchorTop; + break; + } + } + } else { + valign = prop.getPropertyValue(); + } + return valign; + } + + /** + * Sets the type of vertical alignment for the text. + * One of the Anchor* constants defined in this class. + * + * @param align - the type of alignment + */ + public void setVerticalAlignment(int align){ + setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align); + } + + /** + * Sets the type of horizontal alignment for the text. + * One of the Align* constants defined in this class. + * + * @param align - the type of horizontal alignment + */ + public void setHorizontalAlignment(int align){ + HSLFTextParagraph tx = getTextParagraph(); + if(tx != null) tx.getRichTextRuns()[0].setAlignment(align); + } + + /** + * Gets the type of horizontal alignment for the text. + * One of the Align* constants defined in this class. + * + * @return align - the type of horizontal alignment + */ + public int getHorizontalAlignment(){ + HSLFTextParagraph tx = getTextParagraph(); + return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment(); + } + + /** + * Returns the distance (in points) between the bottom of the text frame + * and the bottom of the inscribed rectangle of the shape that contains the text. + * Default value is 1/20 inch. + * + * @return the botom margin + */ + public float getMarginBottom(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); + int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the botom margin. + * @see #getMarginBottom() + * + * @param margin the bottom margin + */ + public void setMarginBottom(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the left edge of the text frame + * and the left edge of the inscribed rectangle of the shape that contains + * the text. + * Default value is 1/10 inch. + * + * @return the left margin + */ + public float getMarginLeft(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT); + int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the left margin. + * @see #getMarginLeft() + * + * @param margin the left margin + */ + public void setMarginLeft(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the right edge of the + * text frame and the right edge of the inscribed rectangle of the shape + * that contains the text. + * Default value is 1/10 inch. + * + * @return the right margin + */ + public float getMarginRight(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); + int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the right margin. + * @see #getMarginRight() + * + * @param margin the right margin + */ + public void setMarginRight(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT)); + } + + /** + * Returns the distance (in points) between the top of the text frame + * and the top of the inscribed rectangle of the shape that contains the text. + * Default value is 1/20 inch. + * + * @return the top margin + */ + public float getMarginTop(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); + int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); + return (float)val/EMU_PER_POINT; + } + + /** + * Sets the top margin. + * @see #getMarginTop() + * + * @param margin the top margin + */ + public void setMarginTop(float margin){ + setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT)); + } + + + /** + * Returns the value indicating word wrap. + * + * @return the value indicating word wrap. + * Must be one of the Wrap* constants defined in this class. + */ + public int getWordWrap(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); + return prop == null ? WrapSquare : prop.getPropertyValue(); + } + + /** + * Specifies how the text should be wrapped + * + * @param wrap the value indicating how the text should be wrapped. + * Must be one of the Wrap* constants defined in this class. + */ + public void setWordWrap(int wrap){ + setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap); + } + + /** + * @return id for the text. + */ + public int getTextId(){ + EscherOptRecord opt = getEscherOptRecord(); + EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTID); + return prop == null ? 0 : prop.getPropertyValue(); + } + + /** + * Sets text ID + * + * @param id of the text + */ + public void setTextId(int id){ + setEscherProperty(EscherProperties.TEXT__TEXTID, id); + } + + /** + * @return the TextRun object for this text box + */ + public HSLFTextParagraph getTextParagraph(){ + if (null == this._txtrun) initTextRun(); + if (null == this._txtrun && null != this._txtbox) { + TextHeaderAtom tha = null; + TextBytesAtom tba = null; + TextCharsAtom tca = null; + StyleTextPropAtom sta = null; + Record[] childRecords = this._txtbox.getChildRecords(); + for (Record r : childRecords) { + if (r instanceof TextHeaderAtom) { + tha = (TextHeaderAtom) r; + } else if (r instanceof TextBytesAtom) { + tba = (TextBytesAtom) r; + } else if (r instanceof TextCharsAtom) { + tca = (TextCharsAtom) r; + } else if (r instanceof StyleTextPropAtom) { + sta = (StyleTextPropAtom) r; + } + } + if (tba != null) { + this._txtrun = new HSLFTextParagraph(tha, tba, sta); + } else if (tca != null) { + this._txtrun = new HSLFTextParagraph(tha, tca, sta); + } + } + return _txtrun; + } + + public void setSheet(HSLFSheet sheet) { + _sheet = sheet; + + // Initialize _txtrun object. + // (We can't do it in the constructor because the sheet + // is not assigned then, it's only built once we have + // all the records) + HSLFTextParagraph tx = getTextParagraph(); + if (tx != null) { + // Supply the sheet to our child RichTextRuns + tx.supplySheet(_sheet); + } + } + + protected void initTextRun(){ + EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); + HSLFSheet sheet = getSheet(); + + if(sheet == null || txtbox == null) return; + + OutlineTextRefAtom ota = null; + + Record[] child = txtbox.getChildRecords(); + for (int i = 0; i < child.length; i++) { + if (child[i] instanceof OutlineTextRefAtom) { + ota = (OutlineTextRefAtom)child[i]; + break; + } + } + + HSLFTextParagraph[] runs = _sheet.getTextRuns(); + if (ota != null) { + int idx = ota.getTextIndex(); + for (int i = 0; i < runs.length; i++) { + if(runs[i].getIndex() == idx){ + _txtrun = runs[i]; + break; + } + } + if(_txtrun == null) { + logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); + } + } else { + EscherSpRecord escherSpRecord = getEscherChild(EscherSpRecord.RECORD_ID); + int shapeId = escherSpRecord.getShapeId(); + if(runs != null) for (int i = 0; i < runs.length; i++) { + if(runs[i].getShapeId() == shapeId){ + _txtrun = runs[i]; + break; + } + } + } + + // ensure the same references child records of TextRun + if(_txtrun != null) { + for (int i = 0; i < child.length; i++) { + for (Record r : _txtrun.getRecords()) { + if (child[i].getRecordType() == r.getRecordType()) { + child[i] = r; + } + } + } + } + } + + public void draw(Graphics2D graphics){ + AffineTransform at = graphics.getTransform(); + ShapePainter.paint(this, graphics); + new TextPainter(this).paint(graphics); + graphics.setTransform(at); + } + + /** + * Return OEPlaceholderAtom, the atom that describes a placeholder. + * + * @return OEPlaceholderAtom or null if not found + */ + public OEPlaceholderAtom getPlaceholderAtom(){ + return getClientDataRecord(RecordTypes.OEPlaceholderAtom.typeID); + } + + /** + * + * Assigns a hyperlink to this text shape + * + * @param linkId id of the hyperlink, @see org.apache.poi.hslf.usermodel.SlideShow#addHyperlink(Hyperlink) + * @param beginIndex the beginning index, inclusive. + * @param endIndex the ending index, exclusive. + * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addHyperlink(Hyperlink) + */ + public void setHyperlink(int linkId, int beginIndex, int endIndex){ + //TODO validate beginIndex and endIndex and throw IllegalArgumentException + + InteractiveInfo info = new InteractiveInfo(); + InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); + infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); + infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url); + infoAtom.setHyperlinkID(linkId); + + _txtbox.appendChildRecord(info); + + TxInteractiveInfoAtom txiatom = new TxInteractiveInfoAtom(); + txiatom.setStartIndex(beginIndex); + txiatom.setEndIndex(endIndex); + _txtbox.appendChildRecord(txiatom); + + } + + @Override + public boolean isPlaceholder() { + OEPlaceholderAtom oep = getPlaceholderAtom(); + if (oep != null) return true; + + //special case for files saved in Office 2007 + RoundTripHFPlaceholder12 hldr = getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID); + if (hldr != null) return true; + + return false; + } + + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java index 8bb441e4e4..bd3a6da399 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/HeadersFooters.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.model; import org.apache.poi.hslf.record.*; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; /** * Header / Footer settings. @@ -31,19 +31,19 @@ public final class HeadersFooters { private HeadersFootersContainer _container; private boolean _newRecord; - private SlideShow _ppt; - private Sheet _sheet; + private HSLFSlideShow _ppt; + private HSLFSheet _sheet; private boolean _ppt2007; - public HeadersFooters(HeadersFootersContainer rec, SlideShow ppt, boolean newRecord, boolean isPpt2007){ + public HeadersFooters(HeadersFootersContainer rec, HSLFSlideShow ppt, boolean newRecord, boolean isPpt2007){ _container = rec; _newRecord = newRecord; _ppt = ppt; _ppt2007 = isPpt2007; } - public HeadersFooters(HeadersFootersContainer rec, Sheet sheet, boolean newRecord, boolean isPpt2007){ + public HeadersFooters(HeadersFootersContainer rec, HSLFSheet sheet, boolean newRecord, boolean isPpt2007){ _container = rec; _newRecord = newRecord; _sheet = sheet; @@ -240,8 +240,8 @@ public final class HeadersFooters { private boolean isVisible(int flag, int placeholderId){ boolean visible; if(_ppt2007){ - Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; - TextShape placeholder = master.getPlaceholder(placeholderId); + HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; + HSLFTextShape placeholder = master.getPlaceholder(placeholderId); visible = placeholder != null && placeholder.getText() != null; } else { visible = _container.getHeadersFootersAtom().getFlag(flag); @@ -252,8 +252,8 @@ public final class HeadersFooters { private String getPlaceholderText(int placeholderId, CString cs){ String text = null; if(_ppt2007){ - Sheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; - TextShape placeholder = master.getPlaceholder(placeholderId); + HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0]; + HSLFTextShape placeholder = master.getPlaceholder(placeholderId); if(placeholder != null) text = placeholder.getText(); //default text in master placeholders is not visible diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java b/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java index df207e6716..2e1f1ec586 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Hyperlink.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.model; import org.apache.poi.hslf.record.*; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherClientDataRecord; @@ -95,7 +95,7 @@ public final class Hyperlink { return address; } - public void setAddress(Slide slide) { + public void setAddress(HSLFSlide slide) { String href = slide._getSheetNumber() + ","+slide.getSlideNumber()+",Slide " + slide.getSlideNumber(); setAddress(href);; setTitle("Slide " + slide.getSlideNumber()); @@ -151,9 +151,9 @@ public final class Hyperlink { * @param run TextRun to lookup hyperlinks in * @return found hyperlinks or null if not found */ - protected static Hyperlink[] find(TextRun run){ + protected static Hyperlink[] find(HSLFTextParagraph run){ List lst = new ArrayList(); - SlideShow ppt = run.getSheet().getSlideShow(); + HSLFSlideShow ppt = run.getSheet().getSlideShow(); //document-level container which stores info about all links in a presentation ExObjList exobj = ppt.getDocumentRecord().getExObjList(); if (exobj == null) { @@ -178,7 +178,7 @@ public final class Hyperlink { */ protected static Hyperlink find(HSLFShape shape){ List lst = new ArrayList(); - SlideShow ppt = shape.getSheet().getSlideShow(); + HSLFSlideShow ppt = shape.getSheet().getSlideShow(); //document-level container which stores info about all links in a presentation ExObjList exobj = ppt.getDocumentRecord().getExObjList(); if (exobj == null) { diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java index e811aeb6bf..b2e0b35884 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java @@ -29,74 +29,7 @@ import java.awt.geom.Line2D; * * @author Yegor Kozlov */ -public final class Line extends SimpleShape { - /** - * Solid (continuous) pen - */ - public static final int PEN_SOLID = 1; - /** - * PS_DASH system dash style - */ - public static final int PEN_PS_DASH = 2; - /** - * PS_DOT system dash style - */ - public static final int PEN_DOT = 3; - /** - * PS_DASHDOT system dash style - */ - public static final int PEN_DASHDOT = 4; - /** - * PS_DASHDOTDOT system dash style - */ - public static final int PEN_DASHDOTDOT = 5; - /** - * square dot style - */ - public static final int PEN_DOTGEL = 6; - /** - * dash style - */ - public static final int PEN_DASH = 7; - /** - * long dash style - */ - public static final int PEN_LONGDASHGEL = 8; - /** - * dash short dash - */ - public static final int PEN_DASHDOTGEL = 9; - /** - * long dash short dash - */ - public static final int PEN_LONGDASHDOTGEL = 10; - /** - * long dash short dash short dash - */ - public static final int PEN_LONGDASHDOTDOTGEL = 11; - - /** - * Single line (of width lineWidth) - */ - public static final int LINE_SIMPLE = 0; - /** - * Double lines of equal width - */ - public static final int LINE_DOUBLE = 1; - /** - * Double lines, one thick, one thin - */ - public static final int LINE_THICKTHIN = 2; - /** - * Double lines, reverse order - */ - public static final int LINE_THINTHICK = 3; - /** - * Three lines, thin, thick, thin - */ - public static final int LINE_TRIPLE = 4; - - +public final class Line extends HSLFSimpleShape { protected Line(EscherContainerRecord escherRecord, ShapeContainer parent){ super(escherRecord, parent); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java deleted file mode 100644 index 5f7bd1a592..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MasterSheet.java +++ /dev/null @@ -1,55 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import org.apache.poi.hslf.record.SheetContainer; -import org.apache.poi.hslf.model.textproperties.TextProp; - -/** - * The superclass of all master sheets - Slide masters, Notes masters, etc. - * - * For now it's empty. When we understand more about masters in ppt we will add the common functionality here. - * - * @author Yegor Kozlov - */ -public abstract class MasterSheet extends Sheet { - public MasterSheet(SheetContainer container, int sheetNo){ - super(container, sheetNo); - } - - /** - * Pickup a style attribute from the master. - * This is the "workhorse" which returns the default style attrubutes. - */ - public abstract TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) ; - - - /** - * Checks if the shape is a placeholder. - * (placeholders aren't normal shapes, they are visible only in the Edit Master mode) - * - * - * @return true if the shape is a placeholder - */ - public static boolean isPlaceholder(HSLFShape shape){ - if(!(shape instanceof TextShape)) return false; - - TextShape tx = (TextShape)shape; - return tx.getPlaceholderAtom() != null; - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java index 834dc870e4..e366fdbe92 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/MovieShape.java @@ -24,7 +24,7 @@ import org.apache.poi.ddf.EscherContainerRecord; import org.apache.poi.ddf.EscherProperties; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.record.*; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.sl.usermodel.ShapeContainer; /** @@ -32,7 +32,7 @@ import org.apache.poi.sl.usermodel.ShapeContainer; * * @author Yegor Kozlov */ -public final class MovieShape extends Picture { +public final class MovieShape extends HSLFPictureShape { public static final int DEFAULT_MOVIE_THUMBNAIL = -1; public static final int MOVIE_MPEG = 1; @@ -113,7 +113,7 @@ public final class MovieShape extends Picture { /** * Assign a movie to this shape * - * @see org.apache.poi.hslf.usermodel.SlideShow#addMovie(String, int) + * @see org.apache.poi.hslf.usermodel.HSLFSlideShow#addMovie(String, int) * @param idx the index of the movie */ public void setMovieIndex(int idx){ @@ -154,7 +154,7 @@ public final class MovieShape extends Picture { OEShapeAtom oe = getClientDataRecord(RecordTypes.OEShapeAtom.typeID); int idx = oe.getOptions(); - SlideShow ppt = getSheet().getSlideShow(); + HSLFSlideShow ppt = getSheet().getSlideShow(); ExObjList lst = (ExObjList)ppt.getDocumentRecord().findFirstOfType(RecordTypes.ExObjList.typeID); if(lst == null) return null; diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java b/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java deleted file mode 100644 index cdb05030b4..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Notes.java +++ /dev/null @@ -1,66 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -/** - * This class represents a slide's notes in a PowerPoint Document. It - * allows access to the text within, and the layout. For now, it only - * does the text side of things though - * - * @author Nick Burch - */ - -public final class Notes extends Sheet -{ - private TextRun[] _runs; - - /** - * Constructs a Notes Sheet from the given Notes record. - * Initialises TextRuns, to provide easier access to the text - * - * @param notes the Notes record to read from - */ - public Notes (org.apache.poi.hslf.record.Notes notes) { - super(notes, notes.getNotesAtom().getSlideID()); - - // Now, build up TextRuns from pairs of TextHeaderAtom and - // one of TextBytesAtom or TextCharsAtom, found inside - // EscherTextboxWrapper's in the PPDrawing - _runs = findTextRuns(getPPDrawing()); - - // Set the sheet on each TextRun - for (int i = 0; i < _runs.length; i++) - _runs[i].setSheet(this); - } - - - // Accesser methods follow - - /** - * Returns an array of all the TextRuns found - */ - public TextRun[] getTextRuns() { return _runs; } - - /** - * Return null - Notes Masters are not yet supported - */ - public MasterSheet getMasterSheet() { - return null; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java index a1e9c94e08..49ed8c2073 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/OLEShape.java @@ -18,8 +18,8 @@ package org.apache.poi.hslf.model; import org.apache.poi.ddf.*; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.usermodel.ObjectData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFObjectData; import org.apache.poi.hslf.record.ExObjList; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.ExEmbed; @@ -34,7 +34,7 @@ import org.apache.poi.util.POILogger; * * @author Yegor Kozlov */ -public final class OLEShape extends Picture { +public final class OLEShape extends HSLFPictureShape { protected ExEmbed _exEmbed; /** @@ -117,13 +117,13 @@ public final class OLEShape extends Picture { * * @return the unique identifier for the OLE object */ - public ObjectData getObjectData(){ - SlideShow ppt = getSheet().getSlideShow(); - ObjectData[] ole = ppt.getEmbeddedObjects(); + public HSLFObjectData getObjectData(){ + HSLFSlideShow ppt = getSheet().getSlideShow(); + HSLFObjectData[] ole = ppt.getEmbeddedObjects(); //persist reference ExEmbed exEmbed = getExEmbed(); - ObjectData data = null; + HSLFObjectData data = null; if(exEmbed != null) { int ref = exEmbed.getExOleObjAtom().getObjStgDataRef(); @@ -156,7 +156,7 @@ public final class OLEShape extends Picture { */ public ExEmbed getExEmbed(){ if(_exEmbed == null){ - SlideShow ppt = getSheet().getSlideShow(); + HSLFSlideShow ppt = getSheet().getSlideShow(); ExObjList lst = ppt.getDocumentRecord().getExObjList(); if(lst == null){ diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java index f775addac3..47500df2f6 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java @@ -28,7 +28,7 @@ import java.awt.image.renderable.RenderableImage; import java.awt.geom.*; import java.text.AttributedCharacterIterator; import java.util.Map; -import org.apache.poi.hslf.usermodel.RichTextRun; +import org.apache.poi.hslf.usermodel.HSLFTextRun; import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogFactory; @@ -214,7 +214,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { */ public void draw(Shape shape){ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape)); - Freeform p = new Freeform(_group); + HSLFFreeformShape p = new HSLFFreeformShape(_group); p.setPath(path); p.getFill().setForegroundColor(null); applyStroke(p); @@ -250,12 +250,11 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { * @see #setClip */ public void drawString(String s, float x, float y) { - TextBox txt = new TextBox(_group); - txt.getTextRun().supplySlideShow(_group.getSheet().getSlideShow()); - txt.getTextRun().setSheet(_group.getSheet()); + HSLFTextBox txt = new HSLFTextBox(_group); + txt.getTextParagraph().supplySheet(_group.getSheet()); txt.setText(s); - RichTextRun rt = txt.getTextRun().getRichTextRuns()[0]; + HSLFTextRun rt = txt.getTextParagraph().getRichTextRuns()[0]; rt.setFontSize(_font.getSize()); rt.setFontName(_font.getFamily()); @@ -267,9 +266,9 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { txt.setMarginTop(0); txt.setMarginLeft(0); txt.setMarginRight(0); - txt.setWordWrap(TextBox.WrapNone); - txt.setHorizontalAlignment(TextBox.AlignLeft); - txt.setVerticalAlignment(TextBox.AnchorMiddle); + txt.setWordWrap(HSLFTextBox.WrapNone); + txt.setHorizontalAlignment(HSLFTextBox.AlignLeft); + txt.setVerticalAlignment(HSLFTextBox.AnchorMiddle); TextLayout layout = new TextLayout(s, _font, getFontRenderContext()); @@ -317,7 +316,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { */ public void fill(Shape shape){ GeneralPath path = new GeneralPath(_transform.createTransformedShape(shape)); - Freeform p = new Freeform(_group); + HSLFFreeformShape p = new HSLFFreeformShape(_group); p.setPath(path); applyPaint(p); p.setLineColor(null); //Fills must be "No Line" @@ -1788,7 +1787,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { } } - protected void applyStroke(SimpleShape shape) { + protected void applyStroke(HSLFSimpleShape shape) { if (_stroke instanceof BasicStroke){ BasicStroke bs = (BasicStroke)_stroke; shape.setLineWidth(bs.getLineWidth()); @@ -1800,7 +1799,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable { } } - protected void applyPaint(SimpleShape shape) { + protected void applyPaint(HSLFSimpleShape shape) { if (_paint instanceof Color) { shape.getFill().setForegroundColor((Color)_paint); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java b/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java deleted file mode 100644 index 8c3b2b6399..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Picture.java +++ /dev/null @@ -1,302 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.List; - -import javax.imageio.ImageIO; - -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherComplexProperty; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.hslf.blip.Bitmap; -import org.apache.poi.hslf.record.Document; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.ShapeType; -import org.apache.poi.util.POILogger; -import org.apache.poi.util.StringUtil; -import org.apache.poi.util.Units; - - -/** - * Represents a picture in a PowerPoint document. - * - * @author Yegor Kozlov - */ -public class Picture extends SimpleShape { - - /** - * Windows Enhanced Metafile (EMF) - */ - public static final int EMF = 2; - - /** - * Windows Metafile (WMF) - */ - public static final int WMF = 3; - - /** - * Macintosh PICT - */ - public static final int PICT = 4; - - /** - * JPEG - */ - public static final int JPEG = 5; - - /** - * PNG - */ - public static final int PNG = 6; - - /** - * Windows DIB (BMP) - */ - public static final byte DIB = 7; - - /** - * Create a new Picture - * - * @param idx the index of the picture - */ - public Picture(int idx){ - this(idx, null); - } - - /** - * Create a new Picture - * - * @param idx the index of the picture - * @param parent the parent shape - */ - public Picture(int idx, ShapeContainer parent) { - super(null, parent); - _escherContainer = createSpContainer(idx, parent instanceof HSLFGroupShape); - } - - /** - * Create a Picture object - * - * @param escherRecord the EscherSpContainer record which holds information about - * this picture in the Slide - * @param parent the parent shape of this picture - */ - protected Picture(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - } - - /** - * Returns index associated with this picture. - * Index starts with 1 and points to a EscherBSE record which - * holds information about this picture. - * - * @return the index to this picture (1 based). - */ - public int getPictureIndex(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.BLIP__BLIPTODISPLAY); - return prop == null ? 0 : prop.getPropertyValue(); - } - - /** - * Create a new Picture and populate the inital structure of the EscherSp record which holds information about this picture. - - * @param idx the index of the picture which refers to EscherBSE container. - * @return the create Picture object - */ - protected EscherContainerRecord createSpContainer(int idx, boolean isChild) { - _escherContainer = super.createSpContainer(isChild); - _escherContainer.setOptions((short)15); - - EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID); - spRecord.setOptions((short)((ShapeType.FRAME.nativeId << 4) | 0x2)); - - //set default properties for a picture - EscherOptRecord opt = getEscherOptRecord(); - setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x800080); - - //another weird feature of powerpoint: for picture id we must add 0x4000. - setEscherProperty(opt, (short)(EscherProperties.BLIP__BLIPTODISPLAY + 0x4000), idx); - - return _escherContainer; - } - - /** - * Resize this picture to the default size. - * For PNG and JPEG resizes the image to 100%, - * for other types sets the default size of 200x200 pixels. - */ - public void setDefaultSize(){ - PictureData pict = getPictureData(); - if (pict instanceof Bitmap){ - BufferedImage img = null; - try { - img = ImageIO.read(new ByteArrayInputStream(pict.getData())); - } - catch (IOException e){} - catch (NegativeArraySizeException ne) {} - - if(img != null) { - // Valid image, set anchor from it - setAnchor(new java.awt.Rectangle(0, 0, img.getWidth()*POINT_DPI/PIXEL_DPI, img.getHeight()*POINT_DPI/PIXEL_DPI)); - } else { - // Invalid image, go with the default metafile size - setAnchor(new java.awt.Rectangle(0, 0, 200, 200)); - } - } else { - //default size of a metafile picture is 200x200 - setAnchor(new java.awt.Rectangle(50, 50, 200, 200)); - } - } - - /** - * Returns the picture data for this picture. - * - * @return the picture data for this picture. - */ - public PictureData getPictureData(){ - SlideShow ppt = getSheet().getSlideShow(); - PictureData[] pict = ppt.getPictureData(); - - EscherBSERecord bse = getEscherBSERecord(); - if (bse == null){ - logger.log(POILogger.ERROR, "no reference to picture data found "); - } else { - for ( int i = 0; i < pict.length; i++ ) { - if (pict[i].getOffset() == bse.getOffset()){ - return pict[i]; - } - } - logger.log(POILogger.ERROR, "no picture found for our BSE offset " + bse.getOffset()); - } - return null; - } - - protected EscherBSERecord getEscherBSERecord(){ - SlideShow ppt = getSheet().getSlideShow(); - Document doc = ppt.getDocumentRecord(); - EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); - EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); - if(bstore == null) { - logger.log(POILogger.DEBUG, "EscherContainerRecord.BSTORE_CONTAINER was not found "); - return null; - } - List lst = bstore.getChildRecords(); - int idx = getPictureIndex(); - if (idx == 0){ - logger.log(POILogger.DEBUG, "picture index was not found, returning "); - return null; - } - return (EscherBSERecord)lst.get(idx-1); - } - - /** - * Name of this picture. - * - * @return name of this picture - */ - public String getPictureName(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherComplexProperty prop = getEscherProperty(opt, EscherProperties.BLIP__BLIPFILENAME); - if (prop == null) return null; - String name = StringUtil.getFromUnicodeLE(prop.getComplexData()); - return name.trim(); - } - - /** - * Name of this picture. - * - * @param name of this picture - */ - public void setPictureName(String name){ - EscherOptRecord opt = getEscherOptRecord(); - byte[] data = StringUtil.getToUnicodeLE(name + '\u0000'); - EscherComplexProperty prop = new EscherComplexProperty(EscherProperties.BLIP__BLIPFILENAME, false, data); - opt.addEscherProperty(prop); - } - - /** - * By default set the orininal image size - */ - protected void afterInsert(Sheet sh){ - super.afterInsert(sh); - - EscherBSERecord bse = getEscherBSERecord(); - bse.setRef(bse.getRef() + 1); - - java.awt.Rectangle anchor = getAnchor(); - if (anchor.equals(new java.awt.Rectangle())){ - setDefaultSize(); - } - } - - public void draw(Graphics2D graphics){ - AffineTransform at = graphics.getTransform(); - ShapePainter.paint(this, graphics); - - PictureData data = getPictureData(); - if(data != null) data.draw(graphics, this); - - graphics.setTransform(at); - } - - /** - * Returns the clipping values as percent ratio relatively to the image size. - * The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size, - * i.e. the size of the already clipped image - * - * @return the clipping as insets converted/scaled to 100000 (=100%) - */ - public Insets getBlipClip() { - EscherOptRecord opt = getEscherOptRecord(); - - double top = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP); - double bottom = getFractProp(opt, EscherProperties.BLIP__CROPFROMBOTTOM); - double left = getFractProp(opt, EscherProperties.BLIP__CROPFROMLEFT); - double right = getFractProp(opt, EscherProperties.BLIP__CROPFROMRIGHT); - - // if all crop values are zero (the default) then no crop rectangle is set, return null - return (top==0 && bottom==0 && left==0 && right==0) - ? null - : new Insets((int)(top*100000), (int)(left*100000), (int)(bottom*100000), (int)(right*100000)); - } - - /** - * @return the fractional property or 0 if not defined - */ - private static double getFractProp(EscherOptRecord opt, short propertyId) { - EscherSimpleProperty prop = getEscherProperty(opt, propertyId); - if (prop == null) return 0; - int fixedPoint = prop.getPropertyValue(); - return Units.fixedPointToDouble(fixedPoint); - } -} \ No newline at end of file diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java index 0e6052e969..470f6a4204 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java @@ -29,7 +29,7 @@ import java.io.ByteArrayOutputStream; * * @author Yegor Kozlov */ -public final class Placeholder extends TextBox { +public final class Placeholder extends HSLFTextBox { protected Placeholder(EscherContainerRecord escherRecord, ShapeContainer parent){ super(escherRecord, parent); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Polygon.java b/src/scratchpad/src/org/apache/poi/hslf/model/Polygon.java index 2d67c03fdc..7bfd95a571 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Polygon.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Polygon.java @@ -29,7 +29,7 @@ import java.awt.geom.Point2D; * * @author Yegor Kozlov */ -public final class Polygon extends AutoShape { +public final class Polygon extends HSLFAutoShape { /** * Create a Polygon object and initialize it from the supplied Record container. * diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java index 01ac53855c..d21cf9dd2b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java @@ -89,7 +89,7 @@ public final class ShapeFactory { ShapeType type = ShapeType.forId(spRecord.getShapeType(), false); switch (type){ case TEXT_BOX: - shape = new TextBox(spContainer, parent); + shape = new HSLFTextBox(spContainer, parent); break; case HOST_CONTROL: case FRAME: { @@ -110,7 +110,7 @@ public final class ShapeFactory { shape = new OLEShape(spContainer, parent); } - if(shape == null) shape = new Picture(spContainer, parent); + if(shape == null) shape = new HSLFPictureShape(spContainer, parent); break; } case LINE: @@ -120,16 +120,16 @@ public final class ShapeFactory { EscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID); EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES); if(prop != null) - shape = new Freeform(spContainer, parent); + shape = new HSLFFreeformShape(spContainer, parent); else { logger.log(POILogger.WARN, "Creating AutoShape for a NotPrimitive shape"); - shape = new AutoShape(spContainer, parent); + shape = new HSLFAutoShape(spContainer, parent); } break; } default: - shape = new AutoShape(spContainer, parent); + shape = new HSLFAutoShape(spContainer, parent); break; } return shape; diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java index c9954a8dee..e9686a6120 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/ShapePainter.java @@ -35,7 +35,7 @@ import org.apache.poi.util.POILogger; public final class ShapePainter { protected static final POILogger logger = POILogFactory.getLogger(ShapePainter.class); - public static void paint(SimpleShape shape, Graphics2D graphics){ + public static void paint(HSLFSimpleShape shape, Graphics2D graphics){ Rectangle2D anchor = shape.getLogicalAnchor2D(); java.awt.Shape outline = shape.getOutline(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java b/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java deleted file mode 100644 index 197043fa65..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java +++ /dev/null @@ -1,543 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Graphics2D; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDgRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.hslf.record.CString; -import org.apache.poi.hslf.record.ColorSchemeAtom; -import org.apache.poi.hslf.record.EscherTextboxWrapper; -import org.apache.poi.hslf.record.MasterTextPropAtom; -import org.apache.poi.hslf.record.OEPlaceholderAtom; -import org.apache.poi.hslf.record.PPDrawing; -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.RoundTripHFPlaceholder12; -import org.apache.poi.hslf.record.SheetContainer; -import org.apache.poi.hslf.record.StyleTextProp9Atom; -import org.apache.poi.hslf.record.StyleTextPropAtom; -import org.apache.poi.hslf.record.TextBytesAtom; -import org.apache.poi.hslf.record.TextCharsAtom; -import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.record.TextRulerAtom; -import org.apache.poi.hslf.record.TextSpecInfoAtom; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * This class defines the common format of "Sheets" in a powerpoint - * document. Such sheets could be Slides, Notes, Master etc - * - * @author Nick Burch - * @author Yegor Kozlov - */ - -public abstract class Sheet implements ShapeContainer { - private static POILogger logger = POILogFactory.getLogger(Sheet.class); - - /** - * The SlideShow we belong to - */ - private SlideShow _slideShow; - - /** - * Sheet background - */ - private Background _background; - - /** - * Record container that holds sheet data. - * For slides it is org.apache.poi.hslf.record.Slide, - * for notes it is org.apache.poi.hslf.record.Notes, - * for slide masters it is org.apache.poi.hslf.record.SlideMaster, etc. - */ - private SheetContainer _container; - - private int _sheetNo; - - public Sheet(SheetContainer container, int sheetNo) { - _container = container; - _sheetNo = sheetNo; - } - - /** - * Returns an array of all the TextRuns in the sheet. - */ - public abstract TextRun[] getTextRuns(); - - /** - * Returns the (internal, RefID based) sheet number, as used - * to in PersistPtr stuff. - */ - public int _getSheetRefId() { - return _container.getSheetId(); - } - - /** - * Returns the (internal, SlideIdentifier based) sheet number, as used - * to reference this sheet from other records. - */ - public int _getSheetNumber() { - return _sheetNo; - } - - /** - * Fetch the PPDrawing from the underlying record - */ - protected PPDrawing getPPDrawing() { - return _container.getPPDrawing(); - } - - /** - * Fetch the SlideShow we're attached to - */ - public SlideShow getSlideShow() { - return _slideShow; - } - - /** - * Return record container for this sheet - */ - public SheetContainer getSheetContainer() { - return _container; - } - - /** - * Set the SlideShow we're attached to. - * Also passes it on to our child RichTextRuns - */ - public void setSlideShow(SlideShow ss) { - _slideShow = ss; - TextRun[] trs = getTextRuns(); - if (trs != null) { - for (int i = 0; i < trs.length; i++) { - trs[i].supplySlideShow(_slideShow); - } - } - } - - - /** - * For a given PPDrawing, grab all the TextRuns - */ - public static TextRun[] findTextRuns(PPDrawing ppdrawing) { - final List runsV = new ArrayList(); - final EscherTextboxWrapper[] wrappers = ppdrawing.getTextboxWrappers(); - for (int i = 0; i < wrappers.length; i++) { - int s1 = runsV.size(); - - // propagate parents to parent-aware records - RecordContainer.handleParentAwareRecords(wrappers[i]); - findTextRuns(wrappers[i], runsV); - int s2 = runsV.size(); - if (s2 != s1){ - TextRun t = runsV.get(runsV.size()-1); - t.setShapeId(wrappers[i].getShapeId()); - } - } - return runsV.toArray(new TextRun[runsV.size()]); - } - /** - * Scans through the supplied record array, looking for - * a TextHeaderAtom followed by one of a TextBytesAtom or - * a TextCharsAtom. Builds up TextRuns from these - * - * @param records the records to build from - * @param found vector to add any found to - */ - protected static void findTextRuns(final Record[] records, final List found) { - findTextRuns(records, found, null); - } - /** - * Scans through the supplied record array, looking for - * a TextHeaderAtom followed by one of a TextBytesAtom or - * a TextCharsAtom. Builds up TextRuns from these - * - * @param wrapper an EscherTextboxWrapper - * @param found vector to add any found to - */ - protected static void findTextRuns(final EscherTextboxWrapper wrapper, final List found) { - findTextRuns(wrapper.getChildRecords(), found, wrapper.getStyleTextProp9Atom()); - } - /** - * Scans through the supplied record array, looking for - * a TextHeaderAtom followed by one of a TextBytesAtom or - * a TextCharsAtom. Builds up TextRuns from these - * - * @param records the records to build from - * @param found vector to add any found to - * @param styleTextProp9Atom a StyleTextProp9Atom with numbered lists info - */ - protected static void findTextRuns(final Record[] records, final List found, final StyleTextProp9Atom styleTextProp9Atom) { - for (int i = 0, slwtIndex=0; i < (records.length - 1); i++) { - if (records[i] instanceof TextHeaderAtom) { - TextHeaderAtom tha = (TextHeaderAtom) records[i]; - StyleTextPropAtom stpa = null; - TextRun trun = null; - Record next = null; - Record subs = null; - - // See what follows the TextHeaderAtom - next = records[i+1]; - if (i < records.length - 2) { - subs = records[i+2]; - } - - // Is the next record one we need to skip over? - if (subs != null) { - if (next instanceof TextRulerAtom || - next instanceof MasterTextPropAtom || - next instanceof TextSpecInfoAtom) { - // Ignore this one, check the one after - next = subs; - if (i < records.length - 3) { - subs = records[i+3]; - } else { - subs = null; - } - } - } - - // Is the subsequent record a style one? - if (subs != null && subs instanceof StyleTextPropAtom) { - stpa = (StyleTextPropAtom)subs; - } - - // Now, check if the next record is one to record - if (next instanceof TextCharsAtom) { - TextCharsAtom tca = (TextCharsAtom)next; - trun = new TextRun(tha, tca, stpa); - } else if (next instanceof TextBytesAtom) { - TextBytesAtom tba = (TextBytesAtom)next; - trun = new TextRun(tha, tba, stpa); - } else if (next instanceof StyleTextPropAtom) { - stpa = (StyleTextPropAtom)next; - } else if (next instanceof TextHeaderAtom) { - // Seems to be a mostly, but not completely deleted block of - // text. Only the header remains, which isn't useful alone - // Skip on to the next TextHeaderAtom - continue; - } else { - logger.log(POILogger.ERROR, "Found a TextHeaderAtom not followed by a TextBytesAtom or TextCharsAtom: Followed by " + next.getRecordType()); - } - - if (trun != null) { - List lst = new ArrayList(); - for (int j = i; j < records.length; j++) { - if(j > i && records[j] instanceof TextHeaderAtom) break; - lst.add(records[j]); - } - Record[] recs = new Record[lst.size()]; - lst.toArray(recs); - trun._records = recs; - trun.setIndex(slwtIndex); - trun.setStyleTextProp9Atom(styleTextProp9Atom); - found.add(trun); - i++; - } else { - // Not a valid one, so skip on to next and look again - } - slwtIndex++; - } - } - } - - /** - * Returns all shapes contained in this Sheet - * - * @return all shapes contained in this Sheet (Slide or Notes) - */ - public HSLFShape[] getShapes() { - List shapeList = getShapeList(); - return shapeList.toArray(new HSLFShape[shapeList.size()]); - } - - /** - * Add a new Shape to this Slide - * - * @param shape - the Shape to add - */ - public void addShape(HSLFShape shape) { - PPDrawing ppdrawing = getPPDrawing(); - - EscherContainerRecord dgContainer = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; - EscherContainerRecord spgr = (EscherContainerRecord) HSLFShape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER); - spgr.addChildRecord(shape.getSpContainer()); - - shape.setSheet(this); - shape.setShapeId(allocateShapeId()); - shape.afterInsert(this); - } - - /** - * Allocates new shape id for the new drawing group id. - * - * @return a new shape id. - */ - public int allocateShapeId() - { - EscherDggRecord dgg = _slideShow.getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); - EscherDgRecord dg = _container.getPPDrawing().getEscherDgRecord(); - - dgg.setNumShapesSaved( dgg.getNumShapesSaved() + 1 ); - - // Add to existing cluster if space available - for (int i = 0; i < dgg.getFileIdClusters().length; i++) - { - EscherDggRecord.FileIdCluster c = dgg.getFileIdClusters()[i]; - if (c.getDrawingGroupId() == dg.getDrawingGroupId() && c.getNumShapeIdsUsed() != 1024) - { - int result = c.getNumShapeIdsUsed() + (1024 * (i+1)); - c.incrementShapeId(); - dg.setNumShapes( dg.getNumShapes() + 1 ); - dg.setLastMSOSPID( result ); - if (result >= dgg.getShapeIdMax()) - dgg.setShapeIdMax( result + 1 ); - return result; - } - } - - // Create new cluster - dgg.addCluster( dg.getDrawingGroupId(), 0, false ); - dgg.getFileIdClusters()[dgg.getFileIdClusters().length-1].incrementShapeId(); - dg.setNumShapes( dg.getNumShapes() + 1 ); - int result = (1024 * dgg.getFileIdClusters().length); - dg.setLastMSOSPID( result ); - if (result >= dgg.getShapeIdMax()) - dgg.setShapeIdMax( result + 1 ); - return result; - } - - /** - * Removes the specified shape from this sheet. - * - * @param shape shape to be removed from this sheet, if present. - * @return true if the shape was deleted. - */ - public boolean removeShape(HSLFShape shape) { - PPDrawing ppdrawing = getPPDrawing(); - - EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; - EscherContainerRecord spgr = null; - - for (Iterator it = dg.getChildIterator(); it.hasNext();) { - EscherRecord rec = it.next(); - if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgr = (EscherContainerRecord) rec; - break; - } - } - if(spgr == null) { - return false; - } - - List lst = spgr.getChildRecords(); - boolean result = lst.remove(shape.getSpContainer()); - spgr.setChildRecords(lst); - return result; - } - - /** - * Called by SlideShow ater a new sheet is created - */ - public void onCreate(){ - - } - - /** - * Return the master sheet . - */ - public abstract MasterSheet getMasterSheet(); - - /** - * Color scheme for this sheet. - */ - public ColorSchemeAtom getColorScheme() { - return _container.getColorScheme(); - } - - /** - * Returns the background shape for this sheet. - * - * @return the background shape for this sheet. - */ - public Background getBackground() { - if (_background == null) { - PPDrawing ppdrawing = getPPDrawing(); - - EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; - EscherContainerRecord spContainer = null; - - for (Iterator it = dg.getChildIterator(); it.hasNext();) { - EscherRecord rec = it.next(); - if (rec.getRecordId() == EscherContainerRecord.SP_CONTAINER) { - spContainer = (EscherContainerRecord) rec; - break; - } - } - _background = new Background(spContainer, null); - _background.setSheet(this); - } - return _background; - } - - public void draw(Graphics2D graphics){ - - } - - /** - * Subclasses should call this method and update the array of text runs - * when a text shape is added - * - * @param shape - */ - protected void onAddTextShape(TextShape shape) { - - } - - /** - * Return placeholder by text type - * - * @param type type of text, See {@link org.apache.poi.hslf.record.TextHeaderAtom} - * @return TextShape or null - */ - public TextShape getPlaceholderByTextType(int type){ - HSLFShape[] shape = getShapes(); - for (int i = 0; i < shape.length; i++) { - if(shape[i] instanceof TextShape){ - TextShape tx = (TextShape)shape[i]; - TextRun run = tx.getTextRun(); - if(run != null && run.getRunType() == type){ - return tx; - } - } - } - return null; - } - - /** - * Search text placeholer by its type - * - * @param type type of placeholder to search. See {@link org.apache.poi.hslf.record.OEPlaceholderAtom} - * @return TextShape or null - */ - public TextShape getPlaceholder(int type){ - HSLFShape[] shape = getShapes(); - for (int i = 0; i < shape.length; i++) { - if(shape[i] instanceof TextShape){ - TextShape tx = (TextShape)shape[i]; - int placeholderId = 0; - OEPlaceholderAtom oep = tx.getPlaceholderAtom(); - if(oep != null) { - placeholderId = oep.getPlaceholderId(); - } else { - //special case for files saved in Office 2007 - RoundTripHFPlaceholder12 hldr = tx.getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID); - if(hldr != null) placeholderId = hldr.getPlaceholderId(); - } - if(placeholderId == type){ - return tx; - } - } - } - return null; - } - - /** - * Return programmable tag associated with this sheet, e.g. ___PPT12. - * - * @return programmable tag associated with this sheet. - */ - public String getProgrammableTag(){ - String tag = null; - RecordContainer progTags = (RecordContainer) - getSheetContainer().findFirstOfType( - RecordTypes.ProgTags.typeID - ); - if(progTags != null) { - RecordContainer progBinaryTag = (RecordContainer) - progTags.findFirstOfType( - RecordTypes.ProgBinaryTag.typeID - ); - if(progBinaryTag != null) { - CString binaryTag = (CString) - progBinaryTag.findFirstOfType( - RecordTypes.CString.typeID - ); - if(binaryTag != null) tag = binaryTag.getText(); - } - } - - return tag; - - } - - public Iterator iterator() { - return getShapeList().iterator(); - } - - - /** - * Returns all shapes contained in this Sheet - * - * @return all shapes contained in this Sheet (Slide or Notes) - */ - protected List getShapeList() { - PPDrawing ppdrawing = getPPDrawing(); - - EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0]; - EscherContainerRecord spgr = null; - - for (Iterator it = dg.getChildIterator(); it.hasNext();) { - EscherRecord rec = it.next(); - if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER) { - spgr = (EscherContainerRecord) rec; - break; - } - } - if (spgr == null) { - throw new IllegalStateException("spgr not found"); - } - - List shapeList = new ArrayList(); - Iterator it = spgr.getChildIterator(); - if (it.hasNext()) { - // skip first item - it.next(); - } - for (; it.hasNext();) { - EscherContainerRecord sp = (EscherContainerRecord) it.next(); - HSLFShape sh = ShapeFactory.createShape(sp, null); - sh.setSheet(this); - shapeList.add(sh); - } - - return shapeList; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java deleted file mode 100644 index bfe6a1d95a..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java +++ /dev/null @@ -1,390 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; - -import org.apache.poi.ddf.DefaultEscherRecordFactory; -import org.apache.poi.ddf.EscherChildAnchorRecord; -import org.apache.poi.ddf.EscherClientAnchorRecord; -import org.apache.poi.ddf.EscherClientDataRecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.InteractiveInfo; -import org.apache.poi.hslf.record.InteractiveInfoAtom; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.LittleEndian; - -/** - * An abstract simple (non-group) shape. - * This is the parent class for all primitive shapes like Line, Rectangle, etc. - * - * @author Yegor Kozlov - */ -public abstract class SimpleShape extends HSLFShape { - - public final static double DEFAULT_LINE_WIDTH = 0.75; - - /** - * Records stored in EscherClientDataRecord - */ - protected Record[] _clientRecords; - protected EscherClientDataRecord _clientData; - - /** - * Create a SimpleShape object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected SimpleShape(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - } - - /** - * Create a new Shape - * - * @param isChild true if the Line is inside a group, false otherwise - * @return the record container which holds this shape - */ - protected EscherContainerRecord createSpContainer(boolean isChild) { - _escherContainer = new EscherContainerRecord(); - _escherContainer.setRecordId( EscherContainerRecord.SP_CONTAINER ); - _escherContainer.setOptions((short)15); - - EscherSpRecord sp = new EscherSpRecord(); - int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE; - if (isChild) flags |= EscherSpRecord.FLAG_CHILD; - sp.setFlags(flags); - _escherContainer.addChildRecord(sp); - - EscherOptRecord opt = new EscherOptRecord(); - opt.setRecordId(EscherOptRecord.RECORD_ID); - _escherContainer.addChildRecord(opt); - - EscherRecord anchor; - if(isChild) anchor = new EscherChildAnchorRecord(); - else { - anchor = new EscherClientAnchorRecord(); - - //hack. internal variable EscherClientAnchorRecord.shortRecord can be - //initialized only in fillFields(). We need to set shortRecord=false; - byte[] header = new byte[16]; - LittleEndian.putUShort(header, 0, 0); - LittleEndian.putUShort(header, 2, 0); - LittleEndian.putInt(header, 4, 8); - anchor.fillFields(header, 0, null); - } - _escherContainer.addChildRecord(anchor); - - return _escherContainer; - } - - /** - * Returns width of the line in in points - */ - public double getLineWidth(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); - double width = prop == null ? DEFAULT_LINE_WIDTH : (double)prop.getPropertyValue()/EMU_PER_POINT; - return width; - } - - /** - * Sets the width of line in in points - * @param width the width of line in in points - */ - public void setLineWidth(double width){ - EscherOptRecord opt = getEscherOptRecord(); - setEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH, (int)(width*EMU_PER_POINT)); - } - - /** - * Sets the color of line - * - * @param color new color of the line - */ - public void setLineColor(Color color){ - EscherOptRecord opt = getEscherOptRecord(); - if (color == null) { - setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000); - } else { - int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB(); - setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb); - setEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH, color == null ? 0x180010 : 0x180018); - } - } - - /** - * @return color of the line. If color is not set returns java.awt.Color.black - */ - public Color getLineColor(){ - EscherOptRecord opt = getEscherOptRecord(); - - EscherSimpleProperty p = getEscherProperty(opt, EscherProperties.LINESTYLE__NOLINEDRAWDASH); - if(p != null && (p.getPropertyValue() & 0x8) == 0) return null; - - Color clr = getColor(EscherProperties.LINESTYLE__COLOR, EscherProperties.LINESTYLE__OPACITY, -1); - return clr == null ? Color.black : clr; - } - - /** - * Gets line dashing. One of the PEN_* constants defined in this class. - * - * @return dashing of the line. - */ - public int getLineDashing(){ - EscherOptRecord opt = getEscherOptRecord(); - - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING); - return prop == null ? Line.PEN_SOLID : prop.getPropertyValue(); - } - - /** - * Sets line dashing. One of the PEN_* constants defined in this class. - * - * @param pen new style of the line. - */ - public void setLineDashing(int pen){ - EscherOptRecord opt = getEscherOptRecord(); - - setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, pen == Line.PEN_SOLID ? -1 : pen); - } - - /** - * Sets line style. One of the constants defined in this class. - * - * @param style new style of the line. - */ - public void setLineStyle(int style){ - EscherOptRecord opt = getEscherOptRecord(); - setEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE, style == Line.LINE_SIMPLE ? -1 : style); - } - - /** - * Returns line style. One of the constants defined in this class. - * - * @return style of the line. - */ - public int getStrokeStyle(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.LINESTYLE__LINESTYLE); - return prop == null ? Line.LINE_SIMPLE : prop.getPropertyValue(); - } - - /** - * The color used to fill this shape. - */ - public Color getFillColor(){ - return getFill().getForegroundColor(); - } - - /** - * The color used to fill this shape. - * - * @param color the background color - */ - public void setFillColor(Color color){ - getFill().setForegroundColor(color); - } - - /** - * - * @return 'absolute' anchor of this shape relative to the parent sheet - */ - public Rectangle2D getLogicalAnchor2D(){ - Rectangle2D anchor = getAnchor2D(); - - //if it is a groupped shape see if we need to transform the coordinates - if (getParent() != null){ - ArrayList lst = new ArrayList(); - for (ShapeContainer parent=this.getParent(); - parent instanceof HSLFGroupShape; - parent = ((HSLFGroupShape)parent).getParent()) { - lst.add(0, (HSLFGroupShape)parent); - } - - AffineTransform tx = new AffineTransform(); - for(HSLFGroupShape prnt : lst) { - Rectangle2D exterior = prnt.getAnchor2D(); - Rectangle2D interior = prnt.getCoordinates(); - - double scaleX = exterior.getWidth() / interior.getWidth(); - double scaleY = exterior.getHeight() / interior.getHeight(); - - tx.translate(exterior.getX(), exterior.getY()); - tx.scale(scaleX, scaleY); - tx.translate(-interior.getX(), -interior.getY()); - - } - anchor = tx.createTransformedShape(anchor).getBounds2D(); - } - - double angle = getRotation(); - if(angle != 0.){ - double centerX = anchor.getX() + anchor.getWidth()/2; - double centerY = anchor.getY() + anchor.getHeight()/2; - - AffineTransform trans = new AffineTransform(); - trans.translate(centerX, centerY); - trans.rotate(Math.toRadians(angle)); - trans.translate(-centerX, -centerY); - - Rectangle2D rect = trans.createTransformedShape(anchor).getBounds2D(); - if((anchor.getWidth() < anchor.getHeight() && rect.getWidth() > rect.getHeight()) || - (anchor.getWidth() > anchor.getHeight() && rect.getWidth() < rect.getHeight()) ){ - trans = new AffineTransform(); - trans.translate(centerX, centerY); - trans.rotate(Math.PI/2); - trans.translate(-centerX, -centerY); - anchor = trans.createTransformedShape(anchor).getBounds2D(); - } - } - return anchor; - } - - public void draw(Graphics2D graphics){ - AffineTransform at = graphics.getTransform(); - ShapePainter.paint(this, graphics); - graphics.setTransform(at); - } - - /** - * Find a record in the underlying EscherClientDataRecord - * - * @param recordType type of the record to search - */ - @SuppressWarnings("unchecked") - protected T getClientDataRecord(int recordType) { - - Record[] records = getClientRecords(); - if(records != null) for (int i = 0; i < records.length; i++) { - if(records[i].getRecordType() == recordType){ - return (T)records[i]; - } - } - return null; - } - - /** - * Search for EscherClientDataRecord, if found, convert its contents into an array of HSLF records - * - * @return an array of HSLF records contained in the shape's EscherClientDataRecord or null - */ - protected Record[] getClientRecords() { - if(_clientData == null){ - EscherRecord r = getEscherChild(EscherClientDataRecord.RECORD_ID); - //ddf can return EscherContainerRecord with recordId=EscherClientDataRecord.RECORD_ID - //convert in to EscherClientDataRecord on the fly - if(r != null && !(r instanceof EscherClientDataRecord)){ - byte[] data = r.serialize(); - r = new EscherClientDataRecord(); - r.fillFields(data, 0, new DefaultEscherRecordFactory()); - } - _clientData = (EscherClientDataRecord)r; - } - if(_clientData != null && _clientRecords == null){ - byte[] data = _clientData.getRemainingData(); - _clientRecords = Record.findChildRecords(data, 0, data.length); - } - return _clientRecords; - } - - protected void updateClientData() { - if(_clientData != null && _clientRecords != null){ - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - for (int i = 0; i < _clientRecords.length; i++) { - _clientRecords[i].writeOut(out); - } - } catch(Exception e){ - throw new HSLFException(e); - } - _clientData.setRemainingData(out.toByteArray()); - } - } - - public void setHyperlink(Hyperlink link){ - if(link.getId() == -1){ - throw new HSLFException("You must call SlideShow.addHyperlink(Hyperlink link) first"); - } - - EscherClientDataRecord cldata = new EscherClientDataRecord(); - cldata.setOptions((short)0xF); - getSpContainer().addChildRecord(cldata); // TODO - junit to prove getChildRecords().add is wrong - - InteractiveInfo info = new InteractiveInfo(); - InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); - - switch(link.getType()){ - case Hyperlink.LINK_FIRSTSLIDE: - infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); - infoAtom.setJump(InteractiveInfoAtom.JUMP_FIRSTSLIDE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_FirstSlide); - break; - case Hyperlink.LINK_LASTSLIDE: - infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); - infoAtom.setJump(InteractiveInfoAtom.JUMP_LASTSLIDE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_LastSlide); - break; - case Hyperlink.LINK_NEXTSLIDE: - infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); - infoAtom.setJump(InteractiveInfoAtom.JUMP_NEXTSLIDE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_NextSlide); - break; - case Hyperlink.LINK_PREVIOUSSLIDE: - infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP); - infoAtom.setJump(InteractiveInfoAtom.JUMP_PREVIOUSSLIDE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_PreviousSlide); - break; - case Hyperlink.LINK_URL: - infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); - infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url); - break; - case Hyperlink.LINK_SLIDENUMBER: - infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); - infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_SlideNumber); - break; - } - - infoAtom.setHyperlinkID(link.getId()); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - try { - info.writeOut(out); - } catch(Exception e){ - throw new HSLFException(e); - } - cldata.setRemainingData(out.toByteArray()); - - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java b/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java deleted file mode 100644 index 1db3173e6a..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Slide.java +++ /dev/null @@ -1,513 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Graphics2D; -import java.util.LinkedList; -import java.util.List; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherDgRecord; -import org.apache.poi.ddf.EscherDggRecord; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.hslf.record.ColorSchemeAtom; -import org.apache.poi.hslf.record.Comment2000; -import org.apache.poi.hslf.record.EscherTextboxWrapper; -import org.apache.poi.hslf.record.HeadersFootersContainer; -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.SSSlideInfoAtom; -import org.apache.poi.hslf.record.SlideAtom; -import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; -import org.apache.poi.hslf.record.StyleTextProp9Atom; -import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.sl.usermodel.ShapeType; - -/** - * This class represents a slide in a PowerPoint Document. It allows - * access to the text within, and the layout. For now, it only does - * the text side of things though - * - * @author Nick Burch - * @author Yegor Kozlov - */ - -public final class Slide extends Sheet { - private int _slideNo; - private SlideAtomsSet _atomSet; - private TextRun[] _runs; - private Notes _notes; // usermodel needs to set this - - /** - * Constructs a Slide from the Slide record, and the SlideAtomsSet - * containing the text. - * Initializes TextRuns, to provide easier access to the text - * - * @param slide the Slide record we're based on - * @param notes the Notes sheet attached to us - * @param atomSet the SlideAtomsSet to get the text from - */ - public Slide(org.apache.poi.hslf.record.Slide slide, Notes notes, SlideAtomsSet atomSet, int slideIdentifier, int slideNumber) { - super(slide, slideIdentifier); - - _notes = notes; - _atomSet = atomSet; - _slideNo = slideNumber; - - // Grab the TextRuns from the PPDrawing - TextRun[] _otherRuns = findTextRuns(getPPDrawing()); - - // For the text coming in from the SlideAtomsSet: - // Build up TextRuns from pairs of TextHeaderAtom and - // one of TextBytesAtom or TextCharsAtom - final List textRuns = new LinkedList(); - if(_atomSet != null) { - findTextRuns(_atomSet.getSlideRecords(),textRuns); - } else { - // No text on the slide, must just be pictures - } - - // Build an array, more useful than a vector - _runs = new TextRun[textRuns.size()+_otherRuns.length]; - // Grab text from SlideListWithTexts entries - int i=0; - for(i=0; i - * For Slide we need to do the following: - *
  • set id of the drawing group. - *
  • set shapeId for the container descriptor and background - *

    - */ - public void onCreate(){ - //initialize drawing group id - EscherDggRecord dgg = getSlideShow().getDocumentRecord().getPPDrawingGroup().getEscherDggRecord(); - EscherContainerRecord dgContainer = (EscherContainerRecord)getSheetContainer().getPPDrawing().getEscherRecords()[0]; - EscherDgRecord dg = (EscherDgRecord) HSLFShape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID); - int dgId = dgg.getMaxDrawingGroupId() + 1; - dg.setOptions((short)(dgId << 4)); - dgg.setDrawingsSaved(dgg.getDrawingsSaved() + 1); - dgg.setMaxDrawingGroupId(dgId); - - for (EscherContainerRecord c : dgContainer.getChildContainers()) { - EscherSpRecord spr = null; - switch(c.getRecordId()){ - case EscherContainerRecord.SPGR_CONTAINER: - EscherContainerRecord dc = (EscherContainerRecord)c.getChild(0); - spr = dc.getChildById(EscherSpRecord.RECORD_ID); - break; - case EscherContainerRecord.SP_CONTAINER: - spr = c.getChildById(EscherSpRecord.RECORD_ID); - break; - } - if(spr != null) spr.setShapeId(allocateShapeId()); - } - - //PPT doen't increment the number of saved shapes for group descriptor and background - dg.setNumShapes(1); - } - - /** - * Create a TextBox object that represents the slide's title. - * - * @return TextBox object that represents the slide's title. - */ - public TextBox addTitle() { - Placeholder pl = new Placeholder(); - pl.setShapeType(ShapeType.RECT); - pl.getTextRun().setRunType(TextHeaderAtom.TITLE_TYPE); - pl.setText("Click to edit title"); - pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90)); - addShape(pl); - return pl; - } - - - // Complex Accesser methods follow - - /** - * Return title of this slide or null if the slide does not have title. - *

    - * The title is a run of text of type TextHeaderAtom.CENTER_TITLE_TYPE or - * TextHeaderAtom.TITLE_TYPE - *

    - * - * @see TextHeaderAtom - * - * @return title of this slide - */ - public String getTitle(){ - TextRun[] txt = getTextRuns(); - for (int i = 0; i < txt.length; i++) { - int type = txt[i].getRunType(); - if (type == TextHeaderAtom.CENTER_TITLE_TYPE || - type == TextHeaderAtom.TITLE_TYPE ){ - String title = txt[i].getText(); - return title; - } - } - return null; - } - - // Simple Accesser methods follow - - /** - * Returns an array of all the TextRuns found - */ - public TextRun[] getTextRuns() { return _runs; } - - /** - * Returns the (public facing) page number of this slide - */ - public int getSlideNumber() { return _slideNo; } - - /** - * Returns the underlying slide record - */ - public org.apache.poi.hslf.record.Slide getSlideRecord() { - return (org.apache.poi.hslf.record.Slide)getSheetContainer(); - } - - /** - * Returns the Notes Sheet for this slide, or null if there isn't one - */ - public Notes getNotesSheet() { return _notes; } - - /** - * @return set of records inside SlideListWithtext container - * which hold text data for this slide (typically for placeholders). - */ - protected SlideAtomsSet getSlideAtomsSet() { return _atomSet; } - - /** - * Returns master sheet associated with this slide. - * It can be either SlideMaster or TitleMaster objects. - * - * @return the master sheet associated with this slide. - */ - public MasterSheet getMasterSheet(){ - SlideMaster[] master = getSlideShow().getSlidesMasters(); - SlideAtom sa = getSlideRecord().getSlideAtom(); - int masterId = sa.getMasterID(); - MasterSheet sheet = null; - for (int i = 0; i < master.length; i++) { - if (masterId == master[i]._getSheetNumber()) { - sheet = master[i]; - break; - } - } - if (sheet == null){ - TitleMaster[] titleMaster = getSlideShow().getTitleMasters(); - if(titleMaster != null) for (int i = 0; i < titleMaster.length; i++) { - if (masterId == titleMaster[i]._getSheetNumber()) { - sheet = titleMaster[i]; - break; - } - } - } - return sheet; - } - - /** - * Change Master of this slide. - */ - public void setMasterSheet(MasterSheet master){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - int sheetNo = master._getSheetNumber(); - sa.setMasterID(sheetNo); - } - - /** - * Sets whether this slide follows master background - * - * @param flag true if the slide follows master, - * false otherwise - */ - public void setFollowMasterBackground(boolean flag){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - sa.setFollowMasterBackground(flag); - } - - /** - * Whether this slide follows master sheet background - * - * @return true if the slide follows master background, - * false otherwise - */ - public boolean getFollowMasterBackground(){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - return sa.getFollowMasterBackground(); - } - - /** - * Sets whether this slide draws master sheet objects - * - * @param flag true if the slide draws master sheet objects, - * false otherwise - */ - public void setFollowMasterObjects(boolean flag){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - sa.setFollowMasterObjects(flag); - } - - /** - * Whether this slide follows master color scheme - * - * @return true if the slide follows master color scheme, - * false otherwise - */ - public boolean getFollowMasterScheme(){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - return sa.getFollowMasterScheme(); - } - - /** - * Sets whether this slide draws master color scheme - * - * @param flag true if the slide draws master color scheme, - * false otherwise - */ - public void setFollowMasterScheme(boolean flag){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - sa.setFollowMasterScheme(flag); - } - - /** - * Whether this slide draws master sheet objects - * - * @return true if the slide draws master sheet objects, - * false otherwise - */ - public boolean getFollowMasterObjects(){ - SlideAtom sa = getSlideRecord().getSlideAtom(); - return sa.getFollowMasterObjects(); - } - - /** - * Background for this slide. - */ - public Background getBackground() { - if(getFollowMasterBackground()) { - return getMasterSheet().getBackground(); - } - return super.getBackground(); - } - - /** - * Color scheme for this slide. - */ - public ColorSchemeAtom getColorScheme() { - if(getFollowMasterScheme()){ - return getMasterSheet().getColorScheme(); - } - return super.getColorScheme(); - } - - /** - * Get the comment(s) for this slide. - * Note - for now, only works on PPT 2000 and - * PPT 2003 files. Doesn't work for PPT 97 - * ones, as they do their comments oddly. - */ - public Comment[] getComments() { - // If there are any, they're in - // ProgTags -> ProgBinaryTag -> BinaryTagData - RecordContainer progTags = (RecordContainer) - getSheetContainer().findFirstOfType( - RecordTypes.ProgTags.typeID - ); - if(progTags != null) { - RecordContainer progBinaryTag = (RecordContainer) - progTags.findFirstOfType( - RecordTypes.ProgBinaryTag.typeID - ); - if(progBinaryTag != null) { - RecordContainer binaryTags = (RecordContainer) - progBinaryTag.findFirstOfType( - RecordTypes.BinaryTagData.typeID - ); - if(binaryTags != null) { - // This is where they'll be - int count = 0; - for(int i=0; inull since SlideMasters doen't have master sheet. */ - public MasterSheet getMasterSheet() { + public HSLFMasterSheet getMasterSheet() { return null; } @@ -112,7 +112,7 @@ public final class SlideMaster extends MasterSheet { * Assign SlideShow for this slide master. * (Used interanlly) */ - public void setSlideShow(SlideShow ss) { + public void setSlideShow(HSLFSlideShow ss) { super.setSlideShow(ss); //after the slide show is assigned collect all available style records @@ -130,12 +130,12 @@ public final class SlideMaster extends MasterSheet { } } - protected void onAddTextShape(TextShape shape) { - TextRun run = shape.getTextRun(); + protected void onAddTextShape(HSLFTextShape shape) { + HSLFTextParagraph run = shape.getTextParagraph(); - if(_runs == null) _runs = new TextRun[]{run}; + if(_runs == null) _runs = new HSLFTextParagraph[]{run}; else { - TextRun[] tmp = new TextRun[_runs.length + 1]; + HSLFTextParagraph[] tmp = new HSLFTextParagraph[_runs.length + 1]; System.arraycopy(_runs, 0, tmp, 0, _runs.length); tmp[tmp.length-1] = run; _runs = tmp; diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java index f94bd7f5b6..99ee13f211 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java @@ -115,7 +115,7 @@ public final class Table extends HSLFGroupShape { return cells.length; } - protected void afterInsert(Sheet sh){ + protected void afterInsert(HSLFSheet sh){ super.afterInsert(sh); EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0); @@ -165,7 +165,7 @@ public final class Table extends HSLFGroupShape { List> lst = new ArrayList>(); List row = null; for (HSLFShape sh : shapeList) { - if(sh instanceof TextShape){ + if(sh instanceof HSLFTextShape){ Rectangle anchor = sh.getAnchor(); if(anchor.y != y0){ y0 = anchor.y; @@ -180,7 +180,7 @@ public final class Table extends HSLFGroupShape { for (int i = 0; i < lst.size(); i++) { row = lst.get(i); for (int j = 0; j < row.size(); j++) { - TextShape tx = (TextShape)row.get(j); + HSLFTextShape tx = (HSLFTextShape)row.get(j); cells[i][j] = new TableCell(tx.getSpContainer(), getParent()); cells[i][j].setSheet(tx.getSheet()); } @@ -192,7 +192,7 @@ public final class Table extends HSLFGroupShape { * * @param sheet owner of this shape */ - public void setSheet(Sheet sheet){ + public void setSheet(HSLFSheet sheet){ super.setSheet(sheet); if(cells == null) initTable(); } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java index 715181cfad..18431a720c 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java @@ -30,7 +30,7 @@ import org.apache.poi.sl.usermodel.ShapeType; * * @author Yegor Kozlov */ -public final class TableCell extends TextBox { +public final class TableCell extends HSLFTextBox { protected static final int DEFAULT_WIDTH = 100; protected static final int DEFAULT_HEIGHT = 40; diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java deleted file mode 100644 index dc5ac94104..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java +++ /dev/null @@ -1,92 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import org.apache.poi.ddf.*; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.sl.usermodel.ShapeType; - -/** - * Represents a TextFrame shape in PowerPoint. - *

    - * Contains the text in a text frame as well as the properties and methods - * that control alignment and anchoring of the text. - *

    - * - * @author Yegor Kozlov - */ -public class TextBox extends TextShape { - - /** - * Create a TextBox object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected TextBox(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - * @param parent the parent of this Shape. For example, if this text box is a cell - * in a table then the parent is Table. - */ - public TextBox(ShapeContainer parent){ - super(parent); - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - */ - public TextBox(){ - this(null); - } - - /** - * Create a new TextBox and initialize its internal structures - * - * @return the created EscherContainerRecord which holds shape data - */ - protected EscherContainerRecord createSpContainer(boolean isChild){ - _escherContainer = super.createSpContainer(isChild); - - setShapeType(ShapeType.TEXT_BOX); - - //set default properties for a TextBox - setEscherProperty(EscherProperties.FILL__FILLCOLOR, 0x8000004); - setEscherProperty(EscherProperties.FILL__FILLBACKCOLOR, 0x8000000); - setEscherProperty(EscherProperties.FILL__NOFILLHITTEST, 0x100000); - setEscherProperty(EscherProperties.LINESTYLE__COLOR, 0x8000001); - setEscherProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x80000); - setEscherProperty(EscherProperties.SHADOWSTYLE__COLOR, 0x8000002); - - _txtrun = createTextRun(); - - return _escherContainer; - } - - protected void setDefaultTextProperties(TextRun _txtrun){ - setVerticalAlignment(TextBox.AnchorTop); - setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002); - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java index 4b8805c266..038e28a04d 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TextPainter.java @@ -35,7 +35,7 @@ import java.util.List; import java.util.Map; import org.apache.poi.hslf.record.TextRulerAtom; -import org.apache.poi.hslf.usermodel.RichTextRun; +import org.apache.poi.hslf.usermodel.HSLFTextRun; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -57,27 +57,27 @@ public final class TextPainter { */ protected static final char DEFAULT_BULLET_CHAR = '\u25a0'; - protected TextShape _shape; + protected HSLFTextShape _shape; - public TextPainter(TextShape shape){ + public TextPainter(HSLFTextShape shape){ _shape = shape; } - public AttributedString getAttributedString(TextRun txrun) { + public AttributedString getAttributedString(HSLFTextParagraph txrun) { return getAttributedString(txrun, null); } /** * Convert the underlying set of rich text runs into java.text.AttributedString */ - public AttributedString getAttributedString(TextRun txrun, Graphics2D graphics){ + public AttributedString getAttributedString(HSLFTextParagraph txrun, Graphics2D graphics){ String text = txrun.getText(); //TODO: properly process tabs text = text.replace('\t', ' '); text = text.replace((char)160, ' '); AttributedString at = new AttributedString(text); - RichTextRun[] rt = txrun.getRichTextRuns(); + HSLFTextRun[] rt = txrun.getRichTextRuns(); for (int i = 0; i < rt.length; i++) { int start = rt[i].getStartIndex(); int end = rt[i].getEndIndex(); @@ -157,15 +157,15 @@ public final class TextPainter { int valign = _shape.getVerticalAlignment(); double y0 = anchor.getY(); switch (valign){ - case TextShape.AnchorTopBaseline: - case TextShape.AnchorTop: + case HSLFTextShape.AnchorTopBaseline: + case HSLFTextShape.AnchorTop: y0 += _shape.getMarginTop(); break; - case TextShape.AnchorBottom: + case HSLFTextShape.AnchorBottom: y0 += anchor.getHeight() - textHeight - _shape.getMarginBottom(); break; default: - case TextShape.AnchorMiddle: + case HSLFTextShape.AnchorMiddle: float delta = (float)anchor.getHeight() - textHeight - _shape.getMarginTop() - _shape.getMarginBottom(); y0 += _shape.getMarginTop() + delta/2; break; @@ -205,14 +205,14 @@ public final class TextPainter { pen.y = y0; switch (elem[i]._align) { default: - case TextShape.AlignLeft: + case HSLFTextShape.AlignLeft: pen.x = anchor.getX() + _shape.getMarginLeft(); break; - case TextShape.AlignCenter: + case HSLFTextShape.AlignCenter: pen.x = anchor.getX() + _shape.getMarginLeft() + (anchor.getWidth() - elem[i].advance - _shape.getMarginLeft() - _shape.getMarginRight()) / 2; break; - case TextShape.AlignRight: + case HSLFTextShape.AlignRight: pen.x = anchor.getX() + _shape.getMarginLeft() + (anchor.getWidth() - elem[i].advance - _shape.getMarginLeft() - _shape.getMarginRight()); break; @@ -235,7 +235,7 @@ public final class TextPainter { } public TextElement[] getTextElements(float textWidth, FontRenderContext frc, Graphics2D graphics){ - TextRun run = _shape.getTextRun(); + HSLFTextParagraph run = _shape.getTextParagraph(); if (run == null) return null; String text = run.getText(); @@ -257,7 +257,7 @@ public final class TextPainter { boolean prStart = text.charAt(startIndex) == '\n'; if(prStart) measurer.setPosition(startIndex++); - RichTextRun rt = run.getRichTextRunAt(startIndex == text.length() ? (startIndex-1) : startIndex); + HSLFTextRun rt = run.getRichTextRunAt(startIndex == text.length() ? (startIndex-1) : startIndex); if(rt == null) { logger.log(POILogger.WARN, "RichTextRun not found at pos" + startIndex + "; text.length: " + text.length()); break; @@ -283,7 +283,7 @@ public final class TextPainter { if(bulletOffset > 0 || prStart || startIndex == 0) wrappingWidth -= textOffset; - if (_shape.getWordWrap() == TextShape.WrapNone) { + if (_shape.getWordWrap() == HSLFTextShape.WrapNone) { wrappingWidth = _shape.getSheet().getSlideShow().getPageSize().width; } diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java deleted file mode 100644 index 755482f183..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java +++ /dev/null @@ -1,746 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -import org.apache.poi.hslf.model.textproperties.TextPropCollection; -import org.apache.poi.hslf.record.PPDrawing; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.RecordContainer; -import org.apache.poi.hslf.record.SlideListWithText; -import org.apache.poi.hslf.record.StyleTextProp9Atom; -import org.apache.poi.hslf.record.StyleTextPropAtom; -import org.apache.poi.hslf.record.TextBytesAtom; -import org.apache.poi.hslf.record.TextCharsAtom; -import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.record.TextRulerAtom; -import org.apache.poi.hslf.record.TextSpecInfoAtom; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.util.StringUtil; - -/** - * This class represents a run of text in a powerpoint document. That - * run could be text on a sheet, or text in a note. - * It is only a very basic class for now - * - * @author Nick Burch - */ - -public final class TextRun -{ - // Note: These fields are protected to help with unit testing - // Other classes shouldn't really go playing with them! - protected TextHeaderAtom _headerAtom; - protected TextBytesAtom _byteAtom; - protected TextCharsAtom _charAtom; - protected StyleTextPropAtom _styleAtom; - protected TextRulerAtom _ruler; - protected boolean _isUnicode; - protected RichTextRun[] _rtRuns; - private SlideShow slideShow; - private Sheet _sheet; - private int shapeId; - private int slwtIndex = -1; //position in the owning SlideListWithText - /** - * all text run records that follow TextHeaderAtom. - * (there can be misc InteractiveInfo, TxInteractiveInfo and other records) - */ - protected Record[] _records; - // private StyleTextPropAtom styleTextPropAtom; - private StyleTextProp9Atom styleTextProp9Atom; - - /** - * Constructs a Text Run from a Unicode text block - * - * @param tha the TextHeaderAtom that defines what's what - * @param tca the TextCharsAtom containing the text - * @param sta the StyleTextPropAtom which defines the character stylings - */ - public TextRun(TextHeaderAtom tha, TextCharsAtom tca, StyleTextPropAtom sta) { - this(tha,null,tca,sta); - } - - /** - * Constructs a Text Run from a Ascii text block - * - * @param tha the TextHeaderAtom that defines what's what - * @param tba the TextBytesAtom containing the text - * @param sta the StyleTextPropAtom which defines the character stylings - */ - public TextRun(TextHeaderAtom tha, TextBytesAtom tba, StyleTextPropAtom sta) { - this(tha,tba,null,sta); - } - - /** - * Internal constructor and initializer - */ - private TextRun(TextHeaderAtom tha, TextBytesAtom tba, TextCharsAtom tca, StyleTextPropAtom sta) { - _headerAtom = tha; - _styleAtom = sta; - if(tba != null) { - _byteAtom = tba; - _isUnicode = false; - } else { - _charAtom = tca; - _isUnicode = true; - } - String runRawText = getText(); - - // Figure out the rich text runs - LinkedList pStyles = new LinkedList(); - LinkedList cStyles = new LinkedList(); - if(_styleAtom != null) { - // Get the style atom to grok itself - _styleAtom.setParentTextSize(runRawText.length()); - pStyles = _styleAtom.getParagraphStyles(); - cStyles = _styleAtom.getCharacterStyles(); - } - buildRichTextRuns(pStyles, cStyles, runRawText); - } - - public void buildRichTextRuns(LinkedList pStyles, LinkedList cStyles, String runRawText){ - - // Handle case of no current style, with a default - if(pStyles.size() == 0 || cStyles.size() == 0) { - _rtRuns = new RichTextRun[1]; - _rtRuns[0] = new RichTextRun(this, 0, runRawText.length()); - } else { - // Build up Rich Text Runs, one for each - // character/paragraph style pair - List rtrs = new ArrayList(); - - int pos = 0; - - int curP = 0; - int curC = 0; - int pLenRemain = -1; - int cLenRemain = -1; - - // Build one for each run with the same style - while(pos <= runRawText.length() && curP < pStyles.size() && curC < cStyles.size()) { - // Get the Props to use - TextPropCollection pProps = pStyles.get(curP); - TextPropCollection cProps = cStyles.get(curC); - - int pLen = pProps.getCharactersCovered(); - int cLen = cProps.getCharactersCovered(); - - // Handle new pass - boolean freshSet = false; - if(pLenRemain == -1 && cLenRemain == -1) { freshSet = true; } - if(pLenRemain == -1) { pLenRemain = pLen; } - if(cLenRemain == -1) { cLenRemain = cLen; } - - // So we know how to build the eventual run - int runLen = -1; - boolean pShared = false; - boolean cShared = false; - - // Same size, new styles - neither shared - if(pLen == cLen && freshSet) { - runLen = cLen; - pShared = false; - cShared = false; - curP++; - curC++; - pLenRemain = -1; - cLenRemain = -1; - } else { - // Some sharing - - // See if we are already in a shared block - if(pLenRemain < pLen) { - // Existing shared p block - pShared = true; - - // Do we end with the c block, or either side of it? - if(pLenRemain == cLenRemain) { - // We end at the same time - cShared = false; - runLen = pLenRemain; - curP++; - curC++; - pLenRemain = -1; - cLenRemain = -1; - } else if(pLenRemain < cLenRemain) { - // We end before the c block - cShared = true; - runLen = pLenRemain; - curP++; - cLenRemain -= pLenRemain; - pLenRemain = -1; - } else { - // We end after the c block - cShared = false; - runLen = cLenRemain; - curC++; - pLenRemain -= cLenRemain; - cLenRemain = -1; - } - } else if(cLenRemain < cLen) { - // Existing shared c block - cShared = true; - - // Do we end with the p block, or either side of it? - if(pLenRemain == cLenRemain) { - // We end at the same time - pShared = false; - runLen = cLenRemain; - curP++; - curC++; - pLenRemain = -1; - cLenRemain = -1; - } else if(cLenRemain < pLenRemain) { - // We end before the p block - pShared = true; - runLen = cLenRemain; - curC++; - pLenRemain -= cLenRemain; - cLenRemain = -1; - } else { - // We end after the p block - pShared = false; - runLen = pLenRemain; - curP++; - cLenRemain -= pLenRemain; - pLenRemain = -1; - } - } else { - // Start of a shared block - if(pLenRemain < cLenRemain) { - // Shared c block - pShared = false; - cShared = true; - runLen = pLenRemain; - curP++; - cLenRemain -= pLenRemain; - pLenRemain = -1; - } else { - // Shared p block - pShared = true; - cShared = false; - runLen = cLenRemain; - curC++; - pLenRemain -= cLenRemain; - cLenRemain = -1; - } - } - } - - // Wind on - int prevPos = pos; - pos += runLen; - // Adjust for end-of-run extra 1 length - if(pos > runRawText.length()) { - runLen--; - } - - // Save - RichTextRun rtr = new RichTextRun(this, prevPos, runLen, pProps, cProps, pShared, cShared); - rtrs.add(rtr); - } - - // Build the array - _rtRuns = rtrs.toArray(new RichTextRun[rtrs.size()]); - } - - } - - // Update methods follow - - /** - * Adds the supplied text onto the end of the TextRun, - * creating a new RichTextRun (returned) for it to - * sit in. - * In many cases, before calling this, you'll want to add - * a newline onto the end of your last RichTextRun - */ - public RichTextRun appendText(String s) { - // We will need a StyleTextProp atom - ensureStyleAtomPresent(); - - // First up, append the text to the - // underlying text atom - int oldSize = getRawText().length(); - storeText( - getRawText() + s - ); - - // If either of the previous styles overran - // the text by one, we need to shuffle that - // extra character onto the new ones - int pOverRun = _styleAtom.getParagraphTextLengthCovered() - oldSize; - int cOverRun = _styleAtom.getCharacterTextLengthCovered() - oldSize; - if(pOverRun > 0) { - TextPropCollection tpc = _styleAtom.getParagraphStyles().getLast(); - tpc.updateTextSize( - tpc.getCharactersCovered() - pOverRun - ); - } - if(cOverRun > 0) { - TextPropCollection tpc = _styleAtom.getCharacterStyles().getLast(); - tpc.updateTextSize( - tpc.getCharactersCovered() - cOverRun - ); - } - - // Next, add the styles for its paragraph and characters - TextPropCollection newPTP = - _styleAtom.addParagraphTextPropCollection(s.length()+pOverRun); - TextPropCollection newCTP = - _styleAtom.addCharacterTextPropCollection(s.length()+cOverRun); - - // Now, create the new RichTextRun - RichTextRun nr = new RichTextRun( - this, oldSize, s.length(), - newPTP, newCTP, false, false - ); - - // Add the new RichTextRun onto our list - RichTextRun[] newRuns = new RichTextRun[_rtRuns.length+1]; - System.arraycopy(_rtRuns, 0, newRuns, 0, _rtRuns.length); - newRuns[newRuns.length-1] = nr; - _rtRuns = newRuns; - - // And return the new run to the caller - return nr; - } - - /** - * Saves the given string to the records. Doesn't - * touch the stylings. - */ - private void storeText(String s) { - // Store in the appropriate record - if(_isUnicode) { - // The atom can safely convert to unicode - _charAtom.setText(s); - } else { - // Will it fit in a 8 bit atom? - boolean hasMultibyte = StringUtil.hasMultibyte(s); - if(! hasMultibyte) { - // Fine to go into 8 bit atom - byte[] text = new byte[s.length()]; - StringUtil.putCompressedUnicode(s,text,0); - _byteAtom.setText(text); - } else { - // Need to swap a TextBytesAtom for a TextCharsAtom - - // Build the new TextCharsAtom - _charAtom = new TextCharsAtom(); - _charAtom.setText(s); - - // Use the TextHeaderAtom to do the swap on the parent - RecordContainer parent = _headerAtom.getParentRecord(); - Record[] cr = parent.getChildRecords(); - for(int i=0; i pStyles = _styleAtom.getParagraphStyles(); - while(pStyles.size() > 1) { pStyles.removeLast(); } - - if (!pStyles.isEmpty()) { - pStyles.getFirst().updateTextSize( s.length()+1 ); - } - - LinkedList cStyles = _styleAtom.getCharacterStyles(); - while(cStyles.size() > 1) { cStyles.removeLast(); } - - if (!cStyles.isEmpty()) { - cStyles.getFirst().updateTextSize( s.length()+1 ); - } - - _rtRuns[0].setText(s); - } else { - // Recreate rich text run with no styling - _rtRuns[0] = new RichTextRun(this,0,s.length()); - } - - } - - /** - * Changes the text. - * Converts '\r' into '\n' - */ - public void setText(String s) { - String text = normalize(s); - setRawText(text); - } - - /** - * Ensure a StyleTextPropAtom is present for this run, - * by adding if required. Normally for internal TextRun use. - */ - public void ensureStyleAtomPresent() { - if(_styleAtom != null) { - // All there - return; - } - - // Create a new one at the right size - _styleAtom = new StyleTextPropAtom(getRawText().length() + 1); - - // Use the TextHeader atom to get at the parent - RecordContainer runAtomsParent = _headerAtom.getParentRecord(); - - // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom - Record addAfter = _byteAtom; - if(_byteAtom == null) { addAfter = _charAtom; } - runAtomsParent.addChildAfter(_styleAtom, addAfter); - - // Feed this to our sole rich text run - if(_rtRuns.length != 1) { - throw new IllegalStateException("Needed to add StyleTextPropAtom when had many rich text runs"); - } - // These are the only styles for now - _rtRuns[0].supplyTextProps( - _styleAtom.getParagraphStyles().get(0), - _styleAtom.getCharacterStyles().get(0), - false, - false - ); - } - - // Accesser methods follow - - /** - * Returns the text content of the run, which has been made safe - * for printing and other use. - */ - public String getText() { - String rawText = getRawText(); - - // PowerPoint seems to store files with \r as the line break - // The messes things up on everything but a Mac, so translate - // them to \n - String text = rawText.replace('\r','\n'); - - int type = _headerAtom == null ? 0 : _headerAtom.getTextType(); - if(type == TextHeaderAtom.TITLE_TYPE || type == TextHeaderAtom.CENTER_TITLE_TYPE){ - //0xB acts like cariage return in page titles and like blank in the others - text = text.replace((char) 0x0B, '\n'); - } else { - text = text.replace((char) 0x0B, ' '); - } - return text; - } - - /** - * Returns the raw text content of the run. This hasn't had any - * changes applied to it, and so is probably unlikely to print - * out nicely. - */ - public String getRawText() { - if(_isUnicode) { - return _charAtom.getText(); - } - return _byteAtom.getText(); - } - - /** - * Fetch the rich text runs (runs of text with the same styling) that - * are contained within this block of text - */ - public RichTextRun[] getRichTextRuns() { - return _rtRuns; - } - - /** - * Returns the type of the text, from the TextHeaderAtom. - * Possible values can be seen from TextHeaderAtom - * @see org.apache.poi.hslf.record.TextHeaderAtom - */ - public int getRunType() { - return _headerAtom.getTextType(); - } - - /** - * Changes the type of the text. Values should be taken - * from TextHeaderAtom. No checking is done to ensure you - * set this to a valid value! - * @see org.apache.poi.hslf.record.TextHeaderAtom - */ - public void setRunType(int type) { - _headerAtom.setTextType(type); - } - - /** - * Supply the SlideShow we belong to. - * Also passes it on to our child RichTextRuns - */ - public void supplySlideShow(SlideShow ss) { - slideShow = ss; - if(_rtRuns != null) { - for(int i=0; i<_rtRuns.length; i++) { - _rtRuns[i].supplySlideShow(slideShow); - } - } - } - - public void setSheet(Sheet sheet){ - this._sheet = sheet; - } - - public Sheet getSheet(){ - return this._sheet; - } - - /** - * @return Shape ID - */ - protected int getShapeId(){ - return shapeId; - } - - /** - * @param id Shape ID - */ - protected void setShapeId(int id){ - shapeId = id; - } - - /** - * @return 0-based index of the text run in the SLWT container - */ - protected int getIndex(){ - return slwtIndex; - } - - /** - * @param id 0-based index of the text run in the SLWT container - */ - protected void setIndex(int id){ - slwtIndex = id; - } - - /** - * Is this Text Run one from a {@link PPDrawing}, or is it - * one from the {@link SlideListWithText}? - */ - public boolean isDrawingBased() { - return (slwtIndex == -1); - } - - /** - * Returns the array of all hyperlinks in this text run - * - * @return the array of all hyperlinks in this text run - * or null if not found. - */ - public Hyperlink[] getHyperlinks(){ - return Hyperlink.find(this); - } - - /** - * Fetch RichTextRun at a given position - * - * @param pos 0-based index in the text - * @return RichTextRun or null if not found - */ - public RichTextRun getRichTextRunAt(int pos){ - for (int i = 0; i < _rtRuns.length; i++) { - int start = _rtRuns[i].getStartIndex(); - int end = _rtRuns[i].getEndIndex(); - if(pos >= start && pos < end) return _rtRuns[i]; - } - return null; - } - - public TextRulerAtom getTextRuler(){ - if(_ruler == null){ - if(_records != null) for (int i = 0; i < _records.length; i++) { - if(_records[i] instanceof TextRulerAtom) { - _ruler = (TextRulerAtom)_records[i]; - break; - } - } - - } - return _ruler; - - } - - public TextRulerAtom createTextRuler(){ - _ruler = getTextRuler(); - if(_ruler == null){ - _ruler = TextRulerAtom.getParagraphInstance(); - _headerAtom.getParentRecord().appendChildRecord(_ruler); - } - return _ruler; - } - - /** - * Returns a new string with line breaks converted into internal ppt representation - */ - public String normalize(String s){ - String ns = s.replaceAll("\\r?\\n", "\r"); - return ns; - } - - /** - * Returns records that make up this text run - * - * @return text run records - */ - public Record[] getRecords(){ - return _records; - } - /** Numbered List info */ - public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) { - this.styleTextProp9Atom = styleTextProp9Atom; - } - /** Numbered List info */ - public StyleTextProp9Atom getStyleTextProp9Atom() { - return this.styleTextProp9Atom; - } - - /** Characters covered */ - public StyleTextPropAtom getStyleTextPropAtom() { - return this._styleAtom; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java deleted file mode 100644 index 3f47ae6a5b..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TextShape.java +++ /dev/null @@ -1,641 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.model; - -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.font.FontRenderContext; -import java.awt.font.TextLayout; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.IOException; - -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherProperties; -import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.ddf.EscherSpRecord; -import org.apache.poi.ddf.EscherTextboxRecord; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.record.EscherTextboxWrapper; -import org.apache.poi.hslf.record.InteractiveInfo; -import org.apache.poi.hslf.record.InteractiveInfoAtom; -import org.apache.poi.hslf.record.OEPlaceholderAtom; -import org.apache.poi.hslf.record.OutlineTextRefAtom; -import org.apache.poi.hslf.record.PPDrawing; -import org.apache.poi.hslf.record.Record; -import org.apache.poi.hslf.record.RecordTypes; -import org.apache.poi.hslf.record.RoundTripHFPlaceholder12; -import org.apache.poi.hslf.record.StyleTextPropAtom; -import org.apache.poi.hslf.record.TextBytesAtom; -import org.apache.poi.hslf.record.TextCharsAtom; -import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.record.TxInteractiveInfoAtom; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.sl.usermodel.ShapeContainer; -import org.apache.poi.util.POILogger; - -/** - * A common superclass of all shapes that can hold text. - * - * @author Yegor Kozlov - */ -public abstract class TextShape extends SimpleShape { - - /** - * How to anchor the text - */ - public static final int AnchorTop = 0; - public static final int AnchorMiddle = 1; - public static final int AnchorBottom = 2; - public static final int AnchorTopCentered = 3; - public static final int AnchorMiddleCentered = 4; - public static final int AnchorBottomCentered = 5; - public static final int AnchorTopBaseline = 6; - public static final int AnchorBottomBaseline = 7; - public static final int AnchorTopCenteredBaseline = 8; - public static final int AnchorBottomCenteredBaseline = 9; - - /** - * How to wrap the text - */ - public static final int WrapSquare = 0; - public static final int WrapByPoints = 1; - public static final int WrapNone = 2; - public static final int WrapTopBottom = 3; - public static final int WrapThrough = 4; - - /** - * How to align the text - */ - public static final int AlignLeft = 0; - public static final int AlignCenter = 1; - public static final int AlignRight = 2; - public static final int AlignJustify = 3; - - /** - * TextRun object which holds actual text and format data - */ - protected TextRun _txtrun; - - /** - * Escher container which holds text attributes such as - * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc. - */ - protected EscherTextboxWrapper _txtbox; - - /** - * Used to calculate text bounds - */ - protected static final FontRenderContext _frc = new FontRenderContext(null, true, true); - - /** - * Create a TextBox object and initialize it from the supplied Record container. - * - * @param escherRecord EscherSpContainer container which holds information about this shape - * @param parent the parent of the shape - */ - protected TextShape(EscherContainerRecord escherRecord, ShapeContainer parent){ - super(escherRecord, parent); - - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - * @param parent the parent of this Shape. For example, if this text box is a cell - * in a table then the parent is Table. - */ - public TextShape(ShapeContainer parent){ - super(null, parent); - _escherContainer = createSpContainer(parent instanceof HSLFGroupShape); - } - - /** - * Create a new TextBox. This constructor is used when a new shape is created. - * - */ - public TextShape(){ - this(null); - } - - public TextRun createTextRun(){ - _txtbox = getEscherTextboxWrapper(); - if(_txtbox == null) _txtbox = new EscherTextboxWrapper(); - - _txtrun = getTextRun(); - if(_txtrun == null){ - TextHeaderAtom tha = new TextHeaderAtom(); - tha.setParentRecord(_txtbox); - _txtbox.appendChildRecord(tha); - - TextCharsAtom tca = new TextCharsAtom(); - _txtbox.appendChildRecord(tca); - - StyleTextPropAtom sta = new StyleTextPropAtom(0); - _txtbox.appendChildRecord(sta); - - _txtrun = new TextRun(tha,tca,sta); - _txtrun._records = new Record[]{tha, tca, sta}; - _txtrun.setText(""); - - _escherContainer.addChildRecord(_txtbox.getEscherRecord()); - - setDefaultTextProperties(_txtrun); - } - - return _txtrun; - } - - /** - * Set default properties for the TextRun. - * Depending on the text and shape type the defaults are different: - * TextBox: align=left, valign=top - * AutoShape: align=center, valign=middle - * - */ - protected void setDefaultTextProperties(TextRun _txtrun){ - - } - - /** - * Returns the text contained in this text frame. - * - * @return the text string for this textbox. - */ - public String getText(){ - TextRun tx = getTextRun(); - return tx == null ? null : tx.getText(); - } - - /** - * Sets the text contained in this text frame. - * - * @param text the text string used by this object. - */ - public void setText(String text){ - TextRun tx = getTextRun(); - if(tx == null){ - tx = createTextRun(); - } - tx.setText(text); - setTextId(text.hashCode()); - } - - /** - * When a textbox is added to a sheet we need to tell upper-level - * PPDrawing about it. - * - * @param sh the sheet we are adding to - */ - protected void afterInsert(Sheet sh){ - super.afterInsert(sh); - - EscherTextboxWrapper _txtbox = getEscherTextboxWrapper(); - if(_txtbox != null){ - PPDrawing ppdrawing = sh.getPPDrawing(); - ppdrawing.addTextboxWrapper(_txtbox); - // Ensure the escher layer knows about the added records - try { - _txtbox.writeOut(null); - } catch (IOException e){ - throw new HSLFException(e); - } - if(getAnchor().equals(new Rectangle()) && !"".equals(getText())) resizeToFitText(); - } - if(_txtrun != null) { - _txtrun.setShapeId(getShapeId()); - sh.onAddTextShape(this); - } - } - - protected EscherTextboxWrapper getEscherTextboxWrapper(){ - if(_txtbox == null){ - EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID); - if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord); - } - return _txtbox; - } - /** - * Adjust the size of the TextShape so it encompasses the text inside it. - * - * @return a Rectangle2D that is the bounds of this TextShape. - */ - public Rectangle2D resizeToFitText(){ - String txt = getText(); - if(txt == null || txt.length() == 0) return new Rectangle2D.Float(); - - RichTextRun rt = getTextRun().getRichTextRuns()[0]; - int size = rt.getFontSize(); - int style = 0; - if (rt.isBold()) style |= Font.BOLD; - if (rt.isItalic()) style |= Font.ITALIC; - String fntname = rt.getFontName(); - Font font = new Font(fntname, style, size); - - float width = 0, height = 0, leading = 0; - String[] lines = txt.split("\n"); - for (int i = 0; i < lines.length; i++) { - if(lines[i].length() == 0) continue; - - TextLayout layout = new TextLayout(lines[i], font, _frc); - - leading = Math.max(leading, layout.getLeading()); - width = Math.max(width, layout.getAdvance()); - height = Math.max(height, (height + (layout.getDescent() + layout.getAscent()))); - } - - // add one character to width - Rectangle2D charBounds = font.getMaxCharBounds(_frc); - width += getMarginLeft() + getMarginRight() + charBounds.getWidth(); - - // add leading to height - height += getMarginTop() + getMarginBottom() + leading; - - Rectangle2D anchor = getAnchor2D(); - anchor.setRect(anchor.getX(), anchor.getY(), width, height); - setAnchor(anchor); - - return anchor; - } - - /** - * Returns the type of vertical alignment for the text. - * One of the Anchor* constants defined in this class. - * - * @return the type of alignment - */ - public int getVerticalAlignment(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT); - int valign = TextShape.AnchorTop; - if (prop == null){ - /** - * If vertical alignment was not found in the shape properties then try to - * fetch the master shape and search for the align property there. - */ - int type = getTextRun().getRunType(); - MasterSheet master = getSheet().getMasterSheet(); - if(master != null){ - TextShape masterShape = master.getPlaceholderByTextType(type); - if(masterShape != null) valign = masterShape.getVerticalAlignment(); - } else { - //not found in the master sheet. Use the hardcoded defaults. - switch (type){ - case TextHeaderAtom.TITLE_TYPE: - case TextHeaderAtom.CENTER_TITLE_TYPE: - valign = TextShape.AnchorMiddle; - break; - default: - valign = TextShape.AnchorTop; - break; - } - } - } else { - valign = prop.getPropertyValue(); - } - return valign; - } - - /** - * Sets the type of vertical alignment for the text. - * One of the Anchor* constants defined in this class. - * - * @param align - the type of alignment - */ - public void setVerticalAlignment(int align){ - setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align); - } - - /** - * Sets the type of horizontal alignment for the text. - * One of the Align* constants defined in this class. - * - * @param align - the type of horizontal alignment - */ - public void setHorizontalAlignment(int align){ - TextRun tx = getTextRun(); - if(tx != null) tx.getRichTextRuns()[0].setAlignment(align); - } - - /** - * Gets the type of horizontal alignment for the text. - * One of the Align* constants defined in this class. - * - * @return align - the type of horizontal alignment - */ - public int getHorizontalAlignment(){ - TextRun tx = getTextRun(); - return tx == null ? -1 : tx.getRichTextRuns()[0].getAlignment(); - } - - /** - * Returns the distance (in points) between the bottom of the text frame - * and the bottom of the inscribed rectangle of the shape that contains the text. - * Default value is 1/20 inch. - * - * @return the botom margin - */ - public float getMarginBottom(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM); - int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the botom margin. - * @see #getMarginBottom() - * - * @param margin the bottom margin - */ - public void setMarginBottom(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTBOTTOM, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the left edge of the text frame - * and the left edge of the inscribed rectangle of the shape that contains - * the text. - * Default value is 1/10 inch. - * - * @return the left margin - */ - public float getMarginLeft(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT); - int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the left margin. - * @see #getMarginLeft() - * - * @param margin the left margin - */ - public void setMarginLeft(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTLEFT, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the right edge of the - * text frame and the right edge of the inscribed rectangle of the shape - * that contains the text. - * Default value is 1/10 inch. - * - * @return the right margin - */ - public float getMarginRight(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT); - int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the right margin. - * @see #getMarginRight() - * - * @param margin the right margin - */ - public void setMarginRight(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTRIGHT, (int)(margin*EMU_PER_POINT)); - } - - /** - * Returns the distance (in points) between the top of the text frame - * and the top of the inscribed rectangle of the shape that contains the text. - * Default value is 1/20 inch. - * - * @return the top margin - */ - public float getMarginTop(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP); - int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue(); - return (float)val/EMU_PER_POINT; - } - - /** - * Sets the top margin. - * @see #getMarginTop() - * - * @param margin the top margin - */ - public void setMarginTop(float margin){ - setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT)); - } - - - /** - * Returns the value indicating word wrap. - * - * @return the value indicating word wrap. - * Must be one of the Wrap* constants defined in this class. - */ - public int getWordWrap(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__WRAPTEXT); - return prop == null ? WrapSquare : prop.getPropertyValue(); - } - - /** - * Specifies how the text should be wrapped - * - * @param wrap the value indicating how the text should be wrapped. - * Must be one of the Wrap* constants defined in this class. - */ - public void setWordWrap(int wrap){ - setEscherProperty(EscherProperties.TEXT__WRAPTEXT, wrap); - } - - /** - * @return id for the text. - */ - public int getTextId(){ - EscherOptRecord opt = getEscherOptRecord(); - EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTID); - return prop == null ? 0 : prop.getPropertyValue(); - } - - /** - * Sets text ID - * - * @param id of the text - */ - public void setTextId(int id){ - setEscherProperty(EscherProperties.TEXT__TEXTID, id); - } - - /** - * @return the TextRun object for this text box - */ - public TextRun getTextRun(){ - if (null == this._txtrun) initTextRun(); - if (null == this._txtrun && null != this._txtbox) { - TextHeaderAtom tha = null; - TextBytesAtom tba = null; - TextCharsAtom tca = null; - StyleTextPropAtom sta = null; - Record[] childRecords = this._txtbox.getChildRecords(); - for (Record r : childRecords) { - if (r instanceof TextHeaderAtom) { - tha = (TextHeaderAtom) r; - } else if (r instanceof TextBytesAtom) { - tba = (TextBytesAtom) r; - } else if (r instanceof TextCharsAtom) { - tca = (TextCharsAtom) r; - } else if (r instanceof StyleTextPropAtom) { - sta = (StyleTextPropAtom) r; - } - } - if (tba != null) { - this._txtrun = new TextRun(tha, tba, sta); - } else if (tca != null) { - this._txtrun = new TextRun(tha, tca, sta); - } - } - return _txtrun; - } - - public void setSheet(Sheet sheet) { - _sheet = sheet; - - // Initialize _txtrun object. - // (We can't do it in the constructor because the sheet - // is not assigned then, it's only built once we have - // all the records) - TextRun tx = getTextRun(); - if (tx != null) { - // Supply the sheet to our child RichTextRuns - tx.setSheet(_sheet); - RichTextRun[] rt = tx.getRichTextRuns(); - for (int i = 0; i < rt.length; i++) { - rt[i].supplySlideShow(_sheet.getSlideShow()); - } - } - - } - - protected void initTextRun(){ - EscherTextboxWrapper txtbox = getEscherTextboxWrapper(); - Sheet sheet = getSheet(); - - if(sheet == null || txtbox == null) return; - - OutlineTextRefAtom ota = null; - - Record[] child = txtbox.getChildRecords(); - for (int i = 0; i < child.length; i++) { - if (child[i] instanceof OutlineTextRefAtom) { - ota = (OutlineTextRefAtom)child[i]; - break; - } - } - - TextRun[] runs = _sheet.getTextRuns(); - if (ota != null) { - int idx = ota.getTextIndex(); - for (int i = 0; i < runs.length; i++) { - if(runs[i].getIndex() == idx){ - _txtrun = runs[i]; - break; - } - } - if(_txtrun == null) { - logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx); - } - } else { - EscherSpRecord escherSpRecord = getEscherChild(EscherSpRecord.RECORD_ID); - int shapeId = escherSpRecord.getShapeId(); - if(runs != null) for (int i = 0; i < runs.length; i++) { - if(runs[i].getShapeId() == shapeId){ - _txtrun = runs[i]; - break; - } - } - } - // ensure the same references child records of TextRun - if(_txtrun != null) for (int i = 0; i < child.length; i++) { - for (Record r : _txtrun.getRecords()) { - if (child[i].getRecordType() == r.getRecordType()) { - child[i] = r; - } - } - } - } - - public void draw(Graphics2D graphics){ - AffineTransform at = graphics.getTransform(); - ShapePainter.paint(this, graphics); - new TextPainter(this).paint(graphics); - graphics.setTransform(at); - } - - /** - * Return OEPlaceholderAtom, the atom that describes a placeholder. - * - * @return OEPlaceholderAtom or null if not found - */ - public OEPlaceholderAtom getPlaceholderAtom(){ - return getClientDataRecord(RecordTypes.OEPlaceholderAtom.typeID); - } - - /** - * - * Assigns a hyperlink to this text shape - * - * @param linkId id of the hyperlink, @see org.apache.poi.hslf.usermodel.SlideShow#addHyperlink(Hyperlink) - * @param beginIndex the beginning index, inclusive. - * @param endIndex the ending index, exclusive. - * @see org.apache.poi.hslf.usermodel.SlideShow#addHyperlink(Hyperlink) - */ - public void setHyperlink(int linkId, int beginIndex, int endIndex){ - //TODO validate beginIndex and endIndex and throw IllegalArgumentException - - InteractiveInfo info = new InteractiveInfo(); - InteractiveInfoAtom infoAtom = info.getInteractiveInfoAtom(); - infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK); - infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url); - infoAtom.setHyperlinkID(linkId); - - _txtbox.appendChildRecord(info); - - TxInteractiveInfoAtom txiatom = new TxInteractiveInfoAtom(); - txiatom.setStartIndex(beginIndex); - txiatom.setEndIndex(endIndex); - _txtbox.appendChildRecord(txiatom); - - } - - @Override - public boolean isPlaceholder() { - OEPlaceholderAtom oep = getPlaceholderAtom(); - if (oep != null) return true; - - //special case for files saved in Office 2007 - RoundTripHFPlaceholder12 hldr = getClientDataRecord(RecordTypes.RoundTripHFPlaceholder12.typeID); - if (hldr != null) return true; - - return false; - } - - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TitleMaster.java b/src/scratchpad/src/org/apache/poi/hslf/model/TitleMaster.java index 843f123890..8184c030fa 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/model/TitleMaster.java +++ b/src/scratchpad/src/org/apache/poi/hslf/model/TitleMaster.java @@ -25,8 +25,8 @@ import org.apache.poi.hslf.record.*; * * @author Yegor Kozlov */ -public final class TitleMaster extends MasterSheet { - private TextRun[] _runs; +public final class TitleMaster extends HSLFMasterSheet { + private HSLFTextParagraph[] _runs; /** * Constructs a TitleMaster @@ -42,7 +42,7 @@ public final class TitleMaster extends MasterSheet { /** * Returns an array of all the TextRuns found */ - public TextRun[] getTextRuns() { + public HSLFTextParagraph[] getTextRuns() { return _runs; } @@ -50,14 +50,14 @@ public final class TitleMaster extends MasterSheet { * Delegate the call to the underlying slide master. */ public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) { - MasterSheet master = getMasterSheet(); + HSLFMasterSheet master = getMasterSheet(); return master == null ? null : master.getStyleAttribute(txtype, level, name, isCharacter); } /** * Returns the slide master for this title master. */ - public MasterSheet getMasterSheet(){ + public HSLFMasterSheet getMasterSheet(){ SlideMaster[] master = getSlideShow().getSlidesMasters(); SlideAtom sa = ((org.apache.poi.hslf.record.Slide)getSheetContainer()).getSlideAtom(); int masterId = sa.getMasterID(); diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFObjectData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFObjectData.java new file mode 100644 index 0000000000..f02ddbe785 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFObjectData.java @@ -0,0 +1,70 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.hslf.usermodel; + +import java.io.InputStream; +import java.io.IOException; + +import org.apache.poi.hslf.record.ExOleObjStg; + +/** + * A class that represents object data embedded in a slide show. + * + * @author Daniel Noll + */ +public class HSLFObjectData { + /** + * The record that contains the object data. + */ + private ExOleObjStg storage; + + /** + * Creates the object data wrapping the record that contains the object data. + * + * @param storage the record that contains the object data. + */ + public HSLFObjectData(ExOleObjStg storage) { + this.storage = storage; + } + + /** + * Gets an input stream which returns the binary of the embedded data. + * + * @return the input stream which will contain the binary of the embedded data. + */ + public InputStream getData() { + return storage.getData(); + } + + /** + * Sets the embedded data. + * + * @param data the embedded data. + */ + public void setData(byte[] data) throws IOException { + storage.setData(data); + } + + /** + * Return the record that contains the object data. + * + * @return the record that contains the object data. + */ + public ExOleObjStg getExOleObjStg() { + return storage; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java new file mode 100644 index 0000000000..9d9b0dc594 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java @@ -0,0 +1,264 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import java.awt.Graphics2D; +import java.io.IOException; +import java.io.OutputStream; +import java.security.MessageDigest; + +import org.apache.poi.hslf.blip.BitmapPainter; +import org.apache.poi.hslf.blip.DIB; +import org.apache.poi.hslf.blip.EMF; +import org.apache.poi.hslf.blip.ImagePainter; +import org.apache.poi.hslf.blip.JPEG; +import org.apache.poi.hslf.blip.PICT; +import org.apache.poi.hslf.blip.PNG; +import org.apache.poi.hslf.blip.WMF; +import org.apache.poi.hslf.model.HSLFPictureShape; +import org.apache.poi.poifs.crypt.CryptoFunctions; +import org.apache.poi.poifs.crypt.HashAlgorithm; +import org.apache.poi.util.LittleEndian; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * A class that represents image data contained in a slide show. + * + * @author Yegor Kozlov + */ +public abstract class HSLFPictureData { + + protected POILogger logger = POILogFactory.getLogger(this.getClass()); + + /** + * Size of the image checksum calculated using MD5 algorithm. + */ + protected static final int CHECKSUM_SIZE = 16; + + /** + * Binary data of the picture + */ + private byte[] rawdata; + /** + * The offset to the picture in the stream + */ + protected int offset; + + /** + * Returns type of this picture. + * Must be one of the static constants defined in the Picture class. + * + * @return type of this picture. + */ + public abstract int getType(); + + + /** + * Returns content type (mime type) of this picture. + * + * @return content type of this picture. + */ + public abstract String getContentType(); + + /** + * Returns the binary data of this Picture + * @return picture data + */ + public abstract byte[] getData(); + + /** + * Set picture data + */ + public abstract void setData(byte[] data) throws IOException; + + /** + * Blip signature. + */ + protected abstract int getSignature(); + + protected static final ImagePainter[] painters = new ImagePainter[8]; + static { + HSLFPictureData.setImagePainter(HSLFPictureShape.PNG, new BitmapPainter()); + HSLFPictureData.setImagePainter(HSLFPictureShape.JPEG, new BitmapPainter()); + HSLFPictureData.setImagePainter(HSLFPictureShape.DIB, new BitmapPainter()); + } + + /** + * Returns the raw binary data of this Picture excluding the first 8 bytes + * which hold image signature and size of the image data. + * + * @return picture data + */ + public byte[] getRawData(){ + return rawdata; + } + + public void setRawData(byte[] data){ + rawdata = data; + } + + /** + * File offset in the 'Pictures' stream + * + * @return offset in the 'Pictures' stream + */ + public int getOffset(){ + return offset; + } + + /** + * Set offset of this picture in the 'Pictures' stream. + * We need to set it when a new picture is created. + * + * @param offset in the 'Pictures' stream + */ + public void setOffset(int offset){ + this.offset = offset; + } + + /** + * Returns 16-byte checksum of this picture + */ + public byte[] getUID(){ + byte[] uid = new byte[16]; + System.arraycopy(rawdata, 0, uid, 0, uid.length); + return uid; + } + + + /** + * Compute 16-byte checksum of this picture using MD5 algorithm. + */ + public static byte[] getChecksum(byte[] data) { + MessageDigest md5 = CryptoFunctions.getMessageDigest(HashAlgorithm.md5); + md5.update(data); + return md5.digest(); + } + + /** + * Write this picture into OutputStream + */ + public void write(OutputStream out) throws IOException { + byte[] data; + + data = new byte[LittleEndian.SHORT_SIZE]; + LittleEndian.putUShort(data, 0, getSignature()); + out.write(data); + + data = new byte[LittleEndian.SHORT_SIZE]; + LittleEndian.putUShort(data, 0, getType() + 0xF018); + out.write(data); + + byte[] rawdata = getRawData(); + + data = new byte[LittleEndian.INT_SIZE]; + LittleEndian.putInt(data, 0, rawdata.length); + out.write(data); + + out.write(rawdata); + } + + /** + * Create an instance of PictureData by type. + * + * @param type type of the picture data. + * Must be one of the static constants defined in the Picture class. + * @return concrete instance of PictureData + */ + public static HSLFPictureData create(int type){ + HSLFPictureData pict; + switch (type){ + case HSLFPictureShape.EMF: + pict = new EMF(); + break; + case HSLFPictureShape.WMF: + pict = new WMF(); + break; + case HSLFPictureShape.PICT: + pict = new PICT(); + break; + case HSLFPictureShape.JPEG: + pict = new JPEG(); + break; + case HSLFPictureShape.PNG: + pict = new PNG(); + break; + case HSLFPictureShape.DIB: + pict = new DIB(); + break; + default: + throw new IllegalArgumentException("Unsupported picture type: " + type); + } + return pict; + } + + /** + * Return 24 byte header which preceeds the actual picture data. + *

    + * The header consists of 2-byte signature, 2-byte type, + * 4-byte image size and 16-byte checksum of the image data. + *

    + * + * @return the 24 byte header which preceeds the actual picture data. + */ + public byte[] getHeader() { + byte[] header = new byte[16 + 8]; + LittleEndian.putInt(header, 0, getSignature()); + LittleEndian.putInt(header, 4, getRawData().length); + System.arraycopy(rawdata, 0, header, 8, 16); + return header; + } + + /** + * Return image size in bytes + * + * @return the size of the picture in bytes + * @deprecated Use getData().length instead. + */ + public int getSize(){ + return getData().length; + } + + public void draw(Graphics2D graphics, HSLFPictureShape parent){ + ImagePainter painter = painters[getType()]; + if(painter != null) painter.paint(graphics, this, parent); + else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName()); + } + + /** + * Register ImagePainter for the specified image type + * + * @param type image type, must be one of the static constants defined in the Picture class. + * @param painter + */ + public static void setImagePainter(int type, ImagePainter painter){ + painters[type] = painter; + } + + /** + * Return ImagePainter for the specified image type + * + * @param type blip type, must be one of the static constants defined in the Picture class. + * @return ImagePainter for the specified image type + */ + public static ImagePainter getImagePainter(int type){ + return painters[type]; + } + +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java new file mode 100644 index 0000000000..1f9f6ca027 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java @@ -0,0 +1,1163 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import java.awt.Dimension; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.poi.ddf.EscherBSERecord; +import org.apache.poi.ddf.EscherContainerRecord; +import org.apache.poi.ddf.EscherOptRecord; +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.hpsf.ClassID; +import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; +import org.apache.poi.hslf.exceptions.HSLFException; +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.ExAviMovie; +import org.apache.poi.hslf.record.ExControl; +import org.apache.poi.hslf.record.ExEmbed; +import org.apache.poi.hslf.record.ExEmbedAtom; +import org.apache.poi.hslf.record.ExHyperlink; +import org.apache.poi.hslf.record.ExHyperlinkAtom; +import org.apache.poi.hslf.record.ExMCIMovie; +import org.apache.poi.hslf.record.ExObjList; +import org.apache.poi.hslf.record.ExObjListAtom; +import org.apache.poi.hslf.record.ExOleObjAtom; +import org.apache.poi.hslf.record.ExOleObjStg; +import org.apache.poi.hslf.record.ExVideoContainer; +import org.apache.poi.hslf.record.FontCollection; +import org.apache.poi.hslf.record.FontEntityAtom; +import org.apache.poi.hslf.record.HeadersFootersContainer; +import org.apache.poi.hslf.record.PersistPtrHolder; +import org.apache.poi.hslf.record.PositionDependentRecord; +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.SlideListWithText; +import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; +import org.apache.poi.hslf.record.SlidePersistAtom; +import org.apache.poi.hslf.record.UserEditAtom; +import org.apache.poi.poifs.filesystem.DirectoryNode; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.sl.usermodel.SlideShow; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + +/** + * This class is a friendly wrapper on top of the more scary HSLFSlideShow. + * + * TODO: - figure out how to match notes to their correct sheet (will involve + * understanding DocSlideList and DocNotesList) - handle Slide creation cleaner + * + * @author Nick Burch + * @author Yegor kozlov + */ +public final class HSLFSlideShow implements SlideShow { + // What we're based on + private HSLFSlideShowImpl _hslfSlideShow; + + // Pointers to the most recent versions of the core records + // (Document, Notes, Slide etc) + private Record[] _mostRecentCoreRecords; + // Lookup between the PersitPtr "sheet" IDs, and the position + // in the mostRecentCoreRecords array + private Map _sheetIdToCoreRecordsLookup; + + // Records that are interesting + private Document _documentRecord; + + // Friendly objects for people to deal with + private SlideMaster[] _masters; + private TitleMaster[] _titleMasters; + private HSLFSlide[] _slides; + private HSLFNotes[] _notes; + private FontCollection _fonts; + + // For logging + private POILogger logger = POILogFactory.getLogger(this.getClass()); + + + /* =============================================================== + * Setup Code + * =============================================================== + */ + + + /** + * Constructs a Powerpoint document from the underlying + * HSLFSlideShow object. Finds the model stuff from this + * + * @param hslfSlideShow the HSLFSlideShow to base on + */ + public HSLFSlideShow(HSLFSlideShowImpl hslfSlideShow) { + // Get useful things from our base slideshow + _hslfSlideShow = hslfSlideShow; + + // Handle Parent-aware Records + for (Record record : _hslfSlideShow.getRecords()) { + if(record instanceof RecordContainer){ + RecordContainer.handleParentAwareRecords((RecordContainer)record); + } + } + + // Find the versions of the core records we'll want to use + findMostRecentCoreRecords(); + + // Build up the model level Slides and Notes + buildSlidesAndNotes(); + } + + /** + * Constructs a new, empty, Powerpoint document. + */ + public HSLFSlideShow() { + this(HSLFSlideShowImpl.create()); + } + + /** + * Constructs a Powerpoint document from an input stream. + */ + public HSLFSlideShow(InputStream inputStream) throws IOException { + this(new HSLFSlideShowImpl(inputStream)); + } + + /** + * Use the PersistPtrHolder entries to figure out what is the "most recent" + * version of all the core records (Document, Notes, Slide etc), and save a + * record of them. Do this by walking from the oldest PersistPtr to the + * newest, overwriting any references found along the way with newer ones + */ + private void findMostRecentCoreRecords() { + // To start with, find the most recent in the byte offset domain + Map mostRecentByBytes = new HashMap(); + for (Record record : _hslfSlideShow.getRecords()) { + if (record instanceof PersistPtrHolder) { + PersistPtrHolder pph = (PersistPtrHolder) record; + + // If we've already seen any of the "slide" IDs for this + // PersistPtr, remove their old positions + int[] ids = pph.getKnownSlideIDs(); + for (int id : ids) { + if (mostRecentByBytes.containsKey(id)) { + mostRecentByBytes.remove(id); + } + } + + // Now, update the byte level locations with their latest values + Map thisSetOfLocations = pph.getSlideLocationsLookup(); + for (int id : ids) { + mostRecentByBytes.put(id, thisSetOfLocations.get(id)); + } + } + } + + // We now know how many unique special records we have, so init + // the array + _mostRecentCoreRecords = new Record[mostRecentByBytes.size()]; + + // We'll also want to be able to turn the slide IDs into a position + // in this array + _sheetIdToCoreRecordsLookup = new HashMap(); + Integer[] allIDs = mostRecentByBytes.keySet().toArray(new Integer[mostRecentByBytes.size()]); + Arrays.sort(allIDs); + for (int i = 0; i < allIDs.length; i++) { + _sheetIdToCoreRecordsLookup.put(allIDs[i], i); + } + + Map mostRecentByBytesRev = new HashMap(mostRecentByBytes.size()); + for (Map.Entry me : mostRecentByBytes.entrySet()) { + mostRecentByBytesRev.put(me.getValue(), me.getKey()); + } + + // Now convert the byte offsets back into record offsets + for (Record record : _hslfSlideShow.getRecords()) { + if (!(record instanceof PositionDependentRecord)) continue; + + PositionDependentRecord pdr = (PositionDependentRecord) record; + int recordAt = pdr.getLastOnDiskOffset(); + + Integer thisID = mostRecentByBytesRev.get(recordAt); + + if (thisID == null) continue; + + // Bingo. Now, where do we store it? + int storeAt = _sheetIdToCoreRecordsLookup.get(thisID); + + // Tell it its Sheet ID, if it cares + if (pdr instanceof PositionDependentRecordContainer) { + PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer) record; + pdrc.setSheetId(thisID); + } + + // Finally, save the record + _mostRecentCoreRecords[storeAt] = record; + } + + // Now look for the interesting records in there + for (Record record : _mostRecentCoreRecords) { + // Check there really is a record at this number + if (record != null) { + // Find the Document, and interesting things in it + if (record.getRecordType() == RecordTypes.Document.typeID) { + _documentRecord = (Document) record; + _fonts = _documentRecord.getEnvironment().getFontCollection(); + } + } else { + // No record at this number + // Odd, but not normally a problem + } + } + } + + /** + * For a given SlideAtomsSet, return the core record, based on the refID + * from the SlidePersistAtom + */ + private Record getCoreRecordForSAS(SlideAtomsSet sas) { + SlidePersistAtom spa = sas.getSlidePersistAtom(); + int refID = spa.getRefID(); + return getCoreRecordForRefID(refID); + } + + /** + * For a given refID (the internal, 0 based numbering scheme), return the + * core record + * + * @param refID + * the refID + */ + private Record getCoreRecordForRefID(int refID) { + Integer coreRecordId = _sheetIdToCoreRecordsLookup.get(refID); + if (coreRecordId != null) { + Record r = _mostRecentCoreRecords[coreRecordId]; + return r; + } + logger.log(POILogger.ERROR, + "We tried to look up a reference to a core record, but there was no core ID for reference ID " + + refID); + return null; + } + + /** + * Build up model level Slide and Notes objects, from the underlying + * records. + */ + private void buildSlidesAndNotes() { + // Ensure we really found a Document record earlier + // If we didn't, then the file is probably corrupt + if (_documentRecord == null) { + throw new CorruptPowerPointFileException( + "The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt."); + } + + // Fetch the SlideListWithTexts in the most up-to-date Document Record + // + // As far as we understand it: + // * The first SlideListWithText will contain a SlideAtomsSet + // for each of the master slides + // * The second SlideListWithText will contain a SlideAtomsSet + // for each of the slides, in their current order + // These SlideAtomsSets will normally contain text + // * The third SlideListWithText (if present), will contain a + // SlideAtomsSet for each Notes + // These SlideAtomsSets will not normally contain text + // + // Having indentified the masters, slides and notes + their orders, + // we have to go and find their matching records + // We always use the latest versions of these records, and use the + // SlideAtom/NotesAtom to match them with the StyleAtomSet + + SlideListWithText masterSLWT = _documentRecord.getMasterSlideListWithText(); + SlideListWithText slidesSLWT = _documentRecord.getSlideSlideListWithText(); + SlideListWithText notesSLWT = _documentRecord.getNotesSlideListWithText(); + + // Find master slides + // These can be MainMaster records, but oddly they can also be + // Slides or Notes, and possibly even other odd stuff.... + // About the only thing you can say is that the master details are in + // the first SLWT. + SlideAtomsSet[] masterSets = new SlideAtomsSet[0]; + if (masterSLWT != null) { + masterSets = masterSLWT.getSlideAtomsSets(); + + ArrayList mmr = new ArrayList(); + ArrayList tmr = new ArrayList(); + + for (SlideAtomsSet sas : masterSets) { + Record r = getCoreRecordForSAS(sas); + int sheetNo = sas.getSlidePersistAtom().getSlideIdentifier(); + if (r instanceof org.apache.poi.hslf.record.Slide) { + TitleMaster master = new TitleMaster((org.apache.poi.hslf.record.Slide) r, + sheetNo); + master.setSlideShow(this); + tmr.add(master); + } else if (r instanceof org.apache.poi.hslf.record.MainMaster) { + SlideMaster master = new SlideMaster((org.apache.poi.hslf.record.MainMaster) r, + sheetNo); + master.setSlideShow(this); + mmr.add(master); + } + } + + _masters = mmr.toArray(new SlideMaster[mmr.size()]); + _titleMasters = tmr.toArray(new TitleMaster[tmr.size()]); + } + + // Having sorted out the masters, that leaves the notes and slides + + // Start by finding the notes records to go with the entries in + // notesSLWT + org.apache.poi.hslf.record.Notes[] notesRecords; + SlideAtomsSet[] notesSets = new SlideAtomsSet[0]; + Map slideIdToNotes = new HashMap(); + if (notesSLWT == null) { + // None + notesRecords = new org.apache.poi.hslf.record.Notes[0]; + } else { + // Match up the records and the SlideAtomSets + notesSets = notesSLWT.getSlideAtomsSets(); + List notesRecordsL = + new ArrayList(); + for (int i = 0; i < notesSets.length; i++) { + // Get the right core record + Record r = getCoreRecordForSAS(notesSets[i]); + + // Ensure it really is a notes record + if (r == null || r instanceof org.apache.poi.hslf.record.Notes) { + if (r == null) { + logger.log(POILogger.WARN, "A Notes SlideAtomSet at " + i + + " said its record was at refID " + + notesSets[i].getSlidePersistAtom().getRefID() + + ", but that record didn't exist - record ignored."); + } + // we need to add also null-records, otherwise the index references to other existing + // don't work anymore + 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(); + int slideId = spa.getSlideIdentifier(); + slideIdToNotes.put(slideId, 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); + } + } + notesRecords = new org.apache.poi.hslf.record.Notes[notesRecordsL.size()]; + notesRecords = notesRecordsL.toArray(notesRecords); + } + + // Now, do the same thing for our slides + org.apache.poi.hslf.record.Slide[] slidesRecords; + SlideAtomsSet[] slidesSets = new SlideAtomsSet[0]; + if (slidesSLWT == null) { + // None + slidesRecords = new org.apache.poi.hslf.record.Slide[0]; + } else { + // Match up the records and the SlideAtomSets + slidesSets = slidesSLWT.getSlideAtomsSets(); + slidesRecords = new org.apache.poi.hslf.record.Slide[slidesSets.length]; + for (int i = 0; i < slidesSets.length; i++) { + // Get the right core record + Record r = getCoreRecordForSAS(slidesSets[i]); + + // Ensure it really is a slide record + if (r instanceof org.apache.poi.hslf.record.Slide) { + slidesRecords[i] = (org.apache.poi.hslf.record.Slide) r; + } else { + 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); + } + } + } + + // Finally, generate model objects for everything + // Notes first + _notes = new HSLFNotes[notesRecords.length]; + for (int i = 0; i < _notes.length; i++) { + if (notesRecords[i] != null) { + _notes[i] = new HSLFNotes(notesRecords[i]); + _notes[i].setSlideShow(this); + } + } + // Then slides + _slides = new HSLFSlide[slidesRecords.length]; + for (int i = 0; i < _slides.length; i++) { + SlideAtomsSet sas = slidesSets[i]; + int slideIdentifier = sas.getSlidePersistAtom().getSlideIdentifier(); + + // Do we have a notes for this? + HSLFNotes notes = null; + // 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 = slideIdToNotes.get(noteId); + if (notesPos != null) { + notes = _notes[notesPos]; + } else { + logger.log(POILogger.ERROR, "Notes not found for noteId=" + noteId); + } + } + + // Now, build our slide + _slides[i] = new HSLFSlide(slidesRecords[i], notes, sas, slideIdentifier, (i + 1)); + _slides[i].setSlideShow(this); + } + } + + /** + * Writes out the slideshow file the is represented by an instance of this + * class + * + * @param out + * The OutputStream to write to. + * @throws IOException + * If there is an unexpected IOException from the passed in + * OutputStream + */ + public void write(OutputStream out) throws IOException { + _hslfSlideShow.write(out); + } + + /* + * =============================================================== + * Accessor Code + * =============================================================== + */ + + /** + * Returns an array of the most recent version of all the interesting + * records + */ + public Record[] getMostRecentCoreRecords() { + return _mostRecentCoreRecords; + } + + /** + * Returns an array of all the normal Slides found in the slideshow + */ + public HSLFSlide[] getSlides() { + return _slides; + } + + /** + * Returns an array of all the normal Notes found in the slideshow + */ + public HSLFNotes[] getNotes() { + return _notes; + } + + /** + * Returns an array of all the normal Slide Masters found in the slideshow + */ + public SlideMaster[] getSlidesMasters() { + return _masters; + } + + /** + * Returns an array of all the normal Title Masters found in the slideshow + */ + public TitleMaster[] getTitleMasters() { + return _titleMasters; + } + + /** + * Returns the data of all the pictures attached to the SlideShow + */ + public HSLFPictureData[] getPictureData() { + return _hslfSlideShow.getPictures(); + } + + /** + * Returns the data of all the embedded OLE object in the SlideShow + */ + public HSLFObjectData[] getEmbeddedObjects() { + return _hslfSlideShow.getEmbeddedObjects(); + } + + /** + * Returns the data of all the embedded sounds in the SlideShow + */ + public HSLFSoundData[] getSoundData() { + return HSLFSoundData.find(_documentRecord); + } + + /** + * Return the current page size + */ + public Dimension getPageSize() { + DocumentAtom docatom = _documentRecord.getDocumentAtom(); + int pgx = (int) docatom.getSlideSizeX() * HSLFShape.POINT_DPI / HSLFShape.MASTER_DPI; + int pgy = (int) docatom.getSlideSizeY() * HSLFShape.POINT_DPI / HSLFShape.MASTER_DPI; + return new Dimension(pgx, pgy); + } + + /** + * Change the current page size + * + * @param pgsize + * page size (in points) + */ + public void setPageSize(Dimension pgsize) { + DocumentAtom docatom = _documentRecord.getDocumentAtom(); + docatom.setSlideSizeX(pgsize.width * HSLFShape.MASTER_DPI / HSLFShape.POINT_DPI); + docatom.setSlideSizeY(pgsize.height * HSLFShape.MASTER_DPI / HSLFShape.POINT_DPI); + } + + /** + * Helper method for usermodel: Get the font collection + */ + protected FontCollection getFontCollection() { + return _fonts; + } + + /** + * Helper method for usermodel and model: Get the document record + */ + public Document getDocumentRecord() { + return _documentRecord; + } + + /* + * =============================================================== + * Re-ordering Code + * =============================================================== + */ + + /** + * Re-orders a slide, to a new position. + * + * @param oldSlideNumber + * The old slide number (1 based) + * @param newSlideNumber + * The new slide number (1 based) + */ + public void reorderSlide(int oldSlideNumber, int newSlideNumber) { + // Ensure these numbers are valid + if (oldSlideNumber < 1 || newSlideNumber < 1) { + throw new IllegalArgumentException("Old and new slide numbers must be greater than 0"); + } + if (oldSlideNumber > _slides.length || newSlideNumber > _slides.length) { + throw new IllegalArgumentException( + "Old and new slide numbers must not exceed the number of slides (" + + _slides.length + ")"); + } + + // The order of slides is defined by the order of slide atom sets in the + // SlideListWithText container. + SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); + SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); + + SlideAtomsSet tmp = sas[oldSlideNumber - 1]; + sas[oldSlideNumber - 1] = sas[newSlideNumber - 1]; + sas[newSlideNumber - 1] = tmp; + + ArrayList lst = new ArrayList(); + for (int i = 0; i < sas.length; i++) { + lst.add(sas[i].getSlidePersistAtom()); + Record[] r = sas[i].getSlideRecords(); + for (int j = 0; j < r.length; j++) { + lst.add(r[j]); + } + _slides[i].setSlideNumber(i + 1); + } + Record[] r = lst.toArray(new Record[lst.size()]); + slwt.setChildRecord(r); + } + + /** + * Removes the slide at the given index (0-based). + *

    + * Shifts any subsequent slides to the left (subtracts one from their slide + * numbers). + *

    + * + * @param index + * the index of the slide to remove (0-based) + * @return the slide that was removed from the slide show. + */ + public HSLFSlide removeSlide(int index) { + int lastSlideIdx = _slides.length - 1; + if (index < 0 || index > lastSlideIdx) { + throw new IllegalArgumentException("Slide index (" + index + ") is out of range (0.." + + lastSlideIdx + ")"); + } + + SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); + SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); + + HSLFSlide removedSlide = null; + ArrayList records = new ArrayList(); + ArrayList sa = new ArrayList(); + ArrayList sl = new ArrayList(); + + ArrayList nt = new ArrayList(); + for (HSLFNotes notes : getNotes()) + nt.add(notes); + + for (int i = 0, num = 0; i < _slides.length; i++) { + if (i != index) { + sl.add(_slides[i]); + sa.add(sas[i]); + _slides[i].setSlideNumber(num++); + records.add(sas[i].getSlidePersistAtom()); + records.addAll(Arrays.asList(sas[i].getSlideRecords())); + } else { + removedSlide = _slides[i]; + nt.remove(_slides[i].getNotesSheet()); + } + } + if (sa.size() == 0) { + _documentRecord.removeSlideListWithText(slwt); + } else { + slwt.setSlideAtomsSets(sa.toArray(new SlideAtomsSet[sa.size()])); + slwt.setChildRecord(records.toArray(new Record[records.size()])); + } + _slides = sl.toArray(new HSLFSlide[sl.size()]); + + // if the removed slide had notes - remove references to them too + + if (removedSlide != null) { + int notesId = removedSlide.getSlideRecord().getSlideAtom().getNotesID(); + if (notesId != 0) { + SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText(); + records = new ArrayList(); + ArrayList na = new ArrayList(); + for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) { + if (ns.getSlidePersistAtom().getSlideIdentifier() != notesId) { + na.add(ns); + records.add(ns.getSlidePersistAtom()); + if (ns.getSlideRecords() != null) + records.addAll(Arrays.asList(ns.getSlideRecords())); + } + } + if (na.size() == 0) { + _documentRecord.removeSlideListWithText(nslwt); + } else { + nslwt.setSlideAtomsSets(na.toArray(new SlideAtomsSet[na.size()])); + nslwt.setChildRecord(records.toArray(new Record[records.size()])); + } + + } + } + _notes = nt.toArray(new HSLFNotes[nt.size()]); + + return removedSlide; + } + + /* + * =============================================================== + * Addition Code + * =============================================================== + */ + + /** + * Create a blank Slide. + * + * @return the created Slide + */ + public HSLFSlide createSlide() { + SlideListWithText slist = null; + + // We need to add the records to the SLWT that deals + // with Slides. + // Add it, if it doesn't exist + slist = _documentRecord.getSlideSlideListWithText(); + if (slist == null) { + // Need to add a new one + slist = new SlideListWithText(); + slist.setInstance(SlideListWithText.SLIDES); + _documentRecord.addSlideListWithText(slist); + } + + // Grab the SlidePersistAtom with the highest Slide Number. + // (Will stay as null if no SlidePersistAtom exists yet in + // the slide, or only master slide's ones do) + SlidePersistAtom prev = null; + for (SlideAtomsSet sas : slist.getSlideAtomsSets()) { + SlidePersistAtom spa = sas.getSlidePersistAtom(); + if (spa.getSlideIdentifier() < 0) { + // This is for a master slide + // Odd, since we only deal with the Slide SLWT + } else { + // Must be for a real slide + if (prev == null) { + prev = spa; + } + if (prev.getSlideIdentifier() < spa.getSlideIdentifier()) { + prev = spa; + } + } + } + + // Set up a new SlidePersistAtom for this slide + SlidePersistAtom sp = new SlidePersistAtom(); + + // First slideId is always 256 + sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); + + // Add this new SlidePersistAtom to the SlideListWithText + slist.addSlidePersistAtom(sp); + + // Create a new Slide + HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length + 1); + slide.setSlideShow(this); + slide.onCreate(); + + // Add in to the list of Slides + HSLFSlide[] s = new HSLFSlide[_slides.length + 1]; + System.arraycopy(_slides, 0, s, 0, _slides.length); + s[_slides.length] = slide; + _slides = s; + logger.log(POILogger.INFO, "Added slide " + _slides.length + " with ref " + sp.getRefID() + + " and identifier " + sp.getSlideIdentifier()); + + // Add the core records for this new Slide to the record tree + org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord(); + int psrId = addPersistentObject(slideRecord); + sp.setRefID(psrId); + slideRecord.setSheetId(psrId); + + slide.setMasterSheet(_masters[0]); + // All done and added + return slide; + } + + /** + * Adds a picture to this presentation and returns the associated index. + * + * @param data + * picture data + * @param format + * the format of the picture. One of constans defined in the + * Picture class. + * @return the index to this picture (1 based). + */ + public int addPicture(byte[] data, int format) throws IOException { + byte[] uid = HSLFPictureData.getChecksum(data); + + EscherContainerRecord bstore; + + EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer(); + bstore = (EscherContainerRecord) HSLFShape.getEscherChild(dggContainer, + EscherContainerRecord.BSTORE_CONTAINER); + if (bstore == null) { + bstore = new EscherContainerRecord(); + bstore.setRecordId(EscherContainerRecord.BSTORE_CONTAINER); + + dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID); + } else { + Iterator iter = bstore.getChildIterator(); + for (int i = 0; iter.hasNext(); i++) { + EscherBSERecord bse = (EscherBSERecord) iter.next(); + if (Arrays.equals(bse.getUid(), uid)) { + return i + 1; + } + } + } + + HSLFPictureData pict = HSLFPictureData.create(format); + pict.setData(data); + + int offset = _hslfSlideShow.addPicture(pict); + + EscherBSERecord bse = new EscherBSERecord(); + bse.setRecordId(EscherBSERecord.RECORD_ID); + bse.setOptions((short) (0x0002 | (format << 4))); + bse.setSize(pict.getRawData().length + 8); + bse.setUid(uid); + + bse.setBlipTypeMacOS((byte) format); + bse.setBlipTypeWin32((byte) format); + + if (format == HSLFPictureShape.EMF) + bse.setBlipTypeMacOS((byte) HSLFPictureShape.PICT); + else if (format == HSLFPictureShape.WMF) + bse.setBlipTypeMacOS((byte) HSLFPictureShape.PICT); + else if (format == HSLFPictureShape.PICT) + bse.setBlipTypeWin32((byte) HSLFPictureShape.WMF); + + bse.setRef(0); + bse.setOffset(offset); + bse.setRemainingData(new byte[0]); + + bstore.addChildRecord(bse); + int count = bstore.getChildRecords().size(); + bstore.setOptions((short) ((count << 4) | 0xF)); + + return count; + } + + /** + * Adds a picture to this presentation and returns the associated index. + * + * @param pict + * the file containing the image to add + * @param format + * the format of the picture. One of constans defined in the + * Picture class. + * @return the index to this picture (1 based). + */ + public int addPicture(File pict, int format) throws IOException { + int length = (int) pict.length(); + byte[] data = new byte[length]; + FileInputStream is = null; + try { + is = new FileInputStream(pict); + is.read(data); + } finally { + if(is != null) is.close(); + } + return addPicture(data, format); + } + + /** + * Add a font in this presentation + * + * @param font + * the font to add + * @return 0-based index of the font + */ + public int addFont(PPFont font) { + FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection(); + int idx = fonts.getFontIndex(font.getFontName()); + if (idx == -1) { + idx = fonts.addFont(font.getFontName(), font.getCharSet(), font.getFontFlags(), font + .getFontType(), font.getPitchAndFamily()); + } + return idx; + } + + /** + * Get a font by index + * + * @param idx + * 0-based index of the font + * @return of an instance of PPFont or null if not + * found + */ + public PPFont getFont(int idx) { + FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection(); + for (Record ch : fonts.getChildRecords()) { + if (ch instanceof FontEntityAtom) { + FontEntityAtom atom = (FontEntityAtom) ch; + if (atom.getFontIndex() == idx) { + return new PPFont(atom); + } + } + } + return null; + } + + /** + * get the number of fonts in the presentation + * + * @return number of fonts + */ + public int getNumberOfFonts() { + return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts(); + } + + /** + * Return Header / Footer settings for slides + * + * @return Header / Footer settings for slides + */ + public HeadersFooters getSlideHeadersFooters() { + // detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + + HeadersFootersContainer hdd = null; + for (Record ch : _documentRecord.getChildRecords()) { + if (ch instanceof HeadersFootersContainer + && ((HeadersFootersContainer) ch).getOptions() == HeadersFootersContainer.SlideHeadersFootersContainer) { + hdd = (HeadersFootersContainer) ch; + break; + } + } + boolean newRecord = false; + if (hdd == null) { + hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer); + newRecord = true; + } + return new HeadersFooters(hdd, this, newRecord, ppt2007); + } + + /** + * Return Header / Footer settings for notes + * + * @return Header / Footer settings for notes + */ + public HeadersFooters getNotesHeadersFooters() { + // detect if this ppt was saved in Office2007 + String tag = getSlidesMasters()[0].getProgrammableTag(); + boolean ppt2007 = "___PPT12".equals(tag); + + HeadersFootersContainer hdd = null; + for (Record ch : _documentRecord.getChildRecords()) { + if (ch instanceof HeadersFootersContainer + && ((HeadersFootersContainer) ch).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer) { + hdd = (HeadersFootersContainer) ch; + break; + } + } + boolean newRecord = false; + if (hdd == null) { + hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer); + newRecord = true; + } + if (ppt2007 && _notes.length > 0) { + return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007); + } + return new HeadersFooters(hdd, this, newRecord, ppt2007); + } + + /** + * Add a movie in this presentation + * + * @param path + * the path or url to the movie + * @return 0-based index of the movie + */ + public int addMovie(String path, int type) { + ExMCIMovie mci; + switch (type) { + case MovieShape.MOVIE_MPEG: + mci = new ExMCIMovie(); + break; + case MovieShape.MOVIE_AVI: + mci = new ExAviMovie(); + break; + default: + throw new IllegalArgumentException("Unsupported Movie: " + type); + } + + ExVideoContainer exVideo = mci.getExVideo(); + exVideo.getExMediaAtom().setMask(0xE80000); + exVideo.getPathAtom().setText(path); + + int objectId = addToObjListAtom(mci); + exVideo.getExMediaAtom().setObjectId(objectId); + + return objectId; + } + + /** + * Add a control in this presentation + * + * @param name + * name of the control, e.g. "Shockwave Flash Object" + * @param progId + * OLE Programmatic Identifier, e.g. + * "ShockwaveFlash.ShockwaveFlash.9" + * @return 0-based index of the control + */ + public int addControl(String name, String progId) { + ExControl ctrl = new ExControl(); + ctrl.setProgId(progId); + ctrl.setMenuName(name); + ctrl.setClipboardName(name); + + ExOleObjAtom oleObj = ctrl.getExOleObjAtom(); + oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); + oleObj.setType(ExOleObjAtom.TYPE_CONTROL); + oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); + + int objectId = addToObjListAtom(ctrl); + oleObj.setObjID(objectId); + return objectId; + } + + /** + * Add a hyperlink to this presentation + * + * @return 0-based index of the hyperlink + */ + public int addHyperlink(Hyperlink link) { + ExHyperlink ctrl = new ExHyperlink(); + ExHyperlinkAtom obj = ctrl.getExHyperlinkAtom(); + if(link.getType() == Hyperlink.LINK_SLIDENUMBER) { + ctrl.setLinkURL(link.getAddress(), 0x30); + } else { + ctrl.setLinkURL(link.getAddress()); + } + ctrl.setLinkTitle(link.getTitle()); + + int objectId = addToObjListAtom(ctrl); + link.setId(objectId); + obj.setNumber(objectId); + + return objectId; + } + + /** + * Add a embedded object to this presentation + * + * @return 0-based index of the embedded object + */ + public int addEmbed(POIFSFileSystem poiData) { + DirectoryNode root = poiData.getRoot(); + + // prepare embedded data + if (new ClassID().equals(root.getStorageClsid())) { + // need to set class id + Map olemap = getOleMap(); + ClassID classID = null; + for (Map.Entry entry : olemap.entrySet()) { + if (root.hasEntry(entry.getKey())) { + classID = entry.getValue(); + break; + } + } + if (classID == null) { + throw new IllegalArgumentException("Unsupported embedded document"); + } + + root.setStorageClsid(classID); + } + + ExEmbed exEmbed = new ExEmbed(); + // remove unneccessary infos, so we don't need to specify the type + // of the ole object multiple times + Record children[] = exEmbed.getChildRecords(); + exEmbed.removeChild(children[2]); + exEmbed.removeChild(children[3]); + exEmbed.removeChild(children[4]); + + ExEmbedAtom eeEmbed = exEmbed.getExEmbedAtom(); + eeEmbed.setCantLockServerB(true); + + ExOleObjAtom eeAtom = exEmbed.getExOleObjAtom(); + eeAtom.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); + eeAtom.setType(ExOleObjAtom.TYPE_EMBEDDED); + // eeAtom.setSubType(ExOleObjAtom.SUBTYPE_EXCEL); + // should be ignored?!?, see MS-PPT ExOleObjAtom, but Libre Office sets it ... + eeAtom.setOptions(1226240); + + ExOleObjStg exOleObjStg = new ExOleObjStg(); + try { + final String OLESTREAM_NAME = "\u0001Ole"; + if (!root.hasEntry(OLESTREAM_NAME)) { + // the following data was taken from an example libre office document + // beside this "\u0001Ole" record there were several other records, e.g. CompObj, + // OlePresXXX, but it seems, that they aren't neccessary + byte oleBytes[] = { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + poiData.createDocument(new ByteArrayInputStream(oleBytes), OLESTREAM_NAME); + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + poiData.writeFilesystem(bos); + exOleObjStg.setData(bos.toByteArray()); + } catch (IOException e) { + throw new HSLFException(e); + } + + int psrId = addPersistentObject(exOleObjStg); + exOleObjStg.setPersistId(psrId); + eeAtom.setObjStgDataRef(psrId); + + int objectId = addToObjListAtom(exEmbed); + eeAtom.setObjID(objectId); + return objectId; + } + + protected int addToObjListAtom(RecordContainer exObj) { + ExObjList lst = (ExObjList) _documentRecord.findFirstOfType(RecordTypes.ExObjList.typeID); + if (lst == null) { + lst = new ExObjList(); + _documentRecord.addChildAfter(lst, _documentRecord.getDocumentAtom()); + } + ExObjListAtom objAtom = lst.getExObjListAtom(); + // increment the object ID seed + int objectId = (int) objAtom.getObjectIDSeed() + 1; + objAtom.setObjectIDSeed(objectId); + + lst.addChildAfter(exObj, objAtom); + + return objectId; + } + + protected static Map getOleMap() { + Map olemap = new HashMap(); + olemap.put("PowerPoint Document", ClassID.PPT_SHOW); + olemap.put("Workbook", ClassID.EXCEL97); // as per BIFF8 spec + olemap.put("WORKBOOK", ClassID.EXCEL97); // Typically from third party programs + olemap.put("BOOK", ClassID.EXCEL97); // Typically odd Crystal Reports exports + // ... to be continued + return olemap; + } + + protected int addPersistentObject(PositionDependentRecord slideRecord) { + slideRecord.setLastOnDiskOffset(HSLFSlideShowImpl.UNSET_OFFSET); + _hslfSlideShow.appendRootLevelRecord((Record)slideRecord); + + // For position dependent records, hold where they were and now are + // As we go along, update, and hand over, to any Position Dependent + // records we happen across + Map interestingRecords = + new HashMap(); + + try { + _hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords); + } catch (IOException e) { + throw new HSLFException(e); + } + + PersistPtrHolder ptr = (PersistPtrHolder)interestingRecords.get(RecordTypes.PersistPtrIncrementalBlock); + UserEditAtom usr = (UserEditAtom)interestingRecords.get(RecordTypes.UserEditAtom); + + // persist ID is UserEditAtom.maxPersistWritten + 1 + int psrId = usr.getMaxPersistWritten() + 1; + + // Last view is now of the slide + usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW); + // increment the number of persistent objects + usr.setMaxPersistWritten(psrId); + + // Add the new slide into the last PersistPtr + // (Also need to tell it where it is) + int slideOffset = slideRecord.getLastOnDiskOffset(); + slideRecord.setLastOnDiskOffset(slideOffset); + ptr.addSlideLookup(psrId, slideOffset); + logger.log(POILogger.INFO, "New slide/object ended up at " + slideOffset); + + return psrId; + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSoundData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSoundData.java new file mode 100644 index 0000000000..7750b25f15 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSoundData.java @@ -0,0 +1,94 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import org.apache.poi.hslf.record.*; + +import java.util.ArrayList; + +/** + * A class that represents sound data embedded in a slide show. + * + * @author Yegor Kozlov + */ +public final class HSLFSoundData { + /** + * The record that contains the object data. + */ + private Sound _container; + + /** + * Creates the object data wrapping the record that contains the sound data. + * + * @param container the record that contains the sound data. + */ + public HSLFSoundData(Sound container) { + this._container = container; + } + + /** + * Name of the sound (e.g. "crash") + * + * @return name of the sound + */ + public String getSoundName(){ + return _container.getSoundName(); + } + + /** + * Type of the sound (e.g. ".wav") + * + * @return type of the sound + */ + public String getSoundType(){ + return _container.getSoundType(); + } + + /** + * Gets an input stream which returns the binary of the sound data. + * + * @return the input stream which will contain the binary of the sound data. + */ + public byte[] getData() { + return _container.getSoundData(); + } + + /** + * Find all sound records in the supplied Document records + * + * @param document the document to find in + * @return the array with the sound data + */ + public static HSLFSoundData[] find(Document document){ + ArrayList lst = new ArrayList(); + Record[] ch = document.getChildRecords(); + for (int i = 0; i < ch.length; i++) { + if(ch[i].getRecordType() == RecordTypes.SoundCollection.typeID){ + RecordContainer col = (RecordContainer)ch[i]; + Record[] sr = col.getChildRecords(); + for (int j = 0; j < sr.length; j++) { + if(sr[j] instanceof Sound){ + lst.add(new HSLFSoundData((Sound)sr[j])); + } + } + } + + } + return lst.toArray(new HSLFSoundData[lst.size()]); + } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java new file mode 100644 index 0000000000..06980e9ff5 --- /dev/null +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java @@ -0,0 +1,793 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.hslf.usermodel; + +import java.awt.Color; + +import org.apache.poi.hslf.model.*; +import org.apache.poi.hslf.model.textproperties.BitMaskTextProp; +import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp; +import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp; +import org.apache.poi.hslf.model.textproperties.TextProp; +import org.apache.poi.hslf.model.textproperties.TextPropCollection; +import org.apache.poi.hslf.record.ColorSchemeAtom; +import org.apache.poi.sl.usermodel.TextRun; +import org.apache.poi.util.POILogFactory; +import org.apache.poi.util.POILogger; + + +/** + * Represents a run of text, all with the same style + * + */ +public final class HSLFTextRun implements TextRun { + protected POILogger logger = POILogFactory.getLogger(this.getClass()); + + /** The TextRun we belong to */ + private HSLFTextParagraph parentParagraph; + /** The SlideShow we belong to */ + // private SlideShow slideShow; + + /** Where in the parent TextRun we start from */ + private int startPos; + + /** How long a string (in the parent TextRun) we represent */ + private int length; + + private String _fontname; + /** + * Our paragraph and character style. + * Note - we may share these styles with other RichTextRuns + */ + private TextPropCollection paragraphStyle; + private TextPropCollection characterStyle; + private boolean sharingParagraphStyle; + private boolean sharingCharacterStyle; + + /** + * Create a new wrapper around a (currently not) + * rich text string + * @param parent + * @param startAt + * @param len + */ + public HSLFTextRun(HSLFTextParagraph parent, int startAt, int len) { + this(parent, startAt, len, null, null, false, false); + } + /** + * Create a new wrapper around a rich text string + * @param parent The parent TextRun + * @param startAt The start position of this run + * @param len The length of this run + * @param pStyle The paragraph style property collection + * @param cStyle The character style property collection + * @param pShared The paragraph styles are shared with other runs + * @param cShared The character styles are shared with other runs + */ + public HSLFTextRun(HSLFTextParagraph parent, int startAt, int len, + TextPropCollection pStyle, TextPropCollection cStyle, + boolean pShared, boolean cShared) { + parentParagraph = parent; + startPos = startAt; + length = len; + paragraphStyle = pStyle; + characterStyle = cStyle; + sharingParagraphStyle = pShared; + sharingCharacterStyle = cShared; + } + + /** + * Supply (normally default) textprops, and if they're shared, + * when a run gets them + */ + public void supplyTextProps(TextPropCollection pStyle, TextPropCollection cStyle, boolean pShared, boolean cShared) { + if(paragraphStyle != null || characterStyle != null) { + throw new IllegalStateException("Can't call supplyTextProps if run already has some"); + } + paragraphStyle = pStyle; + characterStyle = cStyle; + sharingParagraphStyle = pShared; + sharingCharacterStyle = cShared; + } + /** + * Supply the SlideShow we belong to + */ + public void updateSheet() { + if (_fontname != null) { + setFontName(_fontname); + _fontname = null; + } + } + + /** + * Get the length of the text + */ + public int getLength() { + return length; + } + + /** + * The beginning index, inclusive. + * + * @return the beginning index, inclusive. + */ + public int getStartIndex(){ + return startPos; + } + + /** + * The ending index, exclusive. + * + * @return the ending index, exclusive. + */ + public int getEndIndex(){ + return startPos + length; + } + + /** + * Fetch the text, in output suitable form + */ + public String getText() { + return parentParagraph.getText().substring(startPos, startPos+length); + } + /** + * Fetch the text, in raw storage form + */ + public String getRawText() { + return parentParagraph.getRawText().substring(startPos, startPos+length); + } + + /** + * Change the text + */ + public void setText(String text) { + String s = parentParagraph.normalize(text); + setRawText(s); + } + + /** + * Change the text + */ + public void setRawText(String text) { + length = text.length(); + parentParagraph.changeTextInRichTextRun(this,text); + } + + /** + * Tells the RichTextRun its new position in the parent TextRun + * @param startAt + */ + public void updateStartPosition(int startAt) { + startPos = startAt; + } + + + // --------------- Internal helpers on rich text properties ------- + + /** + * Fetch the value of the given flag in the CharFlagsTextProp. + * Returns false if the CharFlagsTextProp isn't present, since the + * text property won't be set if there's no CharFlagsTextProp. + */ + private boolean isCharFlagsTextPropVal(int index) { + return getFlag(true, index); + } + + private boolean getFlag(boolean isCharacter, int index) { + TextPropCollection props; + String propname; + if (isCharacter){ + props = characterStyle; + propname = CharFlagsTextProp.NAME; + } else { + props = paragraphStyle; + propname = ParagraphFlagsTextProp.NAME; + } + + BitMaskTextProp prop = null; + if (props != null){ + prop = (BitMaskTextProp)props.findByName(propname); + } + if (prop == null){ + HSLFSheet sheet = parentParagraph.getSheet(); + if(sheet != null){ + int txtype = parentParagraph.getRunType(); + HSLFMasterSheet master = sheet.getMasterSheet(); + if (master != null){ + prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter); + } + } else { + logger.log(POILogger.WARN, "MasterSheet is not available"); + } + } + + return prop == null ? false : prop.getSubValue(index); + } + + /** + * Set the value of the given flag in the CharFlagsTextProp, adding + * it if required. + */ + private void setCharFlagsTextPropVal(int index, boolean value) { + if(getFlag(true, index) != value) setFlag(true, index, value); + } + + public void setFlag(boolean isCharacter, int index, boolean value) { + TextPropCollection props; + String propname; + if (isCharacter){ + props = characterStyle; + propname = CharFlagsTextProp.NAME; + } else { + props = paragraphStyle; + propname = ParagraphFlagsTextProp.NAME; + } + + // Ensure we have the StyleTextProp atom we're going to need + if(props == null) { + parentParagraph.ensureStyleAtomPresent(); + props = isCharacter ? characterStyle : paragraphStyle; + } + + BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(props, propname); + prop.setSubValue(value,index); + } + + /** + * Returns the named TextProp, either by fetching it (if it exists) or adding it + * (if it didn't) + * @param textPropCol The TextPropCollection to fetch from / add into + * @param textPropName The name of the TextProp to fetch/add + */ + private TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) { + // Fetch / Add the TextProp + TextProp tp = textPropCol.findByName(textPropName); + if(tp == null) { + tp = textPropCol.addWithName(textPropName); + } + return tp; + } + + /** + * Fetch the value of the given Character related TextProp. + * Returns -1 if that TextProp isn't present. + * If the TextProp isn't present, the value from the appropriate + * Master Sheet will apply. + */ + private int getCharTextPropVal(String propName) { + TextProp prop = null; + if (characterStyle != null){ + prop = characterStyle.findByName(propName); + } + + if (prop == null){ + HSLFSheet sheet = parentParagraph.getSheet(); + int txtype = parentParagraph.getRunType(); + HSLFMasterSheet master = sheet.getMasterSheet(); + if (master != null) + prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true); + } + return prop == null ? -1 : prop.getValue(); + } + /** + * Fetch the value of the given Paragraph related TextProp. + * Returns -1 if that TextProp isn't present. + * If the TextProp isn't present, the value from the appropriate + * Master Sheet will apply. + */ + private int getParaTextPropVal(String propName) { + TextProp prop = null; + boolean hardAttribute = false; + if (paragraphStyle != null){ + prop = paragraphStyle.findByName(propName); + + BitMaskTextProp maskProp = (BitMaskTextProp)paragraphStyle.findByName(ParagraphFlagsTextProp.NAME); + hardAttribute = maskProp != null && maskProp.getValue() == 0; + } + if (prop == null && !hardAttribute){ + HSLFSheet sheet = parentParagraph.getSheet(); + int txtype = parentParagraph.getRunType(); + HSLFMasterSheet master = sheet.getMasterSheet(); + if (master != null) + prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false); + } + + return prop == null ? -1 : prop.getValue(); + } + + /** + * Sets the value of the given Character TextProp, add if required + * @param propName The name of the Character TextProp + * @param val The value to set for the TextProp + */ + public void setParaTextPropVal(String propName, int val) { + // Ensure we have the StyleTextProp atom we're going to need + if(paragraphStyle == null) { + parentParagraph.ensureStyleAtomPresent(); + // paragraphStyle will now be defined + } + + assert(paragraphStyle!=null); + TextProp tp = fetchOrAddTextProp(paragraphStyle, propName); + tp.setValue(val); + } + /** + * Sets the value of the given Paragraph TextProp, add if required + * @param propName The name of the Paragraph TextProp + * @param val The value to set for the TextProp + */ + public void setCharTextPropVal(String propName, int val) { + // Ensure we have the StyleTextProp atom we're going to need + if(characterStyle == null) { + parentParagraph.ensureStyleAtomPresent(); + // characterStyle will now be defined + } + + assert(characterStyle!=null); + TextProp tp = fetchOrAddTextProp(characterStyle, propName); + tp.setValue(val); + } + + + // --------------- Friendly getters / setters on rich text properties ------- + + /** + * Is the text bold? + */ + public boolean isBold() { + return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX); + } + + /** + * Is the text bold? + */ + public void setBold(boolean bold) { + setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold); + } + + /** + * Is the text italic? + */ + public boolean isItalic() { + return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX); + } + + /** + * Is the text italic? + */ + public void setItalic(boolean italic) { + setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic); + } + + /** + * Is the text underlined? + */ + public boolean isUnderline() { + return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX); + } + + /** + * Is the text underlined? + */ + public void setUnderline(boolean underlined) { + setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined); + } + + /** + * Does the text have a shadow? + */ + public boolean isShadowed() { + return isCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX); + } + + /** + * Does the text have a shadow? + */ + public void setShadowed(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX, flag); + } + + /** + * Is this text embossed? + */ + public boolean isEmbossed() { + return isCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX); + } + + /** + * Is this text embossed? + */ + public void setEmbossed(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag); + } + + /** + * Gets the strikethrough flag + */ + public boolean isStrikethrough() { + return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX); + } + + /** + * Sets the strikethrough flag + */ + public void setStrikethrough(boolean flag) { + setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag); + } + + /** + * Gets the subscript/superscript option + * + * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript + */ + public int getSuperscript() { + int val = getCharTextPropVal("superscript"); + return val == -1 ? 0 : val; + } + + /** + * Sets the subscript/superscript option + * + * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript + */ + public void setSuperscript(int val) { + setCharTextPropVal("superscript", val); + } + + /** + * Gets the font size + */ + public int getFontSize() { + return getCharTextPropVal("font.size"); + } + + + /** + * Sets the font size + */ + public void setFontSize(int fontSize) { + setCharTextPropVal("font.size", fontSize); + } + + /** + * Gets the font index + */ + public int getFontIndex() { + return getCharTextPropVal("font.index"); + } + + /** + * Sets the font index + */ + public void setFontIndex(int idx) { + setCharTextPropVal("font.index", idx); + } + + + /** + * Sets the font name to use + */ + public void setFontName(String fontName) { + HSLFSheet sheet = parentParagraph.getSheet(); + HSLFSlideShowImpl slideShow = (sheet == null) ? null : sheet.getSlideShow(); + if (sheet == null || slideShow == null) { + //we can't set font since slideshow is not assigned yet + _fontname = fontName; + return; + } + // Get the index for this font (adding if needed) + int fontIdx = slideShow.getFontCollection().addFont(fontName); + setCharTextPropVal("font.index", fontIdx); + } + + /** + * Gets the font name + */ + public String getFontName() { + HSLFSheet sheet = parentParagraph.getSheet(); + HSLFSlideShowImpl slideShow = (sheet == null) ? null : sheet.getSlideShow(); + if (sheet == null || slideShow == null) { + return _fontname; + } + int fontIdx = getCharTextPropVal("font.index"); + if(fontIdx == -1) { return null; } + return slideShow.getFontCollection().getFontWithId(fontIdx); + } + + /** + * @return font color as RGB value + * @see java.awt.Color + */ + public Color getFontColor() { + int rgb = getCharTextPropVal("font.color"); + + int cidx = rgb >> 24; + if (rgb % 0x1000000 == 0){ + ColorSchemeAtom ca = parentParagraph.getSheet().getColorScheme(); + if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx); + } + Color tmp = new Color(rgb, true); + return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); + } + + /** + * Sets color of the text, as a int bgr. + * (PowerPoint stores as BlueGreenRed, not the more + * usual RedGreenBlue) + * @see java.awt.Color + */ + public void setFontColor(int bgr) { + setCharTextPropVal("font.color", bgr); + } + + /** + * Sets color of the text, as a java.awt.Color + */ + public void setFontColor(Color color) { + // In PowerPont RGB bytes are swapped, as BGR + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); + setFontColor(rgb); + } + + /** + * Sets the type of horizontal alignment for the text. + * One of the Align* constants defined in the TextBox class. + * + * @param align - the type of alignment + */ + public void setAlignment(int align) { + setParaTextPropVal("alignment", align); + } + /** + * Returns the type of horizontal alignment for the text. + * One of the Align* constants defined in the TextBox class. + * + * @return the type of alignment + */ + public int getAlignment() { + return getParaTextPropVal("alignment"); + } + + /** + * + * @return indentation level + */ + public int getIndentLevel() { + return paragraphStyle == null ? 0 : paragraphStyle.getReservedField(); + } + + /** + * Sets indentation level + * + * @param level indentation level. Must be in the range [0, 4] + */ + public void setIndentLevel(int level) { + if(paragraphStyle != null ) paragraphStyle.setReservedField((short)level); + } + + /** + * Sets whether this rich text run has bullets + */ + public void setBullet(boolean flag) { + setFlag(false, ParagraphFlagsTextProp.BULLET_IDX, flag); + } + + /** + * Returns whether this rich text run has bullets + */ + public boolean isBullet() { + return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX); + } + + /** + * Returns whether this rich text run has bullets + */ + public boolean isBulletHard() { + return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX); + } + + /** + * Sets the bullet character + */ + public void setBulletChar(char c) { + setParaTextPropVal("bullet.char", c); + } + + /** + * Returns the bullet character + */ + public char getBulletChar() { + return (char)getParaTextPropVal("bullet.char"); + } + + /** + * Sets the bullet offset + */ + public void setBulletOffset(int offset) { + setParaTextPropVal("bullet.offset", offset*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI); + } + + /** + * Returns the bullet offset + */ + public int getBulletOffset() { + return getParaTextPropVal("bullet.offset")*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI; + } + + /** + * Sets the text offset + */ + public void setTextOffset(int offset) { + setParaTextPropVal("text.offset", offset*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI); + } + + /** + * Returns the text offset + */ + public int getTextOffset() { + return getParaTextPropVal("text.offset")*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI; + } + + /** + * Sets the bullet size + */ + public void setBulletSize(int size) { + setParaTextPropVal("bullet.size", size); + } + + /** + * Returns the bullet size + */ + public int getBulletSize() { + return getParaTextPropVal("bullet.size"); + } + + /** + * Sets the bullet color + */ + public void setBulletColor(Color color) { + int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); + setParaTextPropVal("bullet.color", rgb); + } + + /** + * Returns the bullet color + */ + public Color getBulletColor() { + int rgb = getParaTextPropVal("bullet.color"); + if(rgb == -1) return getFontColor(); + + int cidx = rgb >> 24; + if (rgb % 0x1000000 == 0){ + ColorSchemeAtom ca = parentParagraph.getSheet().getColorScheme(); + if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx); + } + Color tmp = new Color(rgb, true); + return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); + } + + /** + * Sets the bullet font + */ + public void setBulletFont(int idx) { + setParaTextPropVal("bullet.font", idx); + setFlag(false, ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true); + } + + /** + * Returns the bullet font + */ + public int getBulletFont() { + return getParaTextPropVal("bullet.font"); + } + + /** + * Sets the line spacing. + *

    + * If linespacing >= 0, then linespacing is a percentage of normal line height. + * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates. + *

    + */ + public void setLineSpacing(int val) { + setParaTextPropVal("linespacing", val); + } + + /** + * Returns the line spacing + *

    + * If linespacing >= 0, then linespacing is a percentage of normal line height. + * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates. + *

    + * + * @return the spacing between lines + */ + public int getLineSpacing() { + int val = getParaTextPropVal("linespacing"); + return val == -1 ? 0 : val; + } + + /** + * Sets spacing before a paragraph. + *

    + * If spacebefore >= 0, then spacebefore is a percentage of normal line height. + * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates. + *

    + */ + public void setSpaceBefore(int val) { + setParaTextPropVal("spacebefore", val); + } + + /** + * Returns spacing before a paragraph + *

    + * If spacebefore >= 0, then spacebefore is a percentage of normal line height. + * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates. + *

    + * + * @return the spacing before a paragraph + */ + public int getSpaceBefore() { + int val = getParaTextPropVal("spacebefore"); + return val == -1 ? 0 : val; + } + + /** + * Sets spacing after a paragraph. + *

    + * If spaceafter >= 0, then spaceafter is a percentage of normal line height. + * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates. + *

    + */ + public void setSpaceAfter(int val) { + setParaTextPropVal("spaceafter", val); + } + + /** + * Returns spacing after a paragraph + *

    + * If spaceafter >= 0, then spaceafter is a percentage of normal line height. + * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates. + *

    + * + * @return the spacing before a paragraph + */ + public int getSpaceAfter() { + int val = getParaTextPropVal("spaceafter"); + return val == -1 ? 0 : val; + } + // --------------- Internal HSLF methods, not intended for end-user use! ------- + + /** + * Internal Use Only - get the underlying paragraph style collection. + * For normal use, use the friendly setters and getters + */ + public TextPropCollection _getRawParagraphStyle() { return paragraphStyle; } + /** + * Internal Use Only - get the underlying character style collection. + * For normal use, use the friendly setters and getters + */ + public TextPropCollection _getRawCharacterStyle() { return characterStyle; } + /** + * Internal Use Only - are the Paragraph styles shared? + */ + public boolean _isParagraphStyleShared() { return sharingParagraphStyle; } + /** + * Internal Use Only - are the Character styles shared? + */ + public boolean _isCharacterStyleShared() { return sharingCharacterStyle; } +} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java deleted file mode 100644 index bbef87a96c..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/ObjectData.java +++ /dev/null @@ -1,70 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ -package org.apache.poi.hslf.usermodel; - -import java.io.InputStream; -import java.io.IOException; - -import org.apache.poi.hslf.record.ExOleObjStg; - -/** - * A class that represents object data embedded in a slide show. - * - * @author Daniel Noll - */ -public class ObjectData { - /** - * The record that contains the object data. - */ - private ExOleObjStg storage; - - /** - * Creates the object data wrapping the record that contains the object data. - * - * @param storage the record that contains the object data. - */ - public ObjectData(ExOleObjStg storage) { - this.storage = storage; - } - - /** - * Gets an input stream which returns the binary of the embedded data. - * - * @return the input stream which will contain the binary of the embedded data. - */ - public InputStream getData() { - return storage.getData(); - } - - /** - * Sets the embedded data. - * - * @param data the embedded data. - */ - public void setData(byte[] data) throws IOException { - storage.setData(data); - } - - /** - * Return the record that contains the object data. - * - * @return the record that contains the object data. - */ - public ExOleObjStg getExOleObjStg() { - return storage; - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java deleted file mode 100644 index 857ad5451e..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/PictureData.java +++ /dev/null @@ -1,256 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import java.awt.Graphics2D; -import java.io.IOException; -import java.io.OutputStream; -import java.security.MessageDigest; - -import org.apache.poi.hslf.blip.BitmapPainter; -import org.apache.poi.hslf.blip.DIB; -import org.apache.poi.hslf.blip.EMF; -import org.apache.poi.hslf.blip.ImagePainter; -import org.apache.poi.hslf.blip.JPEG; -import org.apache.poi.hslf.blip.PICT; -import org.apache.poi.hslf.blip.PNG; -import org.apache.poi.hslf.blip.WMF; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.LittleEndian; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * A class that represents image data contained in a slide show. - * - * @author Yegor Kozlov - */ -public abstract class PictureData { - - protected POILogger logger = POILogFactory.getLogger(this.getClass()); - - /** - * Size of the image checksum calculated using MD5 algorithm. - */ - protected static final int CHECKSUM_SIZE = 16; - - /** - * Binary data of the picture - */ - private byte[] rawdata; - /** - * The offset to the picture in the stream - */ - protected int offset; - - /** - * Returns type of this picture. - * Must be one of the static constants defined in the Picture class. - * - * @return type of this picture. - */ - public abstract int getType(); - - /** - * Returns the binary data of this Picture - * @return picture data - */ - public abstract byte[] getData(); - - /** - * Set picture data - */ - public abstract void setData(byte[] data) throws IOException; - - /** - * Blip signature. - */ - protected abstract int getSignature(); - - protected static final ImagePainter[] painters = new ImagePainter[8]; - static { - PictureData.setImagePainter(Picture.PNG, new BitmapPainter()); - PictureData.setImagePainter(Picture.JPEG, new BitmapPainter()); - PictureData.setImagePainter(Picture.DIB, new BitmapPainter()); - } - - /** - * Returns the raw binary data of this Picture excluding the first 8 bytes - * which hold image signature and size of the image data. - * - * @return picture data - */ - public byte[] getRawData(){ - return rawdata; - } - - public void setRawData(byte[] data){ - rawdata = data; - } - - /** - * File offset in the 'Pictures' stream - * - * @return offset in the 'Pictures' stream - */ - public int getOffset(){ - return offset; - } - - /** - * Set offset of this picture in the 'Pictures' stream. - * We need to set it when a new picture is created. - * - * @param offset in the 'Pictures' stream - */ - public void setOffset(int offset){ - this.offset = offset; - } - - /** - * Returns 16-byte checksum of this picture - */ - public byte[] getUID(){ - byte[] uid = new byte[16]; - System.arraycopy(rawdata, 0, uid, 0, uid.length); - return uid; - } - - - /** - * Compute 16-byte checksum of this picture using MD5 algorithm. - */ - public static byte[] getChecksum(byte[] data) { - MessageDigest md5 = CryptoFunctions.getMessageDigest(HashAlgorithm.md5); - md5.update(data); - return md5.digest(); - } - - /** - * Write this picture into OutputStream - */ - public void write(OutputStream out) throws IOException { - byte[] data; - - data = new byte[LittleEndian.SHORT_SIZE]; - LittleEndian.putUShort(data, 0, getSignature()); - out.write(data); - - data = new byte[LittleEndian.SHORT_SIZE]; - LittleEndian.putUShort(data, 0, getType() + 0xF018); - out.write(data); - - byte[] rawdata = getRawData(); - - data = new byte[LittleEndian.INT_SIZE]; - LittleEndian.putInt(data, 0, rawdata.length); - out.write(data); - - out.write(rawdata); - } - - /** - * Create an instance of PictureData by type. - * - * @param type type of the picture data. - * Must be one of the static constants defined in the Picture class. - * @return concrete instance of PictureData - */ - public static PictureData create(int type){ - PictureData pict; - switch (type){ - case Picture.EMF: - pict = new EMF(); - break; - case Picture.WMF: - pict = new WMF(); - break; - case Picture.PICT: - pict = new PICT(); - break; - case Picture.JPEG: - pict = new JPEG(); - break; - case Picture.PNG: - pict = new PNG(); - break; - case Picture.DIB: - pict = new DIB(); - break; - default: - throw new IllegalArgumentException("Unsupported picture type: " + type); - } - return pict; - } - - /** - * Return 24 byte header which preceeds the actual picture data. - *

    - * The header consists of 2-byte signature, 2-byte type, - * 4-byte image size and 16-byte checksum of the image data. - *

    - * - * @return the 24 byte header which preceeds the actual picture data. - */ - public byte[] getHeader() { - byte[] header = new byte[16 + 8]; - LittleEndian.putInt(header, 0, getSignature()); - LittleEndian.putInt(header, 4, getRawData().length); - System.arraycopy(rawdata, 0, header, 8, 16); - return header; - } - - /** - * Return image size in bytes - * - * @return the size of the picture in bytes - * @deprecated Use getData().length instead. - */ - public int getSize(){ - return getData().length; - } - - public void draw(Graphics2D graphics, Picture parent){ - ImagePainter painter = painters[getType()]; - if(painter != null) painter.paint(graphics, this, parent); - else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName()); - } - - /** - * Register ImagePainter for the specified image type - * - * @param type image type, must be one of the static constants defined in the Picture class. - * @param painter - */ - public static void setImagePainter(int type, ImagePainter painter){ - painters[type] = painter; - } - - /** - * Return ImagePainter for the specified image type - * - * @param type blip type, must be one of the static constants defined in the Picture class. - * @return ImagePainter for the specified image type - */ - public static ImagePainter getImagePainter(int type){ - return painters[type]; - } - -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java deleted file mode 100644 index 878f8c12eb..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java +++ /dev/null @@ -1,792 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import java.awt.Color; - -import org.apache.poi.hslf.model.MasterSheet; -import org.apache.poi.hslf.model.HSLFShape; -import org.apache.poi.hslf.model.Sheet; -import org.apache.poi.hslf.model.TextRun; -import org.apache.poi.hslf.model.textproperties.BitMaskTextProp; -import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp; -import org.apache.poi.hslf.model.textproperties.ParagraphFlagsTextProp; -import org.apache.poi.hslf.model.textproperties.TextProp; -import org.apache.poi.hslf.model.textproperties.TextPropCollection; -import org.apache.poi.hslf.record.ColorSchemeAtom; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - - -/** - * Represents a run of text, all with the same style - * - */ -public final class RichTextRun { - protected POILogger logger = POILogFactory.getLogger(this.getClass()); - - /** The TextRun we belong to */ - private TextRun parentRun; - /** The SlideShow we belong to */ - private SlideShow slideShow; - - /** Where in the parent TextRun we start from */ - private int startPos; - - /** How long a string (in the parent TextRun) we represent */ - private int length; - - private String _fontname; - /** - * Our paragraph and character style. - * Note - we may share these styles with other RichTextRuns - */ - private TextPropCollection paragraphStyle; - private TextPropCollection characterStyle; - private boolean sharingParagraphStyle; - private boolean sharingCharacterStyle; - - /** - * Create a new wrapper around a (currently not) - * rich text string - * @param parent - * @param startAt - * @param len - */ - public RichTextRun(TextRun parent, int startAt, int len) { - this(parent, startAt, len, null, null, false, false); - } - /** - * Create a new wrapper around a rich text string - * @param parent The parent TextRun - * @param startAt The start position of this run - * @param len The length of this run - * @param pStyle The paragraph style property collection - * @param cStyle The character style property collection - * @param pShared The paragraph styles are shared with other runs - * @param cShared The character styles are shared with other runs - */ - public RichTextRun(TextRun parent, int startAt, int len, - TextPropCollection pStyle, TextPropCollection cStyle, - boolean pShared, boolean cShared) { - parentRun = parent; - startPos = startAt; - length = len; - paragraphStyle = pStyle; - characterStyle = cStyle; - sharingParagraphStyle = pShared; - sharingCharacterStyle = cShared; - } - - /** - * Supply (normally default) textprops, and if they're shared, - * when a run gets them - */ - public void supplyTextProps(TextPropCollection pStyle, TextPropCollection cStyle, boolean pShared, boolean cShared) { - if(paragraphStyle != null || characterStyle != null) { - throw new IllegalStateException("Can't call supplyTextProps if run already has some"); - } - paragraphStyle = pStyle; - characterStyle = cStyle; - sharingParagraphStyle = pShared; - sharingCharacterStyle = cShared; - } - /** - * Supply the SlideShow we belong to - */ - public void supplySlideShow(SlideShow ss) { - slideShow = ss; - if (_fontname != null) { - setFontName(_fontname); - _fontname = null; - } - } - - /** - * Get the length of the text - */ - public int getLength() { - return length; - } - - /** - * The beginning index, inclusive. - * - * @return the beginning index, inclusive. - */ - public int getStartIndex(){ - return startPos; - } - - /** - * The ending index, exclusive. - * - * @return the ending index, exclusive. - */ - public int getEndIndex(){ - return startPos + length; - } - - /** - * Fetch the text, in output suitable form - */ - public String getText() { - return parentRun.getText().substring(startPos, startPos+length); - } - /** - * Fetch the text, in raw storage form - */ - public String getRawText() { - return parentRun.getRawText().substring(startPos, startPos+length); - } - - /** - * Change the text - */ - public void setText(String text) { - String s = parentRun.normalize(text); - setRawText(s); - } - - /** - * Change the text - */ - public void setRawText(String text) { - length = text.length(); - parentRun.changeTextInRichTextRun(this,text); - } - - /** - * Tells the RichTextRun its new position in the parent TextRun - * @param startAt - */ - public void updateStartPosition(int startAt) { - startPos = startAt; - } - - - // --------------- Internal helpers on rich text properties ------- - - /** - * Fetch the value of the given flag in the CharFlagsTextProp. - * Returns false if the CharFlagsTextProp isn't present, since the - * text property won't be set if there's no CharFlagsTextProp. - */ - private boolean isCharFlagsTextPropVal(int index) { - return getFlag(true, index); - } - - private boolean getFlag(boolean isCharacter, int index) { - TextPropCollection props; - String propname; - if (isCharacter){ - props = characterStyle; - propname = CharFlagsTextProp.NAME; - } else { - props = paragraphStyle; - propname = ParagraphFlagsTextProp.NAME; - } - - BitMaskTextProp prop = null; - if (props != null){ - prop = (BitMaskTextProp)props.findByName(propname); - } - if (prop == null){ - Sheet sheet = parentRun.getSheet(); - if(sheet != null){ - int txtype = parentRun.getRunType(); - MasterSheet master = sheet.getMasterSheet(); - if (master != null){ - prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter); - } - } else { - logger.log(POILogger.WARN, "MasterSheet is not available"); - } - } - - return prop == null ? false : prop.getSubValue(index); - } - - /** - * Set the value of the given flag in the CharFlagsTextProp, adding - * it if required. - */ - private void setCharFlagsTextPropVal(int index, boolean value) { - if(getFlag(true, index) != value) setFlag(true, index, value); - } - - public void setFlag(boolean isCharacter, int index, boolean value) { - TextPropCollection props; - String propname; - if (isCharacter){ - props = characterStyle; - propname = CharFlagsTextProp.NAME; - } else { - props = paragraphStyle; - propname = ParagraphFlagsTextProp.NAME; - } - - // Ensure we have the StyleTextProp atom we're going to need - if(props == null) { - parentRun.ensureStyleAtomPresent(); - props = isCharacter ? characterStyle : paragraphStyle; - } - - BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(props, propname); - prop.setSubValue(value,index); - } - - /** - * Returns the named TextProp, either by fetching it (if it exists) or adding it - * (if it didn't) - * @param textPropCol The TextPropCollection to fetch from / add into - * @param textPropName The name of the TextProp to fetch/add - */ - private TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) { - // Fetch / Add the TextProp - TextProp tp = textPropCol.findByName(textPropName); - if(tp == null) { - tp = textPropCol.addWithName(textPropName); - } - return tp; - } - - /** - * Fetch the value of the given Character related TextProp. - * Returns -1 if that TextProp isn't present. - * If the TextProp isn't present, the value from the appropriate - * Master Sheet will apply. - */ - private int getCharTextPropVal(String propName) { - TextProp prop = null; - if (characterStyle != null){ - prop = characterStyle.findByName(propName); - } - - if (prop == null){ - Sheet sheet = parentRun.getSheet(); - int txtype = parentRun.getRunType(); - MasterSheet master = sheet.getMasterSheet(); - if (master != null) - prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true); - } - return prop == null ? -1 : prop.getValue(); - } - /** - * Fetch the value of the given Paragraph related TextProp. - * Returns -1 if that TextProp isn't present. - * If the TextProp isn't present, the value from the appropriate - * Master Sheet will apply. - */ - private int getParaTextPropVal(String propName) { - TextProp prop = null; - boolean hardAttribute = false; - if (paragraphStyle != null){ - prop = paragraphStyle.findByName(propName); - - BitMaskTextProp maskProp = (BitMaskTextProp)paragraphStyle.findByName(ParagraphFlagsTextProp.NAME); - hardAttribute = maskProp != null && maskProp.getValue() == 0; - } - if (prop == null && !hardAttribute){ - Sheet sheet = parentRun.getSheet(); - int txtype = parentRun.getRunType(); - MasterSheet master = sheet.getMasterSheet(); - if (master != null) - prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false); - } - - return prop == null ? -1 : prop.getValue(); - } - - /** - * Sets the value of the given Character TextProp, add if required - * @param propName The name of the Character TextProp - * @param val The value to set for the TextProp - */ - public void setParaTextPropVal(String propName, int val) { - // Ensure we have the StyleTextProp atom we're going to need - if(paragraphStyle == null) { - parentRun.ensureStyleAtomPresent(); - // paragraphStyle will now be defined - } - - assert(paragraphStyle!=null); - TextProp tp = fetchOrAddTextProp(paragraphStyle, propName); - tp.setValue(val); - } - /** - * Sets the value of the given Paragraph TextProp, add if required - * @param propName The name of the Paragraph TextProp - * @param val The value to set for the TextProp - */ - public void setCharTextPropVal(String propName, int val) { - // Ensure we have the StyleTextProp atom we're going to need - if(characterStyle == null) { - parentRun.ensureStyleAtomPresent(); - // characterStyle will now be defined - } - - assert(characterStyle!=null); - TextProp tp = fetchOrAddTextProp(characterStyle, propName); - tp.setValue(val); - } - - - // --------------- Friendly getters / setters on rich text properties ------- - - /** - * Is the text bold? - */ - public boolean isBold() { - return isCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX); - } - - /** - * Is the text bold? - */ - public void setBold(boolean bold) { - setCharFlagsTextPropVal(CharFlagsTextProp.BOLD_IDX, bold); - } - - /** - * Is the text italic? - */ - public boolean isItalic() { - return isCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX); - } - - /** - * Is the text italic? - */ - public void setItalic(boolean italic) { - setCharFlagsTextPropVal(CharFlagsTextProp.ITALIC_IDX, italic); - } - - /** - * Is the text underlined? - */ - public boolean isUnderlined() { - return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX); - } - - /** - * Is the text underlined? - */ - public void setUnderlined(boolean underlined) { - setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined); - } - - /** - * Does the text have a shadow? - */ - public boolean isShadowed() { - return isCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX); - } - - /** - * Does the text have a shadow? - */ - public void setShadowed(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.SHADOW_IDX, flag); - } - - /** - * Is this text embossed? - */ - public boolean isEmbossed() { - return isCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX); - } - - /** - * Is this text embossed? - */ - public void setEmbossed(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.RELIEF_IDX, flag); - } - - /** - * Gets the strikethrough flag - */ - public boolean isStrikethrough() { - return isCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX); - } - - /** - * Sets the strikethrough flag - */ - public void setStrikethrough(boolean flag) { - setCharFlagsTextPropVal(CharFlagsTextProp.STRIKETHROUGH_IDX, flag); - } - - /** - * Gets the subscript/superscript option - * - * @return the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript - */ - public int getSuperscript() { - int val = getCharTextPropVal("superscript"); - return val == -1 ? 0 : val; - } - - /** - * Sets the subscript/superscript option - * - * @param val the percentage of the font size. If the value is positive, it is superscript, otherwise it is subscript - */ - public void setSuperscript(int val) { - setCharTextPropVal("superscript", val); - } - - /** - * Gets the font size - */ - public int getFontSize() { - return getCharTextPropVal("font.size"); - } - - - /** - * Sets the font size - */ - public void setFontSize(int fontSize) { - setCharTextPropVal("font.size", fontSize); - } - - /** - * Gets the font index - */ - public int getFontIndex() { - return getCharTextPropVal("font.index"); - } - - /** - * Sets the font index - */ - public void setFontIndex(int idx) { - setCharTextPropVal("font.index", idx); - } - - - /** - * Sets the font name to use - */ - public void setFontName(String fontName) { - if (slideShow == null) { - //we can't set font since slideshow is not assigned yet - _fontname = fontName; - } else { - // Get the index for this font (adding if needed) - int fontIdx = slideShow.getFontCollection().addFont(fontName); - setCharTextPropVal("font.index", fontIdx); - } - } - - /** - * Gets the font name - */ - public String getFontName() { - if (slideShow == null) { - return _fontname; - } - int fontIdx = getCharTextPropVal("font.index"); - if(fontIdx == -1) { return null; } - return slideShow.getFontCollection().getFontWithId(fontIdx); - } - - /** - * @return font color as RGB value - * @see java.awt.Color - */ - public Color getFontColor() { - int rgb = getCharTextPropVal("font.color"); - - int cidx = rgb >> 24; - if (rgb % 0x1000000 == 0){ - ColorSchemeAtom ca = parentRun.getSheet().getColorScheme(); - if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx); - } - Color tmp = new Color(rgb, true); - return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); - } - - /** - * Sets color of the text, as a int bgr. - * (PowerPoint stores as BlueGreenRed, not the more - * usual RedGreenBlue) - * @see java.awt.Color - */ - public void setFontColor(int bgr) { - setCharTextPropVal("font.color", bgr); - } - - /** - * Sets color of the text, as a java.awt.Color - */ - public void setFontColor(Color color) { - // In PowerPont RGB bytes are swapped, as BGR - int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); - setFontColor(rgb); - } - - /** - * Sets the type of horizontal alignment for the text. - * One of the Align* constants defined in the TextBox class. - * - * @param align - the type of alignment - */ - public void setAlignment(int align) { - setParaTextPropVal("alignment", align); - } - /** - * Returns the type of horizontal alignment for the text. - * One of the Align* constants defined in the TextBox class. - * - * @return the type of alignment - */ - public int getAlignment() { - return getParaTextPropVal("alignment"); - } - - /** - * - * @return indentation level - */ - public int getIndentLevel() { - return paragraphStyle == null ? 0 : paragraphStyle.getReservedField(); - } - - /** - * Sets indentation level - * - * @param level indentation level. Must be in the range [0, 4] - */ - public void setIndentLevel(int level) { - if(paragraphStyle != null ) paragraphStyle.setReservedField((short)level); - } - - /** - * Sets whether this rich text run has bullets - */ - public void setBullet(boolean flag) { - setFlag(false, ParagraphFlagsTextProp.BULLET_IDX, flag); - } - - /** - * Returns whether this rich text run has bullets - */ - public boolean isBullet() { - return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX); - } - - /** - * Returns whether this rich text run has bullets - */ - public boolean isBulletHard() { - return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX); - } - - /** - * Sets the bullet character - */ - public void setBulletChar(char c) { - setParaTextPropVal("bullet.char", c); - } - - /** - * Returns the bullet character - */ - public char getBulletChar() { - return (char)getParaTextPropVal("bullet.char"); - } - - /** - * Sets the bullet offset - */ - public void setBulletOffset(int offset) { - setParaTextPropVal("bullet.offset", offset*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI); - } - - /** - * Returns the bullet offset - */ - public int getBulletOffset() { - return getParaTextPropVal("bullet.offset")*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI; - } - - /** - * Sets the text offset - */ - public void setTextOffset(int offset) { - setParaTextPropVal("text.offset", offset*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI); - } - - /** - * Returns the text offset - */ - public int getTextOffset() { - return getParaTextPropVal("text.offset")*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI; - } - - /** - * Sets the bullet size - */ - public void setBulletSize(int size) { - setParaTextPropVal("bullet.size", size); - } - - /** - * Returns the bullet size - */ - public int getBulletSize() { - return getParaTextPropVal("bullet.size"); - } - - /** - * Sets the bullet color - */ - public void setBulletColor(Color color) { - int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB(); - setParaTextPropVal("bullet.color", rgb); - } - - /** - * Returns the bullet color - */ - public Color getBulletColor() { - int rgb = getParaTextPropVal("bullet.color"); - if(rgb == -1) return getFontColor(); - - int cidx = rgb >> 24; - if (rgb % 0x1000000 == 0){ - ColorSchemeAtom ca = parentRun.getSheet().getColorScheme(); - if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx); - } - Color tmp = new Color(rgb, true); - return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed()); - } - - /** - * Sets the bullet font - */ - public void setBulletFont(int idx) { - setParaTextPropVal("bullet.font", idx); - setFlag(false, ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true); - } - - /** - * Returns the bullet font - */ - public int getBulletFont() { - return getParaTextPropVal("bullet.font"); - } - - /** - * Sets the line spacing. - *

    - * If linespacing >= 0, then linespacing is a percentage of normal line height. - * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates. - *

    - */ - public void setLineSpacing(int val) { - setParaTextPropVal("linespacing", val); - } - - /** - * Returns the line spacing - *

    - * If linespacing >= 0, then linespacing is a percentage of normal line height. - * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates. - *

    - * - * @return the spacing between lines - */ - public int getLineSpacing() { - int val = getParaTextPropVal("linespacing"); - return val == -1 ? 0 : val; - } - - /** - * Sets spacing before a paragraph. - *

    - * If spacebefore >= 0, then spacebefore is a percentage of normal line height. - * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates. - *

    - */ - public void setSpaceBefore(int val) { - setParaTextPropVal("spacebefore", val); - } - - /** - * Returns spacing before a paragraph - *

    - * If spacebefore >= 0, then spacebefore is a percentage of normal line height. - * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates. - *

    - * - * @return the spacing before a paragraph - */ - public int getSpaceBefore() { - int val = getParaTextPropVal("spacebefore"); - return val == -1 ? 0 : val; - } - - /** - * Sets spacing after a paragraph. - *

    - * If spaceafter >= 0, then spaceafter is a percentage of normal line height. - * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates. - *

    - */ - public void setSpaceAfter(int val) { - setParaTextPropVal("spaceafter", val); - } - - /** - * Returns spacing after a paragraph - *

    - * If spaceafter >= 0, then spaceafter is a percentage of normal line height. - * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates. - *

    - * - * @return the spacing before a paragraph - */ - public int getSpaceAfter() { - int val = getParaTextPropVal("spaceafter"); - return val == -1 ? 0 : val; - } - // --------------- Internal HSLF methods, not intended for end-user use! ------- - - /** - * Internal Use Only - get the underlying paragraph style collection. - * For normal use, use the friendly setters and getters - */ - public TextPropCollection _getRawParagraphStyle() { return paragraphStyle; } - /** - * Internal Use Only - get the underlying character style collection. - * For normal use, use the friendly setters and getters - */ - public TextPropCollection _getRawCharacterStyle() { return characterStyle; } - /** - * Internal Use Only - are the Paragraph styles shared? - */ - public boolean _isParagraphStyleShared() { return sharingParagraphStyle; } - /** - * Internal Use Only - are the Character styles shared? - */ - public boolean _isCharacterStyleShared() { return sharingCharacterStyle; } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java deleted file mode 100644 index d6829b4b4e..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java +++ /dev/null @@ -1,1172 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import java.awt.Dimension; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.ddf.EscherContainerRecord; -import org.apache.poi.ddf.EscherOptRecord; -import org.apache.poi.ddf.EscherRecord; -import org.apache.poi.hpsf.ClassID; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; -import org.apache.poi.hslf.exceptions.HSLFException; -import org.apache.poi.hslf.model.HeadersFooters; -import org.apache.poi.hslf.model.Hyperlink; -import org.apache.poi.hslf.model.MovieShape; -import org.apache.poi.hslf.model.Notes; -import org.apache.poi.hslf.model.PPFont; -import org.apache.poi.hslf.model.Picture; -import org.apache.poi.hslf.model.HSLFShape; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.SlideMaster; -import org.apache.poi.hslf.model.TitleMaster; -import org.apache.poi.hslf.record.Document; -import org.apache.poi.hslf.record.DocumentAtom; -import org.apache.poi.hslf.record.ExAviMovie; -import org.apache.poi.hslf.record.ExControl; -import org.apache.poi.hslf.record.ExEmbed; -import org.apache.poi.hslf.record.ExEmbedAtom; -import org.apache.poi.hslf.record.ExHyperlink; -import org.apache.poi.hslf.record.ExHyperlinkAtom; -import org.apache.poi.hslf.record.ExMCIMovie; -import org.apache.poi.hslf.record.ExObjList; -import org.apache.poi.hslf.record.ExObjListAtom; -import org.apache.poi.hslf.record.ExOleObjAtom; -import org.apache.poi.hslf.record.ExOleObjStg; -import org.apache.poi.hslf.record.ExVideoContainer; -import org.apache.poi.hslf.record.FontCollection; -import org.apache.poi.hslf.record.FontEntityAtom; -import org.apache.poi.hslf.record.HeadersFootersContainer; -import org.apache.poi.hslf.record.PersistPtrHolder; -import org.apache.poi.hslf.record.PositionDependentRecord; -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.SlideListWithText; -import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet; -import org.apache.poi.hslf.record.SlidePersistAtom; -import org.apache.poi.hslf.record.UserEditAtom; -import org.apache.poi.poifs.filesystem.DirectoryNode; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; - -/** - * This class is a friendly wrapper on top of the more scary HSLFSlideShow. - * - * TODO: - figure out how to match notes to their correct sheet (will involve - * understanding DocSlideList and DocNotesList) - handle Slide creation cleaner - * - * @author Nick Burch - * @author Yegor kozlov - */ -public final class SlideShow { - // What we're based on - private HSLFSlideShow _hslfSlideShow; - - // Pointers to the most recent versions of the core records - // (Document, Notes, Slide etc) - private Record[] _mostRecentCoreRecords; - // Lookup between the PersitPtr "sheet" IDs, and the position - // in the mostRecentCoreRecords array - private Map _sheetIdToCoreRecordsLookup; - - // Records that are interesting - private Document _documentRecord; - - // Friendly objects for people to deal with - private SlideMaster[] _masters; - private TitleMaster[] _titleMasters; - private Slide[] _slides; - private Notes[] _notes; - private FontCollection _fonts; - - // For logging - private POILogger logger = POILogFactory.getLogger(this.getClass()); - - - /* =============================================================== - * Setup Code - * =============================================================== - */ - - - /** - * Constructs a Powerpoint document from the underlying - * HSLFSlideShow object. Finds the model stuff from this - * - * @param hslfSlideShow the HSLFSlideShow to base on - */ - public SlideShow(HSLFSlideShow hslfSlideShow) { - // Get useful things from our base slideshow - _hslfSlideShow = hslfSlideShow; - - // Handle Parent-aware Records - for (Record record : _hslfSlideShow.getRecords()) { - if(record instanceof RecordContainer){ - RecordContainer.handleParentAwareRecords((RecordContainer)record); - } - } - - // Find the versions of the core records we'll want to use - findMostRecentCoreRecords(); - - // Build up the model level Slides and Notes - buildSlidesAndNotes(); - } - - /** - * Constructs a new, empty, Powerpoint document. - */ - public SlideShow() { - this(HSLFSlideShow.create()); - } - - /** - * Constructs a Powerpoint document from an input stream. - */ - public SlideShow(InputStream inputStream) throws IOException { - this(new HSLFSlideShow(inputStream)); - } - - /** - * Use the PersistPtrHolder entries to figure out what is the "most recent" - * version of all the core records (Document, Notes, Slide etc), and save a - * record of them. Do this by walking from the oldest PersistPtr to the - * newest, overwriting any references found along the way with newer ones - */ - private void findMostRecentCoreRecords() { - // To start with, find the most recent in the byte offset domain - Map mostRecentByBytes = new HashMap(); - for (Record record : _hslfSlideShow.getRecords()) { - if (record instanceof PersistPtrHolder) { - PersistPtrHolder pph = (PersistPtrHolder) record; - - // If we've already seen any of the "slide" IDs for this - // PersistPtr, remove their old positions - int[] ids = pph.getKnownSlideIDs(); - for (int id : ids) { - if (mostRecentByBytes.containsKey(id)) { - mostRecentByBytes.remove(id); - } - } - - // Now, update the byte level locations with their latest values - Map thisSetOfLocations = pph.getSlideLocationsLookup(); - for (int id : ids) { - mostRecentByBytes.put(id, thisSetOfLocations.get(id)); - } - } - } - - // We now know how many unique special records we have, so init - // the array - _mostRecentCoreRecords = new Record[mostRecentByBytes.size()]; - - // We'll also want to be able to turn the slide IDs into a position - // in this array - _sheetIdToCoreRecordsLookup = new HashMap(); - Integer[] allIDs = mostRecentByBytes.keySet().toArray(new Integer[mostRecentByBytes.size()]); - Arrays.sort(allIDs); - for (int i = 0; i < allIDs.length; i++) { - _sheetIdToCoreRecordsLookup.put(allIDs[i], i); - } - - Map mostRecentByBytesRev = new HashMap(mostRecentByBytes.size()); - for (Map.Entry me : mostRecentByBytes.entrySet()) { - mostRecentByBytesRev.put(me.getValue(), me.getKey()); - } - - // Now convert the byte offsets back into record offsets - for (Record record : _hslfSlideShow.getRecords()) { - if (!(record instanceof PositionDependentRecord)) continue; - - PositionDependentRecord pdr = (PositionDependentRecord) record; - int recordAt = pdr.getLastOnDiskOffset(); - - Integer thisID = mostRecentByBytesRev.get(recordAt); - - if (thisID == null) continue; - - // Bingo. Now, where do we store it? - int storeAt = _sheetIdToCoreRecordsLookup.get(thisID); - - // Tell it its Sheet ID, if it cares - if (pdr instanceof PositionDependentRecordContainer) { - PositionDependentRecordContainer pdrc = (PositionDependentRecordContainer) record; - pdrc.setSheetId(thisID); - } - - // Finally, save the record - _mostRecentCoreRecords[storeAt] = record; - } - - // Now look for the interesting records in there - for (Record record : _mostRecentCoreRecords) { - // Check there really is a record at this number - if (record != null) { - // Find the Document, and interesting things in it - if (record.getRecordType() == RecordTypes.Document.typeID) { - _documentRecord = (Document) record; - _fonts = _documentRecord.getEnvironment().getFontCollection(); - } - } else { - // No record at this number - // Odd, but not normally a problem - } - } - } - - /** - * For a given SlideAtomsSet, return the core record, based on the refID - * from the SlidePersistAtom - */ - private Record getCoreRecordForSAS(SlideAtomsSet sas) { - SlidePersistAtom spa = sas.getSlidePersistAtom(); - int refID = spa.getRefID(); - return getCoreRecordForRefID(refID); - } - - /** - * For a given refID (the internal, 0 based numbering scheme), return the - * core record - * - * @param refID - * the refID - */ - private Record getCoreRecordForRefID(int refID) { - Integer coreRecordId = _sheetIdToCoreRecordsLookup.get(refID); - if (coreRecordId != null) { - Record r = _mostRecentCoreRecords[coreRecordId]; - return r; - } - logger.log(POILogger.ERROR, - "We tried to look up a reference to a core record, but there was no core ID for reference ID " - + refID); - return null; - } - - /** - * Build up model level Slide and Notes objects, from the underlying - * records. - */ - private void buildSlidesAndNotes() { - // Ensure we really found a Document record earlier - // If we didn't, then the file is probably corrupt - if (_documentRecord == null) { - throw new CorruptPowerPointFileException( - "The PowerPoint file didn't contain a Document Record in its PersistPtr blocks. It is probably corrupt."); - } - - // Fetch the SlideListWithTexts in the most up-to-date Document Record - // - // As far as we understand it: - // * The first SlideListWithText will contain a SlideAtomsSet - // for each of the master slides - // * The second SlideListWithText will contain a SlideAtomsSet - // for each of the slides, in their current order - // These SlideAtomsSets will normally contain text - // * The third SlideListWithText (if present), will contain a - // SlideAtomsSet for each Notes - // These SlideAtomsSets will not normally contain text - // - // Having indentified the masters, slides and notes + their orders, - // we have to go and find their matching records - // We always use the latest versions of these records, and use the - // SlideAtom/NotesAtom to match them with the StyleAtomSet - - SlideListWithText masterSLWT = _documentRecord.getMasterSlideListWithText(); - SlideListWithText slidesSLWT = _documentRecord.getSlideSlideListWithText(); - SlideListWithText notesSLWT = _documentRecord.getNotesSlideListWithText(); - - // Find master slides - // These can be MainMaster records, but oddly they can also be - // Slides or Notes, and possibly even other odd stuff.... - // About the only thing you can say is that the master details are in - // the first SLWT. - SlideAtomsSet[] masterSets = new SlideAtomsSet[0]; - if (masterSLWT != null) { - masterSets = masterSLWT.getSlideAtomsSets(); - - ArrayList mmr = new ArrayList(); - ArrayList tmr = new ArrayList(); - - for (SlideAtomsSet sas : masterSets) { - Record r = getCoreRecordForSAS(sas); - int sheetNo = sas.getSlidePersistAtom().getSlideIdentifier(); - if (r instanceof org.apache.poi.hslf.record.Slide) { - TitleMaster master = new TitleMaster((org.apache.poi.hslf.record.Slide) r, - sheetNo); - master.setSlideShow(this); - tmr.add(master); - } else if (r instanceof org.apache.poi.hslf.record.MainMaster) { - SlideMaster master = new SlideMaster((org.apache.poi.hslf.record.MainMaster) r, - sheetNo); - master.setSlideShow(this); - mmr.add(master); - } - } - - _masters = mmr.toArray(new SlideMaster[mmr.size()]); - _titleMasters = tmr.toArray(new TitleMaster[tmr.size()]); - } - - // Having sorted out the masters, that leaves the notes and slides - - // Start by finding the notes records to go with the entries in - // notesSLWT - org.apache.poi.hslf.record.Notes[] notesRecords; - SlideAtomsSet[] notesSets = new SlideAtomsSet[0]; - Map slideIdToNotes = new HashMap(); - if (notesSLWT == null) { - // None - notesRecords = new org.apache.poi.hslf.record.Notes[0]; - } else { - // Match up the records and the SlideAtomSets - notesSets = notesSLWT.getSlideAtomsSets(); - List notesRecordsL = - new ArrayList(); - for (int i = 0; i < notesSets.length; i++) { - // Get the right core record - Record r = getCoreRecordForSAS(notesSets[i]); - - // Ensure it really is a notes record - if (r == null || r instanceof org.apache.poi.hslf.record.Notes) { - if (r == null) { - logger.log(POILogger.WARN, "A Notes SlideAtomSet at " + i - + " said its record was at refID " - + notesSets[i].getSlidePersistAtom().getRefID() - + ", but that record didn't exist - record ignored."); - } - // we need to add also null-records, otherwise the index references to other existing - // don't work anymore - 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(); - int slideId = spa.getSlideIdentifier(); - slideIdToNotes.put(slideId, 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); - } - } - notesRecords = new org.apache.poi.hslf.record.Notes[notesRecordsL.size()]; - notesRecords = notesRecordsL.toArray(notesRecords); - } - - // Now, do the same thing for our slides - org.apache.poi.hslf.record.Slide[] slidesRecords; - SlideAtomsSet[] slidesSets = new SlideAtomsSet[0]; - if (slidesSLWT == null) { - // None - slidesRecords = new org.apache.poi.hslf.record.Slide[0]; - } else { - // Match up the records and the SlideAtomSets - slidesSets = slidesSLWT.getSlideAtomsSets(); - slidesRecords = new org.apache.poi.hslf.record.Slide[slidesSets.length]; - for (int i = 0; i < slidesSets.length; i++) { - // Get the right core record - Record r = getCoreRecordForSAS(slidesSets[i]); - - // Ensure it really is a slide record - if (r instanceof org.apache.poi.hslf.record.Slide) { - slidesRecords[i] = (org.apache.poi.hslf.record.Slide) r; - } else { - 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); - } - } - } - - // Finally, generate model objects for everything - // Notes first - _notes = new Notes[notesRecords.length]; - for (int i = 0; i < _notes.length; i++) { - if (notesRecords[i] != null) { - _notes[i] = new Notes(notesRecords[i]); - _notes[i].setSlideShow(this); - } - } - // Then slides - _slides = new Slide[slidesRecords.length]; - for (int i = 0; i < _slides.length; i++) { - SlideAtomsSet sas = slidesSets[i]; - int slideIdentifier = sas.getSlidePersistAtom().getSlideIdentifier(); - - // Do we have a notes for this? - Notes notes = null; - // 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 = slideIdToNotes.get(noteId); - if (notesPos != null) { - notes = _notes[notesPos]; - } 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); - } - } - - /** - * Writes out the slideshow file the is represented by an instance of this - * class - * - * @param out - * The OutputStream to write to. - * @throws IOException - * If there is an unexpected IOException from the passed in - * OutputStream - */ - public void write(OutputStream out) throws IOException { - _hslfSlideShow.write(out); - } - - /* - * =============================================================== - * Accessor Code - * =============================================================== - */ - - /** - * Returns an array of the most recent version of all the interesting - * records - */ - public Record[] getMostRecentCoreRecords() { - return _mostRecentCoreRecords; - } - - /** - * Returns an array of all the normal Slides found in the slideshow - */ - public Slide[] getSlides() { - return _slides; - } - - /** - * Returns an array of all the normal Notes found in the slideshow - */ - public Notes[] getNotes() { - return _notes; - } - - /** - * Returns an array of all the normal Slide Masters found in the slideshow - */ - public SlideMaster[] getSlidesMasters() { - return _masters; - } - - /** - * Returns an array of all the normal Title Masters found in the slideshow - */ - public TitleMaster[] getTitleMasters() { - return _titleMasters; - } - - /** - * Returns the data of all the pictures attached to the SlideShow - */ - public PictureData[] getPictureData() { - return _hslfSlideShow.getPictures(); - } - - /** - * Returns the data of all the embedded OLE object in the SlideShow - */ - public ObjectData[] getEmbeddedObjects() { - return _hslfSlideShow.getEmbeddedObjects(); - } - - /** - * Returns the data of all the embedded sounds in the SlideShow - */ - public SoundData[] getSoundData() { - return SoundData.find(_documentRecord); - } - - /** - * Return the current page size - */ - public Dimension getPageSize() { - DocumentAtom docatom = _documentRecord.getDocumentAtom(); - int pgx = (int) docatom.getSlideSizeX() * HSLFShape.POINT_DPI / HSLFShape.MASTER_DPI; - int pgy = (int) docatom.getSlideSizeY() * HSLFShape.POINT_DPI / HSLFShape.MASTER_DPI; - return new Dimension(pgx, pgy); - } - - /** - * Change the current page size - * - * @param pgsize - * page size (in points) - */ - public void setPageSize(Dimension pgsize) { - DocumentAtom docatom = _documentRecord.getDocumentAtom(); - docatom.setSlideSizeX(pgsize.width * HSLFShape.MASTER_DPI / HSLFShape.POINT_DPI); - docatom.setSlideSizeY(pgsize.height * HSLFShape.MASTER_DPI / HSLFShape.POINT_DPI); - } - - /** - * Helper method for usermodel: Get the font collection - */ - protected FontCollection getFontCollection() { - return _fonts; - } - - /** - * Helper method for usermodel and model: Get the document record - */ - public Document getDocumentRecord() { - return _documentRecord; - } - - /* - * =============================================================== - * Re-ordering Code - * =============================================================== - */ - - /** - * Re-orders a slide, to a new position. - * - * @param oldSlideNumber - * The old slide number (1 based) - * @param newSlideNumber - * The new slide number (1 based) - */ - public void reorderSlide(int oldSlideNumber, int newSlideNumber) { - // Ensure these numbers are valid - if (oldSlideNumber < 1 || newSlideNumber < 1) { - throw new IllegalArgumentException("Old and new slide numbers must be greater than 0"); - } - if (oldSlideNumber > _slides.length || newSlideNumber > _slides.length) { - throw new IllegalArgumentException( - "Old and new slide numbers must not exceed the number of slides (" - + _slides.length + ")"); - } - - // The order of slides is defined by the order of slide atom sets in the - // SlideListWithText container. - SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); - SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); - - SlideAtomsSet tmp = sas[oldSlideNumber - 1]; - sas[oldSlideNumber - 1] = sas[newSlideNumber - 1]; - sas[newSlideNumber - 1] = tmp; - - ArrayList lst = new ArrayList(); - for (int i = 0; i < sas.length; i++) { - lst.add(sas[i].getSlidePersistAtom()); - Record[] r = sas[i].getSlideRecords(); - for (int j = 0; j < r.length; j++) { - lst.add(r[j]); - } - _slides[i].setSlideNumber(i + 1); - } - Record[] r = lst.toArray(new Record[lst.size()]); - slwt.setChildRecord(r); - } - - /** - * Removes the slide at the given index (0-based). - *

    - * Shifts any subsequent slides to the left (subtracts one from their slide - * numbers). - *

    - * - * @param index - * the index of the slide to remove (0-based) - * @return the slide that was removed from the slide show. - */ - public Slide removeSlide(int index) { - int lastSlideIdx = _slides.length - 1; - if (index < 0 || index > lastSlideIdx) { - throw new IllegalArgumentException("Slide index (" + index + ") is out of range (0.." - + lastSlideIdx + ")"); - } - - SlideListWithText slwt = _documentRecord.getSlideSlideListWithText(); - SlideAtomsSet[] sas = slwt.getSlideAtomsSets(); - - Slide removedSlide = null; - ArrayList records = new ArrayList(); - ArrayList sa = new ArrayList(); - ArrayList sl = new ArrayList(); - - ArrayList nt = new ArrayList(); - for (Notes notes : getNotes()) - nt.add(notes); - - for (int i = 0, num = 0; i < _slides.length; i++) { - if (i != index) { - sl.add(_slides[i]); - sa.add(sas[i]); - _slides[i].setSlideNumber(num++); - records.add(sas[i].getSlidePersistAtom()); - records.addAll(Arrays.asList(sas[i].getSlideRecords())); - } else { - removedSlide = _slides[i]; - nt.remove(_slides[i].getNotesSheet()); - } - } - if (sa.size() == 0) { - _documentRecord.removeSlideListWithText(slwt); - } else { - slwt.setSlideAtomsSets(sa.toArray(new SlideAtomsSet[sa.size()])); - slwt.setChildRecord(records.toArray(new Record[records.size()])); - } - _slides = sl.toArray(new Slide[sl.size()]); - - // if the removed slide had notes - remove references to them too - - if (removedSlide != null) { - int notesId = removedSlide.getSlideRecord().getSlideAtom().getNotesID(); - if (notesId != 0) { - SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText(); - records = new ArrayList(); - ArrayList na = new ArrayList(); - for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) { - if (ns.getSlidePersistAtom().getSlideIdentifier() != notesId) { - na.add(ns); - records.add(ns.getSlidePersistAtom()); - if (ns.getSlideRecords() != null) - records.addAll(Arrays.asList(ns.getSlideRecords())); - } - } - if (na.size() == 0) { - _documentRecord.removeSlideListWithText(nslwt); - } else { - nslwt.setSlideAtomsSets(na.toArray(new SlideAtomsSet[na.size()])); - nslwt.setChildRecord(records.toArray(new Record[records.size()])); - } - - } - } - _notes = nt.toArray(new Notes[nt.size()]); - - return removedSlide; - } - - /* - * =============================================================== - * Addition Code - * =============================================================== - */ - - /** - * Create a blank Slide. - * - * @return the created Slide - */ - public Slide createSlide() { - SlideListWithText slist = null; - - // We need to add the records to the SLWT that deals - // with Slides. - // Add it, if it doesn't exist - slist = _documentRecord.getSlideSlideListWithText(); - if (slist == null) { - // Need to add a new one - slist = new SlideListWithText(); - slist.setInstance(SlideListWithText.SLIDES); - _documentRecord.addSlideListWithText(slist); - } - - // Grab the SlidePersistAtom with the highest Slide Number. - // (Will stay as null if no SlidePersistAtom exists yet in - // the slide, or only master slide's ones do) - SlidePersistAtom prev = null; - for (SlideAtomsSet sas : slist.getSlideAtomsSets()) { - SlidePersistAtom spa = sas.getSlidePersistAtom(); - if (spa.getSlideIdentifier() < 0) { - // This is for a master slide - // Odd, since we only deal with the Slide SLWT - } else { - // Must be for a real slide - if (prev == null) { - prev = spa; - } - if (prev.getSlideIdentifier() < spa.getSlideIdentifier()) { - prev = spa; - } - } - } - - // Set up a new SlidePersistAtom for this slide - SlidePersistAtom sp = new SlidePersistAtom(); - - // First slideId is always 256 - sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1)); - - // Add this new SlidePersistAtom to the SlideListWithText - slist.addSlidePersistAtom(sp); - - // Create a new Slide - Slide slide = new Slide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length + 1); - slide.setSlideShow(this); - slide.onCreate(); - - // Add in to the list of Slides - Slide[] s = new Slide[_slides.length + 1]; - System.arraycopy(_slides, 0, s, 0, _slides.length); - s[_slides.length] = slide; - _slides = s; - logger.log(POILogger.INFO, "Added slide " + _slides.length + " with ref " + sp.getRefID() - + " and identifier " + sp.getSlideIdentifier()); - - // Add the core records for this new Slide to the record tree - org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord(); - int psrId = addPersistentObject(slideRecord); - sp.setRefID(psrId); - slideRecord.setSheetId(psrId); - - slide.setMasterSheet(_masters[0]); - // All done and added - return slide; - } - - /** - * Adds a picture to this presentation and returns the associated index. - * - * @param data - * picture data - * @param format - * the format of the picture. One of constans defined in the - * Picture class. - * @return the index to this picture (1 based). - */ - public int addPicture(byte[] data, int format) throws IOException { - byte[] uid = PictureData.getChecksum(data); - - EscherContainerRecord bstore; - - EscherContainerRecord dggContainer = _documentRecord.getPPDrawingGroup().getDggContainer(); - bstore = (EscherContainerRecord) HSLFShape.getEscherChild(dggContainer, - EscherContainerRecord.BSTORE_CONTAINER); - if (bstore == null) { - bstore = new EscherContainerRecord(); - bstore.setRecordId(EscherContainerRecord.BSTORE_CONTAINER); - - dggContainer.addChildBefore(bstore, EscherOptRecord.RECORD_ID); - } else { - Iterator iter = bstore.getChildIterator(); - for (int i = 0; iter.hasNext(); i++) { - EscherBSERecord bse = (EscherBSERecord) iter.next(); - if (Arrays.equals(bse.getUid(), uid)) { - return i + 1; - } - } - } - - PictureData pict = PictureData.create(format); - pict.setData(data); - - int offset = _hslfSlideShow.addPicture(pict); - - EscherBSERecord bse = new EscherBSERecord(); - bse.setRecordId(EscherBSERecord.RECORD_ID); - bse.setOptions((short) (0x0002 | (format << 4))); - bse.setSize(pict.getRawData().length + 8); - bse.setUid(uid); - - bse.setBlipTypeMacOS((byte) format); - bse.setBlipTypeWin32((byte) format); - - if (format == Picture.EMF) - bse.setBlipTypeMacOS((byte) Picture.PICT); - else if (format == Picture.WMF) - bse.setBlipTypeMacOS((byte) Picture.PICT); - else if (format == Picture.PICT) - bse.setBlipTypeWin32((byte) Picture.WMF); - - bse.setRef(0); - bse.setOffset(offset); - bse.setRemainingData(new byte[0]); - - bstore.addChildRecord(bse); - int count = bstore.getChildRecords().size(); - bstore.setOptions((short) ((count << 4) | 0xF)); - - return count; - } - - /** - * Adds a picture to this presentation and returns the associated index. - * - * @param pict - * the file containing the image to add - * @param format - * the format of the picture. One of constans defined in the - * Picture class. - * @return the index to this picture (1 based). - */ - public int addPicture(File pict, int format) throws IOException { - int length = (int) pict.length(); - byte[] data = new byte[length]; - FileInputStream is = null; - try { - is = new FileInputStream(pict); - is.read(data); - } finally { - if(is != null) is.close(); - } - return addPicture(data, format); - } - - /** - * Add a font in this presentation - * - * @param font - * the font to add - * @return 0-based index of the font - */ - public int addFont(PPFont font) { - FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection(); - int idx = fonts.getFontIndex(font.getFontName()); - if (idx == -1) { - idx = fonts.addFont(font.getFontName(), font.getCharSet(), font.getFontFlags(), font - .getFontType(), font.getPitchAndFamily()); - } - return idx; - } - - /** - * Get a font by index - * - * @param idx - * 0-based index of the font - * @return of an instance of PPFont or null if not - * found - */ - public PPFont getFont(int idx) { - FontCollection fonts = getDocumentRecord().getEnvironment().getFontCollection(); - for (Record ch : fonts.getChildRecords()) { - if (ch instanceof FontEntityAtom) { - FontEntityAtom atom = (FontEntityAtom) ch; - if (atom.getFontIndex() == idx) { - return new PPFont(atom); - } - } - } - return null; - } - - /** - * get the number of fonts in the presentation - * - * @return number of fonts - */ - public int getNumberOfFonts() { - return getDocumentRecord().getEnvironment().getFontCollection().getNumberOfFonts(); - } - - /** - * Return Header / Footer settings for slides - * - * @return Header / Footer settings for slides - */ - public HeadersFooters getSlideHeadersFooters() { - // detect if this ppt was saved in Office2007 - String tag = getSlidesMasters()[0].getProgrammableTag(); - boolean ppt2007 = "___PPT12".equals(tag); - - HeadersFootersContainer hdd = null; - for (Record ch : _documentRecord.getChildRecords()) { - if (ch instanceof HeadersFootersContainer - && ((HeadersFootersContainer) ch).getOptions() == HeadersFootersContainer.SlideHeadersFootersContainer) { - hdd = (HeadersFootersContainer) ch; - break; - } - } - boolean newRecord = false; - if (hdd == null) { - hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer); - newRecord = true; - } - return new HeadersFooters(hdd, this, newRecord, ppt2007); - } - - /** - * Return Header / Footer settings for notes - * - * @return Header / Footer settings for notes - */ - public HeadersFooters getNotesHeadersFooters() { - // detect if this ppt was saved in Office2007 - String tag = getSlidesMasters()[0].getProgrammableTag(); - boolean ppt2007 = "___PPT12".equals(tag); - - HeadersFootersContainer hdd = null; - for (Record ch : _documentRecord.getChildRecords()) { - if (ch instanceof HeadersFootersContainer - && ((HeadersFootersContainer) ch).getOptions() == HeadersFootersContainer.NotesHeadersFootersContainer) { - hdd = (HeadersFootersContainer) ch; - break; - } - } - boolean newRecord = false; - if (hdd == null) { - hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer); - newRecord = true; - } - if (ppt2007 && _notes.length > 0) { - return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007); - } - return new HeadersFooters(hdd, this, newRecord, ppt2007); - } - - /** - * Add a movie in this presentation - * - * @param path - * the path or url to the movie - * @return 0-based index of the movie - */ - public int addMovie(String path, int type) { - ExMCIMovie mci; - switch (type) { - case MovieShape.MOVIE_MPEG: - mci = new ExMCIMovie(); - break; - case MovieShape.MOVIE_AVI: - mci = new ExAviMovie(); - break; - default: - throw new IllegalArgumentException("Unsupported Movie: " + type); - } - - ExVideoContainer exVideo = mci.getExVideo(); - exVideo.getExMediaAtom().setMask(0xE80000); - exVideo.getPathAtom().setText(path); - - int objectId = addToObjListAtom(mci); - exVideo.getExMediaAtom().setObjectId(objectId); - - return objectId; - } - - /** - * Add a control in this presentation - * - * @param name - * name of the control, e.g. "Shockwave Flash Object" - * @param progId - * OLE Programmatic Identifier, e.g. - * "ShockwaveFlash.ShockwaveFlash.9" - * @return 0-based index of the control - */ - public int addControl(String name, String progId) { - ExControl ctrl = new ExControl(); - ctrl.setProgId(progId); - ctrl.setMenuName(name); - ctrl.setClipboardName(name); - - ExOleObjAtom oleObj = ctrl.getExOleObjAtom(); - oleObj.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); - oleObj.setType(ExOleObjAtom.TYPE_CONTROL); - oleObj.setSubType(ExOleObjAtom.SUBTYPE_DEFAULT); - - int objectId = addToObjListAtom(ctrl); - oleObj.setObjID(objectId); - return objectId; - } - - /** - * Add a hyperlink to this presentation - * - * @return 0-based index of the hyperlink - */ - public int addHyperlink(Hyperlink link) { - ExHyperlink ctrl = new ExHyperlink(); - ExHyperlinkAtom obj = ctrl.getExHyperlinkAtom(); - if(link.getType() == Hyperlink.LINK_SLIDENUMBER) { - ctrl.setLinkURL(link.getAddress(), 0x30); - } else { - ctrl.setLinkURL(link.getAddress()); - } - ctrl.setLinkTitle(link.getTitle()); - - int objectId = addToObjListAtom(ctrl); - link.setId(objectId); - obj.setNumber(objectId); - - return objectId; - } - - /** - * Add a embedded object to this presentation - * - * @return 0-based index of the embedded object - */ - public int addEmbed(POIFSFileSystem poiData) { - DirectoryNode root = poiData.getRoot(); - - // prepare embedded data - if (new ClassID().equals(root.getStorageClsid())) { - // need to set class id - Map olemap = getOleMap(); - ClassID classID = null; - for (Map.Entry entry : olemap.entrySet()) { - if (root.hasEntry(entry.getKey())) { - classID = entry.getValue(); - break; - } - } - if (classID == null) { - throw new IllegalArgumentException("Unsupported embedded document"); - } - - root.setStorageClsid(classID); - } - - ExEmbed exEmbed = new ExEmbed(); - // remove unneccessary infos, so we don't need to specify the type - // of the ole object multiple times - Record children[] = exEmbed.getChildRecords(); - exEmbed.removeChild(children[2]); - exEmbed.removeChild(children[3]); - exEmbed.removeChild(children[4]); - - ExEmbedAtom eeEmbed = exEmbed.getExEmbedAtom(); - eeEmbed.setCantLockServerB(true); - - ExOleObjAtom eeAtom = exEmbed.getExOleObjAtom(); - eeAtom.setDrawAspect(ExOleObjAtom.DRAW_ASPECT_VISIBLE); - eeAtom.setType(ExOleObjAtom.TYPE_EMBEDDED); - // eeAtom.setSubType(ExOleObjAtom.SUBTYPE_EXCEL); - // should be ignored?!?, see MS-PPT ExOleObjAtom, but Libre Office sets it ... - eeAtom.setOptions(1226240); - - ExOleObjStg exOleObjStg = new ExOleObjStg(); - try { - final String OLESTREAM_NAME = "\u0001Ole"; - if (!root.hasEntry(OLESTREAM_NAME)) { - // the following data was taken from an example libre office document - // beside this "\u0001Ole" record there were several other records, e.g. CompObj, - // OlePresXXX, but it seems, that they aren't neccessary - byte oleBytes[] = { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - poiData.createDocument(new ByteArrayInputStream(oleBytes), OLESTREAM_NAME); - } - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - poiData.writeFilesystem(bos); - exOleObjStg.setData(bos.toByteArray()); - } catch (IOException e) { - throw new HSLFException(e); - } - - int psrId = addPersistentObject(exOleObjStg); - exOleObjStg.setPersistId(psrId); - eeAtom.setObjStgDataRef(psrId); - - int objectId = addToObjListAtom(exEmbed); - eeAtom.setObjID(objectId); - return objectId; - } - - protected int addToObjListAtom(RecordContainer exObj) { - ExObjList lst = (ExObjList) _documentRecord.findFirstOfType(RecordTypes.ExObjList.typeID); - if (lst == null) { - lst = new ExObjList(); - _documentRecord.addChildAfter(lst, _documentRecord.getDocumentAtom()); - } - ExObjListAtom objAtom = lst.getExObjListAtom(); - // increment the object ID seed - int objectId = (int) objAtom.getObjectIDSeed() + 1; - objAtom.setObjectIDSeed(objectId); - - lst.addChildAfter(exObj, objAtom); - - return objectId; - } - - protected static Map getOleMap() { - Map olemap = new HashMap(); - olemap.put("PowerPoint Document", ClassID.PPT_SHOW); - olemap.put("Workbook", ClassID.EXCEL97); // as per BIFF8 spec - olemap.put("WORKBOOK", ClassID.EXCEL97); // Typically from third party programs - olemap.put("BOOK", ClassID.EXCEL97); // Typically odd Crystal Reports exports - // ... to be continued - return olemap; - } - - protected int addPersistentObject(PositionDependentRecord slideRecord) { - slideRecord.setLastOnDiskOffset(HSLFSlideShow.UNSET_OFFSET); - _hslfSlideShow.appendRootLevelRecord((Record)slideRecord); - - // For position dependent records, hold where they were and now are - // As we go along, update, and hand over, to any Position Dependent - // records we happen across - Map interestingRecords = - new HashMap(); - - try { - _hslfSlideShow.updateAndWriteDependantRecords(null,interestingRecords); - } catch (IOException e) { - throw new HSLFException(e); - } - - PersistPtrHolder ptr = (PersistPtrHolder)interestingRecords.get(RecordTypes.PersistPtrIncrementalBlock); - UserEditAtom usr = (UserEditAtom)interestingRecords.get(RecordTypes.UserEditAtom); - - // persist ID is UserEditAtom.maxPersistWritten + 1 - int psrId = usr.getMaxPersistWritten() + 1; - - // Last view is now of the slide - usr.setLastViewType((short) UserEditAtom.LAST_VIEW_SLIDE_VIEW); - // increment the number of persistent objects - usr.setMaxPersistWritten(psrId); - - // Add the new slide into the last PersistPtr - // (Also need to tell it where it is) - int slideOffset = slideRecord.getLastOnDiskOffset(); - slideRecord.setLastOnDiskOffset(slideOffset); - ptr.addSlideLookup(psrId, slideOffset); - logger.log(POILogger.INFO, "New slide/object ended up at " + slideOffset); - - return psrId; - } -} diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SoundData.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/SoundData.java deleted file mode 100644 index 9fd85e1bdb..0000000000 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/SoundData.java +++ /dev/null @@ -1,94 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.hslf.usermodel; - -import org.apache.poi.hslf.record.*; - -import java.util.ArrayList; - -/** - * A class that represents sound data embedded in a slide show. - * - * @author Yegor Kozlov - */ -public final class SoundData { - /** - * The record that contains the object data. - */ - private Sound _container; - - /** - * Creates the object data wrapping the record that contains the sound data. - * - * @param container the record that contains the sound data. - */ - public SoundData(Sound container) { - this._container = container; - } - - /** - * Name of the sound (e.g. "crash") - * - * @return name of the sound - */ - public String getSoundName(){ - return _container.getSoundName(); - } - - /** - * Type of the sound (e.g. ".wav") - * - * @return type of the sound - */ - public String getSoundType(){ - return _container.getSoundType(); - } - - /** - * Gets an input stream which returns the binary of the sound data. - * - * @return the input stream which will contain the binary of the sound data. - */ - public byte[] getData() { - return _container.getSoundData(); - } - - /** - * Find all sound records in the supplied Document records - * - * @param document the document to find in - * @return the array with the sound data - */ - public static SoundData[] find(Document document){ - ArrayList lst = new ArrayList(); - Record[] ch = document.getChildRecords(); - for (int i = 0; i < ch.length; i++) { - if(ch[i].getRecordType() == RecordTypes.SoundCollection.typeID){ - RecordContainer col = (RecordContainer)ch[i]; - Record[] sr = col.getChildRecords(); - for (int j = 0; j < sr.length; j++) { - if(sr[j] instanceof Sound){ - lst.add(new SoundData((Sound)sr[j])); - } - } - } - - } - return lst.toArray(new SoundData[lst.size()]); - } -} diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java index f28c2cbfd4..f9fc966575 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawAutoShape.java @@ -3,7 +3,7 @@ package org.apache.poi.sl.draw; import org.apache.poi.sl.usermodel.*; -public class DrawAutoShape> extends DrawTextShape { +public class DrawAutoShape>> extends DrawTextShape { public DrawAutoShape(T shape) { super(shape); } diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java index 80b95ee5f6..bf82208cdc 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java @@ -45,7 +45,7 @@ public class DrawFactory { boolean isHint = false; if (graphics != null) { factory = (DrawFactory)graphics.getRenderingHint(DRAW_FACTORY); - isHint = true; + isHint = (factory != null); } // secondly try the thread local default if (factory == null) { @@ -76,25 +76,25 @@ public class DrawFactory { } else if (shape instanceof Background) { return getDrawable((Background)shape); } else if (shape instanceof Slide) { - return getDrawable((Slide)shape); + return getDrawable((Slide)shape); } else if (shape instanceof MasterSheet) { - return getDrawable((MasterSheet)shape); + return getDrawable((MasterSheet)shape); } else if (shape instanceof Sheet) { - return getDrawable((Sheet)shape); + return getDrawable((Sheet)shape); } throw new IllegalArgumentException("Unsupported shape type: "+shape.getClass()); } - public > DrawSlide getDrawable(T sheet) { + public > DrawSlide getDrawable(T sheet) { return new DrawSlide(sheet); } - public > DrawSheet getDrawable(T sheet) { + public > DrawSheet getDrawable(T sheet) { return new DrawSheet(sheet); } - public > DrawMasterSheet getDrawable(T sheet) { + public > DrawMasterSheet getDrawable(T sheet) { return new DrawMasterSheet(sheet); } diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java index 7a89828ede..452704a757 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawMasterSheet.java @@ -3,7 +3,7 @@ package org.apache.poi.sl.draw; import org.apache.poi.sl.usermodel.*; -public class DrawMasterSheet> extends DrawSheet { +public class DrawMasterSheet> extends DrawSheet { public DrawMasterSheet(T sheet) { super(sheet); diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java index 77a0da740a..ca2346b207 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawPaint.java @@ -17,6 +17,7 @@ package org.apache.poi.sl.draw; +import static org.apache.poi.sl.usermodel.PaintStyle.TRANSPARENT_PAINT; import java.awt.*; import java.awt.MultipleGradientPaint.ColorSpaceType; import java.awt.MultipleGradientPaint.CycleMethod; @@ -35,7 +36,7 @@ import org.apache.poi.util.POILogger; public class DrawPaint { - public final static Color NO_PAINT = new Color(0xFF, 0xFF, 0xFF, 0); + private final static POILogger LOG = POILogFactory.getLogger(DrawPaint.class); protected PlaceableShape shape; @@ -43,6 +44,21 @@ public class DrawPaint { public DrawPaint(PlaceableShape shape) { this.shape = shape; } + + public static SolidPaint createSolidPaint(final Color color) { + return new SolidPaint() { + public ColorStyle getSolidColor() { + return new ColorStyle(){ + public Color getColor() { return color; } + public int getAlpha() { return -1; } + public int getLumOff() { return -1; } + public int getLumMod() { return -1; } + public int getShade() { return -1; } + public int getTint() { return -1; } + }; + } + }; + } public Paint getPaint(Graphics2D graphics, PaintStyle paint) { if (paint instanceof SolidPaint) { @@ -74,7 +90,7 @@ public class DrawPaint { protected Paint getTexturePaint(TexturePaint fill, Graphics2D graphics) { InputStream is = fill.getImageData(); - if (is == null) return NO_PAINT; + if (is == null) return TRANSPARENT_PAINT.getSolidColor().getColor(); assert(graphics != null); ImageRenderer renderer = (ImageRenderer)graphics.getRenderingHint(Drawable.IMAGE_RENDERER); @@ -84,7 +100,7 @@ public class DrawPaint { renderer.loadImage(fill.getImageData(), fill.getContentType()); } catch (IOException e) { LOG.log(POILogger.ERROR, "Can't load image data - using transparent color", e); - return NO_PAINT; + return TRANSPARENT_PAINT.getSolidColor().getColor(); } int alpha = fill.getAlpha(); @@ -105,7 +121,9 @@ public class DrawPaint { public static Color applyColorTransform(ColorStyle color){ Color result = color.getColor(); - if (result == null || color.getAlpha() == 100) return NO_PAINT; + if (result == null || color.getAlpha() == 100) { + return TRANSPARENT_PAINT.getSolidColor().getColor(); + } result = applyAlpha(result, color); result = applyLuminanace(result, color); diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java index 238bb1a116..ceda9280c4 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java @@ -7,17 +7,12 @@ import java.awt.geom.Rectangle2D; import org.apache.poi.sl.usermodel.*; -public class DrawShapeGroup> implements Drawable { +public class DrawShapeGroup> extends DrawShape implements Drawable { - protected final T shape; - public DrawShapeGroup(T shape) { - this.shape = shape; + super(shape); } - public void applyTransform(Graphics2D context) { - } - public void draw(Graphics2D graphics) { // the coordinate system of this group of shape @@ -54,7 +49,4 @@ public class DrawShapeGroup> implements Dr graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0); } - - public void drawContent(Graphics2D context) { - } } diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java index d3901b39b3..d0026f31dc 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSheet.java @@ -6,7 +6,7 @@ import java.awt.geom.AffineTransform; import org.apache.poi.sl.usermodel.*; -public class DrawSheet> implements Drawable { +public class DrawSheet> implements Drawable { protected final T sheet; @@ -14,14 +14,9 @@ public class DrawSheet> implements Drawable { this.sheet = sheet; } - public void applyTransform(Graphics2D context) { - // TODO Auto-generated method stub - - } - public void draw(Graphics2D graphics) { DrawFactory drawFact = DrawFactory.getInstance(graphics); - MasterSheet master = sheet.getMasterSheet(); + MasterSheet master = sheet.getMasterSheet(); if(sheet.getFollowMasterGraphics() && master != null) { Drawable drawer = drawFact.getDrawable(master); @@ -53,9 +48,10 @@ public class DrawSheet> implements Drawable { } } + public void applyTransform(Graphics2D context) { + } + public void drawContent(Graphics2D context) { - // TODO Auto-generated method stub - } /** diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java index c5e5b4244c..4ff0034eba 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSimpleShape.java @@ -18,7 +18,7 @@ import org.apache.poi.sl.draw.geom.*; import org.apache.poi.sl.usermodel.*; import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize; import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint; -import org.apache.poi.sl.usermodel.StrokeStyle.LineDash; +import org.apache.poi.sl.usermodel.StrokeStyle.*; import org.apache.poi.util.Units; @@ -223,15 +223,22 @@ public class DrawSimpleShape extends DrawShape { if (lineWidth == 0.0f) lineWidth = 0.25f; // Both PowerPoint and OOo draw zero-length lines as 0.25pt LineDash lineDash = strokeStyle.getLineDash(); + if (lineDash == null) { + lineDash = LineDash.SOLID; + lineWidth = 0.0f; + } + int dashPatI[] = lineDash.pattern; float[] dashPatF = new float[dashPatI.length]; final float dash_phase = 0; for (int i=0; i extends DrawShape { int lineJoin = BasicStroke.JOIN_ROUND; - return new BasicStroke(lineWidth, lineCap, lineJoin, Math.max(1, lineWidth), dashPatF, dash_phase); + return new BasicStroke(lineWidth, lineCap, lineJoin, lineWidth, dashPatF, dash_phase); } protected void drawShadow( diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java index 8bc4eaf686..cada314ece 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawSlide.java @@ -5,7 +5,7 @@ import java.awt.Graphics2D; import org.apache.poi.sl.usermodel.*; -public class DrawSlide> extends DrawSheet { +public class DrawSlide> extends DrawSheet { public DrawSlide(T slide) { super(slide); diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java index c9bf1f4085..4b2c79e378 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextFragment.java @@ -4,8 +4,6 @@ import java.awt.Graphics2D; import java.awt.font.TextLayout; import java.text.*; -import org.apache.poi.xslf.usermodel.XSLFRenderingHint; - public class DrawTextFragment implements Drawable { final TextLayout layout; final AttributedString str; @@ -29,8 +27,8 @@ public class DrawTextFragment implements Drawable { double yBaseline = y + layout.getAscent(); - Integer textMode = (Integer)graphics.getRenderingHint(XSLFRenderingHint.TEXT_RENDERING_MODE); - if(textMode != null && textMode == XSLFRenderingHint.TEXT_AS_SHAPES){ + Integer textMode = (Integer)graphics.getRenderingHint(Drawable.TEXT_RENDERING_MODE); + if(textMode != null && textMode == Drawable.TEXT_AS_SHAPES){ layout.draw(graphics, (float)x, (float)yBaseline); } else { graphics.drawString(str.getIterator(), (float)x, (float)yBaseline ); @@ -38,13 +36,9 @@ public class DrawTextFragment implements Drawable { } public void applyTransform(Graphics2D graphics) { - // TODO Auto-generated method stub - } public void drawContent(Graphics2D graphics) { - // TODO Auto-generated method stub - } public TextLayout getLayout() { diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java index cda6a1a88f..f0b4ff42b3 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/DrawTextShape.java @@ -8,7 +8,7 @@ import java.util.Iterator; import org.apache.poi.sl.usermodel.*; -public class DrawTextShape> extends DrawSimpleShape { +public class DrawTextShape>> extends DrawSimpleShape { public DrawTextShape(T shape) { super(shape); @@ -26,7 +26,7 @@ public class DrawTextShape> extends // Transform of text in flipped shapes is special. // At this point the flip and rotation transform is already applied - // (see XSLFShape#applyTransform ), but we need to restore it to avoid painting "upside down". + // (see DrawShape#applyTransform ), but we need to restore it to avoid painting "upside down". // See Bugzilla 54210. if(shape.getFlipVertical()){ @@ -84,12 +84,12 @@ public class DrawTextShape> extends Insets2D shapePadding = shape.getInsets(); double y0 = y; - Iterator paragraphs = shape.iterator(); + Iterator> paragraphs = shape.iterator(); boolean isFirstLine = true; while (paragraphs.hasNext()){ - TextParagraph p = paragraphs.next(); - DrawTextParagraph dp = fact.getDrawable(p); + TextParagraph p = paragraphs.next(); + DrawTextParagraph dp = fact.getDrawable(p); dp.setInsets(shapePadding); dp.breakText(graphics); diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java b/src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java index d876d1512a..736dc0d668 100644 --- a/src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java +++ b/src/scratchpad/src/org/apache/poi/sl/draw/geom/PresetGeometries.java @@ -45,7 +45,7 @@ public class PresetGeometries extends LinkedHashMap { @SuppressWarnings("unused") public void init(InputStream is) throws XMLStreamException, JAXBException { - Reader xml = new InputStreamReader( is, Charset.forName("UTF-8") ); + // Reader xml = new InputStreamReader( is, Charset.forName("UTF-8") ); // StAX: @@ -58,7 +58,7 @@ public class PresetGeometries extends LinkedHashMap { long cntElem = 0; XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - XMLEventReader staxReader = staxFactory.createXMLEventReader(xml); + XMLEventReader staxReader = staxFactory.createXMLEventReader(is); XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter); // ignore StartElement: XMLEvent evDoc = staxFiltRd.nextEvent(); diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java index 21c3a507fd..1bf073dfbb 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/AutoShape.java @@ -17,5 +17,5 @@ package org.apache.poi.sl.usermodel; -public interface AutoShape extends TextShape { +public interface AutoShape> extends TextShape { } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java index 09d61989df..e0843a11a1 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/FreeformShape.java @@ -17,6 +17,6 @@ package org.apache.poi.sl.usermodel; -public interface FreeformShape extends AutoShape { +public interface FreeformShape> extends AutoShape { } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java index 8ba80156bd..727217d3fa 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/MasterSheet.java @@ -17,6 +17,6 @@ package org.apache.poi.sl.usermodel; -public interface MasterSheet extends Sheet { +public interface MasterSheet extends Sheet { } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java index c16774c298..08f023cd9f 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/Notes.java @@ -17,6 +17,8 @@ package org.apache.poi.sl.usermodel; -public interface Notes extends Sheet { - public TextRun getTextRun(); +import java.util.List; + +public interface Notes extends Sheet { + List> getTextParagraphs(); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java index 9dcd495e40..2551201692 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/PaintStyle.java @@ -17,8 +17,11 @@ package org.apache.poi.sl.usermodel; +import java.awt.Color; import java.io.InputStream; +import org.apache.poi.sl.draw.DrawPaint; + public interface PaintStyle { @@ -55,4 +58,6 @@ public interface PaintStyle { */ int getAlpha(); } + + SolidPaint TRANSPARENT_PAINT = DrawPaint.createSolidPaint(new Color(0xFF, 0xFF, 0xFF, 0)); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java index 6ad149b489..4de645d41f 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/Shape.java @@ -19,14 +19,11 @@ package org.apache.poi.sl.usermodel; public interface Shape { - ShapeContainer getParent(); + ShapeContainer getParent(); /** * * @return the sheet this shape belongs to */ - Sheet getSheet(); - - - + Sheet getSheet(); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java index 8de1dbcb06..7bd940c36c 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java @@ -19,6 +19,6 @@ package org.apache.poi.sl.usermodel; import java.awt.geom.Rectangle2D; -public interface ShapeGroup extends ShapeContainer, PlaceableShape { +public interface ShapeGroup extends Shape, ShapeContainer, PlaceableShape { Rectangle2D getInteriorAnchor(); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java index 64b53a3014..6f4ba0ac67 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java @@ -21,8 +21,8 @@ package org.apache.poi.sl.usermodel; /** * Common parent of Slides, Notes and Masters */ -public interface Sheet extends ShapeContainer { - SlideShow getSlideShow(); +public interface Sheet extends ShapeContainer { + SS getSlideShow(); /** * @return whether shapes on the master sheet should be shown. By default master graphics is turned off. @@ -31,7 +31,7 @@ public interface Sheet extends ShapeContainer { */ boolean getFollowMasterGraphics(); - MasterSheet getMasterSheet(); + MasterSheet getMasterSheet(); Background getBackground(); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java index 243d9a8174..b2027c182c 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/Slide.java @@ -17,9 +17,9 @@ package org.apache.poi.sl.usermodel; -public interface Slide extends Sheet { - public Notes getNotes(); - public void setNotes(Notes notes); +public interface Slide extends Sheet { + public Notes getNotes(); + public void setNotes(Notes notes); public boolean getFollowMasterBackground(); public void setFollowMasterBackground(boolean follow); diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java index 4505ca5843..e3007f6c17 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/SlideShow.java @@ -21,11 +21,11 @@ import java.awt.Dimension; import java.io.IOException; public interface SlideShow { - Slide createSlide() throws IOException; - MasterSheet createMasterSheet() throws IOException; + Slide createSlide() throws IOException; + MasterSheet createMasterSheet() throws IOException; - Slide[] getSlides(); - MasterSheet[] getMasterSheet(); + Slide[] getSlides(); + MasterSheet[] getMasterSheet(); Resources getResources(); diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java index c02e1a33f9..a55317740a 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/StrokeStyle.java @@ -33,27 +33,75 @@ public interface StrokeStyle { * with actual line width */ enum LineDash { - SOLID(1), - DOT(1,1), - DASH(3,4), - LG_DASH(8,3), - DASH_DOT(4,3,1,3), - LG_DASH_DOT(8,3,1,3), - LG_DASH_DOT_DOT(8,3,1,3,1,3), - SYS_DASH(2,2), - SYS_DOT(1,1), - SYS_DASH_DOT, - SYS_DASH_DOT_DOT; - - public int pattern[]; - - LineDash(int... pattern) { + /** Solid (continuous) pen - native 1 */ + SOLID(1, 1), + /** square dot style - native 6 */ + DOT(6, 1,1), + /** dash style - native 7 */ + DASH(7, 3,4), + /** dash short dash - native 9*/ + DASH_DOT(9, 4,3,1,3), + /** long dash style - native 8 */ + LG_DASH(8, 8,3), + /** long dash short dash - native 10 */ + LG_DASH_DOT(10, 8,3,1,3), + /** long dash short dash short dash - native 11 */ + LG_DASH_DOT_DOT(11, 8,3,1,3,1,3), + /** PS_DASH system dash style - native 2 */ + SYS_DASH(2, 2,2), + /** PS_DOT system dash style - native 3 */ + SYS_DOT(3, 1,1), + /** PS_DASHDOT system dash style - native 4 */ + SYS_DASH_DOT(4, 2,2,1,1), + /** PS_DASHDOTDOT system dash style / native 5 */ + SYS_DASH_DOT_DOT(5, 2,2,1,1,1,1); + + public final int pattern[]; + public final int nativeId; + + LineDash(int nativeId, int... pattern) { + this.nativeId = nativeId; this.pattern = (pattern == null || pattern.length == 0) ? new int[]{1} : pattern; } + + public static LineDash fromNativeId(int nativeId) { + for (LineDash ld : values()) { + if (ld.nativeId == nativeId) return ld; + } + return null; + } + } + + enum LineCompound { + /** Single line (of width lineWidth) - native 0 / ooxml default */ + SINGLE(0), + /** Double lines of equal width - native 1 / ooxml "dbl" */ + DOUBLE(1), + /** Double lines, one thick, one thin - native 2 / ooxml "thickThin" */ + THICK_THIN(2), + /** Double lines, reverse order - native 3 / ooxml "thinThick" */ + THIN_THICK(3), + /** Three lines, thin, thick, thin - native 4 / ooxml "tri" */ + TRIPLE(4); + + public final int nativeId; + + LineCompound(int nativeId) { + this.nativeId = nativeId; + } + + public static LineCompound fromNativeId(int nativeId) { + for (LineCompound lc : values()) { + if (lc.nativeId == nativeId) return lc; + } + return null; + } } - + + PaintStyle getPaint(); LineCap getLineCap(); LineDash getLineDash(); + LineCompound getLineCompound(); double getLineWidth(); } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java index 9ac61d526a..3fa3bbe20d 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/TextBox.java @@ -17,5 +17,5 @@ package org.apache.poi.sl.usermodel; -public interface TextBox extends AutoShape { +public interface TextBox> extends AutoShape { } diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java index f9b1833610..a6a53fe1bd 100644 --- a/src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java +++ b/src/scratchpad/src/org/apache/poi/sl/usermodel/TextShape.java @@ -19,7 +19,7 @@ package org.apache.poi.sl.usermodel; -public interface TextShape> extends SimpleShape, Iterable { +public interface TextShape> extends SimpleShape, Iterable { /** * Vertical Text Types */ diff --git a/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java b/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java index b3f91236ec..134f3e8ac0 100644 --- a/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java +++ b/src/scratchpad/testcases/org/apache/poi/TestPOIDocumentScratchpad.java @@ -22,9 +22,10 @@ package org.apache.poi; import junit.framework.TestCase; + import java.io.*; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hwpf.HWPFTestDataSamples; import org.apache.poi.poifs.filesystem.*; @@ -47,7 +48,7 @@ public final class TestPOIDocumentScratchpad extends TestCase { * a Word Document for our testing */ public void setUp() throws Exception { - doc = new HSLFSlideShow(POIDataSamples.getSlideShowInstance().openResourceAsStream("basic_test_ppt_file.ppt")); + doc = new HSLFSlideShowImpl(POIDataSamples.getSlideShowInstance().openResourceAsStream("basic_test_ppt_file.ppt")); doc2 = HWPFTestDataSamples.openSampleFile("test2.doc"); } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java b/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java index 6740708792..6207a4597d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/HSLFTestDataSamples.java @@ -24,7 +24,8 @@ import java.io.IOException; import java.io.InputStream; import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; public class HSLFTestDataSamples { @@ -45,12 +46,12 @@ public class HSLFTestDataSamples { * from a ByteArrayInputStream.

    * Useful for verifying that the serialisation round trip */ - public static HSLFSlideShow writeOutAndReadBack(HSLFSlideShow original) { + public static HSLFSlideShowImpl writeOutAndReadBack(HSLFSlideShowImpl original) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); original.write(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - return new HSLFSlideShow(bais); + return new HSLFSlideShowImpl(bais); } catch (IOException e) { throw new RuntimeException(e); } @@ -61,12 +62,12 @@ public class HSLFTestDataSamples { * from a ByteArrayInputStream.

    * Useful for verifying that the serialisation round trip */ - public static SlideShow writeOutAndReadBack(SlideShow original) { + public static HSLFSlideShow writeOutAndReadBack(HSLFSlideShow original) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); original.write(baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); - return new SlideShow(bais); + return new HSLFSlideShow(bais); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java index da07810b86..3de6032ae5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestEncryptedFile.java @@ -21,6 +21,7 @@ package org.apache.poi.hslf; import junit.framework.TestCase; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.POIDataSamples; /** @@ -32,28 +33,28 @@ public final class TestEncryptedFile extends TestCase { private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); public void testLoadNonEncrypted() throws Exception { - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); assertNotNull(hss); } public void testLoadEncrypted() throws Exception { try { - new HSLFSlideShow(slTests.openResourceAsStream("Password_Protected-hello.ppt")); + new HSLFSlideShowImpl(slTests.openResourceAsStream("Password_Protected-hello.ppt")); fail(); } catch(EncryptedPowerPointFileException e) { // Good } try { - new HSLFSlideShow(slTests.openResourceAsStream("Password_Protected-np-hello.ppt")); + new HSLFSlideShowImpl(slTests.openResourceAsStream("Password_Protected-np-hello.ppt")); fail(); } catch(EncryptedPowerPointFileException e) { // Good } try { - new HSLFSlideShow(slTests.openResourceAsStream("Password_Protected-56-hello.ppt")); + new HSLFSlideShowImpl(slTests.openResourceAsStream("Password_Protected-56-hello.ppt")); fail(); } catch(EncryptedPowerPointFileException e) { // Good diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java index 1398e747e1..ae64b3614d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java @@ -25,7 +25,8 @@ import java.io.FileNotFoundException; import junit.framework.TestCase; import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -37,9 +38,9 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; */ public final class TestReWrite extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow hssA; - private HSLFSlideShow hssB; - private HSLFSlideShow hssC; + private HSLFSlideShowImpl hssA; + private HSLFSlideShowImpl hssB; + private HSLFSlideShowImpl hssC; // POIFS primed on the test data private POIFSFileSystem pfsA; private POIFSFileSystem pfsB; @@ -50,20 +51,20 @@ public final class TestReWrite extends TestCase { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); pfsA = new POIFSFileSystem(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - hssA = new HSLFSlideShow(pfsA); + hssA = new HSLFSlideShowImpl(pfsA); pfsB = new POIFSFileSystem(slTests.openResourceAsStream("ParagraphStylesShorterThanCharStyles.ppt")); - hssB = new HSLFSlideShow(pfsB); + hssB = new HSLFSlideShowImpl(pfsB); pfsC = new POIFSFileSystem(slTests.openResourceAsStream("WithMacros.ppt")); - hssC = new HSLFSlideShow(pfsC); + hssC = new HSLFSlideShowImpl(pfsC); } public void testWritesOutTheSame() throws Exception { assertWritesOutTheSame(hssA, pfsA); assertWritesOutTheSame(hssB, pfsB); } - public void assertWritesOutTheSame(HSLFSlideShow hss, POIFSFileSystem pfs) throws Exception { + public void assertWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception { // Write out to a byte array ByteArrayOutputStream baos = new ByteArrayOutputStream(); hss.write(baos); @@ -129,9 +130,9 @@ public final class TestReWrite extends TestCase { // We need to identify and fix that first //assertSlideShowWritesOutTheSame(hssB, pfsB); } - public void assertSlideShowWritesOutTheSame(HSLFSlideShow hss, POIFSFileSystem pfs) throws Exception { + public void assertSlideShowWritesOutTheSame(HSLFSlideShowImpl hss, POIFSFileSystem pfs) throws Exception { // Create a slideshow covering it - SlideShow ss = new SlideShow(hss); + HSLFSlideShow ss = new HSLFSlideShow(hss); ss.getSlides(); ss.getNotes(); @@ -163,7 +164,7 @@ public final class TestReWrite extends TestCase { } public void test48593() throws Exception { - SlideShow slideShow = new SlideShow(); + HSLFSlideShow slideShow = new HSLFSlideShow(); slideShow.createSlide(); slideShow = HSLFTestDataSamples.writeOutAndReadBack(slideShow); slideShow.createSlide(); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWriteSanity.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWriteSanity.java index ae76116a41..31a80ae306 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWriteSanity.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWriteSanity.java @@ -19,8 +19,11 @@ package org.apache.poi.hslf; import junit.framework.TestCase; + import java.io.*; import java.util.*; + +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; import org.apache.poi.poifs.filesystem.*; import org.apache.poi.POIDataSamples; @@ -33,14 +36,14 @@ import org.apache.poi.POIDataSamples; */ public final class TestReWriteSanity extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow ss; + private HSLFSlideShowImpl ss; // POIFS primed on the test data private POIFSFileSystem pfs; public TestReWriteSanity() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); pfs = new POIFSFileSystem(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(pfs); + ss = new HSLFSlideShowImpl(pfs); } public void testUserEditAtomsRight() throws Exception { @@ -52,7 +55,7 @@ public final class TestReWriteSanity extends TestCase { ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); // Create a new one from that - HSLFSlideShow wss = new HSLFSlideShow(bais); + HSLFSlideShowImpl wss = new HSLFSlideShowImpl(bais); // Find the location of the PersistPtrIncrementalBlocks and // UserEditAtoms diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestRecordCounts.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestRecordCounts.java index 5d509b6203..732f609381 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestRecordCounts.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestRecordCounts.java @@ -19,6 +19,8 @@ package org.apache.poi.hslf; import junit.framework.TestCase; + +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; import org.apache.poi.POIDataSamples; @@ -30,11 +32,11 @@ import org.apache.poi.POIDataSamples; */ public final class TestRecordCounts extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow ss; + private HSLFSlideShowImpl ss; public TestRecordCounts() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - ss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); } public void testSheetsCount() { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java b/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java index 7fc234f8ef..a00d75d03e 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/extractor/TestExtractor.java @@ -23,9 +23,9 @@ import java.util.List; import org.apache.poi.POIDataSamples; import org.apache.poi.POITestCase; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.model.OLEShape; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.poifs.filesystem.DirectoryNode; @@ -140,7 +140,7 @@ public final class TestExtractor extends POITestCase { POIFSFileSystem fs = new POIFSFileSystem( POIDataSamples.getSpreadSheetInstance().openResourceAsStream("excel_with_embeded.xls") ); - HSLFSlideShow ss; + HSLFSlideShowImpl ss; DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B6"); @@ -151,14 +151,14 @@ public final class TestExtractor extends POITestCase { assertNotNull(dirB.getEntry("PowerPoint Document")); // Check the first file - ss = new HSLFSlideShow(dirA); + ss = new HSLFSlideShowImpl(dirA); ppe = new PowerPointExtractor(ss); assertEquals("Sample PowerPoint file\nThis is the 1st file\nNot much too it\n", ppe.getText(true, false) ); // And the second - ss = new HSLFSlideShow(dirB); + ss = new HSLFSlideShowImpl(dirB); ppe = new PowerPointExtractor(ss); assertEquals("Sample PowerPoint file\nThis is the 2nd file\nNot much too it either\n", ppe.getText(true, false) @@ -186,7 +186,7 @@ public final class TestExtractor extends POITestCase { num_doc++; } else if ("Presentation".equals(name)) { num_ppt++; - SlideShow ppt = new SlideShow(data); + HSLFSlideShow ppt = new HSLFSlideShow(data); } } assertEquals("Expected 2 embedded Word Documents", 2, num_doc); @@ -241,8 +241,8 @@ public final class TestExtractor extends POITestCase { String text; // With a header on the notes - HSLFSlideShow hslf = new HSLFSlideShow(slTests.openResourceAsStream("45537_Header.ppt")); - SlideShow ss = new SlideShow(hslf); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("45537_Header.ppt")); + HSLFSlideShow ss = new HSLFSlideShow(hslf); assertNotNull(ss.getNotesHeadersFooters()); assertEquals("testdoc test phrase", ss.getNotesHeadersFooters().getHeaderText()); @@ -259,8 +259,8 @@ public final class TestExtractor extends POITestCase { // And with a footer, also on notes - hslf = new HSLFSlideShow(slTests.openResourceAsStream("45537_Footer.ppt")); - ss = new SlideShow(hslf); + hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("45537_Footer.ppt")); + ss = new HSLFSlideShow(hslf); assertNotNull(ss.getNotesHeadersFooters()); assertEquals("testdoc test phrase", ss.getNotesHeadersFooters().getFooterText()); @@ -281,7 +281,7 @@ public final class TestExtractor extends POITestCase { String masterTitleText = "This is the Master Title"; String masterRandomText = "This text comes from the Master Slide"; String masterFooterText = "Footer from the master slide"; - HSLFSlideShow hslf = new HSLFSlideShow(slTests.openResourceAsStream("WithMaster.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithMaster.ppt")); ppe = new PowerPointExtractor(hslf); @@ -309,7 +309,7 @@ public final class TestExtractor extends POITestCase { // Now with another file only containing master text // Will always show up String masterText = "Footer from the master slide"; - HSLFSlideShow hslf = new HSLFSlideShow(slTests.openResourceAsStream("WithMaster.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithMaster.ppt")); ppe = new PowerPointExtractor(hslf); @@ -322,7 +322,7 @@ public final class TestExtractor extends POITestCase { * Bug #54880 Chinese text not extracted properly */ public void testChineseText() throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(slTests.openResourceAsStream("54880_chinese.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("54880_chinese.ppt")); ppe = new PowerPointExtractor(hslf); String text = ppe.getText(); @@ -360,7 +360,7 @@ public final class TestExtractor extends POITestCase { // Open via a HWPFDocument for(DirectoryNode dir : files) { - HSLFSlideShow slideshow = new HSLFSlideShow(dir); + HSLFSlideShowImpl slideshow = new HSLFSlideShowImpl(dir); PowerPointExtractor extractor = new PowerPointExtractor(slideshow); assertEquals(expectText, extractor.getText()); } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java index 8838561501..0d1cfd9e09 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java @@ -32,9 +32,8 @@ import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperties; import org.apache.poi.ddf.EscherRecord; import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.record.Document; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.sl.usermodel.ShapeType; import org.junit.Test; @@ -52,16 +51,16 @@ public final class TestBackground { */ @Test public void defaults() { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - assertEquals(Fill.FILL_SOLID, ppt.getSlidesMasters()[0].getBackground().getFill().getFillType()); + assertEquals(HSLFFill.FILL_SOLID, ppt.getSlidesMasters()[0].getBackground().getFill().getFillType()); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); assertTrue(slide.getFollowMasterBackground()); - assertEquals(Fill.FILL_SOLID, slide.getBackground().getFill().getFillType()); + assertEquals(HSLFFill.FILL_SOLID, slide.getBackground().getFill().getFillType()); - HSLFShape shape = new AutoShape(ShapeType.RECT); - assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + HSLFShape shape = new HSLFAutoShape(ShapeType.RECT); + assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType()); } /** @@ -69,31 +68,31 @@ public final class TestBackground { */ @Test public void readBackground() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("backgrounds.ppt")); - Fill fill; + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("backgrounds.ppt")); + HSLFFill fill; HSLFShape shape; - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); fill = slide[0].getBackground().getFill(); - assertEquals(Fill.FILL_PICTURE, fill.getFillType()); + assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType()); shape = slide[0].getShapes()[0]; - assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType()); fill = slide[1].getBackground().getFill(); - assertEquals(Fill.FILL_PATTERN, fill.getFillType()); + assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType()); shape = slide[1].getShapes()[0]; - assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType()); fill = slide[2].getBackground().getFill(); - assertEquals(Fill.FILL_TEXTURE, fill.getFillType()); + assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType()); shape = slide[2].getShapes()[0]; - assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType()); fill = slide[3].getBackground().getFill(); - assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType()); + assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType()); shape = slide[3].getShapes()[0]; - assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType()); } /** @@ -101,9 +100,9 @@ public final class TestBackground { */ @Test public void backgroundPicture() throws Exception { - SlideShow ppt = new SlideShow(); - Slide slide; - Fill fill; + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide; + HSLFFill fill; HSLFShape shape; int idx; @@ -111,45 +110,45 @@ public final class TestBackground { slide = ppt.createSlide(); slide.setFollowMasterBackground(false); fill = slide.getBackground().getFill(); - idx = ppt.addPicture(_slTests.readFile("tomcat.png"), Picture.PNG); - fill.setFillType(Fill.FILL_PICTURE); + idx = ppt.addPicture(_slTests.readFile("tomcat.png"), HSLFPictureShape.PNG); + fill.setFillType(HSLFFill.FILL_PICTURE); fill.setPictureData(idx); - shape = new AutoShape(ShapeType.RECT); + shape = new HSLFAutoShape(ShapeType.RECT); shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); fill = shape.getFill(); - fill.setFillType(Fill.FILL_SOLID); + fill.setFillType(HSLFFill.FILL_SOLID); slide.addShape(shape); //slide 2 slide = ppt.createSlide(); slide.setFollowMasterBackground(false); fill = slide.getBackground().getFill(); - idx = ppt.addPicture(_slTests.readFile("tomcat.png"), Picture.PNG); - fill.setFillType(Fill.FILL_PATTERN); + idx = ppt.addPicture(_slTests.readFile("tomcat.png"), HSLFPictureShape.PNG); + fill.setFillType(HSLFFill.FILL_PATTERN); fill.setPictureData(idx); fill.setBackgroundColor(Color.green); fill.setForegroundColor(Color.red); - shape = new AutoShape(ShapeType.RECT); + shape = new HSLFAutoShape(ShapeType.RECT); shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); fill = shape.getFill(); - fill.setFillType(Fill.FILL_BACKGROUND); + fill.setFillType(HSLFFill.FILL_BACKGROUND); slide.addShape(shape); //slide 3 slide = ppt.createSlide(); slide.setFollowMasterBackground(false); fill = slide.getBackground().getFill(); - idx = ppt.addPicture(_slTests.readFile("tomcat.png"), Picture.PNG); - fill.setFillType(Fill.FILL_TEXTURE); + idx = ppt.addPicture(_slTests.readFile("tomcat.png"), HSLFPictureShape.PNG); + fill.setFillType(HSLFFill.FILL_TEXTURE); fill.setPictureData(idx); - shape = new AutoShape(ShapeType.RECT); + shape = new HSLFAutoShape(ShapeType.RECT); shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); fill = shape.getFill(); - fill.setFillType(Fill.FILL_PICTURE); - idx = ppt.addPicture(_slTests.readFile("clock.jpg"), Picture.JPEG); + fill.setFillType(HSLFFill.FILL_PICTURE); + idx = ppt.addPicture(_slTests.readFile("clock.jpg"), HSLFPictureShape.JPEG); fill.setPictureData(idx); slide.addShape(shape); @@ -157,14 +156,14 @@ public final class TestBackground { slide = ppt.createSlide(); slide.setFollowMasterBackground(false); fill = slide.getBackground().getFill(); - fill.setFillType(Fill.FILL_SHADE_CENTER); + fill.setFillType(HSLFFill.FILL_SHADE_CENTER); fill.setBackgroundColor(Color.white); fill.setForegroundColor(Color.darkGray); - shape = new AutoShape(ShapeType.RECT); + shape = new HSLFAutoShape(ShapeType.RECT); shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200)); fill = shape.getFill(); - fill.setFillType(Fill.FILL_SHADE); + fill.setFillType(HSLFFill.FILL_SHADE); fill.setBackgroundColor(Color.red); fill.setForegroundColor(Color.green); slide.addShape(shape); @@ -174,42 +173,42 @@ public final class TestBackground { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); - Slide[] slides = ppt.getSlides(); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); + HSLFSlide[] slides = ppt.getSlides(); fill = slides[0].getBackground().getFill(); - assertEquals(Fill.FILL_PICTURE, fill.getFillType()); + assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType()); assertEquals(3, getFillPictureRefCount(slides[0].getBackground(), fill)); shape = slides[0].getShapes()[0]; - assertEquals(Fill.FILL_SOLID, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType()); fill = slides[1].getBackground().getFill(); - assertEquals(Fill.FILL_PATTERN, fill.getFillType()); + assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType()); shape = slides[1].getShapes()[0]; - assertEquals(Fill.FILL_BACKGROUND, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType()); fill = slides[2].getBackground().getFill(); - assertEquals(Fill.FILL_TEXTURE, fill.getFillType()); + assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType()); assertEquals(3, getFillPictureRefCount(slides[2].getBackground(), fill)); shape = slides[2].getShapes()[0]; - assertEquals(Fill.FILL_PICTURE, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType()); assertEquals(1, getFillPictureRefCount(shape, fill)); fill = slides[3].getBackground().getFill(); - assertEquals(Fill.FILL_SHADE_CENTER, fill.getFillType()); + assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType()); shape = slides[3].getShapes()[0]; - assertEquals(Fill.FILL_SHADE, shape.getFill().getFillType()); + assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType()); } - private int getFillPictureRefCount(HSLFShape shape, Fill fill) { + private int getFillPictureRefCount(HSLFShape shape, HSLFFill fill) { EscherOptRecord opt = shape.getEscherOptRecord(); EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE); if(p != null) { int idx = p.getPropertyValue(); - Sheet sheet = shape.getSheet(); - SlideShow ppt = sheet.getSlideShow(); + HSLFSheet sheet = shape.getSheet(); + HSLFSlideShow ppt = sheet.getSlideShow(); Document doc = ppt.getDocumentRecord(); EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer(); EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java index 6ff4870386..6d1365efbe 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java @@ -43,7 +43,7 @@ public final class TestFreeform extends TestCase { path1.lineTo(100, 200); path1.closePath(); - Freeform p = new Freeform(); + HSLFFreeformShape p = new HSLFFreeformShape(); p.setPath(path1); java.awt.Shape path2 = p.getOutline(); @@ -54,7 +54,7 @@ public final class TestFreeform extends TestCase { GeneralPath path1 = new GeneralPath(new Line2D.Double(100, 100, 200, 100)); - Freeform p = new Freeform(); + HSLFFreeformShape p = new HSLFFreeformShape(); p.setPath(path1); java.awt.Shape path2 = p.getOutline(); @@ -65,7 +65,7 @@ public final class TestFreeform extends TestCase { GeneralPath path1 = new GeneralPath(new Rectangle2D.Double(100, 100, 200, 50)); - Freeform p = new Freeform(); + HSLFFreeformShape p = new HSLFFreeformShape(); p.setPath(path1); java.awt.Shape path2 = p.getOutline(); @@ -78,7 +78,7 @@ public final class TestFreeform extends TestCase { */ public void test54188() { - Freeform p = new Freeform(); + HSLFFreeformShape p = new HSLFFreeformShape(); GeneralPath path = (GeneralPath)p.getOutline(); GeneralPath emptyPath = new GeneralPath(); assertEquals(emptyPath.getBounds2D(), path.getBounds2D()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java index 1e86b8c3af..8239a359d5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHeadersFooters.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.model; import java.io.*; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; import junit.framework.TestCase; @@ -33,7 +33,7 @@ public final class TestHeadersFooters extends TestCase public void testRead() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("headers_footers.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("headers_footers.ppt")); HeadersFooters slideHdd = ppt.getSlideHeadersFooters(); assertTrue(slideHdd.isFooterVisible()); @@ -53,7 +53,7 @@ public final class TestHeadersFooters extends TestCase assertTrue(notesHdd.isUserDateVisible()); assertNull(notesHdd.getDateTimeText()); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); //the first slide uses presentation-scope headers / footers HeadersFooters hd1 = slide[0].getHeadersFooters(); assertEquals(slideHdd.isFooterVisible(), hd1.isFooterVisible()); @@ -77,7 +77,7 @@ public final class TestHeadersFooters extends TestCase */ public void testReadNoHeadersFooters() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); HeadersFooters slideHdd = ppt.getSlideHeadersFooters(); assertFalse(slideHdd.isFooterVisible()); @@ -97,7 +97,7 @@ public final class TestHeadersFooters extends TestCase assertFalse(notesHdd.isUserDateVisible()); assertNull(notesHdd.getDateTimeText()); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for(int i=0 ; i < slide.length; i++){ HeadersFooters hd1 = slide[i].getHeadersFooters(); assertFalse(hd1.isFooterVisible()); @@ -114,7 +114,7 @@ public final class TestHeadersFooters extends TestCase */ public void testRead2007() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("headers_footers_2007.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("headers_footers_2007.ppt")); HeadersFooters slideHdd = ppt.getSlideHeadersFooters(); assertTrue(slideHdd.isFooterVisible()); @@ -137,7 +137,7 @@ public final class TestHeadersFooters extends TestCase //assertEquals("08/12/08", notesHdd.getDateTimeText()); //per-slide headers / footers - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); //the first slide uses presentation-scope headers / footers HeadersFooters hd1 = slide[0].getHeadersFooters(); assertTrue(hd1.isFooterVisible()); @@ -174,7 +174,7 @@ public final class TestHeadersFooters extends TestCase public void testCreateSlideFooters() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); HeadersFooters hdd = ppt.getSlideHeadersFooters(); hdd.setFootersText("My slide footer"); hdd.setSlideNumberVisible(true); @@ -183,7 +183,7 @@ public final class TestHeadersFooters extends TestCase ppt.write(out); byte[] b = out.toByteArray(); - SlideShow ppt2 = new SlideShow(new ByteArrayInputStream(b)); + HSLFSlideShow ppt2 = new HSLFSlideShow(new ByteArrayInputStream(b)); HeadersFooters hdd2 = ppt2.getSlideHeadersFooters(); assertTrue(hdd2.isSlideNumberVisible()); assertTrue(hdd2.isFooterVisible()); @@ -192,7 +192,7 @@ public final class TestHeadersFooters extends TestCase public void testCreateNotesFooters() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); HeadersFooters hdd = ppt.getNotesHeadersFooters(); hdd.setFootersText("My notes footer"); hdd.setHeaderText("My notes header"); @@ -202,7 +202,7 @@ public final class TestHeadersFooters extends TestCase ppt.write(out); byte[] b = out.toByteArray(); - SlideShow ppt2 = new SlideShow(new ByteArrayInputStream(b)); + HSLFSlideShow ppt2 = new HSLFSlideShow(new ByteArrayInputStream(b)); HeadersFooters hdd2 = ppt2.getNotesHeadersFooters(); assertTrue(hdd2.isSlideNumberVisible()); assertTrue(hdd2.isFooterVisible()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java index 6f9f9eb8b4..83e6ca6582 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestHyperlink.java @@ -19,7 +19,7 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -31,10 +31,10 @@ public final class TestHyperlink extends TestCase { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); public void testTextRunHyperlinks() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("WithLinks.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("WithLinks.ppt")); - TextRun[] run; - Slide slide; + HSLFTextParagraph[] run; + HSLFSlide slide; slide = ppt.getSlides()[0]; run = slide.getTextRuns(); for (int i = 0; i < run.length; i++) { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java index 9de8cad43e..11a64f6379 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java @@ -23,7 +23,7 @@ import junit.framework.TestCase; import org.apache.poi.hslf.blip.BitmapPainter; import org.apache.poi.hslf.blip.ImagePainter; -import org.apache.poi.hslf.usermodel.PictureData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; /** * Test Picture shape. @@ -36,19 +36,19 @@ public final class TestImagePainter extends TestCase { public CustomImagePainter() { // no fields to initialise } - public void paint(Graphics2D graphics, PictureData pict, Picture parent){ + public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent){ //do noting } } public void testImagePainter() { - ImagePainter pntr = PictureData.getImagePainter(Picture.PNG); - assertTrue(PictureData.getImagePainter(Picture.PNG) instanceof BitmapPainter); - assertTrue(PictureData.getImagePainter(Picture.JPEG) instanceof BitmapPainter); - assertTrue(PictureData.getImagePainter(Picture.DIB) instanceof BitmapPainter); + ImagePainter pntr = HSLFPictureData.getImagePainter(HSLFPictureShape.PNG); + assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.PNG) instanceof BitmapPainter); + assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.JPEG) instanceof BitmapPainter); + assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.DIB) instanceof BitmapPainter); - PictureData.setImagePainter(Picture.WMF, new CustomImagePainter()); - assertTrue(PictureData.getImagePainter(Picture.WMF) instanceof CustomImagePainter); + HSLFPictureData.setImagePainter(HSLFPictureShape.WMF, new CustomImagePainter()); + assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.WMF) instanceof CustomImagePainter); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java index 735fa30466..413ff8ebe8 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestLine.java @@ -21,7 +21,7 @@ import java.awt.Color; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; /** * Test Line shape. @@ -31,9 +31,9 @@ import org.apache.poi.hslf.usermodel.SlideShow; public final class TestLine extends TestCase { public void testCreateLines() { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); slide.addTitle().setText("Lines tester"); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java index 9460642bb4..1b5bbd3298 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestMovieShape.java @@ -23,7 +23,7 @@ import java.io.ByteArrayOutputStream; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -36,13 +36,13 @@ public final class TestMovieShape extends TestCase { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); public void testCreate() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); String path = "/test-movie.mpg"; int movieIdx = ppt.addMovie(path, MovieShape.MOVIE_MPEG); - int thumbnailIdx = ppt.addPicture(_slTests.readFile("tomcat.png"), Picture.PNG); + int thumbnailIdx = ppt.addPicture(_slTests.readFile("tomcat.png"), HSLFPictureShape.PNG); MovieShape shape = new MovieShape(movieIdx, thumbnailIdx); shape.setAnchor(new Rectangle2D.Float(300,225,120,90)); @@ -56,7 +56,7 @@ public final class TestMovieShape extends TestCase { ByteArrayOutputStream out = new ByteArrayOutputStream(); ppt.write(out); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); slide = ppt.getSlides()[0]; shape = (MovieShape)slide.getShapes()[0]; assertEquals(path, shape.getPath()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java index 249c4ee964..410f48226a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestOleEmbedding.java @@ -28,10 +28,9 @@ import java.io.InputStream; import junit.framework.TestCase; import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.ObjectData; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFObjectData; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hwpf.HWPFDocument; @@ -46,31 +45,31 @@ public final class TestOleEmbedding extends TestCase { * @throws Exception if an error occurs. */ public void testOleEmbedding2003() throws Exception { - HSLFSlideShow slideShow = new HSLFSlideShow(_slTests.openResourceAsStream("ole2-embedding-2003.ppt")); + HSLFSlideShowImpl slideShow = new HSLFSlideShowImpl(_slTests.openResourceAsStream("ole2-embedding-2003.ppt")); // Placeholder EMFs for clients that don't support the OLE components. - PictureData[] pictures = slideShow.getPictures(); + HSLFPictureData[] pictures = slideShow.getPictures(); assertEquals("Should be two pictures", 2, pictures.length); //assertDigestEquals("Wrong data for picture 1", "8d1fbadf4814f321bb1ccdd056e3c788", pictures[0].getData()); //assertDigestEquals("Wrong data for picture 2", "987a698e83559cf3d38a0deeba1cc63b", pictures[1].getData()); // Actual embedded objects. - ObjectData[] objects = slideShow.getEmbeddedObjects(); + HSLFObjectData[] objects = slideShow.getEmbeddedObjects(); assertEquals("Should be two objects", 2, objects.length); //assertDigestEquals("Wrong data for objecs 1", "0d1fcc61a83de5c4894dc0c88e9a019d", objects[0].getData()); //assertDigestEquals("Wrong data for object 2", "b323604b2003a7299c77c2693b641495", objects[1].getData()); } public void testOLEShape() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("ole2-embedding-2003.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("ole2-embedding-2003.ppt")); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; HSLFShape[] sh = slide.getShapes(); int cnt = 0; for (int i = 0; i < sh.length; i++) { if(sh[i] instanceof OLEShape){ cnt++; OLEShape ole = (OLEShape)sh[i]; - ObjectData data = ole.getObjectData(); + HSLFObjectData data = ole.getObjectData(); if("Worksheet".equals(ole.getInstanceName())){ //Voila! we created a workbook from the embedded OLE data HSSFWorkbook wb = new HSSFWorkbook(data.getData()); @@ -94,11 +93,11 @@ public final class TestOleEmbedding extends TestCase { } public void testEmbedding() throws Exception { - HSLFSlideShow _hslfSlideShow = HSLFSlideShow.create(); - SlideShow ppt = new SlideShow(_hslfSlideShow); + HSLFSlideShowImpl _hslfSlideShow = HSLFSlideShowImpl.create(); + HSLFSlideShow ppt = new HSLFSlideShow(_hslfSlideShow); File pict = POIDataSamples.getSlideShowInstance().getFile("clock.jpg"); - int pictId = ppt.addPicture(pict, Picture.JPEG); + int pictId = ppt.addPicture(pict, HSLFPictureShape.JPEG); InputStream is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("Employee.xls"); POIFSFileSystem poiData1 = new POIFSFileSystem(is); @@ -106,14 +105,14 @@ public final class TestOleEmbedding extends TestCase { int oleObjectId1 = ppt.addEmbed(poiData1); - Slide slide1 = ppt.createSlide(); + HSLFSlide slide1 = ppt.createSlide(); OLEShape oleShape1 = new OLEShape(pictId); oleShape1.setObjectID(oleObjectId1); slide1.addShape(oleShape1); oleShape1.setAnchor(new Rectangle2D.Double(100,100,100,100)); // add second slide with different order in object creation - Slide slide2 = ppt.createSlide(); + HSLFSlide slide2 = ppt.createSlide(); OLEShape oleShape2 = new OLEShape(pictId); is = POIDataSamples.getSpreadSheetInstance().openResourceAsStream("SimpleWithImages.xls"); @@ -129,7 +128,7 @@ public final class TestOleEmbedding extends TestCase { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ppt.write(bos); - ppt = new SlideShow(new ByteArrayInputStream(bos.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray())); OLEShape comp = (OLEShape)ppt.getSlides()[0].getShapes()[0]; byte compData[] = IOUtils.toByteArray(comp.getObjectData().getData()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java index aff848dfc5..fb04ccf5dd 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPFont.java @@ -18,7 +18,7 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; /** * Test adding fonts to the presenataion resources @@ -28,7 +28,7 @@ import org.apache.poi.hslf.usermodel.SlideShow; public final class TestPPFont extends TestCase{ public void testCreate() { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); assertEquals(1, ppt.getNumberOfFonts()); assertEquals("Arial", ppt.getFont(0).getFontName()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPGraphics2D.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPGraphics2D.java index b58dbadecf..b71ce01035 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPGraphics2D.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPPGraphics2D.java @@ -18,12 +18,11 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.HSLFSlideShow; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; import java.awt.*; -import java.awt.Rectangle; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; @@ -34,10 +33,10 @@ import java.io.ByteArrayInputStream; */ public final class TestPPGraphics2D extends TestCase { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - private SlideShow ppt; + private HSLFSlideShow ppt; protected void setUp() throws Exception { - ppt = new SlideShow(_slTests.openResourceAsStream("empty.ppt")); + ppt = new HSLFSlideShow(_slTests.openResourceAsStream("empty.ppt")); } public void testGraphics() throws Exception { @@ -45,7 +44,7 @@ public final class TestPPGraphics2D extends TestCase { assertEquals(0, ppt.getSlides().length); // Add a slide - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); assertEquals(1, ppt.getSlides().length); // Add some stuff into it @@ -73,7 +72,7 @@ public final class TestPPGraphics2D extends TestCase { out.close(); // And read it back in - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertEquals(1, ppt.getSlides().length); slide = ppt.getSlides()[0]; diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java index fabf63beee..08077f0e00 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestPicture.java @@ -36,9 +36,8 @@ import javax.imageio.ImageIO; import org.apache.poi.POIDataSamples; import org.apache.poi.ddf.EscherBSERecord; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.util.JvmBugs; import org.junit.Ignore; import org.junit.Test; @@ -58,16 +57,16 @@ public final class TestPicture { */ @Test public void multiplePictures() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide s = ppt.createSlide(); - Slide s2 = ppt.createSlide(); - Slide s3 = ppt.createSlide(); + HSLFSlide s = ppt.createSlide(); + HSLFSlide s2 = ppt.createSlide(); + HSLFSlide s3 = ppt.createSlide(); - int idx = ppt.addPicture(_slTests.readFile("clock.jpg"), Picture.JPEG); - Picture pict = new Picture(idx); - Picture pict2 = new Picture(idx); - Picture pict3 = new Picture(idx); + int idx = ppt.addPicture(_slTests.readFile("clock.jpg"), HSLFPictureShape.JPEG); + HSLFPictureShape pict = new HSLFPictureShape(idx); + HSLFPictureShape pict2 = new HSLFPictureShape(idx); + HSLFPictureShape pict3 = new HSLFPictureShape(idx); pict.setAnchor(new Rectangle(10,10,100,100)); s.addShape(pict); @@ -93,12 +92,12 @@ public final class TestPicture { */ @Test public void bug46122() { - SlideShow ppt = new SlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); - Picture pict = new Picture(-1); //index to non-existing picture data + HSLFPictureShape pict = new HSLFPictureShape(-1); //index to non-existing picture data pict.setSheet(slide); - PictureData data = pict.getPictureData(); + HSLFPictureData data = pict.getPictureData(); assertNull(data); BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); @@ -108,9 +107,9 @@ public final class TestPicture { @Test public void macImages() throws Exception { - HSLFSlideShow hss = new HSLFSlideShow(_slTests.openResourceAsStream("53446.ppt")); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("53446.ppt")); - PictureData[] pictures = hss.getPictures(); + HSLFPictureData[] pictures = hss.getPictures(); assertEquals(15, pictures.length); int[][] expectedSizes = { @@ -134,7 +133,7 @@ public final class TestPicture { for (int i = 0; i < pictures.length; i++) { BufferedImage image = ImageIO.read(new ByteArrayInputStream(pictures[i].getData())); - if (pictures[i].getType() != Picture.WMF && pictures[i].getType() != Picture.EMF) { + if (pictures[i].getType() != HSLFPictureShape.WMF && pictures[i].getType() != HSLFPictureShape.EMF) { assertNotNull(image); int[] dimensions = expectedSizes[i]; @@ -163,12 +162,12 @@ public final class TestPicture { // System.out.println("########################"); InputStream is = _slTests.openResourceAsStream("54541_cropped_bitmap.ppt"); - SlideShow ss = new SlideShow(is); + HSLFSlideShow ss = new HSLFSlideShow(is); is.close(); Dimension pg = ss.getPageSize(); int i=1; - for(Slide slide : ss.getSlides()) { + for(HSLFSlide slide : ss.getSlides()) { BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = img.createGraphics(); fixFonts(graphics); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSetBoldItalic.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSetBoldItalic.java index 23b798fd6f..e1703626ca 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSetBoldItalic.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSetBoldItalic.java @@ -18,9 +18,9 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.usermodel.SlideShow; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.HSLFSlideShow; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; import java.io.ByteArrayOutputStream; import java.io.ByteArrayInputStream; @@ -36,15 +36,15 @@ public final class TestSetBoldItalic extends TestCase { * and set some of the style attributes */ public void testTextBoxWrite() throws Exception { - SlideShow ppt = new SlideShow(); - Slide sl = ppt.createSlide(); - RichTextRun rt; + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide sl = ppt.createSlide(); + HSLFTextRun rt; String val = "Hello, World!"; // Create a new textbox, and give it lots of properties - TextBox txtbox = new TextBox(); - rt = txtbox.getTextRun().getRichTextRuns()[0]; + HSLFTextBox txtbox = new HSLFTextBox(); + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; txtbox.setText(val); rt.setFontSize(42); rt.setBold(true); @@ -53,7 +53,7 @@ public final class TestSetBoldItalic extends TestCase { sl.addShape(txtbox); // Check it before save - rt = txtbox.getTextRun().getRichTextRuns()[0]; + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; assertEquals(val, rt.getText()); assertEquals(42, rt.getFontSize()); assertTrue(rt.isBold()); @@ -64,11 +64,11 @@ public final class TestSetBoldItalic extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); sl = ppt.getSlides()[0]; - txtbox = (TextBox)sl.getShapes()[0]; - rt = txtbox.getTextRun().getRichTextRuns()[0]; + txtbox = (HSLFTextBox)sl.getShapes()[0]; + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; // Check after save assertEquals(val, rt.getText()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java index 700b758a1e..9456c211f8 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java @@ -38,9 +38,8 @@ import org.apache.poi.ddf.EscherDggRecord; import org.apache.poi.ddf.EscherOptRecord; import org.apache.poi.ddf.EscherProperties; import org.apache.poi.ddf.EscherSimpleProperty; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.sl.usermodel.ShapeType; import org.junit.Before; import org.junit.Test; @@ -53,17 +52,17 @@ import org.junit.Test; public final class TestShapes { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - private SlideShow ppt; - private SlideShow pptB; + private HSLFSlideShow ppt; + private HSLFSlideShow pptB; @Before public void setUp() throws Exception { InputStream is1 = null, is2 = null; try { is1 = _slTests.openResourceAsStream("empty.ppt"); - ppt = new SlideShow(is1); + ppt = new HSLFSlideShow(is1); is2 = _slTests.openResourceAsStream("empty_textbox.ppt"); - pptB = new SlideShow(is2); + pptB = new HSLFSlideShow(is2); } finally { is1.close(); is2.close(); @@ -72,7 +71,7 @@ public final class TestShapes { @Test public void graphics() throws Exception { - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); Line line = new Line(); java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60); @@ -82,7 +81,7 @@ public final class TestShapes { line.setLineColor(Color.red); slide.addShape(line); - AutoShape ellipse = new AutoShape(ShapeType.ELLIPSE); + HSLFAutoShape ellipse = new HSLFAutoShape(ShapeType.ELLIPSE); java.awt.Rectangle ellipseAnchor = new Rectangle(320, 154, 55, 111); ellipse.setAnchor(ellipseAnchor); ellipse.setLineWidth(2); @@ -97,7 +96,7 @@ public final class TestShapes { //read ppt from byte array - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertEquals(1, ppt.getSlides().length); slide = ppt.getSlides()[0]; @@ -107,7 +106,7 @@ public final class TestShapes { assertTrue(shape[0] instanceof Line); //group shape assertEquals(lineAnchor, shape[0].getAnchor()); //group shape - assertTrue(shape[1] instanceof AutoShape); //group shape + assertTrue(shape[1] instanceof HSLFAutoShape); //group shape assertEquals(ellipseAnchor, shape[1].getAnchor()); //group shape } @@ -117,17 +116,17 @@ public final class TestShapes { */ @Test public void textBoxRead() throws Exception { - ppt = new SlideShow(_slTests.openResourceAsStream("with_textbox.ppt")); - Slide sl = ppt.getSlides()[0]; + ppt = new HSLFSlideShow(_slTests.openResourceAsStream("with_textbox.ppt")); + HSLFSlide sl = ppt.getSlides()[0]; HSLFShape[] sh = sl.getShapes(); for (int i = 0; i < sh.length; i++) { - assertTrue(sh[i] instanceof TextBox); - TextBox txtbox = (TextBox)sh[i]; + assertTrue(sh[i] instanceof HSLFTextBox); + HSLFTextBox txtbox = (HSLFTextBox)sh[i]; String text = txtbox.getText(); assertNotNull(text); - assertEquals(txtbox.getTextRun().getRichTextRuns().length, 1); - RichTextRun rt = txtbox.getTextRun().getRichTextRuns()[0]; + assertEquals(txtbox.getTextParagraph().getRichTextRuns().length, 1); + HSLFTextRun rt = txtbox.getTextParagraph().getRichTextRuns()[0]; if (text.equals("Hello, World!!!")){ assertEquals(32, rt.getFontSize()); @@ -153,15 +152,15 @@ public final class TestShapes { */ @Test public void textBoxWriteBytes() throws Exception { - ppt = new SlideShow(); - Slide sl = ppt.createSlide(); - RichTextRun rt; + ppt = new HSLFSlideShow(); + HSLFSlide sl = ppt.createSlide(); + HSLFTextRun rt; String val = "Hello, World!"; // Create a new textbox, and give it lots of properties - TextBox txtbox = new TextBox(); - rt = txtbox.getTextRun().getRichTextRuns()[0]; + HSLFTextBox txtbox = new HSLFTextBox(); + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; txtbox.setText(val); rt.setFontName("Arial"); rt.setFontSize(42); @@ -172,7 +171,7 @@ public final class TestShapes { sl.addShape(txtbox); // Check it before save - rt = txtbox.getTextRun().getRichTextRuns()[0]; + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; assertEquals(val, rt.getText()); assertEquals(42, rt.getFontSize()); assertTrue(rt.isBold()); @@ -186,11 +185,11 @@ public final class TestShapes { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); sl = ppt.getSlides()[0]; - txtbox = (TextBox)sl.getShapes()[0]; - rt = txtbox.getTextRun().getRichTextRuns()[0]; + txtbox = (HSLFTextBox)sl.getShapes()[0]; + rt = txtbox.getTextParagraph().getRichTextRuns()[0]; // Check after save assertEquals(val, rt.getText()); @@ -208,8 +207,8 @@ public final class TestShapes { @Test public void emptyTextBox() { assertEquals(2, pptB.getSlides().length); - Slide s1 = pptB.getSlides()[0]; - Slide s2 = pptB.getSlides()[1]; + HSLFSlide s1 = pptB.getSlides()[0]; + HSLFSlide s2 = pptB.getSlides()[1]; // Check we can get the shapes count assertEquals(2, s1.getShapes().length); @@ -231,11 +230,11 @@ public final class TestShapes { } private void textBoxSet(String filename) throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream(filename)); - Slide[] sl = ppt.getSlides(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(filename)); + HSLFSlide[] sl = ppt.getSlides(); for (int k = 0; k < sl.length; k++) { ArrayList lst1 = new ArrayList(); - TextRun[] txt = sl[k].getTextRuns(); + HSLFTextParagraph[] txt = sl[k].getTextRuns(); for (int i = 0; i < txt.length; i++) { lst1.add(txt[i].getText()); } @@ -243,8 +242,8 @@ public final class TestShapes { ArrayList lst2 = new ArrayList(); HSLFShape[] sh = sl[k].getShapes(); for (int i = 0; i < sh.length; i++) { - if (sh[i] instanceof TextShape){ - TextShape tbox = (TextShape)sh[i]; + if (sh[i] instanceof HSLFTextShape){ + HSLFTextShape tbox = (HSLFTextShape)sh[i]; lst2.add(tbox.getText()); } } @@ -258,9 +257,9 @@ public final class TestShapes { */ @Test public void shapeGroup() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); Dimension pgsize = ppt.getPageSize(); HSLFGroupShape group = new HSLFGroupShape(); @@ -268,8 +267,8 @@ public final class TestShapes { group.setAnchor(new Rectangle(0, 0, (int)pgsize.getWidth(), (int)pgsize.getHeight())); slide.addShape(group); - int idx = ppt.addPicture(_slTests.readFile("clock.jpg"), Picture.JPEG); - Picture pict = new Picture(idx, group); + int idx = ppt.addPicture(_slTests.readFile("clock.jpg"), HSLFPictureShape.JPEG); + HSLFPictureShape pict = new HSLFPictureShape(idx, group); pict.setAnchor(new Rectangle(0, 0, 200, 200)); group.addShape(pict); @@ -283,7 +282,7 @@ public final class TestShapes { out.close(); ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray()); - ppt = new SlideShow(is); + ppt = new HSLFSlideShow(is); is.close(); slide = ppt.getSlides()[0]; @@ -295,10 +294,10 @@ public final class TestShapes { group = (HSLFGroupShape)shape[0]; HSLFShape[] grshape = group.getShapes(); assertEquals(2, grshape.length); - assertTrue(grshape[0] instanceof Picture); + assertTrue(grshape[0] instanceof HSLFPictureShape); assertTrue(grshape[1] instanceof Line); - pict = (Picture)grshape[0]; + pict = (HSLFPictureShape)grshape[0]; assertEquals(new Rectangle(0, 0, 200, 200), pict.getAnchor()); line = (Line)grshape[1]; @@ -311,8 +310,8 @@ public final class TestShapes { @Test public void removeShapes() throws IOException { String file = "with_textbox.ppt"; - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream(file)); - Slide sl = ppt.getSlides()[0]; + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(file)); + HSLFSlide sl = ppt.getSlides()[0]; HSLFShape[] sh = sl.getShapes(); assertEquals("expected four shaped in " + file, 4, sh.length); //remove all @@ -328,30 +327,30 @@ public final class TestShapes { ppt.write(out); out.close(); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); sl = ppt.getSlides()[0]; assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().length); } @Test public void lineWidth() { - SimpleShape sh = new AutoShape(ShapeType.RT_TRIANGLE); + HSLFSimpleShape sh = new HSLFAutoShape(ShapeType.RT_TRIANGLE); EscherOptRecord opt = sh.getEscherOptRecord(); - EscherSimpleProperty prop = SimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); + EscherSimpleProperty prop = HSLFSimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); assertNull(prop); - assertEquals(SimpleShape.DEFAULT_LINE_WIDTH, sh.getLineWidth(), 0); + assertEquals(HSLFSimpleShape.DEFAULT_LINE_WIDTH, sh.getLineWidth(), 0); sh.setLineWidth(1.0); - prop = SimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); + prop = HSLFSimpleShape.getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH); assertNotNull(prop); assertEquals(1.0, sh.getLineWidth(), 0); } @Test public void shapeId() { - SlideShow ppt = new SlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); HSLFShape shape = null; //EscherDgg is a document-level record which keeps track of the drawing groups @@ -400,25 +399,25 @@ public final class TestShapes { @Test public void lineColor() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("51731.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt")); HSLFShape[] shape = ppt.getSlides()[0].getShapes(); assertEquals(4, shape.length); - TextShape sh1 = (TextShape)shape[0]; + HSLFTextShape sh1 = (HSLFTextShape)shape[0]; assertEquals("Hello Apache POI", sh1.getText()); assertNull(sh1.getLineColor()); - TextShape sh2 = (TextShape)shape[1]; + HSLFTextShape sh2 = (HSLFTextShape)shape[1]; assertEquals("Why are you showing this border?", sh2.getText()); assertNull(sh2.getLineColor()); - TextShape sh3 = (TextShape)shape[2]; + HSLFTextShape sh3 = (HSLFTextShape)shape[2]; assertEquals("Text in a black border", sh3.getText()); assertEquals(Color.black, sh3.getLineColor()); assertEquals(0.75, sh3.getLineWidth(), 0); - TextShape sh4 = (TextShape)shape[3]; + HSLFTextShape sh4 = (HSLFTextShape)shape[3]; assertEquals("Border width is 5 pt", sh4.getText()); assertEquals(Color.black, sh4.getLineColor()); assertEquals(5.0, sh4.getLineWidth(), 0); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSheet.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSheet.java index a22e7eb3f9..60b8ca42e2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSheet.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSheet.java @@ -23,7 +23,7 @@ import junit.framework.TestCase; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; import org.apache.poi.hslf.record.ColorSchemeAtom; import org.apache.poi.hslf.record.PPDrawing; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -42,7 +42,7 @@ public final class TestSheet extends TestCase { String[] tests = {"SampleShow.ppt", "backgrounds.ppt", "text_shapes.ppt", "pictures.ppt"}; for (String file : tests) { try { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream(file)); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(file)); doSlideShow(ppt); } catch (EncryptedPowerPointFileException e){ ; //skip encrypted ppt @@ -50,21 +50,21 @@ public final class TestSheet extends TestCase { } } - private void doSlideShow(SlideShow ppt) { - Slide[] slide = ppt.getSlides(); + private void doSlideShow(HSLFSlideShow ppt) { + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { verify(slide[i]); - Notes notes = slide[i].getNotesSheet(); + HSLFNotes notes = slide[i].getNotesSheet(); if(notes != null) verify(notes); - MasterSheet master = slide[i].getMasterSheet(); + HSLFMasterSheet master = slide[i].getMasterSheet(); assertNotNull(master); verify(master); } } - private void verify(Sheet sheet){ + private void verify(HSLFSheet sheet){ assertNotNull(sheet.getSlideShow()); ColorSchemeAtom colorscheme = sheet.getColorScheme(); @@ -73,13 +73,13 @@ public final class TestSheet extends TestCase { PPDrawing ppdrawing = sheet.getPPDrawing(); assertNotNull(ppdrawing); - Background background = sheet.getBackground(); + HSLFBackground background = sheet.getBackground(); assertNotNull(background); assertTrue(sheet._getSheetNumber() != 0); assertTrue(sheet._getSheetRefId() != 0); - TextRun[] txt = sheet.getTextRuns(); + HSLFTextParagraph[] txt = sheet.getTextRuns(); if (txt == null) { throw new AssertionFailedError("no text runs"); } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideChangeNotes.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideChangeNotes.java index 71c95f87b7..2d4fe15131 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideChangeNotes.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideChangeNotes.java @@ -20,9 +20,8 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.record.SlideAtom; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -32,16 +31,16 @@ import org.apache.poi.POIDataSamples; */ public final class TestSlideChangeNotes extends TestCase { // SlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; public TestSlideChangeNotes() throws Exception { POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testSetToNone() { - Slide slideOne = ss.getSlides()[0]; + HSLFSlide slideOne = ss.getSlides()[0]; SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); slideOne.setNotes(null); @@ -50,8 +49,8 @@ public final class TestSlideChangeNotes extends TestCase { } public void testSetToSomething() { - Slide slideOne = ss.getSlides()[0]; - Notes notesOne = ss.getNotes()[1]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFNotes notesOne = ss.getNotes()[1]; SlideAtom sa = slideOne.getSlideRecord().getSlideAtom(); slideOne.setNotes(notesOne); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideMaster.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideMaster.java index 45c3c0c2bc..ffb6563da5 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideMaster.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlideMaster.java @@ -22,12 +22,11 @@ import java.io.ByteArrayOutputStream; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.model.textproperties.CharFlagsTextProp; import org.apache.poi.hslf.record.Environment; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -43,7 +42,7 @@ public final class TestSlideMaster extends TestCase{ * Check we can read their attributes. */ public void testSlideMaster() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); Environment env = ppt.getDocumentRecord().getEnvironment(); @@ -83,7 +82,7 @@ public final class TestSlideMaster extends TestCase{ * Test we can read default text attributes for a title master sheet */ public void testTitleMasterTextAttributes() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); TitleMaster[] master = ppt.getTitleMasters(); assertEquals(1, master.length); @@ -104,14 +103,14 @@ public final class TestSlideMaster extends TestCase{ * Slide 3 has title layout and follows the TitleMaster. Verify that. */ public void testTitleMaster() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); - Slide slide = ppt.getSlides()[2]; - MasterSheet masterSheet = slide.getMasterSheet(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlide slide = ppt.getSlides()[2]; + HSLFMasterSheet masterSheet = slide.getMasterSheet(); assertTrue(masterSheet instanceof TitleMaster); - TextRun[] txt = slide.getTextRuns(); + HSLFTextParagraph[] txt = slide.getTextRuns(); for (int i = 0; i < txt.length; i++) { - RichTextRun rt = txt[i].getRichTextRuns()[0]; + HSLFTextRun rt = txt[i].getRichTextRuns()[0]; switch(txt[i].getRunType()){ case TextHeaderAtom.CENTER_TITLE_TYPE: assertEquals("Arial", rt.getFontName()); @@ -133,20 +132,20 @@ public final class TestSlideMaster extends TestCase{ * If a style attribute is not set ensure it is read from the master */ public void testMasterAttributes() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); - Slide[] slide = ppt.getSlides(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlide[] slide = ppt.getSlides(); assertEquals(3, slide.length); - TextRun[] trun; + HSLFTextParagraph[] trun; trun = slide[0].getTextRuns(); for (int i = 0; i < trun.length; i++) { if (trun[i].getRunType() == TextHeaderAtom.TITLE_TYPE){ - RichTextRun rt = trun[i].getRichTextRuns()[0]; + HSLFTextRun rt = trun[i].getRichTextRuns()[0]; assertEquals(40, rt.getFontSize()); assertEquals(true, rt.isUnderlined()); assertEquals("Arial", rt.getFontName()); } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){ - RichTextRun rt; + HSLFTextRun rt; rt = trun[i].getRichTextRuns()[0]; assertEquals(0, rt.getIndentLevel()); assertEquals(32, rt.getFontSize()); @@ -163,12 +162,12 @@ public final class TestSlideMaster extends TestCase{ trun = slide[1].getTextRuns(); for (int i = 0; i < trun.length; i++) { if (trun[i].getRunType() == TextHeaderAtom.TITLE_TYPE){ - RichTextRun rt = trun[i].getRichTextRuns()[0]; + HSLFTextRun rt = trun[i].getRichTextRuns()[0]; assertEquals(48, rt.getFontSize()); assertEquals(true, rt.isItalic()); assertEquals("Georgia", rt.getFontName()); } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){ - RichTextRun rt; + HSLFTextRun rt; rt = trun[i].getRichTextRuns()[0]; assertEquals(0, rt.getIndentLevel()); assertEquals(32, rt.getFontSize()); @@ -182,9 +181,9 @@ public final class TestSlideMaster extends TestCase{ * Check we can dynamically assign a slide master to a slide. */ public void testChangeSlideMaster() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); SlideMaster[] master = ppt.getSlidesMasters(); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); int sheetNo; //each slide uses its own master @@ -203,7 +202,7 @@ public final class TestSlideMaster extends TestCase{ ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); master = ppt.getSlidesMasters(); slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { @@ -216,19 +215,19 @@ public final class TestSlideMaster extends TestCase{ * (typical for the "bullted body" placeholder) */ public void testIndentation() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("slide_master.ppt")); - Slide slide = ppt.getSlides()[0]; - TextRun[] trun; + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt")); + HSLFSlide slide = ppt.getSlides()[0]; + HSLFTextParagraph[] trun; trun = slide.getTextRuns(); for (int i = 0; i < trun.length; i++) { if (trun[i].getRunType() == TextHeaderAtom.TITLE_TYPE){ - RichTextRun rt = trun[i].getRichTextRuns()[0]; + HSLFTextRun rt = trun[i].getRichTextRuns()[0]; assertEquals(40, rt.getFontSize()); assertEquals(true, rt.isUnderlined()); assertEquals("Arial", rt.getFontName()); } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){ - RichTextRun[] rt = trun[i].getRichTextRuns(); + HSLFTextRun[] rt = trun[i].getRichTextRuns(); for (int j = 0; j < rt.length; j++) { int indent = rt[j].getIndentLevel(); switch (indent){ diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlides.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlides.java index 11889f4409..f5e0abef59 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlides.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestSlides.java @@ -18,8 +18,8 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.SlideShow; + +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; import java.io.ByteArrayOutputStream; @@ -39,10 +39,10 @@ public final class TestSlides extends TestCase { * @throws Exception */ public void testAddSlides1() throws Exception { - SlideShow ppt = new SlideShow(new HSLFSlideShow( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); + HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); assertTrue(ppt.getSlides().length == 0); - Slide s1 = ppt.createSlide(); + HSLFSlide s1 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 1); assertEquals(3, s1._getSheetRefId()); assertEquals(256, s1._getSheetNumber()); @@ -53,7 +53,7 @@ public final class TestSlides extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertTrue(ppt.getSlides().length == 1); } @@ -62,16 +62,16 @@ public final class TestSlides extends TestCase { * @throws Exception */ public void testAddSlides2() throws Exception { - SlideShow ppt = new SlideShow(new HSLFSlideShow( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); + HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); assertTrue(ppt.getSlides().length == 0); - Slide s1 = ppt.createSlide(); + HSLFSlide s1 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 1); assertEquals(3, s1._getSheetRefId()); assertEquals(256, s1._getSheetNumber()); assertEquals(1, s1.getSlideNumber()); - Slide s2 = ppt.createSlide(); + HSLFSlide s2 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 2); assertEquals(4, s2._getSheetRefId()); assertEquals(257, s2._getSheetNumber()); @@ -82,7 +82,7 @@ public final class TestSlides extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertTrue(ppt.getSlides().length == 2); } @@ -91,22 +91,22 @@ public final class TestSlides extends TestCase { * @throws Exception */ public void testAddSlides3() throws Exception { - SlideShow ppt = new SlideShow(new HSLFSlideShow( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); + HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") )); assertTrue(ppt.getSlides().length == 0); - Slide s1 = ppt.createSlide(); + HSLFSlide s1 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 1); assertEquals(3, s1._getSheetRefId()); assertEquals(256, s1._getSheetNumber()); assertEquals(1, s1.getSlideNumber()); - Slide s2 = ppt.createSlide(); + HSLFSlide s2 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 2); assertEquals(4, s2._getSheetRefId()); assertEquals(257, s2._getSheetNumber()); assertEquals(2, s2.getSlideNumber()); - Slide s3 = ppt.createSlide(); + HSLFSlide s3 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 3); assertEquals(5, s3._getSheetRefId()); assertEquals(258, s3._getSheetNumber()); @@ -118,7 +118,7 @@ public final class TestSlides extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertTrue(ppt.getSlides().length == 3); // Check IDs are still right @@ -139,22 +139,22 @@ public final class TestSlides extends TestCase { */ public void testAddSlides2to3() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - SlideShow ppt = new SlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); assertTrue(ppt.getSlides().length == 2); // First slide is 256 / 4 - Slide s1 = ppt.getSlides()[0]; + HSLFSlide s1 = ppt.getSlides()[0]; assertEquals(256, s1._getSheetNumber()); assertEquals(4, s1._getSheetRefId()); // Last slide is 257 / 6 - Slide s2 = ppt.getSlides()[1]; + HSLFSlide s2 = ppt.getSlides()[1]; assertEquals(257, s2._getSheetNumber()); assertEquals(6, s2._getSheetRefId()); // Add another slide, goes in at the end - Slide s3 = ppt.createSlide(); + HSLFSlide s3 = ppt.createSlide(); assertTrue(ppt.getSlides().length == 3); assertEquals(258, s3._getSheetNumber()); assertEquals(8, s3._getSheetRefId()); @@ -165,7 +165,7 @@ public final class TestSlides extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()))); + ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray()))); assertTrue(ppt.getSlides().length == 3); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java index 480fd8ab65..d3fb354063 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java @@ -23,7 +23,7 @@ import java.io.ByteArrayOutputStream; import junit.framework.TestCase; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; /** * Test Table object. @@ -36,16 +36,16 @@ public final class TestTable extends TestCase { * Test that ShapeFactory works properly and returns Table */ public void testShapeFactory() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); Table tbl = new Table(2, 5); slide.addShape(tbl); TableCell cell = tbl.getCell(0, 0); //table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033 - assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextRun().getRunType()); + assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraph().getRunType()); assertTrue(slide.getShapes()[0] instanceof Table); Table tbl2 = (Table)slide.getShapes()[0]; @@ -56,7 +56,7 @@ public final class TestTable extends TestCase { ppt.write(out); out.close(); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); slide = ppt.getSlides()[0]; assertTrue(slide.getShapes()[0] instanceof Table); Table tbl3 = (Table)slide.getShapes()[0]; @@ -68,8 +68,8 @@ public final class TestTable extends TestCase { * Error constructing Table when rownum=1 */ public void test45889(){ - SlideShow ppt = new SlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); HSLFShape[] shapes; Table tbl1 = new Table(1, 5); assertEquals(5, tbl1.getNumberOfColumns()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java index 1b0119307a..01ce6a0534 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRun.java @@ -30,8 +30,8 @@ import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.TextBytesAtom; import org.apache.poi.hslf.record.TextCharsAtom; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -43,24 +43,24 @@ public final class TestTextRun extends TestCase { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); // SlideShow primed on the test data - private SlideShow ss; - private SlideShow ssRich; + private HSLFSlideShow ss; + private HSLFSlideShow ssRich; protected void setUp() throws IOException { // Basic (non rich) test file - ss = new SlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); // Rich test file - ssRich = new SlideShow(_slTests.openResourceAsStream("Single_Coloured_Page.ppt")); + ssRich = new HSLFSlideShow(_slTests.openResourceAsStream("Single_Coloured_Page.ppt")); } /** * Test to ensure that getting the text works correctly */ public void testGetText() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); assertEquals(2, textRuns.length); @@ -74,8 +74,8 @@ public final class TestTextRun extends TestCase { // Now check on a rich text run - Slide slideOneR = ssRich.getSlides()[0]; - TextRun[] textRunsR = slideOneR.getTextRuns(); + HSLFSlide slideOneR = ssRich.getSlides()[0]; + HSLFTextParagraph[] textRunsR = slideOneR.getTextRuns(); assertEquals(2, textRunsR.length); assertEquals("This is a title, it\u2019s in black", textRunsR[0].getText()); @@ -88,9 +88,9 @@ public final class TestTextRun extends TestCase { * Test to ensure changing non rich text bytes->bytes works correctly */ public void testSetText() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - TextRun run = textRuns[0]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextParagraph run = textRuns[0]; // Check current text assertEquals("This is a test title", run.getText()); @@ -110,8 +110,8 @@ public final class TestTextRun extends TestCase { * chars works correctly */ public void testAdvancedSetText() { - Slide slideOne = ss.getSlides()[0]; - TextRun run = slideOne.getTextRuns()[0]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph run = slideOne.getTextRuns()[0]; TextHeaderAtom tha = run._headerAtom; TextBytesAtom tba = run._byteAtom; @@ -171,19 +171,19 @@ public final class TestTextRun extends TestCase { * set up for it */ public void testGetRichTextNonRich() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); assertEquals(2, textRuns.length); - TextRun trA = textRuns[0]; - TextRun trB = textRuns[1]; + HSLFTextParagraph trA = textRuns[0]; + HSLFTextParagraph trB = textRuns[1]; assertEquals(1, trA.getRichTextRuns().length); assertEquals(1, trB.getRichTextRuns().length); - RichTextRun rtrA = trA.getRichTextRuns()[0]; - RichTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrA = trA.getRichTextRuns()[0]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; assertEquals(trA.getText(), rtrA.getText()); assertEquals(trB.getText(), rtrB.getText()); @@ -198,21 +198,21 @@ public final class TestTextRun extends TestCase { * Tests to ensure that the rich text runs are built up correctly */ public void testGetRichText() { - Slide slideOne = ssRich.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); + HSLFSlide slideOne = ssRich.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); assertEquals(2, textRuns.length); - TextRun trA = textRuns[0]; - TextRun trB = textRuns[1]; + HSLFTextParagraph trA = textRuns[0]; + HSLFTextParagraph trB = textRuns[1]; assertEquals(1, trA.getRichTextRuns().length); assertEquals(3, trB.getRichTextRuns().length); - RichTextRun rtrA = trA.getRichTextRuns()[0]; - RichTextRun rtrB = trB.getRichTextRuns()[0]; - RichTextRun rtrC = trB.getRichTextRuns()[1]; - RichTextRun rtrD = trB.getRichTextRuns()[2]; + HSLFTextRun rtrA = trA.getRichTextRuns()[0]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrC = trB.getRichTextRuns()[1]; + HSLFTextRun rtrD = trB.getRichTextRuns()[2]; assertEquals(trA.getText(), rtrA.getText()); @@ -244,12 +244,12 @@ public final class TestTextRun extends TestCase { * ensuring that everything stays with the same default styling */ public void testSetTextWhereNotRich() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - TextRun trB = textRuns[1]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextParagraph trB = textRuns[1]; assertEquals(1, trB.getRichTextRuns().length); - RichTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; assertEquals(trB.getText(), rtrB.getText()); assertNull(rtrB._getRawCharacterStyle()); assertNull(rtrB._getRawParagraphStyle()); @@ -268,14 +268,14 @@ public final class TestTextRun extends TestCase { * sets everything to the same styling */ public void testSetTextWhereRich() { - Slide slideOne = ssRich.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - TextRun trB = textRuns[1]; + HSLFSlide slideOne = ssRich.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextParagraph trB = textRuns[1]; assertEquals(3, trB.getRichTextRuns().length); - RichTextRun rtrB = trB.getRichTextRuns()[0]; - RichTextRun rtrC = trB.getRichTextRuns()[1]; - RichTextRun rtrD = trB.getRichTextRuns()[2]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrC = trB.getRichTextRuns()[1]; + HSLFTextRun rtrD = trB.getRichTextRuns()[2]; TextPropCollection tpBP = rtrB._getRawParagraphStyle(); TextPropCollection tpBC = rtrB._getRawCharacterStyle(); TextPropCollection tpCP = rtrC._getRawParagraphStyle(); @@ -316,12 +316,12 @@ public final class TestTextRun extends TestCase { * in a rich text run, that doesn't happen to actually be rich */ public void testChangeTextInRichTextRunNonRich() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - TextRun trB = textRuns[1]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextParagraph trB = textRuns[1]; assertEquals(1, trB.getRichTextRuns().length); - RichTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; assertEquals(trB.getText(), rtrB.getText()); assertNull(rtrB._getRawCharacterStyle()); assertNull(rtrB._getRawParagraphStyle()); @@ -341,16 +341,16 @@ public final class TestTextRun extends TestCase { * correctly */ public void testChangeTextInRichTextRun() { - Slide slideOne = ssRich.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - TextRun trB = textRuns[1]; + HSLFSlide slideOne = ssRich.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextParagraph trB = textRuns[1]; assertEquals(3, trB.getRichTextRuns().length); // We start with 3 text runs, each with their own set of styles, // but all sharing the same paragraph styles - RichTextRun rtrB = trB.getRichTextRuns()[0]; - RichTextRun rtrC = trB.getRichTextRuns()[1]; - RichTextRun rtrD = trB.getRichTextRuns()[2]; + HSLFTextRun rtrB = trB.getRichTextRuns()[0]; + HSLFTextRun rtrC = trB.getRichTextRuns()[1]; + HSLFTextRun rtrD = trB.getRichTextRuns()[2]; TextPropCollection tpBP = rtrB._getRawParagraphStyle(); TextPropCollection tpBC = rtrB._getRawCharacterStyle(); TextPropCollection tpCP = rtrC._getRawParagraphStyle(); @@ -421,11 +421,11 @@ public final class TestTextRun extends TestCase { * */ public void testBug41015() throws IOException { - RichTextRun[] rt; + HSLFTextRun[] rt; - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("bug-41015.ppt")); - Slide sl = ppt.getSlides()[0]; - TextRun[] txt = sl.getTextRuns(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("bug-41015.ppt")); + HSLFSlide sl = ppt.getSlides()[0]; + HSLFTextParagraph[] txt = sl.getTextRuns(); assertEquals(2, txt.length); rt = txt[0].getRichTextRuns(); @@ -448,24 +448,24 @@ public final class TestTextRun extends TestCase { * Test creation of TextRun objects. */ public void testAddTextRun() { - SlideShow ppt = new SlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); assertNull(slide.getTextRuns()); - TextBox shape1 = new TextBox(); - TextRun run1 = shape1.getTextRun(); + HSLFTextBox shape1 = new HSLFTextBox(); + HSLFTextParagraph run1 = shape1.getTextParagraph(); assertSame(run1, shape1.createTextRun()); run1.setText("Text 1"); slide.addShape(shape1); //The array of Slide's text runs must be updated when new text shapes are added. - TextRun[] runs = slide.getTextRuns(); + HSLFTextParagraph[] runs = slide.getTextRuns(); assertNotNull(runs); assertSame(run1, runs[0]); - TextBox shape2 = new TextBox(); - TextRun run2 = shape2.getTextRun(); + HSLFTextBox shape2 = new HSLFTextBox(); + HSLFTextParagraph run2 = shape2.getTextParagraph(); assertSame(run2, shape2.createTextRun()); run2.setText("Text 2"); slide.addShape(shape2); @@ -479,14 +479,14 @@ public final class TestTextRun extends TestCase { //as getShapes() HSLFShape[] sh = slide.getShapes(); assertEquals(2, sh.length); - assertTrue(sh[0] instanceof TextBox); - TextBox box1 = (TextBox)sh[0]; - assertSame(run1, box1.getTextRun()); - TextBox box2 = (TextBox)sh[1]; - assertSame(run2, box2.getTextRun()); + assertTrue(sh[0] instanceof HSLFTextBox); + HSLFTextBox box1 = (HSLFTextBox)sh[0]; + assertSame(run1, box1.getTextParagraph()); + HSLFTextBox box2 = (HSLFTextBox)sh[1]; + assertSame(run2, box2.getTextParagraph()); //test Table - a complex group of shapes containing text objects - Slide slide2 = ppt.createSlide(); + HSLFSlide slide2 = ppt.createSlide(); assertNull(slide2.getTextRuns()); Table table = new Table(2, 2); slide2.addShape(table); @@ -496,12 +496,12 @@ public final class TestTextRun extends TestCase { } public void test48916() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); - for(Slide slide : ppt.getSlides()){ + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); + for(HSLFSlide slide : ppt.getSlides()){ for(HSLFShape sh : slide.getShapes()){ - if(sh instanceof TextShape){ - TextShape tx = (TextShape)sh; - TextRun run = tx.getTextRun(); + if(sh instanceof HSLFTextShape){ + HSLFTextShape tx = (HSLFTextShape)sh; + HSLFTextParagraph run = tx.getTextParagraph(); //verify that records cached in TextRun and EscherTextboxWrapper are the same Record[] runChildren = run.getRecords(); Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords(); @@ -517,13 +517,13 @@ public final class TestTextRun extends TestCase { } ByteArrayOutputStream out = new ByteArrayOutputStream(); ppt.write(out); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); - for(Slide slide : ppt.getSlides()){ + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); + for(HSLFSlide slide : ppt.getSlides()){ for(HSLFShape sh : slide.getShapes()){ - if(sh instanceof TextShape){ - TextShape tx = (TextShape)sh; - TextRun run = tx.getTextRun(); - RichTextRun rt = run.getRichTextRuns()[0]; + if(sh instanceof HSLFTextShape){ + HSLFTextShape tx = (HSLFTextShape)sh; + HSLFTextParagraph run = tx.getTextParagraph(); + HSLFTextRun rt = run.getRichTextRuns()[0]; assertTrue(rt.isBold()); assertEquals(rt.getFontColor(), Color.RED); } @@ -533,9 +533,9 @@ public final class TestTextRun extends TestCase { } public void test52244() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("52244.ppt")); - Slide slide = ppt.getSlides()[0]; - TextRun[] runs = slide.getTextRuns(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("52244.ppt")); + HSLFSlide slide = ppt.getSlides()[0]; + HSLFTextParagraph[] runs = slide.getTextRuns(); assertEquals("Arial", runs[0].getRichTextRuns()[0].getFontName()); assertEquals(36, runs[0].getRichTextRuns()[0].getFontSize()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRunReWrite.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRunReWrite.java index db55a2c052..c5a01341ae 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRunReWrite.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextRunReWrite.java @@ -19,11 +19,11 @@ package org.apache.poi.hslf.model; import junit.framework.TestCase; + import java.io.*; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.RichTextRun; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFTextRun; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.poifs.filesystem.*; import org.apache.poi.POIDataSamples; @@ -36,9 +36,9 @@ import org.apache.poi.POIDataSamples; */ public final class TestTextRunReWrite extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow hss; + private HSLFSlideShowImpl hss; // HSLFSlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; // POIFS primed on the test data private POIFSFileSystem pfs; @@ -49,14 +49,14 @@ public final class TestTextRunReWrite extends TestCase { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); String filename = "Single_Coloured_Page_With_Fonts_and_Alignments.ppt"; pfs = new POIFSFileSystem(slTests.openResourceAsStream(filename)); - hss = new HSLFSlideShow(pfs); - ss = new SlideShow(hss); + hss = new HSLFSlideShowImpl(pfs); + ss = new HSLFSlideShow(hss); } public void testWritesOutTheSameNonRich() throws Exception { // Grab the first text run on the first sheet - TextRun tr1 = ss.getSlides()[0].getTextRuns()[0]; - TextRun tr2 = ss.getSlides()[0].getTextRuns()[1]; + HSLFTextParagraph tr1 = ss.getSlides()[0].getTextRuns()[0]; + HSLFTextParagraph tr2 = ss.getSlides()[0].getTextRuns()[1]; // Ensure the text lengths are as we'd expect to start with assertEquals(1, ss.getSlides().length); @@ -112,10 +112,10 @@ public final class TestTextRunReWrite extends TestCase { public void testWritesOutTheSameRich() throws Exception { // Grab the first text run on the first sheet - TextRun tr1 = ss.getSlides()[0].getTextRuns()[0]; + HSLFTextParagraph tr1 = ss.getSlides()[0].getTextRuns()[0]; // Get the first rich text run - RichTextRun rtr1 = tr1.getRichTextRuns()[0]; + HSLFTextRun rtr1 = tr1.getRichTextRuns()[0]; // Check that the text sizes are as expected diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java index 542d608d8e..5666b8db0e 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestTextShape.java @@ -34,7 +34,7 @@ import java.util.Map; import org.apache.poi.POIDataSamples; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.sl.usermodel.ShapeType; import org.junit.Test; @@ -48,14 +48,14 @@ public final class TestTextShape { @Test public void createAutoShape(){ - TextShape shape = new AutoShape(ShapeType.TRAPEZOID); - assertNull(shape.getTextRun()); + HSLFTextShape shape = new HSLFAutoShape(ShapeType.TRAPEZOID); + assertNull(shape.getTextParagraph()); assertNull(shape.getText()); assertNull(shape.getEscherTextboxWrapper()); - TextRun run = shape.createTextRun(); + HSLFTextParagraph run = shape.createTextRun(); assertNotNull(run); - assertNotNull(shape.getTextRun()); + assertNotNull(shape.getTextParagraph()); assertNotNull(shape.getEscherTextboxWrapper()); assertEquals("", shape.getText()); assertSame(run, shape.createTextRun()); @@ -64,14 +64,14 @@ public final class TestTextShape { @Test public void createTextBox(){ - TextShape shape = new TextBox(); - TextRun run = shape.getTextRun(); + HSLFTextShape shape = new HSLFTextBox(); + HSLFTextParagraph run = shape.getTextParagraph(); assertNotNull(run); assertNotNull(shape.getText()); assertNotNull(shape.getEscherTextboxWrapper()); assertSame(run, shape.createTextRun()); - assertNotNull(shape.getTextRun()); + assertNotNull(shape.getTextParagraph()); assertNotNull(shape.getEscherTextboxWrapper()); assertEquals("", shape.getText()); @@ -85,15 +85,15 @@ public final class TestTextShape { */ @Test public void read() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("text_shapes.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("text_shapes.ppt")); List lst1 = new ArrayList(); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; HSLFShape[] shape = slide.getShapes(); for (int i = 0; i < shape.length; i++) { - assertTrue("Expected TextShape but found " + shape[i].getClass().getName(), shape[i] instanceof TextShape); - TextShape tx = (TextShape)shape[i]; - TextRun run = tx.getTextRun(); + assertTrue("Expected TextShape but found " + shape[i].getClass().getName(), shape[i] instanceof HSLFTextShape); + HSLFTextShape tx = (HSLFTextShape)shape[i]; + HSLFTextParagraph run = tx.getTextParagraph(); assertNotNull(run); int runType = run.getRunType(); @@ -125,7 +125,7 @@ public final class TestTextShape { } List lst2 = new ArrayList(); - TextRun[] run = slide.getTextRuns(); + HSLFTextParagraph[] run = slide.getTextRuns(); for (int i = 0; i < run.length; i++) { lst2.add(run[i].getText()); } @@ -135,18 +135,18 @@ public final class TestTextShape { @Test public void readWrite() throws IOException { - SlideShow ppt = new SlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlideShow ppt = new HSLFSlideShow(); + HSLFSlide slide = ppt.createSlide(); - TextShape shape1 = new TextBox(); - TextRun run1 = shape1.createTextRun(); + HSLFTextShape shape1 = new HSLFTextBox(); + HSLFTextParagraph run1 = shape1.createTextRun(); run1.setText("Hello, World!"); slide.addShape(shape1); shape1.moveTo(100, 100); - TextShape shape2 = new AutoShape(ShapeType.RIGHT_ARROW); - TextRun run2 = shape2.createTextRun(); + HSLFTextShape shape2 = new HSLFAutoShape(ShapeType.RIGHT_ARROW); + HSLFTextParagraph run2 = shape2.createTextRun(); run2.setText("Testing TextShape"); slide.addShape(shape2); shape2.moveTo(300, 300); @@ -155,37 +155,37 @@ public final class TestTextShape { ppt.write(out); out.close(); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); slide = ppt.getSlides()[0]; HSLFShape[] shape = slide.getShapes(); - assertTrue(shape[0] instanceof TextShape); - shape1 = (TextShape)shape[0]; + assertTrue(shape[0] instanceof HSLFTextShape); + shape1 = (HSLFTextShape)shape[0]; assertEquals(ShapeType.TEXT_BOX, shape1.getShapeType()); - assertEquals("Hello, World!", shape1.getTextRun().getText()); + assertEquals("Hello, World!", shape1.getTextParagraph().getText()); - assertTrue(shape[1] instanceof TextShape); - shape1 = (TextShape)shape[1]; + assertTrue(shape[1] instanceof HSLFTextShape); + shape1 = (HSLFTextShape)shape[1]; assertEquals(ShapeType.RIGHT_ARROW, shape1.getShapeType()); - assertEquals("Testing TextShape", shape1.getTextRun().getText()); + assertEquals("Testing TextShape", shape1.getTextParagraph().getText()); } @Test public void margins() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("text-margins.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("text-margins.ppt")); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; - Map map = new HashMap(); + Map map = new HashMap(); HSLFShape[] shape = slide.getShapes(); for (int i = 0; i < shape.length; i++) { - if(shape[i] instanceof TextShape){ - TextShape tx = (TextShape)shape[i]; + if(shape[i] instanceof HSLFTextShape){ + HSLFTextShape tx = (HSLFTextShape)shape[i]; map.put(tx.getText(), tx); } } - TextShape tx; + HSLFTextShape tx; tx = map.get("TEST1"); assertEquals(0.1, tx.getMarginLeft()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01); @@ -214,22 +214,22 @@ public final class TestTextShape { @Test public void bug52599() throws IOException { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("52599.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("52599.ppt")); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; HSLFShape[] sh = slide.getShapes(); assertEquals(3, sh.length); - TextShape sh0 = (TextShape)sh[0]; + HSLFTextShape sh0 = (HSLFTextShape)sh[0]; assertEquals(null, sh0.getText()); - assertEquals(null, sh0.getTextRun()); + assertEquals(null, sh0.getTextParagraph()); - TextShape sh1 = (TextShape)sh[1]; + HSLFTextShape sh1 = (HSLFTextShape)sh[1]; assertEquals(null, sh1.getText()); - assertEquals(null, sh1.getTextRun()); + assertEquals(null, sh1.getTextParagraph()); - TextShape sh2 = (TextShape)sh[2]; + HSLFTextShape sh2 = (HSLFTextShape)sh[2]; assertEquals("this box should be shown just once", sh2.getText()); - assertEquals(-1, sh2.getTextRun().getIndex()); + assertEquals(-1, sh2.getTextParagraph().getIndex()); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TextPainterTest.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TextPainterTest.java index 7db3ca6c8e..7e37b47a43 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/model/TextPainterTest.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/model/TextPainterTest.java @@ -19,7 +19,7 @@ package org.apache.poi.hslf.model; import org.apache.poi.hslf.record.StyleTextPropAtom; import org.apache.poi.hslf.record.TextCharsAtom; import org.apache.poi.hslf.record.TextHeaderAtom; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hssf.usermodel.DummyGraphics2d; import org.junit.Test; @@ -27,22 +27,22 @@ import org.junit.Test; public class TextPainterTest { @Test public void testTextPainter() { - TextShape shape = new Polygon(); + HSLFTextShape shape = new Polygon(); TextPainter painter = new TextPainter(shape); - painter.getAttributedString(new TextRun(null, new TextCharsAtom(), null)); + painter.getAttributedString(new HSLFTextParagraph(null, new TextCharsAtom(), null)); painter.paint(new DummyGraphics2d()); painter.getTextElements((float)1.0, null); } @Test public void testTextPainterWithText() { - TextShape shape = new Polygon(); + HSLFTextShape shape = new Polygon(); TextPainter painter = new TextPainter(shape); TextCharsAtom tca = new TextCharsAtom(); tca.setText("some text to read"); - TextRun txrun = new TextRun(new TextHeaderAtom(), tca, new StyleTextPropAtom(10)); - Slide sheet = new Slide(1, 1, 1); - sheet.setSlideShow(new SlideShow()); + HSLFTextParagraph txrun = new HSLFTextParagraph(new TextHeaderAtom(), tca, new StyleTextPropAtom(10)); + HSLFSlide sheet = new HSLFSlide(1, 1, 1); + sheet.setSlideShow(new HSLFSlideShow()); txrun.setSheet(sheet); painter.getAttributedString(txrun, new DummyGraphics2d()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestCurrentUserAtom.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestCurrentUserAtom.java index 05478e3374..60aee0f49d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestCurrentUserAtom.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestCurrentUserAtom.java @@ -24,8 +24,8 @@ import java.io.ByteArrayOutputStream; import java.io.InputStream; import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.poifs.filesystem.DocumentEntry; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.junit.Test; @@ -72,7 +72,7 @@ public final class TestCurrentUserAtom { new CurrentUserAtom(fs); assertTrue(true); // not yet failed - new HSLFSlideShow(fs); + new HSLFSlideShowImpl(fs); } @Test diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocument.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocument.java index 114a41da8d..d7de61c877 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocument.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocument.java @@ -19,7 +19,7 @@ package org.apache.poi.hslf.record; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.poifs.filesystem.*; import org.apache.poi.POIDataSamples; @@ -30,14 +30,14 @@ import org.apache.poi.POIDataSamples; */ public final class TestDocument extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow ss; + private HSLFSlideShowImpl ss; // POIFS primed on the test data private POIFSFileSystem pfs; public TestDocument() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); pfs = new POIFSFileSystem(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new HSLFSlideShow(pfs); + ss = new HSLFSlideShowImpl(pfs); } private Document getDocRecord() { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java index d9e3717842..12c114b344 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestDocumentEncryption.java @@ -33,11 +33,11 @@ import org.apache.poi.hpsf.DocumentSummaryInformation; import org.apache.poi.hpsf.PropertySet; import org.apache.poi.hpsf.PropertySetFactory; import org.apache.poi.hpsf.SummaryInformation; -import org.apache.poi.hslf.HSLFSlideShow; import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.usermodel.PictureData; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlide; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFPictureData; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.EncryptionInfo; @@ -71,8 +71,8 @@ public class TestDocumentEncryption { for (String pptFile : encPpts) { try { NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); - HSLFSlideShow hss = new HSLFSlideShow(fs); - new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); + new HSLFSlideShow(hss); fs.close(); } catch (EncryptedPowerPointFileException e) { fail(pptFile+" can't be decrypted"); @@ -85,9 +85,9 @@ public class TestDocumentEncryption { String pptFile = "cryptoapi-proc2356.ppt"; Biff8EncryptionKey.setCurrentUserPassword("crypto"); NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); - HSLFSlideShow hss = new HSLFSlideShow(fs); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); // need to cache data (i.e. read all data) before changing the key size - PictureData picsExpected[] = hss.getPictures(); + HSLFPictureData picsExpected[] = hss.getPictures(); hss.getDocumentSummaryInformation(); EncryptionInfo ei = hss.getDocumentEncryptionAtom().getEncryptionInfo(); ((CryptoAPIEncryptionHeader)ei.getHeader()).setKeySize(0x78); @@ -97,8 +97,8 @@ public class TestDocumentEncryption { fs.close(); fs = new NPOIFSFileSystem(new ByteArrayInputStream(bos.toByteArray())); - hss = new HSLFSlideShow(fs); - PictureData picsActual[] = hss.getPictures(); + hss = new HSLFSlideShowImpl(fs); + HSLFPictureData picsActual[] = hss.getPictures(); fs.close(); assertEquals(picsExpected.length, picsActual.length); @@ -112,7 +112,7 @@ public class TestDocumentEncryption { /* documents with multiple edits need to be normalized for encryption */ String pptFile = "57272_corrupted_usereditatom.ppt"; NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile(pptFile), true); - HSLFSlideShow hss = new HSLFSlideShow(fs); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); hss.normalizeRecords(); // normalized ppt @@ -128,7 +128,7 @@ public class TestDocumentEncryption { // decrypted ByteArrayInputStream bis = new ByteArrayInputStream(encrypted.toByteArray()); fs = new NPOIFSFileSystem(bis); - hss = new HSLFSlideShow(fs); + hss = new HSLFSlideShowImpl(fs); Biff8EncryptionKey.setCurrentUserPassword(null); ByteArrayOutputStream actual = new ByteArrayOutputStream(); hss.write(actual); @@ -143,10 +143,10 @@ public class TestDocumentEncryption { // http://blogs.msdn.com/b/openspecification/archive/2009/05/08/dominic-salemno.aspx Biff8EncryptionKey.setCurrentUserPassword("crypto"); NPOIFSFileSystem fs = new NPOIFSFileSystem(slTests.getFile("cryptoapi-proc2356.ppt")); - HSLFSlideShow hss = new HSLFSlideShow(fs); - SlideShow ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(fs); + HSLFSlideShow ss = new HSLFSlideShow(hss); - Slide slide = ss.getSlides()[0]; + HSLFSlide slide = ss.getSlides()[0]; assertEquals("Dominic Salemno", slide.getTextRuns()[0].getText()); String picCmp[][] = { @@ -160,9 +160,9 @@ public class TestDocumentEncryption { }; MessageDigest md = CryptoFunctions.getMessageDigest(HashAlgorithm.sha1); - PictureData pd[] = hss.getPictures(); + HSLFPictureData pd[] = hss.getPictures(); int i = 0; - for (PictureData p : pd) { + for (HSLFPictureData p : pd) { byte hash[] = md.digest(p.getData()); assertEquals(Integer.parseInt(picCmp[i][0]), p.getOffset()); assertEquals(picCmp[i][1], Base64.encodeBase64String(hash)); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExHyperlink.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExHyperlink.java index fff9d7286e..f712e20a6d 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExHyperlink.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExHyperlink.java @@ -25,8 +25,8 @@ import java.util.List; import junit.framework.AssertionFailedError; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -99,8 +99,8 @@ public final class TestExHyperlink extends TestCase { public void testRealFile() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("WithLinks.ppt")); - SlideShow ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithLinks.ppt")); + HSLFSlideShow ss = new HSLFSlideShow(hss); // Get the document Document doc = ss.getDocumentRecord(); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExObjList.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExObjList.java index d3739ec3b8..836016666e 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExObjList.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestExObjList.java @@ -20,8 +20,8 @@ package org.apache.poi.hslf.record; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.usermodel.SlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; +import org.apache.poi.hslf.usermodel.HSLFSlideShow; import org.apache.poi.POIDataSamples; /** @@ -32,8 +32,8 @@ import org.apache.poi.POIDataSamples; public class TestExObjList extends TestCase { public void testRealFile() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("WithLinks.ppt")); - SlideShow ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("WithLinks.ppt")); + HSLFSlideShow ss = new HSLFSlideShow(hss); // Get the document Document doc = ss.getDocumentRecord(); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordContainer.java b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordContainer.java index 8481cbc70f..cecf3ee319 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordContainer.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/record/TestRecordContainer.java @@ -20,7 +20,7 @@ package org.apache.poi.hslf.record; import junit.framework.TestCase; -import org.apache.poi.hslf.HSLFSlideShow; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.POIDataSamples; /** @@ -149,7 +149,7 @@ public final class TestRecordContainer extends TestCase { // Find a real RecordContainer record POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); Record[] r = hss.getRecords(); for(int i=0; i notesMap = new HashMap(); @@ -143,10 +128,10 @@ public final class TestBugs { notesMap.put(Integer.valueOf(7), "Although multiply and square root are easier"); notesMap.put(Integer.valueOf(8), "The bus Z is split into Z_H and Z_L"); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { Integer slideNumber = Integer.valueOf(slide[i].getSlideNumber()); - Notes notes = slide[i].getNotesSheet(); + HSLFNotes notes = slide[i].getNotesSheet(); if (notesMap.containsKey(slideNumber)){ assertNotNull(notes); String text = notes.getTextRuns()[0].getRawText(); @@ -162,18 +147,18 @@ public final class TestBugs { */ @Test public void bug42485 () throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("42485.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("42485.ppt")); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); HSLFShape[] shape = ppt.getSlides()[0].getShapes(); for (int i = 0; i < shape.length; i++) { if(shape[i] instanceof HSLFGroupShape){ HSLFGroupShape group = (HSLFGroupShape)shape[i]; HSLFShape[] sh = group.getShapes(); for (int j = 0; j < sh.length; j++) { - if( sh[j] instanceof TextBox){ - TextBox txt = (TextBox)sh[j]; - assertNotNull(txt.getTextRun()); + if( sh[j] instanceof HSLFTextBox){ + HSLFTextBox txt = (HSLFTextBox)sh[j]; + assertNotNull(txt.getTextParagraph()); } } } @@ -185,9 +170,9 @@ public final class TestBugs { */ @Test public void bug42484 () throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("42485.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("42485.ppt")); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); HSLFShape[] shape = ppt.getSlides()[0].getShapes(); for (int i = 0; i < shape.length; i++) { if(shape[i] instanceof HSLFGroupShape){ @@ -207,16 +192,16 @@ public final class TestBugs { */ @Test public void bug41381() throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("alterman_security.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("alterman_security.ppt")); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); assertTrue("No Exceptions while reading file", true); assertEquals(1, ppt.getSlidesMasters().length); assertEquals(1, ppt.getTitleMasters().length); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { - MasterSheet master = slide[i].getMasterSheet(); + HSLFMasterSheet master = slide[i].getMasterSheet(); if (i == 0) assertTrue(master instanceof TitleMaster); //the first slide follows TitleMaster else assertTrue(master instanceof SlideMaster); } @@ -227,10 +212,10 @@ public final class TestBugs { */ @Test public void bug42486 () throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("42486.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("42486.ppt")); - SlideShow ppt = new SlideShow(hslf); - Slide[] slide = ppt.getSlides(); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { @SuppressWarnings("unused") HSLFShape[] shape = slide[i].getShapes(); @@ -244,11 +229,11 @@ public final class TestBugs { */ @Test public void bug42524 () throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("42486.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("42486.ppt")); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); //walk down the tree and see if there were no errors while reading - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { HSLFShape[] shape = slide[i].getShapes(); for (int j = 0; j < shape.length; j++) { @@ -272,17 +257,17 @@ public final class TestBugs { */ @Test public void bug42520 () throws Exception { - HSLFSlideShow hslf = new HSLFSlideShow(_slTests.openResourceAsStream("42520.ppt")); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(_slTests.openResourceAsStream("42520.ppt")); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); //test case from the bug report HSLFGroupShape shapeGroup = (HSLFGroupShape)ppt.getSlides()[11].getShapes()[10]; - Picture picture = (Picture)shapeGroup.getShapes()[0]; + HSLFPictureShape picture = (HSLFPictureShape)shapeGroup.getShapes()[0]; picture.getPictureData(); //walk down the tree and see if there were no errors while reading - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++) { HSLFShape[] shape = slide[i].getShapes(); for (int j = 0; j < shape.length; j++) { @@ -291,9 +276,9 @@ public final class TestBugs { HSLFShape[] comps = group.getShapes(); for (int k = 0; k < comps.length; k++) { HSLFShape comp = comps[k]; - if (comp instanceof Picture){ + if (comp instanceof HSLFPictureShape){ @SuppressWarnings("unused") - PictureData pict = ((Picture)comp).getPictureData(); + HSLFPictureData pict = ((HSLFPictureShape)comp).getPictureData(); } } } @@ -310,13 +295,13 @@ public final class TestBugs { */ @Test public void bug38256 () throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("38256.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("38256.ppt")); assertTrue("No Exceptions while reading file", true); - Slide[] slide = ppt.getSlides(); + HSLFSlide[] slide = ppt.getSlides(); assertEquals(1, slide.length); - TextRun[] runs = slide[0].getTextRuns(); + HSLFTextParagraph[] runs = slide[0].getTextRuns(); assertEquals(4, runs.length); Set txt = new HashSet(); @@ -338,13 +323,13 @@ public final class TestBugs { */ @Test public void bug43781 () throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("43781.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("43781.ppt")); assertTrue("No Exceptions while reading file", true); // Check the first slide - Slide slide = ppt.getSlides()[0]; - TextRun[] slTr = slide.getTextRuns(); + HSLFSlide slide = ppt.getSlides()[0]; + HSLFTextParagraph[] slTr = slide.getTextRuns(); // Has two text runs, one from slide text, one from drawing assertEquals(2, slTr.length); @@ -354,11 +339,11 @@ public final class TestBugs { assertEquals("Second run", slTr[1].getText()); // Check the shape based text runs - List lst = new ArrayList(); + List lst = new ArrayList(); HSLFShape[] shape = slide.getShapes(); for (int i = 0; i < shape.length; i++) { - if( shape[i] instanceof TextShape){ - TextRun textRun = ((TextShape)shape[i]).getTextRun(); + if( shape[i] instanceof HSLFTextShape){ + HSLFTextParagraph textRun = ((HSLFTextShape)shape[i]).getTextParagraph(); if(textRun != null) { lst.add(textRun); } @@ -377,17 +362,17 @@ public final class TestBugs { */ @Test public void bug44296 () throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("44296.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("44296.ppt")); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; - Background b = slide.getBackground(); - Fill f = b.getFill(); - assertEquals(Fill.FILL_PICTURE, f.getFillType()); + HSLFBackground b = slide.getBackground(); + HSLFFill f = b.getFill(); + assertEquals(HSLFFill.FILL_PICTURE, f.getFillType()); - PictureData pict = f.getPictureData(); + HSLFPictureData pict = f.getPictureData(); assertNotNull(pict); - assertEquals(Picture.JPEG, pict.getType()); + assertEquals(HSLFPictureShape.JPEG, pict.getType()); } /** @@ -396,7 +381,7 @@ public final class TestBugs { @Test public void bug44770() throws Exception { try { - new SlideShow(_slTests.openResourceAsStream("44770.ppt")); + new HSLFSlideShow(_slTests.openResourceAsStream("44770.ppt")); } catch (RuntimeException e) { if (e.getMessage().equals("Couldn't instantiate the class for type with id 1036 on class class org.apache.poi.hslf.record.PPDrawing")) { throw new AssertionFailedError("Identified bug 44770"); @@ -410,16 +395,16 @@ public final class TestBugs { */ @Test public void bug41071() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("41071.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("41071.ppt")); - Slide slide = ppt.getSlides()[0]; + HSLFSlide slide = ppt.getSlides()[0]; HSLFShape[] sh = slide.getShapes(); assertEquals(1, sh.length); - assertTrue(sh[0] instanceof TextShape); - TextShape tx = (TextShape)sh[0]; - assertEquals("Fundera, planera och involvera.", tx.getTextRun().getText()); + assertTrue(sh[0] instanceof HSLFTextShape); + HSLFTextShape tx = (HSLFTextShape)sh[0]; + assertEquals("Fundera, planera och involvera.", tx.getTextParagraph().getText()); - TextRun[] run = slide.getTextRuns(); + HSLFTextParagraph[] run = slide.getTextRuns(); assertEquals(1, run.length); assertEquals("Fundera, planera och involvera.", run[0].getText()); } @@ -431,10 +416,10 @@ public final class TestBugs { @Test(expected=OldPowerPointFormatException.class) public void bug41711() throws Exception { // New file is fine - new SlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); + new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt")); // PowerPoint 95 gives an old format exception - new SlideShow(_slTests.openResourceAsStream("PPT95.ppt")); + new HSLFSlideShow(_slTests.openResourceAsStream("PPT95.ppt")); } /** @@ -442,9 +427,9 @@ public final class TestBugs { */ @Test public void bug49648() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("49648.ppt")); - for(Slide slide : ppt.getSlides()) { - for(TextRun run : slide.getTextRuns()) { + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("49648.ppt")); + for(HSLFSlide slide : ppt.getSlides()) { + for(HSLFTextParagraph run : slide.getTextRuns()) { String text = run.getRawText(); text.replace("{txtTot}", "With \u0123\u1234\u5678 unicode"); run.setRawText(text); @@ -458,10 +443,10 @@ public final class TestBugs { @Test public void bug41246a() throws Exception { InputStream fis = _slTests.openResourceAsStream("41246-1.ppt"); - HSLFSlideShow hslf = new HSLFSlideShow(fis); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(fis); fis.close(); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); assertTrue("No Exceptions while reading file", true); ppt = HSLFTestDataSamples.writeOutAndReadBack(ppt); @@ -471,10 +456,10 @@ public final class TestBugs { @Test public void bug41246b() throws Exception { InputStream fis = _slTests.openResourceAsStream("41246-2.ppt"); - HSLFSlideShow hslf = new HSLFSlideShow(fis); + HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(fis); fis.close(); - SlideShow ppt = new SlideShow(hslf); + HSLFSlideShow ppt = new HSLFSlideShow(hslf); assertTrue("No Exceptions while reading file", true); ppt = HSLFTestDataSamples.writeOutAndReadBack(ppt); @@ -487,14 +472,14 @@ public final class TestBugs { @Test public void bug45776() throws Exception { InputStream is = _slTests.openResourceAsStream("45776.ppt"); - SlideShow ppt = new SlideShow(new HSLFSlideShow(is)); + HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl(is)); is.close(); // get slides - for (Slide slide : ppt.getSlides()) { + for (HSLFSlide slide : ppt.getSlides()) { for (HSLFShape shape : slide.getShapes()) { - if (!(shape instanceof TextBox)) continue; - TextBox tb = (TextBox) shape; + if (!(shape instanceof HSLFTextBox)) continue; + HSLFTextBox tb = (HSLFTextBox) shape; // work with TextBox String str = tb.getText(); @@ -502,7 +487,7 @@ public final class TestBugs { str = str.replace("$$DATE$$", new Date().toString()); tb.setText(str); - TextRun tr = tb.getTextRun(); + HSLFTextParagraph tr = tb.getTextParagraph(); assertEquals(str.length()+1,tr.getStyleTextPropAtom().getParagraphStyles().getFirst().getCharactersCovered()); assertEquals(str.length()+1,tr.getStyleTextPropAtom().getCharacterStyles().getFirst().getCharactersCovered()); } @@ -513,12 +498,12 @@ public final class TestBugs { public void bug55732() throws Exception { File file = _slTests.getFile("bug55732.ppt"); - HSLFSlideShow ss = new HSLFSlideShow(file.getAbsolutePath()); - SlideShow _show = new SlideShow(ss); - Slide[] _slides = _show.getSlides(); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(file.getAbsolutePath()); + HSLFSlideShow _show = new HSLFSlideShow(ss); + HSLFSlide[] _slides = _show.getSlides(); /* Iterate over slides and extract text */ - for( Slide slide : _slides ) { + for( HSLFSlide slide : _slides ) { HeadersFooters hf = slide.getHeadersFooters(); /*boolean visible =*/ hf.isHeaderVisible(); // exception happens here } @@ -529,9 +514,9 @@ public final class TestBugs { public void bug56260() throws Exception { File file = _slTests.getFile("56260.ppt"); - HSLFSlideShow ss = new HSLFSlideShow(file.getAbsolutePath()); - SlideShow _show = new SlideShow(ss); - Slide[] _slides = _show.getSlides(); + HSLFSlideShowImpl ss = new HSLFSlideShowImpl(file.getAbsolutePath()); + HSLFSlideShow _show = new HSLFSlideShow(ss); + HSLFSlide[] _slides = _show.getSlides(); assertEquals(13, _slides.length); // Check the number of TextHeaderAtoms on Slide 1 @@ -553,7 +538,7 @@ public final class TestBugs { // Check the number of text runs based on the slide (not textbox) // Will have skipped the empty one int str = 0; - for (TextRun tr : _slides[0].getTextRuns()) { + for (HSLFTextParagraph tr : _slides[0].getTextRuns()) { if (! tr.isDrawingBased()) str++; } assertEquals(1, str); @@ -563,10 +548,10 @@ public final class TestBugs { public void bug37625() throws IOException { InputStream inputStream = new FileInputStream(_slTests.getFile("37625.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); assertEquals(29, slideShow.getSlides().length); - SlideShow slideBack = HSLFTestDataSamples.writeOutAndReadBack(slideShow); + HSLFSlideShow slideBack = HSLFTestDataSamples.writeOutAndReadBack(slideShow); assertNotNull(slideBack); assertEquals(29, slideBack.getSlides().length); } finally { @@ -578,10 +563,10 @@ public final class TestBugs { public void bug57272() throws Exception { InputStream inputStream = new FileInputStream(_slTests.getFile("57272_corrupted_usereditatom.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); assertEquals(6, slideShow.getSlides().length); - SlideShow slideBack = HSLFTestDataSamples.writeOutAndReadBack(slideShow); + HSLFSlideShow slideBack = HSLFTestDataSamples.writeOutAndReadBack(slideShow); assertNotNull(slideBack); assertEquals(6, slideBack.getSlides().length); } finally { @@ -593,10 +578,10 @@ public final class TestBugs { public void bug49541() throws Exception { InputStream inputStream = new FileInputStream(_slTests.getFile("49541_symbol_map.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); - Slide slide = slideShow.getSlides()[0]; + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); + HSLFSlide slide = slideShow.getSlides()[0]; HSLFGroupShape sg = (HSLFGroupShape)slide.getShapes()[0]; - TextBox tb = (TextBox)sg.getShapes()[0]; + HSLFTextBox tb = (HSLFTextBox)sg.getShapes()[0]; String text = StringUtil.mapMsCodepointString(tb.getText()); assertEquals("\u226575 years", text); } finally { @@ -608,7 +593,7 @@ public final class TestBugs { public void bug47261() throws Exception { InputStream inputStream = new FileInputStream(_slTests.getFile("bug47261.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); slideShow.removeSlide(0); slideShow.createSlide(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -622,7 +607,7 @@ public final class TestBugs { public void bug56240() throws Exception { InputStream inputStream = new FileInputStream(_slTests.getFile("bug56240.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); int slideCnt = slideShow.getSlides().length; assertEquals(105, slideCnt); ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -637,8 +622,8 @@ public final class TestBugs { public void bug46441() throws Exception { InputStream inputStream = new FileInputStream(_slTests.getFile("bug46441.ppt")); try { - SlideShow slideShow = new SlideShow(inputStream); - AutoShape as = (AutoShape)slideShow.getSlides()[0].getShapes()[0]; + HSLFSlideShow slideShow = new HSLFSlideShow(inputStream); + HSLFAutoShape as = (HSLFAutoShape)slideShow.getSlides()[0].getShapes()[0]; EscherOptRecord opt = as.getEscherOptRecord(); EscherArrayProperty ep = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__SHADECOLORS); double exp[][] = { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestCounts.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestCounts.java index eb84e7711a..dbee82742f 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestCounts.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestCounts.java @@ -19,6 +19,7 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; + import org.apache.poi.hslf.*; import org.apache.poi.hslf.model.*; import org.apache.poi.POIDataSamples; @@ -30,16 +31,16 @@ import org.apache.poi.POIDataSamples; */ public final class TestCounts extends TestCase { // SlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; public TestCounts() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testSheetsCount() { - Slide[] slides = ss.getSlides(); + HSLFSlide[] slides = ss.getSlides(); // Two sheets - master sheet is separate assertEquals(2, slides.length); @@ -57,7 +58,7 @@ public final class TestCounts extends TestCase { } public void testNotesCount() { - Notes[] notes = ss.getNotes(); + HSLFNotes[] notes = ss.getNotes(); // Two sheets -> two notes // Note: there are also notes on the slide master //assertEquals(3, notes.length); // When we do slide masters diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestFontRendering.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestFontRendering.java index a6fa770059..37b7bb6965 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestFontRendering.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestFontRendering.java @@ -39,7 +39,7 @@ import java.util.Map; import javax.imageio.ImageIO; import org.apache.poi.POIDataSamples; -import org.apache.poi.hslf.model.Slide; +import org.apache.poi.hslf.model.HSLFSlide; import org.apache.poi.hslf.model.TextPainter; import org.apache.poi.util.TempFile; import org.junit.Ignore; @@ -82,12 +82,12 @@ public class TestFontRendering { } InputStream is = slTests.openResourceAsStream("bug55902-mixedFontChineseCharacters.ppt"); - SlideShow ss = new SlideShow(is); + HSLFSlideShow ss = new HSLFSlideShow(is); is.close(); Dimension pgsize = ss.getPageSize(); - Slide slide = ss.getSlides()[0]; + HSLFSlide slide = ss.getSlides()[0]; // render it double zoom = 1; diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java index ce68b7a2d8..088dbb0cee 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestMostRecentRecords.java @@ -19,7 +19,9 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; + import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.*; import org.apache.poi.POIDataSamples; @@ -30,14 +32,14 @@ import org.apache.poi.POIDataSamples; */ public final class TestMostRecentRecords extends TestCase { // HSLFSlideShow primed on the test data - private HSLFSlideShow hss; + private HSLFSlideShowImpl hss; // SlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; public TestMostRecentRecords() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testCount() { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNotesText.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNotesText.java index 3def468f9e..22b40a22e2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNotesText.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNotesText.java @@ -19,6 +19,7 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; + import org.apache.poi.hslf.*; import org.apache.poi.hslf.model.*; import org.apache.poi.POIDataSamples; @@ -30,16 +31,16 @@ import org.apache.poi.POIDataSamples; */ public final class TestNotesText extends TestCase { // SlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; public TestNotesText() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testNotesOne() { - Notes notes = ss.getNotes()[0]; + HSLFNotes notes = ss.getNotes()[0]; String[] expectText = new String[] {"These are the notes for page 1"}; assertEquals(expectText.length, notes.getTextRuns().length); @@ -49,7 +50,7 @@ public final class TestNotesText extends TestCase { } public void testNotesTwo() { - Notes notes = ss.getNotes()[1]; + HSLFNotes notes = ss.getNotes()[1]; String[] expectText = new String[] {"These are the notes on page two, again lacking formatting"}; assertEquals(expectText.length, notes.getTextRuns().length); for(int i=0; i 3 assertEquals(s1._getSheetNumber(), _s3._getSheetNumber()); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRecordSetup.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRecordSetup.java index 5475dae9c1..c15bacd1f2 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRecordSetup.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRecordSetup.java @@ -19,7 +19,9 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; + import org.apache.poi.hslf.*; +import org.apache.poi.hslf.model.HSLFSlideShowImpl; import org.apache.poi.hslf.record.ParentAwareRecord; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.RecordContainer; @@ -34,13 +36,13 @@ import org.apache.poi.POIDataSamples; */ public final class TestRecordSetup extends TestCase { // SlideShow primed on the test data - private SlideShow ss; - private HSLFSlideShow hss; + private HSLFSlideShow ss; + private HSLFSlideShowImpl hss; public TestRecordSetup() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testHandleParentAwareRecords() { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java index a71b72a28b..267e9ec7a4 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestRichTextRun.java @@ -23,10 +23,7 @@ import java.io.FileInputStream; import org.apache.poi.POIDataSamples; import org.apache.poi.POITestCase; -import org.apache.poi.hslf.HSLFSlideShow; -import org.apache.poi.hslf.model.Slide; -import org.apache.poi.hslf.model.TextBox; -import org.apache.poi.hslf.model.TextRun; +import org.apache.poi.hslf.model.*; import org.apache.poi.hslf.record.Record; import org.apache.poi.hslf.record.SlideListWithText; @@ -39,40 +36,40 @@ public final class TestRichTextRun extends POITestCase { private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance(); // SlideShow primed on the test data - private SlideShow ss; - private SlideShow ssRichA; - private SlideShow ssRichB; - private SlideShow ssRichC; - private SlideShow ssChinese; - private HSLFSlideShow hss; - private HSLFSlideShow hssRichA; - private HSLFSlideShow hssRichB; - private HSLFSlideShow hssRichC; - private HSLFSlideShow hssChinese; + private HSLFSlideShow ss; + private HSLFSlideShow ssRichA; + private HSLFSlideShow ssRichB; + private HSLFSlideShow ssRichC; + private HSLFSlideShow ssChinese; + private HSLFSlideShowImpl hss; + private HSLFSlideShowImpl hssRichA; + private HSLFSlideShowImpl hssRichB; + private HSLFSlideShowImpl hssRichC; + private HSLFSlideShowImpl hssChinese; private static String filenameC; protected void setUp() throws Exception { // Basic (non rich) test file - hss = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); // Rich test file A - hssRichA = new HSLFSlideShow(_slTests.openResourceAsStream("Single_Coloured_Page.ppt")); - ssRichA = new SlideShow(hssRichA); + hssRichA = new HSLFSlideShowImpl(_slTests.openResourceAsStream("Single_Coloured_Page.ppt")); + ssRichA = new HSLFSlideShow(hssRichA); // Rich test file B - hssRichB = new HSLFSlideShow(_slTests.openResourceAsStream("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")); - ssRichB = new SlideShow(hssRichB); + hssRichB = new HSLFSlideShowImpl(_slTests.openResourceAsStream("Single_Coloured_Page_With_Fonts_and_Alignments.ppt")); + ssRichB = new HSLFSlideShow(hssRichB); // Rich test file C - has paragraph styles that run out before // the character ones do filenameC = "ParagraphStylesShorterThanCharStyles.ppt"; - hssRichC = new HSLFSlideShow(_slTests.openResourceAsStream(filenameC)); - ssRichC = new SlideShow(hssRichC); + hssRichC = new HSLFSlideShowImpl(_slTests.openResourceAsStream(filenameC)); + ssRichC = new HSLFSlideShow(hssRichC); // Rich test file with Chinese + English text in it - hssChinese = new HSLFSlideShow(_slTests.openResourceAsStream("54880_chinese.ppt")); - ssChinese = new SlideShow(hssChinese); + hssChinese = new HSLFSlideShowImpl(_slTests.openResourceAsStream("54880_chinese.ppt")); + ssChinese = new HSLFSlideShow(hssChinese); } /** @@ -80,9 +77,9 @@ public final class TestRichTextRun extends POITestCase { * on a non rich text run */ public void testBoldNonRich() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - RichTextRun rtr = textRuns[0].getRichTextRuns()[0]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextRun rtr = textRuns[0].getRichTextRuns()[0]; assertNull(rtr._getRawCharacterStyle()); assertNull(rtr._getRawParagraphStyle()); @@ -108,9 +105,9 @@ public final class TestRichTextRun extends POITestCase { * on a rich text run */ public void testBoldRich() { - Slide slideOneR = ssRichA.getSlides()[0]; - TextRun[] textRunsR = slideOneR.getTextRuns(); - RichTextRun[] rtrs = textRunsR[1].getRichTextRuns(); + HSLFSlide slideOneR = ssRichA.getSlides()[0]; + HSLFTextParagraph[] textRunsR = slideOneR.getTextRuns(); + HSLFTextRun[] rtrs = textRunsR[1].getRichTextRuns(); assertEquals(3, rtrs.length); assertTrue(rtrs[0].isBold()); @@ -136,15 +133,15 @@ public final class TestRichTextRun extends POITestCase { */ public void testFontSize() { - Slide slideOne = ss.getSlides()[0]; - TextRun[] textRuns = slideOne.getTextRuns(); - RichTextRun rtr = textRuns[0].getRichTextRuns()[0]; + HSLFSlide slideOne = ss.getSlides()[0]; + HSLFTextParagraph[] textRuns = slideOne.getTextRuns(); + HSLFTextRun rtr = textRuns[0].getRichTextRuns()[0]; - Slide slideOneR = ssRichB.getSlides()[0]; - TextRun[] textRunsR = slideOneR.getTextRuns(); - RichTextRun rtrRa = textRunsR[0].getRichTextRuns()[0]; - RichTextRun rtrRb = textRunsR[1].getRichTextRuns()[0]; - RichTextRun rtrRc = textRunsR[1].getRichTextRuns()[3]; + HSLFSlide slideOneR = ssRichB.getSlides()[0]; + HSLFTextParagraph[] textRunsR = slideOneR.getTextRuns(); + HSLFTextRun rtrRa = textRunsR[0].getRichTextRuns()[0]; + HSLFTextRun rtrRb = textRunsR[1].getRichTextRuns()[0]; + HSLFTextRun rtrRc = textRunsR[1].getRichTextRuns()[3]; String defaultFont = "Arial"; @@ -195,14 +192,14 @@ public final class TestRichTextRun extends POITestCase { } public void testChangeWriteRead() throws Exception { - HSLFSlideShow[] h = new HSLFSlideShow[] { hss, hssRichA, hssRichB }; - Slide[] s = new Slide[] { ss.getSlides()[0], ssRichA.getSlides()[0], ssRichB.getSlides()[0] }; + HSLFSlideShowImpl[] h = new HSLFSlideShowImpl[] { hss, hssRichA, hssRichB }; + HSLFSlide[] s = new HSLFSlide[] { ss.getSlides()[0], ssRichA.getSlides()[0], ssRichB.getSlides()[0] }; for(int i=0; i(text a)(text a)(text b) // TR: // (text) - TextRun[] s7tr = slideSevenC.getTextRuns(); - RichTextRun[] s7rtr0 = s7tr[0].getRichTextRuns(); - RichTextRun[] s7rtr1 = s7tr[1].getRichTextRuns(); - RichTextRun[] s7rtr2 = s7tr[2].getRichTextRuns(); + HSLFTextParagraph[] s7tr = slideSevenC.getTextRuns(); + HSLFTextRun[] s7rtr0 = s7tr[0].getRichTextRuns(); + HSLFTextRun[] s7rtr1 = s7tr[1].getRichTextRuns(); + HSLFTextRun[] s7rtr2 = s7tr[2].getRichTextRuns(); assertEquals(1, s7rtr0.length); assertEquals(3, s7rtr1.length); @@ -334,11 +331,11 @@ public final class TestRichTextRun extends POITestCase { assertMatchesSLTWC(ssRichC); assertMatchesFileC(ssRichC); - Slide slideSevenC = ssRichC.getSlides()[6]; - TextRun[] s7tr = slideSevenC.getTextRuns(); - RichTextRun[] s7rtr0 = s7tr[0].getRichTextRuns(); - RichTextRun[] s7rtr1 = s7tr[1].getRichTextRuns(); - RichTextRun[] s7rtr2 = s7tr[2].getRichTextRuns(); + HSLFSlide slideSevenC = ssRichC.getSlides()[6]; + HSLFTextParagraph[] s7tr = slideSevenC.getTextRuns(); + HSLFTextRun[] s7rtr0 = s7tr[0].getRichTextRuns(); + HSLFTextRun[] s7rtr1 = s7tr[1].getRichTextRuns(); + HSLFTextRun[] s7rtr2 = s7tr[2].getRichTextRuns(); String oldText; @@ -374,9 +371,9 @@ public final class TestRichTextRun extends POITestCase { * contents. * @param s */ - private void assertMatchesSLTWC(SlideShow s) throws Exception { + private void assertMatchesSLTWC(HSLFSlideShow s) throws Exception { // Grab a new copy of slideshow C - SlideShow refC = new SlideShow(_slTests.openResourceAsStream(filenameC)); + HSLFSlideShow refC = new HSLFSlideShow(_slTests.openResourceAsStream(filenameC)); // Write out the 2nd SLWT in the active document SlideListWithText refSLWT = refC.getDocumentRecord().getSlideListWithTexts()[1]; @@ -411,7 +408,7 @@ public final class TestRichTextRun extends POITestCase { * Checks that the supplied slideshow still matches the bytes * of slideshow c */ - private static void assertMatchesFileC(SlideShow s) throws Exception { + private static void assertMatchesFileC(HSLFSlideShow s) throws Exception { if (true) { // TODO - test is disabled, pending fix of bug #39800 // System.err.println("Skipping test, as would be marked as failed due to bug #39800"); // return; @@ -450,12 +447,12 @@ if(false) { } public void testIndentationLevel() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("ParagraphStylesShorterThanCharStyles.ppt")); - Slide[] sl = ppt.getSlides(); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("ParagraphStylesShorterThanCharStyles.ppt")); + HSLFSlide[] sl = ppt.getSlides(); for (int i = 0; i < sl.length; i++) { - TextRun[] txt = sl[i].getTextRuns(); + HSLFTextParagraph[] txt = sl[i].getTextRuns(); for (int j = 0; j < txt.length; j++) { - RichTextRun[] rt = txt[j].getRichTextRuns(); + HSLFTextRun[] rt = txt[j].getRichTextRuns(); for (int k = 0; k < rt.length; k++) { int indent = rt[k].getIndentLevel(); assertTrue(indent >= 0 && indent <= 4 ); @@ -466,12 +463,12 @@ if(false) { } public void testReadParagraphStyles() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("bullets.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("bullets.ppt")); assertTrue("No Exceptions while reading file", true); - RichTextRun rt; - TextRun[] txt; - Slide[] slide = ppt.getSlides(); + HSLFTextRun rt; + HSLFTextParagraph[] txt; + HSLFSlide[] slide = ppt.getSlides(); assertEquals(2, slide.length); txt = slide[0].getTextRuns(); @@ -516,12 +513,12 @@ if(false) { } public void testSetParagraphStyles() throws Exception { - SlideShow ppt = new SlideShow(); + HSLFSlideShow ppt = new HSLFSlideShow(); - Slide slide = ppt.createSlide(); + HSLFSlide slide = ppt.createSlide(); - TextBox shape = new TextBox(); - RichTextRun rt = shape.getTextRun().getRichTextRuns()[0]; + HSLFTextBox shape = new HSLFTextBox(); + HSLFTextRun rt = shape.getTextParagraph().getRichTextRuns()[0]; shape.setText( "Hello, World!\r" + "This should be\r" + @@ -547,10 +544,10 @@ if(false) { ppt.write(out); out.close(); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); slide = ppt.getSlides()[0]; - shape = (TextBox)slide.getShapes()[0]; - rt = shape.getTextRun().getRichTextRuns()[0]; + shape = (HSLFTextBox)slide.getShapes()[0]; + rt = shape.getTextParagraph().getRichTextRuns()[0]; assertEquals(42, rt.getFontSize()); assertEquals(true, rt.isBullet()); assertEquals(50, rt.getTextOffset()); @@ -559,12 +556,12 @@ if(false) { } public void testAddText() throws Exception { - SlideShow ppt = new SlideShow(_slTests.openResourceAsStream("bullets.ppt")); + HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("bullets.ppt")); assertTrue("No Exceptions while reading file", true); - RichTextRun rt; - TextRun[] txt; - Slide[] slides = ppt.getSlides(); + HSLFTextRun rt; + HSLFTextParagraph[] txt; + HSLFSlide[] slides = ppt.getSlides(); assertEquals(2, slides.length); txt = slides[0].getTextRuns(); @@ -605,7 +602,7 @@ if(false) { ppt.write(out); out.close(); - ppt = new SlideShow(new ByteArrayInputStream(out.toByteArray())); + ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())); slides = ppt.getSlides(); assertEquals(2, slides.length); @@ -628,10 +625,10 @@ if(false) { } public void testChineseParagraphs() throws Exception { - RichTextRun[] rts; - RichTextRun rt; - TextRun[] txt; - Slide[] slides = ssChinese.getSlides(); + HSLFTextRun[] rts; + HSLFTextRun rt; + HSLFTextParagraph[] txt; + HSLFSlide[] slides = ssChinese.getSlides(); // One slide assertEquals(1, slides.length); diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestSheetText.java b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestSheetText.java index cb27d3ee92..fda2aba0d0 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestSheetText.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestSheetText.java @@ -19,6 +19,7 @@ package org.apache.poi.hslf.usermodel; import junit.framework.TestCase; + import org.apache.poi.hslf.*; import org.apache.poi.hslf.model.*; import org.apache.poi.POIDataSamples; @@ -30,16 +31,16 @@ import org.apache.poi.POIDataSamples; */ public final class TestSheetText extends TestCase { // SlideShow primed on the test data - private SlideShow ss; + private HSLFSlideShow ss; public TestSheetText() throws Exception { POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); - HSLFSlideShow hss = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); - ss = new SlideShow(hss); + HSLFSlideShowImpl hss = new HSLFSlideShowImpl(slTests.openResourceAsStream("basic_test_ppt_file.ppt")); + ss = new HSLFSlideShow(hss); } public void testSheetOne() { - Sheet slideOne = ss.getSlides()[0]; + HSLFSheet slideOne = ss.getSlides()[0]; String[] expectText = new String[] {"This is a test title","This is a test subtitle\nThis is on page 1"}; assertEquals(expectText.length, slideOne.getTextRuns().length); @@ -49,7 +50,7 @@ public final class TestSheetText extends TestCase { } public void testSheetTwo() { - Sheet slideTwo = ss.getSlides()[1]; + HSLFSheet slideTwo = ss.getSlides()[1]; String[] expectText = new String[] {"This is the title on page 2","This is page two\nIt has several blocks of text\nNone of them have formatting"}; assertEquals(expectText.length, slideTwo.getTextRuns().length); for(int i=0; i