]> source.dussan.org Git - poi.git/commitdiff
Add Yegor's new slide functionality (see bug 38954), with a bit of refactoring
authorNick Burch <nick@apache.org>
Sun, 19 Mar 2006 17:53:49 +0000 (17:53 +0000)
committerNick Burch <nick@apache.org>
Sun, 19 Mar 2006 17:53:49 +0000 (17:53 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@387008 13f79535-47bb-0310-9956-ffa450edef68

24 files changed:
src/scratchpad/src/org/apache/poi/hslf/HSLFSlideShow.java
src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Line.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Notes.java
src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Shape.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/ShapeTypes.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Sheet.java
src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
src/scratchpad/src/org/apache/poi/hslf/record/ColorSchemeAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/FontCollection.java
src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java
src/scratchpad/src/org/apache/poi/hslf/record/PersistPtrHolder.java
src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java
src/scratchpad/src/org/apache/poi/hslf/record/Slide.java
src/scratchpad/src/org/apache/poi/hslf/record/SlideAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java
src/scratchpad/src/org/apache/poi/hslf/record/SlidePersistAtom.java
src/scratchpad/src/org/apache/poi/hslf/record/UserEditAtom.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/SlideShow.java

index f12896a140557174e750caf608bc9e3a23cc2bfa..ed2de1af24244c422bafe134bb51fed2deac2b1b 100644 (file)
@@ -262,6 +262,7 @@ public class HSLFSlideShow
                        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);
                }
@@ -317,6 +318,31 @@ public class HSLFSlideShow
    * 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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java b/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java
new file mode 100644 (file)
index 0000000..9db9501
--- /dev/null
@@ -0,0 +1,60 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Line.java b/src/scratchpad/src/org/apache/poi/hslf/model/Line.java
new file mode 100644 (file)
index 0000000..ea8e32f
--- /dev/null
@@ -0,0 +1,123 @@
+/* ====================================================================\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
index ca1b467a53237263d055abbfac63858352ee9b94..f7fd0038598461a2cf65459996ffa7378066a69c 100644 (file)
@@ -70,4 +70,5 @@ public class Notes extends Sheet
    * Returns the sheet number
    */
   public int getSheetNumber() { return _sheetNo; }
-} 
+  
+  protected PPDrawing getPPDrawing() { return _notes.getPPDrawing(); }} 
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java b/src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
new file mode 100644 (file)
index 0000000..f84d968
--- /dev/null
@@ -0,0 +1,434 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java b/src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java
new file mode 100644 (file)
index 0000000..a4be8e2
--- /dev/null
@@ -0,0 +1,60 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java b/src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
new file mode 100644 (file)
index 0000000..a01b116
--- /dev/null
@@ -0,0 +1,172 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
new file mode 100644 (file)
index 0000000..67f2d70
--- /dev/null
@@ -0,0 +1,61 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeGroup.java
new file mode 100644 (file)
index 0000000..c11e294
--- /dev/null
@@ -0,0 +1,151 @@
+/* ====================================================================\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
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/ShapeTypes.java b/src/scratchpad/src/org/apache/poi/hslf/model/ShapeTypes.java
new file mode 100644 (file)
index 0000000..fd571c1
--- /dev/null
@@ -0,0 +1,257 @@
+/* ====================================================================\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
index ca5c1a565e6dadf3a78932446a9d598920907242..f0834578e77225c312c1068700435e470b92e0c9 100644 (file)
 
 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;
 
 /**
@@ -40,6 +47,11 @@ public abstract class Sheet
    * 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
@@ -106,4 +118,49 @@ public abstract class Sheet
        }
   }
 
+  /**
+   * 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);
+  }
 } 
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java b/src/scratchpad/src/org/apache/poi/hslf/model/SimpleShape.java
new file mode 100644 (file)
index 0000000..7f08b83
--- /dev/null
@@ -0,0 +1,147 @@
+/* ====================================================================\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
index 5719c7e8abc1d48787383a0b2a1895402c848c94..6f374ec050dc981f26e3d82b3c3996dd109a8543 100644 (file)
@@ -86,7 +86,13 @@ public class Slide extends Sheet
                _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
@@ -129,4 +135,6 @@ public class Slide extends Sheet
    * 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(); }
 } 
index 61c67ae61cf1548761901f9484984f437726b4ad..c0b9bf4ec057e5f07b03e110b645c4276bf7e851 100644 (file)
@@ -118,6 +118,27 @@ public class ColorSchemeAtom extends RecordAtom
                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
index 44b584e755999e8f11411676c50b21f175074941..d11ba429e4994d26b4b8d85d9e4b5259def879d0 100644 (file)
@@ -81,8 +81,8 @@ public class FontCollection extends RecordContainer {
         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
     }
index e19bc0a994c78c110ef87ec93f08c595de8d2ade..4cbcca00bf6ba30e9a4e5709231c0861dc4a96f0 100644 (file)
@@ -21,6 +21,7 @@ package org.apache.poi.hslf.record;
 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;
@@ -97,6 +98,20 @@ public class PPDrawing extends RecordAtom
                        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
@@ -188,4 +203,63 @@ public class PPDrawing extends RecordAtom
                // 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
+               };
+       }
 }
index cb5b5dee216756c4c134a6e952b919540b0466f4..34671ee4a31c09f213b905eb34bfdb0464338bc9 100644 (file)
@@ -77,6 +77,13 @@ public class PersistPtrHolder extends PositionDependentRecordAtom
        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.
@@ -104,6 +111,10 @@ public class PersistPtrHolder extends PositionDependentRecordAtom
 
                // 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);
        }
 
        /** 
index cd7aa16b326904e4a300c785f2fd37078bdc144a..996f929093b7ee4da271eab9e8970fbabe9158f6 100644 (file)
@@ -48,17 +48,12 @@ public abstract class RecordContainer extends Record
        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;
        }
        
        /**
index 9717a58c2ee250d8bfb499a4429fcd8c1b2be0ff..06262909ad584cf1ad6293ee54118f8d8dd6a34f 100644 (file)
 
 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,
@@ -73,6 +73,27 @@ public class Slide extends PositionDependentRecordContainer
                }
        }
 
+       /**
+        * 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
index 677b3d8592d9f72ea601c511de40519f2e12c651..f1c4bcb684d0ef6314bc400ce35029a8433d62e5 100644 (file)
@@ -111,6 +111,27 @@ public class SlideAtom extends RecordAtom
                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
@@ -180,6 +201,8 @@ public class SlideAtom extends RecordAtom
 
                /** 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
index ca1f88ff24fe4c671b4ca1a70c13056623d85a5b..560dd1e5b00906760708582d98966632dac87377 100644 (file)
@@ -97,6 +97,17 @@ public class SlideListWithText extends RecordContainer
                }
        }
 
+       /**
+        * 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
index f52bfbfc2a6412ac865cb5846df7e7297a0d0d8b..7c93494fc23b6fe2ddbe3e7a889b07227c57cb82 100644 (file)
@@ -48,6 +48,14 @@ public class SlidePersistAtom extends RecordAtom
        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 ********************** */
 
@@ -84,6 +92,19 @@ public class SlidePersistAtom extends RecordAtom
                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
index 2bc61f8577302614a5df449d6e2e105685589fe8..534dabfce81c8cde678ce17bc88422fab8138103 100644 (file)
@@ -66,6 +66,7 @@ public class UserEditAtom extends PositionDependentRecordAtom
        // 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 ********************** */
 
index ac16539c406e4afec6427307853cff77ba92ac92..c47294495affaa4bc602f1845ef19f6427af2854 100644 (file)
@@ -34,6 +34,8 @@ import org.apache.poi.hslf.record.RecordContainer;
 import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.hslf.record.SlideAtom;
 import org.apache.poi.hslf.record.SlideListWithText;
+import org.apache.poi.hslf.record.SlidePersistAtom;
+import org.apache.poi.hslf.record.UserEditAtom;
 import org.apache.poi.hslf.record.SlideListWithText.*;
 import org.apache.poi.hslf.record.PersistPtrHolder;
 import org.apache.poi.hslf.record.PositionDependentRecord;
@@ -378,74 +380,94 @@ public class SlideShow
         * @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;
        }