int oldPos = pdr.getLastOnDiskOffset();
int newPos = baos.size();
pdr.setLastOnDiskOffset(newPos);
+ //System.out.println(i + " " + oldPos + " " + newPos);
oldToNewPositions.put(new Integer(oldPos),new Integer(newPos));
pdr.updateOtherRecordReferences(oldToNewPositions);
}
* Returns an array of all the records found in the slideshow
*/
public Record[] getRecords() { return _records; }
+
+ /**
+ * 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;
+ }
/**
* Returns an array of the bytes of the file. Only correct after a
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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 org.apache.poi.ddf.*;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * Represents a ellipse in a PowerPoint drawing\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Ellipse extends SimpleShape {\r
+\r
+ protected Ellipse(EscherContainerRecord escherRecord, Shape parent){\r
+ super(escherRecord, parent);\r
+ }\r
+\r
+ public Ellipse(Shape parent){\r
+ super(null, parent);\r
+ _escherContainer = create(parent instanceof ShapeGroup);\r
+ }\r
+\r
+ public Ellipse(){\r
+ this(null);\r
+ }\r
+\r
+ protected EscherContainerRecord create(boolean isChild){\r
+ EscherContainerRecord spcont = super.create(isChild);\r
+ spcont.setOptions((short)15);\r
+\r
+ EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);\r
+ short type = (ShapeTypes.Ellipse << 4) + 2;\r
+ spRecord.setOptions(type);\r
+\r
+ //set default properties for a line\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);\r
+\r
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4));\r
+ opt.sortProperties();\r
+\r
+ return spcont;\r
+ }\r
+\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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 org.apache.poi.ddf.*;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * Represents a line in a PowerPoint drawing\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Line extends SimpleShape {\r
+ /**\r
+ * Solid (continuous) pen\r
+ */\r
+ public static final int LineSolid = 1;\r
+ /**\r
+ * PS_DASH system dash style\r
+ */\r
+ public static final int LineDashSys = 2;\r
+ /**\r
+ * PS_DOT system dash style\r
+ */\r
+ public static final int LineDotSys = 3;\r
+ /**\r
+ * PS_DASHDOT system dash style\r
+ */\r
+ public static final int LineDashDotSys = 4;\r
+\r
+ /**\r
+ * PS_DASHDOTDOT system dash style\r
+ */\r
+ public static final int LineDashDotDotSys = 5;\r
+ /**\r
+ * square dot style\r
+ */\r
+ public static final int LineDotGEL = 6;\r
+ /**\r
+ * dash style\r
+ */\r
+ public static final int LineDashGEL = 7;\r
+ /**\r
+ * long dash style\r
+ */\r
+ public static final int LineLongDashGEL = 8;\r
+ /**\r
+ * dash short dash\r
+ */\r
+ public static final int LineDashDotGEL = 9;\r
+ /**\r
+ * long dash short dash\r
+ */\r
+ public static final int LineLongDashDotGEL = 10;\r
+ /**\r
+ * long dash short dash short dash\r
+ */\r
+ public static final int LineLongDashDotDotGEL = 11;\r
+\r
+ /**\r
+ * Decoration of the end of line,\r
+ * reserved in API but not supported.\r
+ */\r
+\r
+ /**\r
+ * Line ends at end point\r
+ */\r
+ public static final int EndCapFlat = 0;\r
+ /**\r
+ * Rounded ends - the default\r
+ */\r
+ public static final int EndCapRound = 1;\r
+ /**\r
+ * Square protrudes by half line width\r
+ */\r
+ public static final int EndCapSquare = 2;\r
+\r
+ protected Line(EscherContainerRecord escherRecord, Shape parent){\r
+ super(escherRecord, parent);\r
+ }\r
+\r
+ public Line(Shape parent){\r
+ super(null, parent);\r
+ _escherContainer = create(parent instanceof ShapeGroup);\r
+ }\r
+\r
+ public Line(){\r
+ this(null);\r
+ }\r
+\r
+ protected EscherContainerRecord create(boolean isChild){\r
+ EscherContainerRecord spcont = super.create(isChild);\r
+ spcont.setOptions((short)15);\r
+\r
+ EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);\r
+ short type = (ShapeTypes.Line << 4) + 2;\r
+ spRecord.setOptions(type);\r
+ \r
+ //set default properties for a line\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);\r
+\r
+ //opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4));\r
+ opt.sortProperties();\r
+\r
+ return spcont;\r
+ }\r
+\r
+}\r
* Returns the sheet number
*/
public int getSheetNumber() { return _sheetNo; }
-}
+
+ protected PPDrawing getPPDrawing() { return _notes.getPPDrawing(); }}
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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
+package org.apache.poi.hslf.model;\r
+\r
+\r
+import java.awt.*;\r
+import java.awt.Shape;\r
+import java.awt.font.FontRenderContext;\r
+import java.awt.font.GlyphVector;\r
+import java.awt.image.*;\r
+import java.awt.image.renderable.RenderableImage;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.PathIterator;\r
+import java.text.AttributedCharacterIterator;\r
+import java.util.Map;\r
+\r
+import org.apache.poi.ddf.EscherProperties;\r
+\r
+/**\r
+ * Translates Graphics2D calls into PowerPoint.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class PPGraphics2D extends Graphics2D {\r
+ //The group to write the graphics calls into.\r
+ private ShapeGroup group;\r
+\r
+ private AffineTransform transform;\r
+ private Stroke stroke;\r
+ private Paint paint;\r
+ private Font font;\r
+ private Color foreground;\r
+ private Color background = Color.white;\r
+ private Shape clip;\r
+\r
+ /**\r
+ * Construct an powerpoint Graphics object.\r
+ *\r
+ * @param group The shape group to write the graphics calls into.\r
+ */\r
+ public PPGraphics2D(ShapeGroup group){\r
+ this.group = group;\r
+ transform = new AffineTransform();\r
+ }\r
+\r
+ /**\r
+ * @return the shape group being used for drawing\r
+ */\r
+ public ShapeGroup getShapeGroup(){\r
+ return group;\r
+ }\r
+\r
+ public Font getFont(){\r
+ return font;\r
+ }\r
+\r
+ public void setFont(Font font){\r
+ this.font = font;\r
+ }\r
+\r
+ public Color getColor(){\r
+ return foreground;\r
+ }\r
+\r
+ public void setColor(Color color) {\r
+ this.foreground = color;\r
+ }\r
+\r
+ public Stroke getStroke(){\r
+ return stroke;\r
+ }\r
+\r
+ public void setStroke(Stroke s){\r
+ this.stroke = s;\r
+ }\r
+\r
+ public Paint getPaint(){\r
+ return paint;\r
+ }\r
+\r
+ public void setPaint(Paint paint){\r
+ this.paint = paint;\r
+ if (paint instanceof Color) setColor((Color)paint);\r
+ }\r
+\r
+ public AffineTransform getTransform(){\r
+ return (AffineTransform)transform.clone();\r
+ }\r
+\r
+ public void setTransform(AffineTransform trans) {\r
+ transform = (AffineTransform)trans.clone();\r
+ }\r
+\r
+ public void draw(Shape shape){\r
+ if(clip != null) {\r
+ if (!clip.getBounds().contains(transform.createTransformedShape(shape).getBounds())) {\r
+ //return;\r
+ }\r
+ }\r
+\r
+ PathIterator it = shape.getPathIterator(transform);\r
+ double[] prev = null;\r
+ double[] coords = new double[6];\r
+ double[] first = new double[6];\r
+ if(!it.isDone()) it.currentSegment(first); //first point\r
+ while(!it.isDone()){\r
+ int type = it.currentSegment(coords);\r
+ if (prev != null ){\r
+ Line line = new Line(group);\r
+ if (stroke instanceof BasicStroke){\r
+ BasicStroke bs = (BasicStroke)stroke;\r
+ line.setLineWidth(bs.getLineWidth());\r
+ }\r
+ if(getColor() != null) line.setLineColor(getColor());\r
+ if (type == PathIterator.SEG_LINETO) {\r
+ line.setAnchor(new java.awt.Rectangle((int)prev[0], (int)prev[1], (int)(coords[0] - prev[0]), (int)(coords[1] - prev[1])));\r
+ } else if (type == PathIterator.SEG_CLOSE){\r
+ line.setAnchor(new java.awt.Rectangle((int)coords[0], (int)coords[1], (int)(first[0] - coords[0]), (int)(first[1] - coords[1])));\r
+ }\r
+ group.addShape(line);\r
+ }\r
+ prev = new double[]{coords[0], coords[1]};\r
+ it.next();\r
+ }\r
+\r
+ }\r
+\r
+ public void drawString(String string, float x, float y){\r
+ }\r
+\r
+ public void fill(Shape shape){\r
+ if (paint instanceof Color){\r
+ Color color = (Color)paint;\r
+ }\r
+\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void translate(int x, int y) {\r
+ AffineTransform at = new AffineTransform();\r
+ at.translate(x, y);\r
+ transform.concatenate(at);\r
+ }\r
+\r
+ public void clip(Shape shape) {\r
+ this.clip = transform.createTransformedShape(shape);\r
+ //update size of the escher group which holds the drawing\r
+ group.setAnchor(clip.getBounds());\r
+ }\r
+\r
+ public Shape getClip() {\r
+ return clip;\r
+ }\r
+\r
+ public void scale(double sx, double sy) {\r
+ AffineTransform at = new AffineTransform();\r
+ at.scale(sx, sy);\r
+ transform.concatenate(at);\r
+ }\r
+ //===============================================\r
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawString(String str, int x, int y) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void fillOval(int x, int y, int width, int height) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void fillArc(int x, int y, int width, int height,\r
+ int startAngle, int arcAngle) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setPaintMode() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawArc(int x, int y, int width, int height,\r
+ int startAngle, int arcAngle) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+\r
+ public void drawPolyline(int xPoints[], int yPoints[],\r
+ int nPoints) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public Graphics create() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawOval(int x, int y, int width, int height) {\r
+ Ellipse ellipse = new Ellipse();\r
+ ellipse.setAnchor(new java.awt.Rectangle(x-width/2, y-height/2, width, height));\r
+ if (stroke instanceof BasicStroke){\r
+ BasicStroke bs = (BasicStroke)stroke;\r
+ ellipse.setLineWidth(bs.getLineWidth());\r
+ }\r
+ if(getColor() != null) ellipse.setLineColor(getColor());\r
+ if (paint instanceof Color){\r
+ Color color = (Color)paint;\r
+ ellipse.setFillColor(color);\r
+ }\r
+\r
+ group.addShape(ellipse);\r
+ }\r
+\r
+ public void setXORMode(Color color1) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+\r
+ public boolean drawImage(Image img, int x, int y,\r
+ Color bgcolor,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean drawImage(Image img, int x, int y,\r
+ int width, int height,\r
+ Color bgcolor,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+\r
+ public boolean drawImage(Image img,\r
+ int dx1, int dy1, int dx2, int dy2,\r
+ int sx1, int sy1, int sx2, int sy2,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean drawImage(Image img,\r
+ int dx1, int dy1, int dx2, int dy2,\r
+ int sx1, int sy1, int sx2, int sy2,\r
+ Color bgcolor,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean drawImage(Image img, int x, int y,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean drawImage(Image img, int x, int y,\r
+ int width, int height,\r
+ ImageObserver observer) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void dispose() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawLine(int x1, int y1, int x2, int y2) {\r
+ Line line = new Line();\r
+ line.setAnchor(new java.awt.Rectangle(x1, y1, x2-x1, y2-y1));\r
+ if (stroke instanceof BasicStroke){\r
+ BasicStroke bs = (BasicStroke)stroke;\r
+ line.setLineWidth(bs.getLineWidth());\r
+ }\r
+ if(getColor() != null) line.setLineColor(getColor());\r
+ group.addShape(line);\r
+ }\r
+\r
+ public void fillPolygon(int xPoints[], int yPoints[],\r
+ int nPoints) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public FontMetrics getFontMetrics(Font f) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void fillRect(int x, int y, int width, int height) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawPolygon(int xPoints[], int yPoints[],\r
+ int nPoints) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void clipRect(int x, int y, int width, int height) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setClip(Shape clip) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public java.awt.Rectangle getClipBounds() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawString(AttributedCharacterIterator iterator, int x, int y) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void clearRect(int x, int y, int width, int height) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setClip(int x, int y, int width, int height) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void rotate(double d) {\r
+ throw new RuntimeException("Not implemented");\r
+\r
+ }\r
+\r
+ public void rotate(double d, double d1, double d2) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void shear(double d, double d1) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public FontRenderContext getFontRenderContext() {\r
+ return new FontRenderContext(transform, true, true);\r
+ }\r
+\r
+ public void transform(AffineTransform affinetransform) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawImage(BufferedImage bufferedimage, BufferedImageOp op, int x, int y) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setBackground(Color c) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawRenderedImage(RenderedImage renderedimage, AffineTransform affinetransform) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public Color getBackground() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setComposite(Composite composite) {\r
+ throw new RuntimeException("Not implemented");\r
+\r
+ }\r
+\r
+ public Composite getComposite() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public Object getRenderingHint(java.awt.RenderingHints.Key key) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean drawImage(Image image, AffineTransform affinetransform, ImageObserver imageobserver) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setRenderingHint(java.awt.RenderingHints.Key key, Object obj) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+\r
+ public void drawGlyphVector(GlyphVector g, float x, float y) {\r
+ throw new RuntimeException("Not implemented");\r
+\r
+ }\r
+\r
+ public GraphicsConfiguration getDeviceConfiguration() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void addRenderingHints(Map map) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void translate(double d, double d1) {\r
+\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void drawString(AttributedCharacterIterator attributedcharacteriterator, float x, float y) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public boolean hit(java.awt.Rectangle rectangle, Shape shape, boolean flag) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public RenderingHints getRenderingHints() {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+ public void setRenderingHints(Map map) {\r
+ throw new RuntimeException("Not implemented");\r
+\r
+ }\r
+\r
+ public void drawRenderableImage(RenderableImage renderableimage, AffineTransform affinetransform) {\r
+ throw new RuntimeException("Not implemented");\r
+ }\r
+\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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 org.apache.poi.ddf.*;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * Represents a line in a PowerPoint drawing\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Rectangle extends SimpleShape {\r
+\r
+ protected Rectangle(EscherContainerRecord escherRecord, Shape parent){\r
+ super(escherRecord, parent);\r
+ }\r
+\r
+ public Rectangle(Shape parent){\r
+ super(null, parent);\r
+ _escherContainer = create(parent instanceof ShapeGroup);\r
+ }\r
+\r
+ public Rectangle(){\r
+ this(null);\r
+ }\r
+\r
+ protected EscherContainerRecord create(boolean isChild){\r
+ EscherContainerRecord spcont = super.create(isChild);\r
+ spcont.setOptions((short)15);\r
+\r
+ EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);\r
+ short type = (ShapeTypes.Rectangle << 4) + 2;\r
+ spRecord.setOptions(type);\r
+\r
+ //set default properties for a rectangle\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);\r
+\r
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GEOMETRY__SHAPEPATH, 4));\r
+ opt.sortProperties();\r
+\r
+ return spcont;\r
+ }\r
+\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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
+package org.apache.poi.hslf.model;\r
+\r
+import org.apache.poi.ddf.*;\r
+import org.apache.poi.hslf.model.ShapeTypes;\r
+\r
+import java.awt.*;\r
+import java.util.Iterator;\r
+\r
+/**\r
+ * Represents a Shape which is the elemental object that composes a drawing.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Shape {\r
+\r
+ public static final int EMU_PER_POINT = 12700;\r
+\r
+ /**\r
+ * The parent of the shape\r
+ */\r
+ protected Shape _parent;\r
+\r
+ /**\r
+ * Either EscherSpContainer or EscheSpgrContainer record\r
+ * which holds information about this shape.\r
+ */\r
+ protected EscherContainerRecord _escherContainer;\r
+\r
+ protected Shape(EscherContainerRecord escherRecord, Shape parent){\r
+ _escherContainer = escherRecord;\r
+ _parent = parent;\r
+ }\r
+\r
+ /**\r
+ * @return the parent of this shape\r
+ */\r
+ public Shape getParent(){\r
+ return _parent;\r
+ }\r
+\r
+ /**\r
+ * @return name of the shape.\r
+ */\r
+ public String getShapeName(){\r
+ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+ return ShapeTypes.typeName(spRecord.getOptions() >> 4);\r
+ }\r
+\r
+ /**\r
+ * Returns the anchor (the bounding box rectangle) of this shape.\r
+ * All coordinates are expressed in Master units (576 dpi).\r
+ *\r
+ * @return the anchor of this shape\r
+ */\r
+ public java.awt.Rectangle getAnchor(){\r
+ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+ int flags = spRecord.getFlags();\r
+ java.awt.Rectangle anchor=null;\r
+ if ((flags & EscherSpRecord.FLAG_CHILD) != 0){\r
+ EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);\r
+ anchor = new java.awt.Rectangle();\r
+ anchor.x = rec.getDx1();\r
+ anchor.y = rec.getDy1();\r
+ anchor.width = rec.getDx2() - anchor.x;\r
+ anchor.height = rec.getDy2() - anchor.y;\r
+ }\r
+ else {\r
+ EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);\r
+ anchor = new java.awt.Rectangle();\r
+ anchor.y = rec.getFlag();\r
+ anchor.x = rec.getCol1();\r
+ anchor.width = rec.getDx1() - anchor.x;\r
+ anchor.height = rec.getRow1() - anchor.y;\r
+ }\r
+ return anchor;\r
+ }\r
+\r
+ /**\r
+ * Sets the anchor (the bounding box rectangle) of this shape.\r
+ * All coordinates should be expressed in Master units (576 dpi).\r
+ *\r
+ * @param anchor new anchor\r
+ */\r
+ public void setAnchor(java.awt.Rectangle anchor){\r
+ EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+ int flags = spRecord.getFlags();\r
+ if ((flags & EscherSpRecord.FLAG_CHILD) != 0){\r
+ EscherChildAnchorRecord rec = (EscherChildAnchorRecord)getEscherChild(_escherContainer, EscherChildAnchorRecord.RECORD_ID);\r
+ rec.setDx1(anchor.x);\r
+ rec.setDy1(anchor.y);\r
+ rec.setDx2(anchor.width + anchor.x);\r
+ rec.setDy2(anchor.height + anchor.y);\r
+ }\r
+ else {\r
+ EscherClientAnchorRecord rec = (EscherClientAnchorRecord)getEscherChild(_escherContainer, EscherClientAnchorRecord.RECORD_ID);\r
+ rec.setFlag((short)anchor.y);\r
+ rec.setCol1((short)anchor.x);\r
+ rec.setDx1((short)(anchor.width + anchor.x));\r
+ rec.setRow1((short)(anchor.height + anchor.y));\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * Moves the top left corner of the shape to the specified point.\r
+ *\r
+ * @param x the x coordinate of the top left corner of the shape\r
+ * @param y the y coordinate of the top left corner of the shape\r
+ */\r
+ public void moveTo(int x, int y){\r
+ java.awt.Rectangle anchor = getAnchor();\r
+ anchor.setLocation(x, y);\r
+ setAnchor(anchor);\r
+ }\r
+\r
+ protected static EscherRecord getEscherChild(EscherContainerRecord owner, int recordId){\r
+ for ( Iterator iterator = owner.getChildRecords().iterator(); iterator.hasNext(); )\r
+ {\r
+ EscherRecord escherRecord = (EscherRecord) iterator.next();\r
+ if (escherRecord.getRecordId() == recordId)\r
+ return (EscherRecord) escherRecord;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ protected static EscherProperty getEscherProperty(EscherOptRecord opt, int propId){\r
+ for ( Iterator iterator = opt.getEscherProperties().iterator(); iterator.hasNext(); )\r
+ {\r
+ EscherProperty prop = (EscherProperty) iterator.next();\r
+ if (prop.getId() == propId)\r
+ return prop;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ protected static void setEscherProperty(EscherOptRecord opt, short propId, int value){\r
+ java.util.List props = opt.getEscherProperties();\r
+ for ( Iterator iterator = props.iterator(); iterator.hasNext(); ) {\r
+ EscherProperty prop = (EscherProperty) iterator.next();\r
+ if (prop.getId() == propId){\r
+ iterator.remove();\r
+ }\r
+ }\r
+ if (value != -1) {\r
+ opt.addEscherProperty(new EscherSimpleProperty(propId, value));\r
+ opt.sortProperties();\r
+ }\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @return escher container which holds information about this shape\r
+ */\r
+ public EscherContainerRecord getShapeRecord(){\r
+ return _escherContainer;\r
+ }\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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
+package org.apache.poi.hslf.model;\r
+\r
+import org.apache.poi.ddf.EscherSpRecord;\r
+import org.apache.poi.ddf.EscherContainerRecord;\r
+\r
+/**\r
+ * Create a <code>Shape</code> object depending on its type\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class ShapeFactory {\r
+\r
+ public static Shape createShape(EscherContainerRecord spContainer, Shape parent){\r
+ if (spContainer.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){\r
+ return new ShapeGroup(spContainer, parent);\r
+ }\r
+\r
+ Shape shape;\r
+ EscherSpRecord spRecord = spContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+\r
+ int type = spRecord.getOptions() >> 4;\r
+ switch (type){\r
+ case ShapeTypes.TextBox:\r
+ case ShapeTypes.Rectangle:\r
+ shape = new Shape(spContainer, parent);\r
+ break;\r
+ case ShapeTypes.PictureFrame:\r
+ shape = new Shape(spContainer, parent);\r
+ break;\r
+ case ShapeTypes.Line:\r
+ shape = new Line(spContainer, parent);\r
+ break;\r
+ case ShapeTypes.Ellipse:\r
+ shape = new Ellipse(spContainer, parent);\r
+ break;\r
+ case ShapeTypes.NotPrimitive:\r
+ shape = new ShapeGroup(spContainer, parent);\r
+ break;\r
+ default:\r
+ shape = new Shape(spContainer, parent);\r
+ break;\r
+ }\r
+ return shape;\r
+ }\r
+\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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
+package org.apache.poi.hslf.model;\r
+\r
+import org.apache.poi.ddf.*;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+import java.util.List;\r
+\r
+/**\r
+ * Represents a group of shapes.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class ShapeGroup extends Shape{\r
+\r
+ public ShapeGroup(Shape parent){\r
+ super(null, parent);\r
+ _escherContainer = create();\r
+ }\r
+\r
+ public ShapeGroup(){\r
+ this(null);\r
+ }\r
+\r
+ protected ShapeGroup(EscherContainerRecord escherRecord, Shape parent){\r
+ super(escherRecord, parent);\r
+ }\r
+\r
+ /**\r
+ * @return the shapes contained in this group container\r
+ */\r
+ public Shape[] getShapes() {\r
+ //several SpContainers, the first of which is the group shape itself\r
+ List lst = _escherContainer.getChildRecords();\r
+\r
+ //don't include the first SpContainer, it is always NotPrimitive\r
+ Shape[] shapes = new Shape[lst.size() - 1];\r
+ for (int i = 1; i < lst.size(); i++){\r
+ EscherContainerRecord container = (EscherContainerRecord)lst.get(i);\r
+ shapes[i-1] = ShapeFactory.createShape(container, this);\r
+ }\r
+ return shapes;\r
+ }\r
+\r
+ /**\r
+ * Sets the anchor (the bounding box rectangle) of this shape.\r
+ * All coordinates should be expressed in Master units (576 dpi).\r
+ *\r
+ * @param anchor new anchor\r
+ */\r
+ public void setAnchor(java.awt.Rectangle anchor){\r
+\r
+ EscherContainerRecord spContainer = (EscherContainerRecord)_escherContainer.getChildRecords().get(0);\r
+\r
+ EscherClientAnchorRecord clientAnchor = (EscherClientAnchorRecord)getEscherChild(spContainer, EscherClientAnchorRecord.RECORD_ID);\r
+ //hack. internal variable EscherClientAnchorRecord.shortRecord can be\r
+ //initialized only in fillFields(). We need to set shortRecord=false;\r
+ byte[] header = new byte[16];\r
+ LittleEndian.putUShort(header, 0, 0);\r
+ LittleEndian.putUShort(header, 2, 0);\r
+ LittleEndian.putInt(header, 4, 8);\r
+ clientAnchor.fillFields(header, 0, null);\r
+\r
+ clientAnchor.setFlag((short)anchor.y);\r
+ clientAnchor.setCol1((short)anchor.x);\r
+ clientAnchor.setDx1((short)(anchor.width + anchor.x));\r
+ clientAnchor.setRow1((short)(anchor.height + anchor.y));\r
+\r
+ EscherSpgrRecord spgr = (EscherSpgrRecord)getEscherChild(spContainer, EscherSpgrRecord.RECORD_ID);\r
+\r
+ spgr.setRectX1(anchor.x);\r
+ spgr.setRectY1(anchor.y);\r
+ spgr.setRectX2(anchor.x + anchor.width);\r
+ spgr.setRectY2(anchor.y + anchor.height);\r
+ }\r
+\r
+ /**\r
+ * Create a new ShapeGroup and create an instance of <code>EscherSpgrContainer</code> which represents a group of shapes\r
+ */\r
+ protected EscherContainerRecord create() {\r
+ EscherContainerRecord spgr = new EscherContainerRecord();\r
+ spgr.setRecordId(EscherContainerRecord.SPGR_CONTAINER);\r
+ spgr.setOptions((short)15);\r
+\r
+ //The group itself is a shape, and always appears as the first EscherSpContainer in the group container.\r
+ EscherContainerRecord spcont = new EscherContainerRecord();\r
+ spcont.setRecordId(EscherContainerRecord.SP_CONTAINER);\r
+ spcont.setOptions((short)15);\r
+\r
+ EscherSpgrRecord spg = new EscherSpgrRecord();\r
+ spg.setOptions((short)1);\r
+ spcont.addChildRecord(spg);\r
+\r
+ EscherSpRecord sp = new EscherSpRecord();\r
+ short type = (ShapeTypes.NotPrimitive << 4) + 2;\r
+ sp.setOptions(type);\r
+ sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_GROUP);\r
+ spcont.addChildRecord(sp);\r
+\r
+ EscherClientAnchorRecord anchor = new EscherClientAnchorRecord();\r
+ spcont.addChildRecord(anchor);\r
+\r
+ spgr.addChildRecord(spcont);\r
+ return spgr;\r
+ }\r
+\r
+ /**\r
+ * Add a shape to this group.\r
+ *\r
+ * @param shape - the Shape to add\r
+ */\r
+ public void addShape(Shape shape){\r
+ _escherContainer.addChildRecord(shape.getShapeRecord());\r
+ }\r
+\r
+ /**\r
+ * Moves this <code>ShapeGroup</code> to the specified location.\r
+ * <p>\r
+ * @param x the x coordinate of the top left corner of the shape in new location\r
+ * @param y the y coordinate of the top left corner of the shape in new location\r
+ */\r
+ public void moveTo(int x, int y){\r
+ java.awt.Rectangle anchor = getAnchor();\r
+ int dx = x - anchor.x;\r
+ int dy = y - anchor.y;\r
+ anchor.translate(dx, dy);\r
+ setAnchor(anchor);\r
+\r
+ Shape[] shape = getShapes();\r
+ for (int i = 0; i < shape.length; i++) {\r
+ java.awt.Rectangle chanchor = shape[i].getAnchor();\r
+ chanchor.translate(dx, dy);\r
+ shape[i].setAnchor(chanchor);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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
+package org.apache.poi.hslf.model;\r
+\r
+import java.util.HashMap;\r
+import java.lang.reflect.Field;\r
+\r
+/**\r
+ * Contains all known shape types in PowerPoint\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class ShapeTypes {\r
+ public static final int NotPrimitive = 0;\r
+ public static final int Rectangle = 1;\r
+ public static final int RoundRectangle = 2;\r
+ public static final int Ellipse = 3;\r
+ public static final int Diamond = 4;\r
+ public static final int IsocelesTriangle = 5;\r
+ public static final int RightTriangle = 6;\r
+ public static final int Parallelogram = 7;\r
+ public static final int Trapezoid = 8;\r
+ public static final int Hexagon = 9;\r
+ public static final int Octagon = 10;\r
+ public static final int Plus = 11;\r
+ public static final int Star = 12;\r
+ public static final int Arrow = 13;\r
+ public static final int ThickArrow = 14;\r
+ public static final int HomePlate = 15;\r
+ public static final int Cube = 16;\r
+ public static final int Balloon = 17;\r
+ public static final int Seal = 18;\r
+ public static final int Arc = 19;\r
+ public static final int Line = 20;\r
+ public static final int Plaque = 21;\r
+ public static final int Can = 22;\r
+ public static final int Donut = 23;\r
+ public static final int TextSimple = 24;\r
+ public static final int TextOctagon = 25;\r
+ public static final int TextHexagon = 26;\r
+ public static final int TextCurve = 27;\r
+ public static final int TextWave = 28;\r
+ public static final int TextRing = 29;\r
+ public static final int TextOnCurve = 30;\r
+ public static final int TextOnRing = 31;\r
+ public static final int StraightConnector1 = 32;\r
+ public static final int BentConnector2 = 33;\r
+ public static final int BentConnector3 = 34;\r
+ public static final int BentConnector4 = 35;\r
+ public static final int BentConnector5 = 36;\r
+ public static final int CurvedConnector2 = 37;\r
+ public static final int CurvedConnector3 = 38;\r
+ public static final int CurvedConnector4 = 39;\r
+ public static final int CurvedConnector5 = 40;\r
+ public static final int Callout1 = 41;\r
+ public static final int Callout2 = 42;\r
+ public static final int Callout3 = 43;\r
+ public static final int AccentCallout1 = 44;\r
+ public static final int AccentCallout2 = 45;\r
+ public static final int AccentCallout3 = 46;\r
+ public static final int BorderCallout1 = 47;\r
+ public static final int BorderCallout2 = 48;\r
+ public static final int BorderCallout3 = 49;\r
+ public static final int AccentBorderCallout1 = 50;\r
+ public static final int AccentBorderCallout2 = 51;\r
+ public static final int AccentBorderCallout3 = 52;\r
+ public static final int Ribbon = 53;\r
+ public static final int Ribbon2 = 54;\r
+ public static final int Chevron = 55;\r
+ public static final int Pentagon = 56;\r
+ public static final int NoSmoking = 57;\r
+ public static final int Seal8 = 58;\r
+ public static final int Seal16 = 59;\r
+ public static final int Seal32 = 60;\r
+ public static final int WedgeRectCallout = 61;\r
+ public static final int WedgeRRectCallout = 62;\r
+ public static final int WedgeEllipseCallout = 63;\r
+ public static final int Wave = 64;\r
+ public static final int FoldedCorner = 65;\r
+ public static final int LeftArrow = 66;\r
+ public static final int DownArrow = 67;\r
+ public static final int UpArrow = 68;\r
+ public static final int LeftRightArrow = 69;\r
+ public static final int UpDownArrow = 70;\r
+ public static final int IrregularSeal1 = 71;\r
+ public static final int IrregularSeal2 = 72;\r
+ public static final int LightningBolt = 73;\r
+ public static final int Heart = 74;\r
+ public static final int PictureFrame = 75;\r
+ public static final int QuadArrow = 76;\r
+ public static final int LeftArrowCallout = 77;\r
+ public static final int RightArrowCallout = 78;\r
+ public static final int UpArrowCallout = 79;\r
+ public static final int DownArrowCallout = 80;\r
+ public static final int LeftRightArrowCallout = 81;\r
+ public static final int UpDownArrowCallout = 82;\r
+ public static final int QuadArrowCallout = 83;\r
+ public static final int Bevel = 84;\r
+ public static final int LeftBracket = 85;\r
+ public static final int RightBracket = 86;\r
+ public static final int LeftBrace = 87;\r
+ public static final int RightBrace = 88;\r
+ public static final int LeftUpArrow = 89;\r
+ public static final int BentUpArrow = 90;\r
+ public static final int BentArrow = 91;\r
+ public static final int Seal24 = 92;\r
+ public static final int StripedRightArrow = 93;\r
+ public static final int NotchedRightArrow = 94;\r
+ public static final int BlockArc = 95;\r
+ public static final int SmileyFace = 96;\r
+ public static final int VerticalScroll = 97;\r
+ public static final int HorizontalScroll = 98;\r
+ public static final int CircularArrow = 99;\r
+ public static final int NotchedCircularArrow = 100;\r
+ public static final int UturnArrow = 101;\r
+ public static final int CurvedRightArrow = 102;\r
+ public static final int CurvedLeftArrow = 103;\r
+ public static final int CurvedUpArrow = 104;\r
+ public static final int CurvedDownArrow = 105;\r
+ public static final int CloudCallout = 106;\r
+ public static final int EllipseRibbon = 107;\r
+ public static final int EllipseRibbon2 = 108;\r
+ public static final int FlowChartProcess = 109;\r
+ public static final int FlowChartDecision = 110;\r
+ public static final int FlowChartInputOutput = 111;\r
+ public static final int FlowChartPredefinedProcess = 112;\r
+ public static final int FlowChartInternalStorage = 113;\r
+ public static final int FlowChartDocument = 114;\r
+ public static final int FlowChartMultidocument = 115;\r
+ public static final int FlowChartTerminator = 116;\r
+ public static final int FlowChartPreparation = 117;\r
+ public static final int FlowChartManualInput = 118;\r
+ public static final int FlowChartManualOperation = 119;\r
+ public static final int FlowChartConnector = 120;\r
+ public static final int FlowChartPunchedCard = 121;\r
+ public static final int FlowChartPunchedTape = 122;\r
+ public static final int FlowChartSummingJunction = 123;\r
+ public static final int FlowChartOr = 124;\r
+ public static final int FlowChartCollate = 125;\r
+ public static final int FlowChartSort = 126;\r
+ public static final int FlowChartExtract = 127;\r
+ public static final int FlowChartMerge = 128;\r
+ public static final int FlowChartOfflineStorage = 129;\r
+ public static final int FlowChartOnlineStorage = 130;\r
+ public static final int FlowChartMagneticTape = 131;\r
+ public static final int FlowChartMagneticDisk = 132;\r
+ public static final int FlowChartMagneticDrum = 133;\r
+ public static final int FlowChartDisplay = 134;\r
+ public static final int FlowChartDelay = 135;\r
+ public static final int TextPlainText = 136;\r
+ public static final int TextStop = 137;\r
+ public static final int TextTriangle = 138;\r
+ public static final int TextTriangleInverted = 139;\r
+ public static final int TextChevron = 140;\r
+ public static final int TextChevronInverted = 141;\r
+ public static final int TextRingInside = 142;\r
+ public static final int TextRingOutside = 143;\r
+ public static final int TextArchUpCurve = 144;\r
+ public static final int TextArchDownCurve = 145;\r
+ public static final int TextCircleCurve = 146;\r
+ public static final int TextButtonCurve = 147;\r
+ public static final int TextArchUpPour = 148;\r
+ public static final int TextArchDownPour = 149;\r
+ public static final int TextCirclePour = 150;\r
+ public static final int TextButtonPour = 151;\r
+ public static final int TextCurveUp = 152;\r
+ public static final int TextCurveDown = 153;\r
+ public static final int TextCascadeUp = 154;\r
+ public static final int TextCascadeDown = 155;\r
+ public static final int TextWave1 = 156;\r
+ public static final int TextWave2 = 157;\r
+ public static final int TextWave3 = 158;\r
+ public static final int TextWave4 = 159;\r
+ public static final int TextInflate = 160;\r
+ public static final int TextDeflate = 161;\r
+ public static final int TextInflateBottom = 162;\r
+ public static final int TextDeflateBottom = 163;\r
+ public static final int TextInflateTop = 164;\r
+ public static final int TextDeflateTop = 165;\r
+ public static final int TextDeflateInflate = 166;\r
+ public static final int TextDeflateInflateDeflate = 167;\r
+ public static final int TextFadeRight = 168;\r
+ public static final int TextFadeLeft = 169;\r
+ public static final int TextFadeUp = 170;\r
+ public static final int TextFadeDown = 171;\r
+ public static final int TextSlantUp = 172;\r
+ public static final int TextSlantDown = 173;\r
+ public static final int TextCanUp = 174;\r
+ public static final int TextCanDown = 175;\r
+ public static final int FlowChartAlternateProcess = 176;\r
+ public static final int FlowChartOffpageConnector = 177;\r
+ public static final int Callout90 = 178;\r
+ public static final int AccentCallout90 = 179;\r
+ public static final int BorderCallout90 = 180;\r
+ public static final int AccentBorderCallout90 = 181;\r
+ public static final int LeftRightUpArrow = 182;\r
+ public static final int Sun = 183;\r
+ public static final int Moon = 184;\r
+ public static final int BracketPair = 185;\r
+ public static final int BracePair = 186;\r
+ public static final int Seal4 = 187;\r
+ public static final int DoubleWave = 188;\r
+ public static final int ActionButtonBlank = 189;\r
+ public static final int ActionButtonHome = 190;\r
+ public static final int ActionButtonHelp = 191;\r
+ public static final int ActionButtonInformation = 192;\r
+ public static final int ActionButtonForwardNext = 193;\r
+ public static final int ActionButtonBackPrevious = 194;\r
+ public static final int ActionButtonEnd = 195;\r
+ public static final int ActionButtonBeginning = 196;\r
+ public static final int ActionButtonReturn = 197;\r
+ public static final int ActionButtonDocument = 198;\r
+ public static final int ActionButtonSound = 199;\r
+ public static final int ActionButtonMovie = 200;\r
+ public static final int HostControl = 201;\r
+ public static final int TextBox = 202;\r
+\r
+ /**\r
+ * Return name of the shape by id\r
+ * @param type - the id of the shape, one of the static constants defined in this class\r
+ * @return the name of the shape\r
+ */\r
+ public static String typeName(int type) {\r
+ String name = (String)types.get(new Integer(type));\r
+ return name;\r
+ }\r
+\r
+ public static HashMap types;\r
+ static {\r
+ types = new HashMap();\r
+ try {\r
+ Field[] f = ShapeTypes.class.getFields();\r
+ for (int i = 0; i < f.length; i++){\r
+ Object val = f[i].get(null);\r
+ if (val instanceof Integer) {\r
+ types.put(val, f[i].getName());\r
+ }\r
+ }\r
+ } catch (IllegalAccessException e){\r
+ throw new RuntimeException("Failed to initialize shape types");\r
+ }\r
+ }\r
+\r
+}\r
package org.apache.poi.hslf.model;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherDgRecord;
+import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.hslf.record.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import java.util.Vector;
/**
* Returns the sheet number
*/
public abstract int getSheetNumber();
+
+ /**
+ * Fetch the PPDrawing from the underlying record
+ */
+ protected abstract PPDrawing getPPDrawing();
/**
* For a given PPDrawing, grab all the TextRuns
}
}
+ /**
+ * Returns all shapes contained in this Sheet
+ *
+ * @return all shapes contained in this Sheet (Slide or Notes)
+ */
+ public Shape[] getShapes() {
+ PPDrawing ppdrawing = getPPDrawing();
+
+ EscherContainerRecord dg = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
+ EscherContainerRecord spgr = null;
+ List ch = dg.getChildRecords();
+
+ for (Iterator it = ch.iterator(); it.hasNext();) {
+ EscherRecord rec = (EscherRecord)it.next();
+ if (rec.getRecordId() == EscherContainerRecord.SPGR_CONTAINER){
+ spgr = (EscherContainerRecord)rec;
+ break;
+ }
+ }
+ ch = spgr.getChildRecords();
+
+ ArrayList shapes = new ArrayList();
+ for (int i=1;i<ch.size();i++) {
+ EscherContainerRecord sp = (EscherContainerRecord)ch.get(i);
+ shapes.add(ShapeFactory.createShape(sp, null));
+ }
+
+ return (Shape[])shapes.toArray(new Shape[shapes.size()]);
+ }
+
+ /**
+ * Add a new Shape to this Slide
+ *
+ * @param shape - the Shape to add
+ */
+ public void addShape(Shape shape){
+ PPDrawing ppdrawing = getPPDrawing();
+
+ EscherContainerRecord dgContainer = (EscherContainerRecord)ppdrawing.getEscherRecords()[0];
+ EscherContainerRecord spgr = (EscherContainerRecord)Shape.getEscherChild(dgContainer, EscherContainerRecord.SPGR_CONTAINER);
+ spgr.addChildRecord(shape.getShapeRecord());
+
+ EscherDgRecord dg = (EscherDgRecord)Shape.getEscherChild(dgContainer, EscherDgRecord.RECORD_ID);
+ dg.setNumShapes(dg.getNumShapes()+1);
+ }
}
--- /dev/null
+/* ====================================================================\r
+ Copyright 2002-2004 Apache Software Foundation\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ 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 org.apache.poi.ddf.*;\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+import java.awt.*;\r
+\r
+/**\r
+ * An abstract simple (non-group) shape.\r
+ * This is the parent class for all primitive shapes like Line, Rectangle, etc.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class SimpleShape extends Shape {\r
+\r
+ protected SimpleShape(EscherContainerRecord escherRecord, Shape parent){\r
+ super(escherRecord, parent);\r
+ }\r
+\r
+ /**\r
+ * Create a new Shape\r
+ *\r
+ * @param isChild <code>true</code> if the Line is inside a group, <code>false</code> otherwise\r
+ * @return the record container which holds this shape\r
+ */\r
+ protected EscherContainerRecord create(boolean isChild) {\r
+ EscherContainerRecord spContainer = new EscherContainerRecord();\r
+ spContainer.setRecordId( EscherContainerRecord.SP_CONTAINER );\r
+ //spContainer.setOptions((short)15);\r
+\r
+ EscherSpRecord sp = new EscherSpRecord();\r
+ int flags = EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE;\r
+ if (isChild) flags |= EscherSpRecord.FLAG_CHILD;\r
+ sp.setFlags(flags);\r
+ spContainer.addChildRecord(sp);\r
+\r
+ EscherOptRecord opt = new EscherOptRecord();\r
+ opt.setRecordId(EscherOptRecord.RECORD_ID);\r
+ spContainer.addChildRecord(opt);\r
+\r
+ EscherRecord anchor;\r
+ if(isChild) anchor = new EscherChildAnchorRecord();\r
+ else {\r
+ anchor = new EscherClientAnchorRecord();\r
+\r
+ //hack. internal variable EscherClientAnchorRecord.shortRecord can be\r
+ //initialized only in fillFields(). We need to set shortRecord=false;\r
+ byte[] header = new byte[16];\r
+ LittleEndian.putUShort(header, 0, 0);\r
+ LittleEndian.putUShort(header, 2, 0);\r
+ LittleEndian.putInt(header, 4, 8);\r
+ anchor.fillFields(header, 0, null);\r
+ }\r
+ spContainer.addChildRecord(anchor);\r
+\r
+ return spContainer;\r
+ }\r
+\r
+ /**\r
+ * Returns width of the line in in points\r
+ */\r
+ public double getLineWidth(){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH);\r
+ return prop == null ? 0 : (double)prop.getPropertyValue()/EMU_PER_POINT;\r
+ }\r
+\r
+ /**\r
+ * Sets the width of line in in points\r
+ * @param width the width of line in in points\r
+ */\r
+ public void setLineWidth(double width){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ setEscherProperty(opt, EscherProperties.LINESTYLE__LINEWIDTH, (int)(width*EMU_PER_POINT));\r
+ }\r
+\r
+ /**\r
+ * Sets the color of line\r
+ *\r
+ * @param color new color of the line\r
+ */\r
+ public void setLineColor(Color color){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();\r
+ setEscherProperty(opt, EscherProperties.LINESTYLE__COLOR, rgb);\r
+ }\r
+\r
+ /**\r
+ * @return color of the line\r
+ */\r
+ public Color getLineColor(){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ EscherRGBProperty prop = (EscherRGBProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__COLOR);\r
+ Color color = null;\r
+ if (prop != null){\r
+ Color swp = new Color(prop.getRgbColor());\r
+ color = new Color(swp.getBlue(), swp.getGreen(), swp.getRed());\r
+ }\r
+ return color;\r
+ }\r
+\r
+ /**\r
+ * Sets line style. One of the constants defined in this class.\r
+ *\r
+ * @param style new style of the line.\r
+ */\r
+ public void setLineStyle(int style){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ setEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING, style == Line.LineSolid ? -1 : style);\r
+ }\r
+\r
+ /**\r
+ * Returns line style. One of the constants defined in this class.\r
+ *\r
+ * @return style of the line.\r
+ */\r
+ public int getLineStyle(){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ EscherSimpleProperty prop = (EscherSimpleProperty)getEscherProperty(opt, EscherProperties.LINESTYLE__LINEDASHING);\r
+ return prop == null ? Line.LineSolid : prop.getPropertyValue();\r
+ }\r
+\r
+ public void setFillColor(Color color){\r
+ EscherOptRecord opt = (EscherOptRecord)getEscherChild(_escherContainer, EscherOptRecord.RECORD_ID);\r
+ int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 0).getRGB();\r
+ setEscherProperty(opt, EscherProperties.FILL__FILLCOLOR, rgb);\r
+ setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 1376273);\r
+ }\r
+\r
+\r
+}\r
_runs[i] = _otherRuns[k];
}
}
-
+
+ /**
+ * Create a new Slide instance
+ */
+ public Slide(){
+ _slide = new org.apache.poi.hslf.record.Slide();
+ }
/**
* Sets the Notes that are associated with this. Updates the
* Returns the Notes Sheet for this slide, or null if there isn't one
*/
public Notes getNotesSheet() { return _notes; }
+
+ protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); }
}
accentAndHyperlinkColourRGB = (int)LittleEndian.getInt(source,start+8+24);
accentAndFollowingHyperlinkColourRGB = (int)LittleEndian.getInt(source,start+8+28);
}
+
+ /**
+ * Create a new ColorSchemeAtom, to go with a new Slide
+ */
+ public ColorSchemeAtom(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 16);
+ LittleEndian.putUShort(_header, 2, (int)_type);
+ LittleEndian.putInt(_header, 4, 32);
+
+ // Setup the default rgb values
+ backgroundColourRGB = 16777215;
+ textAndLinesColourRGB = 0;
+ shadowsColourRGB = 8421504;
+ titleTextColourRGB = 0;
+ fillsColourRGB = 10079232;
+ accentColourRGB = 13382451;
+ accentAndHyperlinkColourRGB = 16764108;
+ accentAndFollowingHyperlinkColourRGB = 11711154;
+ }
+
/**
* We are of type 3999
fnt.setFontName(name);
fonts.add(name);
- // append new child to the end
- _children = appendChildRecord(fnt,_children);
+ // Append new child to the end
+ appendChildRecord(fnt);
return fonts.size()-1; //the added font is the last in the list
}
import org.apache.poi.util.LittleEndian;
import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.model.ShapeTypes;
import java.io.IOException;
import java.io.OutputStream;
textboxWrappers[i] = (EscherTextboxWrapper)textboxes.get(i);
}
}
+
+ /**
+ * Creates a new, empty, PPDrawing (typically for use with a new Slide
+ * or Notes)
+ */
+ public PPDrawing(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 15);
+ LittleEndian.putUShort(_header, 2, (int)RecordTypes.PPDrawing.typeID);
+ LittleEndian.putInt(_header, 4, 0);
+
+ textboxWrappers = new EscherTextboxWrapper[]{};
+ create();
+ }
/**
* Tree walking way of finding Escher Child Records
// Finally, write out the children
out.write(b);
}
+
+ /**
+ * Create the Escher records associated with a new PPDrawing
+ */
+ private void create(){
+ EscherContainerRecord dgContainer = new EscherContainerRecord();
+ dgContainer.setRecordId( EscherContainerRecord.DG_CONTAINER );
+ dgContainer.setOptions((short)15);
+
+ EscherDgRecord dg = new EscherDgRecord();
+ dg.setOptions((short)16);
+ dg.setNumShapes(1);
+ dgContainer.addChildRecord(dg);
+
+ EscherContainerRecord spgrContainer = new EscherContainerRecord();
+ spgrContainer.setOptions((short)15);
+ spgrContainer.setRecordId(EscherContainerRecord.SPGR_CONTAINER);
+
+ EscherContainerRecord spContainer = new EscherContainerRecord();
+ spContainer.setOptions((short)15);
+ spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
+
+ EscherSpgrRecord spgr = new EscherSpgrRecord();
+ spgr.setOptions((short)1);
+ spContainer.addChildRecord(spgr);
+
+ EscherSpRecord sp = new EscherSpRecord();
+ sp.setOptions((short)((ShapeTypes.NotPrimitive << 4) + 2));
+ sp.setFlags(EscherSpRecord.FLAG_PATRIARCH | EscherSpRecord.FLAG_GROUP);
+ spContainer.addChildRecord(sp);
+ spgrContainer.addChildRecord(spContainer);
+ dgContainer.addChildRecord(spgrContainer);
+
+ spContainer = new EscherContainerRecord();
+ spContainer.setOptions((short)15);
+ spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
+ sp = new EscherSpRecord();
+ sp.setOptions((short)((ShapeTypes.Rectangle << 4) + 2));
+ sp.setFlags(EscherSpRecord.FLAG_BACKGROUND | EscherSpRecord.FLAG_HASSHAPETYPE);
+ spContainer.addChildRecord(sp);
+
+ EscherOptRecord opt = new EscherOptRecord();
+ opt.setRecordId(EscherOptRecord.RECORD_ID);
+ opt.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLCOLOR, 134217728));
+ opt.addEscherProperty(new EscherRGBProperty(EscherProperties.FILL__FILLBACKCOLOR, 134217733));
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__RECTRIGHT, 10064750));
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.FILL__RECTBOTTOM, 7778750));
+ opt.addEscherProperty(new EscherBoolProperty(EscherProperties.FILL__NOFILLHITTEST, 1179666));
+ opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 524288));
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHAPE__BLACKANDWHITESETTINGS, 9));
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.SHAPE__BACKGROUNDSHAPE, 65537));
+ spContainer.addChildRecord(opt);
+
+ dgContainer.addChildRecord(spContainer);
+
+ childRecords = new EscherRecord[]{
+ dgContainer
+ };
+ }
}
public Hashtable getSlideLocationsLookup() {
return _slideLocations;
}
+ /**
+ * Get the lookup from slide numbers to their offsets inside
+ * _ptrData, used when adding or moving slides.
+ */
+ public Hashtable getSlideOffsetDataLocationsLookup() {
+ return _slideOffsetDataLocation;
+ }
/**
* Adds a new slide, notes or similar, to be looked up by this.
// Update the atom header
LittleEndian.putInt(_header,4,newPtrData.length);
+
+ // Update info (first 4 bytes in ptr data)
+ int info = (slideID << 20 | 1);
+ LittleEndian.putInt(_ptrData, 0, info);
}
/**
public boolean isAnAtom() { return false; }
/**
- * Add a new child record onto a record's list of children, and
- * return the new list.
+ * Add a new child record onto a record's list of children.
*/
- public Record[] appendChildRecord(Record newChild, Record[] children) {
- Record[] r;
+ public void appendChildRecord(Record newChild) {
synchronized(addingChildRecordLock) {
- r = new Record[children.length + 1];
- System.arraycopy(children,0,r,0,children.length);
- r[r.length-1] = newChild;
+ addChildAt(newChild, _children.length);
}
- return r;
}
/**
package org.apache.poi.hslf.record;
-import org.apache.poi.util.LittleEndian;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
+
+import org.apache.poi.util.LittleEndian;
/**
* Master container for Slides. There is one of these for every slide,
}
}
+ /**
+ * Create a new, empty, Slide, along with its required
+ * child records.
+ */
+ public Slide(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 15);
+ LittleEndian.putUShort(_header, 2, (int)_type);
+ LittleEndian.putInt(_header, 4, 0);
+
+ slideAtom = new SlideAtom();
+ ppDrawing = new PPDrawing();
+
+ ColorSchemeAtom colorAtom = new ColorSchemeAtom();
+
+ _children = new Record[] {
+ slideAtom,
+ ppDrawing,
+ colorAtom
+ };
+ }
/**
* We are of type 1006
reserved = new byte[len-30];
System.arraycopy(source,start+30,reserved,0,reserved.length);
}
+
+ /**
+ * Create a new SlideAtom, to go with a new Slide
+ */
+ public SlideAtom(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 2);
+ LittleEndian.putUShort(_header, 2, (int)_type);
+ LittleEndian.putInt(_header, 4, 24);
+
+ byte[] ssdate = new byte[12];
+ layoutAtom = new SSlideLayoutAtom(ssdate);
+ layoutAtom.setGeometryType(SSlideLayoutAtom.BLANK_SLIDE);
+
+ followMasterObjects = true;
+ followMasterScheme = true;
+ followMasterBackground = true;
+ masterID = -2147483648;
+ notesID = 0;
+ reserved = new byte[2];
+ }
/**
* We are of type 1007
/** Retrieve the geometry type */
public int getGeometryType() { return geometry; }
+ /** Set the geometry type */
+ public void setGeometryType(int geom) { geometry = geom; }
/**
* Create a new Embeded SSlideLayoutAtom, from 12 bytes of data
}
}
+ /**
+ * Create a new, empty, SlideListWithText
+ */
+ public SlideListWithText(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 15);
+ LittleEndian.putUShort(_header, 2, (int)_type);
+ LittleEndian.putInt(_header, 4, 0);
+
+ _children = new Record[0];
+ }
/**
* Get access to the SlideAtomsSets of the children of this record
public int getSlideIdentifier() { return slideIdentifier; }
public int getNumPlaceholderTexts() { return numPlaceholderTexts; }
public boolean getHasShapesOtherThanPlaceholders() { return hasShapesOtherThanPlaceholders; }
+
+ // Only set these if you know what you're doing!
+ public void setRefID(int id) {
+ refID = id;
+ }
+ public void setSlideIdentifier(int id) {
+ slideIdentifier = id;
+ }
/* *************** record code follows ********************** */
reservedFields = new byte[len-24];
System.arraycopy(source,start+24,reservedFields,0,reservedFields.length);
}
+
+ /**
+ * Create a new SlidePersistAtom, for use with a new Slide
+ */
+ public SlidePersistAtom(){
+ _header = new byte[8];
+ LittleEndian.putUShort(_header, 0, 0);
+ LittleEndian.putUShort(_header, 2, (int)_type);
+ LittleEndian.putInt(_header, 4, 20);
+
+ hasShapesOtherThanPlaceholders = true;
+ reservedFields = new byte[4];
+ }
/**
* We are of type 1011
// More scary internal setters
public void setLastUserEditAtomOffset(int offset) { lastUserEditAtomOffset = offset; }
public void setPersistPointersOffset(int offset) { persistPointersOffset = offset; }
+ public void setLastViewType(short type) { lastViewType=type; }
/* *************** record code follows ********************** */
import org.apache.poi.hslf.record.RecordTypes;
import org.apache.poi.hslf.record.SlideAtom;
import org.apache.poi.hslf.record.SlideListWithText;
+import org.apache.poi.hslf.record.SlidePersistAtom;
+import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.hslf.record.SlideListWithText.*;
import org.apache.poi.hslf.record.PersistPtrHolder;
import org.apache.poi.hslf.record.PositionDependentRecord;
* @throws IOException
*/
public Slide createSlide() throws IOException {
-// RecordContainer slist=null;
-// Record[] rec = doc.getChildRecords();
-// int num = 0;
-// for (int i = 0; i < rec.length; i++) {
-// Record record = rec[i];
-// if (record.getRecordType() == RecordTypes.SlideListWithText.typeID){
-// if (num > 0){
-// slist = (RecordContainer)record;
-// }
-// num++;
-// }
-// }
-// if (num == 1){
-// slist = new SlideListWithText();
-// rec = doc.getChildRecords();
-// for (int i = 0; i < rec.length-1; i++) {
-// Record record = rec[i+1];
-// if (record.getRecordType() == RecordTypes.EndDocument.typeID){
-//
-// doc.addChildAfter(slist, rec[i]);
-// }
-// }
-// }
-// rec = slist.getChildRecords();
-//
-// //add SlidePersistAtom
-// SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1];
-// SlidePersistAtom sp = new SlidePersistAtom();
-//
-// //refernce is the 1-based index of the slide container in the document root.
-// //it always starts with 3 (1 is Document, 2 is MainMaster, 3 is the first slide)
-// sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1));
-// //first slideId is always 256
-// sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
-//
-// Record[] r = slist.appendChildRecord(sp,
-// slist.getChildRecords() == null ? new Record[]{} : slist.getChildRecords());
-// slist.setChildRecords(r);
-// Slide slide = new Slide();
-//
-// int offset = 0;
-// List lst = new ArrayList();
-// for (int i = 0; i < _records.length; i++) {
-// Record record = _records[i];
-// lst.add(record);
-// ByteArrayOutputStream out = new ByteArrayOutputStream();
-// record.writeOut(out);
-//
-// if (_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
-// lst.add(i, slide.getSlideRecord());
-//
-// slide.getSlideRecord().setLastOnDiskOffset(offset);
-// PersistPtrHolder ptr = (PersistPtrHolder)_records[i];
-// int id = sp.getRefID();
-// ptr.getSlideDataLocationsLookup().put(new Integer(id), new Integer((i+1)*4));
-// ptr.getSlideLocationsLookup().put(new Integer(id), new Integer(offset));
-// ptr.addSlideLookup(id, offset);
-//
-// }
-// offset += out.size() ;
-// }
-// _records = (Record[])lst.toArray(new Record[lst.size()]);
-// _hslfSlideShow.setRecords(_records);
-//
-// UserEditAtom usr = (UserEditAtom)_records[_records.length-1];
-// usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW);
-// return slide;
- return null;
+ SlideListWithText[] slwts = _documentRecord.getSlideListWithTexts();
+ SlideListWithText slist = null;
+
+ if(slwts.length > 1) {
+ // Just use the last one
+ slist = slwts[slwts.length - 1];
+ } else {
+ // Need to add a new one
+ slist = new SlideListWithText();
+
+ // Goes in just before the EndDocumentRecord
+ Record[] docChildren = _documentRecord.getChildRecords();
+ Record endDoc = docChildren[docChildren.length - 1];
+ if(endDoc.getRecordType() != RecordTypes.EndDocument.typeID) {
+ throw new IllegalStateException("The last child record of a Document should be EndDocument, but it was " + endDoc);
+ }
+ _documentRecord.addChildBefore(slist, endDoc);
+ }
+
+ Record[] rec = slist.getChildRecords();
+
+ // Add SlidePersistAtom
+ SlidePersistAtom prev = rec.length == 0 ? null : (SlidePersistAtom)rec[rec.length - 1];
+ SlidePersistAtom sp = new SlidePersistAtom();
+
+ // Refernce is the 1-based index of the slide container in
+ // the document root.
+ // It always starts with 3 (1 is Document, 2 is MainMaster, 3 is
+ // the first slide)
+ sp.setRefID(prev == null ? 3 : (prev.getRefID() + 1));
+ // First slideId is always 256
+ sp.setSlideIdentifier(prev == null ? 256 : (prev.getSlideIdentifier() + 1));
+
+ slist.appendChildRecord(sp);
+
+ // Create a new Slide
+ Slide slide = new Slide();
+ Slide[] s = new Slide[_slides.length+1];
+ System.arraycopy(_slides, 0, s, 0, _slides.length);
+ s[_slides.length] = slide;
+ _slides = s;
+ System.out.println("Added slide " + _slides.length + " with ref " + sp.getRefID() + " and identifier " + sp.getSlideIdentifier());
+
+ // Add in to the core records
+ org.apache.poi.hslf.record.Slide slideRecord = slide.getSlideRecord();
+ int slideRecordPos = _hslfSlideShow.appendRootLevelRecord(slideRecord);
+
+ // Add the new Slide into the PersistPtr stuff
+ int offset = 0;
+ int slideOffset = 0;
+ PersistPtrHolder ptr = null;
+ UserEditAtom usr = null;
+ for (int i = 0; i < _records.length; i++) {
+ Record record = _records[i];
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ record.writeOut(out);
+
+ // Grab interesting records as they come past
+ if(_records[i].getRecordType() == RecordTypes.PersistPtrIncrementalBlock.typeID){
+ ptr = (PersistPtrHolder)_records[i];
+ }
+ if(_records[i].getRecordType() == RecordTypes.UserEditAtom.typeID) {
+ usr = (UserEditAtom)_records[i];
+ }
+
+ if(i == slideRecordPos) {
+ slideOffset = offset;
+ }
+ offset += out.size();
+ }
+
+ // Add the new slide into the last PersistPtr
+ slideRecord.setLastOnDiskOffset(slideOffset);
+ int id = sp.getRefID();
+ ptr.getSlideOffsetDataLocationsLookup().put(
+ new Integer(id),
+ new Integer((slideRecordPos+1)*4)
+ );
+ ptr.getSlideLocationsLookup().put(
+ new Integer(id), new Integer(slideOffset));
+ ptr.addSlideLookup(id, slideOffset);
+ System.out.println("New slide ended up at " + slideOffset);
+
+ // Last view is now of the slide
+ usr.setLastViewType((short)UserEditAtom.LAST_VIEW_SLIDE_VIEW);
+
+ // All done and added
+ return slide;
}