HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
tr1.setText("POI-HSLF");
box1.setAnchor(new Rectangle(54, 78, 612, 115));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
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);
HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextParagraph tr3 = box3.getTextParagraph();
- tr3.getRichTextRuns()[0].setFontSize(32);
+ HSLFTextParagraph tr3 = box3.getTextParagraphs();
+ tr3.getTextRuns()[0].setFontSize(32);
box3.setHorizontalAlignment(HSLFTextBox.AlignCenter);
tr3.setText(
"Yegor Kozlov\r" +
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("What is HSLF?");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.BODY_TYPE);
tr2.setText("HorribleSLideshowFormat is the POI Project's pure Java implementation " +
"of the Powerpoint binary file format. \r" +
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("HSLF in a Nutshell");
box1.setAnchor(new Rectangle(36, 15, 648, 65));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.BODY_TYPE);
tr2.setText(
"HSLF provides a way to read, create and modify MS PowerPoint presentations\r" +
"Pure Java API - you don't need PowerPoint to read and write *.ppt files\r" +
"Comprehensive support of PowerPoint objects");
- tr2.getRichTextRuns()[0].setFontSize(28);
+ tr2.getTextRuns()[0].setFontSize(28);
box2.setAnchor(new Rectangle(36, 80, 648, 200));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextParagraph tr3 = box3.getTextParagraph();
+ HSLFTextParagraph tr3 = box3.getTextParagraphs();
tr3.setRunType(TextHeaderAtom.BODY_TYPE);
tr3.setText(
"Rich text\r" +
"Shapes\r" +
"Pictures\r" +
"Master slides");
- tr3.getRichTextRuns()[0].setFontSize(24);
- tr3.getRichTextRuns()[0].setIndentLevel(1);
+ tr3.getTextRuns()[0].setFontSize(24);
+ tr3.getTextRuns()[0].setIndentLevel(1);
box3.setAnchor(new Rectangle(36, 265, 648, 150));
slide.addShape(box3);
HSLFTextBox box4 = new HSLFTextBox();
- HSLFTextParagraph tr4 = box4.getTextParagraph();
+ HSLFTextParagraph tr4 = box4.getTextParagraphs();
tr4.setRunType(TextHeaderAtom.BODY_TYPE);
tr4.setText("Access to low level data structures");
box4.setAnchor(new Rectangle(36, 430, 648, 50));
for (int j = 0; j < txt1[i].length; j++) {
TableCell cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
- cell.getTextParagraph().getRichTextRuns()[0].setFontSize(10);
- HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0];
+ cell.getTextParagraphs().getTextRuns()[0].setFontSize(10);
+ HSLFTextRun rt = cell.getTextParagraphs().getTextRuns()[0];
rt.setFontName("Arial");
rt.setBold(true);
if(i == 0){
HSLFTextBox box1 = new HSLFTextBox();
box1.setHorizontalAlignment(HSLFTextBox.AlignCenter);
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setText("The source code is available at\r" +
"http://people.apache.org/~yegor/apachecon_eu08/");
- HSLFTextRun rt = tr1.getRichTextRuns()[0];
+ HSLFTextRun rt = tr1.getTextRuns()[0];
rt.setFontSize(24);
box1.setAnchor(new Rectangle(80, 356, 553, 65));
slide.addShape(box1);
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("HSLF in Action - 1\rData Extraction");
box1.setAnchor(new Rectangle(36, 21, 648, 100));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.BODY_TYPE);
tr2.setText(
"Text from slides and notes\r" +
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("HSLF in Action - 2");
box1.setAnchor(new Rectangle(36, 20, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
- tr2.getRichTextRuns()[0].setFontSize(18);
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
+ tr2.getTextRuns()[0].setFontSize(18);
tr2.setText("Creating a simple presentation from scratch");
box2.setAnchor(new Rectangle(170, 100, 364, 30));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextParagraph tr3 = box3.getTextParagraph();
- HSLFTextRun rt3 = tr3.getRichTextRuns()[0];
+ HSLFTextParagraph tr3 = box3.getTextParagraphs();
+ HSLFTextRun rt3 = tr3.getTextRuns()[0];
rt3.setFontName("Courier New");
rt3.setFontSize(8);
tr3.setText(
HSLFTextBox box2 = new HSLFTextBox();
box2.setHorizontalAlignment(HSLFTextBox.AlignCenter);
box2.setVerticalAlignment(HSLFTextBox.AnchorMiddle);
- box2.getTextParagraph().setText("Java Code");
+ box2.getTextParagraphs().setText("Java Code");
box2.getFill().setForegroundColor(new Color(187, 224, 227));
box2.setLineColor(Color.black);
box2.setLineWidth(0.75);
HSLFTextBox box3 = new HSLFTextBox();
box3.setHorizontalAlignment(HSLFTextBox.AlignCenter);
box3.setVerticalAlignment(HSLFTextBox.AnchorMiddle);
- box3.getTextParagraph().setText("*.ppt file");
+ box3.getTextParagraphs().setText("*.ppt file");
box3.setLineWidth(0.75);
box3.setLineColor(Color.black);
box3.getFill().setForegroundColor(new Color(187, 224, 227));
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("Wait, there is more!");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.BODY_TYPE);
tr2.setText(
"Rich text\r" +
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("HSLF in Action - 3");
box1.setAnchor(new Rectangle(36, 20, 648, 50));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
- tr2.getRichTextRuns()[0].setFontSize(18);
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
+ tr2.getTextRuns()[0].setFontSize(18);
tr2.setText("PPGraphics2D: PowerPoint Graphics2D driver");
box2.setAnchor(new Rectangle(178, 70, 387, 30));
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextParagraph tr3 = box3.getTextParagraph();
- HSLFTextRun rt3 = tr3.getRichTextRuns()[0];
+ HSLFTextParagraph tr3 = box3.getTextParagraphs();
+ HSLFTextRun rt3 = tr3.getTextRuns()[0];
rt3.setFontName("Courier New");
rt3.setFontSize(8);
tr3.setText(
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.TITLE_TYPE);
tr1.setText("HSLF Development Plans");
box1.setAnchor(new Rectangle(36, 21, 648, 90));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.BODY_TYPE);
- tr2.getRichTextRuns()[0].setFontSize(32);
+ tr2.getTextRuns()[0].setFontSize(32);
tr2.setText(
"Support for more PowerPoint functionality\r" +
"Rendering slides into java.awt.Graphics2D");
slide.addShape(box2);
HSLFTextBox box3 = new HSLFTextBox();
- HSLFTextParagraph tr3 = box3.getTextParagraph();
+ HSLFTextParagraph tr3 = box3.getTextParagraphs();
tr3.setRunType(TextHeaderAtom.BODY_TYPE);
- tr3.getRichTextRuns()[0].setIndentLevel(1);
+ tr3.getTextRuns()[0].setIndentLevel(1);
tr3.setText(
"A way to export slides into images or other formats");
box3.setAnchor(new Rectangle(36, 220, 648, 70));
slide.addShape(box3);
HSLFTextBox box4 = new HSLFTextBox();
- HSLFTextParagraph tr4 = box4.getTextParagraph();
+ HSLFTextParagraph tr4 = box4.getTextParagraphs();
tr4.setRunType(TextHeaderAtom.BODY_TYPE);
- tr4.getRichTextRuns()[0].setFontSize(32);
+ tr4.getTextRuns()[0].setFontSize(32);
tr4.setText(
"Integration with Apache FOP - Formatting Objects Processor");
box4.setAnchor(new Rectangle(36, 290, 648, 90));
slide.addShape(box4);
HSLFTextBox box5 = new HSLFTextBox();
- HSLFTextParagraph tr5 = box5.getTextParagraph();
+ HSLFTextParagraph tr5 = box5.getTextParagraphs();
tr5.setRunType(TextHeaderAtom.BODY_TYPE);
- tr5.getRichTextRuns()[0].setIndentLevel(1);
+ tr5.getTextRuns()[0].setIndentLevel(1);
tr5.setText(
"Transformation of XSL-FO into PPT\r" +
"PPT2PDF transcoder");
HSLFSlide slide = ppt.createSlide();
HSLFTextBox box1 = new HSLFTextBox();
- HSLFTextParagraph tr1 = box1.getTextParagraph();
+ HSLFTextParagraph tr1 = box1.getTextParagraphs();
tr1.setRunType(TextHeaderAtom.CENTER_TITLE_TYPE);
tr1.setText("Questions?");
box1.setAnchor(new Rectangle(54, 167, 612, 115));
slide.addShape(box1);
HSLFTextBox box2 = new HSLFTextBox();
- HSLFTextParagraph tr2 = box2.getTextParagraph();
+ HSLFTextParagraph tr2 = box2.getTextParagraphs();
tr2.setRunType(TextHeaderAtom.CENTRE_BODY_TYPE);
tr2.setText(
"http://poi.apache.org/hslf/\r" +
package org.apache.poi.hslf.examples;
-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 org.apache.poi.hslf.usermodel.*;
import java.io.FileOutputStream;
HSLFSlide slide = ppt.createSlide();
HSLFTextBox shape = new HSLFTextBox();
- HSLFTextRun rt = shape.getTextParagraph().getRichTextRuns()[0];
+ HSLFTextRun rt = shape.getTextParagraphs().getTextRuns()[0];
shape.setText(
"January\r" +
"February\r" +
package org.apache.poi.hslf.examples;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.model.*;
import java.io.FileOutputStream;
textBox1.setAnchor(new Rectangle(100, 100, 200, 50));
String text = textBox1.getText();
- Hyperlink link = new Hyperlink();
+ HSLFHyperlink link = new HSLFHyperlink();
link.setAddress("http://www.apache.org");
link.setTitle(textBox1.getText());
int linkId = ppt.addHyperlink(link);
textBox2.setText("Go to slide #3");
textBox2.setAnchor(new Rectangle(100, 300, 200, 50));
- Hyperlink link2 = new Hyperlink();
+ HSLFHyperlink link2 = new HSLFHyperlink();
link2.setAddress(slideC);
ppt.addHyperlink(link2);
package org.apache.poi.hslf.examples;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.model.*;
import java.awt.*;
==================================================================== */
package org.apache.poi.hslf.examples;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hslf.model.HeadersFooters;
-import org.apache.poi.hslf.model.HSLFSlide;
import java.io.FileOutputStream;
package org.apache.poi.hslf.examples;
-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;
+import org.apache.poi.hslf.usermodel.*;
import java.io.FileInputStream;
//read hyperlinks from the slide's text runs
System.out.println("reading hyperlinks from the text runs");
- HSLFTextParagraph[] txt = slide[j].getTextRuns();
+ HSLFTextParagraph[] txt = slide[j].getTextParagraphs();
for (int k = 0; k < txt.length; k++) {
- String text = txt[k].getText();
- Hyperlink[] links = txt[k].getHyperlinks();
+ String text = txt[k].getRawText();
+ HSLFHyperlink[] links = txt[k].getHyperlinks();
if(links != null) for (int l = 0; l < links.length; l++) {
- Hyperlink link = links[l];
+ HSLFHyperlink link = links[l];
String title = link.getTitle();
String address = link.getAddress();
System.out.println(" " + title);
System.out.println(" reading hyperlinks from the slide's shapes");
HSLFShape[] sh = slide[j].getShapes();
for (int k = 0; k < sh.length; k++) {
- Hyperlink link = sh[k].getHyperlink();
+ HSLFHyperlink link = sh[k].getHyperlink();
if(link != null) {
String title = link.getTitle();
String address = link.getAddress();
import org.apache.poi.hslf.model.*;
import javax.imageio.ImageIO;
+
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.awt.*;
import org.apache.poi.hslf.record.InteractiveInfoAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.usermodel.*;
+
import java.io.FileInputStream;
import java.util.Iterator;
import java.util.List;
package org.apache.poi.hslf.examples;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.model.*;
import java.awt.*;
for (int j = 0; j < txt1[i].length; j++) {
TableCell cell = table1.getCell(i, j);
cell.setText(txt1[i][j]);
- HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0];
+ HSLFTextRun rt = cell.getTextParagraphs().getTextRuns()[0];
rt.setFontName("Arial");
rt.setFontSize(10);
if(i == 0){
for (int j = 0; j < txt2[i].length; j++) {
TableCell cell = table2.getCell(i, j);
cell.setText(txt2[i][j]);
- HSLFTextRun rt = cell.getTextParagraph().getRichTextRuns()[0];
+ HSLFTextRun rt = cell.getTextParagraphs().getTextRuns()[0];
rt.setFontSize(10);
rt.setFontName("Arial");
if(i == 0){
import org.apache.poi.poifs.filesystem.Entry;\r
import org.apache.poi.poifs.filesystem.POIFSFileSystem;\r
import org.apache.poi.hwpf.HWPFDocument;\r
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;\r
import org.apache.poi.hslf.usermodel.HSLFSlideShow;\r
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;\r
\r
import java.io.FileInputStream;\r
import java.util.Iterator;\r
for(XSLFTextParagraph p : tsh){
System.out.println("Paragraph level: " + p.getLevel());
for(XSLFTextRun r : p){
- System.out.println(r.getText());
+ System.out.println(r.getRawText());
System.out.println(" bold: " + r.isBold());
System.out.println(" italic: " + r.isItalic());
- System.out.println(" underline: " + r.isUnderline());
+ System.out.println(" underline: " + r.isUnderlined());
System.out.println(" font.family: " + r.getFontFamily());
System.out.println(" font.size: " + r.getFontSize());
System.out.println(" font.color: " + r.getFontColor());
import org.apache.poi.openxml4j.opc.OPCPackage;\r
import org.apache.poi.openxml4j.opc.PackagePart;\r
import org.apache.poi.xwpf.usermodel.XWPFDocument;\r
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;\r
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;\r
import org.apache.poi.hwpf.HWPFDocument;\r
import org.apache.poi.xslf.XSLFSlideShow;\r
import org.apache.poi.hssf.usermodel.HSSFWorkbook;\r
import java.io.FileInputStream;
import java.io.InputStream;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.junit.Test;
public class HSLFFileHandler extends POIFSFileHandler {
package org.apache.poi.ddf;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
+import java.util.*;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
}
public Iterator<EscherRecord> getChildIterator() {
- return new ReadOnlyIterator(_childRecords);
+ return Collections.unmodifiableList(_childRecords).iterator();
}
- private static final class ReadOnlyIterator implements Iterator<EscherRecord> {
- private final List<EscherRecord> _list;
- private int _index;
- public ReadOnlyIterator(List<EscherRecord> list) {
- _list = list;
- _index = 0;
- }
-
- public boolean hasNext() {
- return _index < _list.size();
- }
- public EscherRecord next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return _list.get(_index++);
- }
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
/**
* replaces the internal child list with the contents of the supplied <tt>childRecords</tt>
*/
package org.apache.poi.xslf.extractor;
import java.io.IOException;
+import java.util.List;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
public String getText(boolean slideText, boolean notesText, boolean masterText) {
StringBuffer text = new StringBuffer();
- XSLFSlide[] slides = slideshow.getSlides();
+ List<XSLFSlide> slides = slideshow.getSlides();
XSLFCommentAuthors commentAuthors = slideshow.getCommentAuthors();
for (XSLFSlide slide : slides) {
package org.apache.poi.xslf.usermodel;
import java.awt.Dimension;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.io.*;
+import java.util.*;
import java.util.regex.Pattern;
-import org.apache.poi.POIXMLDocument;
-import org.apache.poi.POIXMLDocumentPart;
-import org.apache.poi.POIXMLException;
-import org.apache.poi.POIXMLRelation;
+import org.apache.poi.*;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.openxml4j.opc.PackagePartName;
-import org.apache.poi.openxml4j.opc.TargetMode;
-import org.apache.poi.sl.usermodel.MasterSheet;
-import org.apache.poi.sl.usermodel.Resources;
-import org.apache.poi.sl.usermodel.SlideShow;
-import org.apache.poi.util.Beta;
-import org.apache.poi.util.IOUtils;
-import org.apache.poi.util.Internal;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.util.PackageHelper;
-import org.apache.poi.util.Units;
+import org.apache.poi.openxml4j.opc.*;
+import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.util.*;
import org.apache.poi.xslf.XSLFSlideShow;
-import org.apache.xmlbeans.XmlException;
-import org.apache.xmlbeans.XmlObject;
-import org.apache.xmlbeans.XmlOptions;
+import org.apache.xmlbeans.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextParagraphProperties;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdList;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdListEntry;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTPresentation;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdList;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideSize;
-import org.openxmlformats.schemas.presentationml.x2006.main.PresentationDocument;
-
-import sun.reflect.generics.reflectiveObjects.NotImplementedException;
-
-import com.sun.org.apache.xml.internal.utils.UnImplNode;
+import org.openxmlformats.schemas.presentationml.x2006.main.*;
/**
* High level representation of a ooxml slideshow.
XSLFTheme theme = (XSLFTheme) createRelationship(XSLFRelation.THEME,
XSLFFactory.getInstance(), themeIndex);
- theme.importTheme(getSlides()[0].getTheme());
+ theme.importTheme(getSlides().get(0).getTheme());
_notesMaster.addRelation(theme.getPackageRelationship().getId(), theme);
PackagePartName themePackagePartName = theme.getPackagePart().getPartName();
return _notesMaster;
}
- public XSLFSlideMaster[] getSlideMasters() {
- return _masters.values().toArray(new XSLFSlideMaster[_masters.size()]);
+ @Override
+ public List<XSLFSlideMaster> getSlideMasters() {
+ return new ArrayList<XSLFSlideMaster>(_masters.values());
}
/**
* Return all the slides in the slideshow
*/
- public XSLFSlide[] getSlides() {
- return _slides.toArray(new XSLFSlide[_slides.size()]);
+ public List<XSLFSlide> getSlides() {
+ return _slides;
}
/**
return null;
}
- public XSLFSlideMaster[] getMasterSheet() {
- return getSlideMasters();
- }
-
public MasterSheet createMasterSheet() throws IOException {
// TODO: implement!
throw new UnsupportedOperationException();
import org.apache.poi.openxml4j.opc.*;\r
import org.apache.poi.sl.usermodel.PlaceableShape;\r
import org.apache.poi.sl.usermodel.ShapeGroup;\r
-import org.apache.poi.util.Beta;\r
-import org.apache.poi.util.Units;\r
+import org.apache.poi.util.*;\r
import org.apache.xmlbeans.XmlObject;\r
import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
import org.openxmlformats.schemas.presentationml.x2006.main.*;\r
*/\r
@Beta\r
public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, ShapeGroup<XSLFShape> {\r
+ private static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class);\r
+ \r
private final List<XSLFShape> _shapes;\r
private final CTGroupShapeProperties _grpSpPr;\r
private XSLFDrawing _drawing;\r
*\r
* @return child shapes contained witin this group\r
*/\r
- public XSLFShape[] getShapes(){\r
- return _shapes.toArray(new XSLFShape[_shapes.size()]);\r
+ @Override\r
+ public List<XSLFShape> getShapes(){\r
+ return _shapes;\r
}\r
\r
/**\r
return sh;\r
}\r
\r
+ public XSLFTable createTable(){\r
+ XSLFTable sh = getDrawing().createTable();\r
+ _shapes.add(sh);\r
+ sh.setParent(this);\r
+ return sh;\r
+ }\r
+ \r
@Override\r
public void setFlipHorizontal(boolean flip){\r
getSafeXfrm().setFlipH(flip);\r
@Override\r
void copy(XSLFShape src){\r
XSLFGroupShape gr = (XSLFGroupShape)src;\r
+ \r
+ // clear shapes\r
+ clear();\r
+ \r
// recursively update each shape\r
- XSLFShape[] tgtShapes = getShapes();\r
- XSLFShape[] srcShapes = gr.getShapes();\r
- for(int i = 0; i < tgtShapes.length; i++){\r
- XSLFShape s1 = srcShapes[i];\r
- XSLFShape s2 = tgtShapes[i];\r
-\r
- s2.copy(s1);\r
+ for(XSLFShape shape : gr.getShapes()) {\r
+ XSLFShape newShape = null;\r
+ if (shape instanceof XSLFTextBox) {\r
+ newShape = createTextBox();\r
+ } else if (shape instanceof XSLFAutoShape) {\r
+ newShape = createAutoShape();\r
+ } else if (shape instanceof XSLFConnectorShape) {\r
+ newShape = createConnector();\r
+ } else if (shape instanceof XSLFFreeformShape) {\r
+ newShape = createFreeform();\r
+ } else if (shape instanceof XSLFPictureShape) {\r
+ XSLFPictureShape p = (XSLFPictureShape)shape;\r
+ XSLFPictureData pd = p.getPictureData();\r
+ int picId = getSheet().getSlideShow().addPicture(pd.getData(), pd.getPictureType());\r
+ newShape = createPicture(picId);\r
+ } else if (shape instanceof XSLFGroupShape) {\r
+ newShape = createGroup();\r
+ } else if (shape instanceof XSLFTable) {\r
+ newShape = createTable();\r
+ } else {\r
+ _logger.log(POILogger.WARN, "copying of class "+shape.getClass()+" not supported.");\r
+ continue;\r
+ }\r
+\r
+ newShape.copy(shape);\r
}\r
}\r
\r
}
@Override
- public List<XSLFTextParagraph> getTextParagraphs() {
- List<XSLFTextParagraph> tp = new ArrayList<XSLFTextParagraph>();
+ public List<List<XSLFTextParagraph>> getTextParagraphs() {
+ List<List<XSLFTextParagraph>> tp = new ArrayList<List<XSLFTextParagraph>>();
for (XSLFShape sh : super.getShapes()) {
if (sh instanceof XSLFTextShape) {
XSLFTextShape txt = (XSLFTextShape)sh;
- tp.addAll(txt.getTextParagraphs());
+ tp.add(txt.getTextParagraphs());
}
}
return tp;
*
* @return an array of all shapes in this sheet
*/
- public XSLFShape[] getShapes(){
- return getShapeList().toArray(new XSLFShape[_shapes.size()]);
+ public List<XSLFShape> getShapes(){
+ return getShapeList();
}
/**
_spTree = null;
_placeholders = null;
+ // fix-me: wth would this ever happen to work ...
+
+
// first copy the source xml
getSpTree().set(src.getSpTree());
import org.openxmlformats.schemas.presentationml.x2006.main.*;
@Beta
-public final class XSLFSlide extends XSLFSheet implements Slide<XSLFShape, XMLSlideShow> {
+public final class XSLFSlide extends XSLFSheet implements Slide<XSLFShape, XMLSlideShow, XSLFNotes> {
private final CTSlide _slide;
private XSLFSlideLayout _layout;
private XSLFComments _comments;
throw new UnsupportedOperationException();
}
- public void setNotes(Notes<XSLFShape,XMLSlideShow> notes) {
+ public void setNotes(XSLFNotes notes) {
// TODO Auto-generated method stub
}
public String getText(){\r
StringBuilder out = new StringBuilder();\r
for (XSLFTextRun r : _runs) {\r
- out.append(r.getText());\r
+ out.append(r.getRawText());\r
}\r
return out.toString();\r
}\r
}\r
}\r
\r
+ @Override\r
+ public FontAlign getFontAlign(){\r
+ ParagraphPropertyFetcher<FontAlign> fetcher = new ParagraphPropertyFetcher<FontAlign>(getLevel()){\r
+ public boolean fetch(CTTextParagraphProperties props){\r
+ if(props.isSetFontAlgn()){\r
+ FontAlign val = FontAlign.values()[props.getFontAlgn().intValue() - 1];\r
+ setValue(val);\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ };\r
+ fetchParagraphProperty(fetcher);\r
+ return fetcher.getValue() == null ? FontAlign.AUTO : fetcher.getValue();\r
+ }\r
+\r
+ /**\r
+ * Specifies the font alignment that is to be applied to the paragraph.\r
+ * Possible values for this include auto, top, center, baseline and bottom.\r
+ * see {@link org.apache.poi.sl.usermodel.TextParagraph.FontAlign}.\r
+ *\r
+ * @param align font align\r
+ */\r
+ public void setFontAlign(FontAlign align){\r
+ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+ if(align == null) {\r
+ if(pr.isSetFontAlgn()) pr.unsetFontAlgn();\r
+ } else {\r
+ pr.setFontAlgn(STTextFontAlignType.Enum.forInt(align.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ \r
\r
/**\r
* @return the font to be used on bullet characters within a given paragraph\r
*\r
* @param value the indent in points. \r
*/\r
+ @Override\r
public void setIndent(double value){\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
if(value == -1) {\r
*\r
* @return the indent applied to the first line of text in the paragraph.\r
*/\r
+ @Override\r
public double getIndent(){\r
\r
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){\r
* inset and applies only to this text paragraph. That is the text body Inset and the LeftMargin\r
* attributes are additive with respect to the text position.\r
*\r
- * @param value the left margin of the paragraph\r
+ * @param value the left margin (in points) of the paragraph\r
*/\r
+ @Override\r
public void setLeftMargin(double value){\r
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
if(value == -1) {\r
}\r
\r
/**\r
- *\r
- * @return the left margin of the paragraph\r
+ * @return the left margin (in points) of the paragraph\r
*/\r
+ @Override\r
public double getLeftMargin(){\r
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){\r
public boolean fetch(CTTextParagraphProperties props){\r
return fetcher.getValue() == null ? 0 : fetcher.getValue();\r
}\r
\r
+ /**\r
+ * Specifies the right margin of the paragraph. This is specified in addition to the text body\r
+ * inset and applies only to this text paragraph. That is the text body Inset and the RightMargin\r
+ * attributes are additive with respect to the text position.\r
+ *\r
+ * @param value the right margin (in points) of the paragraph\r
+ */\r
+ @Override\r
+ public void setRightMargin(double value){\r
+ CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();\r
+ if(value == -1) {\r
+ if(pr.isSetMarR()) pr.unsetMarR();\r
+ } else {\r
+ pr.setMarR(Units.toEMU(value));\r
+ }\r
+ }\r
+\r
/**\r
*\r
* @return the right margin of the paragraph\r
*/\r
+ @Override\r
public double getRightMargin(){\r
ParagraphPropertyFetcher<Double> fetcher = new ParagraphPropertyFetcher<Double>(getLevel()){\r
public boolean fetch(CTTextParagraphProperties props){\r
}\r
}\r
\r
+ @Override\r
public double getDefaultFontSize() {\r
CTTextCharacterProperties endPr = _p.getEndParaRPr();\r
return (endPr == null || !endPr.isSetSz()) ? 12 : (endPr.getSz() / 100);\r
}\r
\r
+ @Override\r
public String getDefaultFontFamily() {\r
return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily());\r
}\r
return _p;\r
}\r
\r
- public String getText(){\r
+ public String getRawText(){\r
return _r.getT();\r
}\r
\r
/**\r
* @return whether this run of text is formatted as underlined text\r
*/\r
- public boolean isUnderline(){\r
+ public boolean isUnderlined(){\r
CharacterPropertyFetcher<Boolean> fetcher = new CharacterPropertyFetcher<Boolean>(_p.getLevel()){\r
public boolean fetch(CTTextCharacterProperties props){\r
if(props.isSetU()){\r
\r
@Override\r
public String toString(){\r
- return "[" + getClass() + "]" + getText();\r
+ return "[" + getClass() + "]" + getRawText();\r
}\r
\r
public XSLFHyperlink createHyperlink(){\r
boolean italic = r.isItalic();\r
if(italic != isItalic()) setItalic(italic);\r
\r
- boolean underline = r.isUnderline();\r
- if(underline != isUnderline()) setUnderline(underline);\r
+ boolean underline = r.isUnderlined();\r
+ if(underline != isUnderlined()) setUnderline(underline);\r
\r
boolean strike = r.isStrikethrough();\r
if(strike != isStrikethrough()) setStrikethrough(strike);\r
* Sets the type of vertical alignment for the text.
*
* @param anchor - the type of alignment.
- * A <code>null</code> values unsets this property.
+ * A {@code null} values unsets this property.
*/
public void setVerticalAlignment(VerticalAlignment anchor){
CTTextBodyProperties bodyPr = getTextBodyPr();
return fetcher.getValue() == null ? VerticalAlignment.TOP : fetcher.getValue();
}
+ /**
+ * Sets if the paragraphs are horizontal centered
+ *
+ * @param isCentered true, if the paragraphs are horizontal centered
+ * A {@code null} values unsets this property.
+ *
+ * @see TextShape#isHorizontalCentered()
+ */
+ public void setHorizontalCentered(Boolean isCentered){
+ CTTextBodyProperties bodyPr = getTextBodyPr();
+ if (bodyPr != null) {
+ if (isCentered == null) {
+ if (bodyPr.isSetAnchorCtr()) bodyPr.unsetAnchorCtr();
+ } else {
+ bodyPr.setAnchorCtr(isCentered);
+ }
+ }
+ }
+
+ @Override
+ public boolean isHorizontalCentered(){
+ PropertyFetcher<Boolean> fetcher = new TextBodyPropertyFetcher<Boolean>(){
+ public boolean fetch(CTTextBodyProperties props){
+ if(props.isSetAnchorCtr()){
+ setValue(props.getAnchorCtr());
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+ return fetcher.getValue() == null ? false : fetcher.getValue();
+ }
+
/**
*
* @param orientation vertical orientation of the text
}
/**
- * Sets the botom margin.
+ * Sets the bottom margin.
* @see #getBottomInset()
*
* @param margin the bottom margin
}
}
- /**
- * Compute the cumulative height occupied by the text
- */
+ @Override
public double getTextHeight(){
DrawFactory drawFact = DrawFactory.getInstance(null);
DrawTextShape<XSLFTextShape> dts = drawFact.getDrawable(this);
import org.apache.poi.xslf.usermodel.XSLFSlide;\r
\r
import javax.imageio.ImageIO;\r
+\r
import java.awt.Color;\r
import java.awt.Dimension;\r
import java.awt.Graphics2D;\r
import java.awt.RenderingHints;\r
import java.awt.image.BufferedImage;\r
import java.io.FileOutputStream;\r
+import java.util.List;\r
\r
/**\r
* An utulity to convert slides of a .pptx slide show to a PNG image\r
int width = (int) (pgsize.width * scale);\r
int height = (int) (pgsize.height * scale);\r
\r
- XSLFSlide[] slide = ppt.getSlides();\r
- for (int i = 0; i < slide.length; i++) {\r
+ List<XSLFSlide> slide = ppt.getSlides();\r
+ for (int i = 0; i < slide.size(); i++) {\r
if (slidenum != -1 && slidenum != (i + 1)) continue;\r
\r
- String title = slide[i].getTitle();\r
+ String title = slide.get(i).getTitle();\r
System.out.println("Rendering slide " + (i + 1) + (title == null ? "" : ": " + title));\r
\r
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);\r
graphics.scale(scale, scale);\r
\r
// draw stuff\r
- slide[i].draw(graphics);\r
+ slide.get(i).draw(graphics);\r
\r
// save the result\r
int sep = file.lastIndexOf(".");\r
public void bug51187() throws Exception {
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("51187.pptx");
- assertEquals(1, ss.getSlides().length);
- XSLFSlide slide = ss.getSlides()[0];
+ assertEquals(1, ss.getSlides().size());
+ XSLFSlide slide = ss.getSlides().get(0);
// Check the relations on it
// Note - rId3 is a self reference
// Save and re-load
ss = XSLFTestDataSamples.writeOutAndReadBack(ss);
- assertEquals(1, ss.getSlides().length);
+ assertEquals(1, ss.getSlides().size());
slidePart = ss._getXSLFSlideShow().getSlidePart(
ss._getXSLFSlideShow().getSlideReferences().getSldIdArray(0)
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("with_japanese.pptx");
// Should have one slide
- assertEquals(1, ss.getSlides().length);
- XSLFSlide slide = ss.getSlides()[0];
+ assertEquals(1, ss.getSlides().size());
+ XSLFSlide slide = ss.getSlides().get(0);
// Check the relations from this
List<POIXMLDocumentPart> rels = slide.getRelations();
XSLFSlide slide;
// Should find 4 slides
- assertEquals(4, ss.getSlides().length);
+ assertEquals(4, ss.getSlides().size());
// Check the text, to see we got them in order
- slide = ss.getSlides()[0];
+ slide = ss.getSlides().get(0);
assertContains("POI cannot read this", getSlideText(slide));
- slide = ss.getSlides()[1];
+ slide = ss.getSlides().get(1);
assertContains("POI can read this", getSlideText(slide));
assertContains("Has a relationship to another slide", getSlideText(slide));
- slide = ss.getSlides()[2];
+ slide = ss.getSlides().get(2);
assertContains("POI can read this", getSlideText(slide));
- slide = ss.getSlides()[3];
+ slide = ss.getSlides().get(3);
assertContains("POI can read this", getSlideText(slide));
}
}
@Test
- @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix")
+ // @Ignore("Similar to TestFontRendering it doesn't make sense to compare images because of tiny rendering differences in windows/unix")
public void bug54542() throws Exception {
XMLSlideShow ss = XSLFTestDataSamples.openSampleDocument("54542_cropped_bitmap.pptx");
Dimension pgsize = ss.getPageSize();
- XSLFSlide slide = ss.getSlides()[0];
+ XSLFSlide slide = ss.getSlides().get(0);
// render it
double zoom = 1;
ss = XSLFTestDataSamples.writeOutAndReadBack(ss);
}
- assertEquals(slideTexts.length, ss.getSlides().length);
+ assertEquals(slideTexts.length, ss.getSlides().size());
for (int i = 0; i < slideTexts.length; i++) {
- XSLFSlide slide = ss.getSlides()[i];
+ XSLFSlide slide = ss.getSlides().get(i);
assertContains(getSlideText(slide), slideTexts[i]);
}
}
*/
package org.apache.poi.xslf.geom;
-import junit.framework.TestCase;
-import org.apache.poi.xslf.model.geom.Context;
-import org.apache.poi.xslf.model.geom.CustomGeometry;
-import org.apache.poi.xslf.model.geom.Formula;
-import org.apache.poi.xslf.model.geom.Guide;
-import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
+import org.apache.poi.sl.draw.geom.*;
+import org.junit.Test;
/**
* Date: 10/24/11
*
* @author Yegor Kozlov
*/
-public class TestFormulaParser extends TestCase {
+public class TestFormulaParser {
+ @Test
public void testParse(){
Formula[] ops = {
new Guide("a5", "abs -2"),
};
- CustomGeometry geom = new CustomGeometry(CTCustomGeometry2D.Factory.newInstance());
+ CustomGeometry geom = new CustomGeometry(new CTCustomGeometry2D());
Context ctx = new Context(geom, null, null);
for(Formula fmla : ops) {
ctx.evaluate(fmla);
}
- assertEquals(100.0, ctx.getValue("adj1"));
- assertEquals(200.0, ctx.getValue("adj2"));
- assertEquals(1.0, ctx.getValue("a1"));
- assertEquals(101.0, ctx.getValue("a2"));
- assertEquals(1.5, ctx.getValue("a3"));
- assertEquals(200.0, ctx.getValue("a4"));
- assertEquals(2.0, ctx.getValue("a5"));
+ assertEquals(100.0, ctx.getValue("adj1"), 0.0);
+ assertEquals(200.0, ctx.getValue("adj2"), 0.0);
+ assertEquals(1.0, ctx.getValue("a1"), 0.0);
+ assertEquals(101.0, ctx.getValue("a2"), 0.0);
+ assertEquals(1.5, ctx.getValue("a3"), 0.0);
+ assertEquals(200.0, ctx.getValue("a4"), 0.0);
+ assertEquals(2.0, ctx.getValue("a5"), 0.0);
}
}
*/
package org.apache.poi.xslf.geom;
-import junit.framework.TestCase;
-import org.apache.poi.xslf.model.geom.Context;
-import org.apache.poi.xslf.model.geom.CustomGeometry;
-import org.apache.poi.xslf.model.geom.Guide;
-import org.apache.poi.xslf.model.geom.IAdjustableShape;
-import org.apache.poi.xslf.model.geom.Path;
-import org.apache.poi.xslf.model.geom.PresetGeometries;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.util.Map;
+import org.apache.poi.sl.draw.geom.*;
+import org.junit.Test;
+
/**
* Date: 10/24/11
*
* @author Yegor Kozlov
*/
-public class TestPresetGeometries extends TestCase {
+public class TestPresetGeometries {
+ @Test
public void testRead(){
Map<String, CustomGeometry> shapes = PresetGeometries.getInstance();
import java.util.HashMap;\r
import java.util.Map;\r
\r
-import org.apache.poi.hslf.model.TextPainter;\r
+import org.apache.poi.sl.draw.Drawable;\r
import org.apache.poi.util.JvmBugs;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
import org.junit.Test;\r
@SuppressWarnings("unchecked")\r
private void fixFonts(Graphics2D graphics) {\r
if (!JvmBugs.hasLineBreakMeasurerBug()) return;\r
- Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(TextPainter.KEY_FONTMAP);\r
+ Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);\r
if (fontMap == null) fontMap = new HashMap<String,String>();\r
fontMap.put("Calibri", "Lucida Sans");\r
fontMap.put("Cambria", "Lucida Bright");\r
- graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap); \r
+ graphics.setRenderingHint(Drawable.FONT_MAP, fontMap); \r
}\r
}\r
==================================================================== */
package org.apache.poi.xslf.usermodel;
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTNotesMasterIdListEntry;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideIdListEntry;
-import org.openxmlformats.schemas.presentationml.x2006.main.CTSlideMasterIdListEntry;
+import org.junit.Before;
+import org.junit.Test;
+import org.openxmlformats.schemas.presentationml.x2006.main.*;
-public class TestXMLSlideShow extends TestCase {
+public class TestXMLSlideShow {
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
private OPCPackage pack;
- protected void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
pack = OPCPackage.open(slTests.openResourceAsStream("sample.pptx"));
}
+ @Test
public void testContainsMainContentType() throws Exception {
boolean found = false;
for(PackagePart part : pack.getParts()) {
assertTrue(found);
}
+ @Test
public void testOpen() throws Exception {
XMLSlideShow xml;
assertNotNull(xml.getCTPresentation());
// Check it has some slides
- assertNotNull(xml.getSlides().length);
- assertTrue(xml.getSlides().length > 0);
-
- assertNotNull(xml.getSlideMasters().length);
- assertTrue(xml.getSlideMasters().length > 0);
+ assertFalse(xml.getSlides().isEmpty());
+ assertFalse(xml.getSlideMasters().isEmpty());
}
+ @Test
@SuppressWarnings("deprecation")
public void testSlideBasics() throws Exception {
XMLSlideShow xml = new XMLSlideShow(pack);
// Should have 1 master
- assertEquals(1, xml.getSlideMasters().length);
+ assertEquals(1, xml.getSlideMasters().size());
// Should have two sheets
- assertEquals(2, xml.getSlides().length);
+ assertEquals(2, xml.getSlides().size());
// Check they're as expected
CTSlideIdListEntry[] slides = xml.getCTPresentation().getSldIdLst().getSldIdArray();
assertEquals("rId3", slides[1].getId2());
// Now get those objects
- assertNotNull(xml.getSlides()[0]);
- assertNotNull(xml.getSlides()[1]);
+ assertNotNull(xml.getSlides().get(0));
+ assertNotNull(xml.getSlides().get(1));
// And check they have notes as expected
- assertNotNull(xml.getSlides()[0].getNotes());
- assertNotNull(xml.getSlides()[1].getNotes());
+ assertNotNull(xml.getSlides().get(0).getNotes());
+ assertNotNull(xml.getSlides().get(1).getNotes());
// Next up look for the slide master
CTSlideMasterIdListEntry[] masters = xml.getCTPresentation().getSldMasterIdLst().getSldMasterIdArray();
assertEquals(2147483648l, masters[0].getId());
assertEquals("rId1", masters[0].getId2());
- assertNotNull(xml.getSlideMasters()[0]);
+ assertNotNull(xml.getSlideMasters().get(0));
// Finally look for the notes master
CTNotesMasterIdListEntry notesMaster =
assertNotNull(xml.getNotesMaster());
}
+ @Test
public void testMetadataBasics() throws Exception {
XMLSlideShow xml = new XMLSlideShow(pack);
assertEquals(null, xml.getProperties().getCoreProperties().getUnderlyingProperties().getSubjectProperty().getValue());
}
+ @Test
public void testComments() throws Exception {
// Default sample file has none
XMLSlideShow xml = new XMLSlideShow(pack);
assertEquals("XPVMWARE01", xmlComments.getCommentAuthors().getAuthorById(0).getName());
// First two slides have comments
- for (int i=0; i<xmlComments.getSlides().length; i++) {
- XSLFSlide slide = xmlComments.getSlides()[i];
+ int i = -1;
+ for (XSLFSlide slide : xmlComments.getSlides()) {
+ i++;
if(i == 0) {
assertNotNull(slide.getComments());
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
\r
import org.apache.poi.sl.usermodel.*;\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.TextShape.TextAutofit;\r
import org.apache.poi.sl.usermodel.TextShape.TextDirection;\r
import org.apache.poi.util.Units;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextStrikeType;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFAutoShape extends TestCase {\r
+public class TestXSLFAutoShape {\r
+ @Test\r
public void testTextBodyProperies() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
shape.addNewTextParagraph().addNewTextRun().setText("POI");\r
\r
// default margins from slide master\r
- assertEquals(3.6, shape.getBottomInset());\r
- assertEquals(3.6, shape.getTopInset());\r
- assertEquals(7.2, shape.getLeftInset());\r
- assertEquals(7.2, shape.getRightInset());\r
+ assertEquals(3.6, shape.getBottomInset(), 0);\r
+ assertEquals(3.6, shape.getTopInset(), 0);\r
+ assertEquals(7.2, shape.getLeftInset(), 0);\r
+ assertEquals(7.2, shape.getRightInset(), 0);\r
\r
shape.setBottomInset(1.0);\r
- assertEquals(1.0, shape.getBottomInset());\r
+ assertEquals(1.0, shape.getBottomInset(), 0);\r
shape.setTopInset(2.0);\r
- assertEquals(2.0, shape.getTopInset());\r
+ assertEquals(2.0, shape.getTopInset(), 0);\r
shape.setLeftInset(3.0);\r
- assertEquals(3.0, shape.getLeftInset());\r
+ assertEquals(3.0, shape.getLeftInset(), 0);\r
shape.setRightInset(4.0);\r
- assertEquals(4.0, shape.getRightInset());\r
+ assertEquals(4.0, shape.getRightInset(), 0);\r
\r
shape.setBottomInset(0.0);\r
- assertEquals(0.0, shape.getBottomInset());\r
+ assertEquals(0.0, shape.getBottomInset(), 0);\r
shape.setTopInset(0.0);\r
- assertEquals(0.0, shape.getTopInset());\r
+ assertEquals(0.0, shape.getTopInset(), 0);\r
shape.setLeftInset(0.0);\r
- assertEquals(0.0, shape.getLeftInset());\r
+ assertEquals(0.0, shape.getLeftInset(), 0);\r
shape.setRightInset(0.0);\r
- assertEquals(0.0, shape.getRightInset());\r
+ assertEquals(0.0, shape.getRightInset(), 0);\r
\r
// unset to defauls\r
shape.setBottomInset(-1);\r
- assertEquals(3.6, shape.getBottomInset());\r
+ assertEquals(3.6, shape.getBottomInset(), 0);\r
shape.setTopInset(-1);\r
- assertEquals(3.6, shape.getTopInset());\r
+ assertEquals(3.6, shape.getTopInset(), 0);\r
shape.setLeftInset(-1);\r
- assertEquals(7.2, shape.getLeftInset());\r
+ assertEquals(7.2, shape.getLeftInset(), 0);\r
shape.setRightInset(-1);\r
- assertEquals(7.2, shape.getRightInset());\r
+ assertEquals(7.2, shape.getRightInset(), 0);\r
\r
// shape\r
assertTrue(shape.getWordWrap());\r
assertEquals(TextDirection.HORIZONTAL, shape.getTextDirection());\r
}\r
\r
+ @Test\r
public void testTextParagraph() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
- assertEquals(0, slide.getShapes().length);\r
+ assertTrue(slide.getShapes().isEmpty());\r
\r
XSLFAutoShape shape = slide.createAutoShape();\r
assertEquals(0, shape.getTextParagraphs().size());\r
XSLFTextParagraph p = shape.addNewTextParagraph();\r
assertEquals(1, shape.getTextParagraphs().size());\r
\r
- assertEquals(0., p.getIndent());\r
- assertEquals(0., p.getLeftMargin());\r
- assertEquals(100., p.getLineSpacing());\r
- assertEquals(0., p.getSpaceAfter());\r
- assertEquals(0., p.getSpaceBefore());\r
+ assertEquals(0., p.getIndent(), 0);\r
+ assertEquals(0., p.getLeftMargin(), 0);\r
+ assertEquals(100., p.getLineSpacing(), 0);\r
+ assertEquals(0., p.getSpaceAfter(), 0);\r
+ assertEquals(0., p.getSpaceBefore(), 0);\r
assertEquals(0, p.getLevel());\r
\r
p.setIndent(2.0);\r
- assertEquals(2.0, p.getIndent());\r
+ assertEquals(2.0, p.getIndent(), 0);\r
assertTrue(p.getXmlObject().getPPr().isSetIndent());\r
p.setIndent(-1);\r
- assertEquals(0.0, p.getIndent());\r
+ assertEquals(0.0, p.getIndent(), 0);\r
assertFalse(p.getXmlObject().getPPr().isSetIndent());\r
p.setIndent(10.0);\r
- assertEquals(10., p.getIndent());\r
+ assertEquals(10., p.getIndent(), 0);\r
assertTrue(p.getXmlObject().getPPr().isSetIndent());\r
\r
\r
assertEquals(2, p.getLevel());\r
\r
p.setLeftMargin(2.0);\r
- assertEquals(2.0, p.getLeftMargin());\r
+ assertEquals(2.0, p.getLeftMargin(), 0);\r
assertTrue(p.getXmlObject().getPPr().isSetMarL());\r
p.setLeftMargin(10.0);\r
- assertEquals(10., p.getLeftMargin());\r
+ assertEquals(10., p.getLeftMargin(), 0);\r
assertEquals(Units.toEMU(10), p.getXmlObject().getPPr().getMarL());\r
\r
\r
assertFalse(p.getXmlObject().getPPr().isSetAlgn());\r
}\r
\r
+ @Test\r
public void testTextRun() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
assertEquals(1, p.getTextRuns().size());\r
assertSame(r, p.getTextRuns().get(0));\r
\r
- assertEquals(18.0, r.getFontSize()); // default font size for text boxes\r
+ assertEquals(18.0, r.getFontSize(), 0); // default font size for text boxes\r
assertFalse(r.getXmlObject().getRPr().isSetSz());\r
r.setFontSize(10.0);\r
assertTrue(r.getXmlObject().isSetRPr());\r
assertTrue(r.isItalic());\r
assertEquals(true, r.getXmlObject().getRPr().getI());\r
\r
- assertFalse(r.isUnderline());\r
+ assertFalse(r.isUnderlined());\r
assertFalse(r.getXmlObject().getRPr().isSetU());\r
r.setUnderline(true);\r
- assertTrue(r.isUnderline());\r
+ assertTrue(r.isUnderlined());\r
assertEquals(STTextUnderlineType.SNG, r.getXmlObject().getRPr().getU());\r
\r
r.setText("Apache");\r
- assertEquals("Apache", r.getText());\r
+ assertEquals("Apache", r.getRawText());\r
r.setText("POI");\r
- assertEquals("POI", r.getText());\r
+ assertEquals("POI", r.getRawText());\r
r.setText(null);\r
- assertNull(r.getText());\r
+ assertNull(r.getRawText());\r
}\r
\r
+ @Test\r
public void testShapeType() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
String chartTitle = "Apache POI"; // first line is chart title\r
\r
XMLSlideShow pptx = XSLFTestDataSamples.openSampleDocument("pie-chart.pptx");\r
- XSLFSlide slide = pptx.getSlides()[0];\r
+ XSLFSlide slide = pptx.getSlides().get(0);\r
\r
// find chart in the slide\r
XSLFChart chart = null;\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertFalse;\r
+\r
import java.awt.Color;\r
import java.awt.Rectangle;\r
\r
-import junit.framework.TestCase;\r
-\r
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;\r
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;\r
import org.apache.poi.sl.usermodel.*;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFConnectorShape extends TestCase {\r
+public class TestXSLFConnectorShape {\r
\r
+ @Test\r
public void testLineDecorations() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
\r
XSLFConnectorShape shape = slide.createConnector();\r
- assertEquals(1, slide.getShapes().length);\r
+ assertEquals(1, slide.getShapes().size());\r
\r
assertFalse(shape.getSpPr().getLn().isSetHeadEnd());\r
assertFalse(shape.getSpPr().getLn().isSetTailEnd());\r
\r
}\r
\r
+ @Test\r
public void testAddConnector(){\r
XMLSlideShow pptx = new XMLSlideShow();\r
XSLFSlide slide = pptx.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
\r
import java.awt.Rectangle;\r
import java.awt.geom.Ellipse2D;\r
import java.awt.geom.GeneralPath;\r
\r
+import org.junit.Test;\r
+\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFFreeformShape extends TestCase {\r
+public class TestXSLFFreeformShape {\r
\r
+ @Test\r
public void testSetPath() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
\r
import java.awt.Dimension;\r
import java.awt.geom.Rectangle2D;\r
\r
+import org.junit.Test;\r
+\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFGroupShape extends TestCase {\r
+public class TestXSLFGroupShape {\r
\r
+ @Test\r
public void testCreateShapes() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
ppt.setPageSize(new Dimension(792, 612));\r
\r
XSLFGroupShape group = slide.createGroup();\r
- assertEquals(1, slide.getShapes().length);\r
+ assertEquals(1, slide.getShapes().size());\r
\r
Rectangle2D interior = new Rectangle2D.Double(-10, -10, 20, 20);\r
group.setInteriorAnchor(interior);\r
group.setAnchor(anchor);\r
assertEquals(anchor, group.getAnchor());\r
\r
- assertEquals(0, group.getShapes().length);\r
+ assertTrue(group.getShapes().isEmpty());\r
\r
XSLFTextBox shape1 = group.createTextBox();\r
- assertEquals(1, group.getShapes().length);\r
- assertSame(shape1, group.getShapes()[0]);\r
+ assertEquals(1, group.getShapes().size());\r
+ assertSame(shape1, group.getShapes().get(0));\r
assertEquals(3, shape1.getShapeId());\r
\r
XSLFAutoShape shape2 = group.createAutoShape();\r
- assertEquals(2, group.getShapes().length);\r
- assertSame(shape1, group.getShapes()[0]);\r
- assertSame(shape2, group.getShapes()[1]);\r
+ assertEquals(2, group.getShapes().size());\r
+ assertSame(shape1, group.getShapes().get(0));\r
+ assertSame(shape2, group.getShapes().get(1));\r
assertEquals(4, shape2.getShapeId());\r
\r
XSLFConnectorShape shape3 = group.createConnector();\r
- assertEquals(3, group.getShapes().length);\r
- assertSame(shape3, group.getShapes()[2]);\r
+ assertEquals(3, group.getShapes().size());\r
+ assertSame(shape3, group.getShapes().get(2));\r
assertEquals(5, shape3.getShapeId());\r
\r
XSLFGroupShape shape4 = group.createGroup();\r
- assertEquals(4, group.getShapes().length);\r
- assertSame(shape4, group.getShapes()[3]);\r
+ assertEquals(4, group.getShapes().size());\r
+ assertSame(shape4, group.getShapes().get(3));\r
assertEquals(6, shape4.getShapeId());\r
\r
group.removeShape(shape2);\r
- assertEquals(3, group.getShapes().length);\r
- assertSame(shape1, group.getShapes()[0]);\r
- assertSame(shape3, group.getShapes()[1]);\r
- assertSame(shape4, group.getShapes()[2]);\r
+ assertEquals(3, group.getShapes().size());\r
+ assertSame(shape1, group.getShapes().get(0));\r
+ assertSame(shape3, group.getShapes().get(1));\r
+ assertSame(shape4, group.getShapes().get(2));\r
\r
group.removeShape(shape3);\r
- assertEquals(2, group.getShapes().length);\r
- assertSame(shape1, group.getShapes()[0]);\r
- assertSame(shape4, group.getShapes()[1]);\r
+ assertEquals(2, group.getShapes().size());\r
+ assertSame(shape1, group.getShapes().get(0));\r
+ assertSame(shape4, group.getShapes().get(1));\r
\r
group.removeShape(shape1);\r
group.removeShape(shape4);\r
- assertEquals(0, group.getShapes().length);\r
+ assertTrue(group.getShapes().isEmpty());\r
}\r
\r
+ @Test\r
public void testRemoveShapes() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+\r
+import java.net.URI;\r
+import java.util.List;\r
+\r
import org.apache.poi.openxml4j.opc.PackageRelationship;\r
import org.apache.poi.openxml4j.opc.TargetMode;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
-\r
-import java.net.URI;\r
+import org.junit.Test;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFHyperlink extends TestCase {\r
+public class TestXSLFHyperlink {\r
\r
+ @Test\r
public void testRead(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
\r
- XSLFSlide slide = ppt.getSlides()[4];\r
- XSLFShape[] shapes = slide.getShapes();\r
- XSLFTable tbl = (XSLFTable)shapes[0];\r
+ XSLFSlide slide = ppt.getSlides().get(4);\r
+ List<XSLFShape> shapes = slide.getShapes();\r
+ XSLFTable tbl = (XSLFTable)shapes.get(0);\r
XSLFTableCell cell1 = tbl.getRows().get(1).getCells().get(0);\r
assertEquals("Web Page", cell1.getText());\r
XSLFHyperlink link1 = cell1.getTextParagraphs().get(0).getTextRuns().get(0).getHyperlink();\r
assertEquals(URI.create("mailto:dev@poi.apache.org?subject=Hi%20There"), link3.getTargetURI());\r
}\r
\r
+ @Test\r
public void testCreate() throws Exception {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide1 = ppt.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.assertArrayEquals;\r
+import static org.junit.Assert.*;\r
\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-\r
-import junit.framework.TestCase;\r
+import java.util.*;\r
\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFPictureShape extends TestCase {\r
+public class TestXSLFPictureShape {\r
\r
+ @Test\r
public void testCreate() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
assertEquals(0, ppt.getAllPictures().size());\r
assertArrayEquals(data1, pics.get(0).getData());\r
assertArrayEquals(data2, pics.get(1).getData());\r
\r
- XSLFShape[] shapes = ppt.getSlides()[0].getShapes();\r
- assertArrayEquals(data1, ((XSLFPictureShape) shapes[0]).getPictureData().getData());\r
- assertArrayEquals(data2, ((XSLFPictureShape) shapes[1]).getPictureData().getData());\r
+ List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();\r
+ assertArrayEquals(data1, ((XSLFPictureShape) shapes.get(0)).getPictureData().getData());\r
+ assertArrayEquals(data2, ((XSLFPictureShape) shapes.get(1)).getPictureData().getData());\r
}\r
\r
+ @Test\r
public void testCreateMultiplePictures() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide1 = ppt.createSlide();\r
}\r
}\r
\r
+ @Test\r
public void testImageCaching() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
byte[] img1 = new byte[]{1,2,3};\r
\r
}\r
\r
+ @Test\r
public void testMerge() {\r
XMLSlideShow ppt1 = new XMLSlideShow();\r
byte[] data1 = new byte[100];\r
XMLSlideShow ppt2 = new XMLSlideShow();\r
\r
XSLFSlide slide2 = ppt2.createSlide().importContent(slide1);\r
- XSLFPictureShape shape2 = (XSLFPictureShape)slide2.getShapes()[0];\r
+ XSLFPictureShape shape2 = (XSLFPictureShape)slide2.getShapes().get(0);\r
\r
assertArrayEquals(data1, shape2.getPictureData().getData());\r
\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
+\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.STTextUnderlineType;\r
\r
import java.util.List;\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFShape extends TestCase {\r
+public class TestXSLFShape {\r
\r
+ @Test\r
public void testReadTextShapes() {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
- XSLFSlide[] slides = ppt.getSlides();\r
+ List<XSLFSlide> slides = ppt.getSlides();\r
\r
- XSLFSlide slide1 = slides[0];\r
- XSLFShape[] shapes1 = slide1.getShapes();\r
- assertEquals(7, shapes1.length);\r
- assertEquals("TextBox 3", shapes1[0].getShapeName());\r
- XSLFAutoShape sh0 = (XSLFAutoShape) shapes1[0];\r
+ XSLFSlide slide1 = slides.get(0);\r
+ List<XSLFShape> shapes1 = slide1.getShapes();\r
+ assertEquals(7, shapes1.size());\r
+ assertEquals("TextBox 3", shapes1.get(0).getShapeName());\r
+ XSLFAutoShape sh0 = (XSLFAutoShape) shapes1.get(0);\r
assertEquals("Learning PPTX", sh0.getText());\r
List<XSLFTextParagraph> paragraphs0 = sh0.getTextParagraphs();\r
assertEquals(1, paragraphs0.size());\r
assertEquals("Learning PPTX", p0.getText());\r
assertEquals(1, p0.getTextRuns().size());\r
XSLFTextRun r0 = p0.getTextRuns().get(0);\r
- assertEquals("Learning PPTX", r0.getText());\r
+ assertEquals("Learning PPTX", r0.getRawText());\r
\r
- XSLFSlide slide2 = slides[1];\r
- XSLFShape[] shapes2 = slide2.getShapes();\r
- assertTrue(shapes2[0] instanceof XSLFAutoShape);\r
- assertEquals("PPTX Title", ((XSLFAutoShape) shapes2[0]).getText());\r
- XSLFAutoShape sh1 = (XSLFAutoShape) shapes2[0];\r
+ XSLFSlide slide2 = slides.get(1);\r
+ List<XSLFShape> shapes2 = slide2.getShapes();\r
+ assertTrue(shapes2.get(0) instanceof XSLFAutoShape);\r
+ assertEquals("PPTX Title", ((XSLFAutoShape) shapes2.get(0)).getText());\r
+ XSLFAutoShape sh1 = (XSLFAutoShape) shapes2.get(0);\r
List<XSLFTextParagraph> paragraphs1 = sh1.getTextParagraphs();\r
assertEquals(1, paragraphs1.size());\r
XSLFTextParagraph p1 = paragraphs1.get(0);\r
assertEquals("PPTX Title", p1.getText());\r
List<XSLFTextRun> r2 = paragraphs1.get(0).getTextRuns();\r
assertEquals(2, r2.size());\r
- assertEquals("PPTX ", r2.get(0).getText());\r
- assertEquals("Title", r2.get(1).getText());\r
+ assertEquals("PPTX ", r2.get(0).getRawText());\r
+ assertEquals("Title", r2.get(1).getRawText());\r
// Title is underlined\r
assertEquals(STTextUnderlineType.SNG, r2.get(1).getXmlObject().getRPr().getU());\r
\r
\r
- assertTrue(shapes2[1] instanceof XSLFAutoShape);\r
- assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2[1]).getText());\r
- XSLFAutoShape sh2 = (XSLFAutoShape) shapes2[1];\r
+ assertTrue(shapes2.get(1) instanceof XSLFAutoShape);\r
+ assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape) shapes2.get(1)).getText());\r
+ XSLFAutoShape sh2 = (XSLFAutoShape) shapes2.get(1);\r
List<XSLFTextParagraph> paragraphs2 = sh2.getTextParagraphs();\r
assertEquals(2, paragraphs2.size());\r
assertEquals("Subtitle", paragraphs2.get(0).getText());\r
assertEquals(1, paragraphs2.get(0).getTextRuns().size());\r
assertEquals(1, paragraphs2.get(1).getTextRuns().size());\r
\r
- assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getText());\r
+ assertEquals("Subtitle", paragraphs2.get(0).getTextRuns().get(0).getRawText());\r
assertTrue(paragraphs2.get(0).getTextRuns().get(0).getXmlObject().getRPr().getB());\r
- assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getText());\r
+ assertEquals("And second line", paragraphs2.get(1).getTextRuns().get(0).getRawText());\r
}\r
\r
public void testCreateShapes() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
- assertEquals(0, slide.getShapes().length);\r
+ assertTrue(slide.getShapes().isEmpty());\r
\r
XSLFTextBox textBox = slide.createTextBox();\r
\r
- assertEquals(1, slide.getShapes().length);\r
- assertSame(textBox, slide.getShapes()[0]);\r
+ assertEquals(1, slide.getShapes().size());\r
+ assertSame(textBox, slide.getShapes().get(0));\r
\r
assertEquals("", textBox.getText());\r
assertEquals(0, textBox.getTextParagraphs().size());\r
*/\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
+\r
+import org.junit.Test;\r
\r
/**\r
* test common operations on containers of shapes (sheets and groups of shapes)\r
*\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFShapeContainer extends TestCase {\r
+public class TestXSLFShapeContainer {\r
\r
+ @SuppressWarnings("unused")\r
+ @Test\r
public void verifyContainer(XSLFShapeContainer container) {\r
container.clear();\r
- assertEquals(0, container.getShapes().length);\r
+ assertEquals(0, container.getShapes().size());\r
\r
XSLFGroupShape shape1 = container.createGroup();\r
- assertEquals(1, container.getShapes().length);\r
+ assertEquals(1, container.getShapes().size());\r
\r
XSLFTextBox shape2 = container.createTextBox();\r
- assertEquals(2, container.getShapes().length);\r
+ assertEquals(2, container.getShapes().size());\r
\r
XSLFAutoShape shape3 = container.createAutoShape();\r
- assertEquals(3, container.getShapes().length);\r
+ assertEquals(3, container.getShapes().size());\r
\r
XSLFConnectorShape shape4 = container.createConnector();\r
- assertEquals(4, container.getShapes().length);\r
+ assertEquals(4, container.getShapes().size());\r
\r
container.clear();\r
- assertEquals(0, container.getShapes().length);\r
+ assertEquals(0, container.getShapes().size());\r
}\r
\r
+ @Test\r
public void testSheet() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSheet sheet = ppt.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
+\r
+import java.util.List;\r
+\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
\r
/**\r
* test common properties for sheets (slides, masters, layouts, etc.)\r
*\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFSheet extends TestCase {\r
+public class TestXSLFSheet {\r
+ \r
+ @Test\r
public void testCreateShapes(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
- assertEquals(0, slide.getShapes().length);\r
+ assertTrue(slide.getShapes().isEmpty());\r
\r
XSLFSimpleShape shape1 = slide.createAutoShape();\r
- assertEquals(1, slide.getShapes().length);\r
- assertSame(shape1, slide.getShapes()[0]);\r
+ assertEquals(1, slide.getShapes().size());\r
+ assertSame(shape1, slide.getShapes().get(0));\r
\r
XSLFTextBox shape2 = slide.createTextBox();\r
- assertEquals(2, slide.getShapes().length);\r
- assertSame(shape1, slide.getShapes()[0]);\r
- assertSame(shape2, slide.getShapes()[1]);\r
+ assertEquals(2, slide.getShapes().size());\r
+ assertSame(shape1, slide.getShapes().get(0));\r
+ assertSame(shape2, slide.getShapes().get(1));\r
\r
XSLFConnectorShape shape3 = slide.createConnector();\r
- assertEquals(3, slide.getShapes().length);\r
- assertSame(shape1, slide.getShapes()[0]);\r
- assertSame(shape2, slide.getShapes()[1]);\r
- assertSame(shape3, slide.getShapes()[2]);\r
+ assertEquals(3, slide.getShapes().size());\r
+ assertSame(shape1, slide.getShapes().get(0));\r
+ assertSame(shape2, slide.getShapes().get(1));\r
+ assertSame(shape3, slide.getShapes().get(2));\r
\r
XSLFGroupShape shape4 = slide.createGroup();\r
- assertEquals(4, slide.getShapes().length);\r
- assertSame(shape1, slide.getShapes()[0]);\r
- assertSame(shape2, slide.getShapes()[1]);\r
- assertSame(shape3, slide.getShapes()[2]);\r
- assertSame(shape4, slide.getShapes()[3]);\r
+ assertEquals(4, slide.getShapes().size());\r
+ assertSame(shape1, slide.getShapes().get(0));\r
+ assertSame(shape2, slide.getShapes().get(1));\r
+ assertSame(shape3, slide.getShapes().get(2));\r
+ assertSame(shape4, slide.getShapes().get(3));\r
\r
ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
- slide = ppt.getSlides()[0];\r
- XSLFShape[] shapes = slide.getShapes();\r
- assertEquals(4, shapes.length);\r
+ slide = ppt.getSlides().get(0);\r
+ List<XSLFShape> shapes = slide.getShapes();\r
+ assertEquals(4, shapes.size());\r
\r
- assertTrue(shapes[0] instanceof XSLFAutoShape);\r
- assertTrue(shapes[1] instanceof XSLFTextBox);\r
- assertTrue(shapes[2] instanceof XSLFConnectorShape);\r
- assertTrue(shapes[3] instanceof XSLFGroupShape);\r
+ assertTrue(shapes.get(0) instanceof XSLFAutoShape);\r
+ assertTrue(shapes.get(1) instanceof XSLFTextBox);\r
+ assertTrue(shapes.get(2) instanceof XSLFConnectorShape);\r
+ assertTrue(shapes.get(3) instanceof XSLFGroupShape);\r
}\r
}
\ No newline at end of file
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import java.awt.Color;\r
+import static org.junit.Assert.*;\r
\r
-import junit.framework.TestCase;\r
+import java.awt.Color;\r
+import java.util.List;\r
\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
import org.apache.poi.util.Units;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFSimpleShape extends TestCase {\r
+public class TestXSLFSimpleShape {\r
+ \r
+ @Test\r
public void testLineStyles() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
\r
XSLFSimpleShape shape = slide.createAutoShape();\r
- assertEquals(1, slide.getShapes().length);\r
+ assertEquals(1, slide.getShapes().size());\r
// line properties are not set by default\r
assertFalse(shape.getSpPr().isSetLn());\r
\r
- assertEquals(0., shape.getLineWidth());\r
+ assertEquals(0., shape.getLineWidth(), 0);\r
assertEquals(null, shape.getLineColor());\r
assertEquals(null, shape.getLineDash());\r
assertEquals(null, shape.getLineCap());\r
\r
// line width\r
shape.setLineWidth(1.0);\r
- assertEquals(1.0, shape.getLineWidth());\r
+ assertEquals(1.0, shape.getLineWidth(), 0);\r
assertEquals(Units.EMU_PER_POINT, shape.getSpPr().getLn().getW());\r
shape.setLineWidth(5.5);\r
- assertEquals(5.5, shape.getLineWidth());\r
+ assertEquals(5.5, shape.getLineWidth(), 0);\r
assertEquals(Units.toEMU(5.5), shape.getSpPr().getLn().getW());\r
shape.setLineWidth(0.0);\r
// setting line width to zero unsets the W attribute\r
ln2.setLineDash(LineDash.DOT);\r
assertEquals(LineDash.DOT, ln2.getLineDash());\r
ln2.setLineWidth(0.);\r
- assertEquals(0., ln2.getLineWidth());\r
+ assertEquals(0., ln2.getLineWidth(), 0);\r
\r
XSLFSimpleShape ln3 = slide.createAutoShape();\r
ln3.setLineWidth(1.);\r
- assertEquals(1., ln3.getLineWidth());\r
+ assertEquals(1., ln3.getLineWidth(), 0);\r
ln3.setLineDash(null);\r
assertEquals(null, ln3.getLineDash());\r
ln3.setLineCap(null);\r
assertEquals(null, ln3.getLineDash());\r
}\r
\r
+ @Test\r
public void testFill() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
assertFalse(shape.getSpPr().isSetSolidFill());\r
}\r
\r
+ @Test\r
public void testDefaultProperties() {\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
\r
- XSLFSlide slide6 = ppt.getSlides()[5];\r
- XSLFShape[] shapes = slide6.getShapes();\r
- for(int i = 1; i < shapes.length; i++){\r
- XSLFSimpleShape s = (XSLFSimpleShape) shapes[i];\r
+ XSLFSlide slide6 = ppt.getSlides().get(5);\r
+ List<XSLFShape> shapes = slide6.getShapes();\r
+ for(XSLFShape xs : shapes){\r
+ XSLFSimpleShape s = (XSLFSimpleShape)xs;\r
// all shapes have a theme color="accent1"\r
assertEquals("accent1", s.getSpStyle().getFillRef().getSchemeClr().getVal().toString());\r
- assertEquals(2.0, s.getLineWidth());\r
+ assertEquals(2.0, s.getLineWidth(), 0);\r
assertEquals(LineCap.FLAT, s.getLineCap());\r
// YK: calculated color is slightly different from PowerPoint\r
assertEquals(new Color(39, 64, 94), s.getLineColor());\r
}\r
\r
- XSLFSimpleShape s0 = (XSLFSimpleShape) shapes[0];\r
+ XSLFSimpleShape s0 = (XSLFSimpleShape) shapes.get(0);\r
// fill is not set\r
assertNull(s0.getSpPr().getSolidFill());\r
//assertEquals(slide6.getTheme().getColor("accent1").getColor(), s0.getFillColor());\r
assertEquals(new Color(79, 129, 189), s0.getFillColor());\r
\r
// lighter 80%\r
- XSLFSimpleShape s1 = (XSLFSimpleShape)shapes[1];\r
+ XSLFSimpleShape s1 = (XSLFSimpleShape)shapes.get(1);\r
CTSchemeColor ref1 = s1.getSpPr().getSolidFill().getSchemeClr();\r
assertEquals(1, ref1.sizeOfLumModArray());\r
assertEquals(1, ref1.sizeOfLumOffArray());\r
assertEquals(new Color(220, 230, 242), s1.getFillColor());\r
\r
// lighter 60%\r
- XSLFSimpleShape s2 = (XSLFSimpleShape)shapes[2];\r
+ XSLFSimpleShape s2 = (XSLFSimpleShape)shapes.get(2);\r
CTSchemeColor ref2 = s2.getSpPr().getSolidFill().getSchemeClr();\r
assertEquals(1, ref2.sizeOfLumModArray());\r
assertEquals(1, ref2.sizeOfLumOffArray());\r
assertEquals(new Color(185, 205, 229), s2.getFillColor());\r
\r
// lighter 40%\r
- XSLFSimpleShape s3 = (XSLFSimpleShape)shapes[3];\r
+ XSLFSimpleShape s3 = (XSLFSimpleShape)shapes.get(3);\r
CTSchemeColor ref3 = s3.getSpPr().getSolidFill().getSchemeClr();\r
assertEquals(1, ref3.sizeOfLumModArray());\r
assertEquals(1, ref3.sizeOfLumOffArray());\r
assertEquals(new Color(149, 179, 215), s3.getFillColor());\r
\r
// darker 25%\r
- XSLFSimpleShape s4 = (XSLFSimpleShape)shapes[4];\r
+ XSLFSimpleShape s4 = (XSLFSimpleShape)shapes.get(4);\r
CTSchemeColor ref4 = s4.getSpPr().getSolidFill().getSchemeClr();\r
assertEquals(1, ref4.sizeOfLumModArray());\r
assertEquals(0, ref4.sizeOfLumOffArray());\r
// YK: calculated color is slightly different from PowerPoint\r
assertEquals(new Color(59, 97, 142), s4.getFillColor());\r
\r
- XSLFSimpleShape s5 = (XSLFSimpleShape)shapes[5];\r
+ XSLFSimpleShape s5 = (XSLFSimpleShape)shapes.get(5);\r
CTSchemeColor ref5 = s5.getSpPr().getSolidFill().getSchemeClr();\r
assertEquals(1, ref5.sizeOfLumModArray());\r
assertEquals(0, ref5.sizeOfLumOffArray());\r
assertEquals(new Color(40, 65, 95), s5.getFillColor());\r
}\r
\r
+ @Test\r
public void testAnchor(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
- XSLFSlide[] slide = ppt.getSlides();\r
+ List<XSLFSlide> slide = ppt.getSlides();\r
\r
- XSLFSlide slide2 = slide[1];\r
+ XSLFSlide slide2 = slide.get(1);\r
XSLFSlideLayout layout2 = slide2.getSlideLayout();\r
- XSLFShape[] shapes2 = slide2.getShapes();\r
- XSLFTextShape sh1 = (XSLFTextShape)shapes2[0];\r
+ List<XSLFShape> shapes2 = slide2.getShapes();\r
+ XSLFTextShape sh1 = (XSLFTextShape)shapes2.get(0);\r
assertEquals(Placeholder.CENTERED_TITLE, sh1.getTextType());\r
assertEquals("PPTX Title", sh1.getText());\r
assertNull(sh1.getSpPr().getXfrm()); // xfrm is not set, the query is delegated to the slide layout\r
assertEquals(sh1.getAnchor(), layout2.getTextShapeByType(Placeholder.CENTERED_TITLE).getAnchor());\r
\r
- XSLFTextShape sh2 = (XSLFTextShape)shapes2[1];\r
+ XSLFTextShape sh2 = (XSLFTextShape)shapes2.get(1);\r
assertEquals("Subtitle\nAnd second line", sh2.getText());\r
assertEquals(Placeholder.SUBTITLE, sh2.getTextType());\r
assertNull(sh2.getSpPr().getXfrm()); // xfrm is not set, the query is delegated to the slide layout\r
assertEquals(sh2.getAnchor(), layout2.getTextShapeByType(Placeholder.SUBTITLE).getAnchor());\r
\r
- XSLFSlide slide5 = slide[4];\r
+ XSLFSlide slide5 = slide.get(4);\r
XSLFSlideLayout layout5 = slide5.getSlideLayout();\r
XSLFTextShape shTitle = slide5.getTextShapeByType(Placeholder.TITLE);\r
assertEquals("Hyperlinks", shTitle.getText());\r
}\r
\r
@SuppressWarnings({ "deprecation", "unused" })\r
+ @Test\r
public void testShadowEffects(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import static org.junit.Assert.assertArrayEquals;\r
+import static org.junit.Assert.*;\r
\r
import java.awt.Color;\r
-\r
-import junit.framework.TestCase;\r
+import java.util.List;\r
\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFSlide extends TestCase {\r
+public class TestXSLFSlide {\r
+ \r
+ @Test\r
public void testReadShapes(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
- XSLFSlide[] slides = ppt.getSlides();\r
-\r
- XSLFSlide slide1 = slides[0];\r
- XSLFShape[] shapes1 = slide1.getShapes();\r
- assertEquals(7, shapes1.length);\r
- assertEquals("TextBox 3", shapes1[0].getShapeName());\r
- assertTrue(shapes1[0] instanceof XSLFTextBox);\r
- XSLFAutoShape sh0 = (XSLFAutoShape)shapes1[0];\r
+ List<XSLFSlide> slides = ppt.getSlides();\r
+\r
+ XSLFSlide slide1 = slides.get(0);\r
+ List<XSLFShape> shapes1 = slide1.getShapes();\r
+ assertEquals(7, shapes1.size());\r
+ assertEquals("TextBox 3", shapes1.get(0).getShapeName());\r
+ assertTrue(shapes1.get(0) instanceof XSLFTextBox);\r
+ XSLFAutoShape sh0 = (XSLFAutoShape)shapes1.get(0);\r
assertEquals("Learning PPTX", sh0.getText());\r
\r
\r
- assertEquals("Straight Connector 5", shapes1[1].getShapeName());\r
- assertTrue(shapes1[1] instanceof XSLFConnectorShape);\r
+ assertEquals("Straight Connector 5", shapes1.get(1).getShapeName());\r
+ assertTrue(shapes1.get(1) instanceof XSLFConnectorShape);\r
\r
- assertEquals("Freeform 6", shapes1[2].getShapeName());\r
- assertTrue(shapes1[2] instanceof XSLFFreeformShape);\r
- XSLFAutoShape sh2 = (XSLFAutoShape)shapes1[2];\r
+ assertEquals("Freeform 6", shapes1.get(2).getShapeName());\r
+ assertTrue(shapes1.get(2) instanceof XSLFFreeformShape);\r
+ XSLFAutoShape sh2 = (XSLFAutoShape)shapes1.get(2);\r
assertEquals("Cloud", sh2.getText());\r
\r
- assertEquals("Picture 1", shapes1[3].getShapeName());\r
- assertTrue(shapes1[3] instanceof XSLFPictureShape);\r
+ assertEquals("Picture 1", shapes1.get(3).getShapeName());\r
+ assertTrue(shapes1.get(3) instanceof XSLFPictureShape);\r
\r
- assertEquals("Table 2", shapes1[4].getShapeName());\r
- assertTrue(shapes1[4] instanceof XSLFGraphicFrame);\r
+ assertEquals("Table 2", shapes1.get(4).getShapeName());\r
+ assertTrue(shapes1.get(4) instanceof XSLFGraphicFrame);\r
\r
- assertEquals("Straight Arrow Connector 7", shapes1[5].getShapeName());\r
- assertTrue(shapes1[5] instanceof XSLFConnectorShape);\r
+ assertEquals("Straight Arrow Connector 7", shapes1.get(5).getShapeName());\r
+ assertTrue(shapes1.get(5) instanceof XSLFConnectorShape);\r
\r
- assertEquals("Elbow Connector 9", shapes1[6].getShapeName());\r
- assertTrue(shapes1[6] instanceof XSLFConnectorShape);\r
+ assertEquals("Elbow Connector 9", shapes1.get(6).getShapeName());\r
+ assertTrue(shapes1.get(6) instanceof XSLFConnectorShape);\r
\r
// titles on slide2\r
- XSLFSlide slide2 = slides[1];\r
- XSLFShape[] shapes2 = slide2.getShapes();\r
- assertEquals(2, shapes2.length);\r
- assertTrue(shapes2[0] instanceof XSLFAutoShape);\r
- assertEquals("PPTX Title", ((XSLFAutoShape)shapes2[0]).getText());\r
- assertTrue(shapes2[1] instanceof XSLFAutoShape);\r
- assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2[1]).getText());\r
+ XSLFSlide slide2 = slides.get(1);\r
+ List<XSLFShape> shapes2 = slide2.getShapes();\r
+ assertEquals(2, shapes2.size());\r
+ assertTrue(shapes2.get(0) instanceof XSLFAutoShape);\r
+ assertEquals("PPTX Title", ((XSLFAutoShape)shapes2.get(0)).getText());\r
+ assertTrue(shapes2.get(1) instanceof XSLFAutoShape);\r
+ assertEquals("Subtitle\nAnd second line", ((XSLFAutoShape)shapes2.get(1)).getText());\r
\r
// group shape on slide3\r
- XSLFSlide slide3 = slides[2];\r
- XSLFShape[] shapes3 = slide3.getShapes();\r
- assertEquals(1, shapes3.length);\r
- assertTrue(shapes3[0] instanceof XSLFGroupShape);\r
- XSLFShape[] groupShapes = ((XSLFGroupShape)shapes3[0]).getShapes();\r
- assertEquals(3, groupShapes.length);\r
- assertTrue(groupShapes[0] instanceof XSLFAutoShape);\r
- assertEquals("Rectangle 1", groupShapes[0].getShapeName());\r
-\r
- assertTrue(groupShapes[1] instanceof XSLFAutoShape);\r
- assertEquals("Oval 2", groupShapes[1].getShapeName());\r
-\r
- assertTrue(groupShapes[2] instanceof XSLFAutoShape);\r
- assertEquals("Right Arrow 3", groupShapes[2].getShapeName());\r
-\r
- XSLFSlide slide4 = slides[3];\r
- XSLFShape[] shapes4 = slide4.getShapes();\r
- assertEquals(1, shapes4.length);\r
- assertTrue(shapes4[0] instanceof XSLFTable);\r
- XSLFTable tbl = (XSLFTable)shapes4[0];\r
+ XSLFSlide slide3 = slides.get(2);\r
+ List<XSLFShape> shapes3 = slide3.getShapes();\r
+ assertEquals(1, shapes3.size());\r
+ assertTrue(shapes3.get(0) instanceof XSLFGroupShape);\r
+ List<XSLFShape> groupShapes = ((XSLFGroupShape)shapes3.get(0)).getShapes();\r
+ assertEquals(3, groupShapes.size());\r
+ assertTrue(groupShapes.get(0) instanceof XSLFAutoShape);\r
+ assertEquals("Rectangle 1", groupShapes.get(0).getShapeName());\r
+\r
+ assertTrue(groupShapes.get(1) instanceof XSLFAutoShape);\r
+ assertEquals("Oval 2", groupShapes.get(1).getShapeName());\r
+\r
+ assertTrue(groupShapes.get(2) instanceof XSLFAutoShape);\r
+ assertEquals("Right Arrow 3", groupShapes.get(2).getShapeName());\r
+\r
+ XSLFSlide slide4 = slides.get(3);\r
+ List<XSLFShape> shapes4 = slide4.getShapes();\r
+ assertEquals(1, shapes4.size());\r
+ assertTrue(shapes4.get(0) instanceof XSLFTable);\r
+ XSLFTable tbl = (XSLFTable)shapes4.get(0);\r
assertEquals(3, tbl.getNumberOfColumns());\r
assertEquals(6, tbl.getNumberOfRows());\r
}\r
\r
+ @Test\r
public void testCreateSlide(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
- assertEquals(0, ppt.getSlides().length);\r
+ assertEquals(0, ppt.getSlides().size());\r
\r
XSLFSlide slide = ppt.createSlide();\r
assertTrue(slide.getFollowMasterGraphics());\r
assertTrue(slide.getFollowMasterGraphics());\r
}\r
\r
+ @Test\r
public void testImportContent(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
XMLSlideShow src = XSLFTestDataSamples.openSampleDocument("themes.pptx");\r
\r
// create a blank slide and import content from the 4th slide of themes.pptx\r
- XSLFSlide slide1 = ppt.createSlide().importContent(src.getSlides()[3]);\r
- XSLFShape[] shapes1 = slide1.getShapes();\r
- assertEquals(2, shapes1.length);\r
+ XSLFSlide slide1 = ppt.createSlide().importContent(src.getSlides().get(3));\r
+ List<XSLFShape> shapes1 = slide1.getShapes();\r
+ assertEquals(2, shapes1.size());\r
\r
- XSLFTextShape sh1 = (XSLFTextShape)shapes1[0];\r
+ XSLFTextShape sh1 = (XSLFTextShape)shapes1.get(0);\r
assertEquals("Austin Theme", sh1.getText());\r
XSLFTextRun r1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Century Gothic", r1.getFontFamily());\r
- assertEquals(40.0, r1.getFontSize());\r
+ assertEquals(40.0, r1.getFontSize(), 0);\r
assertTrue(r1.isBold());\r
assertTrue(r1.isItalic());\r
assertEquals(new Color(148, 198, 0), r1.getFontColor());\r
assertNull(sh1.getFillColor());\r
assertNull(sh1.getLineColor());\r
\r
- XSLFTextShape sh2 = (XSLFTextShape)shapes1[1];\r
+ XSLFTextShape sh2 = (XSLFTextShape)shapes1.get(1);\r
assertEquals(\r
"Text in a autoshape is white\n" +\r
"Fill: RGB(148, 198,0)", sh2.getText());\r
XSLFTextRun r2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Century Gothic", r2.getFontFamily());\r
- assertEquals(18.0, r2.getFontSize());\r
+ assertEquals(18.0, r2.getFontSize(), 0);\r
assertFalse(r2.isBold());\r
assertFalse(r2.isItalic());\r
assertEquals(Color.white, r2.getFontColor());\r
assertEquals(new Color(74, 99, 0), sh2.getLineColor()); // slightly different from PowerPoint!\r
\r
// the 5th slide has a picture and a texture fill\r
- XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides()[4]);\r
- XSLFShape[] shapes2 = slide2.getShapes();\r
- assertEquals(2, shapes2.length);\r
+ XSLFSlide slide2 = ppt.createSlide().importContent(src.getSlides().get(4));\r
+ List<XSLFShape> shapes2 = slide2.getShapes();\r
+ assertEquals(2, shapes2.size());\r
\r
- XSLFTextShape sh3 = (XSLFTextShape)shapes2[0];\r
+ XSLFTextShape sh3 = (XSLFTextShape)shapes2.get(0);\r
assertEquals("This slide overrides master background with a texture fill", sh3.getText());\r
XSLFTextRun r3 = sh3.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Century Gothic", r3.getFontFamily());\r
assertNull(sh3.getFillColor());\r
assertNull(sh3.getLineColor());\r
\r
- XSLFPictureShape sh4 = (XSLFPictureShape)shapes2[1];\r
- XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides()[4].getShapes()[1];\r
+ XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1);\r
+ XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1);\r
assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData());\r
}\r
\r
+ @Test\r
public void testMergeSlides(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
String[] pptx = {"shapes.pptx", "themes.pptx", "layouts.pptx", "backgrounds.pptx"};\r
ppt.createSlide().importContent(srcSlide);\r
}\r
}\r
- assertEquals(30, ppt.getSlides().length);\r
+ assertEquals(30, ppt.getSlides().size());\r
} \r
}
\ No newline at end of file
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
-import org.apache.poi.POIXMLDocumentPart;\r
-import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import static org.junit.Assert.*;\r
\r
import java.awt.Dimension;\r
import java.util.List;\r
\r
+import org.apache.poi.POIXMLDocumentPart;\r
+import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
+\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFSlideShow extends TestCase {\r
+public class TestXSLFSlideShow {\r
+ @Test\r
public void testCreateSlide(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
- assertEquals(0, ppt.getSlides().length);\r
+ assertEquals(0, ppt.getSlides().size());\r
\r
XSLFSlide slide1 = ppt.createSlide();\r
- assertEquals(1, ppt.getSlides().length);\r
- assertSame(slide1, ppt.getSlides()[0]);\r
+ assertEquals(1, ppt.getSlides().size());\r
+ assertSame(slide1, ppt.getSlides().get(0));\r
\r
List<POIXMLDocumentPart> rels = slide1.getRelations();\r
assertEquals(1, rels.size());\r
assertEquals(slide1.getSlideMaster().getLayout(SlideLayout.BLANK), rels.get(0));\r
\r
XSLFSlide slide2 = ppt.createSlide();\r
- assertEquals(2, ppt.getSlides().length);\r
- assertSame(slide2, ppt.getSlides()[1]);\r
+ assertEquals(2, ppt.getSlides().size());\r
+ assertSame(slide2, ppt.getSlides().get(1));\r
\r
ppt.setSlideOrder(slide2, 0);\r
- assertSame(slide2, ppt.getSlides()[0]);\r
- assertSame(slide1, ppt.getSlides()[1]);\r
+ assertSame(slide2, ppt.getSlides().get(0));\r
+ assertSame(slide1, ppt.getSlides().get(1));\r
\r
ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
- assertEquals(2, ppt.getSlides().length);\r
- rels = ppt.getSlides()[0].getRelations();\r
+ assertEquals(2, ppt.getSlides().size());\r
+ rels = ppt.getSlides().get(0).getRelations();\r
}\r
\r
+ @Test\r
public void testRemoveSlide(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
- assertEquals(0, ppt.getSlides().length);\r
+ assertEquals(0, ppt.getSlides().size());\r
\r
XSLFSlide slide1 = ppt.createSlide();\r
XSLFSlide slide2 = ppt.createSlide();\r
\r
- assertEquals(2, ppt.getSlides().length);\r
- assertSame(slide1, ppt.getSlides()[0]);\r
- assertSame(slide2, ppt.getSlides()[1]);\r
+ assertEquals(2, ppt.getSlides().size());\r
+ assertSame(slide1, ppt.getSlides().get(0));\r
+ assertSame(slide2, ppt.getSlides().get(1));\r
\r
XSLFSlide removedSlide = ppt.removeSlide(0);\r
assertSame(slide1, removedSlide);\r
\r
- assertEquals(1, ppt.getSlides().length);\r
- assertSame(slide2, ppt.getSlides()[0]);\r
+ assertEquals(1, ppt.getSlides().size());\r
+ assertSame(slide2, ppt.getSlides().get(0));\r
\r
ppt = XSLFTestDataSamples.writeOutAndReadBack(ppt);\r
- assertEquals(1, ppt.getSlides().length);\r
+ assertEquals(1, ppt.getSlides().size());\r
}\r
\r
+ @Test\r
public void testDimension(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
Dimension sz = ppt.getPageSize();\r
assertEquals(612, sz.height);\r
}\r
\r
+ @Test\r
public void testSlideMasters(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
- XSLFSlideMaster[] masters = ppt.getSlideMasters();\r
- assertEquals(1, masters.length);\r
+ List<XSLFSlideMaster> masters = ppt.getSlideMasters();\r
+ assertEquals(1, masters.size());\r
\r
XSLFSlide slide = ppt.createSlide();\r
- assertSame(masters[0], slide.getSlideMaster());\r
+ assertSame(masters.get(0), slide.getSlideMaster());\r
}\r
\r
+ @Test\r
public void testSlideLayout(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
- XSLFSlideMaster[] masters = ppt.getSlideMasters();\r
- assertEquals(1, masters.length);\r
+ List<XSLFSlideMaster> masters = ppt.getSlideMasters();\r
+ assertEquals(1, masters.size());\r
\r
XSLFSlide slide = ppt.createSlide();\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
assertNotNull(layout);\r
\r
- assertSame(masters[0], layout.getSlideMaster());\r
+ assertSame(masters.get(0), layout.getSlideMaster());\r
}\r
}\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.*;\r
\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableCell;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTable extends TestCase {\r
-\r
+public class TestXSLFTable {\r
+ @Test\r
public void testRead(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");\r
\r
- XSLFSlide slide = ppt.getSlides()[3];\r
- XSLFShape[] shapes = slide.getShapes();\r
- assertEquals(1, shapes.length);\r
- assertTrue(shapes[0] instanceof XSLFTable);\r
- XSLFTable tbl = (XSLFTable)shapes[0];\r
+ XSLFSlide slide = ppt.getSlides().get(3);\r
+ List<XSLFShape> shapes = slide.getShapes();\r
+ assertEquals(1, shapes.size());\r
+ assertTrue(shapes.get(0) instanceof XSLFTable);\r
+ XSLFTable tbl = (XSLFTable)shapes.get(0);\r
assertEquals(3, tbl.getNumberOfColumns());\r
assertEquals(6, tbl.getNumberOfRows());\r
assertNotNull(tbl.getCTTable());\r
List<XSLFTableRow> rows = tbl.getRows();\r
assertEquals(6, rows.size());\r
\r
- assertEquals(90.0, tbl.getColumnWidth(0));\r
- assertEquals(240.0, tbl.getColumnWidth(1));\r
- assertEquals(150.0, tbl.getColumnWidth(2));\r
+ assertEquals(90.0, tbl.getColumnWidth(0), 0);\r
+ assertEquals(240.0, tbl.getColumnWidth(1), 0);\r
+ assertEquals(150.0, tbl.getColumnWidth(2), 0);\r
\r
for(XSLFTableRow row : tbl){\r
// all rows have the same height\r
- assertEquals(29.2, row.getHeight());\r
+ assertEquals(29.2, row.getHeight(), 0);\r
}\r
\r
XSLFTableRow row0 = rows.get(0);\r
assertEquals("C1", cells1.get(2).getText());\r
}\r
\r
+ @Test\r
public void testCreate() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
assertNotNull(row0.getXmlObject());\r
assertEquals(1, tbl.getNumberOfRows());\r
assertSame(row0, tbl.getRows().get(0));\r
- assertEquals(20.0, row0.getHeight());\r
+ assertEquals(20.0, row0.getHeight(), 0);\r
row0.setHeight(30.0);\r
- assertEquals(30.0, row0.getHeight());\r
+ assertEquals(30.0, row0.getHeight(), 0);\r
\r
assertEquals(0, row0.getCells().size());\r
XSLFTableCell cell0 = row0.addCell();\r
\r
assertSame(cell0, row0.getCells().get(0));\r
assertEquals(1, tbl.getNumberOfColumns());\r
- assertEquals(100.0, tbl.getColumnWidth(0));\r
+ assertEquals(100.0, tbl.getColumnWidth(0), 0);\r
cell0.addNewTextParagraph().addNewTextRun().setText("POI");\r
assertEquals("POI", cell0.getText());\r
\r
XSLFTableCell cell1 = row0.addCell();\r
assertSame(cell1, row0.getCells().get(1));\r
assertEquals(2, tbl.getNumberOfColumns());\r
- assertEquals(100.0, tbl.getColumnWidth(1));\r
+ assertEquals(100.0, tbl.getColumnWidth(1), 0);\r
cell1.addNewTextParagraph().addNewTextRun().setText("Apache");\r
assertEquals("Apache", cell1.getText());\r
\r
- assertEquals(1.0, cell1.getBorderBottom());\r
+ assertEquals(1.0, cell1.getBorderBottom(), 0);\r
cell1.setBorderBottom(2.0);\r
- assertEquals(2.0, cell1.getBorderBottom());\r
+ assertEquals(2.0, cell1.getBorderBottom(), 0);\r
assertNull(cell1.getBorderBottomColor());\r
cell1.setBorderBottomColor(Color.yellow);\r
assertEquals(Color.yellow, cell1.getBorderBottomColor());\r
\r
- assertEquals(1.0, cell1.getBorderTop());\r
+ assertEquals(1.0, cell1.getBorderTop(), 0);\r
cell1.setBorderTop(2.0);\r
- assertEquals(2.0, cell1.getBorderTop());\r
+ assertEquals(2.0, cell1.getBorderTop(), 0);\r
assertNull(cell1.getBorderTopColor());\r
cell1.setBorderTopColor(Color.yellow);\r
assertEquals(Color.yellow, cell1.getBorderTopColor());\r
\r
- assertEquals(1.0, cell1.getBorderLeft());\r
+ assertEquals(1.0, cell1.getBorderLeft(), 0);\r
cell1.setBorderLeft(2.0);\r
- assertEquals(2.0, cell1.getBorderLeft());\r
+ assertEquals(2.0, cell1.getBorderLeft(), 0);\r
assertNull(cell1.getBorderLeftColor());\r
cell1.setBorderLeftColor(Color.yellow);\r
assertEquals(Color.yellow, cell1.getBorderLeftColor());\r
\r
- assertEquals(1.0, cell1.getBorderRight());\r
+ assertEquals(1.0, cell1.getBorderRight(), 0);\r
cell1.setBorderRight(2.0);\r
- assertEquals(2.0, cell1.getBorderRight());\r
+ assertEquals(2.0, cell1.getBorderRight(), 0);\r
assertNull(cell1.getBorderRightColor());\r
cell1.setBorderRightColor(Color.yellow);\r
assertEquals(Color.yellow, cell1.getBorderRightColor());\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTableStyle;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTableStyles extends TestCase {\r
+public class TestXSLFTableStyles {\r
\r
+ @Test\r
public void testRead(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFTableStyles tblStyles = ppt.getTableStyles();\r
assertEquals(0, tblStyles.getStyles().size());\r
}\r
\r
+ @SuppressWarnings("unused")\r
+ @Test\r
public void testStyle(){\r
CTTableStyle obj = CTTableStyle.Factory.newInstance();\r
XSLFTableStyle style = new XSLFTableStyle(obj);\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNull;\r
+\r
+import org.junit.Test;\r
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextCharacterProperties;\r
\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTextBox extends TestCase {\r
+public class TestXSLFTextBox {\r
\r
+ @Test\r
public void testPlaceholder() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
/**\r
* text box inherits default text proeprties from presentation.xml\r
*/\r
+ @Test\r
public void testDefaultTextStyle() {\r
XMLSlideShow ppt = new XMLSlideShow();\r
XSLFSlide slide = ppt.createSlide();\r
XSLFTextRun r = shape.getTextParagraphs().get(0).getTextRuns().get(0);\r
\r
assertEquals(1800, pPr.getSz());\r
- assertEquals(18.0, r.getFontSize());\r
+ assertEquals(18.0, r.getFontSize(), 0);\r
assertEquals("Calibri", r.getFontFamily());\r
\r
pPr.setSz(900);\r
pPr.getLatin().setTypeface("Arial");\r
- assertEquals(9.0, r.getFontSize());\r
+ assertEquals(9.0, r.getFontSize(), 0);\r
assertEquals("Arial", r.getFontFamily());\r
\r
// unset font size in presentation.xml. The value should be taken from master slide\r
ppt.getCTPresentation().getDefaultTextStyle().getLvl1PPr().getDefRPr().unsetSz();\r
pPr = slide.getSlideMaster().getXmlObject().getTxStyles().getOtherStyle().getLvl1PPr().getDefRPr();\r
assertEquals(1800, pPr.getSz());\r
- assertEquals(18.0, r.getFontSize());\r
+ assertEquals(18.0, r.getFontSize(), 0);\r
pPr.setSz(2000);\r
- assertEquals(20.0, r.getFontSize());\r
+ assertEquals(20.0, r.getFontSize(), 0);\r
\r
pPr.unsetSz(); // Should never be\r
- assertEquals(-1.0, r.getFontSize());\r
+ assertEquals(-1.0, r.getFontSize(), 0);\r
\r
}\r
}
\ No newline at end of file
@Test\r
public void testThemeInheritance(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("prProps.pptx");\r
- XSLFShape[] shapes = ppt.getSlides()[0].getShapes();\r
- XSLFTextShape sh1 = (XSLFTextShape)shapes[0];\r
+ List<XSLFShape> shapes = ppt.getSlides().get(0).getShapes();\r
+ XSLFTextShape sh1 = (XSLFTextShape)shapes.get(0);\r
assertEquals("Apache", sh1.getText());\r
assertEquals(TextAlign.CENTER, sh1.getTextParagraphs().get(0).getTextAlign());\r
- XSLFTextShape sh2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape sh2 = (XSLFTextShape)shapes.get(1);\r
assertEquals("Software", sh2.getText());\r
assertEquals(TextAlign.CENTER, sh2.getTextParagraphs().get(0).getTextAlign());\r
- XSLFTextShape sh3 = (XSLFTextShape)shapes[2];\r
+ XSLFTextShape sh3 = (XSLFTextShape)shapes.get(2);\r
assertEquals("Foundation", sh3.getText());\r
assertEquals(TextAlign.CENTER, sh3.getTextParagraphs().get(0).getTextAlign());\r
}\r
XSLFTextRun r1 = p.addNewTextRun();\r
r1.setText("Hello,");\r
XSLFTextRun r2 = p.addLineBreak();\r
- assertEquals("\n", r2.getText());\r
+ assertEquals("\n", r2.getRawText());\r
r2.setFontSize(10.0);\r
assertEquals(10.0, r2.getFontSize(), 0);\r
XSLFTextRun r3 = p.addNewTextRun();\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import java.awt.Color;\r
+import static org.junit.Assert.*;\r
\r
-import junit.framework.TestCase;\r
+import java.awt.Color;\r
+import java.util.List;\r
\r
import org.apache.poi.sl.usermodel.TextParagraph.TextAlign;\r
import org.apache.poi.sl.usermodel.VerticalAlignment;\r
/**\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTextShape extends TestCase {\r
+public class TestXSLFTextShape {\r
\r
public void testLayouts(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("layouts.pptx");\r
\r
- XSLFSlide[] slide = ppt.getSlides();\r
+ List<XSLFSlide> slide = ppt.getSlides();\r
\r
- verifySlide1(slide[0]);\r
- verifySlide2(slide[1]);\r
- verifySlide3(slide[2]);\r
- verifySlide4(slide[3]);\r
- verifySlide7(slide[6]);\r
- verifySlide8(slide[7]);\r
- verifySlide10(slide[9]);\r
+ verifySlide1(slide.get(0));\r
+ verifySlide2(slide.get(1));\r
+ verifySlide3(slide.get(2));\r
+ verifySlide4(slide.get(3));\r
+ verifySlide7(slide.get(6));\r
+ verifySlide8(slide.get(7));\r
+ verifySlide10(slide.get(9));\r
}\r
\r
void verifySlide1(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Title Slide",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.CTR_TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
assertEquals("Centered Title", shape1.getText());\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(44.0, r1.getFontSize());\r
+ assertEquals(44.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertEquals(STPlaceholderType.SUB_TITLE, ph2.getType());\r
// anchor is not defined in the shape\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());\r
\r
assertEquals("subtitle", shape2.getText());\r
XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Calibri", r2.getFontFamily());\r
- assertEquals(32.0, r2.getFontSize());\r
+ assertEquals(32.0, r2.getFontSize(), 0);\r
// TODO fix calculation of tint\r
//assertEquals(new Color(137, 137, 137), r2.getFontColor());\r
}\r
\r
void verifySlide2(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Title and Content",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
assertEquals("Title", shape1.getText());\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(44.0, r1.getFontSize());\r
+ assertEquals(44.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertFalse(ph2.isSetType()); // <p:ph idx="1"/>\r
assertTrue(ph2.isSetIdx());\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());\r
\r
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr1.getParentParagraph().getLevel());\r
- assertEquals("Content", pr1.getText());\r
+ assertEquals("Content", pr1.getRawText());\r
assertEquals("Calibri", pr1.getFontFamily());\r
- assertEquals(32.0, pr1.getFontSize());\r
- assertEquals(27.0, pr1.getParentParagraph().getLeftMargin()); \r
+ assertEquals(32.0, pr1.getFontSize(), 0);\r
+ assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0); \r
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter()); \r
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());\r
\r
XSLFTextRun pr2 = shape2.getTextParagraphs().get(1).getTextRuns().get(0);\r
assertEquals(1, pr2.getParentParagraph().getLevel());\r
- assertEquals("Level 2", pr2.getText());\r
+ assertEquals("Level 2", pr2.getRawText());\r
assertEquals("Calibri", pr2.getFontFamily());\r
- assertEquals(28.0, pr2.getFontSize());\r
- assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());\r
+ assertEquals(28.0, pr2.getFontSize(), 0);\r
+ assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());\r
\r
XSLFTextRun pr3 = shape2.getTextParagraphs().get(2).getTextRuns().get(0);\r
assertEquals(2, pr3.getParentParagraph().getLevel());\r
- assertEquals("Level 3", pr3.getText());\r
+ assertEquals("Level 3", pr3.getRawText());\r
assertEquals("Calibri", pr3.getFontFamily());\r
- assertEquals(24.0, pr3.getFontSize());\r
- assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());\r
+ assertEquals(24.0, pr3.getFontSize(), 0);\r
+ assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());\r
\r
XSLFTextRun pr4 = shape2.getTextParagraphs().get(3).getTextRuns().get(0);\r
assertEquals(3, pr4.getParentParagraph().getLevel());\r
- assertEquals("Level 4", pr4.getText());\r
+ assertEquals("Level 4", pr4.getRawText());\r
assertEquals("Calibri", pr4.getFontFamily());\r
- assertEquals(20.0, pr4.getFontSize());\r
- assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());\r
+ assertEquals(20.0, pr4.getFontSize(), 0);\r
+ assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());\r
\r
XSLFTextRun pr5 = shape2.getTextParagraphs().get(4).getTextRuns().get(0);\r
assertEquals(4, pr5.getParentParagraph().getLevel());\r
- assertEquals("Level 5", pr5.getText());\r
+ assertEquals("Level 5", pr5.getRawText());\r
assertEquals("Calibri", pr5.getFontFamily());\r
- assertEquals(20.0, pr5.getFontSize());\r
- assertEquals(162.0, pr5.getParentParagraph().getLeftMargin());\r
+ assertEquals(20.0, pr5.getFontSize(), 0);\r
+ assertEquals(162.0, pr5.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u00bb", pr5.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr5.getParentParagraph().getBulletFont());\r
\r
\r
void verifySlide3(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Section Header",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(40.0, r1.getFontSize());\r
+ assertEquals(40.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
assertTrue(r1.isBold());\r
assertFalse(r1.isItalic());\r
- assertFalse(r1.isUnderline());\r
+ assertFalse(r1.isUnderlined());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertEquals(STPlaceholderType.BODY, ph2.getType());\r
// anchor is not defined in the shape\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.BOTTOM, shape2.getVerticalAlignment());\r
\r
assertEquals("Section Header", shape2.getText());\r
XSLFTextRun r2 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.LEFT, r2.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r2.getFontFamily());\r
- assertEquals(20.0, r2.getFontSize());\r
+ assertEquals(20.0, r2.getFontSize(), 0);\r
// TODO fix calculation of tint\r
//assertEquals(new Color(137, 137, 137), r2.getFontColor());\r
}\r
\r
void verifySlide4(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Two Content",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(44.0, r1.getFontSize());\r
+ assertEquals(44.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertFalse(ph2.isSetType());\r
assertTrue(ph2.isSetIdx());\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());\r
\r
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr1.getParentParagraph().getLevel());\r
- assertEquals("Left", pr1.getText());\r
+ assertEquals("Left", pr1.getRawText());\r
assertEquals("Calibri", pr1.getFontFamily());\r
- assertEquals(28.0, pr1.getFontSize());\r
- assertEquals(27.0, pr1.getParentParagraph().getLeftMargin());\r
+ assertEquals(28.0, pr1.getFontSize(), 0);\r
+ assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());\r
\r
assertEquals(1, pr2.getParentParagraph().getLevel());\r
assertEquals("Level 2", pr2.getParentParagraph().getText());\r
assertEquals("Calibri", pr2.getFontFamily());\r
- assertEquals(24.0, pr2.getFontSize());\r
- assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());\r
+ assertEquals(24.0, pr2.getFontSize(), 0);\r
+ assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());\r
\r
assertEquals(2, pr3.getParentParagraph().getLevel());\r
assertEquals("Level 3", pr3.getParentParagraph().getText());\r
assertEquals("Calibri", pr3.getFontFamily());\r
- assertEquals(20.0, pr3.getFontSize());\r
- assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());\r
+ assertEquals(20.0, pr3.getFontSize(), 0);\r
+ assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());\r
\r
assertEquals(3, pr4.getParentParagraph().getLevel());\r
assertEquals("Level 4", pr4.getParentParagraph().getText());\r
assertEquals("Calibri", pr4.getFontFamily());\r
- assertEquals(18.0, pr4.getFontSize());\r
- assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());\r
+ assertEquals(18.0, pr4.getFontSize(), 0);\r
+ assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());\r
\r
- XSLFTextShape shape3 = (XSLFTextShape)shapes[2];\r
+ XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2);\r
XSLFTextRun pr5 = shape3.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr5.getParentParagraph().getLevel());\r
- assertEquals("Right", pr5.getText());\r
+ assertEquals("Right", pr5.getRawText());\r
assertEquals("Calibri", pr5.getFontFamily());\r
assertEquals(Color.black, pr5.getFontColor());\r
}\r
\r
+ @SuppressWarnings("unused")\r
void verifySlide5(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
// TODO\r
} \r
\r
void verifySlide7(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Blank",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.MIDDLE, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(44.0, r1.getFontSize());\r
+ assertEquals(44.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
assertFalse(r1.isBold());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
\r
CTTextBodyProperties bodyPr2 = shape2.getTextBodyPr();\r
// none of the following properties are set in the shapes and fetched from the master shape\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());\r
\r
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr1.getParentParagraph().getLevel());\r
- assertEquals("Default Text", pr1.getText());\r
+ assertEquals("Default Text", pr1.getRawText());\r
assertEquals("Calibri", pr1.getFontFamily());\r
- assertEquals(18.0, pr1.getFontSize());\r
+ assertEquals(18.0, pr1.getFontSize(), 0);\r
\r
- XSLFTextShape shape3 = (XSLFTextShape)shapes[2];\r
+ XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2);\r
assertEquals("Default", shape3.getTextParagraphs().get(0).getText());\r
assertEquals("Text with levels", shape3.getTextParagraphs().get(1).getText());\r
assertEquals("Level 1", shape3.getTextParagraphs().get(2).getText());\r
for(int p = 0; p < 5; p++) {\r
XSLFTextParagraph pr = shape3.getTextParagraphs().get(p);\r
assertEquals("Calibri", pr.getTextRuns().get(0).getFontFamily());\r
- assertEquals(18.0, pr.getTextRuns().get(0).getFontSize());\r
+ assertEquals(18.0, pr.getTextRuns().get(0).getFontSize(), 0);\r
}\r
}\r
\r
void verifySlide8(XSLFSlide slide){\r
XSLFSlideLayout layout = slide.getSlideLayout();\r
- XSLFShape[] shapes = slide.getShapes();\r
+ List<XSLFShape> shapes = slide.getShapes();\r
assertEquals("Content with Caption",layout.getName());\r
\r
- XSLFTextShape shape1 = (XSLFTextShape)shapes[0];\r
+ XSLFTextShape shape1 = (XSLFTextShape)shapes.get(0);\r
CTPlaceholder ph1 = shape1.getCTPlaceholder();\r
assertEquals(STPlaceholderType.TITLE, ph1.getType());\r
// anchor is not defined in the shape\r
!bodyPr1.isSetBIns() && !bodyPr1.isSetTIns() &&\r
!bodyPr1.isSetAnchor()\r
);\r
- assertEquals(7.2, shape1.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape1.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape1.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape1.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape1.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape1.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape1.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape1.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.BOTTOM, shape1.getVerticalAlignment());\r
\r
// now check text properties\r
XSLFTextRun r1 = shape1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.LEFT, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(20.0, r1.getFontSize());\r
+ assertEquals(20.0, r1.getFontSize(), 0);\r
assertEquals(Color.black, r1.getFontColor());\r
assertTrue(r1.isBold());\r
\r
- XSLFTextShape shape2 = (XSLFTextShape)shapes[1];\r
+ XSLFTextShape shape2 = (XSLFTextShape)shapes.get(1);\r
CTPlaceholder ph2 = shape2.getCTPlaceholder();\r
assertFalse(ph2.isSetType());\r
assertTrue(ph2.isSetIdx());\r
!bodyPr2.isSetBIns() && !bodyPr2.isSetTIns() &&\r
!bodyPr2.isSetAnchor()\r
);\r
- assertEquals(7.2, shape2.getLeftInset()); // 0.1"\r
- assertEquals(7.2, shape2.getRightInset()); // 0.1"\r
- assertEquals(3.6, shape2.getTopInset()); // 0.05"\r
- assertEquals(3.6, shape2.getBottomInset()); // 0.05"\r
+ assertEquals(7.2, shape2.getLeftInset(), 0); // 0.1"\r
+ assertEquals(7.2, shape2.getRightInset(), 0); // 0.1"\r
+ assertEquals(3.6, shape2.getTopInset(), 0); // 0.05"\r
+ assertEquals(3.6, shape2.getBottomInset(), 0); // 0.05"\r
assertEquals(VerticalAlignment.TOP, shape2.getVerticalAlignment());\r
\r
XSLFTextRun pr1 = shape2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr1.getParentParagraph().getLevel());\r
- assertEquals("Level 1", pr1.getText());\r
+ assertEquals("Level 1", pr1.getRawText());\r
assertEquals("Calibri", pr1.getFontFamily());\r
- assertEquals(32.0, pr1.getFontSize());\r
- assertEquals(27.0, pr1.getParentParagraph().getLeftMargin());\r
+ assertEquals(32.0, pr1.getFontSize(), 0);\r
+ assertEquals(27.0, pr1.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2022", pr1.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr1.getParentParagraph().getBulletFont());\r
\r
assertEquals(1, pr2.getParentParagraph().getLevel());\r
assertEquals("Level 2", pr2.getParentParagraph().getText());\r
assertEquals("Calibri", pr2.getFontFamily());\r
- assertEquals(28.0, pr2.getFontSize());\r
- assertEquals(58.5, pr2.getParentParagraph().getLeftMargin());\r
+ assertEquals(28.0, pr2.getFontSize(), 0);\r
+ assertEquals(58.5, pr2.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr2.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr2.getParentParagraph().getBulletFont());\r
\r
assertEquals(2, pr3.getParentParagraph().getLevel());\r
assertEquals("Level 3", pr3.getParentParagraph().getText());\r
assertEquals("Calibri", pr3.getFontFamily());\r
- assertEquals(24.0, pr3.getFontSize());\r
- assertEquals(90.0, pr3.getParentParagraph().getLeftMargin());\r
+ assertEquals(24.0, pr3.getFontSize(), 0);\r
+ assertEquals(90.0, pr3.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2022", pr3.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr3.getParentParagraph().getBulletFont());\r
\r
assertEquals(3, pr4.getParentParagraph().getLevel());\r
assertEquals("Level 4", pr4.getParentParagraph().getText());\r
assertEquals("Calibri", pr4.getFontFamily());\r
- assertEquals(20.0, pr4.getFontSize());\r
- assertEquals(126.0, pr4.getParentParagraph().getLeftMargin());\r
+ assertEquals(20.0, pr4.getFontSize(), 0);\r
+ assertEquals(126.0, pr4.getParentParagraph().getLeftMargin(), 0);\r
assertEquals("\u2013", pr4.getParentParagraph().getBulletCharacter());\r
assertEquals("Arial", pr4.getParentParagraph().getBulletFont());\r
\r
- XSLFTextShape shape3 = (XSLFTextShape)shapes[2];\r
+ XSLFTextShape shape3 = (XSLFTextShape)shapes.get(2);\r
assertEquals(VerticalAlignment.TOP, shape3.getVerticalAlignment());\r
assertEquals("Content with caption", shape3.getText());\r
\r
pr1 = shape3.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(0, pr1.getParentParagraph().getLevel());\r
- assertEquals("Content with caption", pr1.getText());\r
+ assertEquals("Content with caption", pr1.getRawText());\r
assertEquals("Calibri", pr1.getFontFamily());\r
- assertEquals(14.0, pr1.getFontSize());\r
+ assertEquals(14.0, pr1.getFontSize(), 0);\r
\r
}\r
\r
XSLFTextRun r1 = footer.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(TextAlign.CENTER, r1.getParentParagraph().getTextAlign());\r
assertEquals("Calibri", r1.getFontFamily());\r
- assertEquals(12.0, r1.getFontSize());\r
+ assertEquals(12.0, r1.getFontSize(), 0);\r
// TODO calculation of tint is incorrect\r
assertEquals(new Color(64,64,64), r1.getFontColor());\r
\r
public void testTitleStyles(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
- XSLFSlideMaster master = ppt.getSlideMasters()[0];\r
+ XSLFSlideMaster master = ppt.getSlideMasters().get(0);\r
XSLFTheme theme = master.getTheme();\r
XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE);\r
XSLFSlide slide = ppt.createSlide(layout) ;\r
assertSame(layout, slide.getSlideLayout());\r
assertSame(master, slide.getSlideMaster());\r
\r
- XSLFTextShape titleShape = (XSLFTextShape)slide.getPlaceholder(0);\r
+ XSLFTextShape titleShape = slide.getPlaceholder(0);\r
titleShape.setText("Apache POI");\r
XSLFTextParagraph paragraph = titleShape.getTextParagraphs().get(0);\r
XSLFTextRun textRun = paragraph.getTextRuns().get(0);\r
CTTextParagraphProperties lv1PPr = master.getXmlObject().getTxStyles().getTitleStyle().getLvl1PPr();\r
CTTextCharacterProperties lv1CPr = lv1PPr.getDefRPr();\r
assertEquals(4400, lv1CPr.getSz());\r
- assertEquals(44.0, textRun.getFontSize());\r
+ assertEquals(44.0, textRun.getFontSize(), 0);\r
assertEquals("+mj-lt", lv1CPr.getLatin().getTypeface());\r
assertEquals("Calibri", theme.getMajorFont());\r
assertEquals("Calibri", textRun.getFontFamily());\r
lv1CPr.setSz(3200);\r
- assertEquals(32.0, textRun.getFontSize());\r
+ assertEquals(32.0, textRun.getFontSize(), 0);\r
lv1CPr.getLatin().setTypeface("Arial");\r
assertEquals("Arial", textRun.getFontFamily());\r
assertEquals(STTextAlignType.CTR, lv1PPr.getAlgn());\r
CTTextParagraphProperties lv2PPr = tx2.getTextBody(true).getLstStyle().addNewLvl1PPr();\r
CTTextCharacterProperties lv2CPr = lv2PPr.addNewDefRPr();\r
lv2CPr.setSz(3300);\r
- assertEquals(33.0, textRun.getFontSize());\r
+ assertEquals(33.0, textRun.getFontSize(), 0);\r
lv2CPr.addNewLatin().setTypeface("Times");\r
assertEquals("Times", textRun.getFontFamily());\r
lv2PPr.setAlgn(STTextAlignType.R);\r
CTTextParagraphProperties lv3PPr = tx3.getTextBody(true).getLstStyle().addNewLvl1PPr();\r
CTTextCharacterProperties lv3CPr = lv3PPr.addNewDefRPr();\r
lv3CPr.setSz(3400);\r
- assertEquals(34.0, textRun.getFontSize());\r
+ assertEquals(34.0, textRun.getFontSize(), 0);\r
lv3CPr.addNewLatin().setTypeface("Courier New");\r
assertEquals("Courier New", textRun.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.CTR);\r
CTTextParagraphProperties lv4PPr = titleShape.getTextBody(true).getLstStyle().addNewLvl1PPr();\r
CTTextCharacterProperties lv4CPr = lv4PPr.addNewDefRPr();\r
lv4CPr.setSz(3500);\r
- assertEquals(35.0, textRun.getFontSize());\r
+ assertEquals(35.0, textRun.getFontSize(), 0);\r
lv4CPr.addNewLatin().setTypeface("Arial");\r
assertEquals("Arial", textRun.getFontFamily());\r
lv4PPr.setAlgn(STTextAlignType.L);\r
CTTextParagraphProperties lv5PPr = paragraph.getXmlObject().addNewPPr();\r
CTTextCharacterProperties lv5CPr = textRun.getXmlObject().getRPr();\r
lv5CPr.setSz(3600);\r
- assertEquals(36.0, textRun.getFontSize());\r
+ assertEquals(36.0, textRun.getFontSize(), 0);\r
lv5CPr.addNewLatin().setTypeface("Calibri");\r
assertEquals("Calibri", textRun.getFontFamily());\r
lv5PPr.setAlgn(STTextAlignType.CTR);\r
public void testBodyStyles(){\r
XMLSlideShow ppt = new XMLSlideShow();\r
\r
- XSLFSlideMaster master = ppt.getSlideMasters()[0];\r
+ XSLFSlideMaster master = ppt.getSlideMasters().get(0);\r
XSLFTheme theme = master.getTheme();\r
XSLFSlideLayout layout = master.getLayout(SlideLayout.TITLE_AND_CONTENT);\r
XSLFSlide slide = ppt.createSlide(layout) ;\r
assertSame(layout, slide.getSlideLayout());\r
assertSame(master, slide.getSlideMaster());\r
\r
- XSLFTextShape tx1 = (XSLFTextShape)slide.getPlaceholder(1);\r
+ XSLFTextShape tx1 = slide.getPlaceholder(1);\r
tx1.clearText();\r
\r
XSLFTextParagraph p1 = tx1.addNewTextParagraph();\r
CTTextCharacterProperties lv3CPr = lv3PPr.getDefRPr();\r
// lv1\r
assertEquals(3200, lv1CPr.getSz());\r
- assertEquals(32.0, r1.getFontSize());\r
+ assertEquals(32.0, r1.getFontSize(), 0);\r
assertEquals("+mn-lt", lv1CPr.getLatin().getTypeface());\r
assertEquals("Calibri", theme.getMinorFont());\r
assertEquals("Calibri", r1.getFontFamily());\r
lv1CPr.setSz(3300);\r
- assertEquals(33.0, r1.getFontSize());\r
+ assertEquals(33.0, r1.getFontSize(), 0);\r
lv1CPr.getLatin().setTypeface("Arial");\r
assertEquals("Arial", r1.getFontFamily());\r
assertEquals(STTextAlignType.L, lv1PPr.getAlgn());\r
assertEquals(TextAlign.RIGHT, p1.getTextAlign());\r
//lv2\r
assertEquals(2800, lv2CPr.getSz());\r
- assertEquals(28.0, r2.getFontSize());\r
+ assertEquals(28.0, r2.getFontSize(), 0);\r
lv2CPr.setSz(3300);\r
- assertEquals(33.0, r2.getFontSize());\r
+ assertEquals(33.0, r2.getFontSize(), 0);\r
lv2CPr.getLatin().setTypeface("Times");\r
assertEquals("Times", r2.getFontFamily());\r
assertEquals(STTextAlignType.L, lv2PPr.getAlgn());\r
assertEquals(TextAlign.RIGHT, p2.getTextAlign());\r
//lv3\r
assertEquals(2400, lv3CPr.getSz());\r
- assertEquals(24.0, r3.getFontSize());\r
+ assertEquals(24.0, r3.getFontSize(), 0);\r
lv3CPr.setSz(2500);\r
- assertEquals(25.0, r3.getFontSize());\r
+ assertEquals(25.0, r3.getFontSize(), 0);\r
lv3CPr.getLatin().setTypeface("Courier New");\r
assertEquals("Courier New", r3.getFontFamily());\r
assertEquals(STTextAlignType.L, lv3PPr.getAlgn());\r
lv3CPr = lv3PPr.addNewDefRPr();\r
\r
lv1CPr.setSz(3300);\r
- assertEquals(33.0, r1.getFontSize());\r
+ assertEquals(33.0, r1.getFontSize(), 0);\r
lv1CPr.addNewLatin().setTypeface("Times");\r
assertEquals("Times", r1.getFontFamily());\r
lv1PPr.setAlgn(STTextAlignType.L);\r
assertEquals(TextAlign.LEFT, p1.getTextAlign());\r
\r
lv2CPr.setSz(3300);\r
- assertEquals(33.0, r2.getFontSize());\r
+ assertEquals(33.0, r2.getFontSize(), 0);\r
lv2CPr.addNewLatin().setTypeface("Times");\r
assertEquals("Times", r2.getFontFamily());\r
lv2PPr.setAlgn(STTextAlignType.L);\r
assertEquals(TextAlign.LEFT, p2.getTextAlign());\r
\r
lv3CPr.setSz(3300);\r
- assertEquals(33.0, r3.getFontSize());\r
+ assertEquals(33.0, r3.getFontSize(), 0);\r
lv3CPr.addNewLatin().setTypeface("Times");\r
assertEquals("Times", r3.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.L);\r
lv3CPr = lv3PPr.addNewDefRPr();\r
\r
lv1CPr.setSz(3400);\r
- assertEquals(34.0, r1.getFontSize());\r
+ assertEquals(34.0, r1.getFontSize(), 0);\r
lv1CPr.addNewLatin().setTypeface("Courier New");\r
assertEquals("Courier New", r1.getFontFamily());\r
lv1PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, p1.getTextAlign());\r
\r
lv2CPr.setSz(3400);\r
- assertEquals(34.0, r2.getFontSize());\r
+ assertEquals(34.0, r2.getFontSize(), 0);\r
lv2CPr.addNewLatin().setTypeface("Courier New");\r
assertEquals("Courier New", r2.getFontFamily());\r
lv2PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, p2.getTextAlign());\r
\r
lv3CPr.setSz(3400);\r
- assertEquals(34.0, r3.getFontSize());\r
+ assertEquals(34.0, r3.getFontSize(), 0);\r
lv3CPr.addNewLatin().setTypeface("Courier New");\r
assertEquals("Courier New", r3.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.CTR);\r
lv3CPr = lv3PPr.addNewDefRPr();\r
\r
lv1CPr.setSz(3500);\r
- assertEquals(35.0, r1.getFontSize());\r
+ assertEquals(35.0, r1.getFontSize(), 0);\r
lv1CPr.addNewLatin().setTypeface("Arial");\r
assertEquals("Arial", r1.getFontFamily());\r
lv1PPr.setAlgn(STTextAlignType.L);\r
assertEquals(TextAlign.LEFT, p1.getTextAlign());\r
\r
lv2CPr.setSz(3500);\r
- assertEquals(35.0, r2.getFontSize());\r
+ assertEquals(35.0, r2.getFontSize(), 0);\r
lv2CPr.addNewLatin().setTypeface("Arial");\r
assertEquals("Arial", r2.getFontFamily());\r
lv2PPr.setAlgn(STTextAlignType.L);\r
assertEquals(TextAlign.LEFT, p2.getTextAlign());\r
\r
lv3CPr.setSz(3500);\r
- assertEquals(35.0, r3.getFontSize());\r
+ assertEquals(35.0, r3.getFontSize(), 0);\r
lv3CPr.addNewLatin().setTypeface("Arial");\r
assertEquals("Arial", r3.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.L);\r
lv3CPr = r3.getXmlObject().getRPr();\r
\r
lv1CPr.setSz(3600);\r
- assertEquals(36.0, r1.getFontSize());\r
+ assertEquals(36.0, r1.getFontSize(), 0);\r
lv1CPr.addNewLatin().setTypeface("Calibri");\r
assertEquals("Calibri", r1.getFontFamily());\r
lv1PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, p1.getTextAlign());\r
\r
lv2CPr.setSz(3600);\r
- assertEquals(36.0, r2.getFontSize());\r
+ assertEquals(36.0, r2.getFontSize(), 0);\r
lv2CPr.addNewLatin().setTypeface("Calibri");\r
assertEquals("Calibri", r2.getFontFamily());\r
lv2PPr.setAlgn(STTextAlignType.CTR);\r
assertEquals(TextAlign.CENTER, p2.getTextAlign());\r
\r
lv3CPr.setSz(3600);\r
- assertEquals(36.0, r3.getFontSize());\r
+ assertEquals(36.0, r3.getFontSize(), 0);\r
lv3CPr.addNewLatin().setTypeface("Calibri");\r
assertEquals("Calibri", r3.getFontFamily());\r
lv3PPr.setAlgn(STTextAlignType.CTR);\r
==================================================================== */\r
package org.apache.poi.xslf.usermodel;\r
\r
-import junit.framework.TestCase;\r
-import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import static org.junit.Assert.*;\r
\r
import java.awt.Color;\r
-import java.awt.TexturePaint;\r
+import java.util.List;\r
+\r
+import org.apache.poi.sl.usermodel.*;\r
+import org.apache.poi.sl.usermodel.PaintStyle.GradientPaint;\r
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
+import org.apache.poi.sl.usermodel.PaintStyle.TexturePaint;\r
+import org.apache.poi.xslf.XSLFTestDataSamples;\r
+import org.junit.Test;\r
\r
/**\r
* test reading properties from a multi-theme and multi-master document\r
*\r
* @author Yegor Kozlov\r
*/\r
-public class TestXSLFTheme extends TestCase {\r
+public class TestXSLFTheme {\r
+ @Test\r
public void testRead(){\r
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("themes.pptx");\r
- XSLFSlide[] slides = ppt.getSlides();\r
-\r
- slide1(slides[0]);\r
- slide2(slides[1]);\r
- slide3(slides[2]);\r
- slide4(slides[3]);\r
- slide5(slides[4]);\r
- slide6(slides[5]);\r
- slide7(slides[6]);\r
- slide8(slides[7]);\r
- slide9(slides[8]);\r
- slide10(slides[9]);\r
+ List<XSLFSlide> slides = ppt.getSlides();\r
+\r
+ slide1(slides.get(0));\r
+ slide2(slides.get(1));\r
+ slide3(slides.get(2));\r
+ slide4(slides.get(3));\r
+ slide5(slides.get(4));\r
+ slide6(slides.get(5));\r
+ slide7(slides.get(6));\r
+ slide8(slides.get(7));\r
+ slide9(slides.get(8));\r
+ slide10(slides.get(9));\r
}\r
\r
private XSLFShape getShape(XSLFSheet sheet, String name){\r
assertEquals("Office Theme", theme.getName());\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 3");\r
- RenderableShape rsh1 = new RenderableShape(sh1);\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(Color.white, run1.getFontColor());\r
assertEquals(new Color(79, 129, 189), sh1.getFillColor());\r
- assertTrue(rsh1.getFillPaint(null) instanceof Color) ; // solid fill\r
+ assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill\r
\r
}\r
\r
}\r
\r
void slide3(XSLFSlide slide){\r
- assertNull(slide.getBackground().getFillColor());\r
- assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof GradientPaint);\r
}\r
\r
void slide4(XSLFSlide slide){\r
- assertNull(slide.getBackground().getFillColor());\r
- assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof GradientPaint);\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Rectangle 4");\r
- RenderableShape rsh1 = new RenderableShape(sh1);\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(Color.white, run1.getFontColor());\r
assertEquals(new Color(148, 198, 0), sh1.getFillColor());\r
- assertTrue(rsh1.getFillPaint(null) instanceof Color) ; // solid fill\r
+ assertTrue(sh1.getFillStyle().getPaint() instanceof SolidPaint) ; // solid fill\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 3");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
}\r
\r
void slide5(XSLFSlide slide){\r
- assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof TexturePaint);\r
\r
XSLFTextShape sh2 = (XSLFTextShape)getShape(slide, "Title 1");\r
XSLFTextRun run2 = sh2.getTextParagraphs().get(0).getTextRuns().get(0);\r
assertEquals(new Color(148, 198, 0), run2.getFontColor());\r
assertNull(sh2.getFillColor()); // no fill\r
// font size is 40pt and scale factor is 90%\r
- assertEquals(36.0, run2.getFontSize());\r
+ assertEquals(36.0, run2.getFontSize(), 0);\r
\r
assertTrue(slide.getSlideLayout().getFollowMasterGraphics());\r
}\r
}\r
\r
void slide8(XSLFSlide slide){\r
- assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof TexturePaint);\r
}\r
\r
void slide9(XSLFSlide slide){\r
- assertTrue(slide.getBackground().getPaint(null) instanceof TexturePaint);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof TexturePaint);\r
}\r
\r
void slide10(XSLFSlide slide){\r
- assertTrue(slide.getBackground().getPaint(null).getClass().getName().indexOf("Gradient") > 0);\r
+ PaintStyle fs = slide.getBackground().getFillStyle().getPaint();\r
+ assertTrue(fs instanceof GradientPaint);\r
\r
XSLFTextShape sh1 = (XSLFTextShape)getShape(slide, "Title 3");\r
XSLFTextRun run1 = sh1.getTextParagraphs().get(0).getTextRuns().get(0);\r
package org.apache.poi.hslf.blip;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.model.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.POILogFactory;
+
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.model.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.util.LittleEndian;
import java.io.IOException;
/**
* @return type of this picture
- * @see org.apache.poi.hslf.model.HSLFPictureShape#DIB
+ * @see org.apache.poi.hslf.usermodel.HSLFPictureShape#DIB
*/
public int getType(){
return HSLFPictureShape.DIB;
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.model.HSLFPictureShape;
-import org.apache.poi.hslf.model.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.exceptions.HSLFException;
import java.io.ByteArrayOutputStream;
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.model.HSLFPictureShape;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import java.awt.*;
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.model.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
/**
* Represents a JPEG picture data in a PPT file
/**
* @return type of this picture
- * @see org.apache.poi.hslf.model.HSLFPictureShape#JPEG
+ * @see org.apache.poi.hslf.usermodel.HSLFPictureShape#JPEG
*/
public int getType(){
return HSLFPictureShape.JPEG;
import java.util.zip.InflaterInputStream;
import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.hslf.model.HSLFPictureShape;
-import org.apache.poi.hslf.model.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
/**
* Represents Macintosh PICT picture data.
}
/**
- * @see org.apache.poi.hslf.model.HSLFPictureShape#PICT
+ * @see org.apache.poi.hslf.usermodel.HSLFPictureShape#PICT
*/
public int getType(){
return HSLFPictureShape.PICT;
package org.apache.poi.hslf.blip;
-import org.apache.poi.hslf.model.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.util.PngUtils;
/**
/**
* @return type of this picture
- * @see org.apache.poi.hslf.model.HSLFPictureShape#PNG
+ * @see org.apache.poi.hslf.usermodel.HSLFPictureShape#PNG
*/
public int getType(){
return HSLFPictureShape.PNG;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
-import org.apache.poi.hslf.model.HSLFPictureShape;
-import org.apache.poi.hslf.model.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
+import org.apache.poi.hslf.usermodel.HSLFShape;
import org.apache.poi.hslf.exceptions.HSLFException;
import java.io.*;
package org.apache.poi.hslf.dev;
import org.apache.poi.hslf.*;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
package org.apache.poi.hslf.dev;
-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;
import org.apache.poi.hslf.record.SlideListWithText;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
* Uses record level code to Documents.
package org.apache.poi.hslf.dev;
import org.apache.poi.hslf.*;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
* Uses record level code to locate SlideListWithText entries.
package org.apache.poi.hslf.dev;
import org.apache.poi.hslf.*;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
import java.io.ByteArrayOutputStream;
import java.util.Map;
-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;
import org.apache.poi.hslf.record.SlideListWithText;
import org.apache.poi.hslf.record.SlidePersistAtom;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.util.LittleEndian;
/**
import java.io.IOException;
import java.util.Iterator;
-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;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.StyleTextPropAtom;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
* This class provides a way to view the contents of a powerpoint file.
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;
-import org.apache.poi.hslf.record.*;
+import java.util.List;
-import java.util.LinkedList;
+import org.apache.poi.hslf.model.textproperties.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
/**
* Uses record level code to locate StyleTextPropAtom entries.
public static void showStyleTextPropAtom(StyleTextPropAtom stpa) {
System.out.println("\nFound a StyleTextPropAtom");
- LinkedList paragraphStyles = stpa.getParagraphStyles();
+ List<TextPropCollection> paragraphStyles = stpa.getParagraphStyles();
System.out.println("Contains " + paragraphStyles.size() + " paragraph styles:");
for(int i=0; i<paragraphStyles.size(); i++) {
- TextPropCollection tpc = (TextPropCollection)paragraphStyles.get(i);
+ TextPropCollection tpc = paragraphStyles.get(i);
System.out.println(" In paragraph styling " + i + ":");
System.out.println(" Characters covered is " + tpc.getCharactersCovered());
showTextProps(tpc);
}
- LinkedList charStyles = stpa.getCharacterStyles();
+ List<TextPropCollection> charStyles = stpa.getCharacterStyles();
System.out.println("Contains " + charStyles.size() + " character styles:");
for(int i=0; i<charStyles.size(); i++) {
- TextPropCollection tpc = (TextPropCollection)charStyles.get(i);
+ TextPropCollection tpc = charStyles.get(i);
System.out.println(" In character styling " + i + ":");
System.out.println(" Characters covered is " + tpc.getCharactersCovered());
showTextProps(tpc);
}
public static void showTextProps(TextPropCollection tpc) {
- LinkedList textProps = tpc.getTextPropList();
+ List<TextProp> textProps = tpc.getTextPropList();
System.out.println(" Contains " + textProps.size() + " TextProps");
for(int i=0; i<textProps.size(); i++) {
- TextProp tp = (TextProp)textProps.get(i);
+ TextProp tp = textProps.get(i);
System.out.println(" " + i + " - " + tp.getName());
System.out.println(" = " + tp.getValue());
System.out.println(" @ " + tp.getMask());
import java.io.ByteArrayOutputStream;
import java.util.Map;
-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;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.UserEditAtom;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.util.LittleEndian;
/**
package org.apache.poi.hslf.extractor;
-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 org.apache.poi.hslf.usermodel.*;
import java.io.IOException;
import java.io.FileOutputStream;
package org.apache.poi.hslf.extractor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ArrayList;
+import java.io.*;
+import java.util.*;
import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hslf.model.*;
-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;
+import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.poifs.filesystem.*;
/**
* This class can be used to extract text from a PowerPoint file. Can optionally
public final class PowerPointExtractor extends POIOLE2TextExtractor {
private HSLFSlideShowImpl _hslfshow;
private HSLFSlideShow _show;
- private HSLFSlide[] _slides;
+ private List<HSLFSlide> _slides;
private boolean _slidesByDefault = true;
private boolean _notesByDefault = false;
PowerPointExtractor ppe = new PowerPointExtractor(file);
System.out.println(ppe.getText(true, notes, comments, master));
+ ppe.close();
}
/**
public List<OLEShape> getOLEShapes() {
List<OLEShape> list = new ArrayList<OLEShape>();
- for (int i = 0; i < _slides.length; i++) {
- HSLFSlide slide = _slides[i];
-
- HSLFShape[] shapes = slide.getShapes();
- for (int j = 0; j < shapes.length; j++) {
- if (shapes[j] instanceof OLEShape) {
- list.add((OLEShape) shapes[j]);
+ for (HSLFSlide slide : _slides) {
+ for (HSLFShape shape : slide.getShapes()) {
+ if (shape instanceof OLEShape) {
+ list.add((OLEShape) shape);
}
}
}
if (getSlideText) {
if (getMasterText) {
- for (SlideMaster master : _show.getSlidesMasters()) {
+ for (HSLFSlideMaster master : _show.getSlideMasters()) {
for(HSLFShape sh : master.getShapes()){
if(sh instanceof HSLFTextShape){
if(HSLFMasterSheet.isPlaceholder(sh)) {
}
}
- for (int i = 0; i < _slides.length; i++) {
- HSLFSlide slide = _slides[i];
+ for (int i = 0; i < _slides.size(); i++) {
+ HSLFSlide slide = _slides.get(i);
// Slide header, if set
HeadersFooters hf = slide.getHeadersFooters();
}
// Slide text
- textRunsToText(ret, slide.getTextRuns());
+ textRunsToText(ret, slide.getTextParagraphs());
// Table text
for (HSLFShape shape : slide.getShapes()){
HashSet<Integer> seenNotes = new HashSet<Integer>();
HeadersFooters hf = _show.getNotesHeadersFooters();
- for (int i = 0; i < _slides.length; i++) {
- HSLFNotes notes = _slides[i].getNotesSheet();
+ for (int i = 0; i < _slides.size(); i++) {
+ HSLFNotes notes = _slides.get(i).getNotes();
if (notes == null) {
continue;
}
}
// Notes text
- textRunsToText(ret, notes.getTextRuns());
+ textRunsToText(ret, notes.getTextParagraphs());
// Repeat the notes footer, if set
if (hf != null && hf.isFooterVisible() && hf.getFooterText() != null) {
ret.append('\n');
}
}
- private void textRunsToText(StringBuffer ret, HSLFTextParagraph[] runs) {
- if (runs==null) {
+ private void textRunsToText(StringBuffer ret, List<List<HSLFTextParagraph>> paragraphs) {
+ if (paragraphs==null) {
return;
}
- for (int j = 0; j < runs.length; j++) {
- HSLFTextParagraph run = runs[j];
- if (run != null) {
- String text = run.getText();
- ret.append(text);
- if (!text.endsWith("\n")) {
+ for (List<HSLFTextParagraph> lp : paragraphs) {
+ for (HSLFTextParagraph p : lp) {
+ for (HSLFTextRun r : p.getTextRuns()) {
+ ret.append(r.getRawText());
+ }
+ if (ret.length() > 0 && ret.charAt(ret.length()-1) != '\n') {
ret.append("\n");
}
}
package org.apache.poi.hslf.extractor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
-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;
-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.*;
+import org.apache.poi.hslf.usermodel.HSLFTextParagraph;
+import org.apache.poi.hslf.usermodel.HSLFTextShape;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LittleEndian;
}
// Otherwise, check the type to see if it's text
- long type = LittleEndian.getUShort(pptContents,startPos+2);
- HSLFTextParagraph trun = null;
+ int type = LittleEndian.getUShort(pptContents,startPos+2);
// TextBytesAtom
if(type == RecordTypes.TextBytesAtom.typeID) {
TextBytesAtom tba = (TextBytesAtom)Record.createRecordForType(type, pptContents, startPos, len+8);
- trun = new HSLFTextParagraph((TextHeaderAtom)null,tba,(StyleTextPropAtom)null);
+ String text = HSLFTextParagraph.toExternalString(tba.getText(), -1);
+ textV.add(text);
}
// TextCharsAtom
if(type == RecordTypes.TextCharsAtom.typeID) {
TextCharsAtom tca = (TextCharsAtom)Record.createRecordForType(type, pptContents, startPos, len+8);
- trun = new HSLFTextParagraph((TextHeaderAtom)null,tca,(StyleTextPropAtom)null);
+ String text = HSLFTextParagraph.toExternalString(tca.getText(), -1);
+ textV.add(text);
}
// CString (doesn't go via a TextRun)
}
}
- // If we found text via a TextRun, save it in the vector
- if(trun != null) {
- textV.add(trun.getText());
- }
// Wind on by the atom length, and check we're not at the end
int newPos = (startPos + 8 + len);
import org.apache.poi.hslf.record.OEShapeAtom;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.LittleEndian;
+++ /dev/null
-/* ====================================================================
- 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.Arc2D;
-import java.awt.geom.Ellipse2D;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Line2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RoundRectangle2D;
-
-import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.sl.usermodel.ShapeType;
-
-/**
- * Stores definition of auto-shapes.
- * See the Office Drawing 97-2007 Binary Format Specification for details.
- *
- * TODO: follow the spec and define all the auto-shapes
- *
- * @author Yegor Kozlov
- */
-public final class AutoShapes {
- protected static final ShapeOutline[] shapes;
-
-
- /**
- * Return shape outline by shape type
- * @param type shape type see {@link ShapeTypes}
- *
- * @return the shape outline
- */
- public static ShapeOutline getShapeOutline(ShapeType type){
- ShapeOutline outline = shapes[type.nativeId];
- return outline;
- }
-
- /**
- * Auto-shapes are defined in the [0,21600] coordinate system.
- * We need to transform it into normal slide coordinates
- *
- */
- public static java.awt.Shape transform(java.awt.Shape outline, Rectangle2D anchor){
- AffineTransform at = new AffineTransform();
- at.translate(anchor.getX(), anchor.getY());
- at.scale(
- 1.0f/21600*anchor.getWidth(),
- 1.0f/21600*anchor.getHeight()
- );
- return at.createTransformedShape(outline);
- }
-
- static {
- shapes = new ShapeOutline[255];
-
- shapes[ShapeType.RECT.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- Rectangle2D path = new Rectangle2D.Float(0, 0, 21600, 21600);
- return path;
- }
- };
-
- shapes[ShapeType.ROUND_RECT.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
- RoundRectangle2D path = new RoundRectangle2D.Float(0, 0, 21600, 21600, adjval, adjval);
- return path;
- }
- };
-
- shapes[ShapeType.ELLIPSE.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- Ellipse2D path = new Ellipse2D.Float(0, 0, 21600, 21600);
- return path;
- }
- };
-
- shapes[ShapeType.DIAMOND.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- GeneralPath path = new GeneralPath();
- path.moveTo(10800, 0);
- path.lineTo(21600, 10800);
- path.lineTo(10800, 21600);
- path.lineTo(0, 10800);
- path.closePath();
- return path;
- }
- };
-
- //m@0,l,21600r21600
- shapes[ShapeType.TRIANGLE.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 10800);
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(0, 21600);
- path.lineTo(21600, 21600);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.RT_TRIANGLE.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- GeneralPath path = new GeneralPath();
- path.moveTo(0, 0);
- path.lineTo(21600, 21600);
- path.lineTo(0, 21600);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.PARALLELOGRAM.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(21600, 0);
- path.lineTo(21600 - adjval, 21600);
- path.lineTo(0, 21600);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.TRAPEZOID.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(0, 0);
- path.lineTo(adjval, 21600);
- path.lineTo(21600 - adjval, 21600);
- path.lineTo(21600, 0);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.HEXAGON.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(21600 - adjval, 0);
- path.lineTo(21600, 10800);
- path.lineTo(21600 - adjval, 21600);
- path.lineTo(adjval, 21600);
- path.lineTo(0, 10800);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.OCTAGON.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 6326);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(21600 - adjval, 0);
- path.lineTo(21600, adjval);
- path.lineTo(21600, 21600-adjval);
- path.lineTo(21600-adjval, 21600);
- path.lineTo(adjval, 21600);
- path.lineTo(0, 21600-adjval);
- path.lineTo(0, adjval);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.PLUS.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(21600 - adjval, 0);
- path.lineTo(21600 - adjval, adjval);
- path.lineTo(21600, adjval);
- path.lineTo(21600, 21600-adjval);
- path.lineTo(21600-adjval, 21600-adjval);
- path.lineTo(21600-adjval, 21600);
- path.lineTo(adjval, 21600);
- path.lineTo(adjval, 21600-adjval);
- path.lineTo(0, 21600-adjval);
- path.lineTo(0, adjval);
- path.lineTo(adjval, adjval);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.PENTAGON.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
-
- GeneralPath path = new GeneralPath();
- path.moveTo(10800, 0);
- path.lineTo(21600, 8259);
- path.lineTo(21600 - 4200, 21600);
- path.lineTo(4200, 21600);
- path.lineTo(0, 8259);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.DOWN_ARROW.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m0@0 l@1@0 @1,0 @2,0 @2@0,21600@0,10800,21600xe
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 16200);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 5400);
- GeneralPath path = new GeneralPath();
- path.moveTo(0, adjval);
- path.lineTo(adjval2, adjval);
- path.lineTo(adjval2, 0);
- path.lineTo(21600-adjval2, 0);
- path.lineTo(21600-adjval2, adjval);
- path.lineTo(21600, adjval);
- path.lineTo(10800, 21600);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.UP_ARROW.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m0@0 l@1@0 @1,21600@2,21600@2@0,21600@0,10800,xe
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 5400);
- GeneralPath path = new GeneralPath();
- path.moveTo(0, adjval);
- path.lineTo(adjval2, adjval);
- path.lineTo(adjval2, 21600);
- path.lineTo(21600-adjval2, 21600);
- path.lineTo(21600-adjval2, adjval);
- path.lineTo(21600, adjval);
- path.lineTo(10800, 0);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.RIGHT_ARROW.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m@0, l@0@1 ,0@1,0@2@0@2@0,21600,21600,10800xe
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 16200);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 5400);
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(adjval, adjval2);
- path.lineTo(0, adjval2);
- path.lineTo(0, 21600-adjval2);
- path.lineTo(adjval, 21600-adjval2);
- path.lineTo(adjval, 21600);
- path.lineTo(21600, 10800);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.LEFT_ARROW.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m@0, l@0@1,21600@1,21600@2@0@2@0,21600,,10800xe
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 5400);
- GeneralPath path = new GeneralPath();
- path.moveTo(adjval, 0);
- path.lineTo(adjval, adjval2);
- path.lineTo(21600, adjval2);
- path.lineTo(21600, 21600-adjval2);
- path.lineTo(adjval, 21600-adjval2);
- path.lineTo(adjval, 21600);
- path.lineTo(0, 10800);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.CAN.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m10800,qx0@1l0@2qy10800,21600,21600@2l21600@1qy10800,xem0@1qy10800@0,21600@1nfe
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 5400);
-
- GeneralPath path = new GeneralPath();
-
- path.append(new Arc2D.Float(0, 0, 21600, adjval, 0, 180, Arc2D.OPEN), false);
- path.moveTo(0, adjval/2);
-
- path.lineTo(0, 21600 - adjval/2);
- path.closePath();
-
- path.append(new Arc2D.Float(0, 21600 - adjval, 21600, adjval, 180, 180, Arc2D.OPEN), false);
- path.moveTo(21600, 21600 - adjval/2);
-
- path.lineTo(21600, adjval/2);
- path.append(new Arc2D.Float(0, 0, 21600, adjval, 180, 180, Arc2D.OPEN), false);
- path.moveTo(0, adjval/2);
- path.closePath();
- return path;
- }
- };
-
- shapes[ShapeType.LEFT_BRACE.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m21600,qx10800@0l10800@2qy0@11,10800@3l10800@1qy21600,21600e
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 1800);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 10800);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(21600, 0);
-
- path.append(new Arc2D.Float(10800, 0, 21600, adjval*2, 90, 90, Arc2D.OPEN), false);
- path.moveTo(10800, adjval);
-
- path.lineTo(10800, adjval2 - adjval);
-
- path.append(new Arc2D.Float(-10800, adjval2 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false);
- path.moveTo(0, adjval2);
-
- path.append(new Arc2D.Float(-10800, adjval2, 21600, adjval*2, 0, 90, Arc2D.OPEN), false);
- path.moveTo(10800, adjval2 + adjval);
-
- path.lineTo(10800, 21600 - adjval);
-
- path.append(new Arc2D.Float(10800, 21600 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false);
-
- return path;
- }
- };
-
- shapes[ShapeType.RIGHT_BRACE.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- //m,qx10800@0 l10800@2qy21600@11,10800@3l10800@1qy,21600e
- int adjval = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUSTVALUE, 1800);
- int adjval2 = shape.getEscherProperty(EscherProperties.GEOMETRY__ADJUST2VALUE, 10800);
-
- GeneralPath path = new GeneralPath();
- path.moveTo(0, 0);
-
- path.append(new Arc2D.Float(-10800, 0, 21600, adjval*2, 0, 90, Arc2D.OPEN), false);
- path.moveTo(10800, adjval);
-
- path.lineTo(10800, adjval2 - adjval);
-
- path.append(new Arc2D.Float(10800, adjval2 - 2*adjval, 21600, adjval*2, 180, 90, Arc2D.OPEN), false);
- path.moveTo(21600, adjval2);
-
- path.append(new Arc2D.Float(10800, adjval2, 21600, adjval*2, 90, 90, Arc2D.OPEN), false);
- path.moveTo(10800, adjval2 + adjval);
-
- path.lineTo(10800, 21600 - adjval);
-
- path.append(new Arc2D.Float(-10800, 21600 - 2*adjval, 21600, adjval*2, 270, 90, Arc2D.OPEN), false);
-
- return path;
- }
- };
-
- shapes[ShapeType.STRAIGHT_CONNECTOR_1.nativeId] = new ShapeOutline(){
- public java.awt.Shape getOutline(HSLFShape shape){
- return new Line2D.Float(0, 0, 21600, 21600);
- }
- };
-
-
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.
- * <p>
- * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments.
- * See {@link ShapeTypes}
- * </p>
- *
- * @author Yegor Kozlov
- */
-public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFTextParagraph> {
-
- protected HSLFAutoShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
- super(escherRecord, parent);
- }
-
- public HSLFAutoShape(ShapeType type, ShapeContainer<HSLFShape> 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.
- *
- * <p>
- * 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).
- * </p>
- *
- * @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.
- *
- * <p>
- * 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).
- * </p>
- *
- * @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);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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<HSLFShape> parent) {
- super(escherRecord, parent);
- }
-
- protected EscherContainerRecord createSpContainer(boolean isChild) {
- return null;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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 <code>Fill</code> 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 <code>FILL_*</code> 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<EscherRecord> lst = bstore.getChildRecords();
- return (EscherBSERecord)lst.get(idx-1);
- }
-
- /**
- * Sets fill type.
- * Must be one of the <code>FILL_*</code> 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);
- }
- }
-
- /**
- * <code>PictureData</code> 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<EscherRecord> 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 <code>SlideShow.addPicture</code> 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);
- }
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.
- *
- * <p>
- * 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 <code>java.awt.geom.GeneralPath</code>.
- * </p>
- * @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 <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected HSLFFreeformShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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<byte[]> segInfo = new ArrayList<byte[]>();
- List<Point2D.Double> pntInfo = new ArrayList<Point2D.Double>();
- 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);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.poi.ddf.EscherChildAnchorRecord;
-import org.apache.poi.ddf.EscherClientAnchorRecord;
-import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.ddf.EscherSpRecord;
-import org.apache.poi.ddf.EscherSpgrRecord;
-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;
-
-/**
- * Represents a group of shapes.
- *
- * @author Yegor Kozlov
- */
-public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShape> {
-
- /**
- * Create a new ShapeGroup. This constructor is used when a new shape is created.
- *
- */
- public HSLFGroupShape(){
- this(null, null);
- _escherContainer = createSpContainer(false);
- }
-
- /**
- * Create a ShapeGroup object and initilize it from the supplied Record container.
- *
- * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected HSLFGroupShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
- super(escherRecord, parent);
- }
-
- /**
- * @return the shapes contained in this group container
- */
- public HSLFShape[] getShapes() {
- List<HSLFShape> shapeList = getShapeList();
- HSLFShape[] shapes = shapeList.toArray(new HSLFShape[shapeList.size()]);
- return shapes;
- }
-
- /**
- * Sets the anchor (the bounding box rectangle) of this shape.
- * All coordinates should be expressed in Master units (576 dpi).
- *
- * @param anchor new anchor
- */
- public void setAnchor(java.awt.Rectangle anchor){
-
- EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- //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);
- clientAnchor.fillFields(header, 0, null);
-
- clientAnchor.setFlag((short)(anchor.y*MASTER_DPI/POINT_DPI));
- clientAnchor.setCol1((short)(anchor.x*MASTER_DPI/POINT_DPI));
- clientAnchor.setDx1((short)((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI));
- clientAnchor.setRow1((short)((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI));
-
- EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
-
- spgr.setRectX1(anchor.x*MASTER_DPI/POINT_DPI);
- spgr.setRectY1(anchor.y*MASTER_DPI/POINT_DPI);
- spgr.setRectX2((anchor.x + anchor.width)*MASTER_DPI/POINT_DPI);
- spgr.setRectY2((anchor.y + anchor.height)*MASTER_DPI/POINT_DPI);
- }
-
- /**
- * Sets the coordinate space of this group. All children are constrained
- * to these coordinates.
- *
- * @param anchor the coordinate space of this group
- */
- public void setCoordinates(Rectangle2D anchor){
- EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
-
- int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI);
- int y1 = (int)Math.round(anchor.getY()*MASTER_DPI/POINT_DPI);
- int x2 = (int)Math.round((anchor.getX() + anchor.getWidth())*MASTER_DPI/POINT_DPI);
- int y2 = (int)Math.round((anchor.getY() + anchor.getHeight())*MASTER_DPI/POINT_DPI);
-
- spgr.setRectX1(x1);
- spgr.setRectY1(y1);
- spgr.setRectX2(x2);
- spgr.setRectY2(y2);
-
- }
-
- /**
- * Gets the coordinate space of this group. All children are constrained
- * to these coordinates.
- *
- * @return the coordinate space of this group
- */
- public Rectangle2D getCoordinates(){
- EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
-
- Rectangle2D.Float anchor = new Rectangle2D.Float();
- anchor.x = (float)spgr.getRectX1()*POINT_DPI/MASTER_DPI;
- anchor.y = (float)spgr.getRectY1()*POINT_DPI/MASTER_DPI;
- anchor.width = (float)(spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI;
- anchor.height = (float)(spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI;
-
- return anchor;
- }
-
- /**
- * Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes
- */
- protected EscherContainerRecord createSpContainer(boolean isChild) {
- EscherContainerRecord spgr = new EscherContainerRecord();
- spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
- spgr.setOptions((short)15);
-
- //The group itself is a shape, and always appears as the first EscherSpContainer in the group container.
- EscherContainerRecord spcont = new EscherContainerRecord();
- spcont.setRecordId(EscherContainerRecord.SP_CONTAINER);
- spcont.setOptions((short)15);
-
- EscherSpgrRecord spg = new EscherSpgrRecord();
- spg.setOptions((short)1);
- spcont.addChildRecord(spg);
-
- EscherSpRecord sp = new EscherSpRecord();
- short type = (short)((ShapeType.NOT_PRIMITIVE.nativeId << 4) + 2);
- sp.setOptions(type);
- sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_GROUP);
- spcont.addChildRecord(sp);
-
- EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
- spcont.addChildRecord(anchor);
-
- spgr.addChildRecord(spcont);
- return spgr;
- }
-
- /**
- * Add a shape to this group.
- *
- * @param shape - the Shape to add
- */
- public void addShape(HSLFShape shape){
- _escherContainer.addChildRecord(shape.getSpContainer());
-
- HSLFSheet sheet = getSheet();
- shape.setSheet(sheet);
- shape.setShapeId(sheet.allocateShapeId());
- shape.afterInsert(sheet);
- }
-
- /**
- * Moves this <code>ShapeGroup</code> to the specified location.
- * <p>
- * @param x the x coordinate of the top left corner of the shape in new location
- * @param y the y coordinate of the top left corner of the shape in new location
- */
- public void moveTo(int x, int y){
- java.awt.Rectangle anchor = getAnchor();
- int dx = x - anchor.x;
- int dy = y - anchor.y;
- anchor.translate(dx, dy);
- setAnchor(anchor);
-
- HSLFShape[] shape = getShapes();
- for (int i = 0; i < shape.length; i++) {
- java.awt.Rectangle chanchor = shape[i].getAnchor();
- chanchor.translate(dx, dy);
- shape[i].setAnchor(chanchor);
- }
- }
-
- /**
- * Returns the anchor (the bounding box rectangle) of this shape group.
- * All coordinates are expressed in points (72 dpi).
- *
- * @return the anchor of this shape group
- */
- public Rectangle2D getAnchor2D(){
- EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- Rectangle2D.Float anchor = new Rectangle2D.Float();
- if(clientAnchor == null){
- logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord.");
- EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
- anchor = new Rectangle2D.Float(
- (float)rec.getDx1()*POINT_DPI/MASTER_DPI,
- (float)rec.getDy1()*POINT_DPI/MASTER_DPI,
- (float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
- (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
- );
- } else {
- anchor.x = (float)clientAnchor.getCol1()*POINT_DPI/MASTER_DPI;
- anchor.y = (float)clientAnchor.getFlag()*POINT_DPI/MASTER_DPI;
- anchor.width = (float)(clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ;
- anchor.height = (float)(clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI;
- }
-
- return anchor;
- }
-
- /**
- * Return type of the shape.
- * In most cases shape group type is {@link org.apache.poi.hslf.model.ShapeTypes#NotPrimitive}
- *
- * @return type of the shape.
- */
- public ShapeType getShapeType(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- int nativeId = spRecord.getOptions() >> 4;
- return ShapeType.forId(nativeId, false);
- }
-
- /**
- * Returns <code>null</code> - shape groups can't have hyperlinks
- *
- * @return <code>null</code>.
- */
- public Hyperlink getHyperlink(){
- return null;
- }
-
- public void draw(Graphics2D graphics){
-
- AffineTransform at = graphics.getTransform();
-
- HSLFShape[] sh = getShapes();
- for (int i = 0; i < sh.length; i++) {
- sh[i].draw(graphics);
- }
-
- graphics.setTransform(at);
- }
-
- @Override
- public <T extends EscherRecord> T getEscherChild(int recordId){
- EscherContainerRecord groupInfoContainer = (EscherContainerRecord)_escherContainer.getChild(0);
- return groupInfoContainer.getChildById((short)recordId);
- }
-
- public Iterator<HSLFShape> iterator() {
- return getShapeList().iterator();
- }
-
- public boolean removeShape(HSLFShape shape) {
- // TODO: implement!
- throw new UnsupportedOperationException();
- }
-
- /**
- * @return the shapes contained in this group container
- */
- protected List<HSLFShape> getShapeList() {
- // Out escher container record should contain several
- // SpContainers, the first of which is the group shape itself
- Iterator<EscherRecord> iter = _escherContainer.getChildIterator();
-
- // Don't include the first SpContainer, it is always NotPrimitive
- if (iter.hasNext()) {
- iter.next();
- }
- List<HSLFShape> shapeList = new ArrayList<HSLFShape>();
- while (iter.hasNext()) {
- EscherRecord r = iter.next();
- if(r instanceof EscherContainerRecord) {
- // Create the Shape for it
- EscherContainerRecord container = (EscherContainerRecord)r;
- HSLFShape shape = ShapeFactory.createShape(container, this);
- shape.setSheet(getSheet());
- shapeList.add( shape );
- } else {
- // Should we do anything special with these non
- // Container records?
- logger.log(POILogger.ERROR, "Shape contained non container escher record, was " + r.getClass().getName());
- }
- }
-
- return shapeList;
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.model.textproperties.TextProp;
-import org.apache.poi.sl.usermodel.MasterSheet;
-
-/**
- * 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 HSLFMasterSheet extends HSLFSheet implements MasterSheet<HSLFShape,HSLFSlideShow> {
- 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;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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<HSLFShape, HSLFSlideShow> {
- 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<HSLFTextParagraph> getTextParagraphs() {
- return Arrays.asList(_runs);
- }
-
- /**
- * Return <code>null</code> - Notes Masters are not yet supported
- */
- public HSLFMasterSheet getMasterSheet() {
- return null;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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 <code>Picture</code>
- *
- * @param idx the index of the picture
- */
- public HSLFPictureShape(int idx){
- this(idx, null);
- }
-
- /**
- * Create a new <code>Picture</code>
- *
- * @param idx the index of the picture
- * @param parent the parent shape
- */
- public HSLFPictureShape(int idx, ShapeContainer<HSLFShape> parent) {
- super(null, parent);
- _escherContainer = createSpContainer(idx, parent instanceof HSLFGroupShape);
- }
-
- /**
- * Create a <code>Picture</code> object
- *
- * @param escherRecord the <code>EscherSpContainer</code> record which holds information about
- * this picture in the <code>Slide</code>
- * @param parent the parent shape of this picture
- */
- protected HSLFPictureShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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 <code>EscherSp</code> record which holds information about this picture.
-
- * @param idx the index of the picture which refers to <code>EscherBSE</code> 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<EscherRecord> 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
+++ /dev/null
-/* ====================================================================
- 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.Rectangle2D;
-import java.util.Iterator;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.record.ColorSchemeAtom;
-import org.apache.poi.sl.usermodel.*;
-import org.apache.poi.util.*;
-
-/**
- * <p>
- * Represents a Shape which is the elemental object that composes a drawing.
- * This class is a wrapper around EscherSpContainer which holds all information
- * about a shape in PowerPoint document.
- * </p>
- * <p>
- * When you add a shape, you usually specify the dimensions of the shape and the position
- * of the upper'left corner of the bounding box for the shape relative to the upper'left
- * corner of the page, worksheet, or slide. Distances in the drawing layer are measured
- * in points (72 points = 1 inch).
- * </p>
- * <p>
- *
- * @author Yegor Kozlov
- */
-public abstract class HSLFShape implements Shape {
-
- // For logging
- protected POILogger logger = POILogFactory.getLogger(this.getClass());
-
- /**
- * In Escher absolute distances are specified in
- * English Metric Units (EMUs), occasionally referred to as A units;
- * there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point.
- */
- public static final int EMU_PER_INCH = 914400;
- public static final int EMU_PER_POINT = 12700;
- public static final int EMU_PER_CENTIMETER = 360000;
-
- /**
- * Master DPI (576 pixels per inch).
- * Used by the reference coordinate system in PowerPoint.
- */
- public static final int MASTER_DPI = 576;
-
- /**
- * Pixels DPI (96 pixels per inch)
- */
- public static final int PIXEL_DPI = 96;
-
- /**
- * Points DPI (72 pixels per inch)
- */
- public static final int POINT_DPI = 72;
-
- /**
- * Either EscherSpContainer or EscheSpgrContainer record
- * which holds information about this shape.
- */
- protected EscherContainerRecord _escherContainer;
-
- /**
- * Parent of this shape.
- * <code>null</code> for the topmost shapes.
- */
- protected ShapeContainer<HSLFShape> _parent;
-
- /**
- * The <code>Sheet</code> this shape belongs to
- */
- protected HSLFSheet _sheet;
-
- /**
- * Fill
- */
- protected HSLFFill _fill;
-
- /**
- * Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
- *
- * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of this Shape
- */
- protected HSLFShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
- _escherContainer = escherRecord;
- _parent = parent;
- }
-
- /**
- * Creates the lowerlevel escher records for this shape.
- */
- protected abstract EscherContainerRecord createSpContainer(boolean isChild);
-
- /**
- * @return the parent of this shape
- */
- public ShapeContainer<HSLFShape> getParent(){
- return _parent;
- }
-
- /**
- * @return name of the shape.
- */
- public String getShapeName(){
- return getShapeType().nativeName;
- }
-
- /**
- * @return type of the shape.
- * @see org.apache.poi.hslf.record.RecordTypes
- */
- public ShapeType getShapeType(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- return ShapeType.forId(spRecord.getShapeType(), false);
- }
-
- /**
- * @param type type of the shape.
- * @see org.apache.poi.hslf.record.RecordTypes
- */
- public void setShapeType(ShapeType type){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- spRecord.setShapeType( (short) type.nativeId );
- spRecord.setVersion( (short) 0x2 );
- }
-
- /**
- * Returns the anchor (the bounding box rectangle) of this shape.
- * All coordinates are expressed in points (72 dpi).
- *
- * @return the anchor of this shape
- */
- public java.awt.Rectangle getAnchor(){
- Rectangle2D anchor2d = getAnchor2D();
- return anchor2d.getBounds();
- }
-
- /**
- * Returns the anchor (the bounding box rectangle) of this shape.
- * All coordinates are expressed in points (72 dpi).
- *
- * @return the anchor of this shape
- */
- public Rectangle2D getAnchor2D(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- int flags = spRecord.getFlags();
- Rectangle2D anchor=null;
- if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
- EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
- anchor = new java.awt.Rectangle();
- if(rec == null){
- logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found");
- EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- anchor = new java.awt.Rectangle();
- anchor = new Rectangle2D.Float(
- (float)clrec.getCol1()*POINT_DPI/MASTER_DPI,
- (float)clrec.getFlag()*POINT_DPI/MASTER_DPI,
- (float)(clrec.getDx1()-clrec.getCol1())*POINT_DPI/MASTER_DPI,
- (float)(clrec.getRow1()-clrec.getFlag())*POINT_DPI/MASTER_DPI
- );
- } else {
- anchor = new Rectangle2D.Float(
- (float)rec.getDx1()*POINT_DPI/MASTER_DPI,
- (float)rec.getDy1()*POINT_DPI/MASTER_DPI,
- (float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
- (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
- );
- }
- }
- else {
- EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- anchor = new java.awt.Rectangle();
- anchor = new Rectangle2D.Float(
- (float)rec.getCol1()*POINT_DPI/MASTER_DPI,
- (float)rec.getFlag()*POINT_DPI/MASTER_DPI,
- (float)(rec.getDx1()-rec.getCol1())*POINT_DPI/MASTER_DPI,
- (float)(rec.getRow1()-rec.getFlag())*POINT_DPI/MASTER_DPI
- );
- }
- return anchor;
- }
-
- public Rectangle2D getLogicalAnchor2D(){
- return getAnchor2D();
- }
-
- /**
- * Sets the anchor (the bounding box rectangle) of this shape.
- * All coordinates should be expressed in points (72 dpi).
- *
- * @param anchor new anchor
- */
- public void setAnchor(Rectangle2D anchor){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- int flags = spRecord.getFlags();
- if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
- EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(EscherChildAnchorRecord.RECORD_ID);
- rec.setDx1((int)(anchor.getX()*MASTER_DPI/POINT_DPI));
- rec.setDy1((int)(anchor.getY()*MASTER_DPI/POINT_DPI));
- rec.setDx2((int)((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI));
- rec.setDy2((int)((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI));
- }
- else {
- EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(EscherClientAnchorRecord.RECORD_ID);
- rec.setFlag((short)(anchor.getY()*MASTER_DPI/POINT_DPI));
- rec.setCol1((short)(anchor.getX()*MASTER_DPI/POINT_DPI));
- rec.setDx1((short)(((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI)));
- rec.setRow1((short)(((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI)));
- }
-
- }
-
- /**
- * Moves the top left corner of the shape to the specified point.
- *
- * @param x the x coordinate of the top left corner of the shape
- * @param y the y coordinate of the top left corner of the shape
- */
- public void moveTo(float x, float y){
- Rectangle2D anchor = getAnchor2D();
- anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
- setAnchor(anchor);
- }
-
- /**
- * Helper method to return escher child by record ID
- *
- * @return escher record or <code>null</code> if not found.
- */
- public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
- return owner.getChildById((short)recordId);
- }
-
- public <T extends EscherRecord> T getEscherChild(int recordId){
- return _escherContainer.getChildById((short)recordId);
- }
-
- /**
- * Returns escher property by id.
- *
- * @return escher property or <code>null</code> if not found.
- */
- public static <T extends EscherProperty> T getEscherProperty(EscherOptRecord opt, int propId){
- return opt.lookup(propId);
- }
-
- /**
- * Set an escher property for this shape.
- *
- * @param opt The opt record to set the properties to.
- * @param propId The id of the property. One of the constants defined in EscherOptRecord.
- * @param value value of the property. If value = -1 then the property is removed.
- */
- public static void setEscherProperty(EscherOptRecord opt, short propId, int value){
- java.util.List<EscherProperty> props = opt.getEscherProperties();
- for ( Iterator<EscherProperty> iterator = props.iterator(); iterator.hasNext(); ) {
- if (iterator.next().getPropertyNumber() == propId){
- iterator.remove();
- break;
- }
- }
- if (value != -1) {
- opt.addEscherProperty(new EscherSimpleProperty(propId, value));
- opt.sortProperties();
- }
- }
-
- /**
- * Set an simple escher property for this shape.
- *
- * @param propId The id of the property. One of the constants defined in EscherOptRecord.
- * @param value value of the property. If value = -1 then the property is removed.
- */
- public void setEscherProperty(short propId, int value){
- EscherOptRecord opt = getEscherOptRecord();
- setEscherProperty(opt, propId, value);
- }
-
- /**
- * Get the value of a simple escher property for this shape.
- *
- * @param propId The id of the property. One of the constants defined in EscherOptRecord.
- */
- public int getEscherProperty(short propId){
- EscherOptRecord opt = getEscherOptRecord();
- EscherSimpleProperty prop = getEscherProperty(opt, propId);
- return prop == null ? 0 : prop.getPropertyValue();
- }
-
- /**
- * Get the value of a simple escher property for this shape.
- *
- * @param propId The id of the property. One of the constants defined in EscherOptRecord.
- */
- public int getEscherProperty(short propId, int defaultValue){
- EscherOptRecord opt = getEscherOptRecord();
- EscherSimpleProperty prop = getEscherProperty(opt, propId);
- return prop == null ? defaultValue : prop.getPropertyValue();
- }
-
- /**
- * @return The shape container and it's children that can represent this
- * shape.
- */
- public EscherContainerRecord getSpContainer(){
- return _escherContainer;
- }
-
- /**
- * Event which fires when a shape is inserted in the sheet.
- * In some cases we need to propagate changes to upper level containers.
- * <br>
- * Default implementation does nothing.
- *
- * @param sh - owning shape
- */
- protected void afterInsert(HSLFSheet sh){
- if(_fill != null) {
- _fill.afterInsert(sh);
- }
- }
-
- /**
- * @return the <code>SlideShow</code> this shape belongs to
- */
- public HSLFSheet getSheet(){
- return _sheet;
- }
-
- /**
- * Assign the <code>SlideShow</code> this shape belongs to
- *
- * @param sheet owner of this shape
- */
- public void setSheet(HSLFSheet sheet){
- _sheet = sheet;
- }
-
- Color getColor(short colorProperty, short opacityProperty, int defaultColor){
- EscherOptRecord opt = getEscherOptRecord();
- EscherSimpleProperty p = getEscherProperty(opt, colorProperty);
- if(p == null && defaultColor == -1) return null;
-
- int val = (p == null) ? defaultColor : p.getPropertyValue();
-
- EscherColorRef ecr = new EscherColorRef(val);
-
- boolean fPaletteIndex = ecr.hasPaletteIndexFlag();
- boolean fPaletteRGB = ecr.hasPaletteRGBFlag();
- boolean fSystemRGB = ecr.hasSystemRGBFlag();
- boolean fSchemeIndex = ecr.hasSchemeIndexFlag();
- boolean fSysIndex = ecr.hasSysIndexFlag();
-
- int rgb[] = ecr.getRGB();
-
- HSLFSheet sheet = getSheet();
- if (fSchemeIndex && sheet != null) {
- //red is the index to the color scheme
- ColorSchemeAtom ca = sheet.getColorScheme();
- int schemeColor = ca.getColor(ecr.getSchemeIndex());
-
- rgb[0] = (schemeColor >> 0) & 0xFF;
- rgb[1] = (schemeColor >> 8) & 0xFF;
- rgb[2] = (schemeColor >> 16) & 0xFF;
- } else if (fPaletteIndex){
- //TODO
- } else if (fPaletteRGB){
- //TODO
- } else if (fSystemRGB){
- //TODO
- } else if (fSysIndex){
- //TODO
- }
-
- double alpha = getAlpha(opacityProperty);
- return new Color(rgb[0], rgb[1], rgb[2], (int)(alpha*255.0));
- }
-
- double getAlpha(short opacityProperty) {
- EscherOptRecord opt = getEscherOptRecord();
- EscherSimpleProperty op = getEscherProperty(opt, opacityProperty);
- int defaultOpacity = 0x00010000;
- int opacity = (op == null) ? defaultOpacity : op.getPropertyValue();
- return Units.fixedPointToDouble(opacity);
- }
-
- Color toRGB(int val){
- int a = (val >> 24) & 0xFF;
- int b = (val >> 16) & 0xFF;
- int g = (val >> 8) & 0xFF;
- int r = (val >> 0) & 0xFF;
-
- if(a == 0xFE){
- // Color is an sRGB value specified by red, green, and blue fields.
- } else if (a == 0xFF){
- // Color is undefined.
- } else {
- // index in the color scheme
- ColorSchemeAtom ca = getSheet().getColorScheme();
- int schemeColor = ca.getColor(a);
-
- r = (schemeColor >> 0) & 0xFF;
- g = (schemeColor >> 8) & 0xFF;
- b = (schemeColor >> 16) & 0xFF;
- }
- return new Color(r, g, b);
- }
-
- /**
- * @return id for the shape.
- */
- public int getShapeId(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- return spRecord == null ? 0 : spRecord.getShapeId();
- }
-
- /**
- * Sets shape ID
- *
- * @param id of the shape
- */
- public void setShapeId(int id){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- if(spRecord != null) spRecord.setShapeId(id);
- }
-
- /**
- * Fill properties of this shape
- *
- * @return fill properties of this shape
- */
- public HSLFFill getFill(){
- if(_fill == null) {
- _fill = new HSLFFill(this);
- }
- return _fill;
- }
-
- public FillStyle getFillStyle() {
- return getFill().getFillStyle();
- }
-
- /**
- * Returns the hyperlink assigned to this shape
- *
- * @return the hyperlink assigned to this shape
- * or <code>null</code> if not found.
- */
- public Hyperlink getHyperlink(){
- return Hyperlink.find(this);
- }
-
- public void draw(Graphics2D graphics){
- logger.log(POILogger.INFO, "Rendering " + getShapeName());
- }
-
- /**
- * Return shape outline as a java.awt.Shape object
- *
- * @return the shape outline
- */
- public java.awt.Shape getOutline(){
- return getLogicalAnchor2D();
- }
-
- public EscherOptRecord getEscherOptRecord() {
- return getEscherChild(EscherOptRecord.RECORD_ID);
- }
-
- public boolean getFlipHorizontal(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPHORIZ) != 0;
- }
-
- public void setFlipHorizontal(boolean flip) {
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ;
- spRecord.setFlags(flag);
- }
-
- public boolean getFlipVertical(){
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPVERT) != 0;
- }
-
- public void setFlipVertical(boolean flip) {
- EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
- int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPVERT;
- spRecord.setFlags(flag);
- }
-
- public double getRotation(){
- int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION);
- double angle = Units.fixedPointToDouble(rot) % 360.0;
- return angle;
- }
-
- public void setRotation(double theta){
- int rot = Units.doubleToFixedPoint(theta % 360.0);
- setEscherProperty(EscherProperties.TRANSFORM__ROTATION, rot);
- }
-
- public boolean isPlaceholder() {
- return false;
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.*;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.sl.usermodel.Sheet;
-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 HSLFSheet implements Sheet<HSLFShape,HSLFSlideShow> {
- private static POILogger logger = POILogFactory.getLogger(HSLFSheet.class);
-
- /**
- * The <code>SlideShow</code> 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<HSLFTextParagraph> runsV = new ArrayList<HSLFTextParagraph>();
- 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<HSLFTextParagraph> 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<HSLFTextParagraph> 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<HSLFTextParagraph> 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<Record> lst = new ArrayList<Record>();
- 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<HSLFShape> 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 <tt>true</tt> if the shape was deleted.
- */
- public boolean removeShape(HSLFShape shape) {
- PPDrawing ppdrawing = getPPDrawing();
-
- EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
- EscherContainerRecord spgr = null;
-
- for (Iterator<EscherRecord> 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<EscherRecord> 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<EscherRecord> 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 <code>TextShape</code> or <code>null</code>
- */
- 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 <code>TextShape</code> or <code>null</code>
- */
- 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. <code>___PPT12</code>.
- *
- * @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<HSLFShape> iterator() {
- return getShapeList().iterator();
- }
-
-
- /**
- * Returns all shapes contained in this Sheet
- *
- * @return all shapes contained in this Sheet (Slide or Notes)
- */
- protected List<HSLFShape> getShapeList() {
- PPDrawing ppdrawing = getPPDrawing();
-
- EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
- EscherContainerRecord spgr = null;
-
- for (Iterator<EscherRecord> 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<HSLFShape> shapeList = new ArrayList<HSLFShape>();
- Iterator<EscherRecord> 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;
- }
-
-
-}
+++ /dev/null
-/* ====================================================================
- 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 <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected HSLFSimpleShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
- super(escherRecord, parent);
- }
-
- /**
- * Create a new Shape
- *
- * @param isChild <code>true</code> if the Line is inside a group, <code>false</code> 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 <code>java.awt.Color.black</code>
- */
- 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<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>();
- for (ShapeContainer<HSLFShape> 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 extends Record> 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 <code>null</code>
- */
- 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());
-
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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<HSLFShape,HSLFSlideShow> {
- 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<HSLFTextParagraph> textParagraphs = new LinkedList<HSLFTextParagraph>();
- 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.
- * <p>
- * For Slide we need to do the following:
- * <li> set id of the drawing group.
- * <li> set shapeId for the container descriptor and background
- * </p>
- */
- 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 <code>TextBox</code> object that represents the slide's title.
- *
- * @return <code>TextBox</code> 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 <code>null</code> if the slide does not have title.
- * <p>
- * The title is a run of text of type <code>TextHeaderAtom.CENTER_TITLE_TYPE</code> or
- * <code>TextHeaderAtom.TITLE_TYPE</code>
- * </p>
- *
- * @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 <code>SlideListWithtext</code> 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 <code>true</code> if the slide follows master,
- * <code>false</code> otherwise
- */
- public void setFollowMasterBackground(boolean flag){
- SlideAtom sa = getSlideRecord().getSlideAtom();
- sa.setFollowMasterBackground(flag);
- }
-
- /**
- * Whether this slide follows master sheet background
- *
- * @return <code>true</code> if the slide follows master background,
- * <code>false</code> otherwise
- */
- public boolean getFollowMasterBackground(){
- SlideAtom sa = getSlideRecord().getSlideAtom();
- return sa.getFollowMasterBackground();
- }
-
- /**
- * Sets whether this slide draws master sheet objects
- *
- * @param flag <code>true</code> if the slide draws master sheet objects,
- * <code>false</code> otherwise
- */
- public void setFollowMasterObjects(boolean flag){
- SlideAtom sa = getSlideRecord().getSlideAtom();
- sa.setFollowMasterObjects(flag);
- }
-
- /**
- * Whether this slide follows master color scheme
- *
- * @return <code>true</code> if the slide follows master color scheme,
- * <code>false</code> otherwise
- */
- public boolean getFollowMasterScheme(){
- SlideAtom sa = getSlideRecord().getSlideAtom();
- return sa.getFollowMasterScheme();
- }
-
- /**
- * Sets whether this slide draws master color scheme
- *
- * @param flag <code>true</code> if the slide draws master color scheme,
- * <code>false</code> otherwise
- */
- public void setFollowMasterScheme(boolean flag){
- SlideAtom sa = getSlideRecord().getSlideAtom();
- sa.setFollowMasterScheme(flag);
- }
-
- /**
- * Whether this slide draws master sheet objects
- *
- * @return <code>true</code> if the slide draws master sheet objects,
- * <code>false</code> 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<binaryTags.getChildRecords().length; i++) {
- if(binaryTags.getChildRecords()[i] instanceof Comment2000) {
- count++;
- }
- }
-
- // Now build
- Comment[] comments = new Comment[count];
- count = 0;
- for(int i=0; i<binaryTags.getChildRecords().length; i++) {
- if(binaryTags.getChildRecords()[i] instanceof Comment2000) {
- comments[i] = new Comment(
- (Comment2000)binaryTags.getChildRecords()[i]
- );
- count++;
- }
- }
-
- return comments;
- }
- }
- }
-
- // None found
- return new Comment[0];
- }
-
- public void draw(Graphics2D graphics){
- HSLFMasterSheet master = getMasterSheet();
- HSLFBackground bg = getBackground();
- if(bg != null)bg.draw(graphics);
-
- if(getFollowMasterObjects()){
- HSLFShape[] sh = master.getShapes();
- for (int i = 0; i < sh.length; i++) {
- if(HSLFMasterSheet.isPlaceholder(sh[i])) continue;
-
- sh[i].draw(graphics);
- }
- }
-
- HSLFShape[] sh = getShapes();
- for (int i = 0; i < sh.length; i++) {
- sh[i].draw(graphics);
- }
- }
-
- /**
- * Header / Footer settings for this slide.
- *
- * @return Header / Footer settings for this slide
- */
- public HeadersFooters getHeadersFooters(){
- HeadersFootersContainer hdd = null;
- Record[] ch = getSheetContainer().getChildRecords();
- boolean ppt2007 = false;
- for (int i = 0; i < ch.length; i++) {
- if(ch[i] instanceof HeadersFootersContainer){
- hdd = (HeadersFootersContainer)ch[i];
- } else if (ch[i].getRecordType() == RecordTypes.RoundTripContentMasterId.typeID){
- ppt2007 = true;
- }
- }
- boolean newRecord = false;
- if(hdd == null && !ppt2007) {
- return getSlideShow().getSlideHeadersFooters();
- }
- if(hdd == null) {
- hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer);
- newRecord = true;
- }
- return new HeadersFooters(hdd, this, newRecord, ppt2007);
- }
-
- protected void onAddTextShape(HSLFTextShape shape) {
- HSLFTextParagraph run = shape.getTextParagraph();
-
- if(_runs == null) _runs = new HSLFTextParagraph[]{run};
- else {
- HSLFTextParagraph[] tmp = new HSLFTextParagraph[_runs.length + 1];
- System.arraycopy(_runs, 0, tmp, 0, _runs.length);
- tmp[tmp.length-1] = run;
- _runs = tmp;
- }
- }
-
- /** This will return an atom per TextBox, so if the page has two text boxes the method should return two atoms. */
- public StyleTextProp9Atom[] getNumberedListInfo() {
- return this.getPPDrawing().getNumberedListInfo();
- }
-
- public EscherTextboxWrapper[] getTextboxWrappers() {
- return this.getPPDrawing().getTextboxWrappers();
- }
-
- public void setHidden(boolean hidden) {
- org.apache.poi.hslf.record.Slide cont = getSlideRecord();
-
- SSSlideInfoAtom slideInfo =
- (SSSlideInfoAtom)cont.findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
- if (slideInfo == null) {
- slideInfo = new SSSlideInfoAtom();
- cont.addChildAfter(slideInfo, cont.findFirstOfType(RecordTypes.SlideAtom.typeID));
- }
-
- slideInfo.setEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT, hidden);
- }
-
- public boolean getHidden() {
- SSSlideInfoAtom slideInfo =
- (SSSlideInfoAtom)getSlideRecord().findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
- return (slideInfo == null)
- ? false
- : slideInfo.getEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT);
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.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 HSLFSlideShowEncrypted {
- DocumentEncryptionAtom dea;
- CryptoAPIEncryptor enc = null;
- CryptoAPIDecryptor dec = null;
- Cipher cipher = null;
- CipherOutputStream cyos = null;
-
- private static final BitField fieldRecInst = new BitField(0xFFF0);
-
- protected HSLFSlideShowEncrypted(DocumentEncryptionAtom dea) {
- this.dea = dea;
- }
-
- protected HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer,Record> 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<Integer, Record> 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<rgbUidCnt; i++) {
- cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
- offset += 16;
- }
-
- if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
- cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
- offset += 34;
- } else {
- cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
- offset += 1;
- }
-
- int blipLen = endOffset - offset;
- cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
- } catch (GeneralSecurityException e) {
- throw new CorruptPowerPointFileException(e);
- }
- }
-
- protected void encryptPicture(byte[] pictstream, int offset) {
- if (dea == null) return;
-
- encryptInit();
- setPersistId(0);
-
- try {
- int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
- int recType = LittleEndian.getUShort(pictstream, offset+2);
- int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
- cipher.doFinal(pictstream, offset, 8, pictstream, offset);
- 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;
- int cbName = LittleEndian.getUShort(pictstream, offset+1);
- 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
- 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
- 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<rgbUidCnt; i++) {
- cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
- offset += 16;
- }
-
- if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
- cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
- offset += 34;
- } else {
- cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
- offset += 1;
- }
-
- int blipLen = endOffset - offset;
- cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
- } catch (GeneralSecurityException e) {
- throw new CorruptPowerPointFileException(e);
- }
- }
-
- protected Record[] updateEncryptionRecord(Record records[]) {
- String password = Biff8EncryptionKey.getCurrentUserPassword();
- if (password == null) {
- if (dea == null) {
- // no password given, no encryption record exits -> 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<Integer,Integer> slideLocations = new TreeMap<Integer,Integer>();
- TreeMap<Integer,Record> recordMap = new TreeMap<Integer,Record>();
- List<Integer> obsoleteOffsets = new ArrayList<Integer>();
- 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<Integer,Integer> 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<Integer,Integer> 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<Record> recordList = new ArrayList<Record>();
- 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<Integer,Integer> tm = new TreeMap<Integer,Integer>(ptr.getSlideLocationsLookup());
- ptr.clear();
- int maxSlideId = -1;
- for (Map.Entry<Integer,Integer> 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;
- }
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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<HSLFPictureData> _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:
- // <little endian 2 byte "info">
- // <little endian 2 byte "type">
- // <little endian 4 byte "length">
- // If it has a zero length, following it will be another record
- // <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
- // If it has a length, depending on its type it may have children or data
- // If it has children, these will follow straight away
- // <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
- // If it has data, this will come straigh after, and run for the length
- // <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
- // 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<Integer,Record> records = new TreeMap<Integer,Record>(); // offset -> record
- Map<Integer,Integer> persistIds = new HashMap<Integer,Integer>(); // offset -> persistId
- initRecordOffsets(docstream, usrOffset, records, persistIds);
- HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(docstream, records);
-
- for (Map.Entry<Integer,Record> 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<Integer,Record> recordMap, Map<Integer,Integer> 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<Integer,Integer> 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<HSLFPictureData>();
-
- // 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<RecordTypes.Type,PositionDependentRecord> 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<Integer,Integer> oldToNewPositions = new Hashtable<Integer,Integer>();
-
- // 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<Integer,Integer> persistIds = new HashMap<Integer,Integer>();
- for (Map.Entry<Integer,Integer> 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<String> writtenEntries = new ArrayList<String>(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<String> 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 <code>null</code> 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<HSLFObjectData> objects = new ArrayList<HSLFObjectData>();
- 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;
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.
- * <p>
- * Contains the text in a text frame as well as the properties and methods
- * that control alignment and anchoring of the text.
- * </p>
- *
- * @author Yegor Kozlov
- */
-public class HSLFTextBox extends HSLFTextShape {
-
- /**
- * Create a TextBox object and initialize it from the supplied Record container.
- *
- * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected HSLFTextBox(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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 <code>EscherContainerRecord</code> 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);
- }
-
-}
+++ /dev/null
-/* ====================================================================\r
- Licensed to the Apache Software Foundation (ASF) under one or more\r
- contributor license agreements. See the NOTICE file distributed with\r
- this work for additional information regarding copyright ownership.\r
- The ASF licenses this file to You under the Apache License, Version 2.0\r
- (the "License"); you may not use this file except in compliance with\r
- the License. You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-==================================================================== */\r
-\r
-package org.apache.poi.hslf.model;\r
-\r
-import java.util.ArrayList;\r
-import java.util.LinkedList;\r
-import java.util.List;\r
-\r
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;\r
-import org.apache.poi.hslf.record.PPDrawing;\r
-import org.apache.poi.hslf.record.Record;\r
-import org.apache.poi.hslf.record.RecordContainer;\r
-import org.apache.poi.hslf.record.SlideListWithText;\r
-import org.apache.poi.hslf.record.StyleTextProp9Atom;\r
-import org.apache.poi.hslf.record.StyleTextPropAtom;\r
-import org.apache.poi.hslf.record.TextBytesAtom;\r
-import org.apache.poi.hslf.record.TextCharsAtom;\r
-import org.apache.poi.hslf.record.TextHeaderAtom;\r
-import org.apache.poi.hslf.record.TextRulerAtom;\r
-import org.apache.poi.hslf.record.TextSpecInfoAtom;\r
-import org.apache.poi.hslf.usermodel.HSLFTextRun;\r
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;\r
-import org.apache.poi.sl.usermodel.TextParagraph;\r
-import org.apache.poi.util.StringUtil;\r
-\r
-/**\r
- * This class represents a run of text in a powerpoint document. That\r
- * run could be text on a sheet, or text in a note.\r
- * It is only a very basic class for now\r
- *\r
- * @author Nick Burch\r
- */\r
-\r
-public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun>\r
-{\r
- // Note: These fields are protected to help with unit testing\r
- // Other classes shouldn't really go playing with them!\r
- protected TextHeaderAtom _headerAtom;\r
- protected TextBytesAtom _byteAtom;\r
- protected TextCharsAtom _charAtom;\r
- protected StyleTextPropAtom _styleAtom;\r
- protected TextRulerAtom _ruler;\r
- protected boolean _isUnicode;\r
- protected HSLFTextRun[] _rtRuns;\r
- protected HSLFTextShape _parentShape;\r
- // private SlideShow slideShow;\r
- private HSLFSheet _sheet;\r
- private int shapeId;\r
- private int slwtIndex = -1; //position in the owning SlideListWithText\r
- /**\r
- * all text run records that follow TextHeaderAtom.\r
- * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)\r
- */\r
- protected Record[] _records;\r
- // private StyleTextPropAtom styleTextPropAtom;\r
- private StyleTextProp9Atom styleTextProp9Atom;\r
-\r
- /**\r
- * Constructs a Text Run from a Unicode text block\r
- *\r
- * @param tha the TextHeaderAtom that defines what's what\r
- * @param tca the TextCharsAtom containing the text\r
- * @param sta the StyleTextPropAtom which defines the character stylings\r
- */\r
- public HSLFTextParagraph(TextHeaderAtom tha, TextCharsAtom tca, StyleTextPropAtom sta) {\r
- this(tha,null,tca,sta);\r
- }\r
-\r
- /**\r
- * Constructs a Text Run from a Ascii text block\r
- *\r
- * @param tha the TextHeaderAtom that defines what's what\r
- * @param tba the TextBytesAtom containing the text\r
- * @param sta the StyleTextPropAtom which defines the character stylings\r
- */\r
- public HSLFTextParagraph(TextHeaderAtom tha, TextBytesAtom tba, StyleTextPropAtom sta) {\r
- this(tha,tba,null,sta);\r
- }\r
-\r
- /**\r
- * Internal constructor and initializer\r
- */\r
- private HSLFTextParagraph(TextHeaderAtom tha, TextBytesAtom tba, TextCharsAtom tca, StyleTextPropAtom sta) {\r
- _headerAtom = tha;\r
- _styleAtom = sta;\r
- if(tba != null) {\r
- _byteAtom = tba;\r
- _isUnicode = false;\r
- } else {\r
- _charAtom = tca;\r
- _isUnicode = true;\r
- }\r
- String runRawText = getText();\r
-\r
- // Figure out the rich text runs\r
- LinkedList<TextPropCollection> pStyles = new LinkedList<TextPropCollection>();\r
- LinkedList<TextPropCollection> cStyles = new LinkedList<TextPropCollection>();\r
- if(_styleAtom != null) {\r
- // Get the style atom to grok itself\r
- _styleAtom.setParentTextSize(runRawText.length());\r
- pStyles = _styleAtom.getParagraphStyles();\r
- cStyles = _styleAtom.getCharacterStyles();\r
- }\r
- buildRichTextRuns(pStyles, cStyles, runRawText);\r
- }\r
-\r
- public void buildRichTextRuns(LinkedList<TextPropCollection> pStyles, LinkedList<TextPropCollection> cStyles, String runRawText){\r
-\r
- // Handle case of no current style, with a default\r
- if(pStyles.size() == 0 || cStyles.size() == 0) {\r
- _rtRuns = new HSLFTextRun[1];\r
- _rtRuns[0] = new HSLFTextRun(this, 0, runRawText.length());\r
- } else {\r
- // Build up Rich Text Runs, one for each\r
- // character/paragraph style pair\r
- List<HSLFTextRun> rtrs = new ArrayList<HSLFTextRun>();\r
-\r
- int pos = 0;\r
-\r
- int curP = 0;\r
- int curC = 0;\r
- int pLenRemain = -1;\r
- int cLenRemain = -1;\r
-\r
- // Build one for each run with the same style\r
- while(pos <= runRawText.length() && curP < pStyles.size() && curC < cStyles.size()) {\r
- // Get the Props to use\r
- TextPropCollection pProps = pStyles.get(curP);\r
- TextPropCollection cProps = cStyles.get(curC);\r
-\r
- int pLen = pProps.getCharactersCovered();\r
- int cLen = cProps.getCharactersCovered();\r
-\r
- // Handle new pass\r
- boolean freshSet = false;\r
- if(pLenRemain == -1 && cLenRemain == -1) { freshSet = true; }\r
- if(pLenRemain == -1) { pLenRemain = pLen; }\r
- if(cLenRemain == -1) { cLenRemain = cLen; }\r
-\r
- // So we know how to build the eventual run\r
- int runLen = -1;\r
- boolean pShared = false;\r
- boolean cShared = false;\r
-\r
- // Same size, new styles - neither shared\r
- if(pLen == cLen && freshSet) {\r
- runLen = cLen;\r
- pShared = false;\r
- cShared = false;\r
- curP++;\r
- curC++;\r
- pLenRemain = -1;\r
- cLenRemain = -1;\r
- } else {\r
- // Some sharing\r
-\r
- // See if we are already in a shared block\r
- if(pLenRemain < pLen) {\r
- // Existing shared p block\r
- pShared = true;\r
-\r
- // Do we end with the c block, or either side of it?\r
- if(pLenRemain == cLenRemain) {\r
- // We end at the same time\r
- cShared = false;\r
- runLen = pLenRemain;\r
- curP++;\r
- curC++;\r
- pLenRemain = -1;\r
- cLenRemain = -1;\r
- } else if(pLenRemain < cLenRemain) {\r
- // We end before the c block\r
- cShared = true;\r
- runLen = pLenRemain;\r
- curP++;\r
- cLenRemain -= pLenRemain;\r
- pLenRemain = -1;\r
- } else {\r
- // We end after the c block\r
- cShared = false;\r
- runLen = cLenRemain;\r
- curC++;\r
- pLenRemain -= cLenRemain;\r
- cLenRemain = -1;\r
- }\r
- } else if(cLenRemain < cLen) {\r
- // Existing shared c block\r
- cShared = true;\r
-\r
- // Do we end with the p block, or either side of it?\r
- if(pLenRemain == cLenRemain) {\r
- // We end at the same time\r
- pShared = false;\r
- runLen = cLenRemain;\r
- curP++;\r
- curC++;\r
- pLenRemain = -1;\r
- cLenRemain = -1;\r
- } else if(cLenRemain < pLenRemain) {\r
- // We end before the p block\r
- pShared = true;\r
- runLen = cLenRemain;\r
- curC++;\r
- pLenRemain -= cLenRemain;\r
- cLenRemain = -1;\r
- } else {\r
- // We end after the p block\r
- pShared = false;\r
- runLen = pLenRemain;\r
- curP++;\r
- cLenRemain -= pLenRemain;\r
- pLenRemain = -1;\r
- }\r
- } else {\r
- // Start of a shared block\r
- if(pLenRemain < cLenRemain) {\r
- // Shared c block\r
- pShared = false;\r
- cShared = true;\r
- runLen = pLenRemain;\r
- curP++;\r
- cLenRemain -= pLenRemain;\r
- pLenRemain = -1;\r
- } else {\r
- // Shared p block\r
- pShared = true;\r
- cShared = false;\r
- runLen = cLenRemain;\r
- curC++;\r
- pLenRemain -= cLenRemain;\r
- cLenRemain = -1;\r
- }\r
- }\r
- }\r
-\r
- // Wind on\r
- int prevPos = pos;\r
- pos += runLen;\r
- // Adjust for end-of-run extra 1 length\r
- if(pos > runRawText.length()) {\r
- runLen--;\r
- }\r
-\r
- // Save\r
- HSLFTextRun rtr = new HSLFTextRun(this, prevPos, runLen, pProps, cProps, pShared, cShared);\r
- rtrs.add(rtr);\r
- }\r
-\r
- // Build the array\r
- _rtRuns = rtrs.toArray(new HSLFTextRun[rtrs.size()]);\r
- }\r
-\r
- }\r
-\r
- // Update methods follow\r
-\r
- /**\r
- * Adds the supplied text onto the end of the TextRun,\r
- * creating a new RichTextRun (returned) for it to\r
- * sit in.\r
- * In many cases, before calling this, you'll want to add\r
- * a newline onto the end of your last RichTextRun\r
- */\r
- public HSLFTextRun appendText(String s) {\r
- // We will need a StyleTextProp atom\r
- ensureStyleAtomPresent();\r
-\r
- // First up, append the text to the\r
- // underlying text atom\r
- int oldSize = getRawText().length();\r
- storeText(\r
- getRawText() + s\r
- );\r
-\r
- // If either of the previous styles overran\r
- // the text by one, we need to shuffle that\r
- // extra character onto the new ones\r
- int pOverRun = _styleAtom.getParagraphTextLengthCovered() - oldSize;\r
- int cOverRun = _styleAtom.getCharacterTextLengthCovered() - oldSize;\r
- if(pOverRun > 0) {\r
- TextPropCollection tpc = _styleAtom.getParagraphStyles().getLast();\r
- tpc.updateTextSize(\r
- tpc.getCharactersCovered() - pOverRun\r
- );\r
- }\r
- if(cOverRun > 0) {\r
- TextPropCollection tpc = _styleAtom.getCharacterStyles().getLast();\r
- tpc.updateTextSize(\r
- tpc.getCharactersCovered() - cOverRun\r
- );\r
- }\r
-\r
- // Next, add the styles for its paragraph and characters\r
- TextPropCollection newPTP =\r
- _styleAtom.addParagraphTextPropCollection(s.length()+pOverRun);\r
- TextPropCollection newCTP =\r
- _styleAtom.addCharacterTextPropCollection(s.length()+cOverRun);\r
-\r
- // Now, create the new RichTextRun\r
- HSLFTextRun nr = new HSLFTextRun(\r
- this, oldSize, s.length(),\r
- newPTP, newCTP, false, false\r
- );\r
-\r
- // Add the new RichTextRun onto our list\r
- HSLFTextRun[] newRuns = new HSLFTextRun[_rtRuns.length+1];\r
- System.arraycopy(_rtRuns, 0, newRuns, 0, _rtRuns.length);\r
- newRuns[newRuns.length-1] = nr;\r
- _rtRuns = newRuns;\r
-\r
- // And return the new run to the caller\r
- return nr;\r
- }\r
-\r
- /**\r
- * Saves the given string to the records. Doesn't\r
- * touch the stylings.\r
- */\r
- private void storeText(String s) {\r
- // Store in the appropriate record\r
- if(_isUnicode) {\r
- // The atom can safely convert to unicode\r
- _charAtom.setText(s);\r
- } else {\r
- // Will it fit in a 8 bit atom?\r
- boolean hasMultibyte = StringUtil.hasMultibyte(s);\r
- if(! hasMultibyte) {\r
- // Fine to go into 8 bit atom\r
- byte[] text = new byte[s.length()];\r
- StringUtil.putCompressedUnicode(s,text,0);\r
- _byteAtom.setText(text);\r
- } else {\r
- // Need to swap a TextBytesAtom for a TextCharsAtom\r
-\r
- // Build the new TextCharsAtom\r
- _charAtom = new TextCharsAtom();\r
- _charAtom.setText(s);\r
-\r
- // Use the TextHeaderAtom to do the swap on the parent\r
- RecordContainer parent = _headerAtom.getParentRecord();\r
- Record[] cr = parent.getChildRecords();\r
- for(int i=0; i<cr.length; i++) {\r
- // Look for TextBytesAtom\r
- if(cr[i].equals(_byteAtom)) {\r
- // Found it, so replace, then all done\r
- cr[i] = _charAtom;\r
- break;\r
- }\r
- }\r
-\r
- // Flag the change\r
- _byteAtom = null;\r
- _isUnicode = true;\r
- }\r
- }\r
- /**\r
- * If TextSpecInfoAtom is present, we must update the text size in it,\r
- * otherwise the ppt will be corrupted\r
- */\r
- if(_records != null) for (int i = 0; i < _records.length; i++) {\r
- if(_records[i] instanceof TextSpecInfoAtom){\r
- TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_records[i];\r
- if((s.length() + 1) != specAtom.getCharactersCovered()){\r
- specAtom.reset(s.length() + 1);\r
- }\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Handles an update to the text stored in one of the Rich Text Runs\r
- * @param run\r
- * @param s\r
- */\r
- public void changeTextInRichTextRun(HSLFTextRun run, String s) {\r
- // Figure out which run it is\r
- int runID = -1;\r
- for(int i=0; i<_rtRuns.length; i++) {\r
- if(run.equals(_rtRuns[i])) {\r
- runID = i;\r
- }\r
- }\r
- if(runID == -1) {\r
- throw new IllegalArgumentException("Supplied RichTextRun wasn't from this TextRun");\r
- }\r
-\r
- // Ensure a StyleTextPropAtom is present, adding if required\r
- ensureStyleAtomPresent();\r
-\r
- // Update the text length for its Paragraph and Character stylings\r
- // If it's shared:\r
- // * calculate the new length based on the run's old text\r
- // * this should leave in any +1's for the end of block if needed\r
- // If it isn't shared:\r
- // * reset the length, to the new string's length\r
- // * add on +1 if the last block\r
- // The last run needs its stylings to be 1 longer than the raw\r
- // text is. This is to define the stylings that any new text\r
- // that is added will inherit\r
- TextPropCollection pCol = run._getRawParagraphStyle();\r
- TextPropCollection cCol = run._getRawCharacterStyle();\r
- int newSize = s.length();\r
- if(runID == _rtRuns.length-1) {\r
- newSize++;\r
- }\r
-\r
- if(run._isParagraphStyleShared()) {\r
- pCol.updateTextSize( pCol.getCharactersCovered() - run.getLength() + s.length() );\r
- } else {\r
- pCol.updateTextSize(newSize);\r
- }\r
- if(run._isCharacterStyleShared()) {\r
- cCol.updateTextSize( cCol.getCharactersCovered() - run.getLength() + s.length() );\r
- } else {\r
- cCol.updateTextSize(newSize);\r
- }\r
-\r
- // Build up the new text\r
- // As we go through, update the start position for all subsequent runs\r
- // The building relies on the old text still being present\r
- StringBuffer newText = new StringBuffer();\r
- for(int i=0; i<_rtRuns.length; i++) {\r
- int newStartPos = newText.length();\r
-\r
- // Build up the new text\r
- if(i != runID) {\r
- // Not the affected run, so keep old text\r
- newText.append(_rtRuns[i].getRawText());\r
- } else {\r
- // Affected run, so use new text\r
- newText.append(s);\r
- }\r
-\r
- // Do we need to update the start position of this run?\r
- // (Need to get the text before we update the start pos)\r
- if(i <= runID) {\r
- // Change is after this, so don't need to change start position\r
- } else {\r
- // Change has occured, so update start position\r
- _rtRuns[i].updateStartPosition(newStartPos);\r
- }\r
- }\r
-\r
- // Now we can save the new text\r
- storeText(newText.toString());\r
- }\r
-\r
- /**\r
- * Changes the text, and sets it all to have the same styling\r
- * as the the first character has.\r
- * If you care about styling, do setText on a RichTextRun instead\r
- */\r
- public void setRawText(String s) {\r
- // Save the new text to the atoms\r
- storeText(s);\r
- HSLFTextRun fst = _rtRuns[0];\r
-\r
- // Finally, zap and re-do the RichTextRuns\r
- for(int i=0; i<_rtRuns.length; i++) { _rtRuns[i] = null; }\r
- _rtRuns = new HSLFTextRun[1];\r
- _rtRuns[0] = fst;\r
-\r
- // Now handle record stylings:\r
- // If there isn't styling\r
- // no change, stays with no styling\r
- // If there is styling:\r
- // everthing gets the same style that the first block has\r
- // Update the lengths +1 for since these will be the only runs\r
- if(_styleAtom != null) {\r
- LinkedList<TextPropCollection> pStyles = _styleAtom.getParagraphStyles();\r
- while(pStyles.size() > 1) { pStyles.removeLast(); }\r
-\r
- if (!pStyles.isEmpty()) {\r
- pStyles.getFirst().updateTextSize( s.length()+1 );\r
- }\r
-\r
- LinkedList<TextPropCollection> cStyles = _styleAtom.getCharacterStyles();\r
- while(cStyles.size() > 1) { cStyles.removeLast(); }\r
- \r
- if (!cStyles.isEmpty()) {\r
- cStyles.getFirst().updateTextSize( s.length()+1 );\r
- }\r
- \r
- _rtRuns[0].setText(s);\r
- } else {\r
- // Recreate rich text run with no styling\r
- _rtRuns[0] = new HSLFTextRun(this,0,s.length());\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Changes the text.\r
- * Converts '\r' into '\n'\r
- */\r
- public void setText(String s) {\r
- String text = normalize(s);\r
- setRawText(text);\r
- }\r
-\r
- /**\r
- * Ensure a StyleTextPropAtom is present for this run,\r
- * by adding if required. Normally for internal TextRun use.\r
- */\r
- public void ensureStyleAtomPresent() {\r
- if(_styleAtom != null) {\r
- // All there\r
- return;\r
- }\r
-\r
- // Create a new one at the right size\r
- _styleAtom = new StyleTextPropAtom(getRawText().length() + 1);\r
-\r
- // Use the TextHeader atom to get at the parent\r
- RecordContainer runAtomsParent = _headerAtom.getParentRecord();\r
-\r
- // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom\r
- Record addAfter = _byteAtom;\r
- if(_byteAtom == null) { addAfter = _charAtom; }\r
- runAtomsParent.addChildAfter(_styleAtom, addAfter);\r
-\r
- // Feed this to our sole rich text run\r
- if(_rtRuns.length != 1) {\r
- throw new IllegalStateException("Needed to add StyleTextPropAtom when had many rich text runs");\r
- }\r
- // These are the only styles for now\r
- _rtRuns[0].supplyTextProps(\r
- _styleAtom.getParagraphStyles().get(0),\r
- _styleAtom.getCharacterStyles().get(0),\r
- false,\r
- false\r
- );\r
- }\r
-\r
- // Accesser methods follow\r
-\r
- /**\r
- * Returns the text content of the run, which has been made safe\r
- * for printing and other use.\r
- */\r
- public String getText() {\r
- String rawText = getRawText();\r
-\r
- // PowerPoint seems to store files with \r as the line break\r
- // The messes things up on everything but a Mac, so translate\r
- // them to \n\r
- String text = rawText.replace('\r','\n');\r
-\r
- int type = _headerAtom == null ? 0 : _headerAtom.getTextType();\r
- if(type == TextHeaderAtom.TITLE_TYPE || type == TextHeaderAtom.CENTER_TITLE_TYPE){\r
- //0xB acts like cariage return in page titles and like blank in the others\r
- text = text.replace((char) 0x0B, '\n');\r
- } else {\r
- text = text.replace((char) 0x0B, ' ');\r
- }\r
- return text;\r
- }\r
-\r
- /**\r
- * Returns the raw text content of the run. This hasn't had any\r
- * changes applied to it, and so is probably unlikely to print\r
- * out nicely.\r
- */\r
- public String getRawText() {\r
- if(_isUnicode) {\r
- return _charAtom.getText();\r
- }\r
- return _byteAtom.getText();\r
- }\r
-\r
- /**\r
- * Fetch the rich text runs (runs of text with the same styling) that\r
- * are contained within this block of text\r
- */\r
- public HSLFTextRun[] getRichTextRuns() {\r
- return _rtRuns;\r
- }\r
-\r
- /**\r
- * Returns the type of the text, from the TextHeaderAtom.\r
- * Possible values can be seen from TextHeaderAtom\r
- * @see org.apache.poi.hslf.record.TextHeaderAtom\r
- */\r
- public int getRunType() {\r
- return _headerAtom.getTextType();\r
- }\r
-\r
- /**\r
- * Changes the type of the text. Values should be taken\r
- * from TextHeaderAtom. No checking is done to ensure you\r
- * set this to a valid value!\r
- * @see org.apache.poi.hslf.record.TextHeaderAtom\r
- */\r
- public void setRunType(int type) {\r
- _headerAtom.setTextType(type);\r
- }\r
-\r
- /**\r
- * Supply the Sheet we belong to, which might have an assigned SlideShow\r
- * Also passes it on to our child RichTextRuns\r
- */\r
- public void supplySheet(HSLFSheet sheet){\r
- this._sheet = sheet;\r
-\r
- if (_rtRuns == null) return;\r
- for(HSLFTextRun rt : _rtRuns) {\r
- rt.updateSheet();\r
- }\r
- }\r
-\r
- public HSLFSheet getSheet(){\r
- return this._sheet;\r
- }\r
-\r
- /**\r
- * @return Shape ID\r
- */\r
- protected int getShapeId(){\r
- return shapeId;\r
- }\r
-\r
- /**\r
- * @param id Shape ID\r
- */\r
- protected void setShapeId(int id){\r
- shapeId = id;\r
- }\r
-\r
- /**\r
- * @return 0-based index of the text run in the SLWT container\r
- */\r
- protected int getIndex(){\r
- return slwtIndex;\r
- }\r
-\r
- /**\r
- * @param id 0-based index of the text run in the SLWT container\r
- */\r
- protected void setIndex(int id){\r
- slwtIndex = id;\r
- }\r
- \r
- /**\r
- * Is this Text Run one from a {@link PPDrawing}, or is it\r
- * one from the {@link SlideListWithText}?\r
- */\r
- public boolean isDrawingBased() {\r
- return (slwtIndex == -1);\r
- }\r
-\r
- /**\r
- * Returns the array of all hyperlinks in this text run\r
- *\r
- * @return the array of all hyperlinks in this text run\r
- * or <code>null</code> if not found.\r
- */\r
- public Hyperlink[] getHyperlinks(){\r
- return Hyperlink.find(this);\r
- }\r
-\r
- /**\r
- * Fetch RichTextRun at a given position\r
- *\r
- * @param pos 0-based index in the text\r
- * @return RichTextRun or null if not found\r
- */\r
- public HSLFTextRun getRichTextRunAt(int pos){\r
- for (int i = 0; i < _rtRuns.length; i++) {\r
- int start = _rtRuns[i].getStartIndex();\r
- int end = _rtRuns[i].getEndIndex();\r
- if(pos >= start && pos < end) return _rtRuns[i];\r
- }\r
- return null;\r
- }\r
-\r
- public TextRulerAtom getTextRuler(){\r
- if(_ruler == null){\r
- if(_records != null) for (int i = 0; i < _records.length; i++) {\r
- if(_records[i] instanceof TextRulerAtom) {\r
- _ruler = (TextRulerAtom)_records[i];\r
- break;\r
- }\r
- }\r
-\r
- }\r
- return _ruler;\r
-\r
- }\r
-\r
- public TextRulerAtom createTextRuler(){\r
- _ruler = getTextRuler();\r
- if(_ruler == null){\r
- _ruler = TextRulerAtom.getParagraphInstance();\r
- _headerAtom.getParentRecord().appendChildRecord(_ruler);\r
- }\r
- return _ruler;\r
- }\r
-\r
- /**\r
- * Returns a new string with line breaks converted into internal ppt representation\r
- */\r
- public String normalize(String s){\r
- String ns = s.replaceAll("\\r?\\n", "\r");\r
- return ns;\r
- }\r
-\r
- /**\r
- * Returns records that make up this text run\r
- *\r
- * @return text run records\r
- */\r
- public Record[] getRecords(){\r
- return _records;\r
- }\r
- /** Numbered List info */\r
- public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
- this.styleTextProp9Atom = styleTextProp9Atom;\r
- }\r
- /** Numbered List info */\r
- public StyleTextProp9Atom getStyleTextProp9Atom() {\r
- return this.styleTextProp9Atom;\r
- }\r
-\r
- /** Characters covered */\r
- public StyleTextPropAtom getStyleTextPropAtom() {\r
- return this._styleAtom; \r
- }\r
-\r
-}\r
+++ /dev/null
-/* ====================================================================
- 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 <code>EscherSpContainer</code> container which holds information about this shape
- * @param parent the parent of the shape
- */
- protected HSLFTextShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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
- * <code>PPDrawing</code> 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 <code>Rectangle2D</code> that is the bounds of this <code>TextShape</code>.
- */
- 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 <code>Anchor*</code> 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 <code>Anchor*</code> 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 <code>Align*</code> 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 <code>Align*</code> 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 <code>Wrap*</code> 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 <code>Wrap*</code> 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 <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
- *
- * @return <code>OEPlaceholderAtom</code> or <code>null</code> 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;
- }
-
-
-}
package org.apache.poi.hslf.model;
import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
/**
* Header / Footer settings.
private boolean isVisible(int flag, int placeholderId){
boolean visible;
if(_ppt2007){
- HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0];
+ HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlideMasters().get(0);
HSLFTextShape placeholder = master.getPlaceholder(placeholderId);
visible = placeholder != null && placeholder.getText() != null;
} else {
private String getPlaceholderText(int placeholderId, CString cs){
String text = null;
if(_ppt2007){
- HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlidesMasters()[0];
+ HSLFSheet master = _sheet != null ? _sheet : _ppt.getSlideMasters().get(0);
HSLFTextShape placeholder = master.getPlaceholder(placeholderId);
if(placeholder != null) text = placeholder.getText();
+++ /dev/null
-/* ====================================================================
- 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.*;
-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;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Iterator;
-
-/**
- * Represents a hyperlink in a PowerPoint document
- *
- * @author Yegor Kozlov
- */
-public final class Hyperlink {
- public static final byte LINK_NEXTSLIDE = InteractiveInfoAtom.LINK_NextSlide;
- public static final byte LINK_PREVIOUSSLIDE = InteractiveInfoAtom.LINK_PreviousSlide;
- public static final byte LINK_FIRSTSLIDE = InteractiveInfoAtom.LINK_FirstSlide;
- public static final byte LINK_LASTSLIDE = InteractiveInfoAtom.LINK_LastSlide;
- public static final byte LINK_SLIDENUMBER = InteractiveInfoAtom.LINK_SlideNumber;
- public static final byte LINK_URL = InteractiveInfoAtom.LINK_Url;
- public static final byte LINK_NULL = InteractiveInfoAtom.LINK_NULL;
-
- private int id=-1;
- private int type;
- private String address;
- private String title;
- private int startIndex, endIndex;
-
- /**
- * Gets the type of the hyperlink action.
- * Must be a <code>LINK_*</code> constant</code>
- *
- * @return the hyperlink URL
- * @see InteractiveInfoAtom
- */
- public int getType() {
- return type;
- }
-
- public void setType(int val) {
- type = val;
- switch(type){
- case LINK_NEXTSLIDE:
- title = "NEXT";
- address = "1,-1,NEXT";
- break;
- case LINK_PREVIOUSSLIDE:
- title = "PREV";
- address = "1,-1,PREV";
- break;
- case LINK_FIRSTSLIDE:
- title = "FIRST";
- address = "1,-1,FIRST";
- break;
- case LINK_LASTSLIDE:
- title = "LAST";
- address = "1,-1,LAST";
- break;
- case LINK_SLIDENUMBER:
- break;
- default:
- title = "";
- address = "";
- break;
- }
- }
-
- /**
- * Gets the hyperlink URL
- *
- * @return the hyperlink URL
- */
- public String getAddress() {
- return address;
- }
-
- public void setAddress(HSLFSlide slide) {
- String href = slide._getSheetNumber() + ","+slide.getSlideNumber()+",Slide " + slide.getSlideNumber();
- setAddress(href);;
- setTitle("Slide " + slide.getSlideNumber());
- setType(Hyperlink.LINK_SLIDENUMBER);
- }
-
- public void setAddress(String str) {
- address = str;
- }
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- /**
- * Gets the hyperlink user-friendly title (if different from URL)
- *
- * @return the hyperlink user-friendly title
- */
- public String getTitle() {
- return title;
- }
-
- public void setTitle(String str) {
- title = str;
- }
-
- /**
- * Gets the beginning character position
- *
- * @return the beginning character position
- */
- public int getStartIndex() {
- return startIndex;
- }
-
- /**
- * Gets the ending character position
- *
- * @return the ending character position
- */
- public int getEndIndex() {
- return endIndex;
- }
-
- /**
- * Find hyperlinks in a text run
- *
- * @param run <code>TextRun</code> to lookup hyperlinks in
- * @return found hyperlinks or <code>null</code> if not found
- */
- protected static Hyperlink[] find(HSLFTextParagraph run){
- List<Hyperlink> lst = new ArrayList<Hyperlink>();
- 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) {
- return null;
- }
- Record[] records = run._records;
- if(records != null) find(records, exobj, lst);
-
- Hyperlink[] links = null;
- if (lst.size() > 0){
- links = new Hyperlink[lst.size()];
- lst.toArray(links);
- }
- return links;
- }
-
- /**
- * Find hyperlink assigned to the supplied shape
- *
- * @param shape <code>Shape</code> to lookup hyperlink in
- * @return found hyperlink or <code>null</code>
- */
- protected static Hyperlink find(HSLFShape shape){
- List<Hyperlink> lst = new ArrayList<Hyperlink>();
- 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) {
- return null;
- }
-
- EscherContainerRecord spContainer = shape.getSpContainer();
- for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext(); ) {
- EscherRecord obj = it.next();
- if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID){
- byte[] data = obj.serialize();
- Record[] records = Record.findChildRecords(data, 8, data.length-8);
- if(records != null) find(records, exobj, lst);
- }
- }
-
- return lst.size() == 1 ? (Hyperlink)lst.get(0) : null;
- }
-
- private static void find(Record[] records, ExObjList exobj, List<Hyperlink> out){
- for (int i = 0; i < records.length; i++) {
- //see if we have InteractiveInfo in the textrun's records
- if( records[i] instanceof InteractiveInfo){
- InteractiveInfo hldr = (InteractiveInfo)records[i];
- InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
- int id = info.getHyperlinkID();
- ExHyperlink linkRecord = exobj.get(id);
- if (linkRecord != null){
- Hyperlink link = new Hyperlink();
- link.title = linkRecord.getLinkTitle();
- link.address = linkRecord.getLinkURL();
- link.type = info.getAction();
-
- if (++i < records.length && records[i] instanceof TxInteractiveInfoAtom){
- TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[i];
- link.startIndex = txinfo.getStartIndex();
- link.endIndex = txinfo.getEndIndex();
- }
- out.add(link);
- }
- }
- }
- }
-}
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
* @author Yegor Kozlov
*/
public final class Line extends HSLFSimpleShape {
- protected Line(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ public Line(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
super(escherRecord, parent);
}
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.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeContainer;
/**
* this picture in the <code>Slide</code>
* @param parent the parent shape of this picture
*/
- protected MovieShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ public MovieShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
super(escherRecord, parent);
}
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFObjectData;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hslf.record.ExObjList;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.ExEmbed;
* this picture in the <code>Slide</code>
* @param parent the parent shape of this picture
*/
- protected OLEShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ public OLEShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
super(escherRecord, parent);
}
import java.awt.*;
-import java.awt.Shape;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.font.TextLayout;
+import java.awt.font.*;
+import java.awt.geom.*;
import java.awt.image.*;
import java.awt.image.renderable.RenderableImage;
-import java.awt.geom.*;
import java.text.AttributedCharacterIterator;
import java.util.Map;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
+
import org.apache.poi.hslf.exceptions.HSLFException;
-import org.apache.poi.util.POILogger;
+import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.sl.usermodel.StrokeStyle;
+import org.apache.poi.sl.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
/**
* Translates Graphics2D calls into PowerPoint.
*/
public void drawString(String s, float x, float y) {
HSLFTextBox txt = new HSLFTextBox(_group);
- txt.getTextParagraph().supplySheet(_group.getSheet());
+ txt.getTextParagraphs().get(0).supplySheet(_group.getSheet());
txt.setText(s);
- HSLFTextRun rt = txt.getTextParagraph().getRichTextRuns()[0];
+ HSLFTextRun rt = txt.getTextParagraphs().get(0).getTextRuns().get(0);
rt.setFontSize(_font.getSize());
rt.setFontName(_font.getFamily());
if (_font.isBold()) rt.setBold(true);
if (_font.isItalic()) rt.setItalic(true);
- txt.setMarginBottom(0);
- txt.setMarginTop(0);
- txt.setMarginLeft(0);
- txt.setMarginRight(0);
+ txt.setBottomInset(0);
+ txt.setTopInset(0);
+ txt.setLeftInset(0);
+ txt.setRightInset(0);
txt.setWordWrap(HSLFTextBox.WrapNone);
- txt.setHorizontalAlignment(HSLFTextBox.AlignLeft);
- txt.setVerticalAlignment(HSLFTextBox.AnchorMiddle);
+ txt.setHorizontalCentered(false);
+ txt.setVerticalAlignment(VerticalAlignment.MIDDLE);
TextLayout layout = new TextLayout(s, _font, getFontRenderContext());
float[] dash = bs.getDashArray();
if (dash != null) {
//TODO: implement more dashing styles
- shape.setLineDashing(Line.PEN_DASH);
+ shape.setLineDashing(StrokeStyle.LineDash.DASH);
}
}
}
import org.apache.poi.ddf.*;
import org.apache.poi.hslf.record.OEPlaceholderAtom;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFTextBox;
import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.sl.usermodel.ShapeContainer;
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.LittleEndian;
+++ /dev/null
-/* ====================================================================
- 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.Iterator;
-import java.util.List;
-
-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.EscherProperty;
-import org.apache.poi.ddf.EscherPropertyFactory;
-import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.ddf.EscherSimpleProperty;
-import org.apache.poi.ddf.EscherSpRecord;
-import org.apache.poi.hslf.record.InteractiveInfo;
-import org.apache.poi.hslf.record.InteractiveInfoAtom;
-import org.apache.poi.hslf.record.OEShapeAtom;
-import org.apache.poi.hslf.record.Record;
-import org.apache.poi.hslf.record.RecordTypes;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.sl.usermodel.ShapeType;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-/**
- * Create a <code>Shape</code> object depending on its type
- *
- * @author Yegor Kozlov
- */
-public final class ShapeFactory {
- // For logging
- protected static final POILogger logger = POILogFactory.getLogger(ShapeFactory.class);
-
- /**
- * Create a new shape from the data provided.
- */
- public static HSLFShape createShape(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
- if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
- return createShapeGroup(spContainer, parent);
- }
- return createSimpeShape(spContainer, parent);
- }
-
- public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
- HSLFGroupShape group = null;
- EscherRecord opt = HSLFShape.getEscherChild((EscherContainerRecord)spContainer.getChild(0), (short)0xF122);
- if(opt != null){
- try {
- EscherPropertyFactory f = new EscherPropertyFactory();
- List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() );
- EscherSimpleProperty p = (EscherSimpleProperty)props.get(0);
- if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){
- group = new Table(spContainer, parent);
- } else {
- group = new HSLFGroupShape(spContainer, parent);
- }
- } catch (Exception e){
- logger.log(POILogger.WARN, e.getMessage());
- group = new HSLFGroupShape(spContainer, parent);
- }
- } else {
- group = new HSLFGroupShape(spContainer, parent);
- }
-
- return group;
- }
-
- public static HSLFShape createSimpeShape(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
- HSLFShape shape = null;
- EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
-
- ShapeType type = ShapeType.forId(spRecord.getShapeType(), false);
- switch (type){
- case TEXT_BOX:
- shape = new HSLFTextBox(spContainer, parent);
- break;
- case HOST_CONTROL:
- case FRAME: {
- InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
- OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
- if(info != null && info.getInteractiveInfoAtom() != null){
- switch(info.getInteractiveInfoAtom().getAction()){
- case InteractiveInfoAtom.ACTION_OLE:
- shape = new OLEShape(spContainer, parent);
- break;
- case InteractiveInfoAtom.ACTION_MEDIA:
- shape = new MovieShape(spContainer, parent);
- break;
- default:
- break;
- }
- } else if (oes != null){
- shape = new OLEShape(spContainer, parent);
- }
-
- if(shape == null) shape = new HSLFPictureShape(spContainer, parent);
- break;
- }
- case LINE:
- shape = new Line(spContainer, parent);
- break;
- case NOT_PRIMITIVE: {
- EscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
- EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
- if(prop != null)
- shape = new HSLFFreeformShape(spContainer, parent);
- else {
-
- logger.log(POILogger.WARN, "Creating AutoShape for a NotPrimitive shape");
- shape = new HSLFAutoShape(spContainer, parent);
- }
- break;
- }
- default:
- shape = new HSLFAutoShape(spContainer, parent);
- break;
- }
- return shape;
-
- }
-
- @SuppressWarnings("unchecked")
- protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
- Record oep = null;
- for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
- EscherRecord obj = it.next();
- if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
- byte[] data = obj.serialize();
- Record[] records = Record.findChildRecords(data, 8, data.length - 8);
- for (int j = 0; j < records.length; j++) {
- if (records[j].getRecordType() == recordType) {
- return (T)records[j];
- }
- }
- }
- }
- return (T)oep;
- }
-
-}
+++ /dev/null
-/* ====================================================================
- 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;
-
-/**
- * Date: Apr 17, 2008
- *
- * @author Yegor Kozlov
- */
-public interface ShapeOutline {
- java.awt.Shape getOutline(HSLFShape shape);
-
-}
+++ /dev/null
-/* ====================================================================
- 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.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.Stroke;
-import java.awt.geom.Rectangle2D;
-
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-/**
- * Paint a shape into java.awt.Graphics2D
- *
- * @author Yegor Kozlov
- */
-public final class ShapePainter {
- protected static final POILogger logger = POILogFactory.getLogger(ShapePainter.class);
-
- public static void paint(HSLFSimpleShape shape, Graphics2D graphics){
- Rectangle2D anchor = shape.getLogicalAnchor2D();
- java.awt.Shape outline = shape.getOutline();
-
- //flip vertical
- if(shape.getFlipVertical()){
- graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
- graphics.scale(1, -1);
- graphics.translate(-anchor.getX(), -anchor.getY());
- }
- //flip horizontal
- if(shape.getFlipHorizontal()){
- graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
- graphics.scale(-1, 1);
- graphics.translate(-anchor.getX() , -anchor.getY());
- }
-
- //rotate transform
- double angle = shape.getRotation();
-
- if(angle != 0){
- double centerX = anchor.getX() + anchor.getWidth()/2;
- double centerY = anchor.getY() + anchor.getHeight()/2;
-
- graphics.translate(centerX, centerY);
- graphics.rotate(Math.toRadians(angle));
- graphics.translate(-centerX, -centerY);
- }
-
- //fill
- Color fillColor = shape.getFill().getForegroundColor();
- if (fillColor != null) {
- //TODO: implement gradient and texture fill patterns
- graphics.setPaint(fillColor);
- graphics.fill(outline);
- }
-
- //border
- Color lineColor = shape.getLineColor();
- if (lineColor != null){
- graphics.setPaint(lineColor);
- float width = (float)shape.getLineWidth();
-
- int dashing = shape.getLineDashing();
- //TODO: implement more dashing styles
- float[] dashptrn = null;
- switch(dashing){
- case Line.PEN_SOLID:
- dashptrn = null;
- break;
- case Line.PEN_PS_DASH:
- dashptrn = new float[]{width, width};
- break;
- case Line.PEN_DOTGEL:
- dashptrn = new float[]{width*4, width*3};
- break;
- default:
- logger.log(POILogger.WARN, "unsupported dashing: " + dashing);
- dashptrn = new float[]{width, width};
- break;
- }
-
- Stroke stroke = new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dashptrn, 0.0f);
- graphics.setStroke(stroke);
- graphics.draw(outline);
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.model.textproperties.TextProp;
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-import org.apache.poi.hslf.record.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-
-/**
- * SlideMaster determines the graphics, layout, and formatting for all the slides in a given presentation.
- * It stores information about default font styles, placeholder sizes and positions,
- * background design, and color schemes.
- *
- * @author Yegor Kozlov
- */
-public final class SlideMaster extends HSLFMasterSheet {
- private HSLFTextParagraph[] _runs;
-
- /**
- * all TxMasterStyleAtoms available in this master
- */
- private TxMasterStyleAtom[] _txmaster;
-
- /**
- * Constructs a SlideMaster from the MainMaster record,
- *
- */
- public SlideMaster(MainMaster record, int sheetNo) {
- super(record, sheetNo);
-
- _runs = findTextRuns(getPPDrawing());
- for (int i = 0; i < _runs.length; i++) _runs[i].setSheet(this);
- }
-
- /**
- * Returns an array of all the TextRuns found
- */
- public HSLFTextParagraph[] getTextRuns() {
- return _runs;
- }
-
- /**
- * Returns <code>null</code> since SlideMasters doen't have master sheet.
- */
- public HSLFMasterSheet getMasterSheet() {
- return null;
- }
-
- /**
- * Pickup a style attribute from the master.
- * This is the "workhorse" which returns the default style attrubutes.
- */
- public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
-
- TextProp prop = null;
- for (int i = level; i >= 0; i--) {
- TextPropCollection[] styles =
- isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles();
- if (i < styles.length) prop = styles[i].findByName(name);
- if (prop != null) break;
- }
- if (prop == null) {
- if(isCharacter) {
- switch (txtype) {
- case TextHeaderAtom.CENTRE_BODY_TYPE:
- case TextHeaderAtom.HALF_BODY_TYPE:
- case TextHeaderAtom.QUARTER_BODY_TYPE:
- txtype = TextHeaderAtom.BODY_TYPE;
- break;
- case TextHeaderAtom.CENTER_TITLE_TYPE:
- txtype = TextHeaderAtom.TITLE_TYPE;
- break;
- default:
- return null;
- }
- } else {
- switch (txtype) {
- case TextHeaderAtom.CENTRE_BODY_TYPE:
- case TextHeaderAtom.HALF_BODY_TYPE:
- case TextHeaderAtom.QUARTER_BODY_TYPE:
- txtype = TextHeaderAtom.BODY_TYPE;
- break;
- case TextHeaderAtom.CENTER_TITLE_TYPE:
- txtype = TextHeaderAtom.TITLE_TYPE;
- break;
- default:
- return null;
- }
- }
- prop = getStyleAttribute(txtype, level, name, isCharacter);
- }
- return prop;
- }
-
- /**
- * Assign SlideShow for this slide master.
- * (Used interanlly)
- */
- public void setSlideShow(HSLFSlideShow ss) {
- super.setSlideShow(ss);
-
- //after the slide show is assigned collect all available style records
- if (_txmaster == null) {
- _txmaster = new TxMasterStyleAtom[9];
-
- TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
- _txmaster[txdoc.getTextType()] = txdoc;
-
- TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
- for (int i = 0; i < txrec.length; i++) {
- int txType = txrec[i].getTextType();
- if(_txmaster[txType] == null) _txmaster[txType] = txrec[i];
- }
- }
- }
-
- protected void onAddTextShape(HSLFTextShape shape) {
- HSLFTextParagraph run = shape.getTextParagraph();
-
- if(_runs == null) _runs = new HSLFTextParagraph[]{run};
- else {
- HSLFTextParagraph[] tmp = new HSLFTextParagraph[_runs.length + 1];
- System.arraycopy(_runs, 0, tmp, 0, _runs.length);
- tmp[tmp.length-1] = run;
- _runs = tmp;
- }
- }
-
- public TxMasterStyleAtom[] getTxMasterStyleAtoms(){
- return _txmaster;
- }
-}
package org.apache.poi.hslf.model;
import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.util.LittleEndian;
private Line cloneBorder(Line line){
Line border = createBorder();
border.setLineWidth(line.getLineWidth());
- border.setLineStyle(line.getStrokeStyle());
border.setLineDashing(line.getLineDashing());
border.setLineColor(line.getLineColor());
+ border.setLineCompound(line.getLineCompound());
return border;
}
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFTextBox;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
+++ /dev/null
-/* ====================================================================
- 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.Font;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.font.FontRenderContext;
-import java.awt.font.LineBreakMeasurer;
-import java.awt.font.TextAttribute;
-import java.awt.font.TextLayout;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.text.AttributedCharacterIterator;
-import java.text.AttributedString;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.poi.hslf.record.TextRulerAtom;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-/**
- * Paint text into java.awt.Graphics2D
- *
- * @author Yegor Kozlov
- */
-public final class TextPainter {
- public static final Key KEY_FONTFALLBACK = new Key(50, "Font fallback map");
- public static final Key KEY_FONTMAP = new Key(51, "Font map");
-
- protected POILogger logger = POILogFactory.getLogger(this.getClass());
-
- /**
- * Display unicode square if a bullet char can't be displayed,
- * for example, if Wingdings font is used.
- * TODO: map Wingdngs and Symbol to unicode Arial
- */
- protected static final char DEFAULT_BULLET_CHAR = '\u25a0';
-
- protected HSLFTextShape _shape;
-
- public TextPainter(HSLFTextShape shape){
- _shape = shape;
- }
-
- public AttributedString getAttributedString(HSLFTextParagraph txrun) {
- return getAttributedString(txrun, null);
- }
-
- /**
- * Convert the underlying set of rich text runs into java.text.AttributedString
- */
- 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);
- HSLFTextRun[] rt = txrun.getRichTextRuns();
- for (int i = 0; i < rt.length; i++) {
- int start = rt[i].getStartIndex();
- int end = rt[i].getEndIndex();
- if(start == end) {
- logger.log(POILogger.INFO, "Skipping RichTextRun with zero length");
- continue;
- }
-
- String mappedFont = rt[i].getFontName();
- String fallbackFont = Font.SANS_SERIF;
- if (graphics != null) {
- @SuppressWarnings("unchecked")
- Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(KEY_FONTMAP);
- if (fontMap != null && fontMap.containsKey(mappedFont)) {
- mappedFont = fontMap.get(mappedFont);
- }
- @SuppressWarnings("unchecked")
- Map<String,String> fallbackMap = (Map<String,String>)graphics.getRenderingHint(KEY_FONTFALLBACK);
- if (fallbackMap != null && fallbackMap.containsKey(mappedFont)) {
- fallbackFont = fallbackMap.get(mappedFont);
- }
- }
-
- at.addAttribute(TextAttribute.FAMILY, mappedFont, start, end);
- at.addAttribute(TextAttribute.SIZE, new Float(rt[i].getFontSize()), start, end);
- at.addAttribute(TextAttribute.FOREGROUND, rt[i].getFontColor(), start, end);
- if(rt[i].isBold()) at.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, start, end);
- if(rt[i].isItalic()) at.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, start, end);
- if(rt[i].isUnderlined()) {
- at.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, start, end);
- at.addAttribute(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL, start, end);
- }
- if(rt[i].isStrikethrough()) at.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, start, end);
- int superScript = rt[i].getSuperscript();
- if(superScript != 0) at.addAttribute(TextAttribute.SUPERSCRIPT, superScript > 0 ? TextAttribute.SUPERSCRIPT_SUPER : TextAttribute.SUPERSCRIPT_SUB, start, end);
-
-
- int style = (rt[i].isBold() ? Font.BOLD : 0) | (rt[i].isItalic() ? Font.ITALIC : 0);
- Font f = new Font(mappedFont, style, rt[i].getFontSize());
-
- // check for unsupported characters and add a fallback font for these
- char textChr[] = text.toCharArray();
- int nextEnd = f.canDisplayUpTo(textChr, start, end);
- boolean isNextValid = nextEnd == start;
- for (int last = start; nextEnd != -1 && nextEnd <= end; ) {
- if (isNextValid) {
- nextEnd = f.canDisplayUpTo(textChr, nextEnd, end);
- isNextValid = false;
- } else {
- if (nextEnd >= end || f.canDisplay(Character.codePointAt(textChr, nextEnd, end)) ) {
- at.addAttribute(TextAttribute.FAMILY, fallbackFont, last, Math.min(nextEnd,end));
- if (nextEnd >= end) break;
- last = nextEnd;
- isNextValid = true;
- } else {
- boolean isHS = Character.isHighSurrogate(textChr[nextEnd]);
- nextEnd+=(isHS?2:1);
- }
- }
- }
- }
- return at;
- }
-
- public void paint(Graphics2D graphics){
- AffineTransform tx = graphics.getTransform();
-
- Rectangle2D anchor = _shape.getLogicalAnchor2D();
- TextElement[] elem = getTextElements((float)anchor.getWidth(), graphics.getFontRenderContext(), graphics);
- if(elem == null) return;
-
- float textHeight = 0;
- for (int i = 0; i < elem.length; i++) {
- textHeight += elem[i].ascent + elem[i].descent;
- }
-
- int valign = _shape.getVerticalAlignment();
- double y0 = anchor.getY();
- switch (valign){
- case HSLFTextShape.AnchorTopBaseline:
- case HSLFTextShape.AnchorTop:
- y0 += _shape.getMarginTop();
- break;
- case HSLFTextShape.AnchorBottom:
- y0 += anchor.getHeight() - textHeight - _shape.getMarginBottom();
- break;
- default:
- case HSLFTextShape.AnchorMiddle:
- float delta = (float)anchor.getHeight() - textHeight - _shape.getMarginTop() - _shape.getMarginBottom();
- y0 += _shape.getMarginTop() + delta/2;
- break;
- }
-
-
- // 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 Bugzilla 54210.
- if(_shape.getFlipVertical()){
- graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
- graphics.scale(1, -1);
- graphics.translate(-anchor.getX(), -anchor.getY());
-
- // text in vertically flipped shapes is rotated by 180 degrees
- double centerX = anchor.getX() + anchor.getWidth()/2;
- double centerY = anchor.getY() + anchor.getHeight()/2;
- graphics.translate(centerX, centerY);
- graphics.rotate(Math.toRadians(180));
- graphics.translate(-centerX, -centerY);
- }
-
- // Horizontal flipping applies only to shape outline and not to the text in the shape.
- // Applying flip second time restores the original not-flipped transform
- if(_shape.getFlipHorizontal()){
- graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
- graphics.scale(-1, 1);
- graphics.translate(-anchor.getX() , -anchor.getY());
- }
-
- //finally draw the text fragments
- for (int i = 0; i < elem.length; i++) {
- y0 += elem[i].ascent;
-
- Point2D.Double pen = new Point2D.Double();
- pen.y = y0;
- switch (elem[i]._align) {
- default:
- case HSLFTextShape.AlignLeft:
- pen.x = anchor.getX() + _shape.getMarginLeft();
- break;
- case HSLFTextShape.AlignCenter:
- pen.x = anchor.getX() + _shape.getMarginLeft() +
- (anchor.getWidth() - elem[i].advance - _shape.getMarginLeft() - _shape.getMarginRight()) / 2;
- break;
- case HSLFTextShape.AlignRight:
- pen.x = anchor.getX() + _shape.getMarginLeft() +
- (anchor.getWidth() - elem[i].advance - _shape.getMarginLeft() - _shape.getMarginRight());
- break;
- }
- if(elem[i]._bullet != null){
- graphics.drawString(elem[i]._bullet.getIterator(), (float)(pen.x + elem[i]._bulletOffset), (float)pen.y);
- }
- AttributedCharacterIterator chIt = elem[i]._text.getIterator();
- if(chIt.getEndIndex() > chIt.getBeginIndex()) {
- graphics.drawString(chIt, (float)(pen.x + elem[i]._textOffset), (float)pen.y);
- }
- y0 += elem[i].descent;
- }
-
- graphics.setTransform(tx);
- }
-
- public TextElement[] getTextElements(float textWidth, FontRenderContext frc){
- return getTextElements(textWidth, frc, null);
- }
-
- public TextElement[] getTextElements(float textWidth, FontRenderContext frc, Graphics2D graphics){
- HSLFTextParagraph run = _shape.getTextParagraph();
- if (run == null) return null;
-
- String text = run.getText();
- if (text == null || text.equals("")) return null;
-
- AttributedString at = getAttributedString(run, graphics);
-
- AttributedCharacterIterator it = at.getIterator();
- int paragraphStart = it.getBeginIndex();
- int paragraphEnd = it.getEndIndex();
-
- List<TextElement> lines = new ArrayList<TextElement>();
- LineBreakMeasurer measurer = new LineBreakMeasurer(it, frc);
- measurer.setPosition(paragraphStart);
- while (measurer.getPosition() < paragraphEnd) {
- int startIndex = measurer.getPosition();
- int nextBreak = text.indexOf('\n', measurer.getPosition() + 1);
-
- boolean prStart = text.charAt(startIndex) == '\n';
- if(prStart) measurer.setPosition(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;
- }
-
- float wrappingWidth = textWidth - _shape.getMarginLeft() - _shape.getMarginRight();
- int bulletOffset = rt.getBulletOffset();
- int textOffset = rt.getTextOffset();
- int indent = rt.getIndentLevel();
-
- TextRulerAtom ruler = run.getTextRuler();
- if(ruler != null) {
- int bullet_val = ruler.getBulletOffsets()[indent]*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- int text_val = ruler.getTextOffsets()[indent]*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- if(bullet_val > text_val){
- int a = bullet_val;
- bullet_val = text_val;
- text_val = a;
- }
- if(bullet_val != 0 ) bulletOffset = bullet_val;
- if(text_val != 0) textOffset = text_val;
- }
-
- if(bulletOffset > 0 || prStart || startIndex == 0) wrappingWidth -= textOffset;
-
- if (_shape.getWordWrap() == HSLFTextShape.WrapNone) {
- wrappingWidth = _shape.getSheet().getSlideShow().getPageSize().width;
- }
-
- TextLayout textLayout = measurer.nextLayout(wrappingWidth + 1,
- nextBreak == -1 ? paragraphEnd : nextBreak, true);
- if (textLayout == null) {
- textLayout = measurer.nextLayout(textWidth,
- nextBreak == -1 ? paragraphEnd : nextBreak, false);
- }
- if(textLayout == null){
- logger.log(POILogger.WARN, "Failed to break text into lines: wrappingWidth: "+wrappingWidth+
- "; text: " + rt.getText());
- measurer.setPosition(rt.getEndIndex());
- continue;
- }
- int endIndex = measurer.getPosition();
-
- float lineHeight = (float)textLayout.getBounds().getHeight();
- int linespacing = rt.getLineSpacing();
- if(linespacing == 0) linespacing = 100;
-
- TextElement el = new TextElement();
- if(linespacing >= 0){
- el.ascent = textLayout.getAscent()*linespacing/100;
- } else {
- el.ascent = -linespacing*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- }
-
- el._align = rt.getAlignment();
- el.advance = textLayout.getAdvance();
- el._textOffset = textOffset;
- el._text = new AttributedString(it, startIndex, endIndex);
- el.textStartIndex = startIndex;
- el.textEndIndex = endIndex;
-
- if (prStart){
- int sp = rt.getSpaceBefore();
- float spaceBefore;
- if(sp >= 0){
- spaceBefore = lineHeight * sp/100;
- } else {
- spaceBefore = -sp*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- }
- el.ascent += spaceBefore;
- }
-
- float descent;
- if(linespacing >= 0){
- descent = (textLayout.getDescent() + textLayout.getLeading())*linespacing/100;
- } else {
- descent = -linespacing*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- }
- if (prStart){
- int sp = rt.getSpaceAfter();
- float spaceAfter;
- if(sp >= 0){
- spaceAfter = lineHeight * sp/100;
- } else {
- spaceAfter = -sp*HSLFShape.POINT_DPI/HSLFShape.MASTER_DPI;
- }
- el.ascent += spaceAfter;
- }
- el.descent = descent;
-
- if(rt.isBullet() && (prStart || startIndex == 0)){
- it.setIndex(startIndex);
-
- AttributedString bat = new AttributedString(Character.toString(rt.getBulletChar()));
- Color clr = rt.getBulletColor();
- if (clr != null) bat.addAttribute(TextAttribute.FOREGROUND, clr);
- else bat.addAttribute(TextAttribute.FOREGROUND, it.getAttribute(TextAttribute.FOREGROUND));
-
- int fontIdx = rt.getBulletFont();
- if(fontIdx == -1) fontIdx = rt.getFontIndex();
- PPFont bulletFont = _shape.getSheet().getSlideShow().getFont(fontIdx);
- bat.addAttribute(TextAttribute.FAMILY, bulletFont.getFontName());
-
- int bulletSize = rt.getBulletSize();
- int fontSize = rt.getFontSize();
- if(bulletSize != -1) fontSize = Math.round(fontSize*bulletSize*0.01f);
- bat.addAttribute(TextAttribute.SIZE, new Float(fontSize));
-
- if(!new Font(bulletFont.getFontName(), Font.PLAIN, 1).canDisplay(rt.getBulletChar())){
- bat.addAttribute(TextAttribute.FAMILY, "Arial");
- bat = new AttributedString("" + DEFAULT_BULLET_CHAR, bat.getIterator().getAttributes());
- }
-
- if(text.substring(startIndex, endIndex).length() > 1){
- el._bullet = bat;
- el._bulletOffset = bulletOffset;
- }
- }
- lines.add(el);
- }
-
- //finally draw the text fragments
- TextElement[] elems = new TextElement[lines.size()];
- return lines.toArray(elems);
- }
-
- public static class TextElement {
- public AttributedString _text;
- public int _textOffset;
- public AttributedString _bullet;
- public int _bulletOffset;
- public int _align;
- public float ascent, descent;
- public float advance;
- public int textStartIndex, textEndIndex;
- }
-
- public static class Key extends RenderingHints.Key {
- String description;
-
- public Key(int paramInt, String paramString) {
- super(paramInt);
- this.description = paramString;
- }
-
- public final int getIndex() {
- return intKey();
- }
-
- public final String toString() {
- return this.description;
- }
-
- public boolean isCompatibleValue(Object paramObject) {
- return true;
- }
- }
-}
+++ /dev/null
-/* ====================================================================
- 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.model.textproperties.TextProp;
-import org.apache.poi.hslf.record.*;
-
-/**
- * Title masters define the design template for slides with a Title Slide layout.
- *
- * @author Yegor Kozlov
- */
-public final class TitleMaster extends HSLFMasterSheet {
- private HSLFTextParagraph[] _runs;
-
- /**
- * Constructs a TitleMaster
- *
- */
- public TitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) {
- super(record, sheetNo);
-
- _runs = findTextRuns(getPPDrawing());
- for (int i = 0; i < _runs.length; i++) _runs[i].setSheet(this);
- }
-
- /**
- * Returns an array of all the TextRuns found
- */
- public HSLFTextParagraph[] getTextRuns() {
- return _runs;
- }
-
- /**
- * Delegate the call to the underlying slide master.
- */
- public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
- HSLFMasterSheet master = getMasterSheet();
- return master == null ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
- }
-
- /**
- * Returns the slide master for this title master.
- */
- public HSLFMasterSheet getMasterSheet(){
- SlideMaster[] master = getSlideShow().getSlidesMasters();
- SlideAtom sa = ((org.apache.poi.hslf.record.Slide)getSheetContainer()).getSlideAtom();
- int masterId = sa.getMasterID();
- for (int i = 0; i < master.length; i++) {
- if (masterId == master[i]._getSheetNumber()) return master[i];
- }
- return null;
- }
-}
* of the property is itself a mask, encoding several different
* (but related) properties
*/
-public class BitMaskTextProp extends TextProp implements Cloneable {
+public abstract class BitMaskTextProp extends TextProp implements Cloneable {
private String[] subPropNames;
private int[] subPropMasks;
private boolean[] subPropMatches;
subPropMatches[idx] = value;
}
- public Object clone(){
+ @Override
+ public BitMaskTextProp clone(){
BitMaskTextProp newObj = (BitMaskTextProp)super.clone();
// Don't carry over matches, but keep everything
public int getCharactersCovered() { return charactersCovered; }
public int getIndentLevel() {
- return (int)indentLevel;
+ return indentLevel;
}
/**
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hslf.model.textproperties;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.poi.util.LittleEndian;\r
+import org.apache.poi.util.LittleEndianConsts;\r
+\r
+/**\r
+ * Container for tabstop lists\r
+ */\r
+public class TabStopPropCollection extends TextProp {\r
+ public enum TabStopType {\r
+ LEFT(0), CENTER(1), RIGHT(2), DECIMAL(3);\r
+ private final int val;\r
+ TabStopType(int val) {\r
+ this.val = val;\r
+ }\r
+ public static TabStopType fromRecordVal(int val) {\r
+ for (TabStopType tst : values()) {\r
+ if (tst.val == val) return tst;\r
+ }\r
+ return LEFT;\r
+ }\r
+ }\r
+\r
+ public static class TabStop {\r
+ /**\r
+ * If the TextPFException record that contains this TabStop structure also contains a\r
+ * leftMargin, then the value of position is relative to the left margin of the paragraph;\r
+ * otherwise, the value is relative to the left side of the paragraph.\r
+ * \r
+ * If a TextRuler record contains this TabStop structure, the value is relative to the\r
+ * left side of the text ruler.\r
+ */\r
+ private int position;\r
+\r
+ /**\r
+ * A enumeration that specifies how text aligns at the tab stop.\r
+ */\r
+ private TabStopType type;\r
+\r
+ public TabStop(int position, TabStopType type) {\r
+ this.position = position;\r
+ this.type = type;\r
+ }\r
+ \r
+ public int getPosition() {\r
+ return position;\r
+ }\r
+\r
+ public void setPosition(int position) {\r
+ this.position = position;\r
+ }\r
+\r
+ public TabStopType getType() {\r
+ return type;\r
+ }\r
+\r
+ public void setType(TabStopType type) {\r
+ this.type = type;\r
+ }\r
+ }\r
+ \r
+ private List<TabStop> tabStops = new ArrayList<TabStop>();\r
+ \r
+ public TabStopPropCollection() {\r
+ super(0, 0x100000, "tabStops");\r
+ }\r
+ \r
+ /**\r
+ * Parses the tabstops from TxMasterStyle record\r
+ *\r
+ * @param data the data stream\r
+ * @param offset the offset within the data\r
+ * @return the new offset\r
+ */\r
+ public void parseProperty(byte data[], int offset) {\r
+ int count = LittleEndian.getUShort(data, offset);\r
+ offset += LittleEndianConsts.SHORT_SIZE;\r
+ for (int i=0; i<count; i++) {\r
+ int position = LittleEndian.getShort(data, offset);\r
+ offset += LittleEndianConsts.SHORT_SIZE;\r
+ int recVal = LittleEndian.getShort(data, offset);\r
+ TabStopType type = TabStopType.fromRecordVal(recVal);\r
+ offset += LittleEndianConsts.SHORT_SIZE;\r
+ tabStops.add(new TabStop(position, type));\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public int getSize() {\r
+ return LittleEndianConsts.SHORT_SIZE + tabStops.size()*LittleEndianConsts.INT_SIZE;\r
+ }\r
+}\r
this.dataValue = 0;
}
+ /**
+ * Clones the property
+ */
+ public TextProp(TextProp other) {
+ this.sizeOfDataBlock = other.sizeOfDataBlock;
+ this.maskInHeader = other.maskInHeader;
+ this.propName = other.propName;
+ this.dataValue = other.dataValue;
+ }
+
/**
* Name of the text property
*/
/**
* Clone, eg when you want to actually make use of one of these.
*/
- public Object clone(){
+ @Override
+ public TextProp clone(){
try {
- return super.clone();
+ return (TextProp)super.clone();
} catch(CloneNotSupportedException e) {
throw new InternalError(e.getMessage());
}
}
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + dataValue;
+ result = prime * result + maskInHeader;
+ result = prime * result + ((propName == null) ? 0 : propName.hashCode());
+ result = prime * result + sizeOfDataBlock;
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ TextProp other = (TextProp) obj;
+ if (dataValue != other.dataValue) return false;
+ if (maskInHeader != other.maskInHeader) return false;
+ if (propName == null) {
+ if (other.propName != null) return false;
+ } else if (!propName.equals(other.propName)) return false;
+ if (sizeOfDataBlock != other.sizeOfDataBlock) return false;
+ return true;
+ }
}
\ No newline at end of file
import java.io.IOException;
import java.io.OutputStream;
-import java.util.LinkedList;
+import java.util.*;
import org.apache.poi.hslf.record.StyleTextPropAtom;
import org.apache.poi.util.LittleEndian;
public class TextPropCollection {
private int charactersCovered;
private short reservedField;
- private LinkedList<TextProp> textPropList;
+ private List<TextProp> textPropList;
private int maskSpecial = 0;
public int getSpecialMask() { return maskSpecial; }
/** Fetch the number of characters this styling applies to */
public int getCharactersCovered() { return charactersCovered; }
/** Fetch the TextProps that define this styling */
- public LinkedList<TextProp> getTextPropList() { return textPropList; }
+ public List<TextProp> getTextPropList() { return textPropList; }
/** Fetch the TextProp with this name, or null if it isn't present */
public TextProp findByName(String textPropName) {
}
// Add a copy of this property, in the right place to the list
- TextProp textProp = (TextProp)base.clone();
+ TextProp textProp = base.clone();
int pos = 0;
for(int i=0; i<textPropList.size(); i++) {
TextProp curProp = textPropList.get(i);
// For each possible entry, see if we match the mask
// If we do, decode that, save it, and shuffle on
- for(int i=0; i<potentialProperties.length; i++) {
+ for(TextProp tp : potentialProperties) {
// Check there's still data left to read
// Check if this property is found in the mask
- if((containsField & potentialProperties[i].getMask()) != 0) {
+ if((containsField & tp.getMask()) != 0) {
if(dataOffset+bytesPassed >= data.length) {
// Out of data, can't be any more properties to go
// remember the mask and return
- maskSpecial |= potentialProperties[i].getMask();
+ maskSpecial |= tp.getMask();
return bytesPassed;
}
// Bingo, data contains this property
- TextProp prop = (TextProp)potentialProperties[i].clone();
+ TextProp prop = tp.clone();
int val = 0;
- if(prop.getSize() == 2) {
+ if (prop instanceof TabStopPropCollection) {
+ ((TabStopPropCollection)prop).parseProperty(data, dataOffset+bytesPassed);
+ } else if (prop.getSize() == 2) {
val = LittleEndian.getShort(data,dataOffset+bytesPassed);
- } else if(prop.getSize() == 4){
+ } else if(prop.getSize() == 4) {
val = LittleEndian.getInt(data,dataOffset+bytesPassed);
- } else if (prop.getSize() == 0){
+ } else if (prop.getSize() == 0) {
//remember "special" bits.
- maskSpecial |= potentialProperties[i].getMask();
+ maskSpecial |= tp.getMask();
continue;
}
prop.setValue(val);
public TextPropCollection(int charactersCovered, short reservedField) {
this.charactersCovered = charactersCovered;
this.reservedField = reservedField;
- textPropList = new LinkedList<TextProp>();
+ textPropList = new ArrayList<TextProp>();
}
/**
public TextPropCollection(int textSize) {
charactersCovered = textSize;
reservedField = -1;
- textPropList = new LinkedList<TextProp>();
+ textPropList = new ArrayList<TextProp>();
+ }
+
+ /**
+ * Clones the given text properties
+ */
+ public void copy(TextPropCollection other) {
+ this.charactersCovered = other.charactersCovered;
+ this.reservedField = other.reservedField;
+ this.textPropList.clear();
+ for (TextProp tp : other.textPropList) {
+ TextProp tpCopy = tp.clone();
+ if (tpCopy instanceof BitMaskTextProp) {
+ BitMaskTextProp bmt = (BitMaskTextProp)tpCopy;
+ boolean matches[] = ((BitMaskTextProp)tp).getSubPropMatches();
+ for (int i=0; i<matches.length; i++) {
+ bmt.setSubValue(matches[i], i);
+ }
+ }
+ this.textPropList.add(tpCopy);
+ }
}
/**
// Then the mask field
int mask = maskSpecial;
for(int i=0; i<textPropList.size(); i++) {
- TextProp textProp = (TextProp)textPropList.get(i);
+ TextProp textProp = textPropList.get(i);
//sometimes header indicates that the bitmask is present but its value is 0
if (textProp instanceof BitMaskTextProp) {
public void setReservedField(short val){
reservedField = val;
}
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + charactersCovered;
+ result = prime * result + maskSpecial;
+ result = prime * result + reservedField;
+ result = prime * result + ((textPropList == null) ? 0 : textPropList.hashCode());
+ return result;
+ }
+ /**
+ * compares most properties apart of the covered characters length
+ */
+ public boolean equals(Object other) {
+ if (this == other) return true;
+ if (other == null) return false;
+ if (getClass() != other.getClass()) return false;
+
+ TextPropCollection o = (TextPropCollection)other;
+ if (o.maskSpecial != this.maskSpecial || o.reservedField != this.reservedField) {
+ return false;
+ }
+
+ if (textPropList == null) {
+ return (o.textPropList == null);
+ }
+
+ Map<String,TextProp> m = new HashMap<String,TextProp>();
+ for (TextProp tp : o.textPropList) {
+ m.put(tp.getName(), tp);
+ }
+
+ for (TextProp tp : this.textPropList) {
+ TextProp otp = m.get(tp.getName());
+ if (!tp.equals(otp)) return false;
+ }
+
+ return true;
+ }
+
}
* offers methods to get either back out.
*/
public static class Type {
- public int typeID;
- public Class<? extends Record> handlingClass;
+ public final int typeID;
+ public final Class<? extends Record> handlingClass;
public Type(int typeID, Class<? extends Record> handlingClass) {
this.typeID = typeID;
this.handlingClass = handlingClass;
import java.io.OutputStream;
import java.util.LinkedList;
-import org.apache.poi.hslf.model.textproperties.AlignmentTextProp;
-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.model.textproperties.*;
import org.apache.poi.util.HexDump;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogger;
public final class StyleTextPropAtom extends RecordAtom
{
private byte[] _header;
- private static long _type = 4001l;
+ private static final long _type = RecordTypes.StyleTextPropAtom.typeID;
private byte[] reserved;
private byte[] rawContents; // Holds the contents between write-outs
}
/** All the different kinds of paragraph properties we might handle */
- public static final TextProp[] paragraphTextPropTypes = new TextProp[] {
+ public static final TextProp[] paragraphTextPropTypes = {
+ // TextProp order is according to 2.9.20 TextPFException,
+ // bitmask order can be different
new TextProp(0, 0x1, "hasBullet"),
new TextProp(0, 0x2, "hasBulletFont"),
new TextProp(0, 0x4, "hasBulletColor"),
new TextProp(2, 0x40, "bullet.size"),
new TextProp(4, 0x20, "bullet.color"),
new AlignmentTextProp(),
- new TextProp(2, 0x100, "text.offset"),
- new TextProp(2, 0x400, "bullet.offset"),
new TextProp(2, 0x1000, "linespacing"),
new TextProp(2, 0x2000, "spacebefore"),
new TextProp(2, 0x4000, "spaceafter"),
+ new TextProp(2, 0x100, "text.offset"), // left margin
+ // 0x200 - Undefined and MUST be ignored
+ new TextProp(2, 0x400, "bullet.offset"), // indent
new TextProp(2, 0x8000, "defaultTabSize"),
- new TextProp(2, 0x100000, "tabStops"),
+ new TabStopPropCollection(), // tabstops size is variable!
new TextProp(2, 0x10000, "fontAlign"),
- new TextProp(2, 0xA0000, "wrapFlags"),
- new TextProp(2, 0x200000, "textDirection")
+ new TextProp(2, 0xE0000, "wrapFlags"), // charWrap | wordWrap | overflow
+ new TextProp(2, 0x200000, "textDirection"),
+ // 0x400000 MUST be zero and MUST be ignored
+ new TextProp(0, 0x800000, "bullet.blip"), // TODO: check size
+ new TextProp(0, 0x1000000, "bullet.scheme"), // TODO: check size
+ new TextProp(0, 0x2000000, "hasBulletScheme"), // TODO: check size
+ // 0xFC000000 MUST be zero and MUST be ignored
};
/** All the different kinds of character properties we might handle */
public static final TextProp[] characterTextPropTypes = new TextProp[] {
initialised = false;
}
+ /**
+ * Clear styles, so new collections can be added
+ */
+ public void clearStyles() {
+ paragraphStyles.clear();
+ charStyles.clear();
+ }
+
/**
* Create a new Paragraph TextPropCollection, and add it to the list
* @param charactersCovered The number of characters this TextPropCollection will cover
public final class TextBytesAtom extends RecordAtom
{
private byte[] _header;
- private static long _type = 4008l;
+ private static long _type = RecordTypes.TextBytesAtom.typeID;
/** The bytes that make up the text */
private byte[] _text;
public final class TextCharsAtom extends RecordAtom
{
private byte[] _header;
- private static long _type = 4000l;
+ private static long _type = RecordTypes.TextCharsAtom.typeID;
/** The bytes that make up the text */
private byte[] _text;
public final class TextHeaderAtom extends RecordAtom implements ParentAwareRecord
{
private byte[] _header;
- private static long _type = 3999l;
+ private static long _type = RecordTypes.TextHeaderAtom.typeID;
private RecordContainer parentRecord;
public static final int TITLE_TYPE = 0;
/** The kind of text it is */
private int textType;
+ /** position in the owning SlideListWithText */
+ private int index = -1;
public int getTextType() { return textType; }
public void setTextType(int type) { textType = type; }
+
+ /**
+ * @return 0-based index of the text run in the SLWT container
+ */
+ public int getIndex() { return index; }
+
+ /**
+ * @param id 0-based index of the text run in the SLWT container
+ */
+ public void setIndex(int index) { this.index = index; }
public RecordContainer getParentRecord() { return parentRecord; }
public void setParentRecord(RecordContainer record) { this.parentRecord = record; }
* @author Yegor Kozlov
*/
public final class TextSpecInfoAtom extends RecordAtom {
+ private static final long _type = RecordTypes.TextSpecInfoAtom.typeID;
+
/**
* Record header.
*/
* Gets the record type.
* @return the record type.
*/
- public long getRecordType() { return RecordTypes.TextSpecInfoAtom.typeID; }
+ public long getRecordType() { return _type; }
/**
* Write the contents of the record back, so it can be written
*/
public static final int MAX_INDENT = 5;
+/*
+ private static TextProp paragraphSpecialPropTypes[] = {
+ new ParagraphFlagsTextProp(),
+ new TextProp(2, 0x80, "bullet.char"),
+ new TextProp(2, 0x10, "bullet.font"),
+ new TextProp(2, 0x40, "bullet.size"),
+ new TextProp(4, 0x20, "bullet.color"),
+ new TextProp(2, 0xD00, "alignment"),
+ new TextProp(2, 0x1000, "linespacing"),
+ new TextProp(2, 0x2000, "spacebefore"),
+ new TextProp(2, 0x4000, "spaceafter"),
+ new TextProp(2, 0x8000, "text.offset"),
+ new TextProp(2, 0x10000, "bullet.offset"),
+ new TextProp(2, 0x20000, "defaulttab"),
+ new TextProp(2, 0x40000, "para_unknown_2"),
+ new TextProp(2, 0x80000, "para_unknown_3"),
+ new TextProp(2, 0x100000, "para_unknown_4"),
+ new TextProp(2, 0x200000, "para_unknown_5")
+ };
+
+ private static TextProp characterSpecialPropTypes[] = {
+ new CharFlagsTextProp(),
+ new TextProp(2, 0x10000, "font.index"),
+ new TextProp(2, 0x20000, "char_unknown_1"),
+ new TextProp(4, 0x40000, "char_unknown_2"),
+ new TextProp(2, 0x80000, "font.size"),
+ new TextProp(2, 0x100000, "char_unknown_3"),
+ new TextProp(4, 0x200000, "font.color"),
+ new TextProp(2, 0x800000, "char_unknown_4")
+ };
+*/
private byte[] _header;
private static long _type = 4003;
private byte[] _data;
/**
* parse the record data and initialize styles
*/
+ @SuppressWarnings("unused")
protected void init(){
//type of the text
int type = getTextType();
* ones, or the standard StyleTextPropAtom ones
*/
protected TextProp[] getParagraphProps(int type, int level){
- if (level != 0 || type >= MAX_INDENT){
- return StyleTextPropAtom.paragraphTextPropTypes;
- }
- return new TextProp[] {
- new ParagraphFlagsTextProp(),
- new TextProp(2, 0x80, "bullet.char"),
- new TextProp(2, 0x10, "bullet.font"),
- new TextProp(2, 0x40, "bullet.size"),
- new TextProp(4, 0x20, "bullet.color"),
- new TextProp(2, 0xD00, "alignment"),
- new TextProp(2, 0x1000, "linespacing"),
- new TextProp(2, 0x2000, "spacebefore"),
- new TextProp(2, 0x4000, "spaceafter"),
- new TextProp(2, 0x8000, "text.offset"),
- new TextProp(2, 0x10000, "bullet.offset"),
- new TextProp(2, 0x20000, "defaulttab"),
- new TextProp(2, 0x40000, "para_unknown_2"),
- new TextProp(2, 0x80000, "para_unknown_3"),
- new TextProp(2, 0x100000, "para_unknown_4"),
- new TextProp(2, 0x200000, "para_unknown_5")
- };
-
+ return StyleTextPropAtom.paragraphTextPropTypes;
+// return (level != 0 || type >= MAX_INDENT)
+// ? StyleTextPropAtom.paragraphTextPropTypes
+// : paragraphSpecialPropTypes;
}
/**
* ones, or the standard StyleTextPropAtom ones
*/
protected TextProp[] getCharacterProps(int type, int level){
- if (level != 0 || type >= MAX_INDENT){
- return StyleTextPropAtom.characterTextPropTypes;
- }
- return new TextProp[] {
- new CharFlagsTextProp(),
- new TextProp(2, 0x10000, "font.index"),
- new TextProp(2, 0x20000, "char_unknown_1"),
- new TextProp(4, 0x40000, "char_unknown_2"),
- new TextProp(2, 0x80000, "font.size"),
- new TextProp(2, 0x100000, "char_unknown_3"),
- new TextProp(4, 0x200000, "font.color"),
- new TextProp(2, 0x800000, "char_unknown_4")
- };
+ return StyleTextPropAtom.characterTextPropTypes;
+// return (level != 0 || type >= MAX_INDENT)
+// ? StyleTextPropAtom.characterTextPropTypes
+// : characterSpecialPropTypes;
}
}
--- /dev/null
+/* ====================================================================
+ 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.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.ss.usermodel.ShapeTypes;
+
+/**
+ * Represents an AutoShape.
+ * <p>
+ * AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments.
+ * See {@link ShapeTypes}
+ * </p>
+ *
+ * @author Yegor Kozlov
+ */
+public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFTextParagraph> {
+
+ protected HSLFAutoShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ super(escherRecord, parent);
+ }
+
+ public HSLFAutoShape(ShapeType type, ShapeContainer<HSLFShape> 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(VerticalAlignment.MIDDLE);
+ setHorizontalCentered(true);
+ setWordWrap(HSLFTextBox.WrapNone);
+ }
+
+ /**
+ * Gets adjust value which controls smart resizing of the auto-shape.
+ *
+ * <p>
+ * 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).
+ * </p>
+ *
+ * @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.
+ *
+ * <p>
+ * 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).
+ * </p>
+ *
+ * @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);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.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<HSLFShape> parent) {
+ super(escherRecord, parent);
+ }
+
+ protected EscherContainerRecord createSpContainer(boolean isChild) {
+ return null;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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 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.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 <code>Fill</code> 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 <code>FILL_*</code> 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<EscherRecord> lst = bstore.getChildRecords();
+ return (EscherBSERecord)lst.get(idx-1);
+ }
+
+ /**
+ * Sets fill type.
+ * Must be one of the <code>FILL_*</code> 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);
+ }
+ }
+
+ /**
+ * <code>PictureData</code> 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<EscherRecord> 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 <code>SlideShow.addPicture</code> 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);
+ }
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.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.
+ *
+ * <p>
+ * 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 <code>java.awt.geom.GeneralPath</code>.
+ * </p>
+ * @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 <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected HSLFFreeformShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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<byte[]> segInfo = new ArrayList<byte[]>();
+ List<Point2D.Double> pntInfo = new ArrayList<Point2D.Double>();
+ 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);
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.geom.Rectangle2D;
+import java.util.*;
+
+import org.apache.poi.ddf.*;
+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;
+
+/**
+ * Represents a group of shapes.
+ *
+ * @author Yegor Kozlov
+ */
+public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShape> {
+
+ /**
+ * Create a new ShapeGroup. This constructor is used when a new shape is created.
+ *
+ */
+ public HSLFGroupShape(){
+ this(null, null);
+ _escherContainer = createSpContainer(false);
+ }
+
+ /**
+ * Create a ShapeGroup object and initilize it from the supplied Record container.
+ *
+ * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected HSLFGroupShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ super(escherRecord, parent);
+ }
+
+ @Override
+ public List<HSLFShape> getShapes() {
+ return getShapeList();
+ }
+
+ /**
+ * Sets the anchor (the bounding box rectangle) of this shape.
+ * All coordinates should be expressed in Master units (576 dpi).
+ *
+ * @param anchor new anchor
+ */
+ public void setAnchor(java.awt.Rectangle anchor){
+
+ EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+ //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);
+ clientAnchor.fillFields(header, 0, null);
+
+ clientAnchor.setFlag((short)(anchor.y*MASTER_DPI/POINT_DPI));
+ clientAnchor.setCol1((short)(anchor.x*MASTER_DPI/POINT_DPI));
+ clientAnchor.setDx1((short)((anchor.width + anchor.x)*MASTER_DPI/POINT_DPI));
+ clientAnchor.setRow1((short)((anchor.height + anchor.y)*MASTER_DPI/POINT_DPI));
+
+ EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
+
+ spgr.setRectX1(anchor.x*MASTER_DPI/POINT_DPI);
+ spgr.setRectY1(anchor.y*MASTER_DPI/POINT_DPI);
+ spgr.setRectX2((anchor.x + anchor.width)*MASTER_DPI/POINT_DPI);
+ spgr.setRectY2((anchor.y + anchor.height)*MASTER_DPI/POINT_DPI);
+ }
+
+ /**
+ * Sets the coordinate space of this group. All children are constrained
+ * to these coordinates.
+ *
+ * @param anchor the coordinate space of this group
+ */
+ public void setCoordinates(Rectangle2D anchor){
+ EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
+
+ int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI);
+ int y1 = (int)Math.round(anchor.getY()*MASTER_DPI/POINT_DPI);
+ int x2 = (int)Math.round((anchor.getX() + anchor.getWidth())*MASTER_DPI/POINT_DPI);
+ int y2 = (int)Math.round((anchor.getY() + anchor.getHeight())*MASTER_DPI/POINT_DPI);
+
+ spgr.setRectX1(x1);
+ spgr.setRectY1(y1);
+ spgr.setRectX2(x2);
+ spgr.setRectY2(y2);
+
+ }
+
+ /**
+ * Gets the coordinate space of this group. All children are constrained
+ * to these coordinates.
+ *
+ * @return the coordinate space of this group
+ */
+ public Rectangle2D getCoordinates(){
+ EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
+
+ Rectangle2D.Float anchor = new Rectangle2D.Float();
+ anchor.x = (float)spgr.getRectX1()*POINT_DPI/MASTER_DPI;
+ anchor.y = (float)spgr.getRectY1()*POINT_DPI/MASTER_DPI;
+ anchor.width = (float)(spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI;
+ anchor.height = (float)(spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI;
+
+ return anchor;
+ }
+
+ /**
+ * Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes
+ */
+ protected EscherContainerRecord createSpContainer(boolean isChild) {
+ EscherContainerRecord spgr = new EscherContainerRecord();
+ spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
+ spgr.setOptions((short)15);
+
+ //The group itself is a shape, and always appears as the first EscherSpContainer in the group container.
+ EscherContainerRecord spcont = new EscherContainerRecord();
+ spcont.setRecordId(EscherContainerRecord.SP_CONTAINER);
+ spcont.setOptions((short)15);
+
+ EscherSpgrRecord spg = new EscherSpgrRecord();
+ spg.setOptions((short)1);
+ spcont.addChildRecord(spg);
+
+ EscherSpRecord sp = new EscherSpRecord();
+ short type = (short)((ShapeType.NOT_PRIMITIVE.nativeId << 4) + 2);
+ sp.setOptions(type);
+ sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_GROUP);
+ spcont.addChildRecord(sp);
+
+ EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();
+ spcont.addChildRecord(anchor);
+
+ spgr.addChildRecord(spcont);
+ return spgr;
+ }
+
+ /**
+ * Add a shape to this group.
+ *
+ * @param shape - the Shape to add
+ */
+ public void addShape(HSLFShape shape){
+ _escherContainer.addChildRecord(shape.getSpContainer());
+
+ HSLFSheet sheet = getSheet();
+ shape.setSheet(sheet);
+ shape.setShapeId(sheet.allocateShapeId());
+ shape.afterInsert(sheet);
+ }
+
+ /**
+ * Moves this <code>ShapeGroup</code> to the specified location.
+ * <p>
+ * @param x the x coordinate of the top left corner of the shape in new location
+ * @param y the y coordinate of the top left corner of the shape in new location
+ */
+ public void moveTo(int x, int y){
+ java.awt.Rectangle anchor = getAnchor();
+ int dx = x - anchor.x;
+ int dy = y - anchor.y;
+ anchor.translate(dx, dy);
+ setAnchor(anchor);
+
+
+ for (HSLFShape shape : getShapes()) {
+ java.awt.Rectangle chanchor = shape.getAnchor();
+ chanchor.translate(dx, dy);
+ shape.setAnchor(chanchor);
+ }
+ }
+
+ /**
+ * Returns the anchor (the bounding box rectangle) of this shape group.
+ * All coordinates are expressed in points (72 dpi).
+ *
+ * @return the anchor of this shape group
+ */
+ public Rectangle2D getAnchor2D(){
+ EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+ Rectangle2D.Float anchor = new Rectangle2D.Float();
+ if(clientAnchor == null){
+ logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord.");
+ EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
+ anchor = new Rectangle2D.Float(
+ (float)rec.getDx1()*POINT_DPI/MASTER_DPI,
+ (float)rec.getDy1()*POINT_DPI/MASTER_DPI,
+ (float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
+ (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
+ );
+ } else {
+ anchor.x = (float)clientAnchor.getCol1()*POINT_DPI/MASTER_DPI;
+ anchor.y = (float)clientAnchor.getFlag()*POINT_DPI/MASTER_DPI;
+ anchor.width = (float)(clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ;
+ anchor.height = (float)(clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI;
+ }
+
+ return anchor;
+ }
+
+ /**
+ * Return type of the shape.
+ * In most cases shape group type is {@link org.apache.poi.hslf.model.ShapeTypes#NotPrimitive}
+ *
+ * @return type of the shape.
+ */
+ public ShapeType getShapeType(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ int nativeId = spRecord.getOptions() >> 4;
+ return ShapeType.forId(nativeId, false);
+ }
+
+ /**
+ * Returns <code>null</code> - shape groups can't have hyperlinks
+ *
+ * @return <code>null</code>.
+ */
+ public HSLFHyperlink getHyperlink(){
+ return null;
+ }
+
+ @Override
+ public <T extends EscherRecord> T getEscherChild(int recordId){
+ EscherContainerRecord groupInfoContainer = (EscherContainerRecord)_escherContainer.getChild(0);
+ return groupInfoContainer.getChildById((short)recordId);
+ }
+
+ public Iterator<HSLFShape> iterator() {
+ return getShapeList().iterator();
+ }
+
+ public boolean removeShape(HSLFShape shape) {
+ // TODO: implement!
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @return the shapes contained in this group container
+ */
+ protected List<HSLFShape> getShapeList() {
+ // Out escher container record should contain several
+ // SpContainers, the first of which is the group shape itself
+ Iterator<EscherRecord> iter = _escherContainer.getChildIterator();
+
+ // Don't include the first SpContainer, it is always NotPrimitive
+ if (iter.hasNext()) {
+ iter.next();
+ }
+ List<HSLFShape> shapeList = new ArrayList<HSLFShape>();
+ while (iter.hasNext()) {
+ EscherRecord r = iter.next();
+ if(r instanceof EscherContainerRecord) {
+ // Create the Shape for it
+ EscherContainerRecord container = (EscherContainerRecord)r;
+ HSLFShape shape = HSLFShapeFactory.createShape(container, this);
+ shape.setSheet(getSheet());
+ shapeList.add( shape );
+ } else {
+ // Should we do anything special with these non
+ // Container records?
+ logger.log(POILogger.ERROR, "Shape contained non container escher record, was " + r.getClass().getName());
+ }
+ }
+
+ return shapeList;
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.util.*;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+
+/**
+ * Represents a hyperlink in a PowerPoint document
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFHyperlink {
+ public static final byte LINK_NEXTSLIDE = InteractiveInfoAtom.LINK_NextSlide;
+ public static final byte LINK_PREVIOUSSLIDE = InteractiveInfoAtom.LINK_PreviousSlide;
+ public static final byte LINK_FIRSTSLIDE = InteractiveInfoAtom.LINK_FirstSlide;
+ public static final byte LINK_LASTSLIDE = InteractiveInfoAtom.LINK_LastSlide;
+ public static final byte LINK_SLIDENUMBER = InteractiveInfoAtom.LINK_SlideNumber;
+ public static final byte LINK_URL = InteractiveInfoAtom.LINK_Url;
+ public static final byte LINK_NULL = InteractiveInfoAtom.LINK_NULL;
+
+ private int id=-1;
+ private int type;
+ private String address;
+ private String title;
+ private int startIndex, endIndex;
+
+ /**
+ * Gets the type of the hyperlink action.
+ * Must be a <code>LINK_*</code> constant</code>
+ *
+ * @return the hyperlink URL
+ * @see InteractiveInfoAtom
+ */
+ public int getType() {
+ return type;
+ }
+
+ public void setType(int val) {
+ type = val;
+ switch(type){
+ case LINK_NEXTSLIDE:
+ title = "NEXT";
+ address = "1,-1,NEXT";
+ break;
+ case LINK_PREVIOUSSLIDE:
+ title = "PREV";
+ address = "1,-1,PREV";
+ break;
+ case LINK_FIRSTSLIDE:
+ title = "FIRST";
+ address = "1,-1,FIRST";
+ break;
+ case LINK_LASTSLIDE:
+ title = "LAST";
+ address = "1,-1,LAST";
+ break;
+ case LINK_SLIDENUMBER:
+ break;
+ default:
+ title = "";
+ address = "";
+ break;
+ }
+ }
+
+ /**
+ * Gets the hyperlink URL
+ *
+ * @return the hyperlink URL
+ */
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(HSLFSlide slide) {
+ String href = slide._getSheetNumber() + ","+slide.getSlideNumber()+",Slide " + slide.getSlideNumber();
+ setAddress(href);;
+ setTitle("Slide " + slide.getSlideNumber());
+ setType(HSLFHyperlink.LINK_SLIDENUMBER);
+ }
+
+ public void setAddress(String str) {
+ address = str;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the hyperlink user-friendly title (if different from URL)
+ *
+ * @return the hyperlink user-friendly title
+ */
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String str) {
+ title = str;
+ }
+
+ /**
+ * Gets the beginning character position
+ *
+ * @return the beginning character position
+ */
+ public int getStartIndex() {
+ return startIndex;
+ }
+
+ /**
+ * Gets the ending character position
+ *
+ * @return the ending character position
+ */
+ public int getEndIndex() {
+ return endIndex;
+ }
+
+ /**
+ * Find hyperlinks in a text shape
+ *
+ * @param shape <code>TextRun</code> to lookup hyperlinks in
+ * @return found hyperlinks or <code>null</code> if not found
+ */
+ public static HSLFHyperlink[] find(HSLFTextShape shape){
+ List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
+ 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) {
+ return null;
+ }
+
+ Record[] records = shape.getClientRecords();
+ find(records, exobj, lst);
+
+ HSLFHyperlink[] links = null;
+ if (lst.size() > 0){
+ links = new HSLFHyperlink[lst.size()];
+ lst.toArray(links);
+ }
+ return links;
+ }
+
+ /**
+ * Find hyperlinks in a text paragraph
+ *
+ * @param paragraph <code>TextParagraph</code> to lookup hyperlinks in
+ * @return found hyperlinks or <code>null</code> if not found
+ */
+ public static HSLFHyperlink[] find(HSLFTextParagraph paragraph){
+ List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
+ HSLFSlideShow ppt = paragraph.getSheet().getSlideShow();
+ //document-level container which stores info about all links in a presentation
+ ExObjList exobj = ppt.getDocumentRecord().getExObjList();
+ if (exobj == null) {
+ return null;
+ }
+
+ Record[] records = paragraph.getRecords();
+ find(records, exobj, lst);
+
+ HSLFHyperlink[] links = null;
+ if (lst.size() > 0){
+ links = new HSLFHyperlink[lst.size()];
+ lst.toArray(links);
+ }
+ return links;
+ }
+
+ /**
+ * Find hyperlink assigned to the supplied shape
+ *
+ * @param shape <code>Shape</code> to lookup hyperlink in
+ * @return found hyperlink or <code>null</code>
+ */
+ public static HSLFHyperlink find(HSLFShape shape){
+ List<HSLFHyperlink> lst = new ArrayList<HSLFHyperlink>();
+ 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) {
+ return null;
+ }
+
+ EscherContainerRecord spContainer = shape.getSpContainer();
+ for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext(); ) {
+ EscherRecord obj = it.next();
+ if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID){
+ byte[] data = obj.serialize();
+ Record[] records = Record.findChildRecords(data, 8, data.length-8);
+ find(records, exobj, lst);
+ }
+ }
+
+ return lst.size() == 1 ? (HSLFHyperlink)lst.get(0) : null;
+ }
+
+ private static void find(Record[] records, ExObjList exobj, List<HSLFHyperlink> out){
+ if (records == null) return;
+ for (int i = 0; i < records.length; i++) {
+ //see if we have InteractiveInfo in the textrun's records
+ if( records[i] instanceof InteractiveInfo){
+ InteractiveInfo hldr = (InteractiveInfo)records[i];
+ InteractiveInfoAtom info = hldr.getInteractiveInfoAtom();
+ int id = info.getHyperlinkID();
+ ExHyperlink linkRecord = exobj.get(id);
+ if (linkRecord != null){
+ HSLFHyperlink link = new HSLFHyperlink();
+ link.title = linkRecord.getLinkTitle();
+ link.address = linkRecord.getLinkURL();
+ link.type = info.getAction();
+
+ if (++i < records.length && records[i] instanceof TxInteractiveInfoAtom){
+ TxInteractiveInfoAtom txinfo = (TxInteractiveInfoAtom)records[i];
+ link.startIndex = txinfo.getStartIndex();
+ link.endIndex = txinfo.getEndIndex();
+ }
+ out.add(link);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.SheetContainer;
+import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.sl.usermodel.MasterSheet;
+
+/**
+ * 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 HSLFMasterSheet extends HSLFSheet implements MasterSheet<HSLFShape,HSLFSlideShow> {
+ 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;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.sl.usermodel.Notes;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * 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<HSLFShape, HSLFSlideShow> {
+ protected static POILogger logger = POILogFactory.getLogger(HSLFNotes.class);
+
+ private List<List<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 = HSLFTextParagraph.findTextParagraphs(getPPDrawing());
+ if (_runs.isEmpty()) {
+ logger.log(POILogger.WARN, "No text records found for notes sheet");
+ }
+
+ // Set the sheet on each TextRun
+ for (List<HSLFTextParagraph> ltp : _runs) {
+ for (HSLFTextParagraph tp : ltp) {
+ tp.supplySheet(this);
+ }
+ }
+ }
+
+ /**
+ * Returns an array of all the TextParagraphs found
+ */
+ @Override
+ public List<List<HSLFTextParagraph>> getTextParagraphs() {
+ return _runs;
+ }
+
+ /**
+ * Return <code>null</code> - Notes Masters are not yet supported
+ */
+ public HSLFMasterSheet getMasterSheet() {
+ return null;
+ }
+}
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;
--- /dev/null
+/* ====================================================================
+ 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.Insets;
+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.*;
+import org.apache.poi.hslf.blip.Bitmap;
+import org.apache.poi.hslf.record.Document;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.util.*;
+
+
+/**
+ * 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 <code>Picture</code>
+ *
+ * @param idx the index of the picture
+ */
+ public HSLFPictureShape(int idx){
+ this(idx, null);
+ }
+
+ /**
+ * Create a new <code>Picture</code>
+ *
+ * @param idx the index of the picture
+ * @param parent the parent shape
+ */
+ public HSLFPictureShape(int idx, ShapeContainer<HSLFShape> parent) {
+ super(null, parent);
+ _escherContainer = createSpContainer(idx, parent instanceof HSLFGroupShape);
+ }
+
+ /**
+ * Create a <code>Picture</code> object
+ *
+ * @param escherRecord the <code>EscherSpContainer</code> record which holds information about
+ * this picture in the <code>Slide</code>
+ * @param parent the parent shape of this picture
+ */
+ protected HSLFPictureShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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 <code>EscherSp</code> record which holds information about this picture.
+
+ * @param idx the index of the picture which refers to <code>EscherBSE</code> 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<EscherRecord> 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();
+ }
+ }
+
+ /**
+ * 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
--- /dev/null
+/* ====================================================================
+ 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 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.*;
+import org.apache.poi.util.*;
+
+/**
+ * <p>
+ * Represents a Shape which is the elemental object that composes a drawing.
+ * This class is a wrapper around EscherSpContainer which holds all information
+ * about a shape in PowerPoint document.
+ * </p>
+ * <p>
+ * When you add a shape, you usually specify the dimensions of the shape and the position
+ * of the upper'left corner of the bounding box for the shape relative to the upper'left
+ * corner of the page, worksheet, or slide. Distances in the drawing layer are measured
+ * in points (72 points = 1 inch).
+ * </p>
+ * <p>
+ *
+ * @author Yegor Kozlov
+ */
+public abstract class HSLFShape implements Shape {
+
+ // For logging
+ protected POILogger logger = POILogFactory.getLogger(this.getClass());
+
+ /**
+ * In Escher absolute distances are specified in
+ * English Metric Units (EMUs), occasionally referred to as A units;
+ * there are 360000 EMUs per centimeter, 914400 EMUs per inch, 12700 EMUs per point.
+ */
+ public static final int EMU_PER_INCH = 914400;
+ public static final int EMU_PER_POINT = 12700;
+ public static final int EMU_PER_CENTIMETER = 360000;
+
+ /**
+ * Master DPI (576 pixels per inch).
+ * Used by the reference coordinate system in PowerPoint.
+ */
+ public static final int MASTER_DPI = 576;
+
+ /**
+ * Pixels DPI (96 pixels per inch)
+ */
+ public static final int PIXEL_DPI = 96;
+
+ /**
+ * Points DPI (72 pixels per inch)
+ */
+ public static final int POINT_DPI = 72;
+
+ /**
+ * Either EscherSpContainer or EscheSpgrContainer record
+ * which holds information about this shape.
+ */
+ protected EscherContainerRecord _escherContainer;
+
+ /**
+ * Parent of this shape.
+ * <code>null</code> for the topmost shapes.
+ */
+ protected ShapeContainer<HSLFShape> _parent;
+
+ /**
+ * The <code>Sheet</code> this shape belongs to
+ */
+ protected HSLFSheet _sheet;
+
+ /**
+ * Fill
+ */
+ protected HSLFFill _fill;
+
+ /**
+ * Create a Shape object. This constructor is used when an existing Shape is read from from a PowerPoint document.
+ *
+ * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of this Shape
+ */
+ protected HSLFShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ _escherContainer = escherRecord;
+ _parent = parent;
+ }
+
+ /**
+ * Creates the lowerlevel escher records for this shape.
+ */
+ protected abstract EscherContainerRecord createSpContainer(boolean isChild);
+
+ /**
+ * @return the parent of this shape
+ */
+ public ShapeContainer<HSLFShape> getParent(){
+ return _parent;
+ }
+
+ /**
+ * @return name of the shape.
+ */
+ public String getShapeName(){
+ return getShapeType().nativeName;
+ }
+
+ /**
+ * @return type of the shape.
+ * @see org.apache.poi.hslf.record.RecordTypes
+ */
+ public ShapeType getShapeType(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ return ShapeType.forId(spRecord.getShapeType(), false);
+ }
+
+ /**
+ * @param type type of the shape.
+ * @see org.apache.poi.hslf.record.RecordTypes
+ */
+ public void setShapeType(ShapeType type){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ spRecord.setShapeType( (short) type.nativeId );
+ spRecord.setVersion( (short) 0x2 );
+ }
+
+ /**
+ * Returns the anchor (the bounding box rectangle) of this shape.
+ * All coordinates are expressed in points (72 dpi).
+ *
+ * @return the anchor of this shape
+ */
+ public java.awt.Rectangle getAnchor(){
+ Rectangle2D anchor2d = getAnchor2D();
+ return anchor2d.getBounds();
+ }
+
+ /**
+ * Returns the anchor (the bounding box rectangle) of this shape.
+ * All coordinates are expressed in points (72 dpi).
+ *
+ * @return the anchor of this shape
+ */
+ public Rectangle2D getAnchor2D(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ int flags = spRecord.getFlags();
+ Rectangle2D anchor=null;
+ if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
+ EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
+ anchor = new java.awt.Rectangle();
+ if(rec == null){
+ logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found");
+ EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+ anchor = new java.awt.Rectangle();
+ anchor = new Rectangle2D.Float(
+ (float)clrec.getCol1()*POINT_DPI/MASTER_DPI,
+ (float)clrec.getFlag()*POINT_DPI/MASTER_DPI,
+ (float)(clrec.getDx1()-clrec.getCol1())*POINT_DPI/MASTER_DPI,
+ (float)(clrec.getRow1()-clrec.getFlag())*POINT_DPI/MASTER_DPI
+ );
+ } else {
+ anchor = new Rectangle2D.Float(
+ (float)rec.getDx1()*POINT_DPI/MASTER_DPI,
+ (float)rec.getDy1()*POINT_DPI/MASTER_DPI,
+ (float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
+ (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
+ );
+ }
+ }
+ else {
+ EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+ anchor = new java.awt.Rectangle();
+ anchor = new Rectangle2D.Float(
+ (float)rec.getCol1()*POINT_DPI/MASTER_DPI,
+ (float)rec.getFlag()*POINT_DPI/MASTER_DPI,
+ (float)(rec.getDx1()-rec.getCol1())*POINT_DPI/MASTER_DPI,
+ (float)(rec.getRow1()-rec.getFlag())*POINT_DPI/MASTER_DPI
+ );
+ }
+ return anchor;
+ }
+
+ public Rectangle2D getLogicalAnchor2D(){
+ return getAnchor2D();
+ }
+
+ /**
+ * Sets the anchor (the bounding box rectangle) of this shape.
+ * All coordinates should be expressed in points (72 dpi).
+ *
+ * @param anchor new anchor
+ */
+ public void setAnchor(Rectangle2D anchor){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ int flags = spRecord.getFlags();
+ if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
+ EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(EscherChildAnchorRecord.RECORD_ID);
+ rec.setDx1((int)(anchor.getX()*MASTER_DPI/POINT_DPI));
+ rec.setDy1((int)(anchor.getY()*MASTER_DPI/POINT_DPI));
+ rec.setDx2((int)((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI));
+ rec.setDy2((int)((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI));
+ }
+ else {
+ EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(EscherClientAnchorRecord.RECORD_ID);
+ rec.setFlag((short)(anchor.getY()*MASTER_DPI/POINT_DPI));
+ rec.setCol1((short)(anchor.getX()*MASTER_DPI/POINT_DPI));
+ rec.setDx1((short)(((anchor.getWidth() + anchor.getX())*MASTER_DPI/POINT_DPI)));
+ rec.setRow1((short)(((anchor.getHeight() + anchor.getY())*MASTER_DPI/POINT_DPI)));
+ }
+
+ }
+
+ /**
+ * Moves the top left corner of the shape to the specified point.
+ *
+ * @param x the x coordinate of the top left corner of the shape
+ * @param y the y coordinate of the top left corner of the shape
+ */
+ public void moveTo(float x, float y){
+ Rectangle2D anchor = getAnchor2D();
+ anchor.setRect(x, y, anchor.getWidth(), anchor.getHeight());
+ setAnchor(anchor);
+ }
+
+ /**
+ * Helper method to return escher child by record ID
+ *
+ * @return escher record or <code>null</code> if not found.
+ */
+ public static <T extends EscherRecord> T getEscherChild(EscherContainerRecord owner, int recordId){
+ return owner.getChildById((short)recordId);
+ }
+
+ public <T extends EscherRecord> T getEscherChild(int recordId){
+ return _escherContainer.getChildById((short)recordId);
+ }
+
+ /**
+ * Returns escher property by id.
+ *
+ * @return escher property or <code>null</code> if not found.
+ */
+ public static <T extends EscherProperty> T getEscherProperty(EscherOptRecord opt, int propId){
+ return opt.lookup(propId);
+ }
+
+ /**
+ * Set an escher property for this shape.
+ *
+ * @param opt The opt record to set the properties to.
+ * @param propId The id of the property. One of the constants defined in EscherOptRecord.
+ * @param value value of the property. If value = -1 then the property is removed.
+ */
+ public static void setEscherProperty(EscherOptRecord opt, short propId, int value){
+ java.util.List<EscherProperty> props = opt.getEscherProperties();
+ for ( Iterator<EscherProperty> iterator = props.iterator(); iterator.hasNext(); ) {
+ if (iterator.next().getPropertyNumber() == propId){
+ iterator.remove();
+ break;
+ }
+ }
+ if (value != -1) {
+ opt.addEscherProperty(new EscherSimpleProperty(propId, value));
+ opt.sortProperties();
+ }
+ }
+
+ /**
+ * Set an simple escher property for this shape.
+ *
+ * @param propId The id of the property. One of the constants defined in EscherOptRecord.
+ * @param value value of the property. If value = -1 then the property is removed.
+ */
+ public void setEscherProperty(short propId, int value){
+ EscherOptRecord opt = getEscherOptRecord();
+ setEscherProperty(opt, propId, value);
+ }
+
+ /**
+ * Get the value of a simple escher property for this shape.
+ *
+ * @param propId The id of the property. One of the constants defined in EscherOptRecord.
+ */
+ public int getEscherProperty(short propId){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, propId);
+ return prop == null ? 0 : prop.getPropertyValue();
+ }
+
+ /**
+ * Get the value of a simple escher property for this shape.
+ *
+ * @param propId The id of the property. One of the constants defined in EscherOptRecord.
+ */
+ public int getEscherProperty(short propId, int defaultValue){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, propId);
+ return prop == null ? defaultValue : prop.getPropertyValue();
+ }
+
+ /**
+ * @return The shape container and it's children that can represent this
+ * shape.
+ */
+ public EscherContainerRecord getSpContainer(){
+ return _escherContainer;
+ }
+
+ /**
+ * Event which fires when a shape is inserted in the sheet.
+ * In some cases we need to propagate changes to upper level containers.
+ * <br>
+ * Default implementation does nothing.
+ *
+ * @param sh - owning shape
+ */
+ protected void afterInsert(HSLFSheet sh){
+ if(_fill != null) {
+ _fill.afterInsert(sh);
+ }
+ }
+
+ /**
+ * @return the <code>SlideShow</code> this shape belongs to
+ */
+ public HSLFSheet getSheet(){
+ return _sheet;
+ }
+
+ /**
+ * Assign the <code>SlideShow</code> this shape belongs to
+ *
+ * @param sheet owner of this shape
+ */
+ public void setSheet(HSLFSheet sheet){
+ _sheet = sheet;
+ }
+
+ Color getColor(short colorProperty, short opacityProperty, int defaultColor){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty p = getEscherProperty(opt, colorProperty);
+ if(p == null && defaultColor == -1) return null;
+
+ int val = (p == null) ? defaultColor : p.getPropertyValue();
+
+ EscherColorRef ecr = new EscherColorRef(val);
+
+ boolean fPaletteIndex = ecr.hasPaletteIndexFlag();
+ boolean fPaletteRGB = ecr.hasPaletteRGBFlag();
+ boolean fSystemRGB = ecr.hasSystemRGBFlag();
+ boolean fSchemeIndex = ecr.hasSchemeIndexFlag();
+ boolean fSysIndex = ecr.hasSysIndexFlag();
+
+ int rgb[] = ecr.getRGB();
+
+ HSLFSheet sheet = getSheet();
+ if (fSchemeIndex && sheet != null) {
+ //red is the index to the color scheme
+ ColorSchemeAtom ca = sheet.getColorScheme();
+ int schemeColor = ca.getColor(ecr.getSchemeIndex());
+
+ rgb[0] = (schemeColor >> 0) & 0xFF;
+ rgb[1] = (schemeColor >> 8) & 0xFF;
+ rgb[2] = (schemeColor >> 16) & 0xFF;
+ } else if (fPaletteIndex){
+ //TODO
+ } else if (fPaletteRGB){
+ //TODO
+ } else if (fSystemRGB){
+ //TODO
+ } else if (fSysIndex){
+ //TODO
+ }
+
+ double alpha = getAlpha(opacityProperty);
+ return new Color(rgb[0], rgb[1], rgb[2], (int)(alpha*255.0));
+ }
+
+ double getAlpha(short opacityProperty) {
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty op = getEscherProperty(opt, opacityProperty);
+ int defaultOpacity = 0x00010000;
+ int opacity = (op == null) ? defaultOpacity : op.getPropertyValue();
+ return Units.fixedPointToDouble(opacity);
+ }
+
+ Color toRGB(int val){
+ int a = (val >> 24) & 0xFF;
+ int b = (val >> 16) & 0xFF;
+ int g = (val >> 8) & 0xFF;
+ int r = (val >> 0) & 0xFF;
+
+ if(a == 0xFE){
+ // Color is an sRGB value specified by red, green, and blue fields.
+ } else if (a == 0xFF){
+ // Color is undefined.
+ } else {
+ // index in the color scheme
+ ColorSchemeAtom ca = getSheet().getColorScheme();
+ int schemeColor = ca.getColor(a);
+
+ r = (schemeColor >> 0) & 0xFF;
+ g = (schemeColor >> 8) & 0xFF;
+ b = (schemeColor >> 16) & 0xFF;
+ }
+ return new Color(r, g, b);
+ }
+
+ /**
+ * @return id for the shape.
+ */
+ public int getShapeId(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ return spRecord == null ? 0 : spRecord.getShapeId();
+ }
+
+ /**
+ * Sets shape ID
+ *
+ * @param id of the shape
+ */
+ public void setShapeId(int id){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ if(spRecord != null) spRecord.setShapeId(id);
+ }
+
+ /**
+ * Fill properties of this shape
+ *
+ * @return fill properties of this shape
+ */
+ public HSLFFill getFill(){
+ if(_fill == null) {
+ _fill = new HSLFFill(this);
+ }
+ return _fill;
+ }
+
+ public FillStyle getFillStyle() {
+ return getFill().getFillStyle();
+ }
+
+ /**
+ * Returns the hyperlink assigned to this shape
+ *
+ * @return the hyperlink assigned to this shape
+ * or <code>null</code> if not found.
+ */
+ public HSLFHyperlink getHyperlink(){
+ return HSLFHyperlink.find(this);
+ }
+
+ public void draw(Graphics2D graphics){
+ logger.log(POILogger.INFO, "Rendering " + getShapeName());
+ }
+
+ /**
+ * Return shape outline as a java.awt.Shape object
+ *
+ * @return the shape outline
+ */
+ public java.awt.Shape getOutline(){
+ return getLogicalAnchor2D();
+ }
+
+ public EscherOptRecord getEscherOptRecord() {
+ return getEscherChild(EscherOptRecord.RECORD_ID);
+ }
+
+ public boolean getFlipHorizontal(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPHORIZ) != 0;
+ }
+
+ public void setFlipHorizontal(boolean flip) {
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPHORIZ;
+ spRecord.setFlags(flag);
+ }
+
+ public boolean getFlipVertical(){
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ return (spRecord.getFlags()& EscherSpRecord.FLAG_FLIPVERT) != 0;
+ }
+
+ public void setFlipVertical(boolean flip) {
+ EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
+ int flag = spRecord.getFlags() | EscherSpRecord.FLAG_FLIPVERT;
+ spRecord.setFlags(flag);
+ }
+
+ public double getRotation(){
+ int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION);
+ double angle = Units.fixedPointToDouble(rot) % 360.0;
+ return angle;
+ }
+
+ public void setRotation(double theta){
+ int rot = Units.doubleToFixedPoint(theta % 360.0);
+ setEscherProperty(EscherProperties.TRANSFORM__ROTATION, rot);
+ }
+
+ public boolean isPlaceholder() {
+ return false;
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.util.Iterator;
+import java.util.List;
+
+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.EscherProperty;
+import org.apache.poi.ddf.EscherPropertyFactory;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hslf.model.*;
+import org.apache.poi.hslf.record.InteractiveInfo;
+import org.apache.poi.hslf.record.InteractiveInfoAtom;
+import org.apache.poi.hslf.record.OEShapeAtom;
+import org.apache.poi.hslf.record.Record;
+import org.apache.poi.hslf.record.RecordTypes;
+import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+
+/**
+ * Create a <code>Shape</code> object depending on its type
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFShapeFactory {
+ // For logging
+ protected static final POILogger logger = POILogFactory.getLogger(HSLFShapeFactory.class);
+
+ /**
+ * Create a new shape from the data provided.
+ */
+ public static HSLFShape createShape(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
+ if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
+ return createShapeGroup(spContainer, parent);
+ }
+ return createSimpleShape(spContainer, parent);
+ }
+
+ public static HSLFGroupShape createShapeGroup(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
+ HSLFGroupShape group = null;
+ EscherRecord opt = HSLFShape.getEscherChild((EscherContainerRecord)spContainer.getChild(0), (short)0xF122);
+ if(opt != null){
+ try {
+ EscherPropertyFactory f = new EscherPropertyFactory();
+ List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() );
+ EscherSimpleProperty p = (EscherSimpleProperty)props.get(0);
+ if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){
+ group = new Table(spContainer, parent);
+ } else {
+ group = new HSLFGroupShape(spContainer, parent);
+ }
+ } catch (Exception e){
+ logger.log(POILogger.WARN, e.getMessage());
+ group = new HSLFGroupShape(spContainer, parent);
+ }
+ } else {
+ group = new HSLFGroupShape(spContainer, parent);
+ }
+
+ return group;
+ }
+
+ public static HSLFShape createSimpleShape(EscherContainerRecord spContainer, ShapeContainer<HSLFShape> parent){
+ HSLFShape shape = null;
+ EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);
+
+ ShapeType type = ShapeType.forId(spRecord.getShapeType(), false);
+ switch (type){
+ case TEXT_BOX:
+ shape = new HSLFTextBox(spContainer, parent);
+ break;
+ case HOST_CONTROL:
+ case FRAME: {
+ InteractiveInfo info = getClientDataRecord(spContainer, RecordTypes.InteractiveInfo.typeID);
+ OEShapeAtom oes = getClientDataRecord(spContainer, RecordTypes.OEShapeAtom.typeID);
+ if(info != null && info.getInteractiveInfoAtom() != null){
+ switch(info.getInteractiveInfoAtom().getAction()){
+ case InteractiveInfoAtom.ACTION_OLE:
+ shape = new OLEShape(spContainer, parent);
+ break;
+ case InteractiveInfoAtom.ACTION_MEDIA:
+ shape = new MovieShape(spContainer, parent);
+ break;
+ default:
+ break;
+ }
+ } else if (oes != null){
+ shape = new OLEShape(spContainer, parent);
+ }
+
+ if(shape == null) shape = new HSLFPictureShape(spContainer, parent);
+ break;
+ }
+ case LINE:
+ shape = new Line(spContainer, parent);
+ break;
+ case NOT_PRIMITIVE: {
+ EscherOptRecord opt = HSLFShape.getEscherChild(spContainer, EscherOptRecord.RECORD_ID);
+ EscherProperty prop = HSLFShape.getEscherProperty(opt, EscherProperties.GEOMETRY__VERTICES);
+ if(prop != null)
+ shape = new HSLFFreeformShape(spContainer, parent);
+ else {
+
+ logger.log(POILogger.WARN, "Creating AutoShape for a NotPrimitive shape");
+ shape = new HSLFAutoShape(spContainer, parent);
+ }
+ break;
+ }
+ default:
+ shape = new HSLFAutoShape(spContainer, parent);
+ break;
+ }
+ return shape;
+
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static <T extends Record> T getClientDataRecord(EscherContainerRecord spContainer, int recordType) {
+ Record oep = null;
+ for (Iterator<EscherRecord> it = spContainer.getChildIterator(); it.hasNext();) {
+ EscherRecord obj = it.next();
+ if (obj.getRecordId() == EscherClientDataRecord.RECORD_ID) {
+ byte[] data = obj.serialize();
+ Record[] records = Record.findChildRecords(data, 8, data.length - 8);
+ for (int j = 0; j < records.length; j++) {
+ if (records[j].getRecordType() == recordType) {
+ return (T)records[j];
+ }
+ }
+ }
+ }
+ return (T)oep;
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.util.*;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.sl.usermodel.Sheet;
+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 HSLFSheet implements Sheet<HSLFShape,HSLFSlideShow> {
+ private static POILogger logger = POILogFactory.getLogger(HSLFSheet.class);
+
+ /**
+ * The <code>SlideShow</code> 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 List<List<HSLFTextParagraph>> getTextParagraphs();
+
+ /**
+ * 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
+ */
+ public 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;
+ List<List<HSLFTextParagraph>> trs = getTextParagraphs();
+ if (trs == null) return;
+ for (List<HSLFTextParagraph> ltp : trs) {
+ for (HSLFTextParagraph tp : ltp) {
+ tp.supplySheet(this);
+ }
+ }
+ }
+
+
+ /**
+ * Returns all shapes contained in this Sheet
+ *
+ * @return all shapes contained in this Sheet (Slide or Notes)
+ */
+ @Override
+ public List<HSLFShape> getShapes() {
+ return getShapeList();
+ }
+
+ /**
+ * 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 <tt>true</tt> if the shape was deleted.
+ */
+ public boolean removeShape(HSLFShape shape) {
+ PPDrawing ppdrawing = getPPDrawing();
+
+ EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+ EscherContainerRecord spgr = null;
+
+ for (Iterator<EscherRecord> 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<EscherRecord> 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<EscherRecord> 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 <code>TextShape</code> or <code>null</code>
+ */
+ public HSLFTextShape getPlaceholderByTextType(int type){
+ for (HSLFShape shape : getShapes()) {
+ if(shape instanceof HSLFTextShape){
+ HSLFTextShape tx = (HSLFTextShape)shape;
+ if (tx != null && tx.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 <code>TextShape</code> or <code>null</code>
+ */
+ public HSLFTextShape getPlaceholder(int type){
+ for (HSLFShape shape : getShapes()) {
+ if(shape instanceof HSLFTextShape){
+ HSLFTextShape tx = (HSLFTextShape)shape;
+ 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. <code>___PPT12</code>.
+ *
+ * @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<HSLFShape> iterator() {
+ return getShapeList().iterator();
+ }
+
+
+ /**
+ * Returns all shapes contained in this Sheet
+ *
+ * @return all shapes contained in this Sheet (Slide or Notes)
+ */
+ protected List<HSLFShape> getShapeList() {
+ PPDrawing ppdrawing = getPPDrawing();
+
+ EscherContainerRecord dg = (EscherContainerRecord) ppdrawing.getEscherRecords()[0];
+ EscherContainerRecord spgr = null;
+
+ for (Iterator<EscherRecord> 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<HSLFShape> shapeList = new ArrayList<HSLFShape>();
+ Iterator<EscherRecord> it = spgr.getChildIterator();
+ if (it.hasNext()) {
+ // skip first item
+ it.next();
+ }
+ for (; it.hasNext();) {
+ EscherContainerRecord sp = (EscherContainerRecord) it.next();
+ HSLFShape sh = HSLFShapeFactory.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;
+ }
+
+
+}
--- /dev/null
+/* ====================================================================
+ 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 java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.sl.draw.geom.*;
+import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
+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 <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected HSLFSimpleShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+ super(escherRecord, parent);
+ }
+
+ /**
+ * Create a new Shape
+ *
+ * @param isChild <code>true</code> if the Line is inside a group, <code>false</code> 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 <code>java.awt.Color.black</code>
+ */
+ 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<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>();
+ for (ShapeContainer<HSLFShape> 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;
+ }
+
+ /**
+ * Find a record in the underlying EscherClientDataRecord
+ *
+ * @param recordType type of the record to search
+ */
+ @SuppressWarnings("unchecked")
+ protected <T extends Record> 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 <code>null</code>
+ */
+ 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(HSLFHyperlink 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 HSLFHyperlink.LINK_FIRSTSLIDE:
+ infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
+ infoAtom.setJump(InteractiveInfoAtom.JUMP_FIRSTSLIDE);
+ infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_FirstSlide);
+ break;
+ case HSLFHyperlink.LINK_LASTSLIDE:
+ infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
+ infoAtom.setJump(InteractiveInfoAtom.JUMP_LASTSLIDE);
+ infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_LastSlide);
+ break;
+ case HSLFHyperlink.LINK_NEXTSLIDE:
+ infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
+ infoAtom.setJump(InteractiveInfoAtom.JUMP_NEXTSLIDE);
+ infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_NextSlide);
+ break;
+ case HSLFHyperlink.LINK_PREVIOUSSLIDE:
+ infoAtom.setAction(InteractiveInfoAtom.ACTION_JUMP);
+ infoAtom.setJump(InteractiveInfoAtom.JUMP_PREVIOUSSLIDE);
+ infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_PreviousSlide);
+ break;
+ case HSLFHyperlink.LINK_URL:
+ infoAtom.setAction(InteractiveInfoAtom.ACTION_HYPERLINK);
+ infoAtom.setJump(InteractiveInfoAtom.JUMP_NONE);
+ infoAtom.setHyperlinkType(InteractiveInfoAtom.LINK_Url);
+ break;
+ case HSLFHyperlink.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());
+
+ }
+
+ public Guide getAdjustValue(String name) {
+ if (name == null || !name.matches("adj([1-9]|10)")) {
+ throw new IllegalArgumentException("Adjust value '"+name+"' not supported.");
+ }
+ short escherProp;
+ switch (Integer.parseInt(name.substring(3))) {
+ case 1: escherProp = EscherProperties.GEOMETRY__ADJUSTVALUE; break;
+ case 2: escherProp = EscherProperties.GEOMETRY__ADJUST2VALUE; break;
+ case 3: escherProp = EscherProperties.GEOMETRY__ADJUST3VALUE; break;
+ case 4: escherProp = EscherProperties.GEOMETRY__ADJUST4VALUE; break;
+ case 5: escherProp = EscherProperties.GEOMETRY__ADJUST5VALUE; break;
+ case 6: escherProp = EscherProperties.GEOMETRY__ADJUST6VALUE; break;
+ case 7: escherProp = EscherProperties.GEOMETRY__ADJUST7VALUE; break;
+ case 8: escherProp = EscherProperties.GEOMETRY__ADJUST8VALUE; break;
+ case 9: escherProp = EscherProperties.GEOMETRY__ADJUST9VALUE; break;
+ case 10: escherProp = EscherProperties.GEOMETRY__ADJUST10VALUE; break;
+ default: throw new RuntimeException();
+ }
+
+ int adjval = getEscherProperty(escherProp, -1);
+ return (adjval == -1) ? null : new Guide(name, "val "+adjval);
+ }
+
+ public LineDecoration getLineDecoration() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public CustomGeometry getGeometry() {
+ ShapeType st = getShapeType();
+ String name = st.getOoxmlName();
+
+ PresetGeometries dict = PresetGeometries.getInstance();
+ CustomGeometry geom = dict.get(name);
+ if(geom == null) {
+ throw new IllegalStateException("Unknown shape geometry: " + name);
+ }
+
+ return geom;
+ }
+
+ public Shadow getShadow() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+}
--- /dev/null
+/* ====================================================================
+ 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.model.*;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
+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<HSLFShape,HSLFSlideShow,HSLFNotes> {
+ private int _slideNo;
+ private SlideAtomsSet _atomSet;
+ private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>();
+ 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;
+
+ // For the text coming in from the SlideAtomsSet:
+ // Build up TextRuns from pairs of TextHeaderAtom and
+ // one of TextBytesAtom or TextCharsAtom
+ if (_atomSet != null && _atomSet.getSlideRecords().length > 0) {
+ List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_atomSet.getSlideRecords());
+ _paragraphs.addAll(llhtp);
+ if (_paragraphs.isEmpty()) {
+ throw new RuntimeException("No text records found for slide");
+ }
+ } else {
+ // No text on the slide, must just be pictures
+ }
+
+ // Grab text from SlideListWithTexts entries
+ for(List<HSLFTextParagraph> ltp : _paragraphs) {
+ for (HSLFTextParagraph tp : ltp) {
+ tp.supplySheet(this);
+ }
+ }
+
+ // Grab the TextRuns from the PPDrawing
+ List<List<HSLFTextParagraph>> llOtherRuns = HSLFTextParagraph.findTextParagraphs(getPPDrawing());
+ for (List<HSLFTextParagraph> otherRuns : llOtherRuns) {
+ // Grab text from slide's PPDrawing
+ for(HSLFTextParagraph tp : otherRuns) {
+ tp.supplySheet(this);
+ tp.setIndex(-1); // runs found in PPDrawing are not linked with SlideListWithTexts
+ }
+ }
+ _paragraphs.addAll(llOtherRuns);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Returns the Notes Sheet for this slide, or null if there isn't one
+ */
+ @Override
+ public HSLFNotes getNotes() {
+ return _notes;
+ }
+
+ /**
+ * Sets the Notes that are associated with this. Updates the
+ * references in the records to point to the new ID
+ */
+ @Override
+ 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.
+ * <p>
+ * For Slide we need to do the following:
+ * <li> set id of the drawing group.
+ * <li> set shapeId for the container descriptor and background
+ * </p>
+ */
+ 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 <code>TextBox</code> object that represents the slide's title.
+ *
+ * @return <code>TextBox</code> object that represents the slide's title.
+ */
+ public HSLFTextBox addTitle() {
+ Placeholder pl = new Placeholder();
+ pl.setShapeType(ShapeType.RECT);
+ pl.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 <code>null</code> if the slide does not have title.
+ * <p>
+ * The title is a run of text of type <code>TextHeaderAtom.CENTER_TITLE_TYPE</code> or
+ * <code>TextHeaderAtom.TITLE_TYPE</code>
+ * </p>
+ *
+ * @see TextHeaderAtom
+ *
+ * @return title of this slide
+ */
+ public String getTitle(){
+ for (List<HSLFTextParagraph> tp : getTextParagraphs()) {
+ if (tp.isEmpty()) continue;
+ int type = tp.get(0).getRunType();
+ switch (type) {
+ case TextHeaderAtom.CENTER_TITLE_TYPE:
+ case TextHeaderAtom.TITLE_TYPE:
+ String str = HSLFTextParagraph.getRawText(tp);
+ return HSLFTextParagraph.toExternalString(str, type);
+ }
+ }
+ return null;
+ }
+
+ // Simple Accesser methods follow
+
+ /**
+ * Returns an array of all the TextRuns found
+ */
+ public List<List<HSLFTextParagraph>> getTextParagraphs() { return _paragraphs; }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * @return set of records inside <code>SlideListWithtext</code> 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(){
+ int masterId = getSlideRecord().getSlideAtom().getMasterID();
+ for (HSLFSlideMaster sm : getSlideShow().getSlideMasters()) {
+ if (masterId == sm._getSheetNumber()) return sm;
+ }
+ for (HSLFTitleMaster tm : getSlideShow().getTitleMasters()) {
+ if (masterId == tm._getSheetNumber()) return tm;
+ }
+ return null;
+ }
+
+ /**
+ * 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 <code>true</code> if the slide follows master,
+ * <code>false</code> otherwise
+ */
+ public void setFollowMasterBackground(boolean flag){
+ SlideAtom sa = getSlideRecord().getSlideAtom();
+ sa.setFollowMasterBackground(flag);
+ }
+
+ /**
+ * Whether this slide follows master sheet background
+ *
+ * @return <code>true</code> if the slide follows master background,
+ * <code>false</code> otherwise
+ */
+ public boolean getFollowMasterBackground(){
+ SlideAtom sa = getSlideRecord().getSlideAtom();
+ return sa.getFollowMasterBackground();
+ }
+
+ /**
+ * Sets whether this slide draws master sheet objects
+ *
+ * @param flag <code>true</code> if the slide draws master sheet objects,
+ * <code>false</code> otherwise
+ */
+ public void setFollowMasterObjects(boolean flag){
+ SlideAtom sa = getSlideRecord().getSlideAtom();
+ sa.setFollowMasterObjects(flag);
+ }
+
+ /**
+ * Whether this slide follows master color scheme
+ *
+ * @return <code>true</code> if the slide follows master color scheme,
+ * <code>false</code> otherwise
+ */
+ public boolean getFollowMasterScheme(){
+ SlideAtom sa = getSlideRecord().getSlideAtom();
+ return sa.getFollowMasterScheme();
+ }
+
+ /**
+ * Sets whether this slide draws master color scheme
+ *
+ * @param flag <code>true</code> if the slide draws master color scheme,
+ * <code>false</code> otherwise
+ */
+ public void setFollowMasterScheme(boolean flag){
+ SlideAtom sa = getSlideRecord().getSlideAtom();
+ sa.setFollowMasterScheme(flag);
+ }
+
+ /**
+ * Whether this slide draws master sheet objects
+ *
+ * @return <code>true</code> if the slide draws master sheet objects,
+ * <code>false</code> 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<binaryTags.getChildRecords().length; i++) {
+ if(binaryTags.getChildRecords()[i] instanceof Comment2000) {
+ count++;
+ }
+ }
+
+ // Now build
+ Comment[] comments = new Comment[count];
+ count = 0;
+ for(int i=0; i<binaryTags.getChildRecords().length; i++) {
+ if(binaryTags.getChildRecords()[i] instanceof Comment2000) {
+ comments[i] = new Comment(
+ (Comment2000)binaryTags.getChildRecords()[i]
+ );
+ count++;
+ }
+ }
+
+ return comments;
+ }
+ }
+ }
+
+ // None found
+ return new Comment[0];
+ }
+
+ /**
+ * Header / Footer settings for this slide.
+ *
+ * @return Header / Footer settings for this slide
+ */
+ public HeadersFooters getHeadersFooters(){
+ HeadersFootersContainer hdd = null;
+ Record[] ch = getSheetContainer().getChildRecords();
+ boolean ppt2007 = false;
+ for (int i = 0; i < ch.length; i++) {
+ if(ch[i] instanceof HeadersFootersContainer){
+ hdd = (HeadersFootersContainer)ch[i];
+ } else if (ch[i].getRecordType() == RecordTypes.RoundTripContentMasterId.typeID){
+ ppt2007 = true;
+ }
+ }
+ boolean newRecord = false;
+ if(hdd == null && !ppt2007) {
+ return getSlideShow().getSlideHeadersFooters();
+ }
+ if(hdd == null) {
+ hdd = new HeadersFootersContainer(HeadersFootersContainer.SlideHeadersFootersContainer);
+ newRecord = true;
+ }
+ return new HeadersFooters(hdd, this, newRecord, ppt2007);
+ }
+
+ protected void onAddTextShape(HSLFTextShape shape) {
+ List<HSLFTextParagraph> newParas = shape.getTextParagraphs();
+ _paragraphs.add(newParas);
+ }
+
+ /** This will return an atom per TextBox, so if the page has two text boxes the method should return two atoms. */
+ public StyleTextProp9Atom[] getNumberedListInfo() {
+ return this.getPPDrawing().getNumberedListInfo();
+ }
+
+ public EscherTextboxWrapper[] getTextboxWrappers() {
+ return this.getPPDrawing().getTextboxWrappers();
+ }
+
+ public void setHidden(boolean hidden) {
+ org.apache.poi.hslf.record.Slide cont = getSlideRecord();
+
+ SSSlideInfoAtom slideInfo =
+ (SSSlideInfoAtom)cont.findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
+ if (slideInfo == null) {
+ slideInfo = new SSSlideInfoAtom();
+ cont.addChildAfter(slideInfo, cont.findFirstOfType(RecordTypes.SlideAtom.typeID));
+ }
+
+ slideInfo.setEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT, hidden);
+ }
+
+ public boolean getHidden() {
+ SSSlideInfoAtom slideInfo =
+ (SSSlideInfoAtom)getSlideRecord().findFirstOfType(RecordTypes.SSSlideInfoAtom.typeID);
+ return (slideInfo == null)
+ ? false
+ : slideInfo.getEffectTransitionFlagByBit(SSSlideInfoAtom.HIDDEN_BIT);
+ }
+
+ public boolean getFollowMasterColourScheme() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void setFollowMasterColourScheme(boolean follow) {
+ // TODO Auto-generated method stub
+
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.record.*;
+
+/**
+ * SlideMaster determines the graphics, layout, and formatting for all the slides in a given presentation.
+ * It stores information about default font styles, placeholder sizes and positions,
+ * background design, and color schemes.
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFSlideMaster extends HSLFMasterSheet {
+ private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>();
+
+ /**
+ * all TxMasterStyleAtoms available in this master
+ */
+ private TxMasterStyleAtom[] _txmaster;
+
+ /**
+ * Constructs a SlideMaster from the MainMaster record,
+ *
+ */
+ public HSLFSlideMaster(MainMaster record, int sheetNo) {
+ super(record, sheetNo);
+
+ _runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing()));
+ for (List<HSLFTextParagraph> p : _runs) {
+ for (HSLFTextParagraph htp : p) {
+ htp.supplySheet(this);
+ }
+ }
+ }
+
+ /**
+ * Returns an array of all the TextRuns found
+ */
+ public List<List<HSLFTextParagraph>> getTextParagraphs() {
+ return _runs;
+ }
+
+ /**
+ * Returns <code>null</code> since SlideMasters doen't have master sheet.
+ */
+ public HSLFMasterSheet getMasterSheet() {
+ return null;
+ }
+
+ /**
+ * Pickup a style attribute from the master.
+ * This is the "workhorse" which returns the default style attrubutes.
+ */
+ public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
+
+ TextProp prop = null;
+ for (int i = level; i >= 0; i--) {
+ TextPropCollection[] styles =
+ isCharacter ? _txmaster[txtype].getCharacterStyles() : _txmaster[txtype].getParagraphStyles();
+ if (i < styles.length) prop = styles[i].findByName(name);
+ if (prop != null) break;
+ }
+ if (prop == null) {
+ if(isCharacter) {
+ switch (txtype) {
+ case TextHeaderAtom.CENTRE_BODY_TYPE:
+ case TextHeaderAtom.HALF_BODY_TYPE:
+ case TextHeaderAtom.QUARTER_BODY_TYPE:
+ txtype = TextHeaderAtom.BODY_TYPE;
+ break;
+ case TextHeaderAtom.CENTER_TITLE_TYPE:
+ txtype = TextHeaderAtom.TITLE_TYPE;
+ break;
+ default:
+ return null;
+ }
+ } else {
+ switch (txtype) {
+ case TextHeaderAtom.CENTRE_BODY_TYPE:
+ case TextHeaderAtom.HALF_BODY_TYPE:
+ case TextHeaderAtom.QUARTER_BODY_TYPE:
+ txtype = TextHeaderAtom.BODY_TYPE;
+ break;
+ case TextHeaderAtom.CENTER_TITLE_TYPE:
+ txtype = TextHeaderAtom.TITLE_TYPE;
+ break;
+ default:
+ return null;
+ }
+ }
+ prop = getStyleAttribute(txtype, level, name, isCharacter);
+ }
+ return prop;
+ }
+
+ /**
+ * Assign SlideShow for this slide master.
+ * (Used interanlly)
+ */
+ public void setSlideShow(HSLFSlideShow ss) {
+ super.setSlideShow(ss);
+
+ //after the slide show is assigned collect all available style records
+ if (_txmaster == null) {
+ _txmaster = new TxMasterStyleAtom[9];
+
+ TxMasterStyleAtom txdoc = getSlideShow().getDocumentRecord().getEnvironment().getTxMasterStyleAtom();
+ _txmaster[txdoc.getTextType()] = txdoc;
+
+ TxMasterStyleAtom[] txrec = ((MainMaster)getSheetContainer()).getTxMasterStyleAtoms();
+ for (int i = 0; i < txrec.length; i++) {
+ int txType = txrec[i].getTextType();
+ if(_txmaster[txType] == null) _txmaster[txType] = txrec[i];
+ }
+ }
+ }
+
+ protected void onAddTextShape(HSLFTextShape shape) {
+ List<HSLFTextParagraph> runs = shape.getTextParagraphs();
+ _runs.add(runs);
+ }
+
+ public TxMasterStyleAtom[] getTxMasterStyleAtoms(){
+ return _txmaster;
+ }
+}
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 java.util.*;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherContainerRecord;
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.sl.usermodel.*;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
private Document _documentRecord;
// Friendly objects for people to deal with
- private SlideMaster[] _masters;
- private TitleMaster[] _titleMasters;
- private HSLFSlide[] _slides;
- private HSLFNotes[] _notes;
+ private final List<HSLFSlideMaster> _masters = new ArrayList<HSLFSlideMaster>();
+ private final List<HSLFTitleMaster> _titleMasters = new ArrayList<HSLFTitleMaster>();
+ private final List<HSLFSlide> _slides = new ArrayList<HSLFSlide>();
+ private final List<HSLFNotes> _notes = new ArrayList<HSLFNotes>();
private FontCollection _fonts;
// For logging
if (masterSLWT != null) {
masterSets = masterSLWT.getSlideAtomsSets();
- ArrayList<SlideMaster> mmr = new ArrayList<SlideMaster>();
- ArrayList<TitleMaster> tmr = new ArrayList<TitleMaster>();
-
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,
+ HSLFTitleMaster master = new HSLFTitleMaster((org.apache.poi.hslf.record.Slide) r,
sheetNo);
master.setSlideShow(this);
- tmr.add(master);
+ _titleMasters.add(master);
} else if (r instanceof org.apache.poi.hslf.record.MainMaster) {
- SlideMaster master = new SlideMaster((org.apache.poi.hslf.record.MainMaster) r,
+ HSLFSlideMaster master = new HSLFSlideMaster((org.apache.poi.hslf.record.MainMaster) r,
sheetNo);
master.setSlideShow(this);
- mmr.add(master);
+ _masters.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
// 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);
- }
+ for (org.apache.poi.hslf.record.Notes n : notesRecords) {
+ if (n == null) continue;
+ HSLFNotes hn = new HSLFNotes(n);
+ hn.setSlideShow(this);
+ _notes.add(hn);
}
// Then slides
- _slides = new HSLFSlide[slidesRecords.length];
- for (int i = 0; i < _slides.length; i++) {
+ for (int i = 0; i < slidesRecords.length; i++) {
SlideAtomsSet sas = slidesSets[i];
int slideIdentifier = sas.getSlidePersistAtom().getSlideIdentifier();
if (noteId != 0) {
Integer notesPos = slideIdToNotes.get(noteId);
if (notesPos != null) {
- notes = _notes[notesPos];
+ notes = _notes.get(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);
+ HSLFSlide hs = new HSLFSlide(slidesRecords[i], notes, sas, slideIdentifier, (i + 1));
+ hs.setSlideShow(this);
+ _slides.add(hs);
}
}
/**
* Returns an array of all the normal Slides found in the slideshow
*/
- public HSLFSlide[] getSlides() {
+ @Override
+ public List<HSLFSlide> getSlides() {
return _slides;
}
/**
* Returns an array of all the normal Notes found in the slideshow
*/
- public HSLFNotes[] getNotes() {
+ public List<HSLFNotes> getNotes() {
return _notes;
}
/**
* Returns an array of all the normal Slide Masters found in the slideshow
*/
- public SlideMaster[] getSlidesMasters() {
+ @Override
+ public List<HSLFSlideMaster> getSlideMasters() {
return _masters;
}
-
+
/**
* Returns an array of all the normal Title Masters found in the slideshow
*/
- public TitleMaster[] getTitleMasters() {
+ public List<HSLFTitleMaster> getTitleMasters() {
return _titleMasters;
}
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) {
+ if (oldSlideNumber > _slides.size() || newSlideNumber > _slides.size()) {
throw new IllegalArgumentException(
"Old and new slide numbers must not exceed the number of slides ("
- + _slides.length + ")");
+ + _slides.size() + ")");
}
+ _slides.get(newSlideNumber).setSlideNumber(oldSlideNumber);
+ _slides.get(oldSlideNumber).setSlideNumber(newSlideNumber);
+ Collections.swap(_slides, oldSlideNumber-1, newSlideNumber-1);
+
// The order of slides is defined by the order of slide atom sets in the
// SlideListWithText container.
SlideListWithText slwt = _documentRecord.getSlideSlideListWithText();
sas[newSlideNumber - 1] = tmp;
ArrayList<Record> lst = new ArrayList<Record>();
- 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);
+ for (SlideAtomsSet s : sas) {
+ lst.add(s.getSlidePersistAtom());
+ lst.addAll(Arrays.asList(s.getSlideRecords()));
}
Record[] r = lst.toArray(new Record[lst.size()]);
slwt.setChildRecord(r);
* @return the slide that was removed from the slide show.
*/
public HSLFSlide removeSlide(int index) {
- int lastSlideIdx = _slides.length - 1;
+ int lastSlideIdx = _slides.size() - 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<Record> records = new ArrayList<Record>();
- ArrayList<SlideAtomsSet> sa = new ArrayList<SlideAtomsSet>();
- ArrayList<HSLFSlide> sl = new ArrayList<HSLFSlide>();
-
- ArrayList<HSLFNotes> nt = new ArrayList<HSLFNotes>();
- 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());
- }
+ List<Record> records = new ArrayList<Record>();
+ List<SlideAtomsSet> sa = Arrays.asList(sas);
+
+ HSLFSlide removedSlide = _slides.remove(index);
+ _notes.remove(removedSlide.getNotes());
+ sa.remove(index);
+
+ int i=0;
+ for (HSLFSlide s : _slides) s.setSlideNumber(i++);
+
+ for (SlideAtomsSet s : sa) {
+ records.add(s.getSlidePersistAtom());
+ records.addAll(Arrays.asList(s.getSlideRecords()));
}
if (sa.size() == 0) {
_documentRecord.removeSlideListWithText(slwt);
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<Record>();
- ArrayList<SlideAtomsSet> na = new ArrayList<SlideAtomsSet>();
- 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()]));
+ int notesId = (removedSlide != null) ? removedSlide.getSlideRecord().getSlideAtom().getNotesID() : 0;
+ if (notesId != 0) {
+ SlideListWithText nslwt = _documentRecord.getNotesSlideListWithText();
+ records = new ArrayList<Record>();
+ ArrayList<SlideAtomsSet> na = new ArrayList<SlideAtomsSet>();
+ for (SlideAtomsSet ns : nslwt.getSlideAtomsSets()) {
+ if (ns.getSlidePersistAtom().getSlideIdentifier() == notesId) continue;
+ na.add(ns);
+ records.add(ns.getSlidePersistAtom());
+ if (ns.getSlideRecords() != null) {
+ records.addAll(Arrays.asList(ns.getSlideRecords()));
}
-
+ }
+ if (na.isEmpty()) {
+ _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;
}
slist.addSlidePersistAtom(sp);
// Create a new Slide
- HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.length + 1);
+ HSLFSlide slide = new HSLFSlide(sp.getSlideIdentifier(), sp.getRefID(), _slides.size() + 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()
+ _slides.add(slide);
+ logger.log(POILogger.INFO, "Added slide " + _slides.size() + " with ref " + sp.getRefID()
+ " and identifier " + sp.getSlideIdentifier());
// Add the core records for this new Slide to the record tree
sp.setRefID(psrId);
slideRecord.setSheetId(psrId);
- slide.setMasterSheet(_masters[0]);
+ slide.setMasterSheet(_masters.get(0));
// All done and added
return slide;
}
*/
public HeadersFooters getSlideHeadersFooters() {
// detect if this ppt was saved in Office2007
- String tag = getSlidesMasters()[0].getProgrammableTag();
+ String tag = getSlideMasters().get(0).getProgrammableTag();
boolean ppt2007 = "___PPT12".equals(tag);
HeadersFootersContainer hdd = null;
*/
public HeadersFooters getNotesHeadersFooters() {
// detect if this ppt was saved in Office2007
- String tag = getSlidesMasters()[0].getProgrammableTag();
+ String tag = getSlideMasters().get(0).getProgrammableTag();
boolean ppt2007 = "___PPT12".equals(tag);
HeadersFootersContainer hdd = null;
hdd = new HeadersFootersContainer(HeadersFootersContainer.NotesHeadersFootersContainer);
newRecord = true;
}
- if (ppt2007 && _notes.length > 0) {
- return new HeadersFooters(hdd, _notes[0], newRecord, ppt2007);
+ if (ppt2007 && !_notes.isEmpty()) {
+ return new HeadersFooters(hdd, _notes.get(0), newRecord, ppt2007);
}
return new HeadersFooters(hdd, this, newRecord, ppt2007);
}
*
* @return 0-based index of the hyperlink
*/
- public int addHyperlink(Hyperlink link) {
+ public int addHyperlink(HSLFHyperlink link) {
ExHyperlink ctrl = new ExHyperlink();
ExHyperlinkAtom obj = ctrl.getExHyperlinkAtom();
- if(link.getType() == Hyperlink.LINK_SLIDENUMBER) {
+ if(link.getType() == HSLFHyperlink.LINK_SLIDENUMBER) {
ctrl.setLinkURL(link.getAddress(), 0x30);
} else {
ctrl.setLinkURL(link.getAddress());
return psrId;
}
+
+ public MasterSheet<? extends Shape, ? extends SlideShow> createMasterSheet()
+ throws IOException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Resources getResources() {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
--- /dev/null
+/* ====================================================================
+ 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.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 HSLFSlideShowEncrypted {
+ DocumentEncryptionAtom dea;
+ CryptoAPIEncryptor enc = null;
+ CryptoAPIDecryptor dec = null;
+ Cipher cipher = null;
+ CipherOutputStream cyos = null;
+
+ private static final BitField fieldRecInst = new BitField(0xFFF0);
+
+ protected HSLFSlideShowEncrypted(DocumentEncryptionAtom dea) {
+ this.dea = dea;
+ }
+
+ protected HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer,Record> 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<Integer, Record> 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<rgbUidCnt; i++) {
+ cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+ offset += 16;
+ }
+
+ if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
+ cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
+ offset += 34;
+ } else {
+ cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
+ offset += 1;
+ }
+
+ int blipLen = endOffset - offset;
+ cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
+ } catch (GeneralSecurityException e) {
+ throw new CorruptPowerPointFileException(e);
+ }
+ }
+
+ protected void encryptPicture(byte[] pictstream, int offset) {
+ if (dea == null) return;
+
+ encryptInit();
+ setPersistId(0);
+
+ try {
+ int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
+ int recType = LittleEndian.getUShort(pictstream, offset+2);
+ int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
+ cipher.doFinal(pictstream, offset, 8, pictstream, offset);
+ 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;
+ int cbName = LittleEndian.getUShort(pictstream, offset+1);
+ 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
+ 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
+ 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<rgbUidCnt; i++) {
+ cipher.doFinal(pictstream, offset, 16, pictstream, offset); // rgbUid 1/2
+ offset += 16;
+ }
+
+ if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
+ cipher.doFinal(pictstream, offset, 34, pictstream, offset); // metafileHeader
+ offset += 34;
+ } else {
+ cipher.doFinal(pictstream, offset, 1, pictstream, offset); // tag
+ offset += 1;
+ }
+
+ int blipLen = endOffset - offset;
+ cipher.doFinal(pictstream, offset, blipLen, pictstream, offset);
+ } catch (GeneralSecurityException e) {
+ throw new CorruptPowerPointFileException(e);
+ }
+ }
+
+ protected Record[] updateEncryptionRecord(Record records[]) {
+ String password = Biff8EncryptionKey.getCurrentUserPassword();
+ if (password == null) {
+ if (dea == null) {
+ // no password given, no encryption record exits -> 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<Integer,Integer> slideLocations = new TreeMap<Integer,Integer>();
+ TreeMap<Integer,Record> recordMap = new TreeMap<Integer,Record>();
+ List<Integer> obsoleteOffsets = new ArrayList<Integer>();
+ 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<Integer,Integer> 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<Integer,Integer> 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<Record> recordList = new ArrayList<Record>();
+ 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<Integer,Integer> tm = new TreeMap<Integer,Integer>(ptr.getSlideLocationsLookup());
+ ptr.clear();
+ int maxSlideId = -1;
+ for (Map.Entry<Integer,Integer> 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;
+ }
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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.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.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<HSLFPictureData> _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("/org/apache/poi/hslf/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:
+ // <little endian 2 byte "info">
+ // <little endian 2 byte "type">
+ // <little endian 4 byte "length">
+ // If it has a zero length, following it will be another record
+ // <xx xx yy yy 00 00 00 00> <xx xx yy yy zz zz zz zz>
+ // If it has a length, depending on its type it may have children or data
+ // If it has children, these will follow straight away
+ // <xx xx yy yy zz zz zz zz <xx xx yy yy zz zz zz zz>>
+ // If it has data, this will come straigh after, and run for the length
+ // <xx xx yy yy zz zz zz zz dd dd dd dd dd dd dd>
+ // 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<Integer,Record> records = new TreeMap<Integer,Record>(); // offset -> record
+ Map<Integer,Integer> persistIds = new HashMap<Integer,Integer>(); // offset -> persistId
+ initRecordOffsets(docstream, usrOffset, records, persistIds);
+ HSLFSlideShowEncrypted decryptData = new HSLFSlideShowEncrypted(docstream, records);
+
+ for (Map.Entry<Integer,Record> 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<Integer,Record> recordMap, Map<Integer,Integer> 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<Integer,Integer> 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<HSLFPictureData>();
+
+ // 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<RecordTypes.Type,PositionDependentRecord> 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<Integer,Integer> oldToNewPositions = new Hashtable<Integer,Integer>();
+
+ // 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<Integer,Integer> persistIds = new HashMap<Integer,Integer>();
+ for (Map.Entry<Integer,Integer> 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<String> writtenEntries = new ArrayList<String>(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<String> 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 <code>null</code> 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<HSLFObjectData> objects = new ArrayList<HSLFObjectData>();
+ 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;
+ }
+ }
+}
--- /dev/null
+/* ====================================================================
+ 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.ddf.*;
+import org.apache.poi.sl.usermodel.*;
+
+/**
+ * Represents a TextFrame shape in PowerPoint.
+ * <p>
+ * Contains the text in a text frame as well as the properties and methods
+ * that control alignment and anchoring of the text.
+ * </p>
+ *
+ * @author Yegor Kozlov
+ */
+public class HSLFTextBox extends HSLFTextShape {
+
+ /**
+ * Create a TextBox object and initialize it from the supplied Record container.
+ *
+ * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected HSLFTextBox(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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 <code>EscherContainerRecord</code> 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);
+
+ // init paragraphs
+ getTextParagraphs();
+
+ return _escherContainer;
+ }
+
+ protected void setDefaultTextProperties(HSLFTextParagraph _txtrun){
+ setVerticalAlignment(VerticalAlignment.TOP);
+ setEscherProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20002);
+ }
+
+}
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+\r
+package org.apache.poi.hslf.usermodel;\r
+\r
+import java.awt.Color;\r
+import java.util.*;\r
+\r
+import org.apache.poi.hslf.model.textproperties.*;\r
+import org.apache.poi.hslf.record.*;\r
+import org.apache.poi.sl.usermodel.TextParagraph;\r
+import org.apache.poi.util.*;\r
+\r
+/**\r
+ * This class represents a run of text in a powerpoint document. That\r
+ * run could be text on a sheet, or text in a note.\r
+ * It is only a very basic class for now\r
+ *\r
+ * @author Nick Burch\r
+ */\r
+\r
+public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {\r
+ protected static POILogger logger = POILogFactory.getLogger(HSLFTextParagraph.class);\r
+ \r
+ /**\r
+ * How to align the text\r
+ */\r
+ /* package */ static final int AlignLeft = 0;\r
+ /* package */ static final int AlignCenter = 1;\r
+ /* package */ static final int AlignRight = 2;\r
+ /* package */ static final int AlignJustify = 3;\r
+ \r
+ \r
+ // Note: These fields are protected to help with unit testing\r
+ // Other classes shouldn't really go playing with them!\r
+ private final TextHeaderAtom _headerAtom;\r
+ private final TextBytesAtom _byteAtom;\r
+ private final TextCharsAtom _charAtom;\r
+ private StyleTextPropAtom _styleAtom;\r
+ private TextPropCollection _paragraphStyle = new TextPropCollection(1);\r
+ \r
+ protected TextRulerAtom _ruler;\r
+ protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();\r
+ protected HSLFTextShape _parentShape;\r
+ private HSLFSheet _sheet;\r
+ private int shapeId;\r
+\r
+ /**\r
+ * all text run records that follow TextHeaderAtom.\r
+ * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)\r
+ */\r
+ private Record[] _records;\r
+ // private StyleTextPropAtom styleTextPropAtom;\r
+ private StyleTextProp9Atom styleTextProp9Atom;\r
+\r
+ /**\r
+ * Constructs a Text Run from a Unicode text block.\r
+ * Either a {@link TextCharsAtom} or a {@link TextBytesAtom} needs to be provided. \r
+ *\r
+ * @param tha the TextHeaderAtom that defines what's what\r
+ * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided\r
+ * @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided\r
+ * @param sta the StyleTextPropAtom which defines the character stylings\r
+ */\r
+ /* package */ HSLFTextParagraph(\r
+ TextHeaderAtom tha,\r
+ TextBytesAtom tba,\r
+ TextCharsAtom tca,\r
+ StyleTextPropAtom sta\r
+ ) {\r
+ _headerAtom = tha;\r
+ _styleAtom = sta;\r
+ _byteAtom = tba;\r
+ _charAtom = tca;\r
+ }\r
+\r
+ /* package */ HSLFTextParagraph(HSLFTextParagraph other) {\r
+ _headerAtom = other._headerAtom;\r
+ _styleAtom = other._styleAtom;\r
+ _byteAtom = other._byteAtom;\r
+ _charAtom = other._charAtom;\r
+ _paragraphStyle = other._paragraphStyle;\r
+ _parentShape = other._parentShape;\r
+ _sheet = other._sheet;\r
+ _ruler = other._ruler; // ????\r
+ shapeId = other.shapeId;\r
+ _records = other._records;\r
+ }\r
+\r
+ public void addTextRun(HSLFTextRun run) {\r
+ _runs.add(run);\r
+ }\r
+ \r
+ /**\r
+ * Fetch the rich text runs (runs of text with the same styling) that\r
+ * are contained within this block of text\r
+ */\r
+ public List<HSLFTextRun> getTextRuns() {\r
+ return _runs;\r
+ }\r
+\r
+ public TextPropCollection getParagraphStyle() {\r
+ return _paragraphStyle;\r
+ }\r
+ \r
+ public void setParagraphStyle(TextPropCollection paragraphStyle) {\r
+ _paragraphStyle = paragraphStyle;\r
+ }\r
+ \r
+ /**\r
+ * Supply the Sheet we belong to, which might have an assigned SlideShow\r
+ * Also passes it on to our child RichTextRuns\r
+ */\r
+ public void supplySheet(HSLFSheet sheet){\r
+ this._sheet = sheet;\r
+\r
+ if (_runs == null) return;\r
+ for(HSLFTextRun rt : _runs) {\r
+ rt.updateSheet();\r
+ }\r
+ }\r
+\r
+ public HSLFSheet getSheet(){\r
+ return this._sheet;\r
+ }\r
+\r
+ /**\r
+ * @return Shape ID\r
+ */\r
+ protected int getShapeId(){\r
+ return shapeId;\r
+ }\r
+\r
+ /**\r
+ * @param id Shape ID\r
+ */\r
+ protected void setShapeId(int id){\r
+ shapeId = id;\r
+ }\r
+\r
+ /**\r
+ * @return 0-based index of the text run in the SLWT container\r
+ */\r
+ protected int getIndex(){\r
+ return (_headerAtom != null) ? _headerAtom.getIndex() : -1;\r
+ }\r
+\r
+ /**\r
+ * Sets the index of the paragraph in the SLWT container \r
+ *\r
+ * @param index\r
+ */\r
+ protected void setIndex(int index) {\r
+ if (_headerAtom != null) _headerAtom.setIndex(index);\r
+ }\r
+ \r
+ /**\r
+ * Returns the type of the text, from the TextHeaderAtom.\r
+ * Possible values can be seen from TextHeaderAtom\r
+ * @see org.apache.poi.hslf.record.TextHeaderAtom\r
+ */\r
+ public int getRunType() {\r
+ return (_headerAtom != null) ? _headerAtom.getTextType() : -1;\r
+ }\r
+ \r
+ /**\r
+ * Is this Text Run one from a {@link PPDrawing}, or is it\r
+ * one from the {@link SlideListWithText}?\r
+ */\r
+ public boolean isDrawingBased() {\r
+ return (getIndex() == -1);\r
+ }\r
+\r
+ public TextRulerAtom getTextRuler(){\r
+ return _ruler;\r
+\r
+ }\r
+\r
+ public TextRulerAtom createTextRuler(){\r
+ _ruler = getTextRuler();\r
+ if (_ruler == null) {\r
+ _ruler = TextRulerAtom.getParagraphInstance();\r
+ _headerAtom.getParentRecord().appendChildRecord(_ruler);\r
+ }\r
+ return _ruler;\r
+ }\r
+\r
+ /**\r
+ * Returns records that make up this text run\r
+ *\r
+ * @return text run records\r
+ */\r
+ public Record[] getRecords(){\r
+ return _records;\r
+ }\r
+ \r
+ /** Numbered List info */\r
+ public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
+ this.styleTextProp9Atom = styleTextProp9Atom;\r
+ }\r
+ \r
+ /** Numbered List info */\r
+ public StyleTextProp9Atom getStyleTextProp9Atom() {\r
+ return this.styleTextProp9Atom;\r
+ }\r
+\r
+ /** Characters covered */\r
+ public StyleTextPropAtom getStyleTextPropAtom() {\r
+ return this._styleAtom; \r
+ }\r
+\r
+ /**\r
+ * Fetch the value of the given Paragraph related TextProp.\r
+ * Returns -1 if that TextProp isn't present.\r
+ * If the TextProp isn't present, the value from the appropriate\r
+ * Master Sheet will apply.\r
+ */\r
+ private int getParaTextPropVal(String propName) {\r
+ TextProp prop = null;\r
+ boolean hardAttribute = false;\r
+ if (_paragraphStyle != null){\r
+ prop = _paragraphStyle.findByName(propName);\r
+\r
+ BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);\r
+ hardAttribute = maskProp != null && maskProp.getValue() == 0;\r
+ }\r
+ if (prop == null && !hardAttribute){\r
+ HSLFSheet sheet = _parentShape.getSheet();\r
+ int txtype = _parentShape.getRunType();\r
+ HSLFMasterSheet master = sheet.getMasterSheet();\r
+ if (master != null)\r
+ prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, false);\r
+ }\r
+\r
+ return prop == null ? -1 : prop.getValue();\r
+ }\r
+\r
+ /**\r
+ * Sets the value of the given Character TextProp, add if required\r
+ * @param propName The name of the Character TextProp\r
+ * @param val The value to set for the TextProp\r
+ */\r
+ public void setParaTextPropVal(String propName, int val) {\r
+ // Ensure we have the StyleTextProp atom we're going to need\r
+ if(_paragraphStyle == null) {\r
+ ensureStyleAtomPresent();\r
+ // paragraphStyle will now be defined\r
+ }\r
+\r
+ assert(_paragraphStyle!=null);\r
+ TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName);\r
+ tp.setValue(val);\r
+ }\r
+ \r
+ /**\r
+ * Ensure a StyleTextPropAtom is present for this run,\r
+ * by adding if required. Normally for internal TextRun use.\r
+ */\r
+ protected StyleTextPropAtom ensureStyleAtomPresent() {\r
+ if (_styleAtom != null) {\r
+ return _styleAtom;\r
+ }\r
+ \r
+ _styleAtom = ensureStyleAtomPresent(_headerAtom, _byteAtom, _charAtom);\r
+ _paragraphStyle = _styleAtom.getParagraphStyles().get(0);\r
+ \r
+ return _styleAtom;\r
+ }\r
+\r
+ protected static StyleTextPropAtom ensureStyleAtomPresent(TextHeaderAtom header, TextBytesAtom tbytes, TextCharsAtom tchars) {\r
+ RecordContainer wrapper = header.getParentRecord();\r
+ StyleTextPropAtom styleAtom = null;\r
+ \r
+ boolean afterHeader = false;\r
+ for (Record record : wrapper.getChildRecords()) {\r
+ if (afterHeader && record.getRecordType() == RecordTypes.TextHeaderAtom.typeID) break;\r
+ afterHeader |= (header == record);\r
+ if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) {\r
+ styleAtom = (StyleTextPropAtom)record;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (styleAtom != null) return styleAtom;\r
+ \r
+ String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
+ \r
+ // Create a new one at the right size\r
+ styleAtom = new StyleTextPropAtom(rawText.length()+1);\r
+\r
+ // Add the new StyleTextPropAtom after the TextCharsAtom / TextBytesAtom\r
+ wrapper.addChildAfter(styleAtom, (tbytes == null ? tchars : tbytes));\r
+\r
+ return styleAtom;\r
+ }\r
+\r
+ @Override\r
+ public Iterator<HSLFTextRun> iterator() {\r
+ return _runs.iterator();\r
+ }\r
+\r
+ @Override\r
+ public double getLeftMargin() {\r
+ int val = getParaTextPropVal("text.offset");\r
+ return val*HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);\r
+ }\r
+\r
+ @Override\r
+ public void setLeftMargin(double leftMargin) {\r
+ int val = (int)(leftMargin*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);\r
+ setParaTextPropVal("text.offset", val);\r
+ }\r
+ \r
+ @Override\r
+ public double getRightMargin() {\r
+ // TODO: find out, how to determine this value\r
+ return 0;\r
+ }\r
+\r
+ @Override\r
+ public void setRightMargin(double rightMargin) {\r
+ // TODO: find out, how to set this value\r
+ }\r
+ \r
+ @Override\r
+ public double getIndent() {\r
+ int val = getParaTextPropVal("bullet.offset");\r
+ return val*HSLFShape.POINT_DPI/((double)HSLFShape.MASTER_DPI);\r
+ }\r
+\r
+ @Override\r
+ public void setIndent(double intent) {\r
+ int val = (int)(intent*HSLFShape.MASTER_DPI/HSLFShape.POINT_DPI);\r
+ setParaTextPropVal("bullet.offset", val);\r
+ }\r
+\r
+ @Override\r
+ public String getDefaultFontFamily() {\r
+ return (_runs.isEmpty() ? "Arial" : _runs.get(0).getFontFamily());\r
+ }\r
+\r
+ @Override\r
+ public double getDefaultFontSize() {\r
+ return (_runs.isEmpty() ? 12 : _runs.get(0).getFontSize());\r
+ }\r
+\r
+ /**\r
+ * Sets the type of horizontal alignment for the paragraph.\r
+ *\r
+ * @param align - the type of alignment\r
+ */\r
+ public void setAlignment(org.apache.poi.sl.usermodel.TextParagraph.TextAlign align) {\r
+ int alignInt;\r
+ switch (align) {\r
+ default:\r
+ case LEFT: alignInt = AlignmentTextProp.LEFT; break;\r
+ case CENTER: alignInt = AlignmentTextProp.CENTER; break;\r
+ case RIGHT: alignInt = AlignmentTextProp.RIGHT; break;\r
+ case DIST: // TODO: DIST doesn't not exist within hslf, check mapping\r
+ case JUSTIFY: alignInt = AlignmentTextProp.JUSTIFY; break;\r
+ case JUSTIFY_LOW: alignInt = AlignmentTextProp.JUSTIFYLOW; break;\r
+ case THAI_DIST: alignInt = AlignmentTextProp.THAIDISTRIBUTED; break;\r
+ }\r
+ setParaTextPropVal("alignment", alignInt);\r
+ }\r
+ \r
+ @Override\r
+ public org.apache.poi.sl.usermodel.TextParagraph.TextAlign getTextAlign() {\r
+ switch (getParaTextPropVal("alignment")) {\r
+ default:\r
+ case AlignmentTextProp.LEFT: return TextAlign.LEFT;\r
+ case AlignmentTextProp.CENTER: return TextAlign.CENTER;\r
+ case AlignmentTextProp.RIGHT: return TextAlign.RIGHT;\r
+ case AlignmentTextProp.JUSTIFY: return TextAlign.JUSTIFY;\r
+ case AlignmentTextProp.JUSTIFYLOW: return TextAlign.JUSTIFY_LOW;\r
+ case AlignmentTextProp.THAIDISTRIBUTED: return TextAlign.THAI_DIST;\r
+ }\r
+ }\r
+\r
+ public org.apache.poi.sl.usermodel.TextParagraph.FontAlign getFontAlign() {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ public org.apache.poi.sl.usermodel.TextParagraph.BulletStyle getBulletStyle() {\r
+ // TODO Auto-generated method stub\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public HSLFTextShape getParentShape() {\r
+ return _parentShape;\r
+ }\r
+\r
+ public void setParentShape(HSLFTextShape parentShape) {\r
+ _parentShape = parentShape;\r
+ }\r
+\r
+ \r
+ /**\r
+ *\r
+ * @return indentation level\r
+ */\r
+ public int getIndentLevel() {\r
+ return _paragraphStyle == null ? 0 : _paragraphStyle.getReservedField();\r
+ }\r
+\r
+ /**\r
+ * Sets indentation level\r
+ *\r
+ * @param level indentation level. Must be in the range [0, 4]\r
+ */\r
+ public void setIndentLevel(int level) {\r
+ if( _paragraphStyle != null ) _paragraphStyle.setReservedField((short)level);\r
+ }\r
+\r
+ /**\r
+ * Sets whether this rich text run has bullets\r
+ */\r
+ public void setBullet(boolean flag) {\r
+ setFlag(ParagraphFlagsTextProp.BULLET_IDX, flag);\r
+ }\r
+\r
+ /**\r
+ * Returns whether this rich text run has bullets\r
+ */\r
+ public boolean isBullet() {\r
+ return getFlag(ParagraphFlagsTextProp.BULLET_IDX);\r
+ }\r
+\r
+ /**\r
+ * Returns whether this rich text run has bullets\r
+ */\r
+ public boolean isBulletHard() {\r
+ return getFlag(ParagraphFlagsTextProp.BULLET_IDX);\r
+ }\r
+\r
+ /**\r
+ * Sets the bullet character\r
+ */\r
+ public void setBulletChar(char c) {\r
+ setParaTextPropVal("bullet.char", c);\r
+ }\r
+\r
+ /**\r
+ * Returns the bullet character\r
+ */\r
+ public char getBulletChar() {\r
+ return (char)getParaTextPropVal("bullet.char");\r
+ }\r
+\r
+ /**\r
+ * Sets the bullet size\r
+ */\r
+ public void setBulletSize(int size) {\r
+ setParaTextPropVal("bullet.size", size);\r
+ }\r
+\r
+ /**\r
+ * Returns the bullet size\r
+ */\r
+ public int getBulletSize() {\r
+ return getParaTextPropVal("bullet.size");\r
+ }\r
+\r
+ /**\r
+ * Sets the bullet color\r
+ */\r
+ public void setBulletColor(Color color) {\r
+ int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();\r
+ setParaTextPropVal("bullet.color", rgb);\r
+ }\r
+\r
+ /**\r
+ * Returns the bullet color\r
+ */\r
+ public Color getBulletColor() {\r
+ int rgb = getParaTextPropVal("bullet.color");\r
+ if (rgb == -1) {\r
+ // if bullet color is undefined, return color of first run\r
+ if (_runs.isEmpty()) return null;\r
+ return _runs.get(0).getFontColor();\r
+ }\r
+\r
+ int cidx = rgb >> 24;\r
+ if (rgb % 0x1000000 == 0){\r
+ if (_sheet == null) return null;\r
+ ColorSchemeAtom ca = _sheet.getColorScheme();\r
+ if(cidx >= 0 && cidx <= 7) rgb = ca.getColor(cidx);\r
+ }\r
+ Color tmp = new Color(rgb, true);\r
+ return new Color(tmp.getBlue(), tmp.getGreen(), tmp.getRed());\r
+ }\r
+\r
+ /**\r
+ * Sets the bullet font\r
+ */\r
+ public void setBulletFont(int idx) {\r
+ setParaTextPropVal("bullet.font", idx);\r
+ setFlag(ParagraphFlagsTextProp.BULLET_HARDFONT_IDX, true);\r
+ }\r
+\r
+ /**\r
+ * Returns the bullet font\r
+ */\r
+ public int getBulletFont() {\r
+ return getParaTextPropVal("bullet.font");\r
+ }\r
+\r
+ /**\r
+ * Sets the line spacing.\r
+ * <p>\r
+ * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
+ * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.\r
+ * </p>\r
+ */\r
+ public void setLineSpacing(int val) {\r
+ setParaTextPropVal("linespacing", val);\r
+ }\r
+\r
+ /**\r
+ * Returns the line spacing\r
+ * <p>\r
+ * If linespacing >= 0, then linespacing is a percentage of normal line height.\r
+ * If linespacing < 0, the absolute value of linespacing is the spacing in master coordinates.\r
+ * </p>\r
+ *\r
+ * @return the spacing between lines\r
+ */\r
+ @Override\r
+ public double getLineSpacing() {\r
+ int val = getParaTextPropVal("linespacing");\r
+ return val == -1 ? 0 : val;\r
+ }\r
+\r
+ /**\r
+ * Sets spacing before a paragraph.\r
+ * <p>\r
+ * If spacebefore >= 0, then spacebefore is a percentage of normal line height.\r
+ * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates.\r
+ * </p>\r
+ */\r
+ public void setSpaceBefore(int val) {\r
+ setParaTextPropVal("spacebefore", val);\r
+ }\r
+\r
+ /**\r
+ * Returns spacing before a paragraph\r
+ * <p>\r
+ * If spacebefore >= 0, then spacebefore is a percentage of normal line height.\r
+ * If spacebefore < 0, the absolute value of spacebefore is the spacing in master coordinates.\r
+ * </p>\r
+ *\r
+ * @return the spacing before a paragraph\r
+ */\r
+ @Override\r
+ public double getSpaceBefore() {\r
+ int val = getParaTextPropVal("spacebefore");\r
+ return val == -1 ? 0 : val;\r
+ }\r
+\r
+ /**\r
+ * Sets spacing after a paragraph.\r
+ * <p>\r
+ * If spaceafter >= 0, then spaceafter is a percentage of normal line height.\r
+ * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates.\r
+ * </p>\r
+ */\r
+ public void setSpaceAfter(int val) {\r
+ setParaTextPropVal("spaceafter", val);\r
+ }\r
+\r
+ /**\r
+ * Returns spacing after a paragraph\r
+ * <p>\r
+ * If spaceafter >= 0, then spaceafter is a percentage of normal line height.\r
+ * If spaceafter < 0, the absolute value of spaceafter is the spacing in master coordinates.\r
+ * </p>\r
+ *\r
+ * @return the spacing before a paragraph\r
+ */\r
+ @Override\r
+ public double getSpaceAfter() {\r
+ int val = getParaTextPropVal("spaceafter");\r
+ return val == -1 ? 0 : val;\r
+ }\r
+ \r
+ /**\r
+ * Returns the named TextProp, either by fetching it (if it exists) or adding it\r
+ * (if it didn't)\r
+ * @param textPropCol The TextPropCollection to fetch from / add into\r
+ * @param textPropName The name of the TextProp to fetch/add\r
+ */\r
+ protected static TextProp fetchOrAddTextProp(TextPropCollection textPropCol, String textPropName) {\r
+ // Fetch / Add the TextProp\r
+ TextProp tp = textPropCol.findByName(textPropName);\r
+ if (tp == null) {\r
+ tp = textPropCol.addWithName(textPropName);\r
+ }\r
+ return tp;\r
+ }\r
+\r
+ protected boolean getFlag(int index) {\r
+ if (_paragraphStyle == null) return false;\r
+\r
+ BitMaskTextProp prop = (BitMaskTextProp) _paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);\r
+\r
+ if (prop == null) {\r
+ if (_sheet != null) {\r
+ int txtype = getParentShape().getRunType();\r
+ HSLFMasterSheet master = _sheet.getMasterSheet();\r
+ if (master != null) {\r
+ prop = (BitMaskTextProp) master.getStyleAttribute(txtype, getIndentLevel(), ParagraphFlagsTextProp.NAME, false);\r
+ }\r
+ } else {\r
+ logger.log(POILogger.WARN, "MasterSheet is not available");\r
+ }\r
+ }\r
+\r
+ return prop == null ? false : prop.getSubValue(index);\r
+ }\r
+\r
+ protected void setFlag(int index, boolean value) {\r
+ // Ensure we have the StyleTextProp atom we're going to need\r
+ if(_paragraphStyle == null) {\r
+ _paragraphStyle = new TextPropCollection(1);\r
+ }\r
+\r
+ BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME);\r
+ prop.setSubValue(value,index);\r
+ }\r
+\r
+ /**\r
+ * Saves the modified paragraphs/textrun to the records.\r
+ * Also updates the styles to the correct text length.\r
+ */\r
+ protected static void storeText(List<HSLFTextParagraph> paragraphs) {\r
+ String rawText = toInternalString(getRawText(paragraphs));\r
+\r
+ // Will it fit in a 8 bit atom?\r
+ boolean isUnicode = StringUtil.hasMultibyte(rawText);\r
+ \r
+ TextHeaderAtom headerAtom = paragraphs.get(0)._headerAtom;\r
+ TextBytesAtom byteAtom = paragraphs.get(0)._byteAtom;\r
+ TextCharsAtom charAtom = paragraphs.get(0)._charAtom;\r
+\r
+ // Store in the appropriate record\r
+ Record oldRecord = null, newRecord = null;\r
+ if (isUnicode) { \r
+ if (byteAtom != null) {\r
+ oldRecord = byteAtom;\r
+ newRecord = charAtom = new TextCharsAtom();\r
+ }\r
+ charAtom.setText(rawText);\r
+ } else {\r
+ if (charAtom != null) {\r
+ oldRecord = charAtom;\r
+ newRecord = byteAtom = new TextBytesAtom();\r
+ }\r
+ byte[] byteText = new byte[rawText.length()];\r
+ StringUtil.putCompressedUnicode(rawText,byteText,0);\r
+ byteAtom.setText(byteText);\r
+ }\r
+\r
+ RecordContainer _txtbox = headerAtom.getParentRecord();\r
+ \r
+ if (oldRecord != null) {\r
+ // swap not appropriated records\r
+ Record[] cr = _txtbox.getChildRecords();\r
+ int idx=0;\r
+ for (Record r : cr) {\r
+ if(r.equals(oldRecord)) break;\r
+ idx++;\r
+ }\r
+ if (idx >= cr.length) {\r
+ throw new RuntimeException("child record not found - malformed container record");\r
+ }\r
+ cr[idx] = newRecord;\r
+ }\r
+\r
+ // Ensure a StyleTextPropAtom is present, adding if required\r
+ StyleTextPropAtom styleAtom = ensureStyleAtomPresent(headerAtom, byteAtom, charAtom);\r
+\r
+ // Update the text length for its Paragraph and Character stylings\r
+ // If it's shared:\r
+ // * calculate the new length based on the run's old text\r
+ // * this should leave in any +1's for the end of block if needed\r
+ // If it isn't shared:\r
+ // * reset the length, to the new string's length\r
+ // * add on +1 if the last block\r
+ // The last run needs its stylings to be 1 longer than the raw\r
+ // text is. This is to define the stylings that any new text\r
+ // that is added will inherit\r
+ \r
+ styleAtom.clearStyles();\r
+ \r
+ TextPropCollection lastPTPC = null, lastRTPC = null;\r
+ for (HSLFTextParagraph para : paragraphs) {\r
+ TextPropCollection ptpc = para.getParagraphStyle();\r
+ ptpc.updateTextSize(0);\r
+ if (!ptpc.equals(lastPTPC)) {\r
+ lastPTPC = styleAtom.addParagraphTextPropCollection(0);\r
+ lastPTPC.copy(ptpc);\r
+ }\r
+ for (HSLFTextRun tr : para.getTextRuns()) {\r
+ TextPropCollection rtpc = tr.getCharacterStyle();\r
+ if (!rtpc.equals(lastRTPC)) {\r
+ lastRTPC = styleAtom.addCharacterTextPropCollection(0);\r
+ lastRTPC.copy(rtpc);\r
+ }\r
+ int len = tr.getLength();\r
+ ptpc.updateTextSize(ptpc.getCharactersCovered()+len);\r
+ rtpc.updateTextSize(len);\r
+ lastPTPC.updateTextSize(lastPTPC.getCharactersCovered()+len);\r
+ lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+len);\r
+ }\r
+ }\r
+ \r
+ assert(lastPTPC != null && lastRTPC != null);\r
+ lastPTPC.updateTextSize(lastPTPC.getCharactersCovered()+1);\r
+ lastRTPC.updateTextSize(lastRTPC.getCharactersCovered()+1);\r
+ \r
+ /**\r
+ * If TextSpecInfoAtom is present, we must update the text size in it,\r
+ * otherwise the ppt will be corrupted\r
+ */\r
+ TextSpecInfoAtom specAtom = (TextSpecInfoAtom)_txtbox.findFirstOfType(RecordTypes.TextSpecInfoAtom.typeID);\r
+ int len = rawText.length() + 1;\r
+ if(specAtom != null && len != specAtom.getCharactersCovered()) {\r
+ specAtom.reset(len);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Adds the supplied text onto the end of the TextParagraphs,\r
+ * creating a new RichTextRun for it to sit in.\r
+ * \r
+ * @param text the text string used by this object.\r
+ */\r
+ protected static void appendText(List<HSLFTextParagraph> paragraphs, String text, boolean newParagraph) {\r
+ text = toInternalString(text);\r
+ \r
+ // init paragraphs\r
+ assert(!paragraphs.isEmpty());\r
+ \r
+ HSLFTextParagraph lastHTP = paragraphs.get(paragraphs.size()-1);\r
+ HSLFTextRun lastHTR = lastHTP.getTextRuns().get(lastHTP.getTextRuns().size()-1);\r
+ HSLFTextParagraph htp = (newParagraph) ? new HSLFTextParagraph(lastHTP) : lastHTP;\r
+ HSLFTextRun htr = new HSLFTextRun(htp);\r
+ htr.setText(text);\r
+ htr.getCharacterStyle().copy(lastHTR.getCharacterStyle());\r
+ htp.addTextRun(htr);\r
+ }\r
+ \r
+ /**\r
+ * Sets (overwrites) the current text.\r
+ * Uses the properties of the first paragraph / textrun\r
+ * \r
+ * @param text the text string used by this object.\r
+ */\r
+ public static void setText(List<HSLFTextParagraph> paragraphs, String text) {\r
+ text = HSLFTextParagraph.toInternalString(text);\r
+ \r
+ // init paragraphs\r
+ assert(!paragraphs.isEmpty());\r
+\r
+ Iterator<HSLFTextParagraph> paraIter = paragraphs.iterator();\r
+ HSLFTextParagraph firstHTP = paraIter.next(); // keep first\r
+ assert(firstHTP != null);\r
+ while (paraIter.hasNext()) {\r
+ paraIter.next();\r
+ paraIter.remove();\r
+ }\r
+ \r
+ Iterator<HSLFTextRun> runIter = firstHTP.getTextRuns().iterator();\r
+ HSLFTextRun firstHTR = runIter.next();\r
+ assert(firstHTR != null);\r
+ while (runIter.hasNext()) {\r
+ runIter.next();\r
+ runIter.remove();\r
+ }\r
+ \r
+ firstHTR.setText(text);\r
+ }\r
+ \r
+ public static String getRawText(List<HSLFTextParagraph> paragraphs) {\r
+ StringBuilder sb = new StringBuilder();\r
+ for (HSLFTextParagraph p : paragraphs) {\r
+ for (HSLFTextRun r : p.getTextRuns()) {\r
+ sb.append(r.getRawText());\r
+ }\r
+ sb.append("\r");\r
+ }\r
+ sb.deleteCharAt(sb.length()-1); // remove last line break\r
+ return sb.toString(); \r
+ }\r
+ \r
+ /**\r
+ * Returns a new string with line breaks converted into internal ppt\r
+ * representation\r
+ */\r
+ protected static String toInternalString(String s) {\r
+ String ns = s.replaceAll("\\r?\\n", "\r");\r
+ return ns;\r
+ }\r
+\r
+ /**\r
+ * Converts raw text from the text paragraphs to a formatted string,\r
+ * i.e. it converts certain control characters used in the raw txt\r
+ *\r
+ * @param rawText the raw text\r
+ * @param runType the run type of the shape, paragraph or headerAtom.\r
+ * use -1 if unknown\r
+ * @return the formatted string\r
+ */\r
+ public static String toExternalString(String rawText, int runType) {\r
+ // PowerPoint seems to store files with \r as the line break\r
+ // The messes things up on everything but a Mac, so translate\r
+ // them to \n\r
+ String text = rawText.replace('\r', '\n');\r
+\r
+ switch (runType) {\r
+ // 0xB acts like cariage return in page titles and like blank in the\r
+ // others\r
+ case -1:\r
+ case org.apache.poi.hslf.record.TextHeaderAtom.TITLE_TYPE:\r
+ case org.apache.poi.hslf.record.TextHeaderAtom.CENTER_TITLE_TYPE:\r
+ text = text.replace((char) 0x0B, '\n');\r
+ break;\r
+ default:\r
+ text = text.replace((char) 0x0B, ' ');\r
+ break;\r
+ }\r
+\r
+ return text;\r
+ }\r
+\r
+ /**\r
+ * For a given PPDrawing, grab all the TextRuns\r
+ */\r
+ public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing) {\r
+ List<List<HSLFTextParagraph>> runsV = new ArrayList<List<HSLFTextParagraph>>();\r
+ for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) {\r
+ // propagate parents to parent-aware records\r
+ RecordContainer.handleParentAwareRecords(wrapper);\r
+ int shapeId = wrapper.getShapeId();\r
+ List<List<HSLFTextParagraph>> rv = findTextParagraphs(wrapper);\r
+ for (List<HSLFTextParagraph> htpList : rv) {\r
+ for (HSLFTextParagraph htp : htpList) {\r
+ htp.setShapeId(shapeId);\r
+ }\r
+ }\r
+ runsV.addAll(rv);\r
+ }\r
+ return runsV;\r
+ }\r
+ /**\r
+ * Scans through the supplied record array, looking for\r
+ * a TextHeaderAtom followed by one of a TextBytesAtom or\r
+ * a TextCharsAtom. Builds up TextRuns from these\r
+ *\r
+ * @param records the records to build from\r
+ * @param found vector to add any found to\r
+ */\r
+ protected static List<List<HSLFTextParagraph>> findTextParagraphs(final Record[] records) {\r
+ return findTextParagraphs(records, null); \r
+ }\r
+ /**\r
+ * Scans through the supplied record array, looking for\r
+ * a TextHeaderAtom followed by one of a TextBytesAtom or\r
+ * a TextCharsAtom. Builds up TextRuns from these\r
+ *\r
+ * @param wrapper an EscherTextboxWrapper\r
+ */\r
+ protected static List<List<HSLFTextParagraph>> findTextParagraphs(final EscherTextboxWrapper wrapper) {\r
+ return findTextParagraphs(wrapper.getChildRecords(), wrapper.getStyleTextProp9Atom());\r
+ }\r
+\r
+ /**\r
+ * Scans through the supplied record array, looking for\r
+ * a TextHeaderAtom followed by one of a TextBytesAtom or\r
+ * a TextCharsAtom. Builds up TextRuns from these\r
+ *\r
+ * @param records the records to build from\r
+ * @param styleTextProp9Atom an optional StyleTextProp9Atom with numbered lists info\r
+ */\r
+ protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records, StyleTextProp9Atom styleTextProp9Atom) {\r
+ List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>();\r
+ \r
+ if (records == null) {\r
+ throw new NullPointerException("records need to be filled.");\r
+ }\r
+ \r
+ int recordIdx;\r
+ for (recordIdx = 0; recordIdx < records.length; recordIdx++) {\r
+ if (records[recordIdx] instanceof TextHeaderAtom) break;\r
+ }\r
+ \r
+ if (recordIdx == records.length) {\r
+ logger.log(POILogger.INFO, "No text records found.");\r
+ return paragraphCollection;\r
+ }\r
+ \r
+ for (int slwtIndex = 0; recordIdx < records.length-2; slwtIndex++) {\r
+ List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();\r
+ paragraphCollection.add(paragraphs);\r
+ \r
+ TextHeaderAtom header = (TextHeaderAtom)records[recordIdx++];\r
+ TextBytesAtom tbytes = null;\r
+ TextCharsAtom tchars = null;\r
+ StyleTextPropAtom styles = null;\r
+ TextRulerAtom ruler = null;\r
+ MasterTextPropAtom indents = null;\r
+ \r
+ List<Record> otherRecordList = new ArrayList<Record>();\r
+ \r
+ for (; recordIdx < records.length; recordIdx++) {\r
+ Record r = records[recordIdx];\r
+ long rt = r.getRecordType();\r
+ if (RecordTypes.TextHeaderAtom.typeID == rt) break;\r
+ else if (RecordTypes.TextBytesAtom.typeID == rt) tbytes = (TextBytesAtom)r;\r
+ else if (RecordTypes.TextCharsAtom.typeID == rt) tchars = (TextCharsAtom)r;\r
+ else if (RecordTypes.StyleTextPropAtom.typeID == rt) styles = (StyleTextPropAtom)r;\r
+ else if (RecordTypes.TextRulerAtom.typeID == rt) ruler = (TextRulerAtom)r;\r
+ else if (RecordTypes.MasterTextPropAtom.typeID == rt) {\r
+ indents = (MasterTextPropAtom)r;\r
+ otherRecordList.add(indents);\r
+ } else {\r
+ otherRecordList.add(r);\r
+ }\r
+ }\r
+ \r
+ assert(header != null);\r
+ if (header.getIndex() == -1) {\r
+ header.setIndex(slwtIndex);\r
+ }\r
+ \r
+ Record otherRecords[] = otherRecordList.toArray(new Record[otherRecordList.size()]);\r
+ \r
+ if (tbytes == null && tchars == null) {\r
+ tbytes = new TextBytesAtom();\r
+ logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");\r
+ }\r
+ \r
+ String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
+ \r
+ for (String para : rawText.split("\r")) {\r
+ HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);\r
+ paragraphs.add(tpara);\r
+ tpara.setStyleTextProp9Atom(styleTextProp9Atom);\r
+ tpara._ruler = ruler;\r
+ tpara._records = otherRecords;\r
+ tpara.getParagraphStyle().updateTextSize(para.length());\r
+ \r
+ HSLFTextRun trun = new HSLFTextRun(tpara);\r
+ tpara.addTextRun(trun);\r
+ trun.setText(para);\r
+ }\r
+ \r
+ if (styles == null) {\r
+ styles = ensureStyleAtomPresent(header, tbytes, tchars);\r
+ } else {\r
+ styles.setParentTextSize(rawText.length());\r
+ }\r
+ \r
+ applyCharacterStyles(paragraphs, styles.getCharacterStyles());\r
+ applyParagraphStyles(paragraphs, styles.getParagraphStyles());\r
+ if (indents != null) {\r
+ applyParagraphIndents(paragraphs, indents.getIndents());\r
+ }\r
+ }\r
+ \r
+ return paragraphCollection;\r
+ }\r
+\r
+ protected static void applyCharacterStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> charStyles) {\r
+ int paraIdx = 0, runIdx = 0;\r
+ for (TextPropCollection p : charStyles) {\r
+ for (int ccRun = 0, ccStyle = p.getCharactersCovered(); ccRun < ccStyle; ) {\r
+ HSLFTextParagraph para = paragraphs.get(paraIdx);\r
+ List<HSLFTextRun> runs = para.getTextRuns();\r
+ HSLFTextRun trun = runs.get(runIdx);\r
+ int len = trun.getLength();\r
+ \r
+ if (runIdx+1 >= runs.size()) {\r
+ // need to add +1 to the last run of the paragraph\r
+ len++;\r
+ }\r
+ \r
+ TextPropCollection pCopy = new TextPropCollection(1);\r
+ pCopy.copy(p);\r
+ if (ccRun+len <= ccStyle) {\r
+ trun.setCharacterStyle(pCopy);\r
+ pCopy.updateTextSize(len);\r
+ ccRun += len;\r
+ } else {\r
+ String text = trun.getRawText();\r
+ trun.setText(text.substring(0,ccStyle-ccRun));\r
+ pCopy.updateTextSize(ccStyle-ccRun);\r
+ trun.setCharacterStyle(pCopy);\r
+ \r
+ HSLFTextRun nextRun = new HSLFTextRun(para);\r
+ nextRun.setText(text.substring(ccStyle-ccRun));\r
+ runs.add(runIdx+1, nextRun);\r
+ \r
+ ccRun += ccStyle-ccRun;\r
+ }\r
+\r
+ // need to compare it again, in case a run has been added afer\r
+ if (++runIdx >= runs.size()) {\r
+ paraIdx++;\r
+ runIdx = 0;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ protected static void applyParagraphStyles(List<HSLFTextParagraph> paragraphs, List<TextPropCollection> paraStyles) {\r
+ int paraIdx = 0;\r
+ for (TextPropCollection p : paraStyles) {\r
+ for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {\r
+ HSLFTextParagraph para = paragraphs.get(paraIdx);\r
+ TextPropCollection pCopy = new TextPropCollection(1);\r
+ pCopy.copy(p);\r
+ int len = 0;\r
+ for (HSLFTextRun trun : para.getTextRuns()) {\r
+ len += trun.getLength();\r
+ }\r
+ pCopy.updateTextSize(len+1);\r
+ para.setParagraphStyle(pCopy);\r
+ ccPara += len+1;\r
+ }\r
+ }\r
+ }\r
+ \r
+ protected static void applyParagraphIndents(List<HSLFTextParagraph> paragraphs, List<IndentProp> paraStyles) {\r
+ int paraIdx = 0;\r
+ for (IndentProp p : paraStyles) {\r
+ for (int ccPara = 0, ccStyle = p.getCharactersCovered(); ccPara < ccStyle; paraIdx++) {\r
+ HSLFTextParagraph para = paragraphs.get(paraIdx);\r
+ int len = 0;\r
+ for (HSLFTextRun trun : para.getTextRuns()) {\r
+ len += trun.getLength();\r
+ }\r
+ para.setIndentLevel(p.getIndentLevel());\r
+ ccPara += len+1;\r
+ }\r
+ }\r
+ }\r
+ \r
+ protected static List<HSLFTextParagraph> createEmptyParagraph() {\r
+ EscherTextboxWrapper wrapper = new EscherTextboxWrapper();\r
+ \r
+ TextHeaderAtom tha = new TextHeaderAtom();\r
+ tha.setParentRecord(wrapper);\r
+ wrapper.appendChildRecord(tha);\r
+ \r
+ TextCharsAtom tca = new TextCharsAtom();\r
+ wrapper.appendChildRecord(tca);\r
+ \r
+ StyleTextPropAtom sta = new StyleTextPropAtom(0);\r
+ wrapper.appendChildRecord(sta);\r
+ \r
+ HSLFTextParagraph htp = new HSLFTextParagraph(tha, null, tca, sta);\r
+ htp._records = new Record[0];\r
+ HSLFTextRun htr = new HSLFTextRun(htp);\r
+ htp.addTextRun(htr);\r
+ \r
+ return Arrays.asList(htp);\r
+ }\r
+ \r
+ public EscherTextboxWrapper getTextboxWrapper() {\r
+ return (EscherTextboxWrapper)_headerAtom.getParentRecord();\r
+ }\r
+}\r
package org.apache.poi.hslf.usermodel;
+import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.fetchOrAddTextProp;
+
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.model.textproperties.*;
import org.apache.poi.hslf.record.ColorSchemeAtom;
import org.apache.poi.sl.usermodel.TextRun;
import org.apache.poi.util.POILogFactory;
/** 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 _runText = "\r";
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;
+ private TextPropCollection characterStyle = new TextPropCollection(1);
/**
- * Create a new wrapper around a (currently not)
- * rich text string
- * @param parent
- * @param startAt
- * @param len
+ * Create a new wrapper around a rich text string
+ * @param parent The parent paragraph
*/
- public HSLFTextRun(HSLFTextParagraph parent, int startAt, int len) {
- this(parent, startAt, len, null, null, false, false);
+ public HSLFTextRun(HSLFTextParagraph parentParagraph) {
+ this.parentParagraph = parentParagraph;
}
- /**
- * 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;
+
+ public TextPropCollection getCharacterStyle() {
+ return characterStyle;
+ }
+
+ public void setCharacterStyle(TextPropCollection characterStyle) {
+ this.characterStyle = characterStyle;
}
+
/**
* Supply the SlideShow we belong to
*/
* Get the length of the text
*/
public int getLength() {
- return length;
+ return _runText.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);
+ return _runText;
}
/**
* Change the text
*/
public void setText(String text) {
- String s = parentParagraph.normalize(text);
- setRawText(s);
+ _runText = text;
}
- /**
- * 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 -------
/**
* 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;
- }
+ return getFlag(index);
+ }
+
+ protected boolean getFlag(int index) {
+ if (characterStyle == null) return false;
+
+ BitMaskTextProp prop = (BitMaskTextProp)characterStyle.findByName(CharFlagsTextProp.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();
+ int txtype = parentParagraph.getParentShape().getRunType();
HSLFMasterSheet master = sheet.getMasterSheet();
if (master != null){
- prop = (BitMaskTextProp)master.getStyleAttribute(txtype, getIndentLevel(), propname, isCharacter);
+ prop = (BitMaskTextProp)master.getStyleAttribute(txtype, parentParagraph.getIndentLevel(), CharFlagsTextProp.NAME, true);
}
} else {
logger.log(POILogger.WARN, "MasterSheet is not available");
* 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;
+ if(getFlag(index) != value) setFlag(index, value);
}
/**
if (prop == null){
HSLFSheet sheet = parentParagraph.getSheet();
- int txtype = parentParagraph.getRunType();
+ int txtype = parentParagraph.getParentShape().getRunType();
HSLFMasterSheet master = sheet.getMasterSheet();
if (master != null)
- prop = master.getStyleAttribute(txtype, getIndentLevel(), propName, true);
+ prop = master.getStyleAttribute(txtype, parentParagraph.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
public void setCharTextPropVal(String propName, int val) {
// Ensure we have the StyleTextProp atom we're going to need
if(characterStyle == null) {
- parentParagraph.ensureStyleAtomPresent();
+ characterStyle = new TextPropCollection(1);
// characterStyle will now be defined
}
- assert(characterStyle!=null);
TextProp tp = fetchOrAddTextProp(characterStyle, propName);
tp.setValue(val);
}
/**
* Is the text underlined?
*/
- public boolean isUnderline() {
+ public boolean isUnderlined() {
return isCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX);
}
/**
* Is the text underlined?
*/
- public void setUnderline(boolean underlined) {
+ public void setUnderlined(boolean underlined) {
setCharFlagsTextPropVal(CharFlagsTextProp.UNDERLINE_IDX, underlined);
}
/**
* Gets the font size
*/
- public int getFontSize() {
+ public double getFontSize() {
return getCharTextPropVal("font.size");
}
*/
public void setFontName(String fontName) {
HSLFSheet sheet = parentParagraph.getSheet();
- HSLFSlideShowImpl slideShow = (sheet == null) ? null : sheet.getSlideShow();
+ HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
if (sheet == null || slideShow == null) {
//we can't set font since slideshow is not assigned yet
_fontname = fontName;
/**
* Gets the font name
*/
- public String getFontName() {
+ @Override
+ public String getFontFamily() {
HSLFSheet sheet = parentParagraph.getSheet();
- HSLFSlideShowImpl slideShow = (sheet == null) ? null : sheet.getSlideShow();
+ HSLFSlideShow slideShow = (sheet == null) ? null : sheet.getSlideShow();
if (sheet == null || slideShow == null) {
return _fontname;
}
setFontColor(rgb);
}
- /**
- * Sets the type of horizontal alignment for the text.
- * One of the <code>Align*</code> constants defined in the <code>TextBox</code> 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 <code>Align*</code> constants defined in the <code>TextBox</class> class.
- *
- * @return the type of alignment
- */
- public int getAlignment() {
- return getParaTextPropVal("alignment");
- }
+ protected void setFlag(int index, boolean value) {
+ // Ensure we have the StyleTextProp atom we're going to need
+ if (characterStyle == null) {
+ characterStyle = new TextPropCollection(1);
+ }
- /**
- *
- * @return indentation level
- */
- public int getIndentLevel() {
- return paragraphStyle == null ? 0 : paragraphStyle.getReservedField();
- }
+ BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(characterStyle, CharFlagsTextProp.NAME);
+ prop.setSubValue(value, index);
+ }
- /**
- * 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);
- }
+ public TextCap getTextCap() {
+ return TextCap.NONE;
+ }
- /**
- * Sets whether this rich text run has bullets
- */
- public void setBullet(boolean flag) {
- setFlag(false, ParagraphFlagsTextProp.BULLET_IDX, flag);
- }
+ public boolean isSubscript() {
+ return false;
+ }
- /**
- * Returns whether this rich text run has bullets
- */
- public boolean isBullet() {
- return getFlag(false, ParagraphFlagsTextProp.BULLET_IDX);
- }
+ public boolean isSuperscript() {
+ return false;
+ }
- /**
- * 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.
- * <p>
- * 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.
- * </p>
- */
- public void setLineSpacing(int val) {
- setParaTextPropVal("linespacing", val);
- }
-
- /**
- * Returns the line spacing
- * <p>
- * 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.
- * </p>
- *
- * @return the spacing between lines
- */
- public int getLineSpacing() {
- int val = getParaTextPropVal("linespacing");
- return val == -1 ? 0 : val;
- }
-
- /**
- * Sets spacing before a paragraph.
- * <p>
- * 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.
- * </p>
- */
- public void setSpaceBefore(int val) {
- setParaTextPropVal("spacebefore", val);
- }
-
- /**
- * Returns spacing before a paragraph
- * <p>
- * 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.
- * </p>
- *
- * @return the spacing before a paragraph
- */
- public int getSpaceBefore() {
- int val = getParaTextPropVal("spacebefore");
- return val == -1 ? 0 : val;
- }
-
- /**
- * Sets spacing after a paragraph.
- * <p>
- * 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.
- * </p>
- */
- public void setSpaceAfter(int val) {
- setParaTextPropVal("spaceafter", val);
- }
-
- /**
- * Returns spacing after a paragraph
- * <p>
- * 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.
- * </p>
- *
- * @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; }
+ public byte getPitchAndFamily() {
+ return 0;
+ }
}
--- /dev/null
+/* ====================================================================
+ 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 static org.apache.poi.hslf.record.RecordTypes.*;
+
+import java.awt.Rectangle;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.Rectangle2D.Double;
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.poi.POIXMLException;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.exceptions.HSLFException;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.sl.draw.DrawFactory;
+import org.apache.poi.sl.draw.DrawTextShape;
+import org.apache.poi.sl.usermodel.*;
+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 implements TextShape<HSLFTextParagraph> {
+
+ /**
+ * How to anchor the text
+ */
+ /* package */ static final int AnchorTop = 0;
+ /* package */ static final int AnchorMiddle = 1;
+ /* package */ static final int AnchorBottom = 2;
+ /* package */ static final int AnchorTopCentered = 3;
+ /* package */ static final int AnchorMiddleCentered = 4;
+ /* package */ static final int AnchorBottomCentered = 5;
+ /* package */ static final int AnchorTopBaseline = 6;
+ /* package */ static final int AnchorBottomBaseline = 7;
+ /* package */ static final int AnchorTopCenteredBaseline = 8;
+ /* package */ 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;
+
+ /**
+ * TextRun object which holds actual text and format data
+ */
+ protected List<HSLFTextParagraph> _paragraphs = new ArrayList<HSLFTextParagraph>();
+
+ /**
+ * Escher container which holds text attributes such as
+ * TextHeaderAtom, TextBytesAtom ot TextCharsAtom, StyleTextPropAtom etc.
+ */
+ protected EscherTextboxWrapper _txtbox;
+
+ /**
+ * This setting is used for supporting a deprecated alignment
+ *
+ * @see <a href=""></a>
+ */
+ boolean alignToBaseline = false;
+
+ /**
+ * 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 <code>EscherSpContainer</code> container which holds information about this shape
+ * @param parent the parent of the shape
+ */
+ protected HSLFTextShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> 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<HSLFShape> 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);
+ }
+
+ /**
+ * 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){
+
+ }
+
+ /**
+ * When a textbox is added to a sheet we need to tell upper-level
+ * <code>PPDrawing</code> 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();
+ }
+ for (HSLFTextParagraph htp : _paragraphs) {
+ htp.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 shape so it encompasses the text inside it.
+ *
+ * @return a <code>Rectangle2D</code> that is the bounds of this shape.
+ */
+ public Rectangle2D resizeToFitText(){
+ Rectangle2D anchor = getAnchor();
+ if(anchor.getWidth() == 0.) {
+ logger.log(POILogger.WARN, "Width of shape wasn't set. Defaulting to 200px");
+ anchor = new Rectangle2D.Double(anchor.getX(), anchor.getY(), 200, anchor.getHeight());
+ setAnchor(anchor);
+ }
+ double height = getTextHeight();
+ height += 1; // add a pixel to compensate rounding errors
+
+ anchor.setRect(anchor.getX(), anchor.getY(), anchor.getWidth(), height);
+ setAnchor(anchor);
+
+ return anchor;
+ }
+
+ /**
+ * 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() {
+ getEscherTextboxWrapper();
+ if (_txtbox == null) return -1;
+ TextHeaderAtom headerAtom = (TextHeaderAtom)_txtbox.findFirstOfType(TextHeaderAtom.typeID);
+ assert(headerAtom != null);
+ 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) {
+ getEscherTextboxWrapper();
+ if (_txtbox == null) return;
+ TextHeaderAtom headerAtom = (TextHeaderAtom)_txtbox.findFirstOfType(TextHeaderAtom.typeID);
+ assert(headerAtom != null);
+ headerAtom.setTextType(type);
+ }
+
+ /**
+ * Returns the type of vertical alignment for the text.
+ * One of the <code>Anchor*</code> constants defined in this class.
+ *
+ * @return the type of alignment
+ */
+ /* package */ int getAlignment(){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__ANCHORTEXT);
+ int align = 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 = getRunType();
+ HSLFMasterSheet master = getSheet().getMasterSheet();
+ if(master != null){
+ HSLFTextShape masterShape = master.getPlaceholderByTextType(type);
+ if(masterShape != null) align = masterShape.getAlignment();
+ } else {
+ //not found in the master sheet. Use the hardcoded defaults.
+ switch (type){
+ case org.apache.poi.hslf.record.TextHeaderAtom.TITLE_TYPE:
+ case org.apache.poi.hslf.record.TextHeaderAtom.CENTER_TITLE_TYPE:
+ align = HSLFTextShape.AnchorMiddle;
+ break;
+ default:
+ align = HSLFTextShape.AnchorTop;
+ break;
+ }
+ }
+ } else {
+ align = prop.getPropertyValue();
+ }
+
+ alignToBaseline = (align == AnchorBottomBaseline || align == AnchorBottomCenteredBaseline
+ || align == AnchorTopBaseline || align == AnchorTopCenteredBaseline);
+
+ return align;
+ }
+
+ /**
+ * Sets the type of alignment for the text.
+ * One of the <code>Anchor*</code> constants defined in this class.
+ *
+ * @param align - the type of alignment
+ */
+ /* package */ void setAlignment(Boolean isCentered, VerticalAlignment vAlign) {
+ int align[];
+ switch (vAlign) {
+ case TOP:
+ align = new int[]{AnchorTop, AnchorTopCentered, AnchorTopBaseline, AnchorTopCenteredBaseline};
+ break;
+ default:
+ case MIDDLE:
+ align = new int[]{AnchorMiddle, AnchorMiddleCentered, AnchorMiddle, AnchorMiddleCentered};
+ break;
+ case BOTTOM:
+ align = new int[]{AnchorBottom, AnchorBottomCentered, AnchorBottomBaseline, AnchorBottomCenteredBaseline};
+ break;
+ }
+
+ int align2 = align[(isCentered ? 1 : 0)+(alignToBaseline ? 2 : 0)];
+
+ setEscherProperty(EscherProperties.TEXT__ANCHORTEXT, align2);
+ }
+
+ @Override
+ public VerticalAlignment getVerticalAlignment() {
+ int va = getAlignment();
+ switch (va) {
+ case AnchorTop:
+ case AnchorTopCentered:
+ case AnchorTopBaseline:
+ case AnchorTopCenteredBaseline: return VerticalAlignment.TOP;
+ case AnchorBottom:
+ case AnchorBottomCentered:
+ case AnchorBottomBaseline:
+ case AnchorBottomCenteredBaseline: return VerticalAlignment.BOTTOM;
+ default:
+ case AnchorMiddle:
+ case AnchorMiddleCentered: return VerticalAlignment.MIDDLE;
+ }
+ }
+
+ /**
+ * @return true, if vertical alignment is relative to baseline
+ * this is only used for older versions less equals Office 2003
+ */
+ public boolean isAlignToBaseline() {
+ getAlignment();
+ return alignToBaseline;
+ }
+
+ /**
+ * Sets the vertical alignment relative to the baseline
+ *
+ * @param alignToBaseline if true, vertical alignment is relative to baseline
+ */
+ public void setAlignToBaseline(boolean alignToBaseline) {
+ this.alignToBaseline = alignToBaseline;
+ setAlignment(isHorizontalCentered(), getVerticalAlignment());
+ }
+
+ @Override
+ public boolean isHorizontalCentered() {
+ int va = getAlignment();
+ switch (va) {
+ case AnchorTopCentered:
+ case AnchorTopCenteredBaseline:
+ case AnchorBottomCentered:
+ case AnchorBottomCenteredBaseline:
+ case AnchorMiddleCentered:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public void setVerticalAlignment(VerticalAlignment vAlign) {
+ setAlignment(isHorizontalCentered(), vAlign);
+ }
+
+ /**
+ * Sets if the paragraphs are horizontal centered
+ *
+ * @param isCentered true, if the paragraphs are horizontal centered
+ * A {@code null} values unsets this property.
+ *
+ * @see TextShape#isHorizontalCentered()
+ */
+ public void setHorizontalCentered(Boolean isCentered){
+ setAlignment(isCentered, getVerticalAlignment());
+ }
+
+ /**
+ * 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 double getBottomInset(){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTBOTTOM);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the botom margin.
+ * @see #getBottomInset()
+ *
+ * @param margin the bottom margin
+ */
+ public void setBottomInset(double 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 double getLeftInset(){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTLEFT);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the left margin.
+ * @see #getLeftInset()
+ *
+ * @param margin the left margin
+ */
+ public void setLeftInset(double 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 double getRightInset(){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTRIGHT);
+ int val = prop == null ? EMU_PER_INCH/10 : prop.getPropertyValue();
+ return val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the right margin.
+ * @see #getRightInset()
+ *
+ * @param margin the right margin
+ */
+ public void setRightInset(double 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 double getTopInset(){
+ EscherOptRecord opt = getEscherOptRecord();
+ EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.TEXT__TEXTTOP);
+ int val = prop == null ? EMU_PER_INCH/20 : prop.getPropertyValue();
+ return val/EMU_PER_POINT;
+ }
+
+ /**
+ * Sets the top margin.
+ * @see #getTopInset()
+ *
+ * @param margin the top margin
+ */
+ public void setTopInset(double margin){
+ setEscherProperty(EscherProperties.TEXT__TEXTTOP, (int)(margin*EMU_PER_POINT));
+ }
+
+ @Override
+ public boolean getWordWrap(){
+ int ww = getWordWrapEx();
+ return (ww != WrapNone);
+ }
+
+ /**
+ * Returns the value indicating word wrap.
+ *
+ * @return the value indicating word wrap.
+ * Must be one of the <code>Wrap*</code> constants defined in this class.
+ *
+ * @see <a href="https://msdn.microsoft.com/en-us/library/dd948168(v=office.12).aspx">MSOWRAPMODE</a>
+ */
+ public int getWordWrapEx() {
+ 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 <code>Wrap*</code> 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 List<HSLFTextParagraph> getTextParagraphs(){
+ if (!_paragraphs.isEmpty()) return _paragraphs;
+
+ _txtbox = getEscherTextboxWrapper();
+ if (_txtbox == null) {
+ _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
+ _txtbox = _paragraphs.get(0).getTextboxWrapper();
+ } else {
+ initParagraphsFromSheetRecords();
+ if (_paragraphs.isEmpty()) {
+ List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_txtbox);
+ if (!llhtp.isEmpty()) {
+ _paragraphs.addAll(llhtp.get(0));
+ }
+ }
+ }
+
+ for (HSLFTextParagraph p : _paragraphs) {
+ p.setParentShape(this);
+ }
+
+ return _paragraphs;
+ }
+
+ 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)
+ for (HSLFTextParagraph htp : getTextParagraphs()) {
+ // Supply the sheet to our child RichTextRuns
+ htp.supplySheet(_sheet);
+ }
+ }
+
+ protected void initParagraphsFromSheetRecords(){
+ 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;
+ }
+ }
+
+ List<List<HSLFTextParagraph>> sheetRuns = _sheet.getTextParagraphs();
+ _paragraphs.clear();
+ if (sheetRuns != null) {
+ if (ota != null) {
+ int idx = ota.getTextIndex();
+ for (List<HSLFTextParagraph> r : sheetRuns) {
+ if (r.isEmpty()) continue;
+ int ridx = r.get(0).getIndex();
+ if (ridx > idx) break;
+ if (ridx == idx) _paragraphs.addAll(r);
+ }
+ if(_paragraphs.isEmpty()) {
+ logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+ }
+ } else {
+ int shapeId = getShapeId();
+ for (List<HSLFTextParagraph> r : sheetRuns) {
+ if (r.isEmpty()) continue;
+ if (r.get(0).getShapeId() == shapeId) _paragraphs.addAll(r);
+ }
+ }
+ }
+
+ // ensure the same references child records of TextRun
+ // TODO: check the purpose of this ...
+// 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;
+// }
+// }
+// }
+// }
+ }
+
+ /*
+ // 0xB acts like cariage return in page titles and like blank in the others
+ char replChr;
+ switch(tha == null ? -1 : tha.getTextType()) {
+ case -1:
+ case TextHeaderAtom.TITLE_TYPE:
+ case TextHeaderAtom.CENTER_TITLE_TYPE:
+ replChr = '\n';
+ break;
+ default:
+ replChr = ' ';
+ break;
+ }
+
+ // 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').replace('\u000b', replChr);
+ */
+
+ /**
+ * Return <code>OEPlaceholderAtom</code>, the atom that describes a placeholder.
+ *
+ * @return <code>OEPlaceholderAtom</code> or <code>null</code> if not found
+ */
+ public OEPlaceholderAtom getPlaceholderAtom(){
+ return getClientDataRecord(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(HSLFHyperlink)
+ */
+ 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(org.apache.poi.hslf.record.InteractiveInfoAtom.ACTION_HYPERLINK);
+ infoAtom.setHyperlinkType(org.apache.poi.hslf.record.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(RoundTripHFPlaceholder12.typeID);
+ if (hldr != null) return true;
+
+ return false;
+ }
+
+
+ @Override
+ public Iterator<HSLFTextParagraph> iterator() {
+ return _paragraphs.iterator();
+ }
+
+ @Override
+ public Insets2D getInsets() {
+ Insets2D insets = new Insets2D(getTopInset(), getLeftInset(), getBottomInset(), getRightInset());
+ return insets;
+ }
+
+ @Override
+ public double getTextHeight(){
+ DrawFactory drawFact = DrawFactory.getInstance(null);
+ DrawTextShape<HSLFTextShape> dts = drawFact.getDrawable(this);
+ return dts.getTextHeight();
+ }
+
+ @Override
+ public TextDirection getTextDirection() {
+ // TODO: determine vertical text setting
+ return TextDirection.HORIZONTAL;
+ }
+
+ /**
+ * Returns the raw text content of the shape. This hasn't had any
+ * changes applied to it, and so is probably unlikely to print
+ * out nicely.
+ */
+ public String getRawText() {
+ return HSLFTextParagraph.getRawText(getTextParagraphs());
+ }
+
+ /**
+ * Returns the text contained in this text frame, which has been made safe
+ * for printing and other use.
+ *
+ * @return the text string for this textbox.
+ */
+ public String getText() {
+ String rawText = getRawText();
+ TextHeaderAtom _headerAtom = (TextHeaderAtom)_txtbox.findFirstOfType(TextHeaderAtom.typeID);
+ int runType = (_headerAtom == null) ? -1 : _headerAtom.getTextType();
+
+ return HSLFTextParagraph.toExternalString(rawText, runType);
+ }
+
+
+ // Update methods follow
+
+ /**
+ * Adds the supplied text onto the end of the TextParagraphs,
+ * creating a new RichTextRun for it to sit in.
+ *
+ * @param text the text string used by this object.
+ */
+ public void appendText(String text, boolean newParagraph) {
+ // init paragraphs
+ List<HSLFTextParagraph> paras = getTextParagraphs();
+ HSLFTextParagraph.appendText(paras, text, newParagraph);
+ }
+
+ /**
+ * Sets (overwrites) the current text.
+ * Uses the properties of the first paragraph / textrun
+ *
+ * @param text the text string used by this object.
+ */
+ public void setText(String text) {
+ // init paragraphs
+ List<HSLFTextParagraph> paras = getTextParagraphs();
+ HSLFTextParagraph.setText(paras, text);
+ setTextId(text.hashCode());
+ }
+
+ /**
+ * Saves the modified paragraphs/textrun to the records.
+ * Also updates the styles to the correct text length.
+ */
+ protected void storeText() {
+ HSLFTextParagraph.storeText(_paragraphs);
+ }
+ // Accesser methods follow
+
+ /**
+ * Returns the array of all hyperlinks in this text run
+ *
+ * @return the array of all hyperlinks in this text run or <code>null</code>
+ * if not found.
+ */
+ public HSLFHyperlink[] getHyperlinks() {
+ return HSLFHyperlink.find(this);
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.hslf.model.textproperties.TextProp;
+import org.apache.poi.hslf.record.SlideAtom;
+
+/**
+ * Title masters define the design template for slides with a Title Slide layout.
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFTitleMaster extends HSLFMasterSheet {
+ private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>();
+
+ /**
+ * Constructs a TitleMaster
+ *
+ */
+ public HSLFTitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) {
+ super(record, sheetNo);
+
+ _runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing()));
+ }
+
+ /**
+ * Returns an array of all the TextRuns found
+ */
+ public List<List<HSLFTextParagraph>> getTextParagraphs() {
+ return _runs;
+ }
+
+ /**
+ * Delegate the call to the underlying slide master.
+ */
+ public TextProp getStyleAttribute(int txtype, int level, String name, boolean isCharacter) {
+ HSLFMasterSheet master = getMasterSheet();
+ return master == null ? null : master.getStyleAttribute(txtype, level, name, isCharacter);
+ }
+
+ /**
+ * Returns the slide master for this title master.
+ */
+ public HSLFMasterSheet getMasterSheet(){
+ List<HSLFSlideMaster> master = getSlideShow().getSlideMasters();
+ SlideAtom sa = ((org.apache.poi.hslf.record.Slide)getSheetContainer()).getSlideAtom();
+ int masterId = sa.getMasterID();
+ for (HSLFSlideMaster sm : master) {
+ if (masterId == sm._getSheetNumber()) return sm;
+ }
+ return null;
+ }
+}
} else if (shape instanceof Background) {\r
return getDrawable((Background)shape);\r
} else if (shape instanceof Slide) {\r
- return getDrawable((Slide<? extends Shape, ? extends SlideShow>)shape);\r
+ return getDrawable((Slide<? extends Shape, ? extends SlideShow, ? extends Notes<?,?>>)shape);\r
} else if (shape instanceof MasterSheet) {\r
return getDrawable((MasterSheet<? extends Shape, ? extends SlideShow>)shape);\r
} else if (shape instanceof Sheet) {\r
throw new IllegalArgumentException("Unsupported shape type: "+shape.getClass());\r
}\r
\r
- public <T extends Slide<? extends Shape, ? extends SlideShow>> DrawSlide<T> getDrawable(T sheet) {\r
+ public <T extends Slide<? extends Shape, ? extends SlideShow, ? extends Notes<?,?>>> DrawSlide<T> getDrawable(T sheet) {\r
return new DrawSlide<T>(sheet);\r
}\r
\r
import org.apache.poi.sl.usermodel.*;\r
\r
\r
-public class DrawSlide<T extends Slide<? extends Shape, ? extends SlideShow>> extends DrawSheet<T> {\r
+public class DrawSlide<T extends Slide<? extends Shape, ? extends SlideShow, ? extends Notes<?,?>>> extends DrawSheet<T> {\r
\r
public DrawSlide(T slide) {\r
super(slide);\r
protected String getRenderableText(TextRun tr) {\r
StringBuilder buf = new StringBuilder();\r
TextCap cap = tr.getTextCap();\r
- for (char c : tr.getText().toCharArray()) {\r
+ for (char c : tr.getRawText().toCharArray()) {\r
if(c == '\t') {\r
// TODO: finish support for tabs\r
buf.append(" ");\r
if(run.isItalic()) {\r
attList.add(new AttributedStringData(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, beginIndex, endIndex));\r
}\r
- if(run.isUnderline()) {\r
+ if(run.isUnderlined()) {\r
attList.add(new AttributedStringData(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, beginIndex, endIndex));\r
attList.add(new AttributedStringData(TextAttribute.INPUT_METHOD_UNDERLINE, TextAttribute.UNDERLINE_LOW_TWO_PIXEL, beginIndex, endIndex));\r
}\r
package org.apache.poi.sl.draw.geom;
-import java.io.*;
-import java.nio.charset.Charset;
+import java.io.InputStream;
import java.util.LinkedHashMap;
import javax.xml.bind.*;
package org.apache.poi.sl.usermodel;
-public interface Line extends AutoShape {
+public interface Line<T extends TextParagraph<? extends TextRun>> extends AutoShape<T> {
}
import java.util.List;
public interface Notes<T extends Shape, SS extends SlideShow> extends Sheet<T,SS> {
- List<? extends TextParagraph<? extends TextRun>> getTextParagraphs();
+ List<? extends List<? extends TextParagraph<? extends TextRun>>> getTextParagraphs();
}
package org.apache.poi.sl.usermodel;
+import java.util.List;
+
public interface ShapeContainer<T extends Shape> extends Iterable<T> {
/**
- * Returns an array containing all of the elements in this container in proper
+ * Returns an list containing all of the elements in this container in proper
* sequence (from first to last element).
*
- * @return an array containing all of the elements in this container in proper
+ * @return an list containing all of the elements in this container in proper
* sequence
*/
- public T[] getShapes();
+ List<T> getShapes();
- public void addShape(T shape);
+ void addShape(T shape);
/**
* Removes the specified shape from this sheet, if it is present
* @throws IllegalArgumentException if the type of the specified shape
* is incompatible with this sheet (optional)
*/
- public boolean removeShape(T shape);
+ boolean removeShape(T shape);
}
this.nativeName = nativeName;
}
+ /** name of the presetShapeDefinit(i)on entry */
+ public String getOoxmlName() {
+ if (this == SEAL) return STAR_16.getOoxmlName();
+ if (ooxmlId == -1) return null;
+
+ StringBuilder sb = new StringBuilder();
+ boolean toLower = true;
+ for (char ch : name().toCharArray()) {
+ if (ch == '_') {
+ toLower = false;
+ continue;
+ }
+ sb.append(toLower ? Character.toLowerCase(ch) : Character.toUpperCase(ch));
+ toLower = true;
+ }
+
+ return sb.toString();
+ }
+
public static ShapeType forId(int id, boolean isOoxmlId){
for(ShapeType t : values()){
if((isOoxmlId && t.ooxmlId == id) ||
package org.apache.poi.sl.usermodel;
-public interface Slide<T extends Shape, SS extends SlideShow> extends Sheet<T, SS> {
- public Notes<T,SS> getNotes();
- public void setNotes(Notes<T,SS> notes);
+public interface Slide<T extends Shape, SS extends SlideShow, N extends Notes<T,SS>> extends Sheet<T, SS> {
+ N getNotes();
+ void setNotes(N notes);
- public boolean getFollowMasterBackground();
- public void setFollowMasterBackground(boolean follow);
+ boolean getFollowMasterBackground();
+ void setFollowMasterBackground(boolean follow);
- public boolean getFollowMasterColourScheme();
- public void setFollowMasterColourScheme(boolean follow);
+ boolean getFollowMasterColourScheme();
+ void setFollowMasterColourScheme(boolean follow);
- public boolean getFollowMasterObjects();
- public void setFollowMasterObjects(boolean follow);
+ boolean getFollowMasterObjects();
+ void setFollowMasterObjects(boolean follow);
}
import java.awt.Dimension;
import java.io.IOException;
+import java.util.List;
public interface SlideShow {
- Slide<? extends Shape, ? extends SlideShow> createSlide() throws IOException;
- MasterSheet<? extends Shape, ? extends SlideShow> createMasterSheet() throws IOException;
+ Slide<? extends Shape, ? extends SlideShow, ? extends Notes<?,?>> createSlide() throws IOException;
- Slide<? extends Shape, ? extends SlideShow>[] getSlides();
- MasterSheet<? extends Shape, ? extends SlideShow>[] getMasterSheet();
+ List<? extends Slide<? extends Shape, ? extends SlideShow, ? extends Notes<?,?>>> getSlides();
+
+ MasterSheet<? extends Shape, ? extends SlideShow> createMasterSheet() throws IOException;
+
+ /**
+ * Returns all slide masters.
+ * This doesn't include notes master and other arbitrary masters.
+ */
+ List<? extends MasterSheet<? extends Shape, ? extends SlideShow>> getSlideMasters();
Resources getResources();
\r
public interface TextParagraph<T extends TextRun> extends Iterable<T> {\r
/**\r
- * Specified a list of text alignment types\r
+ * Specifies a list of text alignment types\r
*/\r
public enum TextAlign {\r
/**\r
THAI_DIST\r
}\r
\r
+ /**\r
+ * \r
+ */\r
+ public enum FontAlign {\r
+ AUTO, TOP, CENTER, BASELINE, BOTTOM; \r
+ }\r
+ \r
public interface BulletStyle {\r
String getBulletCharacter();\r
String getBulletFont();\r
*/\r
double getLeftMargin();\r
\r
+ /**\r
+ * @param leftMargin the left margin (in points) \r
+ */\r
+ void setLeftMargin(double leftMargin);\r
+ \r
+ \r
/**\r
* @return the right margin (in points) of the paragraph\r
*/\r
double getRightMargin();\r
\r
/**\r
- * @return the indent applied (in points) to the first line of text in the paragraph.\r
+ * @param rightMargin the right margin (in points) of the paragraph\r
+ */\r
+ void setRightMargin(double rightMargin);\r
+ \r
+ /**\r
+ * @return the indent (in points) applied to the first line of text in the paragraph.\r
*/\r
double getIndent();\r
\r
+ /**\r
+ * @param indent the indent (in points) applied to the first line of text in the paragraph\r
+ */\r
+ void setIndent(double indent);\r
+ \r
/**\r
* Returns the vertical line spacing that is to be used within a paragraph.\r
* This may be specified in two different ways, percentage spacing and font point spacing:\r
*/\r
TextAlign getTextAlign();\r
\r
+ \r
+ /**\r
+ * Returns the font alignment that is applied to the paragraph.\r
+ *\r
+ * If this attribute is omitted, then a value of auto (~ left) is implied.\r
+ * @return ??? alignment that is applied to the paragraph\r
+ */\r
+ FontAlign getFontAlign();\r
+ \r
/**\r
* @return the bullet style of the paragraph, if {@code null} then no bullets are used \r
*/\r
ALL
}
- public String getText();
+ public String getRawText();
public void setText(String text);
TextCap getTextCap();
boolean isBold();
boolean isItalic();
- boolean isUnderline();
+ boolean isUnderlined();
boolean isStrikethrough();
boolean isSubscript();
boolean isSuperscript();
\r
package org.apache.poi.sl.usermodel;\r
\r
+import org.apache.poi.ss.usermodel.HorizontalAlignment;\r
+\r
\r
\r
public interface TextShape<T extends TextParagraph<? extends TextRun>> extends SimpleShape, Iterable<T> {\r
*/\r
VerticalAlignment getVerticalAlignment();\r
\r
+ /**\r
+ * Returns if the text is centered.\r
+ * If true and if the individual paragraph settings allow it,\r
+ * the whole text block will be displayed centered, i.e. its left and right\r
+ * margin will be maximized while still keeping the alignment of the paragraphs\r
+ *\r
+ * @return true, if the text anchor is horizontal centered \r
+ */\r
+ boolean isHorizontalCentered();\r
+ \r
/**\r
* @return whether to wrap words within the bounding rectangle\r
*/\r
import java.io.*;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.hwpf.HWPFTestDataSamples;
import org.apache.poi.poifs.filesystem.*;
import java.io.InputStream;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
public class HSLFTestDataSamples {
import junit.framework.TestCase;
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.POIDataSamples;
/**
import junit.framework.TestCase;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import java.io.*;
import java.util.*;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.POIDataSamples;
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.POIDataSamples;
/**
import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.model.OLEShape;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.poifs.filesystem.DirectoryNode;
package org.apache.poi.hslf.model;
+import org.apache.poi.hslf.usermodel.TestTextRun;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
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.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeType;
import org.junit.Test;
public void defaults() {
HSLFSlideShow ppt = new HSLFSlideShow();
- assertEquals(HSLFFill.FILL_SOLID, ppt.getSlidesMasters()[0].getBackground().getFill().getFillType());
+ assertEquals(HSLFFill.FILL_SOLID, ppt.getSlideMasters().get(0).getBackground().getFill().getFillType());
HSLFSlide slide = ppt.createSlide();
assertTrue(slide.getFollowMasterBackground());
HSLFFill fill;
HSLFShape shape;
- HSLFSlide[] slide = ppt.getSlides();
+ List<HSLFSlide> slide = ppt.getSlides();
- fill = slide[0].getBackground().getFill();
+ fill = slide.get(0).getBackground().getFill();
assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
- shape = slide[0].getShapes()[0];
+ shape = slide.get(0).getShapes().get(0);
assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
- fill = slide[1].getBackground().getFill();
+ fill = slide.get(1).getBackground().getFill();
assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
- shape = slide[1].getShapes()[0];
+ shape = slide.get(1).getShapes().get(0);
assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
- fill = slide[2].getBackground().getFill();
+ fill = slide.get(2).getBackground().getFill();
assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
- shape = slide[2].getShapes()[0];
+ shape = slide.get(2).getShapes().get(0);
assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
- fill = slide[3].getBackground().getFill();
+ fill = slide.get(3).getBackground().getFill();
assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
- shape = slide[3].getShapes()[0];
+ shape = slide.get(3).getShapes().get(0);
assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
}
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- HSLFSlide[] slides = ppt.getSlides();
+ List<HSLFSlide> slides = ppt.getSlides();
- fill = slides[0].getBackground().getFill();
+ fill = slides.get(0).getBackground().getFill();
assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
- assertEquals(3, getFillPictureRefCount(slides[0].getBackground(), fill));
- shape = slides[0].getShapes()[0];
+ assertEquals(3, getFillPictureRefCount(slides.get(0).getBackground(), fill));
+ shape = slides.get(0).getShapes().get(0);
assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
- fill = slides[1].getBackground().getFill();
+ fill = slides.get(1).getBackground().getFill();
assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
- shape = slides[1].getShapes()[0];
+ shape = slides.get(1).getShapes().get(0);
assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
- fill = slides[2].getBackground().getFill();
+ fill = slides.get(2).getBackground().getFill();
assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
- assertEquals(3, getFillPictureRefCount(slides[2].getBackground(), fill));
- shape = slides[2].getShapes()[0];
+ assertEquals(3, getFillPictureRefCount(slides.get(2).getBackground(), fill));
+ shape = slides.get(2).getShapes().get(0);
assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
assertEquals(1, getFillPictureRefCount(shape, fill));
- fill = slides[3].getBackground().getFill();
+ fill = slides.get(3).getBackground().getFill();
assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
- shape = slides[3].getShapes()[0];
+ shape = slides.get(3).getShapes().get(0);
assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
}
package org.apache.poi.hslf.model;
-import java.awt.geom.Area;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Line2D;
-import java.awt.geom.Rectangle2D;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import junit.framework.TestCase;
+import java.awt.geom.*;
+
+import org.apache.poi.hslf.usermodel.HSLFFreeformShape;
+import org.junit.Test;
/**
* Test Freeform object.
*
* @author Yegor Kozlov
*/
-public final class TestFreeform extends TestCase {
+public final class TestFreeform {
+ @Test
public void testClosedPath() {
GeneralPath path1 = new GeneralPath();
assertTrue(new Area(path1).equals(new Area(path2)));
}
+ @Test
public void testLine() {
GeneralPath path1 = new GeneralPath(new Line2D.Double(100, 100, 200, 100));
assertTrue(new Area(path1).equals(new Area(path2)));
}
+ @Test
public void testRectangle() {
GeneralPath path1 = new GeneralPath(new Rectangle2D.Double(100, 100, 200, 50));
* Avoid NPE in Freeform.getOutline() if either GEOMETRY__VERTICES or
* GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188
*/
+ @Test
public void test54188() {
HSLFFreeformShape p = new HSLFFreeformShape();
package org.apache.poi.hslf.model;
-import java.io.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
-import junit.framework.TestCase;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.junit.Test;
/**
* Test {@link org.apache.poi.hslf.model.HeadersFooters} object
*/
-public final class TestHeadersFooters extends TestCase
+public final class TestHeadersFooters
{
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
- public void testRead() throws Exception
- {
+ @Test
+ public void testRead() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("headers_footers.ppt"));
HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
assertTrue(notesHdd.isUserDateVisible());
assertNull(notesHdd.getDateTimeText());
- HSLFSlide[] slide = ppt.getSlides();
+ List<HSLFSlide> slide = ppt.getSlides();
//the first slide uses presentation-scope headers / footers
- HeadersFooters hd1 = slide[0].getHeadersFooters();
+ HeadersFooters hd1 = slide.get(0).getHeadersFooters();
assertEquals(slideHdd.isFooterVisible(), hd1.isFooterVisible());
assertEquals(slideHdd.getFooterText(), hd1.getFooterText());
assertEquals(slideHdd.isSlideNumberVisible(), hd1.isSlideNumberVisible());
assertEquals(slideHdd.getDateTimeText(), hd1.getDateTimeText());
//the first slide uses per-slide headers / footers
- HeadersFooters hd2 = slide[1].getHeadersFooters();
+ HeadersFooters hd2 = slide.get(1).getHeadersFooters();
assertEquals(true, hd2.isFooterVisible());
assertEquals("per-slide footer", hd2.getFooterText());
assertEquals(true, hd2.isUserDateVisible());
/**
* If Headers / Footers are not set, all the getters should return <code>false</code> or <code>null</code>
*/
- public void testReadNoHeadersFooters() throws Exception
- {
+ @Test
+ public void testReadNoHeadersFooters() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
assertFalse(notesHdd.isUserDateVisible());
assertNull(notesHdd.getDateTimeText());
- HSLFSlide[] slide = ppt.getSlides();
- for(int i=0 ; i < slide.length; i++){
- HeadersFooters hd1 = slide[i].getHeadersFooters();
+ for(HSLFSlide s : ppt.getSlides()) {
+ HeadersFooters hd1 = s.getHeadersFooters();
assertFalse(hd1.isFooterVisible());
assertNull(hd1.getFooterText());
assertFalse(hd1.isHeaderVisible());
/**
* Test extraction of headers / footers from PPTs saved in Office 2007
*/
- public void testRead2007() throws Exception
- {
+ @Test
+ public void testRead2007() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("headers_footers_2007.ppt"));
HeadersFooters slideHdd = ppt.getSlideHeadersFooters();
//assertEquals("08/12/08", notesHdd.getDateTimeText());
//per-slide headers / footers
- HSLFSlide[] slide = ppt.getSlides();
+ List<HSLFSlide> slide = ppt.getSlides();
//the first slide uses presentation-scope headers / footers
- HeadersFooters hd1 = slide[0].getHeadersFooters();
+ HeadersFooters hd1 = slide.get(0).getHeadersFooters();
assertTrue(hd1.isFooterVisible());
assertEquals("THE FOOTER TEXT", hd1.getFooterText());
assertTrue(hd1.isSlideNumberVisible());
assertEquals("Wednesday, August 06, 2008", hd1.getDateTimeText());
//the second slide uses custom per-slide headers / footers
- HeadersFooters hd2 = slide[1].getHeadersFooters();
+ HeadersFooters hd2 = slide.get(1).getHeadersFooters();
assertTrue(hd2.isFooterVisible());
assertEquals("THE FOOTER TEXT FOR SLIDE 2", hd2.getFooterText());
assertTrue(hd2.isSlideNumberVisible());
assertEquals("August 06, 2008", hd2.getDateTimeText());
//the third slide uses per-slide headers / footers
- HeadersFooters hd3 = slide[2].getHeadersFooters();
+ HeadersFooters hd3 = slide.get(2).getHeadersFooters();
assertTrue(hd3.isFooterVisible());
assertEquals("THE FOOTER TEXT", hd3.getFooterText());
assertTrue(hd3.isSlideNumberVisible());
assertEquals("Wednesday, August 06, 2008", hd3.getDateTimeText());
}
- public void testCreateSlideFooters() throws Exception
- {
+ @Test
+ public void testCreateSlideFooters() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HeadersFooters hdd = ppt.getSlideHeadersFooters();
hdd.setFootersText("My slide footer");
assertEquals("My slide footer", hdd2.getFooterText());
}
- public void testCreateNotesFooters() throws Exception
- {
+ @Test
+ public void testCreateNotesFooters() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HeadersFooters hdd = ppt.getNotesHeadersFooters();
hdd.setFootersText("My notes footer");
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
+import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.getRawText;
+import static org.apache.poi.hslf.usermodel.HSLFTextParagraph.toExternalString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test Hyperlink.
*
* @author Yegor Kozlov
*/
-public final class TestHyperlink extends TestCase {
+public final class TestHyperlink {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+ @Test
public void testTextRunHyperlinks() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("WithLinks.ppt"));
- HSLFTextParagraph[] run;
- HSLFSlide slide;
- slide = ppt.getSlides()[0];
- run = slide.getTextRuns();
- for (int i = 0; i < run.length; i++) {
- String text = run[i].getText();
- if (text.equals(
- "This page has two links:\n" +
- "http://jakarta.apache.org/poi/\n" +
- "\n" +
- "http://slashdot.org/\n" +
- "\n" +
- "In addition, its notes has one link")){
-
- Hyperlink[] links = run[i].getHyperlinks();
- assertNotNull(links);
- assertEquals(2, links.length);
-
- assertEquals("http://jakarta.apache.org/poi/", links[0].getTitle());
- assertEquals("http://jakarta.apache.org/poi/", links[0].getAddress());
- assertEquals("http://jakarta.apache.org/poi/", text.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
-
- assertEquals("http://slashdot.org/", links[1].getTitle());
- assertEquals("http://slashdot.org/", links[1].getAddress());
- assertEquals("http://slashdot.org/", text.substring(links[1].getStartIndex(), links[1].getEndIndex()-1));
-
- }
- }
-
- slide = ppt.getSlides()[1];
- run = slide.getTextRuns();
- for (int i = 0; i < run.length; i++) {
- String text = run[i].getText();
- if (text.equals(
- "I have the one link:\n" +
- "Jakarta HSSF")){
-
- Hyperlink[] links = run[i].getHyperlinks();
- assertNotNull(links);
- assertEquals(1, links.length);
-
- assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getTitle());
- assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getAddress());
- assertEquals("Jakarta HSSF", text.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
-
- }
- }
-
+ HSLFSlide slide = ppt.getSlides().get(0);
+ List<HSLFTextParagraph> para = slide.getTextParagraphs().get(1);
+
+ String rawText = toExternalString(getRawText(para), para.get(0).getRunType());
+ String expected =
+ "This page has two links:\n"+
+ "http://jakarta.apache.org/poi/\n"+
+ "\n"+
+ "http://slashdot.org/\n"+
+ "\n"+
+ "In addition, its notes has one link";
+ assertEquals(expected, rawText);
+
+ HSLFHyperlink[] links = HSLFHyperlink.find(para.get(1));
+ assertNotNull(links);
+ assertEquals(2, links.length);
+
+ assertEquals("http://jakarta.apache.org/poi/", links[0].getTitle());
+ assertEquals("http://jakarta.apache.org/poi/", links[0].getAddress());
+ assertEquals("http://jakarta.apache.org/poi/", rawText.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
+
+ assertEquals("http://slashdot.org/", links[1].getTitle());
+ assertEquals("http://slashdot.org/", links[1].getAddress());
+ assertEquals("http://slashdot.org/", rawText.substring(links[1].getStartIndex(), links[1].getEndIndex()-1));
+
+ slide = ppt.getSlides().get(1);
+ para = slide.getTextParagraphs().get(1);
+ rawText = toExternalString(getRawText(para), para.get(0).getRunType());
+ expected =
+ "I have the one link:\n" +
+ "Jakarta HSSF";
+ assertEquals(expected, rawText);
+
+ links = HSLFHyperlink.find(para.get(1));
+ assertNotNull(links);
+ assertEquals(1, links.length);
+
+ assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getTitle());
+ assertEquals("http://jakarta.apache.org/poi/hssf/", links[0].getAddress());
+ assertEquals("Jakarta HSSF", rawText.substring(links[0].getStartIndex(), links[0].getEndIndex()-1));
}
-
}
import org.apache.poi.hslf.blip.BitmapPainter;
import org.apache.poi.hslf.blip.ImagePainter;
import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFPictureShape;
/**
* Test Picture shape.
import java.awt.Color;
-import junit.framework.TestCase;
-
+import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
+import org.junit.Test;
/**
* Test Line shape.
*
* @author Yegor Kozlov
*/
-public final class TestLine extends TestCase {
+public final class TestLine {
+ @Test
public void testCreateLines() {
HSLFSlideShow ppt = new HSLFSlideShow();
*/
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 200, 300, 0));
- line.setLineStyle(Line.LINE_SIMPLE);
+ line.setLineCompound(LineCompound.SINGLE);
line.setLineColor(Color.blue);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 230, 300, 0));
- line.setLineStyle(Line.LINE_DOUBLE);
+ line.setLineCompound(LineCompound.DOUBLE);
line.setLineWidth(3.5);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 260, 300, 0));
- line.setLineStyle(Line.LINE_TRIPLE);
+ line.setLineCompound(LineCompound.TRIPLE);
line.setLineWidth(6);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 290, 300, 0));
- line.setLineStyle(Line.LINE_THICKTHIN);
+ line.setLineCompound(LineCompound.THICK_THIN);
line.setLineWidth(4.5);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 320, 300, 0));
- line.setLineStyle(Line.LINE_THINTHICK);
+ line.setLineCompound(LineCompound.THIN_THICK);
line.setLineWidth(5.5);
slide.addShape(line);
*/
line = new Line();
line.setAnchor(new java.awt.Rectangle(450, 200, 300, 0));
- line.setLineDashing(Line.PEN_SOLID);
+ line.setLineDashing(LineDash.SOLID);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(450, 230, 300, 0));
- line.setLineDashing(Line.PEN_PS_DASH);
+ line.setLineDashing(LineDash.DASH);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(450, 260, 300, 0));
- line.setLineDashing(Line.PEN_DOT);
+ line.setLineDashing(LineDash.DOT);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(450, 290, 300, 0));
- line.setLineDashing(Line.PEN_DOTGEL);
+ line.setLineDashing(LineDash.DASH_DOT);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(450, 320, 300, 0));
- line.setLineDashing(Line.PEN_LONGDASHDOTDOTGEL);
+ line.setLineDashing(LineDash.LG_DASH_DOT_DOT);
slide.addShape(line);
/**
*/
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 400, 300, 0));
- line.setLineDashing(Line.PEN_DASHDOT);
- line.setLineStyle(Line.LINE_TRIPLE);
+ line.setLineDashing(LineDash.DASH_DOT);
+ line.setLineCompound(LineCompound.TRIPLE);
line.setLineWidth(5.0);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 430, 300, 0));
- line.setLineDashing(Line.PEN_DASH);
- line.setLineStyle(Line.LINE_THICKTHIN);
+ line.setLineDashing(LineDash.DASH);
+ line.setLineCompound(LineCompound.THICK_THIN);
line.setLineWidth(4.0);
slide.addShape(line);
line = new Line();
line.setAnchor(new java.awt.Rectangle(75, 460, 300, 0));
- line.setLineDashing(Line.PEN_DOT);
- line.setLineStyle(Line.LINE_DOUBLE);
+ line.setLineDashing(LineDash.DOT);
+ line.setLineCompound(LineCompound.DOUBLE);
line.setLineWidth(8.0);
slide.addShape(line);
}
package org.apache.poi.hslf.model;
+import static org.junit.Assert.*;
+
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import junit.framework.TestCase;
-
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test <code>MovieShape</code> object.
*
* @author Yegor Kozlov
*/
-public final class TestMovieShape extends TestCase {
+public final class TestMovieShape {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+ @Test
public void testCreate() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
ppt.write(out);
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
- slide = ppt.getSlides()[0];
- shape = (MovieShape)slide.getShapes()[0];
+ slide = ppt.getSlides().get(0);
+ shape = (MovieShape)slide.getShapes().get(0);
assertEquals(path, shape.getPath());
assertFalse(shape.isAutoPlay());
}
package org.apache.poi.hslf.model;
import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
import java.awt.geom.Rectangle2D;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.InputStream;
-
-import junit.framework.TestCase;
+import java.io.*;
import org.apache.poi.POIDataSamples;
-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.hslf.usermodel.*;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.IOUtils;
+import org.junit.Test;
-public final class TestOleEmbedding extends TestCase {
+public final class TestOleEmbedding {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
/**
* Tests support for OLE objects.
*
* @throws Exception if an error occurs.
*/
+ @Test
public void testOleEmbedding2003() throws Exception {
HSLFSlideShowImpl slideShow = new HSLFSlideShowImpl(_slTests.openResourceAsStream("ole2-embedding-2003.ppt"));
// Placeholder EMFs for clients that don't support the OLE components.
//assertDigestEquals("Wrong data for object 2", "b323604b2003a7299c77c2693b641495", objects[1].getData());
}
+ @Test
public void testOLEShape() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("ole2-embedding-2003.ppt"));
- HSLFSlide slide = ppt.getSlides()[0];
- HSLFShape[] sh = slide.getShapes();
+ HSLFSlide slide = ppt.getSlides().get(0);
int cnt = 0;
- for (int i = 0; i < sh.length; i++) {
- if(sh[i] instanceof OLEShape){
+ for (HSLFShape sh : slide.getShapes()) {
+ if(sh instanceof OLEShape){
cnt++;
- OLEShape ole = (OLEShape)sh[i];
+ OLEShape ole = (OLEShape)sh;
HSLFObjectData data = ole.getObjectData();
if("Worksheet".equals(ole.getInstanceName())){
//Voila! we created a workbook from the embedded OLE data
assertEquals(2, sheet.getRow(2).getCell(0).getNumericCellValue(), 0);
assertEquals(3, sheet.getRow(3).getCell(0).getNumericCellValue(), 0);
assertEquals(8, sheet.getRow(5).getCell(0).getNumericCellValue(), 0);
+ wb.close();
} else if ("Document".equals(ole.getInstanceName())){
//creating a HWPF document
HWPFDocument doc = new HWPFDocument(data.getData());
assertEquals("Expected 2 OLE shapes", 2, cnt);
}
+ @Test
public void testEmbedding() throws Exception {
HSLFSlideShowImpl _hslfSlideShow = HSLFSlideShowImpl.create();
HSLFSlideShow ppt = new HSLFSlideShow(_hslfSlideShow);
ppt.write(bos);
ppt = new HSLFSlideShow(new ByteArrayInputStream(bos.toByteArray()));
- OLEShape comp = (OLEShape)ppt.getSlides()[0].getShapes()[0];
+ OLEShape comp = (OLEShape)ppt.getSlides().get(0).getShapes().get(0);
byte compData[] = IOUtils.toByteArray(comp.getObjectData().getData());
bos.reset();
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.junit.Test;
+
/**
* Test adding fonts to the presenataion resources
*
* @author Yegor Kozlov
*/
-public final class TestPPFont extends TestCase{
+public final class TestPPFont {
+ @Test
public void testCreate() {
HSLFSlideShow ppt = new HSLFSlideShow();
assertEquals(1, ppt.getNumberOfFonts());
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
-
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.awt.*;
-import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Before;
+import org.junit.Test;
/**
* Test drawing shapes via Graphics2D
*
* @author Yegor Kozlov
*/
-public final class TestPPGraphics2D extends TestCase {
+public final class TestPPGraphics2D {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
private HSLFSlideShow ppt;
+ @Before
protected void setUp() throws Exception {
ppt = new HSLFSlideShow(_slTests.openResourceAsStream("empty.ppt"));
}
+ @Test
public void testGraphics() throws Exception {
// Starts off empty
- assertEquals(0, ppt.getSlides().length);
+ assertTrue(ppt.getSlides().isEmpty());
// Add a slide
HSLFSlide slide = ppt.createSlide();
- assertEquals(1, ppt.getSlides().length);
+ assertEquals(1, ppt.getSlides().size());
// Add some stuff into it
HSLFGroupShape group = new HSLFGroupShape();
// And read it back in
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertEquals(1, ppt.getSlides().length);
+ assertEquals(1, ppt.getSlides().size());
- slide = ppt.getSlides()[0];
- HSLFShape[] shape = slide.getShapes();
- assertEquals(shape.length, 1); //group shape
+ slide = ppt.getSlides().get(0);
+ List<HSLFShape> shape = slide.getShapes();
+ assertEquals(shape.size(), 1); //group shape
- assertTrue(shape[0] instanceof HSLFGroupShape); //group shape
+ assertTrue(shape.get(0) instanceof HSLFGroupShape); //group shape
- group = (HSLFGroupShape)shape[0];
+ group = (HSLFGroupShape)shape.get(0);
shape = group.getShapes();
- assertEquals(shape.length, 3);
+ assertEquals(shape.size(), 3);
}
}
import org.apache.poi.POIDataSamples;
import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.util.JvmBugs;
import org.junit.Ignore;
import org.junit.Test;
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.hslf.usermodel.HSLFTextRun;
-
-import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test setting text properties of newly added TextBoxes
*
* @author Yegor Kozlov
*/
-public final class TestSetBoldItalic extends TestCase {
+public final class TestSetBoldItalic {
/**
* Verify that we can add TextBox shapes to a slide
* and set some of the style attributes
*/
+ @Test
public void testTextBoxWrite() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide sl = ppt.createSlide();
// Create a new textbox, and give it lots of properties
HSLFTextBox txtbox = new HSLFTextBox();
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
txtbox.setText(val);
rt.setFontSize(42);
rt.setBold(true);
sl.addShape(txtbox);
// Check it before save
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
- assertEquals(val, rt.getText());
- assertEquals(42, rt.getFontSize());
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
+ assertEquals(val, rt.getRawText());
+ assertEquals(42, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- sl = ppt.getSlides()[0];
+ sl = ppt.getSlides().get(0);
- txtbox = (HSLFTextBox)sl.getShapes()[0];
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
+ txtbox = (HSLFTextBox)sl.getShapes().get(0);
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
// Check after save
- assertEquals(val, rt.getText());
- assertEquals(42, rt.getFontSize());
+ assertEquals(val, rt.getRawText());
+ assertEquals(42, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
package org.apache.poi.hslf.model;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Rectangle;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import static org.junit.Assert.*;
+
+import java.awt.*;
+import java.io.*;
import java.util.ArrayList;
+import java.util.List;
import org.apache.poi.POIDataSamples;
-import org.apache.poi.ddf.EscherDgRecord;
-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.usermodel.HSLFTextRun;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
import org.junit.Before;
import org.junit.Test;
java.awt.Rectangle lineAnchor = new java.awt.Rectangle(100, 200, 50, 60);
line.setAnchor(lineAnchor);
line.setLineWidth(3);
- line.setLineStyle(Line.PEN_DASH);
+ line.setLineDashing(LineDash.DASH);
line.setLineColor(Color.red);
slide.addShape(line);
java.awt.Rectangle ellipseAnchor = new Rectangle(320, 154, 55, 111);
ellipse.setAnchor(ellipseAnchor);
ellipse.setLineWidth(2);
- ellipse.setLineStyle(Line.PEN_SOLID);
+ ellipse.setLineDashing(LineDash.SOLID);
ellipse.setLineColor(Color.green);
ellipse.setFillColor(Color.lightGray);
slide.addShape(ellipse);
//read ppt from byte array
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertEquals(1, ppt.getSlides().length);
+ assertEquals(1, ppt.getSlides().size());
- slide = ppt.getSlides()[0];
- HSLFShape[] shape = slide.getShapes();
- assertEquals(2, shape.length);
+ slide = ppt.getSlides().get(0);
+ List<HSLFShape> shape = slide.getShapes();
+ assertEquals(2, shape.size());
- assertTrue(shape[0] instanceof Line); //group shape
- assertEquals(lineAnchor, shape[0].getAnchor()); //group shape
+ assertTrue(shape.get(0) instanceof Line); //group shape
+ assertEquals(lineAnchor, shape.get(0).getAnchor()); //group shape
- assertTrue(shape[1] instanceof HSLFAutoShape); //group shape
- assertEquals(ellipseAnchor, shape[1].getAnchor()); //group shape
+ assertTrue(shape.get(1) instanceof HSLFAutoShape); //group shape
+ assertEquals(ellipseAnchor, shape.get(1).getAnchor()); //group shape
}
/**
@Test
public void textBoxRead() throws Exception {
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 HSLFTextBox);
- HSLFTextBox txtbox = (HSLFTextBox)sh[i];
+ HSLFSlide sl = ppt.getSlides().get(0);
+ for (HSLFShape sh : sl.getShapes()) {
+ assertTrue(sh instanceof HSLFTextBox);
+ HSLFTextBox txtbox = (HSLFTextBox)sh;
String text = txtbox.getText();
assertNotNull(text);
- assertEquals(txtbox.getTextParagraph().getRichTextRuns().length, 1);
- HSLFTextRun rt = txtbox.getTextParagraph().getRichTextRuns()[0];
+ assertEquals(txtbox.getTextParagraphs().get(0).getTextRuns().size(), 1);
+ HSLFTextRun rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
if (text.equals("Hello, World!!!")){
- assertEquals(32, rt.getFontSize());
+ assertEquals(32, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
} else if (text.equals("I am just a poor boy")){
- assertEquals(44, rt.getFontSize());
+ assertEquals(44, rt.getFontSize(), 0);
assertTrue(rt.isBold());
} else if (text.equals("This is Times New Roman")){
- assertEquals(16, rt.getFontSize());
+ assertEquals(16, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertTrue(rt.isUnderlined());
} else if (text.equals("Plain Text")){
- assertEquals(18, rt.getFontSize());
+ assertEquals(18, rt.getFontSize(), 0);
}
}
}
// Create a new textbox, and give it lots of properties
HSLFTextBox txtbox = new HSLFTextBox();
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
txtbox.setText(val);
rt.setFontName("Arial");
rt.setFontSize(42);
sl.addShape(txtbox);
// Check it before save
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
- assertEquals(val, rt.getText());
- assertEquals(42, rt.getFontSize());
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
+ assertEquals(val, rt.getRawText());
+ assertEquals(42, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
- assertEquals("Arial", rt.getFontName());
+ assertEquals("Arial", rt.getFontFamily());
assertEquals(Color.red, rt.getFontColor());
// Serialize and read again
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- sl = ppt.getSlides()[0];
+ sl = ppt.getSlides().get(0);
- txtbox = (HSLFTextBox)sl.getShapes()[0];
- rt = txtbox.getTextParagraph().getRichTextRuns()[0];
+ txtbox = (HSLFTextBox)sl.getShapes().get(0);
+ rt = txtbox.getTextParagraphs().get(0).getTextRuns().get(0);
// Check after save
- assertEquals(val, rt.getText());
- assertEquals(42, rt.getFontSize());
+ assertEquals(val, rt.getRawText());
+ assertEquals(42, rt.getFontSize(), 0);
assertTrue(rt.isBold());
assertTrue(rt.isItalic());
assertFalse(rt.isUnderlined());
- assertEquals("Arial", rt.getFontName());
+ assertEquals("Arial", rt.getFontFamily());
assertEquals(Color.red, rt.getFontColor());
}
*/
@Test
public void emptyTextBox() {
- assertEquals(2, pptB.getSlides().length);
- HSLFSlide s1 = pptB.getSlides()[0];
- HSLFSlide s2 = pptB.getSlides()[1];
+ assertEquals(2, pptB.getSlides().size());
+ HSLFSlide s1 = pptB.getSlides().get(0);
+ HSLFSlide s2 = pptB.getSlides().get(1);
// Check we can get the shapes count
- assertEquals(2, s1.getShapes().length);
- assertEquals(2, s2.getShapes().length);
+ assertEquals(2, s1.getShapes().size());
+ assertEquals(2, s2.getShapes().size());
}
/**
private void textBoxSet(String filename) throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream(filename));
- HSLFSlide[] sl = ppt.getSlides();
- for (int k = 0; k < sl.length; k++) {
+ for (HSLFSlide sld : ppt.getSlides()) {
ArrayList<String> lst1 = new ArrayList<String>();
- HSLFTextParagraph[] txt = sl[k].getTextRuns();
- for (int i = 0; i < txt.length; i++) {
- lst1.add(txt[i].getText());
+ for (List<HSLFTextParagraph> txt : sld.getTextParagraphs()) {
+ for (HSLFTextParagraph p : txt) {
+ for (HSLFTextRun r : p) {
+ lst1.add(r.getRawText());
+ }
+ }
}
ArrayList<String> lst2 = new ArrayList<String>();
- HSLFShape[] sh = sl[k].getShapes();
- for (int i = 0; i < sh.length; i++) {
- if (sh[i] instanceof HSLFTextShape){
- HSLFTextShape tbox = (HSLFTextShape)sh[i];
+ for (HSLFShape sh : sld.getShapes()) {
+ if (sh instanceof HSLFTextShape){
+ HSLFTextShape tbox = (HSLFTextShape)sh;
lst2.add(tbox.getText());
}
}
ppt = new HSLFSlideShow(is);
is.close();
- slide = ppt.getSlides()[0];
+ slide = ppt.getSlides().get(0);
- HSLFShape[] shape = slide.getShapes();
- assertEquals(1, shape.length);
- assertTrue(shape[0] instanceof HSLFGroupShape);
+ List<HSLFShape> shape = slide.getShapes();
+ assertEquals(1, shape.size());
+ assertTrue(shape.get(0) instanceof HSLFGroupShape);
- group = (HSLFGroupShape)shape[0];
- HSLFShape[] grshape = group.getShapes();
- assertEquals(2, grshape.length);
- assertTrue(grshape[0] instanceof HSLFPictureShape);
- assertTrue(grshape[1] instanceof Line);
+ group = (HSLFGroupShape)shape.get(0);
+ List<HSLFShape> grshape = group.getShapes();
+ assertEquals(2, grshape.size());
+ assertTrue(grshape.get(0) instanceof HSLFPictureShape);
+ assertTrue(grshape.get(1) instanceof Line);
- pict = (HSLFPictureShape)grshape[0];
+ pict = (HSLFPictureShape)grshape.get(0);
assertEquals(new Rectangle(0, 0, 200, 200), pict.getAnchor());
- line = (Line)grshape[1];
+ line = (Line)grshape.get(1);
assertEquals(new Rectangle(300, 300, 500, 0), line.getAnchor());
}
public void removeShapes() throws IOException {
String file = "with_textbox.ppt";
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);
+ HSLFSlide sl = ppt.getSlides().get(0);
+ List<HSLFShape> sh = sl.getShapes();
+ assertEquals("expected four shaped in " + file, 4, sh.size());
//remove all
- for (int i = 0; i < sh.length; i++) {
- boolean ok = sl.removeShape(sh[i]);
+ for (int i = 0; i < sh.size(); i++) {
+ boolean ok = sl.removeShape(sh.get(i));
assertTrue("Failed to delete shape #" + i, ok);
}
//now Slide.getShapes() should return an empty array
- assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().length);
+ assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size());
//serialize and read again. The file should be readable and contain no shapes
ByteArrayOutputStream out = new ByteArrayOutputStream();
out.close();
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
- sl = ppt.getSlides()[0];
- assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().length);
+ sl = ppt.getSlides().get(0);
+ assertEquals("expected 0 shaped in " + file, 0, sl.getShapes().size());
}
@Test
@Test
public void lineColor() throws IOException {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("51731.ppt"));
- HSLFShape[] shape = ppt.getSlides()[0].getShapes();
+ List<HSLFShape> shape = ppt.getSlides().get(0).getShapes();
- assertEquals(4, shape.length);
+ assertEquals(4, shape.size());
- HSLFTextShape sh1 = (HSLFTextShape)shape[0];
+ HSLFTextShape sh1 = (HSLFTextShape)shape.get(0);
assertEquals("Hello Apache POI", sh1.getText());
assertNull(sh1.getLineColor());
- HSLFTextShape sh2 = (HSLFTextShape)shape[1];
+ HSLFTextShape sh2 = (HSLFTextShape)shape.get(1);
assertEquals("Why are you showing this border?", sh2.getText());
assertNull(sh2.getLineColor());
- HSLFTextShape sh3 = (HSLFTextShape)shape[2];
+ HSLFTextShape sh3 = (HSLFTextShape)shape.get(2);
assertEquals("Text in a black border", sh3.getText());
assertEquals(Color.black, sh3.getLineColor());
assertEquals(0.75, sh3.getLineWidth(), 0);
- HSLFTextShape sh4 = (HSLFTextShape)shape[3];
+ HSLFTextShape sh4 = (HSLFTextShape)shape.get(3);
assertEquals("Border width is 5 pt", sh4.getText());
assertEquals(Color.black, sh4.getLineColor());
assertEquals(5.0, sh4.getLineWidth(), 0);
package org.apache.poi.hslf.model;
-import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.util.List;
+
+import org.apache.poi.POIDataSamples;
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.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test common functionality of the <code>Sheet</code> object.
*
* @author Yegor Kozlov
*/
-public final class TestSheet extends TestCase {
+public final class TestSheet {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
/**
* For each ppt in the test directory check that all sheets are properly initialized
*/
+ @Test
public void testSheet() throws Exception {
String[] tests = {"SampleShow.ppt", "backgrounds.ppt", "text_shapes.ppt", "pictures.ppt"};
for (String file : tests) {
}
private void doSlideShow(HSLFSlideShow ppt) {
- HSLFSlide[] slide = ppt.getSlides();
- for (int i = 0; i < slide.length; i++) {
- verify(slide[i]);
+ for (HSLFSlide slide : ppt.getSlides()) {
+ verify(slide);
- HSLFNotes notes = slide[i].getNotesSheet();
+ HSLFNotes notes = slide.getNotes();
if(notes != null) verify(notes);
- HSLFMasterSheet master = slide[i].getMasterSheet();
+ HSLFMasterSheet master = slide.getMasterSheet();
assertNotNull(master);
verify(master);
}
assertTrue(sheet._getSheetNumber() != 0);
assertTrue(sheet._getSheetRefId() != 0);
- HSLFTextParagraph[] txt = sheet.getTextRuns();
- if (txt == null) {
- throw new AssertionFailedError("no text runs");
- }
- for (int i = 0; i < txt.length; i++) {
- assertNotNull(txt[i].getSheet());
+ List<HSLFTextParagraph> txt = sheet.getTextParagraphs();
+ assertTrue("no text runs", txt != null && !txt.isEmpty());
+ for (HSLFTextParagraph t : txt) {
+ assertNotNull(t.getSheet());
}
- HSLFShape[] shape = sheet.getShapes();
- if (shape == null) {
- throw new AssertionFailedError("no shapes");
- }
- for (int i = 0; i < shape.length; i++) {
- assertNotNull(shape[i].getSpContainer());
- assertNotNull(shape[i].getSheet());
- assertNotNull(shape[i].getShapeName());
- assertNotNull(shape[i].getAnchor());
+ List<HSLFShape> shape = sheet.getShapes();
+ assertTrue("no shapes", shape != null && !shape.isEmpty());
+ for (HSLFShape s : shape) {
+ assertNotNull(s.getSpContainer());
+ assertNotNull(s.getSheet());
+ assertNotNull(s.getShapeName());
+ assertNotNull(s.getAnchor());
}
}
}
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
-import org.apache.poi.hslf.record.SlideAtom;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.record.SlideAtom;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Before;
+import org.junit.Test;
/**
* Tests that changing a slide's idea of what notes sheet is its works right
*
* @author Nick Burch (nick at torchbox dot com)
*/
-public final class TestSlideChangeNotes extends TestCase {
+public final class TestSlideChangeNotes {
// SlideShow primed on the test data
private HSLFSlideShow ss;
- public TestSlideChangeNotes() throws Exception {
+ @Before
+ public void init() throws Exception {
POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
HSLFSlideShowImpl hss = new HSLFSlideShowImpl(_slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
ss = new HSLFSlideShow(hss);
}
+ @Test
public void testSetToNone() {
- HSLFSlide slideOne = ss.getSlides()[0];
+ HSLFSlide slideOne = ss.getSlides().get(0);
SlideAtom sa = slideOne.getSlideRecord().getSlideAtom();
slideOne.setNotes(null);
assertEquals(0, sa.getNotesID());
}
+ @Test
public void testSetToSomething() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFNotes notesOne = ss.getNotes()[1];
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ HSLFNotes notesOne = ss.getNotes().get(1);
SlideAtom sa = slideOne.getSlideRecord().getSlideAtom();
slideOne.setNotes(notesOne);
package org.apache.poi.hslf.model;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.util.List;
-import junit.framework.TestCase;
-
+import org.apache.poi.POIDataSamples;
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.HSLFTextRun;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Tests for SlideMaster
*
* @author Yegor Kozlov
*/
-public final class TestSlideMaster extends TestCase{
+public final class TestSlideMaster {
private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
/**
* The reference ppt has two masters.
* Check we can read their attributes.
*/
+ @Test
public void testSlideMaster() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
Environment env = ppt.getDocumentRecord().getEnvironment();
- SlideMaster[] master = ppt.getSlidesMasters();
- assertEquals(2, master.length);
+ List<HSLFSlideMaster> master = ppt.getSlideMasters();
+ assertEquals(2, master.size());
//character attributes
- assertEquals(40, master[0].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
- assertEquals(48, master[1].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
+ assertEquals(40, master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
+ assertEquals(48, master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.size", true).getValue());
- int font1 = master[0].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
- int font2 = master[1].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
+ int font1 = master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
+ int font2 = master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "font.index", true).getValue();
assertEquals("Arial", env.getFontCollection().getFontWithId(font1));
assertEquals("Georgia", env.getFontCollection().getFontWithId(font2));
- CharFlagsTextProp prop1 = (CharFlagsTextProp)master[0].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
+ CharFlagsTextProp prop1 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
- CharFlagsTextProp prop2 = (CharFlagsTextProp)master[1].getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
+ CharFlagsTextProp prop2 = (CharFlagsTextProp)master.get(1).getStyleAttribute(TextHeaderAtom.TITLE_TYPE, 0, "char_flags", true);
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(true, prop2.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
//now paragraph attributes
- assertEquals(0x266B, master[0].getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
- assertEquals(0x2022, master[1].getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
+ assertEquals(0x266B, master.get(0).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
+ assertEquals(0x2022, master.get(1).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.char", false).getValue());
- int b1 = master[0].getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
- int b2 = master[1].getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
+ int b1 = master.get(0).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
+ int b2 = master.get(1).getStyleAttribute(TextHeaderAtom.BODY_TYPE, 0, "bullet.font", false).getValue();
assertEquals("Arial", env.getFontCollection().getFontWithId(b1));
assertEquals("Georgia", env.getFontCollection().getFontWithId(b2));
}
/**
* Test we can read default text attributes for a title master sheet
*/
+ @Test
public void testTitleMasterTextAttributes() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- TitleMaster[] master = ppt.getTitleMasters();
- assertEquals(1, master.length);
+ List<HSLFTitleMaster> master = ppt.getTitleMasters();
+ assertEquals(1, master.size());
- assertEquals(32, master[0].getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "font.size", true).getValue());
- CharFlagsTextProp prop1 = (CharFlagsTextProp)master[0].getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "char_flags", true);
+ assertEquals(32, master.get(0).getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "font.size", true).getValue());
+ CharFlagsTextProp prop1 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.CENTER_TITLE_TYPE, 0, "char_flags", true);
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop1.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(true, prop1.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
- assertEquals(20, master[0].getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "font.size", true).getValue());
- CharFlagsTextProp prop2 = (CharFlagsTextProp)master[0].getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "char_flags", true);
+ assertEquals(20, master.get(0).getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "font.size", true).getValue());
+ CharFlagsTextProp prop2 = (CharFlagsTextProp)master.get(0).getStyleAttribute(TextHeaderAtom.CENTRE_BODY_TYPE, 0, "char_flags", true);
assertEquals(true, prop2.getSubValue(CharFlagsTextProp.BOLD_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.ITALIC_IDX));
assertEquals(false, prop2.getSubValue(CharFlagsTextProp.UNDERLINE_IDX));
/**
* Slide 3 has title layout and follows the TitleMaster. Verify that.
*/
+ @Test
public void testTitleMaster() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- HSLFSlide slide = ppt.getSlides()[2];
+ HSLFSlide slide = ppt.getSlides().get(2);
HSLFMasterSheet masterSheet = slide.getMasterSheet();
- assertTrue(masterSheet instanceof TitleMaster);
+ assertTrue(masterSheet instanceof HSLFTitleMaster);
- HSLFTextParagraph[] txt = slide.getTextRuns();
- for (int i = 0; i < txt.length; i++) {
- HSLFTextRun rt = txt[i].getRichTextRuns()[0];
- switch(txt[i].getRunType()){
+ List<HSLFTextParagraph> txt = slide.getTextParagraphs();
+ for (int i = 0; i < txt.size(); i++) {
+ HSLFTextRun rt = txt.get(i).getTextRuns().get(0);
+ switch(txt.get(i).getRunType()){
case TextHeaderAtom.CENTER_TITLE_TYPE:
- assertEquals("Arial", rt.getFontName());
- assertEquals(32, rt.getFontSize());
+ assertEquals("Arial", rt.getFontFamily());
+ assertEquals(32, rt.getFontSize(), 0);
assertEquals(true, rt.isBold());
assertEquals(true, rt.isUnderlined());
break;
case TextHeaderAtom.CENTRE_BODY_TYPE:
- assertEquals("Courier New", rt.getFontName());
- assertEquals(20, rt.getFontSize());
+ assertEquals("Courier New", rt.getFontFamily());
+ assertEquals(20, rt.getFontSize(), 0);
assertEquals(true, rt.isBold());
assertEquals(false, rt.isUnderlined());
break;
/**
* If a style attribute is not set ensure it is read from the master
*/
+ @Test
public void testMasterAttributes() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- HSLFSlide[] slide = ppt.getSlides();
- assertEquals(3, slide.length);
- HSLFTextParagraph[] trun;
-
- trun = slide[0].getTextRuns();
- for (int i = 0; i < trun.length; i++) {
- if (trun[i].getRunType() == TextHeaderAtom.TITLE_TYPE){
- HSLFTextRun rt = trun[i].getRichTextRuns()[0];
- assertEquals(40, rt.getFontSize());
+ List<HSLFSlide> slide = ppt.getSlides();
+ assertEquals(3, slide.size());
+ for (HSLFTextParagraph trun : slide.get(0).getTextParagraphs()) {
+ if (trun.getRunType() == TextHeaderAtom.TITLE_TYPE){
+ HSLFTextRun rt = trun.getTextRuns().get(0);
+ assertEquals(40, rt.getFontSize(), 0);
assertEquals(true, rt.isUnderlined());
- assertEquals("Arial", rt.getFontName());
- } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){
- HSLFTextRun rt;
- rt = trun[i].getRichTextRuns()[0];
- assertEquals(0, rt.getIndentLevel());
- assertEquals(32, rt.getFontSize());
- assertEquals("Arial", rt.getFontName());
-
- rt = trun[i].getRichTextRuns()[1];
- assertEquals(1, rt.getIndentLevel());
- assertEquals(28, rt.getFontSize());
- assertEquals("Arial", rt.getFontName());
+ assertEquals("Arial", rt.getFontFamily());
+ } else if (trun.getRunType() == TextHeaderAtom.BODY_TYPE){
+ HSLFTextRun rt = trun.getTextRuns().get(0);
+ assertEquals(0, trun.getIndentLevel());
+ assertEquals(32, rt.getFontSize(), 0);
+ assertEquals("Arial", rt.getFontFamily());
+
+ rt = trun.getTextRuns().get(1);
+ assertEquals(1, trun.getIndentLevel());
+ assertEquals(28, rt.getFontSize(), 0);
+ assertEquals("Arial", rt.getFontFamily());
}
}
- trun = slide[1].getTextRuns();
- for (int i = 0; i < trun.length; i++) {
- if (trun[i].getRunType() == TextHeaderAtom.TITLE_TYPE){
- HSLFTextRun rt = trun[i].getRichTextRuns()[0];
- assertEquals(48, rt.getFontSize());
+ ;
+ for (HSLFTextParagraph trun : slide.get(1).getTextParagraphs()) {
+ if (trun.getRunType() == TextHeaderAtom.TITLE_TYPE){
+ HSLFTextRun rt = trun.getTextRuns().get(0);
+ assertEquals(48, rt.getFontSize(), 0);
assertEquals(true, rt.isItalic());
- assertEquals("Georgia", rt.getFontName());
- } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){
+ assertEquals("Georgia", rt.getFontFamily());
+ } else if (trun.getRunType() == TextHeaderAtom.BODY_TYPE){
HSLFTextRun rt;
- rt = trun[i].getRichTextRuns()[0];
- assertEquals(0, rt.getIndentLevel());
- assertEquals(32, rt.getFontSize());
- assertEquals("Courier New", rt.getFontName());
+ rt = trun.getTextRuns().get(0);
+ assertEquals(0, trun.getIndentLevel());
+ assertEquals(32, rt.getFontSize(), 0);
+ assertEquals("Courier New", rt.getFontFamily());
}
}
/**
* Check we can dynamically assign a slide master to a slide.
*/
+ @Test
public void testChangeSlideMaster() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("slide_master.ppt"));
- SlideMaster[] master = ppt.getSlidesMasters();
- HSLFSlide[] slide = ppt.getSlides();
+ List<HSLFSlideMaster> master = ppt.getSlideMasters();
+ List<HSLFSlide> slide = ppt.getSlides();
int sheetNo;
//each slide uses its own master
- assertEquals(slide[0].getMasterSheet()._getSheetNumber(), master[0]._getSheetNumber());
- assertEquals(slide[1].getMasterSheet()._getSheetNumber(), master[1]._getSheetNumber());
+ assertEquals(slide.get(0).getMasterSheet()._getSheetNumber(), master.get(0)._getSheetNumber());
+ assertEquals(slide.get(1).getMasterSheet()._getSheetNumber(), master.get(1)._getSheetNumber());
//all slides use the first master slide
- sheetNo = master[0]._getSheetNumber();
- for (int i = 0; i < slide.length; i++) {
- slide[i].setMasterSheet(master[0]);
+ sheetNo = master.get(0)._getSheetNumber();
+ for (HSLFSlide s : slide) {
+ s.setMasterSheet(master.get(0));
}
ByteArrayOutputStream out;
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- master = ppt.getSlidesMasters();
+ master = ppt.getSlideMasters();
slide = ppt.getSlides();
- for (int i = 0; i < slide.length; i++) {
- assertEquals(sheetNo, slide[i].getMasterSheet()._getSheetNumber());
+ for (HSLFSlide s : slide) {
+ assertEquals(sheetNo, s.getMasterSheet()._getSheetNumber());
}
}
* Varify we can read attrubutes for different identtation levels.
* (typical for the "bullted body" placeholder)
*/
+ @Test
public void testIndentation() throws Exception {
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){
- HSLFTextRun rt = trun[i].getRichTextRuns()[0];
- assertEquals(40, rt.getFontSize());
+ HSLFSlide slide = ppt.getSlides().get(0);
+
+ for (HSLFTextParagraph trun : slide.getTextParagraphs()) {
+ if (trun.getRunType() == TextHeaderAtom.TITLE_TYPE){
+ HSLFTextRun rt = trun.getTextRuns().get(0);
+ assertEquals(40, rt.getFontSize(), 0);
assertEquals(true, rt.isUnderlined());
- assertEquals("Arial", rt.getFontName());
- } else if (trun[i].getRunType() == TextHeaderAtom.BODY_TYPE){
- HSLFTextRun[] rt = trun[i].getRichTextRuns();
- for (int j = 0; j < rt.length; j++) {
- int indent = rt[j].getIndentLevel();
- switch (indent){
- case 0:
- assertEquals(32, rt[j].getFontSize());
- break;
- case 1:
- assertEquals(28, rt[j].getFontSize());
- break;
- case 2:
- assertEquals(24, rt[j].getFontSize());
- break;
- }
+ assertEquals("Arial", rt.getFontFamily());
+ } else if (trun.getRunType() == TextHeaderAtom.BODY_TYPE){
+ int indents[] = { 32, 28, 24 };
+ for (HSLFTextRun rt : trun.getTextRuns()) {
+ int indent = trun.getIndentLevel();
+ assertEquals(indents[indent], rt.getFontSize(), 0);
}
}
}
package org.apache.poi.hslf.model;
-import junit.framework.TestCase;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
-
-import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test adding new slides to a ppt.
* stuff does
* @author Yegor Kozlov
*/
-public final class TestSlides extends TestCase {
+public final class TestSlides {
/**
* Add 1 slide to an empty ppt.
* @throws Exception
*/
+ @Test
public void testAddSlides1() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") ));
- assertTrue(ppt.getSlides().length == 0);
+ assertTrue(ppt.getSlides().isEmpty());
HSLFSlide s1 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 1);
+ assertEquals(1, ppt.getSlides().size());
assertEquals(3, s1._getSheetRefId());
assertEquals(256, s1._getSheetNumber());
assertEquals(1, s1.getSlideNumber());
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertTrue(ppt.getSlides().length == 1);
+ assertEquals(1, ppt.getSlides().size());
}
/**
* Add 2 slides to an empty ppt
* @throws Exception
*/
+ @Test
public void testAddSlides2() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") ));
- assertTrue(ppt.getSlides().length == 0);
+ assertTrue(ppt.getSlides().isEmpty());
HSLFSlide s1 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 1);
+ assertEquals(1, ppt.getSlides().size());
assertEquals(3, s1._getSheetRefId());
assertEquals(256, s1._getSheetNumber());
assertEquals(1, s1.getSlideNumber());
HSLFSlide s2 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 2);
+ assertEquals(2, ppt.getSlides().size());
assertEquals(4, s2._getSheetRefId());
assertEquals(257, s2._getSheetNumber());
assertEquals(2, s2.getSlideNumber());
//serialize and read again
- ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
ppt.write(out);
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertTrue(ppt.getSlides().length == 2);
+ assertEquals(2, ppt.getSlides().size());
}
/**
* Add 3 slides to an empty ppt
* @throws Exception
*/
+ @Test
public void testAddSlides3() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(new HSLFSlideShowImpl( TestSlides.class.getResourceAsStream("/org/apache/poi/hslf/data/empty.ppt") ));
- assertTrue(ppt.getSlides().length == 0);
+ assertTrue(ppt.getSlides().isEmpty());
HSLFSlide s1 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 1);
+ assertEquals(1, ppt.getSlides().size());
assertEquals(3, s1._getSheetRefId());
assertEquals(256, s1._getSheetNumber());
assertEquals(1, s1.getSlideNumber());
HSLFSlide s2 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 2);
+ assertEquals(2, ppt.getSlides().size());
assertEquals(4, s2._getSheetRefId());
assertEquals(257, s2._getSheetNumber());
assertEquals(2, s2.getSlideNumber());
HSLFSlide s3 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 3);
+ assertEquals(3, ppt.getSlides().size());
assertEquals(5, s3._getSheetRefId());
assertEquals(258, s3._getSheetNumber());
assertEquals(3, s3.getSlideNumber());
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertTrue(ppt.getSlides().length == 3);
+ assertEquals(3, ppt.getSlides().size());
// Check IDs are still right
- s1 = ppt.getSlides()[0];
+ s1 = ppt.getSlides().get(0);
assertEquals(256, s1._getSheetNumber());
assertEquals(3, s1._getSheetRefId());
- s2 = ppt.getSlides()[1];
+ s2 = ppt.getSlides().get(1);
assertEquals(257, s2._getSheetNumber());
assertEquals(4, s2._getSheetRefId());
- s3 = ppt.getSlides()[2];;
- assertTrue(ppt.getSlides().length == 3);
+ s3 = ppt.getSlides().get(2);;
+ assertEquals(3, ppt.getSlides().size());
assertEquals(258, s3._getSheetNumber());
assertEquals(5, s3._getSheetRefId());
}
/**
* Add slides to ppt which already has two slides
*/
+ @Test
public void testAddSlides2to3() throws Exception {
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
- assertTrue(ppt.getSlides().length == 2);
+ assertEquals(2, ppt.getSlides().size());
// First slide is 256 / 4
- HSLFSlide s1 = ppt.getSlides()[0];
+ HSLFSlide s1 = ppt.getSlides().get(0);
assertEquals(256, s1._getSheetNumber());
assertEquals(4, s1._getSheetRefId());
// Last slide is 257 / 6
- HSLFSlide s2 = ppt.getSlides()[1];
+ HSLFSlide s2 = ppt.getSlides().get(1);
assertEquals(257, s2._getSheetNumber());
assertEquals(6, s2._getSheetRefId());
// Add another slide, goes in at the end
HSLFSlide s3 = ppt.createSlide();
- assertTrue(ppt.getSlides().length == 3);
+ assertEquals(3, ppt.getSlides().size());
assertEquals(258, s3._getSheetNumber());
assertEquals(8, s3._getSheetRefId());
out.close();
ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
- assertTrue(ppt.getSlides().length == 3);
+ assertEquals(3, ppt.getSlides().size());
// Check IDs are still right
- s1 = ppt.getSlides()[0];
+ s1 = ppt.getSlides().get(0);
assertEquals(256, s1._getSheetNumber());
assertEquals(4, s1._getSheetRefId());
- s2 = ppt.getSlides()[1];
+ s2 = ppt.getSlides().get(1);
assertEquals(257, s2._getSheetNumber());
assertEquals(6, s2._getSheetRefId());
- s3 = ppt.getSlides()[2];;
- assertTrue(ppt.getSlides().length == 3);
+ s3 = ppt.getSlides().get(2);
+ assertEquals(3, ppt.getSlides().size());
assertEquals(258, s3._getSheetNumber());
assertEquals(8, s3._getSheetRefId());
}
package org.apache.poi.hslf.model;
+import static org.junit.Assert.*;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-
-import junit.framework.TestCase;
+import java.util.List;
import org.apache.poi.hslf.record.TextHeaderAtom;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Test;
/**
* Test <code>Table</code> object.
*
* @author Yegor Kozlov
*/
-public final class TestTable extends TestCase {
+public final class TestTable {
/**
* Test that ShapeFactory works properly and returns <code>Table</code>
*/
+ @Test
public void testShapeFactory() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow();
TableCell cell = tbl.getCell(0, 0);
//table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033
- assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraph().getRunType());
+ assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType());
- assertTrue(slide.getShapes()[0] instanceof Table);
- Table tbl2 = (Table)slide.getShapes()[0];
+ assertTrue(slide.getShapes().get(0) instanceof Table);
+ Table tbl2 = (Table)slide.getShapes().get(0);
assertEquals(tbl.getNumberOfColumns(), tbl2.getNumberOfColumns());
assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows());
out.close();
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
- slide = ppt.getSlides()[0];
- assertTrue(slide.getShapes()[0] instanceof Table);
- Table tbl3 = (Table)slide.getShapes()[0];
+ slide = ppt.getSlides().get(0);
+ assertTrue(slide.getShapes().get(0) instanceof Table);
+ Table tbl3 = (Table)slide.getShapes().get(0);
assertEquals(tbl.getNumberOfColumns(), tbl3.getNumberOfColumns());
assertEquals(tbl.getNumberOfRows(), tbl3.getNumberOfRows());
}
/**
* Error constructing Table when rownum=1
*/
+ @Test
public void test45889(){
HSLFSlideShow ppt = new HSLFSlideShow();
HSLFSlide slide = ppt.createSlide();
- HSLFShape[] shapes;
+ List<HSLFShape> shapes;
Table tbl1 = new Table(1, 5);
assertEquals(5, tbl1.getNumberOfColumns());
assertEquals(1, tbl1.getNumberOfRows());
slide.addShape(tbl1);
shapes = slide.getShapes();
- assertEquals(1, shapes.length);
+ assertEquals(1, shapes.size());
- Table tbl2 = (Table)shapes[0];
+ Table tbl2 = (Table)shapes.get(0);
assertSame(tbl1.getSpContainer(), tbl2.getSpContainer());
assertEquals(tbl1.getNumberOfColumns(), tbl2.getNumberOfColumns());
assertEquals(tbl1.getNumberOfRows(), tbl2.getNumberOfRows());
}
+ @Test
public void testIllegalCOnstruction(){
try {
new Table(0, 5);
+++ /dev/null
-/* ====================================================================
- 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.*;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hslf.model.textproperties.TextPropCollection;
-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.HSLFTextRun;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.POIDataSamples;
-
-/**
- * Tests for TextRuns
- *
- * @author Nick Burch (nick at torchbox dot com)
- */
-public final class TestTextRun extends TestCase {
- private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
-
- // SlideShow primed on the test data
- private HSLFSlideShow ss;
- private HSLFSlideShow ssRich;
-
- protected void setUp() throws IOException {
-
- // Basic (non rich) test file
- ss = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
-
- // Rich test file
- ssRich = new HSLFSlideShow(_slTests.openResourceAsStream("Single_Coloured_Page.ppt"));
- }
-
- /**
- * Test to ensure that getting the text works correctly
- */
- public void testGetText() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
-
- assertEquals(2, textRuns.length);
-
- // Get text works with \n
- assertEquals("This is a test title", textRuns[0].getText());
- assertEquals("This is a test subtitle\nThis is on page 1", textRuns[1].getText());
-
- // Raw text has \r instead
- assertEquals("This is a test title", textRuns[0].getRawText());
- assertEquals("This is a test subtitle\rThis is on page 1", textRuns[1].getRawText());
-
-
- // Now check on a rich text run
- 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());
- assertEquals("This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)", textRunsR[1].getText());
- assertEquals("This is a title, it\u2019s in black", textRunsR[0].getRawText());
- assertEquals("This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)", textRunsR[1].getRawText());
- }
-
- /**
- * Test to ensure changing non rich text bytes->bytes works correctly
- */
- public void testSetText() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextParagraph run = textRuns[0];
-
- // Check current text
- assertEquals("This is a test title", run.getText());
-
- // Change
- String changeTo = "New test title";
- run.setText(changeTo);
- assertEquals(changeTo, run.getText());
-
- // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r'
- run.setText(changeTo + "\n");
- assertEquals(changeTo + "\n", run.getText());
- }
-
- /**
- * Test to ensure that changing non rich text between bytes and
- * chars works correctly
- */
- public void testAdvancedSetText() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph run = slideOne.getTextRuns()[0];
-
- TextHeaderAtom tha = run._headerAtom;
- TextBytesAtom tba = run._byteAtom;
- TextCharsAtom tca = run._charAtom;
-
- // Bytes -> Bytes
- assertNull(tca);
- assertNotNull(tba);
- assertFalse(run._isUnicode);
- assertEquals("This is a test title", run.getText());
-
- String changeBytesOnly = "New Test Title";
- run.setText(changeBytesOnly);
- tba = run._byteAtom;
- tca = run._charAtom;
-
- assertEquals(changeBytesOnly, run.getText());
- assertFalse(run._isUnicode);
- assertNull(tca);
- assertNotNull(tba);
-
- // Bytes -> Chars
- assertNull(tca);
- assertNotNull(tba);
- assertFalse(run._isUnicode);
- assertEquals(changeBytesOnly, run.getText());
-
- String changeByteChar = "This is a test title with a '\u0121' g with a dot";
- run.setText(changeByteChar);
- tba = run._byteAtom;
- tca = run._charAtom;
-
- assertEquals(changeByteChar, run.getText());
- assertTrue(run._isUnicode);
- assertNotNull(tca);
- assertNull(tba);
-
- // Chars -> Chars
- assertNull(tba);
- assertNotNull(tca);
- assertTrue(run._isUnicode);
- assertEquals(changeByteChar, run.getText());
-
- String changeCharChar = "This is a test title with a '\u0147' N with a hat";
- run.setText(changeCharChar);
- tba = run._byteAtom;
- tca = run._charAtom;
-
- assertEquals(changeCharChar, run.getText());
- assertTrue(run._isUnicode);
- assertNotNull(tca);
- assertNull(tba);
- }
-
- /**
- * Tests to ensure that non rich text has the right default rich text run
- * set up for it
- */
- public void testGetRichTextNonRich() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
-
- assertEquals(2, textRuns.length);
-
- HSLFTextParagraph trA = textRuns[0];
- HSLFTextParagraph trB = textRuns[1];
-
- assertEquals(1, trA.getRichTextRuns().length);
- assertEquals(1, trB.getRichTextRuns().length);
-
- HSLFTextRun rtrA = trA.getRichTextRuns()[0];
- HSLFTextRun rtrB = trB.getRichTextRuns()[0];
-
- assertEquals(trA.getText(), rtrA.getText());
- assertEquals(trB.getText(), rtrB.getText());
-
- assertNull(rtrA._getRawCharacterStyle());
- assertNull(rtrA._getRawParagraphStyle());
- assertNull(rtrB._getRawCharacterStyle());
- assertNull(rtrB._getRawParagraphStyle());
- }
-
- /**
- * Tests to ensure that the rich text runs are built up correctly
- */
- public void testGetRichText() {
- HSLFSlide slideOne = ssRich.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
-
- assertEquals(2, textRuns.length);
-
- HSLFTextParagraph trA = textRuns[0];
- HSLFTextParagraph trB = textRuns[1];
-
- assertEquals(1, trA.getRichTextRuns().length);
- assertEquals(3, trB.getRichTextRuns().length);
-
- 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());
-
- assertEquals(trB.getText().substring(0, 30), rtrB.getText());
- assertEquals(trB.getText().substring(30,58), rtrC.getText());
- assertEquals(trB.getText().substring(58,82), rtrD.getText());
-
- assertNull(rtrA._getRawCharacterStyle());
- assertNull(rtrA._getRawParagraphStyle());
- assertNotNull(rtrB._getRawCharacterStyle());
- assertNotNull(rtrB._getRawParagraphStyle());
- assertNotNull(rtrC._getRawCharacterStyle());
- assertNotNull(rtrC._getRawParagraphStyle());
- assertNotNull(rtrD._getRawCharacterStyle());
- assertNotNull(rtrD._getRawParagraphStyle());
-
- // Same paragraph styles
- assertEquals(rtrB._getRawParagraphStyle(), rtrC._getRawParagraphStyle());
- assertEquals(rtrB._getRawParagraphStyle(), rtrD._getRawParagraphStyle());
-
- // Different char styles
- assertFalse( rtrB._getRawCharacterStyle().equals( rtrC._getRawCharacterStyle() ));
- assertFalse( rtrB._getRawCharacterStyle().equals( rtrD._getRawCharacterStyle() ));
- assertFalse( rtrC._getRawCharacterStyle().equals( rtrD._getRawCharacterStyle() ));
- }
-
- /**
- * Tests to ensure that setting the text where the text isn't rich,
- * ensuring that everything stays with the same default styling
- */
- public void testSetTextWhereNotRich() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextParagraph trB = textRuns[1];
- assertEquals(1, trB.getRichTextRuns().length);
-
- HSLFTextRun rtrB = trB.getRichTextRuns()[0];
- assertEquals(trB.getText(), rtrB.getText());
- assertNull(rtrB._getRawCharacterStyle());
- assertNull(rtrB._getRawParagraphStyle());
-
- // Change text via normal
- trB.setText("Test Foo Test");
- rtrB = trB.getRichTextRuns()[0];
- assertEquals("Test Foo Test", trB.getText());
- assertEquals("Test Foo Test", rtrB.getText());
- assertNull(rtrB._getRawCharacterStyle());
- assertNull(rtrB._getRawParagraphStyle());
- }
-
- /**
- * Tests to ensure that setting the text where the text is rich
- * sets everything to the same styling
- */
- public void testSetTextWhereRich() {
- HSLFSlide slideOne = ssRich.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextParagraph trB = textRuns[1];
- assertEquals(3, trB.getRichTextRuns().length);
-
- 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();
- TextPropCollection tpCC = rtrC._getRawCharacterStyle();
- TextPropCollection tpDP = rtrD._getRawParagraphStyle();
- TextPropCollection tpDC = rtrD._getRawCharacterStyle();
-
- assertEquals(trB.getText().substring(0, 30), rtrB.getText());
- assertNotNull(tpBP);
- assertNotNull(tpBC);
- assertNotNull(tpCP);
- assertNotNull(tpCC);
- assertNotNull(tpDP);
- assertNotNull(tpDC);
- assertTrue(tpBP.equals(tpCP));
- assertTrue(tpBP.equals(tpDP));
- assertTrue(tpCP.equals(tpDP));
- assertFalse(tpBC.equals(tpCC));
- assertFalse(tpBC.equals(tpDC));
- assertFalse(tpCC.equals(tpDC));
-
- // Change text via normal
- trB.setText("Test Foo Test");
-
- // Ensure now have first style
- assertEquals(1, trB.getRichTextRuns().length);
- rtrB = trB.getRichTextRuns()[0];
- assertEquals("Test Foo Test", trB.getText());
- assertEquals("Test Foo Test", rtrB.getText());
- assertNotNull(rtrB._getRawCharacterStyle());
- assertNotNull(rtrB._getRawParagraphStyle());
- assertEquals( tpBP, rtrB._getRawParagraphStyle() );
- assertEquals( tpBC, rtrB._getRawCharacterStyle() );
- }
-
- /**
- * Test to ensure the right stuff happens if we change the text
- * in a rich text run, that doesn't happen to actually be rich
- */
- public void testChangeTextInRichTextRunNonRich() {
- HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextParagraph trB = textRuns[1];
- assertEquals(1, trB.getRichTextRuns().length);
-
- HSLFTextRun rtrB = trB.getRichTextRuns()[0];
- assertEquals(trB.getText(), rtrB.getText());
- assertNull(rtrB._getRawCharacterStyle());
- assertNull(rtrB._getRawParagraphStyle());
-
- // Change text via rich
- rtrB.setText("Test Test Test");
- assertEquals("Test Test Test", trB.getText());
- assertEquals("Test Test Test", rtrB.getText());
-
- // Will now have dummy props
- assertNotNull(rtrB._getRawCharacterStyle());
- assertNotNull(rtrB._getRawParagraphStyle());
- }
-
- /**
- * Tests to ensure changing the text within rich text runs works
- * correctly
- */
- public void testChangeTextInRichTextRun() {
- 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
- 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();
- TextPropCollection tpCC = rtrC._getRawCharacterStyle();
- TextPropCollection tpDP = rtrD._getRawParagraphStyle();
- TextPropCollection tpDC = rtrD._getRawCharacterStyle();
-
- // Check text and stylings
- assertEquals(trB.getText().substring(0, 30), rtrB.getText());
- assertNotNull(tpBP);
- assertNotNull(tpBC);
- assertNotNull(tpCP);
- assertNotNull(tpCC);
- assertNotNull(tpDP);
- assertNotNull(tpDC);
- assertTrue(tpBP.equals(tpCP));
- assertTrue(tpBP.equals(tpDP));
- assertTrue(tpCP.equals(tpDP));
- assertFalse(tpBC.equals(tpCC));
- assertFalse(tpBC.equals(tpDC));
- assertFalse(tpCC.equals(tpDC));
-
- // Check text in the rich runs
- assertEquals("This is the subtitle, in bold\n", rtrB.getText());
- assertEquals("This bit is blue and italic\n", rtrC.getText());
- assertEquals("This bit is red (normal)", rtrD.getText());
-
- String newBText = "New Subtitle, will still be bold\n";
- String newCText = "New blue and italic text\n";
- String newDText = "Funky new normal red text";
- rtrB.setText(newBText);
- rtrC.setText(newCText);
- rtrD.setText(newDText);
- assertEquals(newBText, rtrB.getText());
- assertEquals(newCText, rtrC.getText());
- assertEquals(newDText, rtrD.getText());
-
- assertEquals(newBText + newCText + newDText, trB.getText());
-
- // The styles should have been updated for the new sizes
- assertEquals(newBText.length(), tpBC.getCharactersCovered());
- assertEquals(newCText.length(), tpCC.getCharactersCovered());
- assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger
-
- assertEquals(
- newBText.length() + newCText.length() + newDText.length(),
- tpBP.getCharactersCovered()
- );
-
- // Paragraph style should be sum of text length
- assertEquals(newBText.length() + newCText.length() + newDText.length(), tpBP.getCharactersCovered());
-
- // Check stylings still as expected
- TextPropCollection ntpBC = rtrB._getRawCharacterStyle();
- TextPropCollection ntpCC = rtrC._getRawCharacterStyle();
- TextPropCollection ntpDC = rtrD._getRawCharacterStyle();
- assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
- assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
- assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
- }
-
-
- /**
- * Test case for Bug 41015.
- *
- * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because
- * of the wrong list of potential paragraph properties defined in StyleTextPropAtom.
- *
- */
- public void testBug41015() throws IOException {
- HSLFTextRun[] rt;
-
- 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();
- assertEquals(1, rt.length);
- assertEquals(0, rt[0].getIndentLevel());
- assertEquals("sdfsdfsdf", rt[0].getText());
-
- rt = txt[1].getRichTextRuns();
- assertEquals(2, rt.length);
- assertEquals(0, rt[0].getIndentLevel());
- assertEquals("Sdfsdfsdf\n" +
- "Dfgdfg\n" +
- "Dfgdfgdfg\n", rt[0].getText());
- assertEquals(1, rt[1].getIndentLevel());
- assertEquals("Sdfsdfs\n" +
- "Sdfsdf\n", rt[1].getText());
- }
-
- /**
- * Test creation of TextRun objects.
- */
- public void testAddTextRun() {
- HSLFSlideShow ppt = new HSLFSlideShow();
- HSLFSlide slide = ppt.createSlide();
-
- assertNull(slide.getTextRuns());
-
- 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.
- HSLFTextParagraph[] runs = slide.getTextRuns();
- assertNotNull(runs);
- assertSame(run1, runs[0]);
-
- HSLFTextBox shape2 = new HSLFTextBox();
- HSLFTextParagraph run2 = shape2.getTextParagraph();
- assertSame(run2, shape2.createTextRun());
- run2.setText("Text 2");
- slide.addShape(shape2);
-
- runs = slide.getTextRuns();
- assertEquals(2, runs.length);
-
- assertSame(run1, runs[0]);
- assertSame(run2, runs[1]);
-
- //as getShapes()
- HSLFShape[] sh = slide.getShapes();
- assertEquals(2, sh.length);
- 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
- HSLFSlide slide2 = ppt.createSlide();
- assertNull(slide2.getTextRuns());
- Table table = new Table(2, 2);
- slide2.addShape(table);
- runs = slide2.getTextRuns();
- assertNotNull(runs);
- assertEquals(4, runs.length);
- }
-
- public void test48916() throws IOException {
- HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt"));
- for(HSLFSlide slide : ppt.getSlides()){
- for(HSLFShape sh : slide.getShapes()){
- 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();
- assertEquals(runChildren.length, txboxChildren.length);
- for(int i=0; i < txboxChildren.length; i++){
- assertSame(txboxChildren[i], runChildren[i]);
- }
- //caused NPE prior to fix of Bugzilla #48916
- run.getRichTextRuns()[0].setBold(true);
- run.getRichTextRuns()[0].setFontColor(Color.RED);
- }
- }
- }
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ppt.write(out);
- ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
- for(HSLFSlide slide : ppt.getSlides()){
- for(HSLFShape sh : slide.getShapes()){
- 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);
- }
- }
- }
-
- }
-
- public void test52244() throws IOException {
- 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());
-
- assertEquals("Arial", runs[1].getRichTextRuns()[0].getFontName());
- assertEquals(24, runs[1].getRichTextRuns()[0].getFontSize());
-
- assertEquals("Arial", runs[2].getRichTextRuns()[0].getFontName());
- assertEquals(32, runs[2].getRichTextRuns()[0].getFontSize());
-
- }
-
-}
package org.apache.poi.hslf.model;
+import static org.junit.Assert.assertEquals;
-import junit.framework.TestCase;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
-import java.io.*;
-
-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;
+import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.junit.Before;
+import org.junit.Test;
/**
* Tests that if we load something up, get a TextRun, set the text
*
* @author Nick Burch (nick at torchbox dot com)
*/
-public final class TestTextRunReWrite extends TestCase {
+public final class TestTextRunReWrite {
// HSLFSlideShow primed on the test data
private HSLFSlideShowImpl hss;
// HSLFSlideShow primed on the test data
/**
* Load up a test PPT file with rich data
*/
+ @Before
public void setUp() throws Exception {
POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
String filename = "Single_Coloured_Page_With_Fonts_and_Alignments.ppt";
ss = new HSLFSlideShow(hss);
}
- public void testWritesOutTheSameNonRich() throws Exception {
+ @Test
+ public void testWritesOutTheSameNonRich() throws Exception {
// Grab the first text run on the first sheet
- HSLFTextParagraph tr1 = ss.getSlides()[0].getTextRuns()[0];
- HSLFTextParagraph tr2 = ss.getSlides()[0].getTextRuns()[1];
+ HSLFTextParagraph tr1 = ss.getSlides().get(0).getTextParagraphs().get(0);
+ HSLFTextParagraph tr2 = ss.getSlides().get(0).getTextParagraphs().get(1);
// Ensure the text lengths are as we'd expect to start with
assertEquals(1, ss.getSlides().length);
- assertEquals(2, ss.getSlides()[0].getTextRuns().length);
- assertEquals(30, tr1.getText().length());
- assertEquals(179, tr2.getText().length());
+ assertEquals(2, ss.getSlides().get(0).getTextParagraphs().length);
+ assertEquals(30, tr1.getRawText().length());
+ assertEquals(179, tr2.getRawText().length());
- assertEquals(1, tr1.getRichTextRuns().length);
- assertEquals(30, tr1.getRichTextRuns()[0].getLength());
- assertEquals(30, tr1.getRichTextRuns()[0].getText().length());
- assertEquals(31, tr1.getRichTextRuns()[0]._getRawCharacterStyle().getCharactersCovered());
- assertEquals(31, tr1.getRichTextRuns()[0]._getRawParagraphStyle().getCharactersCovered());
+ assertEquals(1, tr1.getTextRuns().length);
+ assertEquals(30, tr1.getTextRuns().get(0).getLength());
+ assertEquals(30, tr1.getTextRuns().get(0).getRawText().length());
+ assertEquals(31, tr1.getTextRuns().get(0)._getRawCharacterStyle().getCharactersCovered());
+ assertEquals(31, tr1.getTextRuns().get(0)._getRawParagraphStyle().getCharactersCovered());
// Set the text to be as it is now
- tr1.setText( tr1.getText() );
+ tr1.setText( tr1.getRawText() );
// Check the text lengths are still right
- assertEquals(30, tr1.getText().length());
- assertEquals(179, tr2.getText().length());
+ assertEquals(30, tr1.getRawText().length());
+ assertEquals(179, tr2.getRawText().length());
- assertEquals(1, tr1.getRichTextRuns().length);
- assertEquals(30, tr1.getRichTextRuns()[0].getLength());
- assertEquals(30, tr1.getRichTextRuns()[0].getText().length());
- assertEquals(31, tr1.getRichTextRuns()[0]._getRawCharacterStyle().getCharactersCovered());
- assertEquals(31, tr1.getRichTextRuns()[0]._getRawParagraphStyle().getCharactersCovered());
+ assertEquals(1, tr1.getTextRuns().length);
+ assertEquals(30, tr1.getTextRuns().get(0).getLength());
+ assertEquals(30, tr1.getTextRuns().get(0).getRawText().length());
+ assertEquals(31, tr1.getTextRuns().get(0)._getRawCharacterStyle().getCharactersCovered());
+ assertEquals(31, tr1.getTextRuns().get(0)._getRawParagraphStyle().getCharactersCovered());
// Write the slideshow out to a byte array
}
}
+ @Test
public void testWritesOutTheSameRich() throws Exception {
// Grab the first text run on the first sheet
- HSLFTextParagraph tr1 = ss.getSlides()[0].getTextRuns()[0];
+ HSLFTextParagraph tr1 = ss.getSlides().get(0).getTextParagraphs().get(0);
// Get the first rich text run
- HSLFTextRun rtr1 = tr1.getRichTextRuns()[0];
+ HSLFTextRun rtr1 = tr1.getTextRuns().get(0);
// Check that the text sizes are as expected
- assertEquals(1, tr1.getRichTextRuns().length);
- assertEquals(30, tr1.getText().length());
- assertEquals(30, tr1.getRichTextRuns()[0].getText().length());
+ assertEquals(1, tr1.getTextRuns().length);
+ assertEquals(30, tr1.getRawText().length());
+ assertEquals(30, tr1.getTextRuns().get(0).getRawText().length());
assertEquals(30, rtr1.getLength());
- assertEquals(30, rtr1.getText().length());
+ assertEquals(30, rtr1.getRawText().length());
assertEquals(31, rtr1._getRawCharacterStyle().getCharactersCovered());
assertEquals(31, rtr1._getRawParagraphStyle().getCharactersCovered());
// Set the text to be as it is now
- rtr1.setText( rtr1.getText() );
- rtr1 = tr1.getRichTextRuns()[0];
+ rtr1.setText( rtr1.getRawText() );
+ rtr1 = tr1.getTextRuns().get(0);
// Check that the text sizes are still as expected
- assertEquals(1, tr1.getRichTextRuns().length);
- assertEquals(30, tr1.getText().length());
- assertEquals(30, tr1.getRichTextRuns()[0].getText().length());
+ assertEquals(1, tr1.getTextRuns().length);
+ assertEquals(30, tr1.getRawText().length());
+ assertEquals(30, tr1.getTextRuns().get(0).getRawText().length());
assertEquals(30, rtr1.getLength());
- assertEquals(30, rtr1.getText().length());
+ assertEquals(30, rtr1.getRawText().length());
assertEquals(31, rtr1._getRawCharacterStyle().getCharactersCovered());
assertEquals(31, rtr1._getRawParagraphStyle().getCharactersCovered());
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.record.TextHeaderAtom;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.ShapeType;
import org.junit.Test;
@Test
public void createAutoShape(){
HSLFTextShape shape = new HSLFAutoShape(ShapeType.TRAPEZOID);
- assertNull(shape.getTextParagraph());
+ assertNull(shape.getTextParagraphs());
assertNull(shape.getText());
assertNull(shape.getEscherTextboxWrapper());
HSLFTextParagraph run = shape.createTextRun();
assertNotNull(run);
- assertNotNull(shape.getTextParagraph());
+ assertNotNull(shape.getTextParagraphs());
assertNotNull(shape.getEscherTextboxWrapper());
assertEquals("", shape.getText());
assertSame(run, shape.createTextRun());
@Test
public void createTextBox(){
HSLFTextShape shape = new HSLFTextBox();
- HSLFTextParagraph run = shape.getTextParagraph();
+ HSLFTextParagraph run = shape.getTextParagraphs();
assertNotNull(run);
assertNotNull(shape.getText());
assertNotNull(shape.getEscherTextboxWrapper());
assertSame(run, shape.createTextRun());
- assertNotNull(shape.getTextParagraph());
+ assertNotNull(shape.getTextParagraphs());
assertNotNull(shape.getEscherTextboxWrapper());
assertEquals("", shape.getText());
for (int i = 0; i < shape.length; i++) {
assertTrue("Expected TextShape but found " + shape[i].getClass().getName(), shape[i] instanceof HSLFTextShape);
HSLFTextShape tx = (HSLFTextShape)shape[i];
- HSLFTextParagraph run = tx.getTextParagraph();
+ HSLFTextParagraph run = tx.getTextParagraphs();
assertNotNull(run);
int runType = run.getRunType();
ShapeType type = shape[i].getShapeType();
switch (type){
case TEXT_BOX:
- assertEquals("Text in a TextBox", run.getText());
+ assertEquals("Text in a TextBox", run.getRawText());
break;
case RECT:
if(runType == TextHeaderAtom.OTHER_TYPE)
- assertEquals("Rectangle", run.getText());
+ assertEquals("Rectangle", run.getRawText());
else if(runType == TextHeaderAtom.TITLE_TYPE)
- assertEquals("Title Placeholder", run.getText());
+ assertEquals("Title Placeholder", run.getRawText());
break;
case OCTAGON:
- assertEquals("Octagon", run.getText());
+ assertEquals("Octagon", run.getRawText());
break;
case ELLIPSE:
- assertEquals("Ellipse", run.getText());
+ assertEquals("Ellipse", run.getRawText());
break;
case ROUND_RECT:
- assertEquals("RoundRectangle", run.getText());
+ assertEquals("RoundRectangle", run.getRawText());
break;
default:
fail("Unexpected shape: " + shape[i].getShapeName());
}
- lst1.add(run.getText());
+ lst1.add(run.getRawText());
}
List<String> lst2 = new ArrayList<String>();
- HSLFTextParagraph[] run = slide.getTextRuns();
+ HSLFTextParagraph[] run = slide.getTextParagraphs();
for (int i = 0; i < run.length; i++) {
- lst2.add(run[i].getText());
+ lst2.add(run[i].getRawText());
}
assertTrue(lst1.containsAll(lst2));
assertTrue(shape[0] instanceof HSLFTextShape);
shape1 = (HSLFTextShape)shape[0];
assertEquals(ShapeType.TEXT_BOX, shape1.getShapeType());
- assertEquals("Hello, World!", shape1.getTextParagraph().getText());
+ assertEquals("Hello, World!", shape1.getTextParagraphs().getRawText());
assertTrue(shape[1] instanceof HSLFTextShape);
shape1 = (HSLFTextShape)shape[1];
assertEquals(ShapeType.RIGHT_ARROW, shape1.getShapeType());
- assertEquals("Testing TextShape", shape1.getTextParagraph().getText());
+ assertEquals("Testing TextShape", shape1.getTextParagraphs().getRawText());
}
@Test
HSLFTextShape tx;
tx = map.get("TEST1");
- assertEquals(0.1, tx.getMarginLeft()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.1, tx.getMarginRight()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.39, tx.getMarginTop()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginBottom()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getLeftInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getRightInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getTopInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getBottomInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
tx = map.get("TEST2");
- assertEquals(0.1, tx.getMarginLeft()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.1, tx.getMarginRight()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginTop()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.39, tx.getMarginBottom()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getLeftInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getRightInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getTopInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getBottomInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
tx = map.get("TEST3");
- assertEquals(0.39, tx.getMarginLeft()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.1, tx.getMarginRight()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginTop()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginBottom()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getLeftInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getRightInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getTopInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getBottomInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
tx = map.get("TEST4");
- assertEquals(0.1, tx.getMarginLeft()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.39, tx.getMarginRight()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginTop()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
- assertEquals(0.05, tx.getMarginBottom()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.1, tx.getLeftInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.39, tx.getRightInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getTopInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
+ assertEquals(0.05, tx.getBottomInset()*HSLFShape.EMU_PER_POINT/HSLFShape.EMU_PER_INCH, 0.01);
}
@Test
HSLFTextShape sh0 = (HSLFTextShape)sh[0];
assertEquals(null, sh0.getText());
- assertEquals(null, sh0.getTextParagraph());
+ assertEquals(null, sh0.getTextParagraphs());
HSLFTextShape sh1 = (HSLFTextShape)sh[1];
assertEquals(null, sh1.getText());
- assertEquals(null, sh1.getTextParagraph());
+ assertEquals(null, sh1.getTextParagraphs());
HSLFTextShape sh2 = (HSLFTextShape)sh[2];
assertEquals("this box should be shown just once", sh2.getText());
- assertEquals(-1, sh2.getTextParagraph().getIndex());
+ assertEquals(-1, sh2.getTextParagraphs().getIndex());
}
}
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.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.hssf.usermodel.DummyGraphics2d;
import org.junit.Test;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.junit.Test;
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.poifs.filesystem.*;
import org.apache.poi.POIDataSamples;
import org.apache.poi.hpsf.PropertySetFactory;\r
import org.apache.poi.hpsf.SummaryInformation;\r
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;\r
-import org.apache.poi.hslf.model.HSLFSlide;\r
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;\r
-import org.apache.poi.hslf.usermodel.HSLFPictureData;\r
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;\r
+import org.apache.poi.hslf.usermodel.*;\r
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;\r
import org.apache.poi.poifs.crypt.CryptoFunctions;\r
import org.apache.poi.poifs.crypt.EncryptionInfo;\r
HSLFSlideShow ss = new HSLFSlideShow(hss);\r
\r
HSLFSlide slide = ss.getSlides()[0];\r
- assertEquals("Dominic Salemno", slide.getTextRuns()[0].getText());\r
+ assertEquals("Dominic Salemno", slide.getTextParagraphs()[0].getRawText());\r
\r
String picCmp[][] = {\r
{"0","nKsDTKqxTCR8LFkVVWlP9GSTvZ0="},\r
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.POIDataSamples;
/**
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.POIDataSamples;
/**
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlideShowImpl;
+import org.apache.poi.hslf.usermodel.HSLFSlideShowImpl;
import org.apache.poi.POIDataSamples;
/**
public void testSSSlideInfoAtom() throws Exception {
HSLFSlideShow ss = new HSLFSlideShow();
- org.apache.poi.hslf.model.HSLFSlide slide1 = ss.createSlide(), slide2 = ss.createSlide();
+ org.apache.poi.hslf.usermodel.HSLFSlide slide1 = ss.createSlide(), slide2 = ss.createSlide();
slide2.setHidden(true);
ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
notes = ppt.getSlides()[0].getNotesSheet();
assertNotNull(notes);
- txrun = notes.getTextRuns()[0];
+ txrun = notes.getTextParagraphs()[0];
assertEquals("Notes-1", txrun.getRawText());
- assertEquals(false, txrun.getRichTextRuns()[0].isBold());
+ assertEquals(false, txrun.getTextRuns()[0].isBold());
//notes for the second slide are in bold
notes = ppt.getSlides()[1].getNotesSheet();
assertNotNull(notes);
- txrun = notes.getTextRuns()[0];
+ txrun = notes.getTextParagraphs()[0];
assertEquals("Notes-2", txrun.getRawText());
- assertEquals(true, txrun.getRichTextRuns()[0].isBold());
+ assertEquals(true, txrun.getTextRuns()[0].isBold());
}
HSLFNotes notes = slide[i].getNotesSheet();
if (notesMap.containsKey(slideNumber)){
assertNotNull(notes);
- String text = notes.getTextRuns()[0].getRawText();
+ String text = notes.getTextParagraphs()[0].getRawText();
String startingPhrase = notesMap.get(slideNumber);
assertTrue("Notes for slide " + slideNumber + " must start with " +
startingPhrase , text.startsWith(startingPhrase));
for (int j = 0; j < sh.length; j++) {
if( sh[j] instanceof HSLFTextBox){
HSLFTextBox txt = (HSLFTextBox)sh[j];
- assertNotNull(txt.getTextParagraph());
+ assertNotNull(txt.getTextParagraphs());
}
}
}
HSLFSlide[] slide = ppt.getSlides();
for (int i = 0; i < slide.length; i++) {
HSLFMasterSheet master = slide[i].getMasterSheet();
- if (i == 0) assertTrue(master instanceof TitleMaster); //the first slide follows TitleMaster
- else assertTrue(master instanceof SlideMaster);
+ if (i == 0) assertTrue(master instanceof HSLFTitleMaster); //the first slide follows TitleMaster
+ else assertTrue(master instanceof HSLFSlideMaster);
}
}
HSLFSlide[] slide = ppt.getSlides();
assertEquals(1, slide.length);
- HSLFTextParagraph[] runs = slide[0].getTextRuns();
+ HSLFTextParagraph[] runs = slide[0].getTextParagraphs();
assertEquals(4, runs.length);
Set<String> txt = new HashSet<String>();
// Check the first slide
HSLFSlide slide = ppt.getSlides()[0];
- HSLFTextParagraph[] slTr = slide.getTextRuns();
+ HSLFTextParagraph[] slTr = slide.getTextParagraphs();
// Has two text runs, one from slide text, one from drawing
assertEquals(2, slTr.length);
assertEquals(false, slTr[0].isDrawingBased());
assertEquals(true, slTr[1].isDrawingBased());
- assertEquals("First run", slTr[0].getText());
- assertEquals("Second run", slTr[1].getText());
+ assertEquals("First run", slTr[0].getRawText());
+ assertEquals("Second run", slTr[1].getRawText());
// Check the shape based text runs
List<HSLFTextParagraph> lst = new ArrayList<HSLFTextParagraph>();
HSLFShape[] shape = slide.getShapes();
for (int i = 0; i < shape.length; i++) {
if( shape[i] instanceof HSLFTextShape){
- HSLFTextParagraph textRun = ((HSLFTextShape)shape[i]).getTextParagraph();
+ HSLFTextParagraph textRun = ((HSLFTextShape)shape[i]).getTextParagraphs();
if(textRun != null) {
lst.add(textRun);
}
assertEquals(1, lst.size());
// And it should be the second one
- assertEquals("Second run", lst.get(0).getText());
+ assertEquals("Second run", lst.get(0).getRawText());
}
/**
assertEquals(1, sh.length);
assertTrue(sh[0] instanceof HSLFTextShape);
HSLFTextShape tx = (HSLFTextShape)sh[0];
- assertEquals("Fundera, planera och involvera.", tx.getTextParagraph().getText());
+ assertEquals("Fundera, planera och involvera.", tx.getTextParagraphs().getRawText());
- HSLFTextParagraph[] run = slide.getTextRuns();
+ HSLFTextParagraph[] run = slide.getTextParagraphs();
assertEquals(1, run.length);
- assertEquals("Fundera, planera och involvera.", run[0].getText());
+ assertEquals("Fundera, planera och involvera.", run[0].getRawText());
}
/**
public void bug49648() throws Exception {
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("49648.ppt"));
for(HSLFSlide slide : ppt.getSlides()) {
- for(HSLFTextParagraph run : slide.getTextRuns()) {
+ for(HSLFTextParagraph run : slide.getTextParagraphs()) {
String text = run.getRawText();
text.replace("{txtTot}", "With \u0123\u1234\u5678 unicode");
run.setRawText(text);
str = str.replace("$$DATE$$", new Date().toString());
tb.setText(str);
- HSLFTextParagraph tr = tb.getTextParagraph();
+ HSLFTextParagraph tr = tb.getTextParagraphs();
assertEquals(str.length()+1,tr.getStyleTextPropAtom().getParagraphStyles().getFirst().getCharactersCovered());
assertEquals(str.length()+1,tr.getStyleTextPropAtom().getCharacterStyles().getFirst().getCharactersCovered());
}
// Check the number of text runs based on the slide (not textbox)
// Will have skipped the empty one
int str = 0;
- for (HSLFTextParagraph tr : _slides[0].getTextRuns()) {
+ for (HSLFTextParagraph tr : _slides[0].getTextParagraphs()) {
if (! tr.isDrawingBased()) str++;
}
assertEquals(1, str);
import javax.imageio.ImageIO;\r
\r
import org.apache.poi.POIDataSamples;\r
-import org.apache.poi.hslf.model.HSLFSlide;\r
import org.apache.poi.hslf.model.TextPainter;\r
import org.apache.poi.util.TempFile;\r
import org.junit.Ignore;\r
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;
HSLFNotes notes = ss.getNotes()[0];
String[] expectText = new String[] {"These are the notes for page 1"};
- assertEquals(expectText.length, notes.getTextRuns().length);
+ assertEquals(expectText.length, notes.getTextParagraphs().length);
for(int i=0; i<expectText.length; i++) {
- assertEquals(expectText[i], notes.getTextRuns()[i].getText());
+ assertEquals(expectText[i], notes.getTextParagraphs()[i].getRawText());
}
}
public void testNotesTwo() {
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);
+ assertEquals(expectText.length, notes.getTextParagraphs().length);
for(int i=0; i<expectText.length; i++) {
- assertEquals(expectText[i], notes.getTextRuns()[i].getText());
+ assertEquals(expectText[i], notes.getTextParagraphs()[i].getRawText());
}
}
}
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlide;
-import org.apache.poi.hslf.model.HSLFTextParagraph;
import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
assertNull(autoNumbers[1].getAutoNumberScheme());
assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaLcParenRight == autoNumbers[2].getAutoNumberScheme());
- HSLFTextParagraph[] textRuns = s.getTextRuns();
+ HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(2, textRuns.length);
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertEquals("titTe", textRun.getRawText());
- assertEquals(1, textRuns[0].getRichTextRuns().length);
+ assertEquals(1, textRuns[0].getTextRuns().length);
assertFalse(textRun.isBullet());
assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText());
assertNull(autoNumbers[1].getAutoNumberScheme());
assertTrue(TextAutoNumberSchemeEnum.ANM_AlphaUcPeriod == autoNumbers[2].getAutoNumberScheme());
- final HSLFTextParagraph[] textRuns = s.getTextRuns();
+ final HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(2, textRuns.length);
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertEquals("Second Slide Title", textRun.getRawText());
- assertEquals(1, textRuns[0].getRichTextRuns().length);
+ assertEquals(1, textRuns[0].getTextRuns().length);
assertFalse(textRun.isBullet());
assertEquals("This is a text placeholder that \rfollows the design pattern\rJust a test\rWithout any paragraph\rSecond paragraph first line c) ;\rSecond paragraph second line d) . \r", textRuns[1].getRawText());
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlide;
-import org.apache.poi.hslf.model.HSLFTextParagraph;
import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox1[0].getAutoNumberScheme());
- HSLFTextParagraph[] textRuns = s.getTextRuns();
+ HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(2, textRuns.length);
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertEquals("List Item One\rList Item Two\rList Item Three", textRun.getRawText());
- assertEquals(1, textRuns[0].getRichTextRuns().length);
+ assertEquals(1, textRuns[0].getTextRuns().length);
assertTrue(textRun.isBullet());
assertEquals("A numbered list may start at any number \rThis would be used as a continuation list on another page\rThis list should start with #6", textRuns[1].getRawText());
assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox[0].getAutoNumberStartNumber());//Default value = 1 will be used
assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox[0].getAutoNumberScheme());
- HSLFTextParagraph[] textRuns = s.getTextRuns();
+ HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(3, textRuns.length);
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertEquals("Bulleted list\rMore bullets", textRun.getRawText());
- assertEquals(1, textRuns[0].getRichTextRuns().length);
+ assertEquals(1, textRuns[0].getTextRuns().length);
assertTrue(textRun.isBullet());
assertEquals("Numbered list between two bulleted lists\rSecond numbered list item", textRuns[1].getRawText());
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFSlide;
-import org.apache.poi.hslf.model.HSLFTextParagraph;
import org.apache.poi.hslf.model.textproperties.TextPFException9;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.EscherTextboxWrapper;
assertEquals(Short.valueOf((short)1), autoNumbersOfTextBox0[0].getAutoNumberStartNumber());//Default value = 1 will be used
assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox0[0].getAutoNumberScheme());
- final HSLFTextParagraph[] textRuns = s.getTextRuns();
+ final HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(3, textRuns.length);
assertEquals("Bulleted list\rMore bullets\rNo bullets here", textRuns[0].getRawText());
assertEquals("Numbered list between two bulleted lists\rSecond numbered list item", textRuns[1].getRawText());
assertEquals("Second bulleted list \u2013 should appear after numbered list\rMore bullets", textRuns[2].getRawText());
- assertEquals(2, textRuns[0].getRichTextRuns().length);
- assertEquals(1, textRuns[1].getRichTextRuns().length);
- assertEquals(1, textRuns[2].getRichTextRuns().length);
+ assertEquals(2, textRuns[0].getTextRuns().length);
+ assertEquals(1, textRuns[1].getTextRuns().length);
+ assertEquals(1, textRuns[2].getTextRuns().length);
assertNull(textRuns[0].getStyleTextProp9Atom());
assertNotNull(textRuns[1].getStyleTextProp9Atom());
assertNull(textRuns[2].getStyleTextProp9Atom());
assertEquals(67, textProp.getCharactersCovered());
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertTrue(textRun.isBullet());
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;
*/
public void testBoldNonRich() {
HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextRun rtr = textRuns[0].getRichTextRuns()[0];
+ HSLFTextParagraph[] textRuns = slideOne.getTextParagraphs();
+ HSLFTextRun rtr = textRuns[0].getTextRuns()[0];
assertNull(rtr._getRawCharacterStyle());
assertNull(rtr._getRawParagraphStyle());
*/
public void testBoldRich() {
HSLFSlide slideOneR = ssRichA.getSlides()[0];
- HSLFTextParagraph[] textRunsR = slideOneR.getTextRuns();
- HSLFTextRun[] rtrs = textRunsR[1].getRichTextRuns();
+ HSLFTextParagraph[] textRunsR = slideOneR.getTextParagraphs();
+ HSLFTextRun[] rtrs = textRunsR[1].getTextRuns();
assertEquals(3, rtrs.length);
assertTrue(rtrs[0].isBold());
public void testFontSize() {
HSLFSlide slideOne = ss.getSlides()[0];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextRun rtr = textRuns[0].getRichTextRuns()[0];
+ HSLFTextParagraph[] textRuns = slideOne.getTextParagraphs();
+ HSLFTextRun rtr = textRuns[0].getTextRuns()[0];
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];
+ HSLFTextParagraph[] textRunsR = slideOneR.getTextParagraphs();
+ HSLFTextRun rtrRa = textRunsR[0].getTextRuns()[0];
+ HSLFTextRun rtrRb = textRunsR[1].getTextRuns()[0];
+ HSLFTextRun rtrRc = textRunsR[1].getTextRuns()[3];
String defaultFont = "Arial";
for(int i=0; i<h.length; i++) {
// Change
HSLFSlide slideOne = s[i];
- HSLFTextParagraph[] textRuns = slideOne.getTextRuns();
- HSLFTextRun rtr = textRuns[0].getRichTextRuns()[0];
+ HSLFTextParagraph[] textRuns = slideOne.getTextParagraphs();
+ HSLFTextRun rtr = textRuns[0].getTextRuns()[0];
rtr.setBold(true);
rtr.setFontSize(18);
// Now, look at the one we changed, wrote out, and read back in
// Ensure it does contain our original modifications
HSLFSlide slideOneRR = readS.getSlides()[0];
- HSLFTextParagraph[] textRunsRR = slideOneRR.getTextRuns();
- HSLFTextRun rtrRRa = textRunsRR[0].getRichTextRuns()[0];
+ HSLFTextParagraph[] textRunsRR = slideOneRR.getTextParagraphs();
+ HSLFTextRun rtrRRa = textRunsRR[0].getTextRuns()[0];
assertEquals(true, rtrRRa.isBold());
assertEquals(18, rtrRRa.getFontSize());
// Check the number of text runs on interesting sheets
HSLFSlide slideThreeC = ssRichC.getSlides()[2];
HSLFSlide slideSevenC = ssRichC.getSlides()[6];
- assertEquals(3, slideThreeC.getTextRuns().length);
- assertEquals(5, slideSevenC.getTextRuns().length);
+ assertEquals(3, slideThreeC.getTextParagraphs().length);
+ assertEquals(5, slideSevenC.getTextParagraphs().length);
// On slide three, we should have:
// TR:
// Illustrative Example
// .
- HSLFTextParagraph[] s3tr = slideThreeC.getTextRuns();
- HSLFTextRun[] s3rtr0 = s3tr[0].getRichTextRuns();
- HSLFTextRun[] s3rtr1 = s3tr[1].getRichTextRuns();
- HSLFTextRun[] s3rtr2 = s3tr[2].getRichTextRuns();
+ HSLFTextParagraph[] s3tr = slideThreeC.getTextParagraphs();
+ HSLFTextRun[] s3rtr0 = s3tr[0].getTextRuns();
+ HSLFTextRun[] s3rtr1 = s3tr[1].getTextRuns();
+ HSLFTextRun[] s3rtr2 = s3tr[2].getTextRuns();
assertEquals(2, s3rtr0.length);
assertEquals(1, s3rtr1.length);
assertEquals(2, s3rtr2.length);
- assertEquals("You are an important supplier of various items that I need", s3rtr0[0].getText());
- assertEquals("", s3rtr0[1].getText());
- assertEquals("Source: Internal focus groups", s3rtr1[0].getText());
- assertEquals("Illustrative Example", s3rtr2[0].getText());
- assertEquals("", s3rtr2[1].getText());
+ assertEquals("You are an important supplier of various items that I need", s3rtr0[0].getRawText());
+ assertEquals("", s3rtr0[1].getRawText());
+ assertEquals("Source: Internal focus groups", s3rtr1[0].getRawText());
+ assertEquals("Illustrative Example", s3rtr2[0].getRawText());
+ assertEquals("", s3rtr2[1].getRawText());
assertTrue(s3rtr0[0]._isParagraphStyleShared());
assertTrue(s3rtr0[1]._isParagraphStyleShared());
// <ps>(text a)</ps><ps>(text a)(text b)</ps>
// TR:
// (text)
- HSLFTextParagraph[] s7tr = slideSevenC.getTextRuns();
- HSLFTextRun[] s7rtr0 = s7tr[0].getRichTextRuns();
- HSLFTextRun[] s7rtr1 = s7tr[1].getRichTextRuns();
- HSLFTextRun[] s7rtr2 = s7tr[2].getRichTextRuns();
+ HSLFTextParagraph[] s7tr = slideSevenC.getTextParagraphs();
+ HSLFTextRun[] s7rtr0 = s7tr[0].getTextRuns();
+ HSLFTextRun[] s7rtr1 = s7tr[1].getTextRuns();
+ HSLFTextRun[] s7rtr2 = s7tr[2].getTextRuns();
assertEquals(1, s7rtr0.length);
assertEquals(3, s7rtr1.length);
assertMatchesFileC(ssRichC);
HSLFSlide slideSevenC = ssRichC.getSlides()[6];
- HSLFTextParagraph[] s7tr = slideSevenC.getTextRuns();
- HSLFTextRun[] s7rtr0 = s7tr[0].getRichTextRuns();
- HSLFTextRun[] s7rtr1 = s7tr[1].getRichTextRuns();
- HSLFTextRun[] s7rtr2 = s7tr[2].getRichTextRuns();
+ HSLFTextParagraph[] s7tr = slideSevenC.getTextParagraphs();
+ HSLFTextRun[] s7rtr0 = s7tr[0].getTextRuns();
+ HSLFTextRun[] s7rtr1 = s7tr[1].getTextRuns();
+ HSLFTextRun[] s7rtr2 = s7tr[2].getTextRuns();
String oldText;
// Need to ensure it's a run that really has styles!
oldText = s7rtr2[0].getRawText();
s7rtr2[0].setText( oldText );
- assertEquals(oldText, s7rtr2[0].getText());
- assertEquals(oldText, s7tr[2].getText());
+ assertEquals(oldText, s7rtr2[0].getRawText());
+ assertEquals(oldText, s7tr[2].getRawText());
assertEquals(oldText.length() + 1, s7rtr2[0]._getRawCharacterStyle().getCharactersCovered());
assertEquals(oldText.length() + 1, s7rtr2[0]._getRawParagraphStyle().getCharactersCovered());
assertMatchesSLTWC(ssRichC);
// Reset the text on a shared paragraph
oldText = s7rtr1[2].getRawText();
s7rtr1[2].setText( oldText );
- assertEquals(oldText, s7rtr1[2].getText());
+ assertEquals(oldText, s7rtr1[2].getRawText());
assertEquals(oldText.length() + 1, s7rtr1[2]._getRawCharacterStyle().getCharactersCovered());
assertMatchesSLTWC(ssRichC);
assertMatchesFileC(ssRichC);
HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("ParagraphStylesShorterThanCharStyles.ppt"));
HSLFSlide[] sl = ppt.getSlides();
for (int i = 0; i < sl.length; i++) {
- HSLFTextParagraph[] txt = sl[i].getTextRuns();
+ HSLFTextParagraph[] txt = sl[i].getTextParagraphs();
for (int j = 0; j < txt.length; j++) {
- HSLFTextRun[] rt = txt[j].getRichTextRuns();
+ HSLFTextRun[] rt = txt[j].getTextRuns();
for (int k = 0; k < rt.length; k++) {
int indent = rt[k].getIndentLevel();
assertTrue(indent >= 0 && indent <= 4 );
HSLFSlide[] slide = ppt.getSlides();
assertEquals(2, slide.length);
- txt = slide[0].getTextRuns();
+ txt = slide[0].getTextParagraphs();
assertEquals(2, txt.length);
assertEquals("Title text", txt[0].getRawText());
- assertEquals(1, txt[0].getRichTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ assertEquals(1, txt[0].getTextRuns().length);
+ rt = txt[0].getTextRuns()[0];
assertFalse(rt.isBullet());
assertEquals(
"follows the design pattern\r" +
"Defined in the slide master\r" +
"and has bullets by default", txt[1].getRawText());
- assertEquals(1, txt[1].getRichTextRuns().length);
- rt = txt[1].getRichTextRuns()[0];
+ assertEquals(1, txt[1].getTextRuns().length);
+ rt = txt[1].getTextRuns()[0];
assertEquals('\u2022', rt.getBulletChar());
assertTrue(rt.isBullet());
- txt = slide[1].getTextRuns();
+ txt = slide[1].getTextParagraphs();
assertEquals(2, txt.length);
assertEquals(
"With bullets\r" +
"That follow the design pattern\r" +
"From the slide master", txt[0].getRawText());
- assertEquals(1, txt[0].getRichTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ assertEquals(1, txt[0].getTextRuns().length);
+ rt = txt[0].getTextRuns()[0];
assertTrue(rt.isBullet());
assertEquals('\u2022', rt.getBulletChar());
assertEquals(
"I\u2019m a text box with user-defined\r" +
"bullet character", txt[1].getRawText());
- assertEquals(1, txt[1].getRichTextRuns().length);
- rt = txt[1].getRichTextRuns()[0];
+ assertEquals(1, txt[1].getTextRuns().length);
+ rt = txt[1].getTextRuns()[0];
assertTrue(rt.isBullet());
assertEquals('\u263A', rt.getBulletChar());
}
HSLFSlide slide = ppt.createSlide();
HSLFTextBox shape = new HSLFTextBox();
- HSLFTextRun rt = shape.getTextParagraph().getRichTextRuns()[0];
+ HSLFTextRun rt = shape.getTextParagraphs().getTextRuns()[0];
shape.setText(
"Hello, World!\r" +
"This should be\r" +
ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
slide = ppt.getSlides()[0];
shape = (HSLFTextBox)slide.getShapes()[0];
- rt = shape.getTextParagraph().getRichTextRuns()[0];
+ rt = shape.getTextParagraphs().getTextRuns()[0];
assertEquals(42, rt.getFontSize());
assertEquals(true, rt.isBullet());
assertEquals(50, rt.getTextOffset());
HSLFSlide[] slides = ppt.getSlides();
assertEquals(2, slides.length);
- txt = slides[0].getTextRuns();
+ txt = slides[0].getTextParagraphs();
assertEquals(2, txt.length);
assertEquals("Title text", txt[0].getRawText());
- assertEquals(1, txt[0].getRichTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ assertEquals(1, txt[0].getTextRuns().length);
+ rt = txt[0].getTextRuns()[0];
assertFalse(rt.isBullet());
// Add some new text
txt[0].appendText("Foo! I'm new!");
- assertEquals(2, txt[0].getRichTextRuns().length);
+ assertEquals(2, txt[0].getTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ rt = txt[0].getTextRuns()[0];
assertFalse(rt.isBold());
- assertEquals("Title text", rt.getText());
- rt = txt[0].getRichTextRuns()[1];
+ assertEquals("Title text", rt.getRawText());
+ rt = txt[0].getTextRuns()[1];
assertFalse(rt.isBold());
- assertEquals("Foo! I'm new!", rt.getText());
+ assertEquals("Foo! I'm new!", rt.getRawText());
rt.setBold(true);
// And some more
txt[0].appendText("Me too!");
- assertEquals(3, txt[0].getRichTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ assertEquals(3, txt[0].getTextRuns().length);
+ rt = txt[0].getTextRuns()[0];
assertFalse(rt.isBold());
- assertEquals("Title text", rt.getText());
- rt = txt[0].getRichTextRuns()[1];
+ assertEquals("Title text", rt.getRawText());
+ rt = txt[0].getTextRuns()[1];
assertTrue(rt.isBold());
- assertEquals("Foo! I'm new!", rt.getText());
- rt = txt[0].getRichTextRuns()[2];
+ assertEquals("Foo! I'm new!", rt.getRawText());
+ rt = txt[0].getTextRuns()[2];
assertFalse(rt.isBold());
- assertEquals("Me too!", rt.getText());
+ assertEquals("Me too!", rt.getRawText());
// Save and re-open
ByteArrayOutputStream out = new ByteArrayOutputStream();
assertEquals(2, slides.length);
- txt = slides[0].getTextRuns();
+ txt = slides[0].getTextParagraphs();
assertEquals(2, txt.length);
- assertEquals(3, txt[0].getRichTextRuns().length);
- rt = txt[0].getRichTextRuns()[0];
+ assertEquals(3, txt[0].getTextRuns().length);
+ rt = txt[0].getTextRuns()[0];
assertFalse(rt.isBold());
- assertEquals("Title text", rt.getText());
- rt = txt[0].getRichTextRuns()[1];
+ assertEquals("Title text", rt.getRawText());
+ rt = txt[0].getTextRuns()[1];
assertTrue(rt.isBold());
- assertEquals("Foo! I'm new!", rt.getText());
- rt = txt[0].getRichTextRuns()[2];
+ assertEquals("Foo! I'm new!", rt.getRawText());
+ rt = txt[0].getTextRuns()[2];
assertFalse(rt.isBold());
- assertEquals("Me too!", rt.getText());
+ assertEquals("Me too!", rt.getRawText());
// FileOutputStream fout = new FileOutputStream("/tmp/foo.ppt");
// ppt.write(fout);
assertEquals(1, slides.length);
// One block of text within that
- txt = slides[0].getTextRuns();
+ txt = slides[0].getTextParagraphs();
assertEquals(1, txt.length);
// One rich block of text in that - text is all the same style
// TODO Is this completely correct?
- rts = txt[0].getRichTextRuns();
+ rts = txt[0].getTextRuns();
assertEquals(1, rts.length);
rt = rts[0];
// Check we can get the english text out of that
- String text = rt.getText();
+ String text = rt.getRawText();
assertContains(text, "Single byte");
// And the chinese
assertContains(text, "\uff8a\uff9d\uff76\uff78");
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);
+ assertEquals(expectText.length, slideOne.getTextParagraphs().length);
for(int i=0; i<expectText.length; i++) {
- assertEquals(expectText[i], slideOne.getTextRuns()[i].getText());
+ assertEquals(expectText[i], slideOne.getTextParagraphs()[i].getRawText());
}
}
public void testSheetTwo() {
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);
+ assertEquals(expectText.length, slideTwo.getTextParagraphs().length);
for(int i=0; i<expectText.length; i++) {
- assertEquals(expectText[i], slideTwo.getTextRuns()[i].getText());
+ assertEquals(expectText[i], slideTwo.getTextParagraphs()[i].getRawText());
}
}
"COP 11 \u2013 MOP 1\n" + // special long hyphen
"December 5, 2005\n";
- assertEquals(1, s.getTextRuns().length);
- assertEquals(exp, s.getTextRuns()[0].getText());
+ assertEquals(1, s.getTextParagraphs().length);
+ assertEquals(exp, s.getTextParagraphs()[0].getRawText());
}
}
String[] firstTRs = new String[] { "This is a test title", "This is the title on page 2" };
- assertEquals(firstTRs[0], s1.getTextRuns()[0].getText());
- assertEquals(firstTRs[1], s2.getTextRuns()[0].getText());
+ assertEquals(firstTRs[0], s1.getTextParagraphs()[0].getRawText());
+ assertEquals(firstTRs[1], s2.getTextParagraphs()[0].getRawText());
}
/**
String[] firstTRs = new String[] { "Slide 1", "Slide 2", "Slide 3" };
- assertEquals(firstTRs[0], s1.getTextRuns()[0].getText());
- assertEquals(firstTRs[1], s2.getTextRuns()[0].getText());
- assertEquals(firstTRs[2], s3.getTextRuns()[0].getText());
+ assertEquals(firstTRs[0], s1.getTextParagraphs()[0].getRawText());
+ assertEquals(firstTRs[1], s2.getTextParagraphs()[0].getRawText());
+ assertEquals(firstTRs[2], s3.getTextParagraphs()[0].getRawText());
}
/**
import junit.framework.TestCase;
-import org.apache.poi.hslf.model.HSLFShape;
-import org.apache.poi.hslf.model.HSLFSlide;
import org.apache.poi.hslf.model.Table;
-import org.apache.poi.hslf.model.HSLFTextParagraph;
import org.apache.poi.POIDataSamples;
checkSlide(slides[0]);
}
private void checkSlide(final HSLFSlide s) {
- HSLFTextParagraph[] textRuns = s.getTextRuns();
+ HSLFTextParagraph[] textRuns = s.getTextParagraphs();
assertEquals(2, textRuns.length);
- HSLFTextRun textRun = textRuns[0].getRichTextRuns()[0];
+ HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
assertEquals("Table sample", textRun.getRawText().trim());
- assertEquals(1, textRuns[0].getRichTextRuns().length);
+ assertEquals(1, textRuns[0].getTextRuns().length);
assertFalse(textRun.isBullet());
assertEquals("Dummy text", textRuns[1].getRawText());
assertEquals(4, table.getNumberOfColumns());
assertEquals(6, table.getNumberOfRows());
for (int x = 0; x < 4; x ++) {
- assertEquals("TH Cell " + (x + 1), table.getCell(0, x).getTextParagraph().getRawText());
+ assertEquals("TH Cell " + (x + 1), table.getCell(0, x).getTextParagraphs().getRawText());
for (int y = 1; y < 6; y++) {
assertEquals("Row " + y + ", Cell " + (x + 1), table.getCell(y, x).getText());
}
--- /dev/null
+/* ====================================================================
+ 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 static org.junit.Assert.*;
+
+import java.awt.Color;
+import java.io.*;
+import java.util.List;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.model.Table;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.record.*;
+import org.apache.poi.hslf.usermodel.*;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for TextRuns
+ *
+ * @author Nick Burch (nick at torchbox dot com)
+ */
+public final class TestTextRun {
+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+
+ // SlideShow primed on the test data
+ private HSLFSlideShow ss;
+ private HSLFSlideShow ssRich;
+
+ @Before
+ public void setUp() throws IOException {
+
+ // Basic (non rich) test file
+ ss = new HSLFSlideShow(_slTests.openResourceAsStream("basic_test_ppt_file.ppt"));
+
+ // Rich test file
+ ssRich = new HSLFSlideShow(_slTests.openResourceAsStream("Single_Coloured_Page.ppt"));
+ }
+
+ /**
+ * Test to ensure that getting the text works correctly
+ */
+ @Test
+ public void testGetText() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> textParas = slideOne.getTextParagraphs();
+
+ assertEquals(2, textParas.size());
+
+ // Get text works with \n
+ assertEquals("This is a test title", textParas.get(0).getTextRuns().get(0).getRawText());
+ assertEquals("This is a test subtitle\nThis is on page 1", textParas.get(1).getTextRuns().get(0).getRawText());
+
+ // Raw text has \r instead
+ assertEquals("This is a test title", textParas.get(0).getTextRuns().get(0).getRawText());
+ assertEquals("This is a test subtitle\rThis is on page 1", textParas.get(1).getTextRuns().get(0).getRawText());
+
+
+ // Now check on a rich text run
+ HSLFSlide slideOneR = ssRich.getSlides().get(0);
+ List<HSLFTextParagraph> textRunsR = slideOneR.getTextParagraphs();
+
+ assertEquals(2, textRunsR.size());
+ assertEquals("This is a title, it\u2019s in black", textRunsR.get(0).getTextRuns().get(0).getRawText());
+ assertEquals("This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)", textRunsR.get(1).getTextRuns().get(0).getRawText());
+ assertEquals("This is a title, it\u2019s in black", textRunsR.get(0).getTextRuns().get(0).getRawText());
+ assertEquals("This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)", textRunsR.get(1).getTextRuns().get(0).getRawText());
+ }
+
+ /**
+ * Test to ensure changing non rich text bytes->bytes works correctly
+ */
+ @Test
+ public void testSetText() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+ HSLFTextParagraph run = textRuns.get(0);
+ HSLFTextRun tr = run.getTextRuns().get(0);
+
+ // Check current text
+ assertEquals("This is a test title", tr.getRawText());
+
+ // Change
+ String changeTo = "New test title";
+ tr.setText(changeTo);
+ assertEquals(changeTo, tr.getRawText());
+
+ // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r'
+ tr.setText(changeTo + "\n");
+ assertEquals(changeTo + "\n", tr.getRawText());
+ }
+
+ /**
+ * Test to ensure that changing non rich text between bytes and
+ * chars works correctly
+ */
+ @Test
+ public void testAdvancedSetText() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> paras = slideOne.getTextParagraphs();
+ HSLFTextParagraph para = paras.get(0);
+
+ TextHeaderAtom tha = null;
+ TextBytesAtom tba = null;
+ TextCharsAtom tca = null;
+ for (Record r : para.getRecords()) {
+ if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
+ else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
+ else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
+ }
+
+
+ // Bytes -> Bytes
+ assertNull(tca);
+ assertNotNull(tba);
+ // assertFalse(run._isUnicode);
+ assertEquals("This is a test title", para.getTextRuns().get(0).getRawText());
+
+ String changeBytesOnly = "New Test Title";
+ HSLFTextParagraph.setText(paras, changeBytesOnly);
+ para = paras.get(0);
+ tha = null; tba = null; tca = null;
+ for (Record r : para.getRecords()) {
+ if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
+ else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
+ else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
+ }
+
+ assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras));
+ assertNull(tca);
+ assertNotNull(tba);
+
+ // Bytes -> Chars
+ assertNull(tca);
+ assertNotNull(tba);
+ assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras));
+
+ String changeByteChar = "This is a test title with a '\u0121' g with a dot";
+ HSLFTextParagraph.setText(paras, changeByteChar);
+ para = paras.get(0);
+ tha = null; tba = null; tca = null;
+ for (Record r : para.getRecords()) {
+ if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
+ else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
+ else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
+ }
+
+ assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras));
+ assertNotNull(tca);
+ assertNull(tba);
+
+ // Chars -> Chars
+ assertNull(tba);
+ assertNotNull(tca);
+ assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras));
+
+ String changeCharChar = "This is a test title with a '\u0147' N with a hat";
+ HSLFTextParagraph.setText(paras, changeCharChar);
+ para = paras.get(0);
+ tha = null; tba = null; tca = null;
+ for (Record r : para.getRecords()) {
+ if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
+ else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
+ else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
+ }
+
+ assertEquals(changeCharChar, HSLFTextParagraph.getRawText(paras));
+ assertNotNull(tca);
+ assertNull(tba);
+ }
+
+ /**
+ * Tests to ensure that non rich text has the right default rich text run
+ * set up for it
+ */
+ @Test
+ public void testGetRichTextNonRich() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+
+ assertEquals(2, textRuns.size());
+
+ HSLFTextParagraph trA = textRuns.get(0);
+ HSLFTextParagraph trB = textRuns.get(1);
+
+ assertEquals(1, trA.getTextRuns().size());
+ assertEquals(1, trB.getTextRuns().size());
+
+ HSLFTextRun rtrA = trA.getTextRuns().get(0);
+ HSLFTextRun rtrB = trB.getTextRuns().get(0);
+
+ assertEquals(HSLFTextParagraph.getRawText(textRuns.subList(0, 0)), rtrA.getRawText());
+ assertEquals(HSLFTextParagraph.getRawText(textRuns.subList(1, 1)), rtrB.getRawText());
+
+// assertNull(rtrA._getRawCharacterStyle());
+// assertNull(rtrA._getRawParagraphStyle());
+// assertNull(rtrB._getRawCharacterStyle());
+// assertNull(rtrB._getRawParagraphStyle());
+ }
+
+ /**
+ * Tests to ensure that the rich text runs are built up correctly
+ */
+ @Test
+ public void testGetRichText() {
+ HSLFSlide slideOne = ssRich.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+
+ assertEquals(2, textRuns.size());
+
+ HSLFTextParagraph trA = textRuns.get(0);
+ HSLFTextParagraph trB = textRuns.get(1);
+
+ assertEquals(1, trA.getTextRuns().size());
+ assertEquals(3, trB.getTextRuns().size());
+
+ HSLFTextRun rtrA = trA.getTextRuns().get(0);
+ HSLFTextRun rtrB = trB.getTextRuns().get(0);
+ HSLFTextRun rtrC = trB.getTextRuns().get(1);
+ HSLFTextRun rtrD = trB.getTextRuns().get(2);
+
+ assertEquals(HSLFTextParagraph.getRawText(textRuns.subList(0, 0)), rtrA.getRawText());
+
+ String trBstr = HSLFTextParagraph.getRawText(textRuns.subList(1, 1));
+ assertEquals(trBstr.substring(0, 30), rtrB.getRawText());
+ assertEquals(trBstr.substring(30,58), rtrC.getRawText());
+ assertEquals(trBstr.substring(58,82), rtrD.getRawText());
+
+// assertNull(rtrA._getRawCharacterStyle());
+// assertNull(rtrA._getRawParagraphStyle());
+// assertNotNull(rtrB._getRawCharacterStyle());
+// assertNotNull(rtrB._getRawParagraphStyle());
+// assertNotNull(rtrC._getRawCharacterStyle());
+// assertNotNull(rtrC._getRawParagraphStyle());
+// assertNotNull(rtrD._getRawCharacterStyle());
+// assertNotNull(rtrD._getRawParagraphStyle());
+
+ // Same paragraph styles
+// assertEquals(rtrB._getRawParagraphStyle(), rtrC._getRawParagraphStyle());
+// assertEquals(rtrB._getRawParagraphStyle(), rtrD._getRawParagraphStyle());
+
+ // Different char styles
+// assertFalse( rtrB._getRawCharacterStyle().equals( rtrC._getRawCharacterStyle() ));
+// assertFalse( rtrB._getRawCharacterStyle().equals( rtrD._getRawCharacterStyle() ));
+// assertFalse( rtrC._getRawCharacterStyle().equals( rtrD._getRawCharacterStyle() ));
+ }
+
+ /**
+ * Tests to ensure that setting the text where the text isn't rich,
+ * ensuring that everything stays with the same default styling
+ */
+ @Test
+ public void testSetTextWhereNotRich() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+ HSLFTextParagraph trB = textRuns.get(1);
+// assertEquals(1, trB.getTextRuns().length);
+
+ HSLFTextRun rtrB = trB.getTextRuns().get(0);
+// assertEquals(trB.getRawText(), rtrB.getRawText());
+// assertNull(rtrB._getRawCharacterStyle());
+// assertNull(rtrB._getRawParagraphStyle());
+
+ // Change text via normal
+// trB.setText("Test Foo Test");
+ rtrB = trB.getTextRuns().get(0);
+// assertEquals("Test Foo Test", trB.getRawText());
+// assertEquals("Test Foo Test", rtrB.getRawText());
+// assertNull(rtrB._getRawCharacterStyle());
+// assertNull(rtrB._getRawParagraphStyle());
+ }
+
+ /**
+ * Tests to ensure that setting the text where the text is rich
+ * sets everything to the same styling
+ */
+ @Test
+ public void testSetTextWhereRich() {
+ HSLFSlide slideOne = ssRich.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+ HSLFTextParagraph trB = textRuns.get(1);
+ assertEquals(3, trB.getTextRuns().size());
+
+ HSLFTextRun rtrB = trB.getTextRuns().get(0);
+ HSLFTextRun rtrC = trB.getTextRuns().get(1);
+ HSLFTextRun rtrD = trB.getTextRuns().get(2);
+// TextPropCollection tpBP = rtrB._getRawParagraphStyle();
+// TextPropCollection tpBC = rtrB._getRawCharacterStyle();
+// TextPropCollection tpCP = rtrC._getRawParagraphStyle();
+// TextPropCollection tpCC = rtrC._getRawCharacterStyle();
+// TextPropCollection tpDP = rtrD._getRawParagraphStyle();
+// TextPropCollection tpDC = rtrD._getRawCharacterStyle();
+
+// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
+// assertNotNull(tpBP);
+// assertNotNull(tpBC);
+// assertNotNull(tpCP);
+// assertNotNull(tpCC);
+// assertNotNull(tpDP);
+// assertNotNull(tpDC);
+// assertTrue(tpBP.equals(tpCP));
+// assertTrue(tpBP.equals(tpDP));
+// assertTrue(tpCP.equals(tpDP));
+// assertFalse(tpBC.equals(tpCC));
+// assertFalse(tpBC.equals(tpDC));
+// assertFalse(tpCC.equals(tpDC));
+
+ // Change text via normal
+// trB.setText("Test Foo Test");
+
+ // Ensure now have first style
+// assertEquals(1, trB.getTextRuns().length);
+// rtrB = trB.getTextRuns().get(0);
+// assertEquals("Test Foo Test", trB.getRawText());
+// assertEquals("Test Foo Test", rtrB.getRawText());
+// assertNotNull(rtrB._getRawCharacterStyle());
+// assertNotNull(rtrB._getRawParagraphStyle());
+// assertEquals( tpBP, rtrB._getRawParagraphStyle() );
+// assertEquals( tpBC, rtrB._getRawCharacterStyle() );
+ }
+
+ /**
+ * Test to ensure the right stuff happens if we change the text
+ * in a rich text run, that doesn't happen to actually be rich
+ */
+ @Test
+ public void testChangeTextInRichTextRunNonRich() {
+ HSLFSlide slideOne = ss.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+ HSLFTextParagraph trB = textRuns.get(1);
+// assertEquals(1, trB.getTextRuns().length);
+//
+// HSLFTextRun rtrB = trB.getTextRuns().get(0);
+// assertEquals(trB.getRawText(), rtrB.getRawText());
+// assertNull(rtrB._getRawCharacterStyle());
+// assertNull(rtrB._getRawParagraphStyle());
+
+ // Change text via rich
+// rtrB.setText("Test Test Test");
+// assertEquals("Test Test Test", trB.getRawText());
+// assertEquals("Test Test Test", rtrB.getRawText());
+
+ // Will now have dummy props
+// assertNotNull(rtrB._getRawCharacterStyle());
+// assertNotNull(rtrB._getRawParagraphStyle());
+ }
+
+ /**
+ * Tests to ensure changing the text within rich text runs works
+ * correctly
+ */
+ @Test
+ public void testChangeTextInRichTextRun() {
+ HSLFSlide slideOne = ssRich.getSlides().get(0);
+ List<HSLFTextParagraph> textRuns = slideOne.getTextParagraphs();
+ HSLFTextParagraph trB = textRuns.get(1);
+ assertEquals(3, trB.getTextRuns().size());
+
+ // We start with 3 text runs, each with their own set of styles,
+ // but all sharing the same paragraph styles
+ HSLFTextRun rtrB = trB.getTextRuns().get(0);
+ HSLFTextRun rtrC = trB.getTextRuns().get(1);
+ HSLFTextRun rtrD = trB.getTextRuns().get(2);
+// TextPropCollection tpBP = rtrB._getRawParagraphStyle();
+// TextPropCollection tpBC = rtrB._getRawCharacterStyle();
+// TextPropCollection tpCP = rtrC._getRawParagraphStyle();
+// TextPropCollection tpCC = rtrC._getRawCharacterStyle();
+// TextPropCollection tpDP = rtrD._getRawParagraphStyle();
+// TextPropCollection tpDC = rtrD._getRawCharacterStyle();
+
+ // Check text and stylings
+// assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
+// assertNotNull(tpBP);
+// assertNotNull(tpBC);
+// assertNotNull(tpCP);
+// assertNotNull(tpCC);
+// assertNotNull(tpDP);
+// assertNotNull(tpDC);
+// assertTrue(tpBP.equals(tpCP));
+// assertTrue(tpBP.equals(tpDP));
+// assertTrue(tpCP.equals(tpDP));
+// assertFalse(tpBC.equals(tpCC));
+// assertFalse(tpBC.equals(tpDC));
+// assertFalse(tpCC.equals(tpDC));
+
+ // Check text in the rich runs
+ assertEquals("This is the subtitle, in bold\n", rtrB.getRawText());
+ assertEquals("This bit is blue and italic\n", rtrC.getRawText());
+ assertEquals("This bit is red (normal)", rtrD.getRawText());
+
+ String newBText = "New Subtitle, will still be bold\n";
+ String newCText = "New blue and italic text\n";
+ String newDText = "Funky new normal red text";
+ rtrB.setText(newBText);
+ rtrC.setText(newCText);
+ rtrD.setText(newDText);
+ assertEquals(newBText, rtrB.getRawText());
+ assertEquals(newCText, rtrC.getRawText());
+ assertEquals(newDText, rtrD.getRawText());
+
+// assertEquals(newBText + newCText + newDText, trB.getRawText());
+
+ // The styles should have been updated for the new sizes
+// assertEquals(newBText.length(), tpBC.getCharactersCovered());
+// assertEquals(newCText.length(), tpCC.getCharactersCovered());
+// assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger
+
+// assertEquals(
+// newBText.length() + newCText.length() + newDText.length(),
+// tpBP.getCharactersCovered()
+// );
+
+ // Paragraph style should be sum of text length
+// assertEquals(newBText.length() + newCText.length() + newDText.length(), tpBP.getCharactersCovered());
+
+ // Check stylings still as expected
+// TextPropCollection ntpBC = rtrB._getRawCharacterStyle();
+// TextPropCollection ntpCC = rtrC._getRawCharacterStyle();
+// TextPropCollection ntpDC = rtrD._getRawCharacterStyle();
+// assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
+// assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
+// assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
+ }
+
+
+ /**
+ * Test case for Bug 41015.
+ *
+ * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because
+ * of the wrong list of potential paragraph properties defined in StyleTextPropAtom.
+ *
+ */
+ @Test
+ public void testBug41015() throws IOException {
+ List<HSLFTextRun> rt;
+
+ HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("bug-41015.ppt"));
+ HSLFSlide sl = ppt.getSlides().get(0);
+ List<HSLFTextParagraph> txt = sl.getTextParagraphs();
+ assertEquals(2, txt.size());
+
+ rt = txt.get(0).getTextRuns();
+ assertEquals(1, rt.size());
+ assertEquals(0, txt.get(0).getIndentLevel());
+ assertEquals("sdfsdfsdf", rt.get(0).getRawText());
+
+ rt = txt.get(1).getTextRuns();
+ assertEquals(2, rt.size());
+ assertEquals(0, txt.get(0).getIndentLevel());
+ assertEquals("Sdfsdfsdf\n" +
+ "Dfgdfg\n" +
+ "Dfgdfgdfg\n", rt.get(0).getRawText());
+ assertEquals(1, txt.get(1).getIndentLevel());
+ assertEquals("Sdfsdfs\n" +
+ "Sdfsdf\n", rt.get(1).getRawText());
+ }
+
+ /**
+ * Test creation of TextRun objects.
+ */
+ @Test
+ public void testAddTextRun() {
+ HSLFSlideShow ppt = new HSLFSlideShow();
+ HSLFSlide slide = ppt.createSlide();
+
+ assertNull(slide.getTextParagraphs());
+
+ HSLFTextBox shape1 = new HSLFTextBox();
+// HSLFTextParagraph run1 = shape1.getTextParagraphs();
+// 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.
+// HSLFTextParagraph[] runs = slide.getTextParagraphs();
+// assertNotNull(runs);
+// assertSame(run1, runs.get(0));
+//
+// HSLFTextBox shape2 = new HSLFTextBox();
+// HSLFTextParagraph run2 = shape2.getTextParagraphs();
+// assertSame(run2, shape2.createTextRun());
+// run2.setText("Text 2");
+// slide.addShape(shape2);
+//
+// runs = slide.getTextParagraphs();
+// assertEquals(2, runs.length);
+//
+// assertSame(run1, runs.get(0));
+// assertSame(run2, runs.get(1));
+//
+// //as getShapes()
+// HSLFShape[] sh = slide.getShapes();
+// assertEquals(2, sh.length);
+// assertTrue(sh.get(0) instanceof HSLFTextBox);
+// HSLFTextBox box1 = (HSLFTextBox)sh.get(0);
+// assertSame(run1, box1.getTextParagraphs());
+// HSLFTextBox box2 = (HSLFTextBox)sh.get(1);
+// assertSame(run2, box2.getTextParagraphs());
+//
+// //test Table - a complex group of shapes containing text objects
+// HSLFSlide slide2 = ppt.createSlide();
+// assertNull(slide2.getTextParagraphs());
+// Table table = new Table(2, 2);
+// slide2.addShape(table);
+// runs = slide2.getTextParagraphs();
+// assertNotNull(runs);
+// assertEquals(4, runs.length);
+ }
+
+ @Test
+ public void test48916() throws IOException {
+// HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt"));
+// for(HSLFSlide slide : ppt.getSlides()){
+// for(HSLFShape sh : slide.getShapes()){
+// if(sh instanceof HSLFTextShape){
+// HSLFTextShape tx = (HSLFTextShape)sh;
+// HSLFTextParagraph run = tx.getTextParagraphs();
+// //verify that records cached in TextRun and EscherTextboxWrapper are the same
+// Record[] runChildren = run.getRecords();
+// Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords();
+// assertEquals(runChildren.length, txboxChildren.length);
+// for(int i=0; i < txboxChildren.length; i++){
+// assertSame(txboxChildren.get(i), runChildren.get(i));
+// }
+// //caused NPE prior to fix of Bugzilla #48916
+// run.getTextRuns().get(0).setBold(true);
+// run.getTextRuns().get(0).setFontColor(Color.RED);
+// }
+// }
+// }
+// ByteArrayOutputStream out = new ByteArrayOutputStream();
+// ppt.write(out);
+// ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
+// for(HSLFSlide slide : ppt.getSlides()){
+// for(HSLFShape sh : slide.getShapes()){
+// if(sh instanceof HSLFTextShape){
+// HSLFTextShape tx = (HSLFTextShape)sh;
+// HSLFTextParagraph run = tx.getTextParagraphs();
+// HSLFTextRun rt = run.getTextRuns().get(0);
+// assertTrue(rt.isBold());
+// assertEquals(rt.getFontColor(), Color.RED);
+// }
+// }
+// }
+
+ }
+
+ @Test
+ public void test52244() throws IOException {
+ HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("52244.ppt"));
+ HSLFSlide slide = ppt.getSlides().get(0);
+ List<HSLFTextParagraph> runs = slide.getTextParagraphs();
+
+ assertEquals("Arial", runs.get(0).getTextRuns().get(0).getFontFamily());
+ assertEquals(36, runs.get(0).getTextRuns().get(0).getFontSize(), 0);
+
+ assertEquals("Arial", runs.get(1).getTextRuns().get(0).getFontFamily());
+ assertEquals(24, runs.get(1).getTextRuns().get(0).getFontSize(), 0);
+
+ assertEquals("Arial", runs.get(2).getTextRuns().get(0).getFontFamily());
+ assertEquals(32, runs.get(2).getTextRuns().get(0).getFontSize(), 0);
+
+ }
+
+}