]> source.dussan.org Git - poi.git/commitdiff
Fixes from Yegor, from bug #39395
authorNick Burch <nick@apache.org>
Mon, 8 May 2006 16:43:11 +0000 (16:43 +0000)
committerNick Burch <nick@apache.org>
Mon, 8 May 2006 16:43:11 +0000 (16:43 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@405092 13f79535-47bb-0310-9956-ffa450edef68

15 files changed:
src/documentation/content/xdocs/hslf/how-to-shapes.xml
src/documentation/content/xdocs/hslf/hslf_shapes.gif
src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/model/Rectangle.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/model/Shape.java
src/scratchpad/src/org/apache/poi/hslf/model/ShapeFactory.java
src/scratchpad/src/org/apache/poi/hslf/model/Slide.java
src/scratchpad/src/org/apache/poi/hslf/model/TextBox.java
src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/record/RecordTypes.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java
src/scratchpad/testcases/org/apache/poi/hslf/model/TestShapes.java

index 21cdb00d18a592461836abad00797f2895afad40..f20bcef03bfc941bedfe9f4f721fef37c3ab5704 100644 (file)
@@ -18,6 +18,7 @@
                     <li><link href="#GetShapes">How to get shapes contained in a particular slide</link></li>\r
                     <li><link href="#Shapes">Drawing a shape on a slide</link></li>\r
                     <li><link href="#Pictures">How to add/retrieve pictures</link></li>\r
+                    <li><link href="#SlideTitle">How to set slide title</link></li>\r
                 </ul>\r
             </section>\r
             <section><title>Features</title>\r
@@ -62,7 +63,7 @@
                     The following pictute shows the class tree of HSLF shapes:\r
                   </p>\r
                   <p>\r
-                    <img src="hslf_shapes.gif" alt="Class Tree of HSLF Shapes" width="611" height="285"/>\r
+                    <img src="hslf_shapes.gif" alt="Class Tree of HSLF Shapes" width="611" height="412"/>\r
                   </p>\r
                   <p>\r
                     The following fragment demonstrates how to iterate over shapes for each slide.\r
 \r
                     </source>\r
                 </section>\r
+                <anchor id="SlideTitle"/>\r
+                <section><title>How to set slide title</title>\r
+                    <source>\r
+    SlideShow ppt = new SlideShow();\r
+    Slide slide = ppt.createSlide();\r
+    TextBox title = slide.addTitle();\r
+    title.setText("Hello, World!");\r
+    \r
+    //save changes \r
+    FileOutputStream out = new FileOutputStream("slideshow.ppt");\r
+    wb.write(out);\r
+    out.close();\r
+                  </source>\r
+                  <p>\r
+                    Below is the equivalent code in PowerPoint VBA:\r
+                  </p>  \r
+                  <source>\r
+    Set myDocument = ActivePresentation.Slides(1)\r
+    myDocument.Shapes.AddTitle.TextFrame.TextRange.Text = "Hello, World!"\r
+                  </source>\r
+                </section>\r
+                  \r
             </section>\r
         </section>\r
     </body>\r
index 9a078b45ac1c7fe1ad30d1bb55b5d05b15988204..ee5eec9f152eeb32ab85e3948c2be8023644e8d4 100644 (file)
Binary files a/src/documentation/content/xdocs/hslf/hslf_shapes.gif and b/src/documentation/content/xdocs/hslf/hslf_shapes.gif differ
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java b/src/scratchpad/src/org/apache/poi/hslf/model/Ellipse.java
deleted file mode 100644 (file)
index 0c58bdc..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ====================================================================\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 = createSpContainer(parent instanceof ShapeGroup);\r
-    }\r
-\r
-    public Ellipse(){\r
-        this(null);\r
-    }\r
-\r
-    protected EscherContainerRecord createSpContainer(boolean isChild){\r
-        EscherContainerRecord spcont = super.createSpContainer(isChild);\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
index 80f97416cd931e1394e4b2c868d9cdb4e12f8fe0..f7cf9f85ab4d08b3d3fe39416470487a34526912 100644 (file)
@@ -151,7 +151,7 @@ public class PPGraphics2D extends Graphics2D {
          if (font != null){\r
              txt.setFontSize(font.getSize());\r
              txt.setFontName(font.getName());\r
-             //if(getColor() != null) txt.setFontColor(getColor());\r
+             if(getColor() != null) txt.setFontColor(getColor());\r
              if (font.isBold()) txt.setBold(true);\r
              if (font.isItalic()) txt.setItalic(true);\r
          }\r
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java b/src/scratchpad/src/org/apache/poi/hslf/model/Placeholder.java
new file mode 100644 (file)
index 0000000..228eddb
--- /dev/null
@@ -0,0 +1,97 @@
+/* ====================================================================\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.hslf.record.OEPlaceholderAtom;\r
+\r
+import java.util.List;\r
+import java.io.ByteArrayOutputStream;\r
+\r
+/**\r
+ * Represents a Placeholder in PowerPoint.\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+public class Placeholder extends TextBox {\r
+\r
+    protected Placeholder(EscherContainerRecord escherRecord, Shape parent){\r
+        super(escherRecord, parent);\r
+    }\r
+\r
+    public Placeholder(Shape parent){\r
+        super(parent);\r
+    }\r
+\r
+    public Placeholder(){\r
+        super();\r
+    }\r
+\r
+    /**\r
+     * Create a new Placeholder and initialize internal structures\r
+     *\r
+     * @return the created <code>EscherContainerRecord</code> which holds shape data\r
+     */\r
+    protected EscherContainerRecord createSpContainer(boolean isChild){\r
+        EscherContainerRecord spcont = super.createSpContainer(isChild);\r
+\r
+        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);\r
+        spRecord.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HAVEMASTER);\r
+\r
+        EscherClientDataRecord cldata = new EscherClientDataRecord();\r
+        cldata.setOptions((short)15);\r
+\r
+        EscherOptRecord opt = (EscherOptRecord)getEscherChild(spcont, EscherOptRecord.RECORD_ID);\r
+\r
+        //Placeholders can't be grouped\r
+        setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 262144);\r
+\r
+        //OEPlaceholderAtom tells powerpoint that this shape is a placeholder\r
+        //\r
+        OEPlaceholderAtom oep = new OEPlaceholderAtom();\r
+        /**\r
+         * Extarct from MSDN:\r
+         *\r
+         * There is a special case when the placeholder does not have a position in the layout.\r
+         * This occurs when the user has moved the placeholder from its original position.\r
+         * In this case the placeholder ID is -1.\r
+         */\r
+        oep.setPlacementId(-1);\r
+\r
+        oep.setPlaceholderId(OEPlaceholderAtom.Body);\r
+\r
+        //convert hslf into ddf record\r
+        ByteArrayOutputStream out = new ByteArrayOutputStream();\r
+        try {\r
+            oep.writeOut(out);\r
+        } catch(Exception e){\r
+            throw new RuntimeException(e);\r
+        }\r
+        cldata.setRemainingData(out.toByteArray());\r
+\r
+        //append placeholder container before EscherTextboxRecord\r
+        List lst = spcont.getChildRecords();\r
+        for (int i = 0; i < lst.size(); i++) {\r
+              EscherRecord rec = (EscherRecord)lst.get(i);\r
+              if(rec.getRecordId() == EscherTextboxRecord.RECORD_ID){\r
+                  lst.add(i++, cldata);\r
+              }\r
+        }\r
+\r
+        return spcont;\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
deleted file mode 100644 (file)
index 1d69c47..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* ====================================================================\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 rectangle shae in a PowerPoint drawing\r
- *\r
- *  @author Yegor Kozlov\r
- */\r
-public class Rectangle extends TextBox {\r
-\r
-    protected Rectangle(EscherContainerRecord escherRecord, Shape parent){\r
-        super(escherRecord, parent);\r
-    }\r
-\r
-    public Rectangle(Shape parent){\r
-        super(parent);\r
-    }\r
-\r
-    public Rectangle(){\r
-        super();\r
-    }\r
-\r
-    protected EscherContainerRecord createSpContainer(boolean isChild){\r
-        EscherContainerRecord spcont = super.createSpContainer(isChild);\r
-\r
-        EscherSpRecord spRecord = spcont.getChildById(EscherSpRecord.RECORD_ID);\r
-        short type = (ShapeTypes.Rectangle << 4) + 2;\r
-        spRecord.setOptions(type);\r
-\r
-        return spcont;\r
-    }\r
-\r
-}\r
index 666568bfd62d91e92df0c4f48f64c96f0c0bc177..0a51ed8f7c5b7afc5b7707dd6ec5c49675e853e4 100644 (file)
@@ -112,9 +112,27 @@ public abstract class Shape {
         return ShapeTypes.typeName(spRecord.getOptions() >> 4);\r
     }\r
 \r
+    /**\r
+     * @return type of the shape.\r
+     * @see org.apache.poi.hslf.record.RecordTypes\r
+     */\r
+    public int getShapeType(){\r
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+        return spRecord.getOptions() >> 4;\r
+    }\r
+\r
+    /**\r
+     * @param type type of the shape.\r
+     * @see org.apache.poi.hslf.record.RecordTypes\r
+     */\r
+    public void setShapeType(int type){\r
+        EscherSpRecord spRecord = _escherContainer.getChildById(EscherSpRecord.RECORD_ID);\r
+        spRecord.setOptions((short)(type << 4 | 0x2));\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
+     * All coordinates are expressed in points (72 dpi).\r
      *\r
      * @return the anchor of this shape\r
      */\r
@@ -143,7 +161,7 @@ public abstract class Shape {
 \r
     /**\r
      * Sets the anchor (the bounding box rectangle) of this shape.\r
-     * All coordinates should be expressed in poitns (72 dpi).\r
+     * All coordinates should be expressed in points (72 dpi).\r
      *\r
      * @param anchor new anchor\r
      */\r
index 5c7f1c89a94543f47c8530d8e2f3758197e32ff1..f8a86a19632eae0ab9860443a91244833565e894 100644 (file)
@@ -15,8 +15,7 @@
 ==================================================================== */\r
 package org.apache.poi.hslf.model;\r
 \r
-import org.apache.poi.ddf.EscherSpRecord;\r
-import org.apache.poi.ddf.EscherContainerRecord;\r
+import org.apache.poi.ddf.*;\r
 \r
 /**\r
  * Create a <code>Shape</code> object depending on its type\r
@@ -38,12 +37,19 @@ public class ShapeFactory {
 \r
         int type = spRecord.getOptions() >> 4;\r
         switch (type){\r
+            case ShapeTypes.Rectangle:\r
+                EscherTextboxRecord txtbox = (EscherTextboxRecord)Shape.getEscherChild(spContainer, EscherTextboxRecord.RECORD_ID);\r
+                if (txtbox == null) shape = new AutoShape(spContainer, parent);\r
+                else{\r
+                    if(Shape.getEscherChild(spContainer, EscherClientDataRecord.RECORD_ID) != null )\r
+                        shape = new Placeholder(spContainer, parent);\r
+                    else\r
+                        shape = new TextBox(spContainer, parent);\r
+                }\r
+                break;\r
             case ShapeTypes.TextBox:\r
                 shape = new TextBox(spContainer, parent);\r
                 break;\r
-            case ShapeTypes.Rectangle:\r
-                shape = new Rectangle(spContainer, parent);\r
-                break;\r
             case ShapeTypes.PictureFrame:\r
                 shape = new Picture(spContainer, parent);\r
                 break;\r
index 69ee02a439be3dc2f72e23f40984f5449935a801..96ca4a42e986bc495733b9e65a88c648bffcbb06 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Vector;
 
 import org.apache.poi.hslf.record.PPDrawing;
 import org.apache.poi.hslf.record.SlideAtom;
+import org.apache.poi.hslf.record.TextHeaderAtom;
 import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
 
 /**
@@ -117,6 +118,21 @@ public class Slide extends Sheet
                sa.setNotesID(notes._getSheetNumber());
        }
   }
+  
+  /**
+   * Create a <code>TextBox</code> object that represents the slide's title.
+   *
+   * @return <code>TextBox</code> object that represents the slide's title.
+   */
+  public TextBox addTitle() {
+         Placeholder pl = new Placeholder();
+         pl.setShapeType(ShapeTypes.Rectangle);
+         pl.setTextType(TextHeaderAtom.TITLE_TYPE);
+         pl.setText("Click to edit title");
+         pl.setAnchor(new java.awt.Rectangle(54, 48, 612, 90));
+         addShape(pl);
+         return pl;
+  }
 
 
   // Accesser methods follow
@@ -133,7 +149,7 @@ public class Slide extends Sheet
   public int _getSheetRefId() { return _refSheetNo; }
   /**
    * Returns the (internal, SlideIdentifier based) sheet number
-   * @see getSlideNumber()
+   * @see #getSlideNumber()
    */
   public int _getSheetNumber() { return _sheetNo; }
   
@@ -152,5 +168,14 @@ public class Slide extends Sheet
    */
   public Notes getNotesSheet() { return _notes; }
   
+  /**
+   * Returns the PPDrawing associated with this slide, or null if there isn't one
+   */
   protected PPDrawing getPPDrawing() { return _slide.getPPDrawing(); }
+  
+  /**
+   * @return set of records inside <code>SlideListWithtext</code> container
+   *  which hold text data for this slide (typically for placeholders).
+   */
+  protected SlideAtomsSet getSlideAtomsSet() { return _atomSet;  }
 } 
index de1d81c8542ae9f7d92a88c798544c20de6fb13a..465896d61d4d3da7835edc93974041baee2dc189 100644 (file)
@@ -85,6 +85,8 @@ public class TextBox extends SimpleShape {
      */\r
     protected EscherTextboxWrapper _txtbox;\r
 \r
+    private String _fontname;\r
+\r
     /**\r
      * Create a TextBox object and initialize it from the supplied Record container.\r
      * \r
@@ -96,17 +98,6 @@ public class TextBox extends SimpleShape {
 \r
         EscherTextboxRecord textbox = (EscherTextboxRecord)Shape.getEscherChild(_escherContainer, EscherTextboxRecord.RECORD_ID);\r
         _txtbox = new EscherTextboxWrapper(textbox);\r
-        \r
-        // Find our TextRun\r
-        Vector v = new Vector();\r
-        Sheet.findTextRuns(_txtbox.getChildRecords(), v);\r
-        \r
-        // We should just have one\r
-        if(v.size() == 1) {\r
-               _txtrun = (TextRun)v.get(0);\r
-        } else {\r
-               throw new IllegalStateException("A TextBox should have one TextRun's worth of records in it, found " + v.size());\r
-        }\r
     }\r
 \r
     /**\r
@@ -206,6 +197,7 @@ public class TextBox extends SimpleShape {
         } catch (IOException e){\r
             throw new RuntimeException(e);\r
         }\r
+        if(getAnchor().equals(new java.awt.Rectangle())) resizeToFitText();\r
     }\r
 \r
     /**\r
@@ -214,7 +206,7 @@ public class TextBox extends SimpleShape {
      *\r
      * @return  the bounds of this <code>TextFrame</code>.\r
      */\r
-    protected Dimension getTextSize(){\r
+    protected Dimension getTextDimensions(){\r
         FontRenderContext frc = new FontRenderContext(null, true, true);\r
         RichTextRun rt = _txtrun.getRichTextRuns()[0];\r
         int size = rt.getFontSize();\r
@@ -229,9 +221,9 @@ public class TextBox extends SimpleShape {
 \r
         TextLayout layout = new TextLayout(getText(), font, frc);\r
         int width = Math.round(layout.getAdvance());\r
-        width += getMarginLeft() + getMarginRight();\r
+        width += getMarginLeft() + getMarginRight() + 2;\r
         int height = Math.round(layout.getAscent());\r
-        height += getMarginTop() + getMarginBottom();\r
+        height += getMarginTop() + getMarginBottom() + 12;\r
         return new Dimension(width, height);\r
     }\r
 \r
@@ -239,7 +231,7 @@ public class TextBox extends SimpleShape {
      * Adjust the size of the TextBox so it encompasses the text inside it.\r
      */\r
     public void resizeToFitText(){\r
-        Dimension size = getTextSize();\r
+        Dimension size = getTextDimensions();\r
         java.awt.Rectangle anchor = getAnchor();\r
         anchor.setSize(size);\r
         setAnchor(anchor);\r
@@ -448,6 +440,17 @@ public class TextBox extends SimpleShape {
         return rt.getFontSize();\r
     }\r
 \r
+    /**\r
+     *\r
+     * @return  the size of the font applied to this text shape\r
+     */\r
+    public Color getFontColor(){\r
+        RichTextRun rt = _txtrun.getRichTextRuns()[0];\r
+        Color color = new Color(rt.getFontColor());\r
+        //in PowerPont RGB bytes are swapped,\r
+        return new Color(color.getBlue(), color.getGreen(), color.getRed(), 255);\r
+    }\r
+\r
     /**\r
      * Set whether to use bold or not\r
      *\r
@@ -484,8 +487,92 @@ public class TextBox extends SimpleShape {
      * @param name  the name of the font to be applied to this text shape\r
      */\r
     public void setFontName(String name){\r
+        if (_sheet == null) {\r
+            //we can't set font since slideshow is not assigned yet\r
+            _fontname = name;\r
+        } else{\r
         RichTextRun rt = _txtrun.getRichTextRuns()[0];\r
         rt.setFontName(name);\r
     }\r
+    }\r
+\r
+    /**\r
+     * Sets the font color\r
+     * @param color  the font color\r
+     */\r
+    public void setFontColor(Color color){\r
+        //in PowerPont RGB bytes are swapped,\r
+        int rgb = new Color(color.getBlue(), color.getGreen(), color.getRed(), 254).getRGB();\r
+        RichTextRun rt = _txtrun.getRichTextRuns()[0];\r
+        rt.setFontColor(rgb);\r
+    }\r
+\r
+    /**\r
+     * Set type of the text.\r
+     * Must be one of the static constants defined in <code>TextHeaderAtom</code>\r
+     *\r
+     * @param type type of the text\r
+     */\r
+    public void setTextType(int type){\r
+        _txtrun._headerAtom.setTextType(type);\r
+    }\r
     \r
+    public void setSheet(Sheet sheet){\r
+        _sheet = sheet;\r
+\r
+        //initialize _txtrun object.\r
+        //we can't do it in the constructor because the sheet is not assigned yet\r
+        if(_txtrun == null) initTextRun();\r
+\r
+        RichTextRun[] rt = _txtrun.getRichTextRuns();\r
+        for (int i = 0; i < rt.length; i++) {\r
+            rt[i].supplySlideShow(_sheet.getSlideShow());\r
+        }\r
+        if (_fontname != null) {\r
+            setFontName(_fontname);\r
+            _fontname = null;\r
+        }\r
+\r
+    }\r
+\r
+    private void initTextRun(){\r
+\r
+        TextHeaderAtom tha = null;\r
+        TextCharsAtom tca = null;\r
+        TextBytesAtom tba = null;\r
+        StyleTextPropAtom sta = null;\r
+        OutlineTextRefAtom ota = null;\r
+        Record[] child = _txtbox.getChildRecords();\r
+        for (int i = 0; i < child.length; i++) {\r
+            if (child[i] instanceof TextHeaderAtom) tha = (TextHeaderAtom)child[i];\r
+            else if (child[i] instanceof TextBytesAtom) tba = (TextBytesAtom)child[i];\r
+            else if (child[i] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)child[i];\r
+            else if (child[i] instanceof OutlineTextRefAtom) ota = (OutlineTextRefAtom)child[i];\r
+            else if (child[i] instanceof TextCharsAtom) tca = (TextCharsAtom)child[i];\r
+        }\r
+\r
+        if (ota != null){\r
+            //TextHeaderAtom, TextBytesAtom and  StyleTextPropAtom are stored outside of  EscherContainerRecord\r
+            int idx = ota.getTextIndex();\r
+            Slide sl = (Slide)getSheet();\r
+            Record[] rec = sl.getSlideAtomsSet().getSlideRecords();\r
+            for (int i = 0, j = 0; i < rec.length; i++) {\r
+                if(rec[i].getRecordType() == RecordTypes.TextHeaderAtom.typeID){\r
+                    if(j++ == idx) { //we found j-th  TextHeaderAtom, read the text data\r
+                        for (int k = i; k < rec.length; k++) {\r
+                            if (rec[k] instanceof TextHeaderAtom) {\r
+                                if (tha != null) break;\r
+                                else tha = (TextHeaderAtom)rec[k];\r
+                            }\r
+                            else if (rec[k] instanceof TextBytesAtom) tba = (TextBytesAtom)rec[k];\r
+                            else if (rec[k] instanceof TextCharsAtom) tca = (TextCharsAtom)rec[k];\r
+                            else if (rec[k] instanceof StyleTextPropAtom) sta = (StyleTextPropAtom)rec[k];\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        if(tba != null) _txtrun = new TextRun(tha,tba,sta);\r
+        else if (tca != null) _txtrun = new TextRun(tha,tca,sta);\r
+    }\r
 }\r
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OEPlaceholderAtom.java
new file mode 100644 (file)
index 0000000..7c588b9
--- /dev/null
@@ -0,0 +1,200 @@
+\r
+/* ====================================================================\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
+\r
+package org.apache.poi.hslf.record;\r
+\r
+import org.apache.poi.util.LittleEndian;\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+/**\r
+ * OEPlaceholderAtom (3011).\r
+ * <p>\r
+ *  Atom that describes the placeholder.\r
+ * </p>\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+\r
+public class OEPlaceholderAtom extends RecordAtom{\r
+\r
+    public static final int PLACEHOLDER_FULLSIZE = 0;\r
+    public static final int PLACEHOLDER_HALFSIZE = 1;\r
+    public static final int PLACEHOLDER_QUARTSIZE = 2;\r
+\r
+    public static final byte None = 0;\r
+\r
+    public static final byte MasterTitle = 1;\r
+\r
+    public static final byte MasterBody = 2;\r
+\r
+    public static final byte MasterCenteredTitle = 3;\r
+\r
+    public static final byte MasterNotesSlideImage = 4;\r
+\r
+    public static final byte MasterNotesBodyImage = 5;\r
+\r
+    public static final byte MasterDate = 6;\r
+\r
+    public static final byte MasterSlideNumber = 7;\r
+\r
+    public static final byte MasterFooter = 8;\r
+\r
+    public static final byte MasterHeader = 9;\r
+\r
+    public static final byte MasterSubtitle = 10;\r
+\r
+    public static final byte GenericTextObject = 11;\r
+\r
+    public static final byte Title = 12;\r
+\r
+    public static final byte Body = 13;\r
+\r
+    public static final byte NotesBody = 14;\r
+\r
+    public static final byte CenteredTitle = 15;\r
+\r
+    public static final byte Subtitle = 16;\r
+\r
+    public static final byte VerticalTextTitle = 17;\r
+\r
+    public static final byte VerticalTextBody = 18;\r
+\r
+    public static final byte NotesSlideImage = 19;\r
+\r
+    public static final byte Object = 20;\r
+\r
+    public static final byte Graph = 21;\r
+\r
+    public static final byte Table = 22;\r
+\r
+    public static final byte ClipArt = 23;\r
+\r
+    public static final byte OrganizationChart = 24;\r
+\r
+    public static final byte MediaClip = 25;\r
+\r
+       private byte[] _header;\r
+\r
+    private int placementId;\r
+    private int placeholderId;\r
+    private int placeholderSize;\r
+\r
+\r
+    /**\r
+     * Create a new instance of <code>OEPlaceholderAtom</code>\r
+     */\r
+    public OEPlaceholderAtom(){\r
+        _header = new byte[8];\r
+        LittleEndian.putUShort(_header, 0, 0);\r
+        LittleEndian.putUShort(_header, 2, (int)getRecordType());\r
+        LittleEndian.putInt(_header, 4, 8);\r
+\r
+        placementId = 0;\r
+        placeholderId = 0;\r
+        placeholderSize = 0;\r
+    }\r
+\r
+    /**\r
+     * Build an instance of <code>OEPlaceholderAtom</code> from on-disk data\r
+     */\r
+       protected OEPlaceholderAtom(byte[] source, int start, int len) {\r
+               _header = new byte[8];\r
+               System.arraycopy(source,start,_header,0,8);\r
+\r
+        placementId = LittleEndian.getInt(source, start);\r
+        placeholderId = LittleEndian.getUnsignedByte(source, start+4);\r
+        placeholderSize = LittleEndian.getUnsignedByte(source, start+5);\r
+       }\r
+\r
+    /**\r
+     * @return type of this record {@link RecordTypes#OEPlaceholderAtom}.\r
+     */\r
+       public long getRecordType() { return RecordTypes.OEPlaceholderAtom.typeID; }\r
+\r
+    /**\r
+     * Returns the placement Id.\r
+     *\r
+     * @return the placement Id.\r
+     */\r
+    public int getPlacementId(){\r
+        return placementId;\r
+    }\r
+\r
+    /**\r
+     * Sets the placement Id.\r
+     *\r
+     * @param id the placement Id.\r
+     */\r
+   public void setPlacementId(int id){\r
+        placementId = id;\r
+    }\r
+\r
+    /**\r
+     * Returns the placeholder Id.\r
+     *\r
+     * @return the placeholder Id.\r
+     */\r
+    public int getPlaceholderId(){\r
+        return placeholderId;\r
+    }\r
+\r
+    /**\r
+     * Sets the placeholder Id.\r
+     *\r
+     * @param id the placeholder Id.\r
+     */\r
+    public void setPlaceholderId(byte id){\r
+        placeholderId = id;\r
+    }\r
+\r
+    /**\r
+     * Returns the placeholder size.\r
+     * Must be one of the PLACEHOLDER_* static constants defined in this class.\r
+     *\r
+     * @return the placeholder size.\r
+     */\r
+    public int getPlaceholderSize(){\r
+        return placeholderSize;\r
+    }\r
+\r
+    /**\r
+     * Sets the placeholder size.\r
+     * Must be one of the PLACEHOLDER_* static constants defined in this class.\r
+     *\r
+     * @param size the placeholder size.\r
+     */\r
+     public void setPlaceholderSize(byte size){\r
+        placeholderSize = size;\r
+    }\r
+\r
+       /**\r
+        * Write the contents of the record back, so it can be written\r
+        *  to disk\r
+        */\r
+       public void writeOut(OutputStream out) throws IOException {\r
+               out.write(_header);\r
+\r
+        byte[] recdata = new byte[8];\r
+        LittleEndian.putInt(recdata, 0, placementId);\r
+        recdata[4] = (byte)placeholderId;\r
+        recdata[5] = (byte)placeholderSize;\r
+\r
+        out.write(recdata);\r
+       }\r
+}\r
diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/OutlineTextRefAtom.java
new file mode 100644 (file)
index 0000000..ed92d8a
--- /dev/null
@@ -0,0 +1,107 @@
+/* ====================================================================\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.record;\r
+\r
+import org.apache.poi.util.LittleEndian;\r
+\r
+import java.io.OutputStream;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * OEPlaceholderAtom (3998).\r
+ * <br>\r
+ * What MSDN says about  <code>OutlineTextRefAtom</code>:\r
+ * <p>\r
+ * Appears in a slide to indicate a text that is already contained in the document,\r
+ * in a SlideListWithText containter. Sometimes slide texts are not contained\r
+ * within the slide container to be able to delay loading a slide and still display\r
+ * the title and body text in outline view.\r
+ * </p>\r
+ *\r
+ * @author Yegor Kozlov\r
+ */\r
+\r
+public class OutlineTextRefAtom extends RecordAtom {\r
+    /**\r
+     * record header\r
+     */\r
+    private byte[] _header;\r
+\r
+    /**\r
+     * the text's index within the SlideListWithText (0 for title, 1..n for the nth body)\r
+     */\r
+    private int _index;\r
+\r
+    /**\r
+     * Build an instance of <code>OutlineTextRefAtom</code> from on-disk data\r
+     */\r
+    protected OutlineTextRefAtom(byte[] source, int start, int len) {\r
+        // Get the header\r
+        _header = new byte[8];\r
+        System.arraycopy(source,start,_header,0,8);\r
+\r
+        // Grab the record data\r
+        _index = LittleEndian.getInt(source, start+8);\r
+    }\r
+\r
+    /**\r
+     * Create a new instance of <code>FontEntityAtom</code>\r
+     */\r
+    protected OutlineTextRefAtom() {\r
+        _index = 0;\r
+\r
+        _header = new byte[8];\r
+        LittleEndian.putUShort(_header, 0, 0);\r
+        LittleEndian.putUShort(_header, 2, (int)getRecordType());\r
+        LittleEndian.putInt(_header, 4, 4);\r
+    }\r
+\r
+    public long getRecordType() {\r
+        return RecordTypes.OutlineTextRefAtom.typeID;\r
+    }\r
+\r
+    /**\r
+     * Write the contents of the record back, so it can be written to disk\r
+     */\r
+    public void writeOut(OutputStream out) throws IOException {\r
+        out.write(_header);\r
+\r
+        byte[] recdata = new byte[4];\r
+        LittleEndian.putInt(recdata, 0, _index);\r
+        out.write(recdata);\r
+    }\r
+\r
+    /**\r
+     * Sets text's index within the SlideListWithText container\r
+     * (0 for title, 1..n for the nth body).\r
+     *\r
+     * @param idx 0-based text's index\r
+     */\r
+    public void setTextIndex(int idx){\r
+        _index = idx;\r
+    }\r
+\r
+    /**\r
+     * Return text's index within the SlideListWithText container\r
+     * (0 for title, 1..n for the nth body).\r
+     *\r
+     * @return idx text's index\r
+     */\r
+    public int getTextIndex(){\r
+        return _index;\r
+    }\r
+\r
+}\r
index 41935120c1c8175b189539801d6e5c9a84bd16cf..e9b7062d72128bffd8195bb2e8161b9520a65717 100644 (file)
@@ -76,10 +76,10 @@ public class RecordTypes {
     public static final Type ColorSchemeAtom = new Type(2032,ColorSchemeAtom.class);
     public static final Type ExObjRefAtom = new Type(3009,null);
     public static final Type OEShapeAtom = new Type(3009,null);
-    public static final Type OEPlaceholderAtom = new Type(3011,null);
+    public static final Type OEPlaceholderAtom = new Type(3011,OEPlaceholderAtom.class);
     public static final Type GPopublicintAtom = new Type(3024,null);
     public static final Type GRatioAtom = new Type(3031,null);
-    public static final Type OutlineTextRefAtom = new Type(3998,null);
+    public static final Type OutlineTextRefAtom = new Type(3998,OutlineTextRefAtom.class);
     public static final Type TextHeaderAtom = new Type(3999,TextHeaderAtom.class);
     public static final Type TextCharsAtom = new Type(4000,TextCharsAtom.class);
     public static final Type StyleTextPropAtom = new Type(4001,StyleTextPropAtom.class);
index b94250e6c684b9468ef7719d9aadd556c6438ced..bb9bdb5800f7736a06fdf7e6e49fba74122aabbd 100644 (file)
@@ -93,7 +93,7 @@ public class RichTextRun
        /**
         * Supply the SlideShow we belong to
         */
-       protected void supplySlideShow(SlideShow ss) {
+       public void supplySlideShow(SlideShow ss) {
                slideShow = ss;
        }
        
@@ -281,6 +281,21 @@ public class RichTextRun
                return slideShow.getFontCollection().getFontWithId(fontIdx);
        }
        
+       /**
+        * @return font color as RGB value
+        * @see java.awt.Color
+        */
+       public int getFontColor() {
+               return getCharTextPropVal("font.color");
+       }
+       /**
+        * Sets color of the text, as a RGB value
+        * @see java.awt.Color
+        */
+       public void setFontColor(int rgb) {
+               setCharTextPropVal("font.color", rgb);
+       }
+       
        
        // --------------- Internal HSLF methods, not intended for end-user use! -------
        
index ed98fad0abf9c3959ccf6d422ab893715e0a9c7b..a410f8468f60632d48a7967edcb3940796a0a64d 100644 (file)
@@ -25,6 +25,7 @@ import java.awt.Rectangle;
 import java.io.ByteArrayOutputStream;\r
 import java.io.ByteArrayInputStream;\r
 import java.io.FileOutputStream;\r
+import java.util.ArrayList;\r
 \r
 /**\r
  * Test drawing shapes via Graphics2D\r
@@ -132,10 +133,12 @@ public class TestShapes extends TestCase {
         // Create a new textbox, and give it lots of properties\r
         TextBox txtbox = new TextBox();\r
         txtbox.setText(val);\r
+        txtbox.setFontName("Arial");\r
         txtbox.setFontSize(42);\r
         txtbox.setBold(true);\r
         txtbox.setItalic(true);\r
         txtbox.setUnderline(false);\r
+        txtbox.setFontColor(Color.red);\r
         sl.addShape(txtbox);\r
 \r
         // Check it before save\r
@@ -145,6 +148,8 @@ public class TestShapes extends TestCase {
         assertTrue(rt.isBold());\r
         assertTrue(rt.isItalic());\r
         assertFalse(rt.isUnderlined());\r
+        assertEquals("Arial", rt.getFontName());\r
+        assertEquals(Color.red, txtbox.getFontColor());\r
 \r
         // Serialize and read again\r
         ByteArrayOutputStream out = new ByteArrayOutputStream();\r
@@ -162,50 +167,44 @@ public class TestShapes extends TestCase {
         assertTrue(rt.isBold());\r
         assertTrue(rt.isItalic());\r
         assertFalse(rt.isUnderlined());\r
+        assertEquals("Arial", rt.getFontName());\r
+        assertEquals(Color.red, txtbox.getFontColor());\r
     }\r
 \r
     /**\r
-     * Verify that we can add TextBox shapes to a slide\r
-     * and set some of the style attributes, with a unicode string\r
+     * If you iterate over text shapes in a slide and collect them in a set\r
+     * it must be the same as returned by Slide.getTextRuns().\r
      */\r
-    public void testTextBoxWriteChars() throws Exception {\r
-        ppt = new SlideShow();\r
-        Slide sl = ppt.createSlide();\r
-        RichTextRun rt;\r
-\r
-        String val = "Hello, World! (With some \u1234 and \uffee unicode in it)";\r
-\r
-        // Create a new textbox, and give it lots of properties\r
-        TextBox txtbox = new TextBox();\r
-        txtbox.setText(val);\r
-        txtbox.setFontSize(42);\r
-        txtbox.setBold(true);\r
-        txtbox.setUnderline(false);\r
-        sl.addShape(txtbox);\r
-\r
-        // Check it before save\r
-        rt = txtbox.getRichTextRuns()[0];\r
-        assertEquals(val, rt.getText());\r
-        assertEquals(42, rt.getFontSize());\r
-        assertTrue(rt.isBold());\r
-        assertFalse(rt.isItalic());\r
-        assertFalse(rt.isUnderlined());\r
-\r
-        // Serialize and read again\r
-        ByteArrayOutputStream out = new ByteArrayOutputStream();\r
-        ppt.write(out);\r
-        out.close();\r
-\r
-        ppt = new SlideShow(new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray())));\r
+    public void testTextBoxSet() throws Exception {\r
+        textBoxSet("/with_textbox.ppt");\r
+        textBoxSet("/basic_test_ppt_file.ppt");\r
+        textBoxSet("/next_test_ppt_file.ppt");\r
+        textBoxSet("/Single_Coloured_Page.ppt");\r
+        textBoxSet("/Single_Coloured_Page_With_Fonts_and_Alignments.ppt");\r
+        textBoxSet("/incorrect_slide_order.ppt");\r
+    }\r
 \r
-        txtbox = (TextBox)sl.getShapes()[0];\r
-        rt = txtbox.getRichTextRuns()[0];\r
+    private void textBoxSet(String filename) throws Exception {\r
+        String dirname = System.getProperty("HSLF.testdata.path");\r
+        SlideShow ppt = new SlideShow(new HSLFSlideShow(dirname + filename));\r
+        Slide[] sl = ppt.getSlides();\r
+        for (int k = 0; k < sl.length; k++) {\r
+            ArrayList lst1 = new ArrayList();\r
+            TextRun[] txt = sl[k].getTextRuns();\r
+            for (int i = 0; i < txt.length; i++) {\r
+                lst1.add(txt[i].getText());\r
+            }\r
 \r
-        // Check after save\r
-        assertEquals(val, rt.getText());\r
-        assertEquals(42, rt.getFontSize());\r
-        assertTrue(rt.isBold());\r
-        assertFalse(rt.isItalic());\r
-        assertFalse(rt.isUnderlined());\r
+            ArrayList lst2 = new ArrayList();\r
+            Shape[] sh = sl[k].getShapes();\r
+            for (int i = 0; i < sh.length; i++) {\r
+                if (sh[i] instanceof TextBox){\r
+                    TextBox tbox = (TextBox)sh[i];\r
+                    lst2.add(tbox.getText());\r
+                }\r
+            }\r
+            assertTrue(lst1.containsAll(lst2));\r
+            assertTrue(lst2.containsAll(lst1));\r
+        }\r
     }\r
 }\r