]> source.dussan.org Git - poi.git/commitdiff
Fixed TextRun handling and various junit tests
authorAndreas Beeker <kiwiwings@apache.org>
Wed, 10 Jun 2015 22:23:47 +0000 (22:23 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Wed, 10 Jun 2015 22:23:47 +0000 (22:23 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/common_sl@1684773 13f79535-47bb-0310-9956-ffa450edef68

62 files changed:
src/examples/src/org/apache/poi/hslf/examples/ApacheconEU08.java
src/examples/src/org/apache/poi/hslf/examples/Graphics2DDemo.java
src/examples/src/org/apache/poi/hslf/examples/TableDemo.java
src/java/org/apache/poi/ddf/EscherChildAnchorRecord.java
src/java/org/apache/poi/ddf/EscherProperties.java
src/java/org/apache/poi/ddf/EscherTextboxRecord.java
src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFGroupShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSlide.java
src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/extractor/PowerPointExtractor.java
src/scratchpad/src/org/apache/poi/hslf/model/Line.java
src/scratchpad/src/org/apache/poi/hslf/model/Table.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java [deleted file]
src/scratchpad/src/org/apache/poi/hslf/model/textproperties/TextPropCollection.java
src/scratchpad/src/org/apache/poi/hslf/record/EscherTextboxWrapper.java
src/scratchpad/src/org/apache/poi/hslf/record/PPDrawing.java
src/scratchpad/src/org/apache/poi/hslf/record/RecordContainer.java
src/scratchpad/src/org/apache/poi/hslf/record/SlideListWithText.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFGroupShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFNotes.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureData.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFPictureShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShapeFactory.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSheet.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlide.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideMaster.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextParagraph.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextRun.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTextShape.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTitleMaster.java
src/scratchpad/src/org/apache/poi/sl/draw/DrawFactory.java
src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/sl/draw/DrawShape.java
src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java [deleted file]
src/scratchpad/src/org/apache/poi/sl/draw/Drawable.java
src/scratchpad/src/org/apache/poi/sl/draw/ImageRenderer.java
src/scratchpad/src/org/apache/poi/sl/usermodel/GroupShape.java [new file with mode: 0644]
src/scratchpad/src/org/apache/poi/sl/usermodel/PictureShape.java
src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java [deleted file]
src/scratchpad/src/org/apache/poi/sl/usermodel/Sheet.java
src/scratchpad/testcases/org/apache/poi/hslf/model/AllHSLFModelTests.java
src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java [deleted file]
src/scratchpad/testcases/org/apache/poi/hslf/model/TestTable.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestAddingSlides.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBugs.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestFontRendering.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestNumberedList3.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPicture.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestPictures.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTable.java
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestTextRun.java
test-data/slideshow/54541_cropped_bitmap2.ppt [new file with mode: 0644]
test-data/slideshow/sample_pptx_grouping_issues.pptx [new file with mode: 0644]

index 494c7f9c3209daedc21b2fff7cc9b10286fc0670..c27e8e4e8e93208b5db9c962357868b3a4b3cad1 100644 (file)
@@ -146,10 +146,10 @@ public final class ApacheconEU08 {
             {"Note"},
             {"This presentation was created programmatically using POI HSLF"}
         };
-        Table table1 = new Table(2, 1);
+        HSLFTable table1 = new HSLFTable(2, 1);
         for (int i = 0; i < txt1.length; i++) {
             for (int j = 0; j < txt1[i].length; j++) {
-                TableCell cell = table1.getCell(i, j);
+                HSLFTableCell cell = table1.getCell(i, j);
                 cell.setText(txt1[i][j]);
                 HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
                 rt.setFontSize(10);
index 19fe496769651810a094a9b0caf1a839bd478a75..cd900902d8874b6a7279dbb11593f8fa40033565 100644 (file)
@@ -50,7 +50,7 @@ public final class Graphics2DDemo {
         //define position of the drawing in the slide
         Rectangle bounds = new java.awt.Rectangle(200, 100, 350, 300);
         group.setAnchor(bounds);
-        group.setCoordinates(new java.awt.Rectangle(0, 0, 100, 100));
+        group.setInteriorAnchor(new java.awt.Rectangle(0, 0, 100, 100));
         slide.addShape(group);
         Graphics2D graphics = new PPGraphics2D(group);
 
@@ -68,7 +68,7 @@ public final class Graphics2DDemo {
         }
         graphics.setColor(Color.black);
         graphics.setFont(new Font("Arial", Font.BOLD, 14));
-        graphics.draw(group.getCoordinates());
+        graphics.draw(group.getInteriorAnchor());
         graphics.drawString("Performance", x + 30, y + 10);
 
         FileOutputStream out = new FileOutputStream("hslf-graphics.ppt");
index abc40750cc359034fbbb6c456fa78c48469d577b..b931ba1b57295a30d9018d432e332e6d9900338b 100644 (file)
@@ -49,10 +49,10 @@ public final class TableDemo {
         HSLFSlide slide = ppt.createSlide();
 
         //six rows, two columns
-        Table table1 = new Table(6, 2);
+        HSLFTable table1 = new HSLFTable(6, 2);
         for (int i = 0; i < txt1.length; i++) {
             for (int j = 0; j < txt1[i].length; j++) {
-                TableCell cell = table1.getCell(i, j);
+                HSLFTableCell cell = table1.getCell(i, j);
                 HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
                 rt.setFontFamily("Arial");
                 rt.setFontSize(10);
@@ -88,10 +88,10 @@ public final class TableDemo {
         };
 
         //two rows, one column
-        Table table2 = new Table(2, 1);
+        HSLFTable table2 = new HSLFTable(2, 1);
         for (int i = 0; i < txt2.length; i++) {
             for (int j = 0; j < txt2[i].length; j++) {
-                TableCell cell = table2.getCell(i, j);
+                HSLFTableCell cell = table2.getCell(i, j);
                 HSLFTextRun rt = cell.getTextParagraphs().get(0).getTextRuns().get(0);
                 rt.setFontSize(10);
                 rt.setFontFamily("Arial");
index b6193cea4eea7f1b591f145cafb8240efddef072..bbb84bae8c50d817d51c1e24b381cf4e78182dad 100644 (file)
@@ -40,13 +40,26 @@ public class EscherChildAnchorRecord
     private int field_4_dy2;
 
     public int fillFields(byte[] data, int offset, EscherRecordFactory recordFactory) {
-        /*int bytesRemaining =*/ readHeader( data, offset );
+        int bytesRemaining = readHeader( data, offset );
         int pos            = offset + 8;
         int size           = 0;
-        field_1_dx1    =  LittleEndian.getInt( data, pos + size );size+=4;
-        field_2_dy1    =  LittleEndian.getInt( data, pos + size );size+=4;
-        field_3_dx2  =  LittleEndian.getInt( data, pos + size );size+=4;
-        field_4_dy2 =  LittleEndian.getInt( data, pos + size );size+=4;
+        switch (bytesRemaining) {
+        case 16: // RectStruct
+            field_1_dx1 =  LittleEndian.getInt( data, pos + size );size+=4;
+            field_2_dy1 =  LittleEndian.getInt( data, pos + size );size+=4;
+            field_3_dx2 =  LittleEndian.getInt( data, pos + size );size+=4;
+            field_4_dy2 =  LittleEndian.getInt( data, pos + size );size+=4;
+            break;
+        case 8: // SmallRectStruct
+            field_1_dx1 =  LittleEndian.getShort( data, pos + size );size+=2;
+            field_2_dy1 =  LittleEndian.getShort( data, pos + size );size+=2;
+            field_3_dx2 =  LittleEndian.getShort( data, pos + size );size+=2;
+            field_4_dy2 =  LittleEndian.getShort( data, pos + size );size+=2;
+            break;
+        default:
+            throw new RuntimeException("Invalid EscherChildAnchorRecord - neither 8 nor 16 bytes.");
+        }
+            
         return 8 + size;
     }
 
@@ -58,8 +71,8 @@ public class EscherChildAnchorRecord
         LittleEndian.putInt( data, pos, getRecordSize()-8 );       pos += 4;
         LittleEndian.putInt( data, pos, field_1_dx1 );             pos += 4;
         LittleEndian.putInt( data, pos, field_2_dy1 );             pos += 4;
-        LittleEndian.putInt( data, pos, field_3_dx2 );           pos += 4;
-        LittleEndian.putInt( data, pos, field_4_dy2 );          pos += 4;
+        LittleEndian.putInt( data, pos, field_3_dx2 );             pos += 4;
+        LittleEndian.putInt( data, pos, field_4_dy2 );             pos += 4;
 
         listener.afterRecordSerialize( pos, getRecordId(), pos - offset, this );
         return pos - offset;
index 7ec219006bc9c692a0a111dfe5611fcb9cc1cae3..2bee6b92e5f7d8446ade3a1542b16c9929cacf2b 100644 (file)
@@ -507,7 +507,7 @@ public final class EscherProperties {
                addProp(m, SHADOWSTYLE__ORIGINX, "shadowstyle.originx");
                addProp(m, SHADOWSTYLE__ORIGINY, "shadowstyle.originy");
                addProp(m, SHADOWSTYLE__SHADOW, "shadowstyle.shadow");
-               addProp(m, SHADOWSTYLE__SHADOWOBSURED, "shadowstyle.shadowobsured");
+               addProp(m, SHADOWSTYLE__SHADOWOBSURED, "shadowstyle.shadowobscured");
                addProp(m, PERSPECTIVE__TYPE, "perspective.type");
                addProp(m, PERSPECTIVE__OFFSETX, "perspective.offsetx");
                addProp(m, PERSPECTIVE__OFFSETY, "perspective.offsety");
index c21c22796801b5329c65acd31b2b7df4cb2fd8b0..dbf28531fe828dfea4beb2afb093e8fc286e8c1d 100644 (file)
@@ -17,6 +17,7 @@
 
 package org.apache.poi.ddf;
 
+import org.apache.poi.hslf.record.RecordTypes;
 import org.apache.poi.util.HexDump;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.RecordFormatException;
@@ -32,7 +33,7 @@ import org.apache.poi.util.RecordFormatException;
  */
 public class EscherTextboxRecord extends EscherRecord
 {
-    public static final short RECORD_ID = (short)0xF00D;
+    public static final short RECORD_ID = (short)RecordTypes.EscherClientTextbox;
     public static final String RECORD_DESCRIPTION = "msofbtClientTextbox";
 
     private static final byte[] NO_BYTES = new byte[0];
index beadac4646bff259e55e9b52a6ec960075980267..8ada60169754d88c5f16526180b6fb8458043636 100644 (file)
@@ -28,6 +28,7 @@ import java.awt.image.ImageObserver;
 import java.awt.image.RenderedImage;\r
 import java.awt.image.renderable.RenderableImage;\r
 import java.text.AttributedCharacterIterator;\r
+import java.util.Arrays;\r
 import java.util.Map;\r
 \r
 public class DummyGraphics2d\r
@@ -262,7 +263,7 @@ public class DummyGraphics2d
 \r
     public void setPaint( Paint paint )\r
     {\r
-        System.out.println( "setPain(Paint):" );\r
+        System.out.println( "setPaint(Paint):" );\r
         System.out.println( "paint = " + paint );\r
         g2D.setPaint( paint );\r
     }\r
@@ -285,7 +286,19 @@ public class DummyGraphics2d
     public void setStroke(Stroke s)\r
     {\r
         System.out.println( "setStroke(Stoke):" );\r
-        System.out.println( "s = " + s );\r
+        if (s instanceof BasicStroke) {\r
+            BasicStroke bs = (BasicStroke)s;\r
+            StringBuilder str = new StringBuilder("s = BasicStroke(");\r
+            str.append("dash[]: "+Arrays.toString(bs.getDashArray())+", ");\r
+            str.append("dashPhase: "+bs.getDashPhase()+", ");\r
+            str.append("endCap: "+bs.getEndCap()+", ");\r
+            str.append("lineJoin: "+bs.getLineJoin()+", ");\r
+            str.append("width: "+bs.getLineWidth()+", ");\r
+            str.append("miterLimit: "+bs.getMiterLimit()+")");\r
+            System.out.println(str.toString());\r
+        } else {\r
+            System.out.println( "s = " + s );\r
+        }\r
         g2D.setStroke( s );\r
     }\r
 \r
index 685ae46da5414d0ba4d20aabecc7e6043841eb62..309f39fd9f0b9ba4f3098556f1cfd6cca6c5fb13 100644 (file)
@@ -25,8 +25,7 @@ import java.util.List;
 import java.util.regex.Pattern;\r
 \r
 import org.apache.poi.openxml4j.opc.*;\r
-import org.apache.poi.sl.usermodel.PlaceableShape;\r
-import org.apache.poi.sl.usermodel.ShapeGroup;\r
+import org.apache.poi.sl.usermodel.GroupShape;\r
 import org.apache.poi.util.*;\r
 import org.apache.xmlbeans.XmlObject;\r
 import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
@@ -38,7 +37,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.*;
  * @author Yegor Kozlov\r
  */\r
 @Beta\r
-public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, ShapeGroup<XSLFShape> {\r
+public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, GroupShape<XSLFShape> {\r
     private static POILogger _logger = POILogFactory.getLogger(XSLFGroupShape.class);\r
     \r
     private final List<XSLFShape> _shapes;\r
@@ -118,7 +117,7 @@ public class XSLFGroupShape extends XSLFShape implements XSLFShapeContainer, Sha
      * used for calculations of grouping, scaling, and rotation\r
      * behavior of shapes placed within a group.\r
      */\r
-    public void setInteriorAnchor(Rectangle2D anchor){\r
+    public void setInteriorAnchor(Rectangle2D anchor) {\r
         CTGroupTransform2D xfrm = getSafeXfrm();\r
         CTPoint2D off = xfrm.isSetChOff() ? xfrm.getChOff() : xfrm.addNewChOff();\r
         long x = Units.toEMU(anchor.getX());\r
index b815e00d426266e98fa4563a956bcd59035989f9..3d532bb9537e102e61443d36892281d9ccce0191 100644 (file)
@@ -169,6 +169,7 @@ public class XSLFPictureShape extends XSLFSimpleShape implements PictureShape {
         return id;\r
     }\r
 \r
+    @Override\r
     public Insets getClipping(){\r
         CTPicture ct = (CTPicture)getXmlObject();\r
         CTRelativeRect r = ct.getBlipFill().getSrcRect();\r
index 43ec701301a1dc0968d4ba0c08d3ef9bcaa1a7fa..e1fff264cac36bf50fe50d7f26c48c265db37d72 100644 (file)
@@ -481,6 +481,7 @@ public abstract class XSLFSheet extends POIXMLDocumentPart implements XSLFShapeC
      *
      * @param graphics
      */
+    @Override
     public void draw(Graphics2D graphics){
         DrawFactory drawFact = DrawFactory.getInstance(graphics);
         Drawable draw = drawFact.getDrawable(this);
index b6ee1bc8e25b7c7ebdac0d558dc52393ab1f1ee6..8b5e596702fde57e5036c725c5f2c71cbf416cb3 100644 (file)
@@ -21,7 +21,6 @@ import java.io.IOException;
 import org.apache.poi.POIXMLDocumentPart;
 import org.apache.poi.openxml4j.opc.PackagePart;
 import org.apache.poi.openxml4j.opc.PackageRelationship;
-import org.apache.poi.sl.usermodel.Notes;
 import org.apache.poi.sl.usermodel.Slide;
 import org.apache.poi.util.Beta;
 import org.apache.xmlbeans.XmlException;
diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/BitmapPainter.java
deleted file mode 100644 (file)
index cfeffb8..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.blip;
-
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFPictureShape;
-import org.apache.poi.util.POILogger;
-import org.apache.poi.util.POILogFactory;
-
-
-
-
-
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-import javax.imageio.ImageIO;
-
-import java.awt.*;
-import java.awt.geom.AffineTransform;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-
-/**
- * Creates BufferedImage using javax.imageio.ImageIO and draws it in the specified graphics.
- *
- * @author  Yegor Kozlov.
- */
-public final class BitmapPainter implements ImagePainter {
-    protected POILogger logger = POILogFactory.getLogger(this.getClass());
-
-    public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent) {
-        BufferedImage img;
-        try {
-            img = ImageIO.read(new ByteArrayInputStream(pict.getData()));
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "ImageIO failed to create image. image.type: " + pict.getType());
-            return;
-        }
-
-        boolean isClipped = true;
-        Insets clip = parent.getBlipClip();
-        if (clip == null) {
-            isClipped = false;
-            clip = new Insets(0,0,0,0);
-        }        
-        
-        int iw = img.getWidth();
-        int ih = img.getHeight();
-
-        Rectangle anchor = parent.getLogicalAnchor2D().getBounds();
-
-        double cw = (100000-clip.left-clip.right) / 100000.0;
-        double ch = (100000-clip.top-clip.bottom) / 100000.0;
-        double sx = anchor.getWidth()/(iw*cw);
-        double sy = anchor.getHeight()/(ih*ch);
-        double tx = anchor.getX()-(iw*sx*clip.left/100000.0);
-        double ty = anchor.getY()-(ih*sy*clip.top/100000.0);
-        AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ;
-
-        Shape clipOld = graphics.getClip();
-        if (isClipped) graphics.clip(anchor.getBounds2D());
-        graphics.drawRenderedImage(img, at);
-        graphics.setClip(clipOld);
-    }
-
-}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java b/src/scratchpad/src/org/apache/poi/hslf/blip/ImagePainter.java
deleted file mode 100644 (file)
index 76359dc..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.blip;
-
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFPictureShape;
-
-import java.awt.*;
-
-/**
- * A common interface for objects that can render ppt picture data.
- * <p>
- * Subclasses can redefine it and use third-party libraries for actual rendering,
- * for example, Bitmaps can be rendered using javax.imageio.* , WMF can be rendered using Apache Batik,
- * PICT can be rendered using Apple QuickTime API for Java, etc.
- * </p>
- *
- * A typical usage is as follows:
- * <code>
- * public WMFPaiter implements ImagePainter{
- *   public void paint(Graphics2D graphics, PictureData pict, Picture parent){
- *       DataInputStream is = new DataInputStream(new ByteArrayInputStream(pict.getData()));
- *       org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore =
- *               new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore();
- *       try {
- *           wmfStore.read(is);
- *       } catch (IOException e){
- *           return;
- *       }
- *
- *       Rectangle anchor = parent.getAnchor();
- *       float scale = (float)anchor.width/wmfStore.getWidthPixels();
- *
- *       org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter =
- *               new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale);
- *       graphics.translate(anchor.x, anchor.y);
- *       painter.paint(graphics);
- *   }
- * }
- * PictureData.setImagePainter(Picture.WMF, new WMFPaiter());
- * ...
- * </code>
- * Subsequent calls of Slide.draw(Graphics gr) will use WMFPaiter for WMF images.
- *
- * @author  Yegor Kozlov.
- */
-public interface ImagePainter {
-
-    /**
-     * Paints the specified picture data
-     *
-     * @param graphics  the graphics to paintb into
-     * @param pict      the data to paint
-     * @param parent    the shapes that owns the picture data
-     */
-    public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent);
-}
index 5dceebf9c5c0bc50a27a4f6a159ea7f68378bb83..1167cc3558242115a72590cc722ec7db268e92b4 100644 (file)
@@ -247,8 +247,8 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor {
 
                 // Table text
                 for (HSLFShape shape : slide.getShapes()){
-                    if (shape instanceof Table){
-                        extractTableText(ret, (Table)shape);
+                    if (shape instanceof HSLFTable){
+                        extractTableText(ret, (HSLFTable)shape);
                     }
                 }
                 // Slide footer, if set
@@ -305,10 +305,10 @@ public final class PowerPointExtractor extends POIOLE2TextExtractor {
                return ret.toString();
        }
 
-    private void extractTableText(StringBuffer ret, Table table) {
+    private void extractTableText(StringBuffer ret, HSLFTable table) {
         for (int row = 0; row < table.getNumberOfRows(); row++){
             for (int col = 0; col < table.getNumberOfColumns(); col++){
-                TableCell cell = table.getCell(row, col);
+                HSLFTableCell cell = table.getCell(row, col);
                 //defensive null checks; don't know if they're necessary
                 if (cell != null){
                     String txt = cell.getText();
index b28c88ec68cf2194da1182fc35bc61fe41a00763..c777351728845181b843564a03ce547ba210f3dd 100644 (file)
@@ -22,8 +22,8 @@ import org.apache.poi.hslf.usermodel.*;
 import org.apache.poi.sl.usermodel.ShapeContainer;
 import org.apache.poi.sl.usermodel.ShapeType;
 
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.Line2D;
+import java.awt.geom.*;
+import java.util.ArrayList;
 
 /**
  * Represents a line in a PowerPoint drawing
@@ -69,4 +69,63 @@ public final class Line extends HSLFSimpleShape {
         Rectangle2D anchor = getLogicalAnchor2D();
         return new Line2D.Double(anchor.getX(), anchor.getY(), anchor.getX() + anchor.getWidth(), anchor.getY() + anchor.getHeight());
     }
+    
+    /**
+    *
+    * @return 'absolute' anchor of this shape relative to the parent sheet
+    * 
+    * @deprecated TODO: remove the whole class, should work with preset geometries instead
+    */
+   public Rectangle2D getLogicalAnchor2D(){
+       Rectangle2D anchor = getAnchor2D();
+
+       //if it is a groupped shape see if we need to transform the coordinates
+       if (getParent() != null){
+           ArrayList<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>();
+           for (ShapeContainer<HSLFShape> parent=this.getParent();
+               parent instanceof HSLFGroupShape;
+               parent = ((HSLFGroupShape)parent).getParent()) {
+               lst.add(0, (HSLFGroupShape)parent);
+           }
+           
+           AffineTransform tx = new AffineTransform();
+           for(HSLFGroupShape prnt : lst) {
+               Rectangle2D exterior = prnt.getAnchor2D();
+               Rectangle2D interior = prnt.getInteriorAnchor();
+
+               double scaleX =  exterior.getWidth() / interior.getWidth();
+               double scaleY = exterior.getHeight() / interior.getHeight();
+
+               tx.translate(exterior.getX(), exterior.getY());
+               tx.scale(scaleX, scaleY);
+               tx.translate(-interior.getX(), -interior.getY());
+               
+           }
+           anchor = tx.createTransformedShape(anchor).getBounds2D();
+       }
+
+       double angle = getRotation();
+       if(angle != 0.){
+           double centerX = anchor.getX() + anchor.getWidth()/2;
+           double centerY = anchor.getY() + anchor.getHeight()/2;
+
+           AffineTransform trans = new AffineTransform();
+           trans.translate(centerX, centerY);
+           trans.rotate(Math.toRadians(angle));
+           trans.translate(-centerX, -centerY);
+
+           Rectangle2D rect = trans.createTransformedShape(anchor).getBounds2D();
+           if((anchor.getWidth() < anchor.getHeight() && rect.getWidth() > rect.getHeight()) ||
+               (anchor.getWidth() > anchor.getHeight() && rect.getWidth() < rect.getHeight())    ){
+               trans = new AffineTransform();
+               trans.translate(centerX, centerY);
+               trans.rotate(Math.PI/2);
+               trans.translate(-centerX, -centerY);
+               anchor = trans.createTransformedShape(anchor).getBounds2D();
+           }
+       }
+       return anchor;
+   }
+
+
 }
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/Table.java b/src/scratchpad/src/org/apache/poi/hslf/model/Table.java
deleted file mode 100644 (file)
index 8f3b245..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.model;
-
-import org.apache.poi.ddf.*;
-import org.apache.poi.hslf.usermodel.*;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.util.LittleEndian;
-
-import java.util.*;
-import java.util.List;
-import java.awt.*;
-
-/**
- * Represents a table in a PowerPoint presentation
- *
- * @author Yegor Kozlov
- */
-public final class Table extends HSLFGroupShape {
-
-    protected static final int BORDER_TOP = 1;
-    protected static final int BORDER_RIGHT = 2;
-    protected static final int BORDER_BOTTOM = 3;
-    protected static final int BORDER_LEFT = 4;
-
-    protected static final int BORDERS_ALL = 5;
-    protected static final int BORDERS_OUTSIDE = 6;
-    protected static final int BORDERS_INSIDE = 7;
-    protected static final int BORDERS_NONE = 8;
-
-
-    protected TableCell[][] cells;
-
-    /**
-     * Create a new Table of the given number of rows and columns
-     *
-     * @param numrows the number of rows
-     * @param numcols the number of columns
-     */
-    public Table(int numrows, int numcols) {
-        super();
-
-        if(numrows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1");
-        if(numcols < 1) throw new IllegalArgumentException("The number of columns must be greater than 1");
-
-        int x=0, y=0, tblWidth=0, tblHeight=0;
-        cells = new TableCell[numrows][numcols];
-        for (int i = 0; i < cells.length; i++) {
-            x = 0;
-            for (int j = 0; j < cells[i].length; j++) {
-                cells[i][j] = new TableCell(this);
-                Rectangle anchor = new Rectangle(x, y, TableCell.DEFAULT_WIDTH, TableCell.DEFAULT_HEIGHT);
-                cells[i][j].setAnchor(anchor);
-                x += TableCell.DEFAULT_WIDTH;
-            }
-            y += TableCell.DEFAULT_HEIGHT;
-        }
-        tblWidth = x;
-        tblHeight = y;
-        setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
-
-        EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
-        EscherOptRecord opt = new EscherOptRecord();
-        opt.setRecordId((short)0xF122);
-        opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
-        EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | 0x3A0), false, null);
-        p.setSizeOfElements(0x0004);
-        p.setNumberOfElementsInArray(numrows);
-        p.setNumberOfElementsInMemory(numrows);
-        opt.addEscherProperty(p);
-        List<EscherRecord> lst = spCont.getChildRecords();
-        lst.add(lst.size()-1, opt);
-        spCont.setChildRecords(lst);
-    }
-
-    /**
-     * Create a Table object and initilize it from the supplied Record container.
-     *
-     * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
-     * @param parent       the parent of the shape
-     */
-    public Table(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent) {
-        super(escherRecord, parent);
-    }
-
-    /**
-     * Gets a cell
-     *
-     * @param row the row index (0-based)
-     * @param col the column index (0-based)
-     * @return the cell
-     */
-    public TableCell getCell(int row, int col) {
-        return cells[row][col];
-    }
-
-    public int getNumberOfColumns() {
-        return cells[0].length;
-    }
-    public int getNumberOfRows() {
-        return cells.length;
-    }
-
-    protected void afterInsert(HSLFSheet sh){
-        super.afterInsert(sh);
-
-        EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
-        List<EscherRecord> lst = spCont.getChildRecords();
-        EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2);
-        EscherArrayProperty p = opt.lookup(0x3A0); 
-        for (int i = 0; i < cells.length; i++) {
-            TableCell cell = cells[i][0];
-            int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI;
-            byte[] val = new byte[4];
-            LittleEndian.putInt(val, 0, rowHeight);
-            p.setElement(i, val);
-            for (int j = 0; j < cells[i].length; j++) {
-                TableCell c = cells[i][j];
-                addShape(c);
-
-                Line bt = c.getBorderTop();
-                if(bt != null) addShape(bt);
-
-                Line br = c.getBorderRight();
-                if(br != null) addShape(br);
-
-                Line bb = c.getBorderBottom();
-                if(bb != null) addShape(bb);
-
-                Line bl = c.getBorderLeft();
-                if(bl != null) addShape(bl);
-
-            }
-        }
-
-    }
-
-    protected void initTable(){
-        List<HSLFShape> shapeList = getShapeList();
-        Collections.sort(shapeList, new Comparator<HSLFShape>(){
-            public int compare( HSLFShape o1, HSLFShape o2 ) {
-                Rectangle anchor1 = o1.getAnchor();
-                Rectangle anchor2 = o2.getAnchor();
-                int delta = anchor1.y - anchor2.y;
-                if(delta == 0) delta = anchor1.x - anchor2.x;
-                return delta;
-            }
-        });
-        int y0 = -1;
-        int maxrowlen = 0;
-        List<List<HSLFShape>> lst = new ArrayList<List<HSLFShape>>();
-        List<HSLFShape> row = null;
-        for (HSLFShape sh : shapeList) {
-            if(sh instanceof HSLFTextShape){
-                Rectangle anchor = sh.getAnchor();
-                if(anchor.y != y0){
-                    y0 = anchor.y;
-                    row = new ArrayList<HSLFShape>();
-                    lst.add(row);
-                }
-                row.add(sh);
-                maxrowlen = Math.max(maxrowlen, row.size());
-            }
-        }
-        cells = new TableCell[lst.size()][maxrowlen];
-        for (int i = 0; i < lst.size(); i++) {
-            row = lst.get(i);
-            for (int j = 0; j < row.size(); j++) {
-                HSLFTextShape tx = (HSLFTextShape)row.get(j);
-                cells[i][j] = new TableCell(tx.getSpContainer(), getParent());
-                cells[i][j].setSheet(tx.getSheet());
-            }
-        }
-    }
-
-    /**
-     * Assign the <code>SlideShow</code> this shape belongs to
-     *
-     * @param sheet owner of this shape
-     */
-    public void setSheet(HSLFSheet sheet){
-        super.setSheet(sheet);
-        if(cells == null) initTable();
-    }
-
-    /**
-     * Sets the row height.
-     *
-     * @param row the row index (0-based)
-     * @param height the height to set (in pixels)
-     */
-    public void setRowHeight(int row, int height){
-        int currentHeight = cells[row][0].getAnchor().height;
-        int dy = height - currentHeight;
-
-        for (int i = row; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                Rectangle anchor = cells[i][j].getAnchor();
-                if(i == row) anchor.height = height;
-                else anchor.y += dy;
-                cells[i][j].setAnchor(anchor);
-            }
-        }
-        Rectangle tblanchor = getAnchor();
-        tblanchor.height += dy;
-        setAnchor(tblanchor);
-
-    }
-
-    /**
-     * Sets the column width.
-     *
-     * @param col the column index (0-based)
-     * @param width the width to set (in pixels)
-     */
-    public void setColumnWidth(int col, int width){
-        int currentWidth = cells[0][col].getAnchor().width;
-        int dx = width - currentWidth;
-        for (int i = 0; i < cells.length; i++) {
-            Rectangle anchor = cells[i][col].getAnchor();
-            anchor.width = width;
-            cells[i][col].setAnchor(anchor);
-
-            if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
-                anchor = cells[i][j].getAnchor();
-                anchor.x += dx;
-                cells[i][j].setAnchor(anchor);
-            }
-        }
-        Rectangle tblanchor = getAnchor();
-        tblanchor.width += dx;
-        setAnchor(tblanchor);
-    }
-
-    /**
-     * Format the table and apply the specified Line to all cell boundaries,
-     * both outside and inside
-     *
-     * @param line the border line
-     */
-    public void setAllBorders(Line line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                TableCell cell = cells[i][j];
-                cell.setBorderTop(cloneBorder(line));
-                cell.setBorderLeft(cloneBorder(line));
-                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
-                if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-            }
-        }
-    }
-
-    /**
-     * Format the outside border using the specified Line object
-     *
-     * @param line the border line
-     */
-    public void setOutsideBorders(Line line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                TableCell cell = cells[i][j];
-
-                if(j == 0) cell.setBorderLeft(cloneBorder(line));
-                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
-                else {
-                    cell.setBorderLeft(null);
-                    cell.setBorderLeft(null);
-                }
-
-                if(i == 0) cell.setBorderTop(cloneBorder(line));
-                else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-                else {
-                    cell.setBorderTop(null);
-                    cell.setBorderBottom(null);
-                }
-            }
-        }
-    }
-
-    /**
-     * Format the inside border using the specified Line object
-     *
-     * @param line the border line
-     */
-    public void setInsideBorders(Line line){
-        for (int i = 0; i < cells.length; i++) {
-            for (int j = 0; j < cells[i].length; j++) {
-                TableCell cell = cells[i][j];
-
-                if(j != cells[i].length - 1)
-                    cell.setBorderRight(cloneBorder(line));
-                else {
-                    cell.setBorderLeft(null);
-                    cell.setBorderLeft(null);
-                }
-                if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
-                else {
-                    cell.setBorderTop(null);
-                    cell.setBorderBottom(null);
-                }
-            }
-        }
-    }
-
-    private Line cloneBorder(Line line){
-        Line border = createBorder();
-        border.setLineWidth(line.getLineWidth());
-        border.setLineDashing(line.getLineDashing());
-        border.setLineColor(line.getLineColor());
-        border.setLineCompound(line.getLineCompound());
-        return border;
-    }
-
-    /**
-     * Create a border to format this table
-     *
-     * @return the created border
-     */
-    public Line createBorder(){
-        Line line = new Line(this);
-
-        EscherOptRecord opt = getEscherOptRecord();
-        setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
-        setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
-        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
-        setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
-
-        return line;
-    }
-}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java b/src/scratchpad/src/org/apache/poi/hslf/model/TableCell.java
deleted file mode 100644 (file)
index cfdee76..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.model;
-
-import java.awt.Rectangle;
-
-import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.ddf.EscherOptRecord;
-import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.hslf.usermodel.HSLFShape;
-import org.apache.poi.hslf.usermodel.HSLFTextBox;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.sl.usermodel.ShapeType;
-
-/**
- * Represents a cell in a ppt table
- *
- * @author Yegor Kozlov
- */
-public final class TableCell extends HSLFTextBox {
-    protected static final int DEFAULT_WIDTH = 100;
-    protected static final int DEFAULT_HEIGHT = 40;
-
-    private Line borderLeft;
-    private Line borderRight;
-    private Line borderTop;
-    private Line borderBottom;
-
-    /**
-     * Create a TableCell object and initialize it from the supplied Record container.
-     *
-     * @param escherRecord       {@link EscherSpContainer} container which holds information about this shape
-     * @param parent    the parent of the shape
-     */
-   protected TableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
-        super(escherRecord, parent);
-    }
-
-    /**
-     * Create a new TableCell. This constructor is used when a new shape is created.
-     *
-     * @param parent    the parent of this Shape. For example, if this text box is a cell
-     * in a table then the parent is Table.
-     */
-    public TableCell(ShapeContainer<HSLFShape> parent){
-        super(parent);
-
-        setShapeType(ShapeType.RECT);
-        //_txtrun.setRunType(TextHeaderAtom.HALF_BODY_TYPE);
-        //_txtrun.getRichTextRuns()[0].setFlag(false, 0, false);
-    }
-
-    protected EscherContainerRecord createSpContainer(boolean isChild){
-        _escherContainer = super.createSpContainer(isChild);
-        EscherOptRecord opt = getEscherOptRecord();
-        setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
-        setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
-        setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
-        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
-        setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
-
-        return _escherContainer;
-    }
-
-    protected void anchorBorder(int type, Line line){
-        Rectangle cellAnchor = getAnchor();
-        Rectangle lineAnchor = new Rectangle();
-        switch(type){
-            case Table.BORDER_TOP:
-                lineAnchor.x = cellAnchor.x;
-                lineAnchor.y = cellAnchor.y;
-                lineAnchor.width = cellAnchor.width;
-                lineAnchor.height = 0;
-                break;
-            case Table.BORDER_RIGHT:
-                lineAnchor.x = cellAnchor.x + cellAnchor.width;
-                lineAnchor.y = cellAnchor.y;
-                lineAnchor.width = 0;
-                lineAnchor.height = cellAnchor.height;
-                break;
-            case Table.BORDER_BOTTOM:
-                lineAnchor.x = cellAnchor.x;
-                lineAnchor.y = cellAnchor.y + cellAnchor.height;
-                lineAnchor.width = cellAnchor.width;
-                lineAnchor.height = 0;
-                break;
-            case Table.BORDER_LEFT:
-                lineAnchor.x = cellAnchor.x;
-                lineAnchor.y = cellAnchor.y;
-                lineAnchor.width = 0;
-                lineAnchor.height = cellAnchor.height;
-                break;
-            default:
-                throw new IllegalArgumentException("Unknown border type: " + type);
-        }
-        line.setAnchor(lineAnchor);
-    }
-
-    public Line getBorderLeft() {
-        return borderLeft;
-    }
-
-    public void setBorderLeft(Line line) {
-        if(line != null) anchorBorder(Table.BORDER_LEFT, line);
-        this.borderLeft = line;
-    }
-
-    public Line getBorderRight() {
-        return borderRight;
-    }
-
-    public void setBorderRight(Line line) {
-        if(line != null) anchorBorder(Table.BORDER_RIGHT, line);
-        this.borderRight = line;
-    }
-
-    public Line getBorderTop() {
-        return borderTop;
-    }
-
-    public void setBorderTop(Line line) {
-        if(line != null) anchorBorder(Table.BORDER_TOP, line);
-        this.borderTop = line;
-    }
-
-    public Line getBorderBottom() {
-        return borderBottom;
-    }
-
-    public void setBorderBottom(Line line) {
-        if(line != null) anchorBorder(Table.BORDER_BOTTOM, line);
-        this.borderBottom = line;
-    }
-
-    public void setAnchor(Rectangle anchor){
-        super.setAnchor(anchor);
-
-        if(borderTop != null) anchorBorder(Table.BORDER_TOP, borderTop);
-        if(borderRight != null) anchorBorder(Table.BORDER_RIGHT, borderRight);
-        if(borderBottom != null) anchorBorder(Table.BORDER_BOTTOM, borderBottom);
-        if(borderLeft != null) anchorBorder(Table.BORDER_LEFT, borderLeft);
-    }
-}
index 0e46e6a7f5c75d491616d6ceb8a9e226beca9a77..17d0c1d2c5ce46ccf42517876bc0faba7415df58 100644 (file)
@@ -285,6 +285,7 @@ public class TextPropCollection {
      * Clones the given text properties
      */
        public void copy(TextPropCollection other) {
+           if (this == other) return;
         this.charactersCovered = other.charactersCovered;
         this.indentLevel = other.indentLevel;
         this.maskSpecial = other.maskSpecial;
index 715eb817993c3d49fd85bd7f5b1c8e9ecba69f5a..10744e49d75ccc08613c603718a026dc2f8a36f2 100644 (file)
@@ -87,9 +87,7 @@ public final class EscherTextboxWrapper extends RecordContainer {
 
                // Grab the children's data
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-               for(int i=0; i<_children.length; i++) {
-                       _children[i].writeOut(baos);
-               }
+               for (Record r : _children) r.writeOut(baos);
                byte[] data = baos.toByteArray();
 
                // Save in the escher layer
index 09f21d1bafebb6eb6489738953e0bc24f50b76f4..09854b5ab9a2dc552527019c60a60a4dd42dc423 100644 (file)
@@ -97,7 +97,7 @@ public final class PPDrawing extends RecordAtom {
                findEscherChildren(erf, contents, 8, len-8, escherChildren);
                this.childRecords = escherChildren.toArray(new EscherRecord[escherChildren.size()]);
 
-               if (1 == this.childRecords.length && (short)0xf002 == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) {
+               if (1 == this.childRecords.length && (short)RecordTypes.EscherDgContainer == this.childRecords[0].getRecordId() && this.childRecords[0] instanceof EscherContainerRecord) {
                        this.textboxWrappers = findInDgContainer((EscherContainerRecord) this.childRecords[0]);
                } else {
                        // Find and EscherTextboxRecord's, and wrap them up
@@ -106,37 +106,30 @@ public final class PPDrawing extends RecordAtom {
                        this.textboxWrappers = textboxes.toArray(new EscherTextboxWrapper[textboxes.size()]);
                }
        }
-       private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord escherContainerF002) {
+       private EscherTextboxWrapper[] findInDgContainer(final EscherContainerRecord dgContainer) {
                final List<EscherTextboxWrapper> found = new LinkedList<EscherTextboxWrapper>();
-               final EscherContainerRecord SpgrContainer = findFirstEscherContainerRecordOfType((short)0xf003, escherContainerF002);
-               final EscherContainerRecord[] escherContainersF004 = findAllEscherContainerRecordOfType((short)0xf004, SpgrContainer);
-               for (EscherContainerRecord spContainer : escherContainersF004) {
+               final EscherContainerRecord spgrContainer = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherSpgrContainer, dgContainer);
+               final EscherContainerRecord[] spContainers = findAllEscherContainerRecordOfType((short)RecordTypes.EscherSpContainer, spgrContainer);
+               for (EscherContainerRecord spContainer : spContainers) {
                        StyleTextProp9Atom nineAtom = findInSpContainer(spContainer);
-                       EscherSpRecord sp = null;
-                       final EscherRecord escherContainerF00A = findFirstEscherRecordOfType((short)0xf00a, spContainer);
-                       if (null != escherContainerF00A) {
-                               if (escherContainerF00A instanceof EscherSpRecord) {
-                                       sp = (EscherSpRecord) escherContainerF00A;
-                               }
-                       }
-                       final EscherRecord escherContainerF00D = findFirstEscherRecordOfType((short)0xf00d, spContainer);
-                       if (null == escherContainerF00D) { continue; }
-                       if (escherContainerF00D instanceof EscherTextboxRecord) {
-                               EscherTextboxRecord tbr = (EscherTextboxRecord) escherContainerF00D;
-                               EscherTextboxWrapper w = new EscherTextboxWrapper(tbr);
-                               w.setStyleTextProp9Atom(nineAtom);
-                               if (null != sp) {
-                                       w.setShapeId(sp.getShapeId());
-                               }
-                               found.add(w);
+                       EscherSpRecord sp = (EscherSpRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherSp, spContainer);
+                       EscherTextboxRecord clientTextbox = (EscherTextboxRecord)findFirstEscherRecordOfType((short)RecordTypes.EscherClientTextbox, spContainer);
+                       if (null == clientTextbox) { continue; }
+
+                       EscherTextboxWrapper w = new EscherTextboxWrapper(clientTextbox);
+                       w.setStyleTextProp9Atom(nineAtom);
+                       if (null != sp) {
+                           w.setShapeId(sp.getShapeId());
                        }
+                       found.add(w);
                }
                return found.toArray(new EscherTextboxWrapper[found.size()]);
        }
+       
        private StyleTextProp9Atom findInSpContainer(final EscherContainerRecord spContainer) {
-               final EscherContainerRecord escherContainerF011 = findFirstEscherContainerRecordOfType((short)0xf011, spContainer);
-               if (null == escherContainerF011) { return null; }
-               final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, escherContainerF011);
+               EscherContainerRecord clientData = findFirstEscherContainerRecordOfType((short)RecordTypes.EscherClientData, spContainer);
+               if (null == clientData) { return null; }
+               final EscherContainerRecord escherContainer1388 = findFirstEscherContainerRecordOfType((short)0x1388, clientData);
                if (null == escherContainer1388) { return null; }
                final EscherContainerRecord escherContainer138A = findFirstEscherContainerRecordOfType((short)0x138A, escherContainer1388);
                if (null == escherContainer138A) { return null; }
index be732d44ca1c2522cbfed0cf95841f7f5190f1ed..91a590afe8cd4437eec332cefa9f71df00402021 100644 (file)
@@ -294,7 +294,7 @@ public abstract class RecordContainer extends Record
                        // Write out our header, less the size
                        mout.write(new byte[] {headerA,headerB});
                        byte[] typeB = new byte[2];
-                       LittleEndian.putShort(typeB,(short)type);
+                       LittleEndian.putShort(typeB, 0, (short)type);
                        mout.write(typeB);
                        mout.write(new byte[4]);
 
@@ -320,7 +320,7 @@ public abstract class RecordContainer extends Record
                        // Write out our header, less the size
                        baos.write(new byte[] {headerA,headerB});
                        byte[] typeB = new byte[2];
-                       LittleEndian.putShort(typeB,(short)type);
+                       LittleEndian.putShort(typeB,0,(short)type);
                        baos.write(typeB);
                        baos.write(new byte[] {0,0,0,0});
 
index 315455d90c3b83290251c3d2a8dda6644e7a8b71..195b59c08f43a3ad4814525677902449d255c3da 100644 (file)
@@ -93,8 +93,6 @@ public final class SlideListWithText extends RecordContainer {
                                }
 
                                int clen = endPos - i - 1;
-                               boolean emptySet = false;
-                               if(clen == 0) { emptySet = true; }
 
                                // Create a SlideAtomsSets, not caring if they're empty
                                //if(emptySet) { continue; }
@@ -149,7 +147,7 @@ public final class SlideListWithText extends RecordContainer {
        }
 
        public void setInstance(int inst){
-               LittleEndian.putShort(_header, (short)((inst << 4) | 0xF));
+               LittleEndian.putShort(_header, 0, (short)((inst << 4) | 0xF));
        }
 
        /**
index 9b74711fc6873c8ddd6752af1160eaddc854a012..09d97a3b746921cd8a159654b7348ec93695af2d 100644 (file)
@@ -128,9 +128,10 @@ public final class HSLFFill {
                         };
                     }
                     case FILL_PICTURE: {
+                        final HSLFPictureData pd = getPictureData();
+                        if (pd == null) break;
+                        
                         return new TexturePaint() {
-                            final HSLFPictureData pd = getPictureData();
-                            
                             public InputStream getImageData() {
                                 return new ByteArrayInputStream(pd.getData());
                             }
index 5e47776d6e08c5d47cb5ed77983939deda0cdc91..5133ff1229b2b00d7d7ba618e9985b57ed8cb5fb 100644 (file)
@@ -21,8 +21,7 @@ import java.awt.geom.Rectangle2D;
 import java.util.*;
 
 import org.apache.poi.ddf.*;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.*;
 import org.apache.poi.util.LittleEndian;
 import org.apache.poi.util.POILogger;
 
@@ -31,7 +30,7 @@ import org.apache.poi.util.POILogger;
  *
  * @author Yegor Kozlov
  */
-public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShape> {
+public class HSLFGroupShape extends HSLFShape implements GroupShape<HSLFShape> {
 
     /**
       * Create a new ShapeGroup. This constructor is used when a new shape is created.
@@ -87,13 +86,8 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap
         spgr.setRectY2((anchor.y + anchor.height)*MASTER_DPI/POINT_DPI);
     }
 
-    /**
-     * Sets the coordinate space of this group.  All children are constrained
-     * to these coordinates.
-     *
-     * @param anchor the coordinate space of this group
-     */
-    public void setCoordinates(Rectangle2D anchor){
+    @Override
+    public void setInteriorAnchor(Rectangle2D anchor){
         EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
 
         int x1 = (int)Math.round(anchor.getX()*MASTER_DPI/POINT_DPI);
@@ -108,22 +102,14 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap
 
     }
 
-    /**
-     * Gets the coordinate space of this group.  All children are constrained
-     * to these coordinates.
-     *
-     * @return the coordinate space of this group
-     */
-    public Rectangle2D getCoordinates(){
-        EscherSpgrRecord spgr = getEscherChild(EscherSpgrRecord.RECORD_ID);
-
-        Rectangle2D.Float anchor = new Rectangle2D.Float();
-        anchor.x = (float)spgr.getRectX1()*POINT_DPI/MASTER_DPI;
-        anchor.y = (float)spgr.getRectY1()*POINT_DPI/MASTER_DPI;
-        anchor.width = (float)(spgr.getRectX2() - spgr.getRectX1())*POINT_DPI/MASTER_DPI;
-        anchor.height = (float)(spgr.getRectY2() - spgr.getRectY1())*POINT_DPI/MASTER_DPI;
-
-        return anchor;
+    @Override
+    public Rectangle2D getInteriorAnchor(){
+        EscherSpgrRecord rec = getEscherChild(EscherSpgrRecord.RECORD_ID);
+        double x = rec.getRectX1()*POINT_DPI/MASTER_DPI;
+        double y = rec.getRectY1()*POINT_DPI/MASTER_DPI;
+        double width = (rec.getRectX2()-rec.getRectX1())*POINT_DPI/MASTER_DPI;
+        double height = (rec.getRectY2()-rec.getRectY1())*POINT_DPI/MASTER_DPI;
+        return new Rectangle2D.Double(x,y,width,height);
     }
 
     /**
@@ -199,21 +185,21 @@ public class HSLFGroupShape extends HSLFShape implements ShapeContainer<HSLFShap
      */
     public Rectangle2D getAnchor2D(){
         EscherClientAnchorRecord clientAnchor = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
-        Rectangle2D.Float anchor = new Rectangle2D.Float();
+        Rectangle2D anchor;
         if(clientAnchor == null){
             logger.log(POILogger.INFO, "EscherClientAnchorRecord was not found for shape group. Searching for EscherChildAnchorRecord.");
             EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
-            anchor = new Rectangle2D.Float(
-                (float)rec.getDx1()*POINT_DPI/MASTER_DPI,
-                (float)rec.getDy1()*POINT_DPI/MASTER_DPI,
-                (float)(rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI,
-                (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
-            );
+            double x = rec.getDx1()*POINT_DPI/MASTER_DPI;
+            double y = rec.getDy1()*POINT_DPI/MASTER_DPI;
+            double width = (rec.getDx2()-rec.getDx1())*POINT_DPI/MASTER_DPI;
+            double height = (rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI;
+            anchor = new Rectangle2D.Double(x,y,width,height);
         } else {
-            anchor.x = (float)clientAnchor.getCol1()*POINT_DPI/MASTER_DPI;
-            anchor.y = (float)clientAnchor.getFlag()*POINT_DPI/MASTER_DPI;
-            anchor.width = (float)(clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ;
-            anchor.height = (float)(clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI;
+            double x = clientAnchor.getCol1()*POINT_DPI/MASTER_DPI;
+            double y = clientAnchor.getFlag()*POINT_DPI/MASTER_DPI;
+            double width = (clientAnchor.getDx1() - clientAnchor.getCol1())*POINT_DPI/MASTER_DPI ;
+            double height = (clientAnchor.getRow1() - clientAnchor.getFlag())*POINT_DPI/MASTER_DPI;
+            anchor = new Rectangle2D.Double(x,y,width,height);
         }
 
         return anchor;
index 50eb3a6db2bb9a81bad2c7e3092547ac1f3416c9..7f47eafe22d30d88faf571f6135735e1ca0b639f 100644 (file)
@@ -35,7 +35,7 @@ import org.apache.poi.util.POILogger;
 public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFSlideShow> {
     protected static POILogger logger = POILogFactory.getLogger(HSLFNotes.class);
     
-    private List<List<HSLFTextParagraph>> _runs;
+    private List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>();
 
     /**
      * Constructs a Notes Sheet from the given Notes record.
@@ -49,13 +49,16 @@ public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFS
         // Now, build up TextRuns from pairs of TextHeaderAtom and
         // one of TextBytesAtom or TextCharsAtom, found inside
         // EscherTextboxWrapper's in the PPDrawing
-        _runs = HSLFTextParagraph.findTextParagraphs(getPPDrawing());
-        if (_runs.isEmpty()) {
+        for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
+            if (!_paragraphs.contains(l)) _paragraphs.add(l);
+        }
+        
+        if (_paragraphs.isEmpty()) {
             logger.log(POILogger.WARN, "No text records found for notes sheet");
         }
 
         // Set the sheet on each TextRun
-        for (List<HSLFTextParagraph> ltp : _runs) {
+        for (List<HSLFTextParagraph> ltp : _paragraphs) {
             for (HSLFTextParagraph tp : ltp) {
                 tp.supplySheet(this);
             }
@@ -67,7 +70,7 @@ public final class HSLFNotes extends HSLFSheet implements Notes<HSLFShape, HSLFS
      */
     @Override
     public List<List<HSLFTextParagraph>> getTextParagraphs() {
-        return _runs;
+        return _paragraphs;
     }
 
     /**
index b848a2cb9bdabab2bff0a8e8bac71b433f6b6e11..230a6401d2285c0b46033191fe5d77cf62fa3651 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
-import java.awt.Graphics2D;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.security.MessageDigest;
 
-import org.apache.poi.hslf.blip.BitmapPainter;
-import org.apache.poi.hslf.blip.DIB;
-import org.apache.poi.hslf.blip.EMF;
-import org.apache.poi.hslf.blip.ImagePainter;
-import org.apache.poi.hslf.blip.JPEG;
-import org.apache.poi.hslf.blip.PICT;
-import org.apache.poi.hslf.blip.PNG;
-import org.apache.poi.hslf.blip.WMF;
+import org.apache.poi.hslf.blip.*;
 import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.HashAlgorithm;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
+import org.apache.poi.sl.usermodel.PictureData;
+import org.apache.poi.util.*;
 
 /**
  * A class that represents image data contained in a slide show.
  *
  *  @author Yegor Kozlov
  */
-public abstract class HSLFPictureData {
+public abstract class HSLFPictureData implements PictureData {
 
     protected POILogger logger = POILogFactory.getLogger(this.getClass());
 
@@ -91,13 +82,6 @@ public abstract class HSLFPictureData {
      */
     protected abstract int getSignature();
 
-    protected static final ImagePainter[] painters = new ImagePainter[8];
-    static {
-        HSLFPictureData.setImagePainter(HSLFPictureShape.PNG, new BitmapPainter());
-        HSLFPictureData.setImagePainter(HSLFPictureShape.JPEG, new BitmapPainter());
-        HSLFPictureData.setImagePainter(HSLFPictureShape.DIB, new BitmapPainter());
-    }
-
     /**
      * Returns the raw binary data of this Picture excluding the first 8 bytes
      * which hold image signature and size of the image data.
@@ -233,31 +217,4 @@ public abstract class HSLFPictureData {
     public int getSize(){
         return getData().length;
     }
-
-    public void draw(Graphics2D graphics, HSLFPictureShape parent){
-        ImagePainter painter = painters[getType()];
-        if(painter != null) painter.paint(graphics, this, parent);
-        else logger.log(POILogger.WARN, "Rendering is not supported: " + getClass().getName());
-    }
-
-    /**
-     * Register ImagePainter for the specified image type
-     *
-     * @param type  image type, must be one of the static constants defined in the <code>Picture<code> class.
-     * @param painter
-     */
-    public static void setImagePainter(int type, ImagePainter painter){
-        painters[type] = painter;
-    }
-
-    /**
-     * Return ImagePainter for the specified image type
-     *
-     * @param type blip type, must be one of the static constants defined in the <code>Picture<code> class.
-     * @return ImagePainter for the specified image type
-     */
-    public static ImagePainter getImagePainter(int type){
-        return painters[type];
-    }
-
 }
index c97c2816800d22c5e0c99d311eabbd4cd9ea2e76..03a9861ae6af32a2276b4be87f6005859b444f59 100644 (file)
@@ -28,8 +28,7 @@ import javax.imageio.ImageIO;
 import org.apache.poi.ddf.*;
 import org.apache.poi.hslf.blip.Bitmap;
 import org.apache.poi.hslf.record.Document;
-import org.apache.poi.sl.usermodel.ShapeContainer;
-import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.*;
 import org.apache.poi.util.*;
 
 
@@ -38,7 +37,7 @@ import org.apache.poi.util.*;
  *
  * @author Yegor Kozlov
  */
-public class HSLFPictureShape extends HSLFSimpleShape {
+public class HSLFPictureShape extends HSLFSimpleShape implements PictureShape {
 
     /**
     *  Windows Enhanced Metafile (EMF)
@@ -165,11 +164,7 @@ public class HSLFPictureShape extends HSLFSimpleShape {
         }
     }
 
-    /**
-     * Returns the picture data for this picture.
-     *
-     * @return the picture data for this picture.
-     */
+    @Override
     public HSLFPictureData getPictureData(){
         HSLFSlideShow ppt = getSheet().getSlideShow();
         HSLFPictureData[] pict = ppt.getPictureData();
@@ -247,13 +242,11 @@ public class HSLFPictureShape extends HSLFSimpleShape {
     }
 
     /**
-     * Returns the clipping values as percent ratio relatively to the image size.
      * The anchor specified by {@link #getLogicalAnchor2D()} is the displayed size,
      * i.e. the size of the already clipped image
-     * 
-     * @return the clipping as insets converted/scaled to 100000 (=100%) 
      */
-    public Insets getBlipClip() {
+    @Override
+    public Insets getClipping() {
         EscherOptRecord opt = getEscherOptRecord();
         
         double top    = getFractProp(opt, EscherProperties.BLIP__CROPFROMTOP);
index a6be80f92f3437cb1add0fffef60fcc40f1c24f7..a68f3a74e9d21a3a732918c5bb298550007481dc 100644 (file)
@@ -165,14 +165,12 @@ public abstract class HSLFShape implements Shape {
     public Rectangle2D getAnchor2D(){
         EscherSpRecord spRecord = getEscherChild(EscherSpRecord.RECORD_ID);
         int flags = spRecord.getFlags();
-        Rectangle2D anchor=null;
+        Rectangle2D anchor;
         if ((flags & EscherSpRecord.FLAG_CHILD) != 0){
             EscherChildAnchorRecord rec = getEscherChild(EscherChildAnchorRecord.RECORD_ID);
-            anchor = new java.awt.Rectangle();
             if(rec == null){
                 logger.log(POILogger.WARN, "EscherSpRecord.FLAG_CHILD is set but EscherChildAnchorRecord was not found");
                 EscherClientAnchorRecord clrec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
-                anchor = new java.awt.Rectangle();
                 anchor = new Rectangle2D.Float(
                     (float)clrec.getCol1()*POINT_DPI/MASTER_DPI,
                     (float)clrec.getFlag()*POINT_DPI/MASTER_DPI,
@@ -187,10 +185,8 @@ public abstract class HSLFShape implements Shape {
                     (float)(rec.getDy2()-rec.getDy1())*POINT_DPI/MASTER_DPI
                 );
             }
-        }
-        else {
+        } else {
             EscherClientAnchorRecord rec = getEscherChild(EscherClientAnchorRecord.RECORD_ID);
-            anchor = new java.awt.Rectangle();
             anchor = new Rectangle2D.Float(
                 (float)rec.getCol1()*POINT_DPI/MASTER_DPI,
                 (float)rec.getFlag()*POINT_DPI/MASTER_DPI,
@@ -201,10 +197,6 @@ public abstract class HSLFShape implements Shape {
         return anchor;
     }
 
-    public Rectangle2D getLogicalAnchor2D(){
-        return getAnchor2D();
-    }
-
     /**
      * Sets the anchor (the bounding box rectangle) of this shape.
      * All coordinates should be expressed in points (72 dpi).
@@ -262,8 +254,9 @@ public abstract class HSLFShape implements Shape {
      * @return escher property or <code>null</code> if not found.
      */
      public static <T extends EscherProperty> T getEscherProperty(EscherOptRecord opt, int propId){
-        return opt.lookup(propId);
-    }
+         if (opt == null) return null;
+         return opt.lookup(propId);
+     }
 
     /**
      * Set an escher property for this shape.
@@ -475,15 +468,6 @@ public abstract class HSLFShape implements Shape {
         logger.log(POILogger.INFO, "Rendering " + getShapeName());
     }
 
-    /**
-     * Return shape outline as a java.awt.Shape object
-     *
-     * @return the shape outline
-     */
-    public java.awt.Shape getOutline(){
-        return getLogicalAnchor2D();
-    }
-    
     public EscherOptRecord getEscherOptRecord() {
         EscherOptRecord opt = getEscherChild(EscherOptRecord.RECORD_ID);
         if (opt == null) {
@@ -516,8 +500,7 @@ public abstract class HSLFShape implements Shape {
 
     public double getRotation(){
         int rot = getEscherProperty(EscherProperties.TRANSFORM__ROTATION);
-        double angle = Units.fixedPointToDouble(rot) % 360.0;
-        return angle;
+        return Units.fixedPointToDouble(rot);
     }
     
     public void setRotation(double theta){
index 0f9dd2815e4b790e10a6dbdc43c12e5a6b257a59..9f715fb389e126f03b5ea6f29775c2972978c7a5 100644 (file)
@@ -69,7 +69,7 @@ public final class HSLFShapeFactory {
                 List<EscherProperty> props = f.createProperties( opt.serialize(), 8, opt.getInstance() );
                 EscherSimpleProperty p = (EscherSimpleProperty)props.get(0);
                 if(p.getPropertyNumber() == 0x39F && p.getPropertyValue() == 1){
-                    group = new Table(spContainer, parent);
+                    group = new HSLFTable(spContainer, parent);
                 } else {
                     group = new HSLFGroupShape(spContainer, parent);
                 }
index 547e095efbe17cb14fcc99a13fe2033d6ad5937f..0247a759362b438ab0ead3a6a1bf06f175b7dc3f 100644 (file)
@@ -22,6 +22,8 @@ import java.util.*;
 
 import org.apache.poi.ddf.*;
 import org.apache.poi.hslf.record.*;
+import org.apache.poi.sl.draw.DrawFactory;
+import org.apache.poi.sl.draw.Drawable;
 import org.apache.poi.sl.usermodel.Sheet;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
@@ -288,8 +290,11 @@ public abstract class HSLFSheet implements Sheet<HSLFShape,HSLFSlideShow> {
         return _background;
     }
 
-    public void draw(Graphics2D graphics){
-
+    @Override
+    public void draw(Graphics2D graphics) {
+        DrawFactory drawFact = DrawFactory.getInstance(graphics);
+        Drawable draw = drawFact.getDrawable(this);
+        draw.draw(graphics);
     }
 
     /**
index 6c053d49f4b505530221167e12ac38b6e91f9e16..5ddf311e528afa7e2ff27a522409310c17253a23 100644 (file)
 package org.apache.poi.hslf.usermodel;
 
 import java.awt.Color;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
 import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
 
 import org.apache.poi.ddf.*;
 import org.apache.poi.hslf.exceptions.HSLFException;
 import org.apache.poi.hslf.record.*;
+import org.apache.poi.sl.draw.DrawPaint;
 import org.apache.poi.sl.draw.geom.*;
 import org.apache.poi.sl.usermodel.*;
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
 import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
 import org.apache.poi.util.LittleEndian;
@@ -196,7 +195,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape {
     public StrokeStyle getStrokeStyle(){
         return new StrokeStyle() {
             public PaintStyle getPaint() {
-                return null;
+                return DrawPaint.createSolidPaint(HSLFSimpleShape.this.getLineColor());
             }
 
             public LineCap getLineCap() {
@@ -204,15 +203,15 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape {
             }
 
             public LineDash getLineDash() {
-                return null;
+                return HSLFSimpleShape.this.getLineDashing();
             }
 
             public LineCompound getLineCompound() {
-                return null;
+                return HSLFSimpleShape.this.getLineCompound();
             }
 
             public double getLineWidth() {
-                return 0;
+                return HSLFSimpleShape.this.getLineWidth();
             }
             
         };
@@ -234,61 +233,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape {
         getFill().setForegroundColor(color);
     }
 
-    /**
-     *
-     * @return 'absolute' anchor of this shape relative to the parent sheet
-     */
-    public Rectangle2D getLogicalAnchor2D(){
-        Rectangle2D anchor = getAnchor2D();
-
-        //if it is a groupped shape see if we need to transform the coordinates
-        if (getParent() != null){
-            ArrayList<HSLFGroupShape> lst = new ArrayList<HSLFGroupShape>();
-            for (ShapeContainer<HSLFShape> parent=this.getParent();
-                parent instanceof HSLFGroupShape;
-                parent = ((HSLFGroupShape)parent).getParent()) {
-                lst.add(0, (HSLFGroupShape)parent);
-            }
-            
-            AffineTransform tx = new AffineTransform();
-            for(HSLFGroupShape prnt : lst) {
-                Rectangle2D exterior = prnt.getAnchor2D();
-                Rectangle2D interior = prnt.getCoordinates();
-
-                double scaleX =  exterior.getWidth() / interior.getWidth();
-                double scaleY = exterior.getHeight() / interior.getHeight();
-
-                tx.translate(exterior.getX(), exterior.getY());
-                tx.scale(scaleX, scaleY);
-                tx.translate(-interior.getX(), -interior.getY());
-                
-            }
-            anchor = tx.createTransformedShape(anchor).getBounds2D();
-        }
-
-        double angle = getRotation();
-        if(angle != 0.){
-            double centerX = anchor.getX() + anchor.getWidth()/2;
-            double centerY = anchor.getY() + anchor.getHeight()/2;
-
-            AffineTransform trans = new AffineTransform();
-            trans.translate(centerX, centerY);
-            trans.rotate(Math.toRadians(angle));
-            trans.translate(-centerX, -centerY);
-
-            Rectangle2D rect = trans.createTransformedShape(anchor).getBounds2D();
-            if((anchor.getWidth() < anchor.getHeight() && rect.getWidth() > rect.getHeight()) ||
-                (anchor.getWidth() > anchor.getHeight() && rect.getWidth() < rect.getHeight())    ){
-                trans = new AffineTransform();
-                trans.translate(centerX, centerY);
-                trans.rotate(Math.PI/2);
-                trans.translate(-centerX, -centerY);
-                anchor = trans.createTransformedShape(anchor).getBounds2D();
-            }
-        }
-        return anchor;
-    }
-
     /**
      *  Find a record in the underlying EscherClientDataRecord
      *
@@ -424,11 +368,6 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape {
         return (adjval == -1) ? null : new Guide(name, "val "+adjval);
     }
 
-    public LineDecoration getLineDecoration() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
     public CustomGeometry getGeometry() {
         ShapeType st = getShapeType();
         String name = st.getOoxmlName();
@@ -442,11 +381,89 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape {
         return geom;
     }
 
-    public Shadow getShadow() {
-        // TODO Auto-generated method stub
-        return null;
-    }
 
+    public double getShadowAngle() {
+        EscherOptRecord opt = getEscherOptRecord();
+        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX);
+        int offX = (prop == null) ? 0 : prop.getPropertyValue();
+        prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETY);
+        int offY = (prop == null) ? 0 : prop.getPropertyValue();
+        return Math.toDegrees(Math.atan2(offY, offX));
+    }
     
+    public double getShadowDistance() {
+        EscherOptRecord opt = getEscherOptRecord();
+        EscherSimpleProperty prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETX);
+        int offX = (prop == null) ? 0 : prop.getPropertyValue();
+        prop = getEscherProperty(opt, EscherProperties.SHADOWSTYLE__OFFSETY);
+        int offY = (prop == null) ? 0 : prop.getPropertyValue();
+        return Units.toPoints((long)Math.hypot(offX, offY));
+    }
+
+    /**
+     * @return color of the line. If color is not set returns <code>java.awt.Color.black</code>
+     */
+    public Color getShadowColor(){
+        Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1);
+        return clr == null ? Color.black : clr;
+    }    
     
+    public Shadow getShadow() {
+        EscherOptRecord opt = getEscherOptRecord();
+        EscherProperty shadowType = opt.lookup(EscherProperties.SHADOWSTYLE__TYPE);
+        if (shadowType == null) return null;
+        
+        return new Shadow(){
+            public SimpleShape getShadowParent() {
+                return HSLFSimpleShape.this;
+            }
+
+            public double getDistance() {
+                return getShadowDistance();
+            }
+
+            public double getAngle() {
+                return getShadowAngle();
+            }
+
+            public double getBlur() {
+                // TODO Auto-generated method stub
+                return 0;
+            }
+
+            public SolidPaint getFillStyle() {
+                return DrawPaint.createSolidPaint(getShadowColor());
+            }
+            
+        };
+    }
+
+    public LineDecoration getLineDecoration() {
+        return new LineDecoration() {
+
+            public DecorationShape getHeadShape() {
+                return DecorationShape.NONE;
+            }
+
+            public DecorationSize getHeadWidth() {
+                return DecorationSize.MEDIUM;
+            }
+
+            public DecorationSize getHeadLength() {
+                return DecorationSize.MEDIUM;
+            }
+
+            public DecorationShape getTailShape() {
+                return DecorationShape.NONE;
+            }
+
+            public DecorationSize getTailWidth() {
+                return DecorationSize.MEDIUM;
+            }
+
+            public DecorationSize getTailLength() {
+                return DecorationSize.MEDIUM;
+            }
+        };
+    }
 }
index 048655fa6407b721fa122d80298c83aeced90e5b..e2387510381b7cae4fd121c6e9f0072c74210c77 100644 (file)
@@ -72,7 +72,9 @@ public final class HSLFSlide extends HSLFSheet implements Slide<HSLFShape,HSLFSl
                }
 
                // Grab text from slide's PPDrawing
-               _paragraphs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing()));
+               for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
+                   if (!_paragraphs.contains(l)) _paragraphs.add(l);
+               }
 
         for(List<HSLFTextParagraph> ltp : _paragraphs) {
             for (HSLFTextParagraph tp : ltp) {
index 1c6518e5e0803c06a1cd21054d5f86f171bb2192..a6dfedf073849d5faa3734894651647968e3d2a4 100644 (file)
@@ -32,7 +32,7 @@ import org.apache.poi.hslf.record.*;
  * @author Yegor Kozlov
  */
 public final class HSLFSlideMaster extends HSLFMasterSheet {
-    private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>();
+    private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>();
 
     /**
      * all TxMasterStyleAtoms available in this master
@@ -46,8 +46,11 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
     public HSLFSlideMaster(MainMaster record, int sheetNo) {
         super(record, sheetNo);
 
-        _runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing()));
-        for (List<HSLFTextParagraph> p : _runs) {
+        for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
+            if (!_paragraphs.contains(l)) _paragraphs.add(l);
+        }
+
+        for (List<HSLFTextParagraph> p : _paragraphs) {
             for (HSLFTextParagraph htp : p) {
                 htp.supplySheet(this);
             }
@@ -58,7 +61,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
      * Returns an array of all the TextRuns found
      */
     public List<List<HSLFTextParagraph>> getTextParagraphs() {
-        return _runs;
+        return _paragraphs;
     }
 
     /**
@@ -138,7 +141,7 @@ public final class HSLFSlideMaster extends HSLFMasterSheet {
 
     protected void onAddTextShape(HSLFTextShape shape) {
         List<HSLFTextParagraph> runs = shape.getTextParagraphs();
-        _runs.add(runs);
+        _paragraphs.add(runs);
     }
 
     public TxMasterStyleAtom[] getTxMasterStyleAtoms(){
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTable.java
new file mode 100644 (file)
index 0000000..b028758
--- /dev/null
@@ -0,0 +1,346 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hslf.usermodel;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hslf.model.Line;
+import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.util.LittleEndian;
+
+import java.util.*;
+import java.util.List;
+import java.awt.*;
+
+/**
+ * Represents a table in a PowerPoint presentation
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFTable extends HSLFGroupShape {
+
+    protected static final int BORDER_TOP = 1;
+    protected static final int BORDER_RIGHT = 2;
+    protected static final int BORDER_BOTTOM = 3;
+    protected static final int BORDER_LEFT = 4;
+
+    protected static final int BORDERS_ALL = 5;
+    protected static final int BORDERS_OUTSIDE = 6;
+    protected static final int BORDERS_INSIDE = 7;
+    protected static final int BORDERS_NONE = 8;
+
+
+    protected HSLFTableCell[][] cells;
+
+    /**
+     * Create a new Table of the given number of rows and columns
+     *
+     * @param numrows the number of rows
+     * @param numcols the number of columns
+     */
+    public HSLFTable(int numrows, int numcols) {
+        super();
+
+        if(numrows < 1) throw new IllegalArgumentException("The number of rows must be greater than 1");
+        if(numcols < 1) throw new IllegalArgumentException("The number of columns must be greater than 1");
+
+        int x=0, y=0, tblWidth=0, tblHeight=0;
+        cells = new HSLFTableCell[numrows][numcols];
+        for (int i = 0; i < cells.length; i++) {
+            x = 0;
+            for (int j = 0; j < cells[i].length; j++) {
+                cells[i][j] = new HSLFTableCell(this);
+                Rectangle anchor = new Rectangle(x, y, HSLFTableCell.DEFAULT_WIDTH, HSLFTableCell.DEFAULT_HEIGHT);
+                cells[i][j].setAnchor(anchor);
+                x += HSLFTableCell.DEFAULT_WIDTH;
+            }
+            y += HSLFTableCell.DEFAULT_HEIGHT;
+        }
+        tblWidth = x;
+        tblHeight = y;
+        setAnchor(new Rectangle(0, 0, tblWidth, tblHeight));
+
+        EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
+        EscherOptRecord opt = new EscherOptRecord();
+        opt.setRecordId((short)0xF122);
+        opt.addEscherProperty(new EscherSimpleProperty((short)0x39F, 1));
+        EscherArrayProperty p = new EscherArrayProperty((short)(0x4000 | 0x3A0), false, null);
+        p.setSizeOfElements(0x0004);
+        p.setNumberOfElementsInArray(numrows);
+        p.setNumberOfElementsInMemory(numrows);
+        opt.addEscherProperty(p);
+        List<EscherRecord> lst = spCont.getChildRecords();
+        lst.add(lst.size()-1, opt);
+        spCont.setChildRecords(lst);
+    }
+
+    /**
+     * Create a Table object and initilize it from the supplied Record container.
+     *
+     * @param escherRecord <code>EscherSpContainer</code> container which holds information about this shape
+     * @param parent       the parent of the shape
+     */
+    public HSLFTable(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent) {
+        super(escherRecord, parent);
+    }
+
+    /**
+     * Gets a cell
+     *
+     * @param row the row index (0-based)
+     * @param col the column index (0-based)
+     * @return the cell
+     */
+    public HSLFTableCell getCell(int row, int col) {
+        return cells[row][col];
+    }
+
+    public int getNumberOfColumns() {
+        return cells[0].length;
+    }
+    public int getNumberOfRows() {
+        return cells.length;
+    }
+
+    protected void afterInsert(HSLFSheet sh){
+        super.afterInsert(sh);
+
+        EscherContainerRecord spCont = (EscherContainerRecord) getSpContainer().getChild(0);
+        List<EscherRecord> lst = spCont.getChildRecords();
+        EscherOptRecord opt = (EscherOptRecord)lst.get(lst.size()-2);
+        EscherArrayProperty p = opt.lookup(0x3A0); 
+        for (int i = 0; i < cells.length; i++) {
+            HSLFTableCell cell = cells[i][0];
+            int rowHeight = cell.getAnchor().height*MASTER_DPI/POINT_DPI;
+            byte[] val = new byte[4];
+            LittleEndian.putInt(val, 0, rowHeight);
+            p.setElement(i, val);
+            for (int j = 0; j < cells[i].length; j++) {
+                HSLFTableCell c = cells[i][j];
+                addShape(c);
+
+                Line bt = c.getBorderTop();
+                if(bt != null) addShape(bt);
+
+                Line br = c.getBorderRight();
+                if(br != null) addShape(br);
+
+                Line bb = c.getBorderBottom();
+                if(bb != null) addShape(bb);
+
+                Line bl = c.getBorderLeft();
+                if(bl != null) addShape(bl);
+
+            }
+        }
+
+    }
+
+    protected void initTable(){
+        List<HSLFShape> shapeList = getShapeList();
+        Collections.sort(shapeList, new Comparator<HSLFShape>(){
+            public int compare( HSLFShape o1, HSLFShape o2 ) {
+                Rectangle anchor1 = o1.getAnchor();
+                Rectangle anchor2 = o2.getAnchor();
+                int delta = anchor1.y - anchor2.y;
+                if(delta == 0) delta = anchor1.x - anchor2.x;
+                return delta;
+            }
+        });
+        int y0 = -1;
+        int maxrowlen = 0;
+        List<List<HSLFShape>> lst = new ArrayList<List<HSLFShape>>();
+        List<HSLFShape> row = null;
+        for (HSLFShape sh : shapeList) {
+            if(sh instanceof HSLFTextShape){
+                Rectangle anchor = sh.getAnchor();
+                if(anchor.y != y0){
+                    y0 = anchor.y;
+                    row = new ArrayList<HSLFShape>();
+                    lst.add(row);
+                }
+                row.add(sh);
+                maxrowlen = Math.max(maxrowlen, row.size());
+            }
+        }
+        cells = new HSLFTableCell[lst.size()][maxrowlen];
+        for (int i = 0; i < lst.size(); i++) {
+            row = lst.get(i);
+            for (int j = 0; j < row.size(); j++) {
+                HSLFTextShape tx = (HSLFTextShape)row.get(j);
+                cells[i][j] = new HSLFTableCell(tx.getSpContainer(), getParent());
+                cells[i][j].setSheet(tx.getSheet());
+            }
+        }
+    }
+
+    /**
+     * Assign the <code>SlideShow</code> this shape belongs to
+     *
+     * @param sheet owner of this shape
+     */
+    public void setSheet(HSLFSheet sheet){
+        super.setSheet(sheet);
+        if(cells == null) initTable();
+    }
+
+    /**
+     * Sets the row height.
+     *
+     * @param row the row index (0-based)
+     * @param height the height to set (in pixels)
+     */
+    public void setRowHeight(int row, int height){
+        int currentHeight = cells[row][0].getAnchor().height;
+        int dy = height - currentHeight;
+
+        for (int i = row; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                Rectangle anchor = cells[i][j].getAnchor();
+                if(i == row) anchor.height = height;
+                else anchor.y += dy;
+                cells[i][j].setAnchor(anchor);
+            }
+        }
+        Rectangle tblanchor = getAnchor();
+        tblanchor.height += dy;
+        setAnchor(tblanchor);
+
+    }
+
+    /**
+     * Sets the column width.
+     *
+     * @param col the column index (0-based)
+     * @param width the width to set (in pixels)
+     */
+    public void setColumnWidth(int col, int width){
+        int currentWidth = cells[0][col].getAnchor().width;
+        int dx = width - currentWidth;
+        for (int i = 0; i < cells.length; i++) {
+            Rectangle anchor = cells[i][col].getAnchor();
+            anchor.width = width;
+            cells[i][col].setAnchor(anchor);
+
+            if(col < cells[i].length - 1) for (int j = col+1; j < cells[i].length; j++) {
+                anchor = cells[i][j].getAnchor();
+                anchor.x += dx;
+                cells[i][j].setAnchor(anchor);
+            }
+        }
+        Rectangle tblanchor = getAnchor();
+        tblanchor.width += dx;
+        setAnchor(tblanchor);
+    }
+
+    /**
+     * Format the table and apply the specified Line to all cell boundaries,
+     * both outside and inside
+     *
+     * @param line the border line
+     */
+    public void setAllBorders(Line line){
+        for (int i = 0; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                HSLFTableCell cell = cells[i][j];
+                cell.setBorderTop(cloneBorder(line));
+                cell.setBorderLeft(cloneBorder(line));
+                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
+                if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+            }
+        }
+    }
+
+    /**
+     * Format the outside border using the specified Line object
+     *
+     * @param line the border line
+     */
+    public void setOutsideBorders(Line line){
+        for (int i = 0; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                HSLFTableCell cell = cells[i][j];
+
+                if(j == 0) cell.setBorderLeft(cloneBorder(line));
+                if(j == cells[i].length - 1) cell.setBorderRight(cloneBorder(line));
+                else {
+                    cell.setBorderLeft(null);
+                    cell.setBorderLeft(null);
+                }
+
+                if(i == 0) cell.setBorderTop(cloneBorder(line));
+                else if(i == cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+                else {
+                    cell.setBorderTop(null);
+                    cell.setBorderBottom(null);
+                }
+            }
+        }
+    }
+
+    /**
+     * Format the inside border using the specified Line object
+     *
+     * @param line the border line
+     */
+    public void setInsideBorders(Line line){
+        for (int i = 0; i < cells.length; i++) {
+            for (int j = 0; j < cells[i].length; j++) {
+                HSLFTableCell cell = cells[i][j];
+
+                if(j != cells[i].length - 1)
+                    cell.setBorderRight(cloneBorder(line));
+                else {
+                    cell.setBorderLeft(null);
+                    cell.setBorderLeft(null);
+                }
+                if(i != cells.length - 1) cell.setBorderBottom(cloneBorder(line));
+                else {
+                    cell.setBorderTop(null);
+                    cell.setBorderBottom(null);
+                }
+            }
+        }
+    }
+
+    private Line cloneBorder(Line line){
+        Line border = createBorder();
+        border.setLineWidth(line.getLineWidth());
+        border.setLineDashing(line.getLineDashing());
+        border.setLineColor(line.getLineColor());
+        border.setLineCompound(line.getLineCompound());
+        return border;
+    }
+
+    /**
+     * Create a border to format this table
+     *
+     * @return the created border
+     */
+    public Line createBorder(){
+        Line line = new Line(this);
+
+        EscherOptRecord opt = getEscherOptRecord();
+        setEscherProperty(opt, EscherProperties.GEOMETRY__SHAPEPATH, -1);
+        setEscherProperty(opt, EscherProperties.GEOMETRY__FILLOK, -1);
+        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+        setEscherProperty(opt, EscherProperties.THREED__LIGHTFACE, 0x80000);
+
+        return line;
+    }
+}
diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFTableCell.java
new file mode 100644 (file)
index 0000000..b1e7c3e
--- /dev/null
@@ -0,0 +1,157 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hslf.usermodel;
+
+import java.awt.Rectangle;
+
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.hslf.model.Line;
+import org.apache.poi.sl.usermodel.ShapeContainer;
+import org.apache.poi.sl.usermodel.ShapeType;
+
+/**
+ * Represents a cell in a ppt table
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSLFTableCell extends HSLFTextBox {
+    protected static final int DEFAULT_WIDTH = 100;
+    protected static final int DEFAULT_HEIGHT = 40;
+
+    private Line borderLeft;
+    private Line borderRight;
+    private Line borderTop;
+    private Line borderBottom;
+
+    /**
+     * Create a TableCell object and initialize it from the supplied Record container.
+     *
+     * @param escherRecord       {@link EscherSpContainer} container which holds information about this shape
+     * @param parent    the parent of the shape
+     */
+   protected HSLFTableCell(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape> parent){
+        super(escherRecord, parent);
+    }
+
+    /**
+     * Create a new TableCell. This constructor is used when a new shape is created.
+     *
+     * @param parent    the parent of this Shape. For example, if this text box is a cell
+     * in a table then the parent is Table.
+     */
+    public HSLFTableCell(ShapeContainer<HSLFShape> parent){
+        super(parent);
+
+        setShapeType(ShapeType.RECT);
+        //_txtrun.setRunType(TextHeaderAtom.HALF_BODY_TYPE);
+        //_txtrun.getRichTextRuns()[0].setFlag(false, 0, false);
+    }
+
+    protected EscherContainerRecord createSpContainer(boolean isChild){
+        _escherContainer = super.createSpContainer(isChild);
+        EscherOptRecord opt = getEscherOptRecord();
+        setEscherProperty(opt, EscherProperties.TEXT__TEXTID, 0);
+        setEscherProperty(opt, EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x20000);
+        setEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST, 0x150001);
+        setEscherProperty(opt, EscherProperties.SHADOWSTYLE__SHADOWOBSURED, 0x20000);
+        setEscherProperty(opt, EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 0x40000);
+
+        return _escherContainer;
+    }
+
+    protected void anchorBorder(int type, Line line){
+        Rectangle cellAnchor = getAnchor();
+        Rectangle lineAnchor = new Rectangle();
+        switch(type){
+            case HSLFTable.BORDER_TOP:
+                lineAnchor.x = cellAnchor.x;
+                lineAnchor.y = cellAnchor.y;
+                lineAnchor.width = cellAnchor.width;
+                lineAnchor.height = 0;
+                break;
+            case HSLFTable.BORDER_RIGHT:
+                lineAnchor.x = cellAnchor.x + cellAnchor.width;
+                lineAnchor.y = cellAnchor.y;
+                lineAnchor.width = 0;
+                lineAnchor.height = cellAnchor.height;
+                break;
+            case HSLFTable.BORDER_BOTTOM:
+                lineAnchor.x = cellAnchor.x;
+                lineAnchor.y = cellAnchor.y + cellAnchor.height;
+                lineAnchor.width = cellAnchor.width;
+                lineAnchor.height = 0;
+                break;
+            case HSLFTable.BORDER_LEFT:
+                lineAnchor.x = cellAnchor.x;
+                lineAnchor.y = cellAnchor.y;
+                lineAnchor.width = 0;
+                lineAnchor.height = cellAnchor.height;
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown border type: " + type);
+        }
+        line.setAnchor(lineAnchor);
+    }
+
+    public Line getBorderLeft() {
+        return borderLeft;
+    }
+
+    public void setBorderLeft(Line line) {
+        if(line != null) anchorBorder(HSLFTable.BORDER_LEFT, line);
+        this.borderLeft = line;
+    }
+
+    public Line getBorderRight() {
+        return borderRight;
+    }
+
+    public void setBorderRight(Line line) {
+        if(line != null) anchorBorder(HSLFTable.BORDER_RIGHT, line);
+        this.borderRight = line;
+    }
+
+    public Line getBorderTop() {
+        return borderTop;
+    }
+
+    public void setBorderTop(Line line) {
+        if(line != null) anchorBorder(HSLFTable.BORDER_TOP, line);
+        this.borderTop = line;
+    }
+
+    public Line getBorderBottom() {
+        return borderBottom;
+    }
+
+    public void setBorderBottom(Line line) {
+        if(line != null) anchorBorder(HSLFTable.BORDER_BOTTOM, line);
+        this.borderBottom = line;
+    }
+
+    public void setAnchor(Rectangle anchor){
+        super.setAnchor(anchor);
+
+        if(borderTop != null) anchorBorder(HSLFTable.BORDER_TOP, borderTop);
+        if(borderRight != null) anchorBorder(HSLFTable.BORDER_RIGHT, borderRight);
+        if(borderBottom != null) anchorBorder(HSLFTable.BORDER_BOTTOM, borderBottom);
+        if(borderLeft != null) anchorBorder(HSLFTable.BORDER_LEFT, borderLeft);
+    }
+}
index ca6ddf6e800593a895ae18679e68129adc1d42e1..f80bd3fc92a1385b39ab94b770c5da2db7053626 100644 (file)
 \r
 package org.apache.poi.hslf.usermodel;\r
 \r
+import static org.apache.poi.hslf.record.RecordTypes.OutlineTextRefAtom;\r
+\r
 import java.awt.Color;\r
+import java.io.IOException;\r
 import java.util.*;\r
 \r
 import org.apache.poi.hslf.model.PPFont;\r
@@ -52,8 +55,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        private final TextHeaderAtom _headerAtom;\r
        private TextBytesAtom  _byteAtom;\r
        private TextCharsAtom  _charAtom;\r
-       private StyleTextPropAtom _styleAtom;\r
-       private TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
+       private final TextPropCollection _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
 \r
     protected TextRulerAtom _ruler;\r
        protected List<HSLFTextRun> _runs = new ArrayList<HSLFTextRun>();\r
@@ -61,11 +63,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     private HSLFSheet _sheet;\r
     private int shapeId;\r
 \r
-    /**\r
-     * all text run records that follow TextHeaderAtom.\r
-     * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)\r
-     */\r
-    private Record[] _records;\r
        // private StyleTextPropAtom styleTextPropAtom;\r
        private StyleTextProp9Atom styleTextProp9Atom;\r
 \r
@@ -76,32 +73,30 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     * @param tha the TextHeaderAtom that defines what's what\r
     * @param tba the TextBytesAtom containing the text or null if {@link TextCharsAtom} is provided\r
     * @param tca the TextCharsAtom containing the text or null if {@link TextBytesAtom} is provided\r
-    * @param sta the StyleTextPropAtom which defines the character stylings\r
         */\r
        /* package */ HSLFTextParagraph(\r
         TextHeaderAtom tha,\r
         TextBytesAtom tba,\r
-        TextCharsAtom tca,\r
-        StyleTextPropAtom sta\r
+        TextCharsAtom tca\r
     ) {\r
+           if (tha == null)  {\r
+               throw new IllegalArgumentException("TextHeaderAtom must be set.");\r
+           }\r
                _headerAtom = tha;\r
-               _styleAtom = sta;\r
         _byteAtom = tba;\r
         _charAtom = tca;\r
        }\r
 \r
     /* package */ HSLFTextParagraph(HSLFTextParagraph other) {\r
-            _headerAtom = other._headerAtom;\r
-            _styleAtom = other._styleAtom;\r
-            _byteAtom = other._byteAtom;\r
-            _charAtom = other._charAtom;\r
-            _paragraphStyle = other._paragraphStyle;\r
-            _parentShape = other._parentShape;\r
-            _sheet = other._sheet;\r
-            _ruler = other._ruler; // ????\r
-            shapeId = other.shapeId;\r
-            _records = other._records;\r
-        }\r
+        _headerAtom = other._headerAtom;\r
+        _byteAtom = other._byteAtom;\r
+        _charAtom = other._charAtom;\r
+        _parentShape = other._parentShape;\r
+        _sheet = other._sheet;\r
+        _ruler = other._ruler;\r
+        shapeId = other.shapeId;\r
+        _paragraphStyle.copy(other._paragraphStyle);\r
+    }\r
 \r
        public void addTextRun(HSLFTextRun run) {\r
            _runs.add(run);\r
@@ -120,7 +115,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        }\r
 \r
        public void setParagraphStyle(TextPropCollection paragraphStyle) {\r
-           _paragraphStyle = paragraphStyle;\r
+           _paragraphStyle.copy(paragraphStyle);\r
        }\r
 \r
        /**\r
@@ -196,20 +191,52 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         _ruler = getTextRuler();\r
         if (_ruler == null) {\r
             _ruler = TextRulerAtom.getParagraphInstance();\r
-            _headerAtom.getParentRecord().appendChildRecord(_ruler);\r
+            Record childAfter = _byteAtom;\r
+            if (childAfter == null) childAfter = _charAtom;\r
+            if (childAfter == null) childAfter = _headerAtom;\r
+            _headerAtom.getParentRecord().addChildAfter(_ruler, childAfter);\r
         }\r
         return _ruler;\r
     }\r
 \r
     /**\r
-     * Returns records that make up this text run\r
+     * Returns records that make up the list of text paragraphs\r
+     * (there can be misc InteractiveInfo, TxInteractiveInfo and other records)\r
      *\r
      * @return text run records\r
      */\r
     public Record[] getRecords(){\r
-        return _records;\r
+        Record r[] = _headerAtom.getParentRecord().getChildRecords();\r
+        return getRecords(r, new int[]{0}, _headerAtom);\r
     }\r
 \r
+    private static Record[] getRecords(Record[] records, int[] startIdx, TextHeaderAtom headerAtom) {\r
+        if (records == null) {\r
+            throw new NullPointerException("records need to be set.");\r
+        }\r
+        \r
+        for (; startIdx[0] < records.length; startIdx[0]++) {\r
+            Record r = records[startIdx[0]];\r
+            if (r instanceof TextHeaderAtom && (headerAtom == null || r == headerAtom)) break;\r
+        }\r
+\r
+        if (startIdx[0] >= records.length) {\r
+            logger.log(POILogger.INFO, "header atom wasn't found - container might contain only an OutlineTextRefAtom");\r
+            return new Record[0];\r
+        }\r
+        \r
+        int length;\r
+        for (length = 1; startIdx[0]+length < records.length; length++) {\r
+            if (records[startIdx[0]+length] instanceof TextHeaderAtom) break;\r
+        }\r
+        \r
+        Record result[] = new Record[length];\r
+        System.arraycopy(records, startIdx[0], result, 0, length);\r
+        startIdx[0] += length;\r
+        \r
+        return result;\r
+    }\r
+    \r
     /** Numbered List info */\r
        public void setStyleTextProp9Atom(final StyleTextProp9Atom styleTextProp9Atom) {\r
                this.styleTextProp9Atom = styleTextProp9Atom;\r
@@ -220,11 +247,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
                return this.styleTextProp9Atom;\r
        }\r
 \r
-    /** Characters covered */\r
-       public StyleTextPropAtom getStyleTextPropAtom() {\r
-               return this._styleAtom;\r
-       }\r
-\r
        /**\r
      * Fetch the value of the given Paragraph related TextProp.\r
      * Returns -1 if that TextProp isn't present.\r
@@ -232,14 +254,9 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
      *  Master Sheet will apply.\r
      */\r
     private int getParaTextPropVal(String propName) {\r
-        TextProp prop = null;\r
-        boolean hardAttribute = false;\r
-        if (_paragraphStyle != null){\r
-            prop = _paragraphStyle.findByName(propName);\r
-\r
-            BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);\r
-            hardAttribute = maskProp != null && maskProp.getValue() == 0;\r
-        }\r
+        TextProp prop = _paragraphStyle.findByName(propName);\r
+        BitMaskTextProp maskProp = (BitMaskTextProp)_paragraphStyle.findByName(ParagraphFlagsTextProp.NAME);\r
+        boolean hardAttribute = (maskProp != null && maskProp.getValue() == 0);\r
         if (prop == null && !hardAttribute){\r
             HSLFSheet sheet = getSheet();\r
             int txtype = getRunType();\r
@@ -258,11 +275,6 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
      */\r
     public void setParaTextPropVal(String propName, int val) {\r
         // Ensure we have the StyleTextProp atom we're going to need\r
-        if(_paragraphStyle == null) {\r
-            _styleAtom = findStyleAtomPresent(_headerAtom, -1);\r
-            _paragraphStyle = _styleAtom.getParagraphStyles().get(0);\r
-        }\r
-\r
         assert(_paragraphStyle!=null);\r
         TextProp tp = fetchOrAddTextProp(_paragraphStyle, propName);\r
         tp.setValue(val);\r
@@ -615,10 +627,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
 \r
    protected void setFlag(int index, boolean value) {\r
        // Ensure we have the StyleTextProp atom we're going to need\r
-       if(_paragraphStyle == null) {\r
-           _paragraphStyle = new TextPropCollection(1, TextPropType.paragraph);\r
-       }\r
-\r
+       assert(_paragraphStyle!=null);\r
        BitMaskTextProp prop = (BitMaskTextProp) fetchOrAddTextProp(_paragraphStyle, ParagraphFlagsTextProp.NAME);\r
        prop.setSubValue(value,index);\r
    }\r
@@ -653,12 +662,13 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
        boolean afterHeader = false;\r
        StyleTextPropAtom style = null;\r
        for (Record record : header.getParentRecord().getChildRecords()) {\r
-           if (afterHeader && record.getRecordType() == RecordTypes.TextHeaderAtom.typeID) {\r
+           long rt = record.getRecordType();\r
+           if (afterHeader && rt == RecordTypes.TextHeaderAtom.typeID) {\r
                // already on the next header, quit searching\r
                break;\r
            }\r
            afterHeader |= (header == record);\r
-           if (afterHeader && record.getRecordType() == RecordTypes.StyleTextPropAtom.typeID) {\r
+           if (afterHeader && rt == RecordTypes.StyleTextPropAtom.typeID) {\r
                // found it\r
                style = (StyleTextPropAtom)record;\r
            }\r
@@ -789,12 +799,20 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         * If TextSpecInfoAtom is present, we must update the text size in it,\r
         * otherwise the ppt will be corrupted\r
         */\r
-       for (Record r : paragraphs.get(0)._records) {\r
+       for (Record r : paragraphs.get(0).getRecords()) {\r
            if (r instanceof TextSpecInfoAtom) {\r
                ((TextSpecInfoAtom)r).setParentSize(rawText.length()+1);\r
                break;\r
            }\r
        }\r
+       \r
+       if (_txtbox instanceof EscherTextboxWrapper) {\r
+           try {\r
+               ((EscherTextboxWrapper)_txtbox).writeOut(null);\r
+           } catch (IOException e) {\r
+               throw new RuntimeException("failed dummy write", e);\r
+           }\r
+       }\r
    }\r
 \r
    /**\r
@@ -817,7 +835,7 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
            if (!isFirst) {\r
                TextPropCollection tpc = htp.getParagraphStyle();\r
                HSLFTextParagraph prevHtp = htp;\r
-               htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom, htp._styleAtom);\r
+               htp = new HSLFTextParagraph(htp._headerAtom, htp._byteAtom, htp._charAtom);\r
                htp.getParagraphStyle().copy(tpc);\r
                htp.setParentShape(prevHtp.getParentShape());\r
                htp.setShapeId(prevHtp.getShapeId());\r
@@ -930,24 +948,14 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
    /**\r
     * For a given PPDrawing, grab all the TextRuns\r
     */\r
-   public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing) {\r
+   public static List<List<HSLFTextParagraph>> findTextParagraphs(PPDrawing ppdrawing, HSLFSheet sheet) {\r
        List<List<HSLFTextParagraph>> runsV = new ArrayList<List<HSLFTextParagraph>>();\r
        for (EscherTextboxWrapper wrapper : ppdrawing.getTextboxWrappers()) {\r
-           runsV.addAll(findTextParagraphs(wrapper));\r
+           runsV.add(findTextParagraphs(wrapper, sheet));\r
        }\r
        return runsV;\r
    }\r
-   /**\r
-    * Scans through the supplied record array, looking for\r
-    * a TextHeaderAtom followed by one of a TextBytesAtom or\r
-    * a TextCharsAtom. Builds up TextRuns from these\r
-    *\r
-    * @param records the records to build from\r
-    * @param found   vector to add any found to\r
-    */\r
-   protected static List<List<HSLFTextParagraph>> findTextParagraphs(final Record[] records) {\r
-       return findTextParagraphs(records, null);\r
-   }\r
+\r
    /**\r
     * Scans through the supplied record array, looking for\r
     * a TextHeaderAtom followed by one of a TextBytesAtom or\r
@@ -955,14 +963,73 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     *\r
     * @param wrapper an EscherTextboxWrapper\r
     */\r
-   protected static List<List<HSLFTextParagraph>> findTextParagraphs(EscherTextboxWrapper wrapper) {\r
+   protected static List<HSLFTextParagraph> findTextParagraphs(EscherTextboxWrapper wrapper, HSLFSheet sheet) {\r
        // propagate parents to parent-aware records\r
        RecordContainer.handleParentAwareRecords(wrapper);\r
        int shapeId = wrapper.getShapeId();\r
-       List<List<HSLFTextParagraph>> rv = findTextParagraphs(wrapper.getChildRecords(), wrapper.getStyleTextProp9Atom());\r
-       for (List<HSLFTextParagraph> htpList : rv) {\r
-           for (HSLFTextParagraph htp : htpList) {\r
+       List<HSLFTextParagraph> rv = null;\r
+       \r
+       OutlineTextRefAtom ota = (OutlineTextRefAtom)wrapper.findFirstOfType(OutlineTextRefAtom.typeID);\r
+       if (ota != null) {\r
+           // if we are based on an outline, there are no further records to be parsed from the wrapper\r
+           if (sheet == null) {\r
+               throw new RuntimeException("Outline atom reference can't be solved without a sheet record");\r
+           }\r
+           \r
+           List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();\r
+           assert(sheetRuns != null);\r
+           \r
+           int idx = ota.getTextIndex();\r
+           for (List<HSLFTextParagraph> r : sheetRuns) {\r
+               if (r.isEmpty()) continue;\r
+               int ridx = r.get(0).getIndex();\r
+               if (ridx > idx) break;\r
+               if (ridx == idx) {\r
+                   if (rv == null) {\r
+                       rv = r;\r
+                   } else {\r
+                       // create a new container\r
+                       // TODO: ... is this case really happening?\r
+                       rv = new ArrayList<HSLFTextParagraph>(rv);\r
+                       rv.addAll(r);\r
+                   }\r
+               }\r
+           }\r
+           if(rv == null || rv.isEmpty()) {\r
+               logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);\r
+           }\r
+       } else {\r
+           if (sheet != null) {\r
+               // check sheet runs first, so we get exactly the same paragraph list\r
+               List<List<HSLFTextParagraph>> sheetRuns = sheet.getTextParagraphs();\r
+               assert(sheetRuns != null);\r
+\r
+               for (List<HSLFTextParagraph> paras : sheetRuns) {\r
+                   if (!paras.isEmpty() && paras.get(0)._headerAtom.getParentRecord() == wrapper) {\r
+                       rv = paras;\r
+                       break;\r
+                   }\r
+               }\r
+           }\r
+           \r
+           if (rv == null) {\r
+               // if we haven't found the wrapper in the sheet runs, create a new paragraph list from its record\r
+               List<List<HSLFTextParagraph>> rvl = findTextParagraphs(wrapper.getChildRecords());\r
+               switch (rvl.size()) {\r
+               case 0: break; // nothing found\r
+               case 1: rv = rvl.get(0); break; // normal case\r
+               default:\r
+                   throw new RuntimeException("TextBox contains more than one list of paragraphs.");\r
+               }\r
+           }\r
+       }\r
+       \r
+       if (rv !=  null) {\r
+           StyleTextProp9Atom styleTextProp9Atom = wrapper.getStyleTextProp9Atom();\r
+           \r
+           for (HSLFTextParagraph htp : rv) {\r
                htp.setShapeId(shapeId);\r
+               htp.setStyleTextProp9Atom(styleTextProp9Atom);\r
            }\r
        }\r
        return rv;\r
@@ -974,77 +1041,59 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
     * a TextCharsAtom. Builds up TextRuns from these\r
     *\r
     * @param records the records to build from\r
-    * @param styleTextProp9Atom an optional StyleTextProp9Atom with numbered lists info\r
     */\r
-    protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records, StyleTextProp9Atom styleTextProp9Atom) {\r
+    protected static List<List<HSLFTextParagraph>> findTextParagraphs(Record[] records) {\r
         List<List<HSLFTextParagraph>> paragraphCollection = new ArrayList<List<HSLFTextParagraph>>();\r
 \r
-        if (records == null) {\r
-            throw new NullPointerException("records need to be filled.");\r
-        }\r
-\r
-        int recordIdx;\r
-        for (recordIdx = 0; recordIdx < records.length; recordIdx++) {\r
-            if (records[recordIdx] instanceof TextHeaderAtom) break;\r
-        }\r
-\r
-        if (recordIdx == records.length) {\r
-            logger.log(POILogger.INFO, "No text records found.");\r
-            return paragraphCollection;\r
-        }\r
-\r
-        for (int slwtIndex = 0; recordIdx < records.length; slwtIndex++) {\r
-            List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();\r
-            paragraphCollection.add(paragraphs);\r
-\r
-            TextHeaderAtom    header = (TextHeaderAtom)records[recordIdx++];\r
+        int[] recordIdx = {0};\r
+        \r
+        for (int slwtIndex = 0; recordIdx[0] < records.length; slwtIndex++) {\r
+            TextHeaderAtom    header = null;\r
             TextBytesAtom     tbytes = null;\r
             TextCharsAtom     tchars = null;\r
             TextRulerAtom     ruler  = null;\r
             MasterTextPropAtom indents = null;\r
 \r
-            List<Record> otherRecordList = new ArrayList<Record>();\r
-\r
-            for (; recordIdx < records.length; recordIdx++) {\r
-                Record r = records[recordIdx];\r
+            for (Record r : getRecords(records, recordIdx, null)) {\r
                 long rt = r.getRecordType();\r
-                if (RecordTypes.TextHeaderAtom.typeID == rt) break;\r
-                else if (RecordTypes.TextBytesAtom.typeID == rt) tbytes = (TextBytesAtom)r;\r
-                else if (RecordTypes.TextCharsAtom.typeID == rt) tchars = (TextCharsAtom)r;\r
-                // don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below\r
-                else if (RecordTypes.TextRulerAtom.typeID == rt) ruler = (TextRulerAtom)r;\r
-                else if (RecordTypes.MasterTextPropAtom.typeID == rt) {\r
+                if (RecordTypes.TextHeaderAtom.typeID == rt) {\r
+                    header = (TextHeaderAtom)r;\r
+                } else if (RecordTypes.TextBytesAtom.typeID == rt) {\r
+                    tbytes = (TextBytesAtom)r;\r
+                } else if (RecordTypes.TextCharsAtom.typeID == rt) {\r
+                    tchars = (TextCharsAtom)r;\r
+                } else if (RecordTypes.TextRulerAtom.typeID == rt) {\r
+                    ruler = (TextRulerAtom)r;\r
+                } else if (RecordTypes.MasterTextPropAtom.typeID == rt) {\r
                     indents = (MasterTextPropAtom)r;\r
-                    otherRecordList.add(indents);\r
-                } else {\r
-                    otherRecordList.add(r);\r
                 }\r
+                // don't search for RecordTypes.StyleTextPropAtom.typeID here ... see findStyleAtomPresent below\r
             }\r
 \r
-            assert(header != null);\r
+            if (header == null) break;\r
+            \r
             if (header.getParentRecord() instanceof SlideListWithText) {\r
                 // runs found in PPDrawing are not linked with SlideListWithTexts\r
                 header.setIndex(slwtIndex);\r
             }\r
 \r
-            Record otherRecords[] = otherRecordList.toArray(new Record[otherRecordList.size()]);\r
-\r
             if (tbytes == null && tchars == null) {\r
                 tbytes = new TextBytesAtom();\r
-                // header.getParentRecord().addChildAfter(tbytes, header);\r
+                // don't add record yet - set it in storeText\r
                 logger.log(POILogger.INFO, "bytes nor chars atom doesn't exist. Creating dummy record for later saving.");\r
             }\r
 \r
             String rawText = (tchars != null) ? tchars.getText() : tbytes.getText();\r
             StyleTextPropAtom styles = findStyleAtomPresent(header, rawText.length());\r
 \r
+            List<HSLFTextParagraph> paragraphs = new ArrayList<HSLFTextParagraph>();\r
+            paragraphCollection.add(paragraphs);\r
+            \r
             // split, but keep delimiter\r
             for (String para : rawText.split("(?<=\r)")) {\r
-                HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars, styles);\r
+                HSLFTextParagraph tpara = new HSLFTextParagraph(header, tbytes, tchars);\r
                 paragraphs.add(tpara);\r
-                tpara.setStyleTextProp9Atom(styleTextProp9Atom);\r
                 tpara._ruler = ruler;\r
-                tpara._records = otherRecords;\r
                 tpara.getParagraphStyle().updateTextSize(para.length());\r
 \r
                 HSLFTextRun trun = new HSLFTextRun(tpara);\r
@@ -1059,6 +1108,10 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
             }\r
         }\r
 \r
+        if (paragraphCollection.isEmpty()) {\r
+            logger.log(POILogger.DEBUG, "No text records found.");\r
+        }\r
+        \r
         return paragraphCollection;\r
     }\r
 \r
@@ -1166,9 +1219,8 @@ public final class HSLFTextParagraph implements TextParagraph<HSLFTextRun> {
         TextPropCollection charStyle = sta.addCharacterTextPropCollection(1);\r
         wrapper.appendChildRecord(sta);\r
 \r
-        HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null, sta);\r
+        HSLFTextParagraph htp = new HSLFTextParagraph(tha, tba, null);\r
         htp.setParagraphStyle(paraStyle);\r
-        htp._records = new Record[0];\r
 \r
         HSLFTextRun htr = new HSLFTextRun(htp);\r
         htr.setCharacterStyle(charStyle);\r
index 0fb443b604d2af6713aa3b6e3da3c27d7619339c..1e1dca888fd7d14d3852bfdaa576129acd55ec1b 100644 (file)
@@ -92,7 +92,7 @@ public final class HSLFTextRun implements TextRun {
         * Change the text
         */
        public void setText(String text) {
-           _runText = text;
+           _runText = HSLFTextParagraph.toInternalString(text);
        }
 
        // --------------- Internal helpers on rich text properties -------
index e05ae79a60a4815c8663d74a35f5d0584c0a5808..60e9eb84e26c964639eb004450f60b12d12bad8e 100644 (file)
@@ -159,10 +159,29 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
     }
 
     protected EscherTextboxWrapper getEscherTextboxWrapper(){
-        if(_txtbox == null){
-            EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID);
-            if(textRecord != null) _txtbox = new EscherTextboxWrapper(textRecord);
+        if(_txtbox != null) return _txtbox;
+        
+        EscherTextboxRecord textRecord = getEscherChild(EscherTextboxRecord.RECORD_ID);
+        if (textRecord == null) return null;
+        
+        HSLFSheet sheet = getSheet();
+        if (sheet != null) {
+            PPDrawing drawing = sheet.getPPDrawing();
+            if (drawing != null) {
+                EscherTextboxWrapper wrappers[] = drawing.getTextboxWrappers();
+                if (wrappers != null) {
+                    for (EscherTextboxWrapper w : wrappers) {
+                        // check for object identity
+                        if (textRecord == w.getEscherRecord()) {
+                            _txtbox = w;
+                            return _txtbox;
+                        }
+                    }
+                }
+            }
         }
+        
+        _txtbox = new EscherTextboxWrapper(textRecord);
         return _txtbox;
     }
 
@@ -507,13 +526,17 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
             _paragraphs.addAll(HSLFTextParagraph.createEmptyParagraph());
             _txtbox = _paragraphs.get(0).getTextboxWrapper();
         } else {
-            initParagraphsFromSheetRecords();
-            if (_paragraphs.isEmpty()) {
-                List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_txtbox);
-                if (!llhtp.isEmpty()) {
-                    _paragraphs.addAll(llhtp.get(0));
-                }
+            _paragraphs = HSLFTextParagraph.findTextParagraphs(_txtbox, getSheet());
+            if (_paragraphs == null || _paragraphs.isEmpty()) {
+                throw new RuntimeException("TextRecord didn't contained any text lines");
             }
+//            initParagraphsFromSheetRecords();
+//            if (_paragraphs.isEmpty()) {
+//                List<List<HSLFTextParagraph>> llhtp = HSLFTextParagraph.findTextParagraphs(_txtbox);
+//                if (!llhtp.isEmpty()) {
+//                    _paragraphs.addAll(llhtp.get(0));
+//                }
+//            }
         }
 
         for (HSLFTextParagraph p : _paragraphs) {
@@ -536,57 +559,47 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
         }
     }
 
-    protected void initParagraphsFromSheetRecords(){
-        EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
-        HSLFSheet sheet = getSheet();
-
-        if(sheet == null || txtbox == null) return;
-
-        OutlineTextRefAtom ota = null;
-
-        Record[] child = txtbox.getChildRecords();
-        for (int i = 0; i < child.length; i++) {
-            if (child[i] instanceof OutlineTextRefAtom) {
-                ota = (OutlineTextRefAtom)child[i];
-                break;
-            }
-        }
-
-        List<List<HSLFTextParagraph>> sheetRuns = _sheet.getTextParagraphs();
-        _paragraphs.clear();
-        if (sheetRuns != null) {
-            if (ota != null) {
-                int idx = ota.getTextIndex();
-                for (List<HSLFTextParagraph> r : sheetRuns) {
-                    if (r.isEmpty()) continue;
-                    int ridx = r.get(0).getIndex();
-                    if (ridx > idx) break;
-                    if (ridx == idx) _paragraphs.addAll(r);
-                }
-                if(_paragraphs.isEmpty()) {
-                    logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
-                }
-            } else {
-                int shapeId = getShapeId();
-                for (List<HSLFTextParagraph> r : sheetRuns) {
-                    if (r.isEmpty()) continue;
-                    if (r.get(0).getShapeId() == shapeId) _paragraphs.addAll(r);
-                }
-            }
-        }
-
-        // ensure the same references child records of TextRun
-        // TODO: check the purpose of this ...
-//        if(_txtrun != null) {
-//            for (int i = 0; i < child.length; i++) {
-//                for (Record r : _txtrun.getRecords()) {
-//                    if (child[i].getRecordType() == r.getRecordType()) {
-//                        child[i] = r;
-//                    }
-//                }
+//    protected void initParagraphsFromSheetRecords(){
+//        EscherTextboxWrapper txtbox = getEscherTextboxWrapper();
+//        HSLFSheet sheet = getSheet();
+//
+//        if (sheet == null || txtbox == null) return;
+//        List<List<HSLFTextParagraph>> sheetRuns = _sheet.getTextParagraphs();
+//        if (sheetRuns == null) return;
+//
+//        _paragraphs.clear();
+//        OutlineTextRefAtom ota = (OutlineTextRefAtom)txtbox.findFirstOfType(OutlineTextRefAtom.typeID);
+//
+//        if (ota != null) {
+//            int idx = ota.getTextIndex();
+//            for (List<HSLFTextParagraph> r : sheetRuns) {
+//                if (r.isEmpty()) continue;
+//                int ridx = r.get(0).getIndex();
+//                if (ridx > idx) break;
+//                if (ridx == idx) _paragraphs.addAll(r);
+//            }
+//            if(_paragraphs.isEmpty()) {
+//                logger.log(POILogger.WARN, "text run not found for OutlineTextRefAtom.TextIndex=" + idx);
+//            }
+//        } else {
+//            int shapeId = getShapeId();
+//            for (List<HSLFTextParagraph> r : sheetRuns) {
+//                if (r.isEmpty()) continue;
+//                if (r.get(0).getShapeId() == shapeId) _paragraphs.addAll(r);
 //            }
 //        }
-    }
+//
+//        // ensure the same references child records of TextRun - see #48916
+////        if(_txtrun != null) {
+////            for (int i = 0; i < child.length; i++) {
+////                for (Record r : _txtrun.getRecords()) {
+////                    if (child[i].getRecordType() == r.getRecordType()) {
+////                        child[i] = r;
+////                    }
+////                }
+////            }
+////        }
+//    }
 
     /*
         // 0xB acts like cariage return in page titles and like blank in the others
@@ -740,7 +753,8 @@ public abstract class HSLFTextShape extends HSLFSimpleShape implements TextShape
        * Also updates the styles to the correct text length.
        */
       protected void storeText() {
-          HSLFTextParagraph.storeText(_paragraphs);
+          List<HSLFTextParagraph> paras = getTextParagraphs();
+          HSLFTextParagraph.storeText(paras);
       }
       // Accesser methods follow
 
index fc6131d952ce108509ccca9f03b0b7dd69055f79..b1e38d977b13fd653a78a96eb1417ab8ddcb36fb 100644 (file)
@@ -29,7 +29,7 @@ import org.apache.poi.hslf.record.SlideAtom;
  * @author Yegor Kozlov
  */
 public final class HSLFTitleMaster extends HSLFMasterSheet {
-    private final List<List<HSLFTextParagraph>> _runs = new ArrayList<List<HSLFTextParagraph>>();
+    private final List<List<HSLFTextParagraph>> _paragraphs = new ArrayList<List<HSLFTextParagraph>>();
 
     /**
      * Constructs a TitleMaster
@@ -38,14 +38,16 @@ public final class HSLFTitleMaster extends HSLFMasterSheet {
     public HSLFTitleMaster(org.apache.poi.hslf.record.Slide record, int sheetNo) {
         super(record, sheetNo);
 
-        _runs.addAll(HSLFTextParagraph.findTextParagraphs(getPPDrawing()));
+        for (List<HSLFTextParagraph> l : HSLFTextParagraph.findTextParagraphs(getPPDrawing(), this)) {
+            if (!_paragraphs.contains(l)) _paragraphs.add(l);
+        }
     }
 
     /**
      * Returns an array of all the TextRuns found
      */
     public List<List<HSLFTextParagraph>> getTextParagraphs() {
-        return _runs;
+        return _paragraphs;
     }
 
     /**
index df4d635a69beb4a557b560148590aae98778604a..6eb30eb7078001d69fc09f03d43521b8fd8cc751 100644 (file)
@@ -69,8 +69,8 @@ public class DrawFactory {
             return getDrawable((FreeformShape<? extends TextParagraph<? extends TextRun>>)shape);\r
         } else if (shape instanceof TextShape) {\r
             return getDrawable((TextShape<? extends TextParagraph<? extends TextRun>>)shape);\r
-        } else if (shape instanceof ShapeGroup) {\r
-            return getDrawable((ShapeGroup<? extends Shape>)shape);\r
+        } else if (shape instanceof GroupShape) {\r
+            return getDrawable((GroupShape<? extends Shape>)shape);\r
         } else if (shape instanceof PictureShape) {\r
             return getDrawable((PictureShape)shape);\r
         } else if (shape instanceof Background) {\r
@@ -110,8 +110,8 @@ public class DrawFactory {
         return new DrawTextShape<T>(shape);\r
     }\r
 \r
-    public <T extends ShapeGroup<? extends Shape>> DrawShapeGroup<T> getDrawable(T shape) {\r
-        return new DrawShapeGroup<T>(shape);\r
+    public <T extends GroupShape<? extends Shape>> DrawGroupShape<T> getDrawable(T shape) {\r
+        return new DrawGroupShape<T>(shape);\r
     }\r
     \r
     public <T extends PictureShape> DrawPictureShape<T> getDrawable(T shape) {\r
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawGroupShape.java
new file mode 100644 (file)
index 0000000..31f2496
--- /dev/null
@@ -0,0 +1,53 @@
+package org.apache.poi.sl.draw;\r
+\r
+import java.awt.Graphics2D;\r
+import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Rectangle2D;\r
+\r
+import org.apache.poi.sl.usermodel.*;\r
+\r
+\r
+public class DrawGroupShape<T extends GroupShape<? extends Shape>> extends DrawShape<T> implements Drawable {\r
+\r
+    public DrawGroupShape(T shape) {\r
+        super(shape);\r
+    }\r
+    \r
+    public void draw(Graphics2D graphics) {\r
+\r
+        // the coordinate system of this group of shape\r
+        Rectangle2D interior = shape.getInteriorAnchor();\r
+        // anchor of this group relative to the parent shape\r
+        Rectangle2D exterior = shape.getAnchor();\r
+\r
+        AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);\r
+        AffineTransform tx0 = new AffineTransform(tx);\r
+\r
+        double scaleX = interior.getWidth() == 0. ? 1.0 : exterior.getWidth() / interior.getWidth();\r
+        double scaleY = interior.getHeight() == 0. ? 1.0 : exterior.getHeight() / interior.getHeight();\r
+\r
+        tx.translate(exterior.getX(), exterior.getY());\r
+        tx.scale(scaleX, scaleY);\r
+        tx.translate(-interior.getX(), -interior.getY());\r
+\r
+        DrawFactory drawFact = DrawFactory.getInstance(graphics);\r
+        AffineTransform at2 = graphics.getTransform();\r
+        \r
+        for (Shape child : shape) {\r
+            // remember the initial transform and restore it after we are done with the drawing\r
+            AffineTransform at = graphics.getTransform();\r
+            graphics.setRenderingHint(Drawable.GSAVE, true);\r
+\r
+            Drawable draw = drawFact.getDrawable(child);\r
+            draw.applyTransform(graphics);\r
+            draw.draw(graphics);\r
+\r
+            // restore the coordinate system\r
+            graphics.setTransform(at);\r
+            graphics.setRenderingHint(Drawable.GRESTORE, true);\r
+        }\r
+\r
+        graphics.setTransform(at2);\r
+        graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0);\r
+    }\r
+}\r
index 6cb60c9b0188cc676439050437e9d0c9ccb968fd..2bebbfa892728e9dcd33e7c1b98f488d60baf8e0 100644 (file)
@@ -25,11 +25,10 @@ public class DrawShape<T extends Shape> implements Drawable {
         if (!(shape instanceof PlaceableShape)) return;\r
         \r
         PlaceableShape ps = (PlaceableShape)shape;\r
-        Rectangle2D anchor = ps.getAnchor();\r
         AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);\r
-        if(tx != null) {\r
-            anchor = tx.createTransformedShape(anchor).getBounds2D();\r
-        }\r
+        final Rectangle2D anchor = (tx != null)\r
+            ? tx.createTransformedShape(ps.getAnchor()).getBounds2D()\r
+            : ps.getAnchor();\r
 \r
         // rotation\r
         double rotation = ps.getRotation();\r
@@ -39,7 +38,8 @@ public class DrawShape<T extends Shape> implements Drawable {
             double centerY = anchor.getCenterY();\r
 \r
             // normalize rotation\r
-            rotation = (360.+(rotation%360.))%360.;\r
+            rotation %= 360.;\r
+            if (rotation < 0) rotation += 360.;\r
             int quadrant = (((int)rotation+45)/90)%4;\r
             double scaleX = 1.0, scaleY = 1.0;\r
 \r
@@ -53,26 +53,43 @@ public class DrawShape<T extends Shape> implements Drawable {
                 // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might\r
                 // be already (differently) scaled, so you can paint the shape in its default orientation\r
                 // and later on, turn it around again to compare it with its original size ...\r
-                AffineTransform txg = new AffineTransform(); // graphics coordinate space\r
-                AffineTransform txs = new AffineTransform(tx); // shape coordinate space\r
+\r
+                // graphics coordinate space\r
+                AffineTransform txg = new AffineTransform();\r
                 txg.translate(centerX, centerY);\r
-                txg.rotate(Math.toRadians(quadrant*90));\r
+                txg.rotate(Math.toRadians(90));\r
                 txg.translate(-centerX, -centerY);\r
-                txs.translate(centerX, centerY);\r
-                txs.rotate(Math.toRadians(-quadrant*90));\r
-                txs.translate(-centerX, -centerY);\r
-                txg.concatenate(txs);\r
-                Rectangle2D anchor2 = txg.createTransformedShape(ps.getAnchor()).getBounds2D();\r
+\r
+                boolean oldVariant = true;\r
+                Rectangle2D anchor2;\r
+                \r
+                if (oldVariant) {\r
+                    // shape coordinate space\r
+                    AffineTransform txs = new AffineTransform(tx);\r
+                    txs.translate(centerX, centerY);\r
+                    txs.rotate(Math.toRadians(90));\r
+                    txs.translate(-centerX, -centerY);\r
+                    txg.concatenate(txs);\r
+                    anchor2 = txg.createTransformedShape(ps.getAnchor()).getBounds2D();\r
+                } else {\r
+                    anchor2 = txg.createTransformedShape(anchor).getBounds2D();\r
+                }\r
+\r
                 scaleX = anchor.getWidth() == 0. ? 1.0 : anchor.getWidth() / anchor2.getWidth();\r
                 scaleY = anchor.getHeight() == 0. ? 1.0 : anchor.getHeight() / anchor2.getHeight();\r
+                \r
+                graphics.translate(centerX, centerY);\r
+                graphics.rotate(Math.toRadians(rotation-quadrant*90.));\r
+                graphics.scale(scaleX, scaleY);\r
+                graphics.rotate(Math.toRadians(quadrant*90));\r
+                graphics.translate(-centerX, -centerY);\r
+            } else {\r
+                graphics.translate(centerX, centerY);\r
+                graphics.rotate(Math.toRadians(rotation));\r
+                graphics.scale(scaleX, scaleY);\r
+                graphics.translate(-centerX, -centerY);\r
             }\r
-\r
             // transformation is applied reversed ...\r
-            graphics.translate(centerX, centerY);\r
-            graphics.rotate(Math.toRadians(rotation-quadrant*90.));\r
-            graphics.scale(scaleX, scaleY);\r
-            graphics.rotate(Math.toRadians(quadrant*90));\r
-            graphics.translate(-centerX, -centerY);\r
         }\r
 \r
         //flip horizontal\r
diff --git a/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java b/src/scratchpad/src/org/apache/poi/sl/draw/DrawShapeGroup.java
deleted file mode 100644 (file)
index ceda928..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.apache.poi.sl.draw;\r
-\r
-import java.awt.Graphics2D;\r
-import java.awt.geom.AffineTransform;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-import org.apache.poi.sl.usermodel.*;\r
-\r
-\r
-public class DrawShapeGroup<T extends ShapeGroup<? extends Shape>> extends DrawShape<T> implements Drawable {\r
-\r
-    public DrawShapeGroup(T shape) {\r
-        super(shape);\r
-    }\r
-    \r
-    public void draw(Graphics2D graphics) {\r
-\r
-        // the coordinate system of this group of shape\r
-        Rectangle2D interior = shape.getInteriorAnchor();\r
-        // anchor of this group relative to the parent shape\r
-        Rectangle2D exterior = shape.getAnchor();\r
-\r
-        AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);\r
-        AffineTransform tx0 = new AffineTransform(tx);\r
-\r
-        double scaleX = interior.getWidth() == 0. ? 1.0 : exterior.getWidth() / interior.getWidth();\r
-        double scaleY = interior.getHeight() == 0. ? 1.0 : exterior.getHeight() / interior.getHeight();\r
-\r
-        tx.translate(exterior.getX(), exterior.getY());\r
-        tx.scale(scaleX, scaleY);\r
-        tx.translate(-interior.getX(), -interior.getY());\r
-\r
-        DrawFactory drawFact = DrawFactory.getInstance(graphics);\r
-        \r
-        for (Shape child : shape) {\r
-            // remember the initial transform and restore it after we are done with the drawing\r
-            AffineTransform at = graphics.getTransform();\r
-            graphics.setRenderingHint(Drawable.GSAVE, true);\r
-\r
-            Drawable draw = drawFact.getDrawable(child);\r
-            draw.applyTransform(graphics);\r
-            draw.draw(graphics);\r
-\r
-            // restore the coordinate system\r
-            graphics.setTransform(at);\r
-            graphics.setRenderingHint(Drawable.GRESTORE, true);\r
-        }\r
-\r
-        graphics.setRenderingHint(Drawable.GROUP_TRANSFORM, tx0);\r
-        \r
-    }\r
-}\r
index 8789082afd42d635cda354b04f97a4b3e4570ed0..54128b82c6c72b9fb3b93e9ff1eb290e393f73c8 100644 (file)
@@ -32,6 +32,23 @@ public interface Drawable {
         public boolean isCompatibleValue(Object val) {\r
             return true;\r
         }\r
+        \r
+        public String toString() {\r
+            switch (intKey()) {\r
+            case 1: return "DRAW_FACTORY";\r
+            case 2: return "GROUP_TRANSFORM";\r
+            case 3: return "IMAGE_RENDERER";\r
+            case 4: return "TEXT_RENDERING_MODE";\r
+            case 5: return "GRADIENT_SHAPE";\r
+            case 6: return "PRESET_GEOMETRY_CACHE";\r
+            case 7: return "FONT_HANDLER";\r
+            case 8: return "FONT_FALLBACK";\r
+            case 9: return "FONT_MAP";\r
+            case 10: return "GSAVE";\r
+            case 11: return "GRESTORE";\r
+            default: return "UNKNOWN_ID "+intKey();\r
+            }\r
+        }\r
     }\r
     \r
     /**\r
index 9704c2c0a7378747fb1cceed5a5787ba86dd95b3..f4a298cdb688551b11c8c1831294ef9be6ef657e 100644 (file)
@@ -30,18 +30,35 @@ import javax.imageio.ImageIO;
 /**\r
  * For now this class renders only images supported by the javax.imageio.ImageIO\r
  * framework. Subclasses can override this class to support other formats, for\r
- * example, Use Apache batik to render WMF:\r
+ * example, use Apache Batik to render WMF, PICT can be rendered using Apple QuickTime API for Java:\r
  *\r
  * <pre>\r
  * <code>\r
  * public class MyImageRendener extends ImageRendener {\r
+ *     InputStream data;\r
  *\r
  *     public boolean drawImage(Graphics2D graphics,Rectangle2D anchor,Insets clip) {\r
  *         // draw image\r
+ *       DataInputStream is = new DataInputStream(data);\r
+ *       org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore wmfStore =\r
+ *               new org.apache.batik.transcoder.wmf.tosvg.WMFRecordStore();\r
+ *       try {\r
+ *           wmfStore.read(is);\r
+ *       } catch (IOException e){\r
+ *           return;\r
+ *       }\r
+ *\r
+ *       float scale = (float)anchor.width/wmfStore.getWidthPixels();\r
+ *\r
+ *       org.apache.batik.transcoder.wmf.tosvg.WMFPainter painter =\r
+ *               new org.apache.batik.transcoder.wmf.tosvg.WMFPainter(wmfStore, 0, 0, scale);\r
+ *       graphics.translate(anchor.x, anchor.y);\r
+ *       painter.paint(graphics);\r
  *     }\r
  *\r
  *     public void loadImage(InputStream data, String contentType) throws IOException {\r
  *         if ("image/wmf".equals(contentType)) {\r
+ *             this.data = data;\r
  *             // use Apache Batik to handle WMF\r
  *         } else {\r
  *             super.loadImage(data,contentType);\r
@@ -147,12 +164,14 @@ public class ImageRenderer {
         int iw = img.getWidth();\r
         int ih = img.getHeight();\r
 \r
+        \r
         double cw = (100000-clip.left-clip.right) / 100000.0;\r
         double ch = (100000-clip.top-clip.bottom) / 100000.0;\r
         double sx = anchor.getWidth()/(iw*cw);\r
         double sy = anchor.getHeight()/(ih*ch);\r
         double tx = anchor.getX()-(iw*sx*clip.left/100000.0);\r
         double ty = anchor.getY()-(ih*sy*clip.top/100000.0);\r
+\r
         AffineTransform at = new AffineTransform(sx, 0, 0, sy, tx, ty) ;\r
 \r
         Shape clipOld = graphics.getClip();\r
diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/GroupShape.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/GroupShape.java
new file mode 100644 (file)
index 0000000..d71bb25
--- /dev/null
@@ -0,0 +1,39 @@
+/* ====================================================================
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================== */
+
+package org.apache.poi.sl.usermodel;
+
+import java.awt.geom.Rectangle2D;
+
+public interface GroupShape<T extends Shape> extends Shape, ShapeContainer<T>, PlaceableShape {
+
+    /**
+     * Gets the coordinate space of this group.  All children are constrained
+     * to these coordinates.
+     *
+     * @param anchor the coordinate space of this group
+     */
+    Rectangle2D getInteriorAnchor();
+    
+    /**
+     * Sets the coordinate space of this group.  All children are constrained
+     * to these coordinates.
+     *
+     * @param anchor the coordinate space of this group
+     */
+    void setInteriorAnchor(Rectangle2D anchor);
+}
index 970f04353caf837405e830bf86918ea15c5f66f1..a2c0824e0ccf9b561f80ee235419c8920746e8f5 100644 (file)
@@ -20,9 +20,17 @@ package org.apache.poi.sl.usermodel;
 import java.awt.Insets;
 
 public interface PictureShape extends SimpleShape {
-       PictureData getPictureData();
+    /**
+     * Returns the picture data for this picture.
+     *
+     * @return the picture data for this picture.
+     */
+    PictureData getPictureData();
 
        /**
+        * Returns the clipping values as percent ratio relatively to the image size.
+        * The clipping are returned as insets converted/scaled to 100000 (=100%).
+        * 
         * @return the clipping rectangle, which is given in percent in relation to the image width/height
         */
        Insets getClipping();
diff --git a/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java b/src/scratchpad/src/org/apache/poi/sl/usermodel/ShapeGroup.java
deleted file mode 100644 (file)
index 7bd940c..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.sl.usermodel;
-
-import java.awt.geom.Rectangle2D;
-
-public interface ShapeGroup<T extends Shape> extends Shape, ShapeContainer<T>, PlaceableShape {
-    Rectangle2D getInteriorAnchor();
-}
index 6f4ba0ac678c62fbd99d2584ece720a938d81426..f94b7727a780a3aae23c8f3b5c1476a3a1f29c92 100644 (file)
@@ -17,6 +17,8 @@
 
 package org.apache.poi.sl.usermodel;
 
+import java.awt.Graphics2D;
+
 
 /**
  * Common parent of Slides, Notes and Masters
@@ -34,4 +36,11 @@ public interface Sheet<T extends Shape, SS extends SlideShow> extends ShapeConta
        MasterSheet<T,SS> getMasterSheet();
 
        Background getBackground();
+       
+       /**
+        * Convenience method to draw a sheet to a graphics context
+        *
+        * @param graphics
+        */
+       void draw(Graphics2D graphics);
 }
index ca9e6c9a2f72a98b331b049d6111063de1ea5d14..14301af2ba448c93e2db28b0d2f1b08f58d1df6d 100644 (file)
@@ -29,7 +29,6 @@ import org.junit.runners.Suite;
     TestFreeform.class,
     TestHeadersFooters.class,
     TestHyperlink.class,
-    TestImagePainter.class,
     TestLine.class,
     TestMovieShape.class,
     TestOleEmbedding.class,
diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java b/src/scratchpad/testcases/org/apache/poi/hslf/model/TestImagePainter.java
deleted file mode 100644 (file)
index 963beee..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/* ====================================================================
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You under the Apache License, Version 2.0
-   (the "License"); you may not use this file except in compliance with
-   the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hslf.model;
-
-import java.awt.Graphics2D;
-
-import junit.framework.TestCase;
-
-import org.apache.poi.hslf.blip.BitmapPainter;
-import org.apache.poi.hslf.blip.ImagePainter;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFPictureShape;
-
-/**
- * Test Picture shape.
- *
- * @author Yegor Kozlov
- */
-public final class TestImagePainter extends TestCase {
-
-    private static class CustomImagePainter implements ImagePainter {
-        public CustomImagePainter() {
-            // no fields to initialise
-        }
-        public void paint(Graphics2D graphics, HSLFPictureData pict, HSLFPictureShape parent){
-            //do noting
-        }
-    }
-
-    public void testImagePainter() {
-
-        ImagePainter pntr = HSLFPictureData.getImagePainter(HSLFPictureShape.PNG);
-        assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.PNG) instanceof BitmapPainter);
-        assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.JPEG) instanceof BitmapPainter);
-        assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.DIB) instanceof BitmapPainter);
-
-        HSLFPictureData.setImagePainter(HSLFPictureShape.WMF, new CustomImagePainter());
-        assertTrue(HSLFPictureData.getImagePainter(HSLFPictureShape.WMF) instanceof CustomImagePainter);
-    }
-}
index 0c5fcb69bbd1bd75da843d6b0b02213c3792e1e4..3337d58c36262797cbc2dfb752a6255baefd8a19 100644 (file)
@@ -43,15 +43,15 @@ public final class TestTable {
 
         HSLFSlide slide = ppt.createSlide();
 
-        Table tbl = new Table(2, 5);
+        HSLFTable tbl = new HSLFTable(2, 5);
         slide.addShape(tbl);
 
-        TableCell cell = tbl.getCell(0, 0);
+        HSLFTableCell cell = tbl.getCell(0, 0);
         //table cells have type=TextHeaderAtom.OTHER_TYPE, see bug #46033
         assertEquals(TextHeaderAtom.OTHER_TYPE, cell.getTextParagraphs().get(0).getRunType());
 
-        assertTrue(slide.getShapes().get(0) instanceof Table);
-        Table tbl2 = (Table)slide.getShapes().get(0);
+        assertTrue(slide.getShapes().get(0) instanceof HSLFTable);
+        HSLFTable tbl2 = (HSLFTable)slide.getShapes().get(0);
         assertEquals(tbl.getNumberOfColumns(), tbl2.getNumberOfColumns());
         assertEquals(tbl.getNumberOfRows(), tbl2.getNumberOfRows());
 
@@ -61,8 +61,8 @@ public final class TestTable {
 
         ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
         slide = ppt.getSlides().get(0);
-        assertTrue(slide.getShapes().get(0) instanceof Table);
-        Table tbl3 = (Table)slide.getShapes().get(0);
+        assertTrue(slide.getShapes().get(0) instanceof HSLFTable);
+        HSLFTable tbl3 = (HSLFTable)slide.getShapes().get(0);
         assertEquals(tbl.getNumberOfColumns(), tbl3.getNumberOfColumns());
         assertEquals(tbl.getNumberOfRows(), tbl3.getNumberOfRows());
     }
@@ -75,7 +75,7 @@ public final class TestTable {
         HSLFSlideShow ppt = new HSLFSlideShow();
         HSLFSlide slide = ppt.createSlide();
         List<HSLFShape> shapes;
-        Table tbl1 = new Table(1, 5);
+        HSLFTable tbl1 = new HSLFTable(1, 5);
         assertEquals(5, tbl1.getNumberOfColumns());
         assertEquals(1, tbl1.getNumberOfRows());
         slide.addShape(tbl1);
@@ -83,7 +83,7 @@ public final class TestTable {
         shapes = slide.getShapes();
         assertEquals(1, shapes.size());
 
-        Table tbl2 = (Table)shapes.get(0);
+        HSLFTable tbl2 = (HSLFTable)shapes.get(0);
         assertSame(tbl1.getSpContainer(), tbl2.getSpContainer());
 
         assertEquals(tbl1.getNumberOfColumns(), tbl2.getNumberOfColumns());
@@ -93,13 +93,13 @@ public final class TestTable {
     @Test
     public void testIllegalCOnstruction(){
         try {
-            new Table(0, 5);
+            new HSLFTable(0, 5);
             fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
         } catch (IllegalArgumentException e){
 
         }
         try {
-            new Table(5, 0);
+            new HSLFTable(5, 0);
             fail("Table(rownum, colnum) must throw IllegalArgumentException if any of tghe arguments is less than 1");
         } catch (IllegalArgumentException e){
 
index c0634f05fc57f84c141840b8cf33750f4814df11..800df623e3edc4deed50939e20c7dbbe66146543 100644 (file)
@@ -281,7 +281,7 @@ public final class TestAddingSlides extends TestCase {
         assertEquals(14, doc.getNotesSlideListWithText().getSlideAtomsSets().length);
 
         //remove all slides, corresponding notes should be removed too
-        for (int i = 0; i < slides.size(); i++) {
+        for (int i = slides.size(); i > 0; i--) {
             ppt.removeSlide(0);
         }
         assertEquals(0, ppt.getSlides().size());
index 12e3ff6c304306600b38f342da1e9469186aa706..b7dba80b82cc10aa7049346e517b631b72b549aa 100644 (file)
 package org.apache.poi.hslf.usermodel;
 
 import static org.junit.Assert.*;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.io.*;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -44,14 +40,14 @@ import org.apache.poi.ddf.EscherProperties;
 import org.apache.poi.hslf.HSLFTestDataSamples;
 import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
 import org.apache.poi.hslf.model.*;
-import org.apache.poi.hslf.record.Document;
-import org.apache.poi.hslf.record.Record;
-import org.apache.poi.hslf.record.SlideListWithText;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection.TextPropType;
+import org.apache.poi.hslf.record.*;
 import org.apache.poi.hslf.record.SlideListWithText.SlideAtomsSet;
-import org.apache.poi.hslf.record.TextHeaderAtom;
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.StringUtil;
-import org.apache.poi.util.Units;
+import org.apache.poi.poifs.filesystem.DocumentEntry;
+import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import org.apache.poi.util.*;
+import org.junit.Ignore;
 import org.junit.Test;
 
 /**
@@ -527,7 +523,7 @@ public final class TestBugs {
         for (List<HSLFTextParagraph> tr : _slides.get(0).getTextParagraphs()) {
             if (! tr.get(0).isDrawingBased()) str++;
         }
-        assertEquals(1, str);
+        assertEquals(2, str);
     }
     
     @Test
index 3638bad82e2e1188577ef16475a37b74458472b3..cc78643a8b6dddf238c90c4ac19b3729877e4afa 100644 (file)
 \r
 package org.apache.poi.hslf.usermodel;\r
 \r
-import static org.junit.Assert.assertTrue;\r
+import static org.junit.Assert.*;\r
 import static org.junit.Assume.assumeTrue;\r
 \r
-import java.awt.Color;\r
-import java.awt.Dimension;\r
-import java.awt.Font;\r
-import java.awt.Graphics2D;\r
-import java.awt.GraphicsEnvironment;\r
-import java.awt.RenderingHints;\r
+import java.awt.*;\r
 import java.awt.geom.AffineTransform;\r
 import java.awt.geom.Rectangle2D;\r
 import java.awt.image.BufferedImage;\r
 import java.awt.image.DataBufferByte;\r
 import java.io.File;\r
 import java.io.InputStream;\r
-import java.util.Arrays;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
+import java.util.*;\r
 \r
 import javax.imageio.ImageIO;\r
 \r
 import org.apache.poi.POIDataSamples;\r
-import org.apache.poi.hslf.model.TextPainter;\r
+import org.apache.poi.sl.draw.Drawable;\r
 import org.apache.poi.util.TempFile;\r
 import org.junit.Ignore;\r
 import org.junit.Test;\r
@@ -50,7 +43,7 @@ import org.junit.Test;
 public class TestFontRendering {\r
     private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance();\r
 \r
-    @Ignore("This fails on some systems because fonts are rendered slightly different")\r
+    // @Ignore2("This fails on some systems because fonts are rendered slightly different")\r
     @Test\r
     public void bug55902mixedFontWithChineseCharacters() throws Exception {\r
         // font files need to be downloaded first via\r
@@ -86,7 +79,7 @@ public class TestFontRendering {
         \r
         Dimension pgsize = ss.getPageSize();\r
         \r
-        HSLFSlide slide = ss.getSlides()[0];\r
+        HSLFSlide slide = ss.getSlides().get(0);\r
         \r
         // render it\r
         double zoom = 1;\r
@@ -95,8 +88,8 @@ public class TestFontRendering {
         \r
         BufferedImage imgActual = new BufferedImage((int)Math.ceil(pgsize.width*zoom), (int)Math.ceil(pgsize.height*zoom), BufferedImage.TYPE_3BYTE_BGR);\r
         Graphics2D graphics = imgActual.createGraphics();\r
-        graphics.setRenderingHint(TextPainter.KEY_FONTFALLBACK, fallbackMap);\r
-        graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap);\r
+        graphics.setRenderingHint(Drawable.FONT_FALLBACK, fallbackMap);\r
+        graphics.setRenderingHint(Drawable.FONT_MAP, fontMap);\r
         graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);\r
         graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);\r
         graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);\r
@@ -116,7 +109,7 @@ public class TestFontRendering {
         if(!Arrays.equals(expectedData, actualData)) {\r
             ImageIO.write(imgActual, "PNG", TempFile.createTempFile("TestFontRendering", ".png"));\r
         }\r
-        assertTrue("Expected to have matching raster-arrays, but found differences, size " + expectedData.length + " and " + actualData.length, \r
-                Arrays.equals(expectedData, actualData));\r
+        \r
+        assertArrayEquals("Expected to have matching raster-arrays, but found differences", expectedData, actualData);\r
     }\r
 }\r
index ab358f65a0af31a3a38cee646dfae233267b1b91..5ad2bac1c427aa012b2510fb5c8d834a6047c0f6 100644 (file)
@@ -79,10 +79,14 @@ public final class TestNumberedList3 {
                assertEquals(Short.valueOf((short)1), autoNumbers[0].getAutoNumberStartNumber());//Default value = 1 will be used 
                assertTrue(TextAutoNumberSchemeEnum.ANM_ArabicPeriod == autoNumbersOfTextBox0[0].getAutoNumberScheme());
                
-               final List<TextPropCollection> textProps = textParass.get(1).get(0).getStyleTextPropAtom().getCharacterStyles();
-               assertEquals(1, textProps.size());
-               final TextPropCollection textProp = textProps.get(0);
-               assertEquals(67, textProp.getCharactersCovered());
+               int chCovered = 0;
+               for (HSLFTextParagraph htp : textParass.get(1)) {
+               for (HSLFTextRun htr : htp.getTextRuns()) {
+                   TextPropCollection textProp = htr.getCharacterStyle();
+                   chCovered += textProp.getCharactersCovered();
+               }
+               }
+               assertEquals(67, chCovered);
                
                assertTrue(textParass.get(0).get(0).isBullet());
                
index 2410d6ca652d217d0b18a1783cdd70ba4bd30bab..8e5652fb81158aafac79a4d34a2d885b916cd273 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-
-import java.awt.Dimension;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
+import static org.junit.Assert.*;
+
+import java.awt.*;
 import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.InputStream;
+import java.io.*;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -36,8 +29,12 @@ import javax.imageio.ImageIO;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.hslf.usermodel.*;
+import org.apache.poi.hssf.usermodel.DummyGraphics2d;
+import org.apache.poi.sl.draw.Drawable;
+import org.apache.poi.sl.usermodel.Slide;
+import org.apache.poi.sl.usermodel.SlideShow;
 import org.apache.poi.util.JvmBugs;
+import org.apache.poi.xslf.usermodel.XMLSlideShow;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -143,45 +140,42 @@ public final class TestPicture {
     }
 
     @Test
-    @Ignore("Just for visual validation - antialiasing is different on various systems")
+    // @Ignore("Just for visual validation - antialiasing is different on various systems")
     public void bug54541() throws Exception {
-//        InputStream xis = _slTests.openResourceAsStream("54542_cropped_bitmap.pptx");
-//        XMLSlideShow xss = new XMLSlideShow(xis);
-//        xis.close();
-//        
-//        Dimension xpg = xss.getPageSize();
-//        for(XSLFSlide slide : xss.getSlides()) {
-//            BufferedImage img = new BufferedImage(xpg.width, xpg.height, BufferedImage.TYPE_INT_RGB);
-//            Graphics2D graphics = img.createGraphics();
-//            fixFonts(graphics);
-//            slide.draw(graphics);
-//            ImageIO.write(img, "PNG", new File("testx.png"));
-//        }
-//
-//        System.out.println("########################");
-        
-        InputStream is = _slTests.openResourceAsStream("54541_cropped_bitmap.ppt");
-        HSLFSlideShow ss = new HSLFSlideShow(is);
+        String file = new String[]{
+            "54542_cropped_bitmap.pptx",
+            "54541_cropped_bitmap.ppt",
+            "54541_cropped_bitmap2.ppt",
+            "sample_pptx_grouping_issues.pptx"
+        }[3];
+        InputStream is = _slTests.openResourceAsStream(file);
+        SlideShow ss = file.endsWith("pptx") ? new XMLSlideShow(is) : new HSLFSlideShow(is);
         is.close();
         
+        boolean debugOut = false;
         Dimension pg = ss.getPageSize();
         int i=1;
-        for(HSLFSlide slide : ss.getSlides()) {
-            BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB);
-            Graphics2D graphics = img.createGraphics();
-            fixFonts(graphics);
-            slide.draw(graphics);
-            ImageIO.write(img, "PNG", new File("test"+(i++)+".png"));
+        for(Slide<?,?,?> slide : ss.getSlides()) {
+            if (debugOut) {
+                DummyGraphics2d graphics = new DummyGraphics2d();
+                slide.draw(graphics);
+            } else {
+                BufferedImage img = new BufferedImage(pg.width, pg.height, BufferedImage.TYPE_INT_RGB);
+                Graphics2D graphics = img.createGraphics();
+                fixFonts(graphics);
+                slide.draw(graphics);
+                ImageIO.write(img, "PNG", new File("test"+(i++)+"hslf.png"));
+            }
         }
     }
     
     @SuppressWarnings("unchecked")
     private void fixFonts(Graphics2D graphics) {
         if (!JvmBugs.hasLineBreakMeasurerBug()) return;
-        Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(TextPainter.KEY_FONTMAP);
+        Map<String,String> fontMap = (Map<String,String>)graphics.getRenderingHint(Drawable.FONT_MAP);
         if (fontMap == null) fontMap = new HashMap<String,String>();
         fontMap.put("Calibri", "Lucida Sans");
         fontMap.put("Cambria", "Lucida Bright");
-        graphics.setRenderingHint(TextPainter.KEY_FONTMAP, fontMap);        
+        graphics.setRenderingHint(Drawable.FONT_MAP, fontMap);        
     }
 }
index 25f61e1b10a8652937a5da754a24d3b0d73f36b4..61c309106d8b84698b7aba959a849064a3e10194 100644 (file)
@@ -22,17 +22,12 @@ import static org.junit.Assert.assertArrayEquals;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.net.URL;
+import java.util.List;
 
 import junit.framework.TestCase;
 
 import org.apache.poi.POIDataSamples;
-import org.apache.poi.hslf.blip.DIB;
-import org.apache.poi.hslf.blip.EMF;
-import org.apache.poi.hslf.blip.JPEG;
-import org.apache.poi.hslf.blip.PICT;
-import org.apache.poi.hslf.blip.PNG;
-import org.apache.poi.hslf.blip.WMF;
-import org.apache.poi.hslf.model.*;
+import org.apache.poi.hslf.blip.*;
 
 /**
  * Test adding/reading pictures
@@ -65,9 +60,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can read this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -110,9 +105,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can read this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -156,9 +151,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can get this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -195,9 +190,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can read this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -235,9 +230,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can read this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -274,9 +269,9 @@ public final class TestPictures extends TestCase{
         ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));
 
         //make sure we can read this picture shape and it refers to the correct picture data
-        HSLFShape[] sh = ppt.getSlides()[0].getShapes();
-        assertEquals(1, sh.length);
-        pict = (HSLFPictureShape)sh[0];
+        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
+        assertEquals(1, sh.size());
+        pict = (HSLFPictureShape)sh.get(0);
         assertEquals(idx, pict.getPictureIndex());
 
         //check picture data
@@ -302,11 +297,11 @@ public final class TestPictures extends TestCase{
         HSLFPictureData pdata;
 
         HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt"));
-        HSLFSlide[] slides = ppt.getSlides();
+        List<HSLFSlide> slides = ppt.getSlides();
         HSLFPictureData[] pictures = ppt.getPictureData();
         assertEquals(5, pictures.length);
 
-        pict = (HSLFPictureShape)slides[0].getShapes()[0]; //the first slide contains JPEG
+        pict = (HSLFPictureShape)slides.get(0).getShapes().get(0); //the first slide contains JPEG
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof JPEG);
         assertEquals(HSLFPictureShape.JPEG, pdata.getType());
@@ -314,7 +309,7 @@ public final class TestPictures extends TestCase{
         ppt_bytes = slTests.readFile("clock.jpg");
         assertArrayEquals(src_bytes, ppt_bytes);
 
-        pict = (HSLFPictureShape)slides[1].getShapes()[0]; //the second slide contains PNG
+        pict = (HSLFPictureShape)slides.get(1).getShapes().get(0); //the second slide contains PNG
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof PNG);
         assertEquals(HSLFPictureShape.PNG, pdata.getType());
@@ -322,7 +317,7 @@ public final class TestPictures extends TestCase{
         ppt_bytes = slTests.readFile("tomcat.png");
         assertArrayEquals(src_bytes, ppt_bytes);
 
-        pict = (HSLFPictureShape)slides[2].getShapes()[0]; //the third slide contains WMF
+        pict = (HSLFPictureShape)slides.get(2).getShapes().get(0); //the third slide contains WMF
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(HSLFPictureShape.WMF, pdata.getType());
@@ -336,7 +331,7 @@ public final class TestPictures extends TestCase{
         System.arraycopy(ppt_bytes, 22, b2, 0, b2.length);
         assertArrayEquals(b1, b2);
 
-        pict = (HSLFPictureShape)slides[3].getShapes()[0]; //the forth slide contains PICT
+        pict = (HSLFPictureShape)slides.get(3).getShapes().get(0); //the forth slide contains PICT
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof PICT);
         assertEquals(HSLFPictureShape.PICT, pdata.getType());
@@ -350,7 +345,7 @@ public final class TestPictures extends TestCase{
         System.arraycopy(ppt_bytes, 512, b2, 0, b2.length);
         assertArrayEquals(b1, b2);
 
-        pict = (HSLFPictureShape)slides[4].getShapes()[0]; //the fifth slide contains EMF
+        pict = (HSLFPictureShape)slides.get(4).getShapes().get(0); //the fifth slide contains EMF
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof EMF);
         assertEquals(HSLFPictureShape.EMF, pdata.getType());
@@ -375,20 +370,20 @@ public final class TestPictures extends TestCase{
 
                // Now test what happens when we use the SlideShow interface
                HSLFSlideShow ppt = new HSLFSlideShow(hslf);
-        HSLFSlide[] slides = ppt.getSlides();
+        List<HSLFSlide> slides = ppt.getSlides();
         HSLFPictureData[] pictures = ppt.getPictureData();
-        assertEquals(12, slides.length);
+        assertEquals(12, slides.size());
         assertEquals(2, pictures.length);
 
                HSLFPictureShape pict;
                HSLFPictureData pdata;
 
-        pict = (HSLFPictureShape)slides[0].getShapes()[1]; // 2nd object on 1st slide
+        pict = (HSLFPictureShape)slides.get(0).getShapes().get(1); // 2nd object on 1st slide
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(HSLFPictureShape.WMF, pdata.getType());
 
-        pict = (HSLFPictureShape)slides[0].getShapes()[2]; // 3rd object on 1st slide
+        pict = (HSLFPictureShape)slides.get(0).getShapes().get(2); // 3rd object on 1st slide
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(HSLFPictureShape.WMF, pdata.getType());
@@ -411,20 +406,20 @@ public final class TestPictures extends TestCase{
 
                // Now test what happens when we use the SlideShow interface
                HSLFSlideShow ppt = new HSLFSlideShow(hslf);
-        HSLFSlide[] slides = ppt.getSlides();
+        List<HSLFSlide> slides = ppt.getSlides();
         HSLFPictureData[] pictures = ppt.getPictureData();
-        assertEquals(27, slides.length);
+        assertEquals(27, slides.size());
         assertEquals(2, pictures.length);
 
                HSLFPictureShape pict;
                HSLFPictureData pdata;
 
-        pict = (HSLFPictureShape)slides[6].getShapes()[13];
+        pict = (HSLFPictureShape)slides.get(6).getShapes().get(13);
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(HSLFPictureShape.WMF, pdata.getType());
 
-        pict = (HSLFPictureShape)slides[7].getShapes()[13];
+        pict = (HSLFPictureShape)slides.get(7).getShapes().get(13);
         pdata = pict.getPictureData();
         assertTrue(pdata instanceof WMF);
         assertEquals(HSLFPictureShape.WMF, pdata.getType());
@@ -446,9 +441,9 @@ public final class TestPictures extends TestCase{
 
     public void testGetPictureName() throws Exception {
         HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
-        HSLFSlide slide = ppt.getSlides()[0];
+        HSLFSlide slide = ppt.getSlides().get(0);
 
-        HSLFPictureShape p = (HSLFPictureShape)slide.getShapes()[0]; //the first slide contains JPEG
+        HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG
         assertEquals("test", p.getPictureName());
     }
 
@@ -469,7 +464,7 @@ public final class TestPictures extends TestCase{
 
         ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
 
-        HSLFPictureShape p = (HSLFPictureShape)ppt.getSlides()[0].getShapes()[0];
+        HSLFPictureShape p = (HSLFPictureShape)ppt.getSlides().get(0).getShapes().get(0);
         assertEquals("tomcat.png", p.getPictureName());
     }
 }
index 4a456dc7710d3ed6fe46f52985744eb22d334a6a..2270cd420f590c76b74d51bb0fc7103c88fe04db 100644 (file)
 
 package org.apache.poi.hslf.usermodel;
 
-import junit.framework.TestCase;
+import static org.junit.Assert.*;
+
+import java.util.List;
 
-import org.apache.poi.hslf.model.Table;
 import org.apache.poi.POIDataSamples;
+import org.junit.Test;
 
 
 /**
@@ -30,40 +32,39 @@ import org.apache.poi.POIDataSamples;
  * 
  * @author Alex Nikiforov [mailto:anikif@gmail.com]
  */
-public final class TestTable extends TestCase {
+public class TestTable {
     private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
 
-       protected void setUp() throws Exception {
-       }
-
-       public void testTable() throws Exception {
+    @Test
+    public void testTable() throws Exception {
                HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("54111.ppt"));
                assertTrue("No Exceptions while reading file", true);
 
-               final HSLFSlide[] slides = ppt.getSlides();
-               assertEquals(1, slides.length);
-               checkSlide(slides[0]);
+               List<HSLFSlide> slides = ppt.getSlides();
+               assertEquals(1, slides.size());
+               checkSlide(slides.get(0));
        }
+       
        private void checkSlide(final HSLFSlide s) {
-               HSLFTextParagraph[] textRuns = s.getTextParagraphs();
-               assertEquals(2, textRuns.length);
+               List<List<HSLFTextParagraph>> textRuns = s.getTextParagraphs();
+               assertEquals(2, textRuns.size());
 
-               HSLFTextRun textRun = textRuns[0].getTextRuns()[0];
+               HSLFTextRun textRun = textRuns.get(0).get(0).getTextRuns().get(0);
                assertEquals("Table sample", textRun.getRawText().trim());
-               assertEquals(1, textRuns[0].getTextRuns().length);
-               assertFalse(textRun.isBullet());
+               assertEquals(1, textRuns.get(0).get(0).getTextRuns().size());
+               assertFalse(textRun.getTextParagraph().isBullet());
 
-               assertEquals("Dummy text", textRuns[1].getRawText());
+               assertEquals("Dummy text", HSLFTextParagraph.getRawText(textRuns.get(1)));
                
-               final HSLFShape[] shapes = s.getShapes();
+               List<HSLFShape> shapes = s.getShapes();
                assertNotNull(shapes);
-               assertEquals(3, shapes.length);
-               assertTrue(shapes[2] instanceof Table);
-               final Table table = (Table) shapes[2];
+               assertEquals(3, shapes.size());
+               assertTrue(shapes.get(2) instanceof HSLFTable);
+               final HSLFTable table = (HSLFTable) shapes.get(2);
                assertEquals(4, table.getNumberOfColumns());
                assertEquals(6, table.getNumberOfRows());
                for (int x = 0; x < 4; x ++) {
-                       assertEquals("TH Cell " + (x + 1), table.getCell(0, x).getTextParagraphs().getRawText());
+                       assertEquals("TH Cell " + (x + 1), HSLFTextParagraph.getRawText(table.getCell(0, x).getTextParagraphs()));
                        for (int y = 1; y < 6; y++) {
                                assertEquals("Row " + y + ", Cell " + (x + 1), table.getCell(y, x).getText());
                        }
index 3b1313e4eaa158f109209d97c38af560a675e706..9dda9af244cbabdc4f9c87b334b2a212bd879dd7 100644 (file)
@@ -19,10 +19,12 @@ package org.apache.poi.hslf.usermodel;
 
 import static org.junit.Assert.*;
 
-import java.io.IOException;
+import java.awt.Color;
+import java.io.*;
 import java.util.List;
 
 import org.apache.poi.POIDataSamples;
+import org.apache.poi.hslf.model.textproperties.TextPropCollection;
 import org.apache.poi.hslf.record.*;
 import org.junit.Before;
 import org.junit.Test;
@@ -99,7 +101,7 @@ public final class TestTextRun {
 
                // Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r'
                tr.setText(changeTo + "\n");
-               assertEquals(changeTo + "\n", tr.getRawText());
+               assertEquals(changeTo + "\r", tr.getRawText());
        }
 
        /**
@@ -121,7 +123,6 @@ public final class TestTextRun {
                    else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
                    else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
                }
-               
 
                // Bytes -> Bytes
                assertNull(tca);
@@ -197,18 +198,13 @@ public final class TestTextRun {
                List<HSLFTextParagraph> trB = textParass.get(1);
 
                assertEquals(1, trA.size());
-               assertEquals(1, trB.size());
+               assertEquals(2, trB.size());
 
                HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0);
                HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
 
                assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText());
-               assertEquals(HSLFTextParagraph.getRawText(trB), rtrB.getRawText());
-
-//             assertNull(rtrA._getRawCharacterStyle());
-//             assertNull(rtrA._getRawParagraphStyle());
-//             assertNull(rtrB._getRawCharacterStyle());
-//             assertNull(rtrB._getRawParagraphStyle());
+               assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
        }
 
        /**
@@ -284,39 +280,39 @@ public final class TestTextRun {
                HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
                HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
                HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
-//             TextPropCollection tpBP = rtrB._getRawParagraphStyle();
-//             TextPropCollection tpBC = rtrB._getRawCharacterStyle();
-//             TextPropCollection tpCP = rtrC._getRawParagraphStyle();
-//             TextPropCollection tpCC = rtrC._getRawCharacterStyle();
-//             TextPropCollection tpDP = rtrD._getRawParagraphStyle();
-//             TextPropCollection tpDC = rtrD._getRawCharacterStyle();
+               TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpBC = rtrB.getCharacterStyle();
+               TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpCC = rtrC.getCharacterStyle();
+               TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpDC = rtrD.getCharacterStyle();
 
 //             assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
-//             assertNotNull(tpBP);
-//             assertNotNull(tpBC);
-//             assertNotNull(tpCP);
-//             assertNotNull(tpCC);
-//             assertNotNull(tpDP);
-//             assertNotNull(tpDC);
-//             assertTrue(tpBP.equals(tpCP));
-//             assertTrue(tpBP.equals(tpDP));
-//             assertTrue(tpCP.equals(tpDP));
-//             assertFalse(tpBC.equals(tpCC));
-//             assertFalse(tpBC.equals(tpDC));
-//             assertFalse(tpCC.equals(tpDC));
+               assertNotNull(tpBP);
+               assertNotNull(tpBC);
+               assertNotNull(tpCP);
+               assertNotNull(tpCC);
+               assertNotNull(tpDP);
+               assertNotNull(tpDC);
+               assertEquals(tpBP,tpCP);
+               assertEquals(tpBP,tpDP);
+               assertEquals(tpCP,tpDP);
+               assertNotEquals(tpBC,tpCC);
+               assertNotEquals(tpBC,tpDC);
+               assertNotEquals(tpCC,tpDC);
 
                // Change text via normal
-//             trB.setText("Test Foo Test");
+               HSLFTextParagraph.setText(trB, "Test Foo Test");
 
                // Ensure now have first style
-//             assertEquals(1, trB.getTextRuns().length);
-//             rtrB = trB.getTextRuns().get(0);
-//             assertEquals("Test Foo Test", trB.getRawText());
-//             assertEquals("Test Foo Test", rtrB.getRawText());
-//             assertNotNull(rtrB._getRawCharacterStyle());
-//             assertNotNull(rtrB._getRawParagraphStyle());
-//             assertEquals( tpBP, rtrB._getRawParagraphStyle() );
-//             assertEquals( tpBC, rtrB._getRawCharacterStyle() );
+               assertEquals(1, trB.get(0).getTextRuns().size());
+               rtrB = trB.get(0).getTextRuns().get(0);
+               assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB));
+               assertEquals("Test Foo Test", rtrB.getRawText());
+               assertNotNull(rtrB.getCharacterStyle());
+               assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
+               assertEquals( tpBP, rtrB.getTextParagraph().getParagraphStyle() );
+               assertEquals( tpBC, rtrB.getCharacterStyle() );
        }
 
        /**
@@ -328,21 +324,21 @@ public final class TestTextRun {
                HSLFSlide slideOne = ss.getSlides().get(0);
                List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs();
                List<HSLFTextParagraph> trB = textRuns.get(1);
-//             assertEquals(1, trB.getTextRuns().length);
-//
-//             HSLFTextRun rtrB = trB.getTextRuns().get(0);
-//             assertEquals(trB.getRawText(), rtrB.getRawText());
-//             assertNull(rtrB._getRawCharacterStyle());
-//             assertNull(rtrB._getRawParagraphStyle());
+               assertEquals(1, trB.get(0).getTextRuns().size());
+
+               HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
+               assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
+               assertNotNull(rtrB.getCharacterStyle());
+               assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
 
                // Change text via rich
-//             rtrB.setText("Test Test Test");
-//             assertEquals("Test Test Test", trB.getRawText());
-//             assertEquals("Test Test Test", rtrB.getRawText());
+               rtrB.setText("Test Test Test");
+               assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1)));
+               assertEquals("Test Test Test", rtrB.getRawText());
 
                // Will now have dummy props
-//             assertNotNull(rtrB._getRawCharacterStyle());
-//             assertNotNull(rtrB._getRawParagraphStyle());
+        assertNotNull(rtrB.getCharacterStyle());
+        assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
        }
 
        /**
@@ -357,31 +353,31 @@ public final class TestTextRun {
                assertEquals(3, trB.size());
 
                // We start with 3 text runs, each with their own set of styles,
-               //  but all sharing the same paragraph styles
+               // but all sharing the same paragraph styles
                HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
                HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
                HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
-//             TextPropCollection tpBP = rtrB._getRawParagraphStyle();
-//             TextPropCollection tpBC = rtrB._getRawCharacterStyle();
-//             TextPropCollection tpCP = rtrC._getRawParagraphStyle();
-//             TextPropCollection tpCC = rtrC._getRawCharacterStyle();
-//             TextPropCollection tpDP = rtrD._getRawParagraphStyle();
-//             TextPropCollection tpDC = rtrD._getRawCharacterStyle();
+               TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpBC = rtrB.getCharacterStyle();
+               TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpCC = rtrC.getCharacterStyle();
+               TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
+               TextPropCollection tpDC = rtrD.getCharacterStyle();
 
                // Check text and stylings
-//             assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
-//             assertNotNull(tpBP);
-//             assertNotNull(tpBC);
-//             assertNotNull(tpCP);
-//             assertNotNull(tpCC);
-//             assertNotNull(tpDP);
-//             assertNotNull(tpDC);
-//             assertTrue(tpBP.equals(tpCP));
-//             assertTrue(tpBP.equals(tpDP));
-//             assertTrue(tpCP.equals(tpDP));
-//             assertFalse(tpBC.equals(tpCC));
-//             assertFalse(tpBC.equals(tpDC));
-//             assertFalse(tpCC.equals(tpDC));
+               assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText());
+               assertNotNull(tpBP);
+               assertNotNull(tpBC);
+               assertNotNull(tpCP);
+               assertNotNull(tpCC);
+               assertNotNull(tpDP);
+               assertNotNull(tpDC);
+               assertEquals(tpBP, tpCP);
+               assertEquals(tpBP, tpDP);
+               assertEquals(tpCP, tpDP);
+               assertNotEquals(tpBC, tpCC);
+               assertNotEquals(tpBC, tpDC);
+               assertNotEquals(tpCC, tpDC);
 
                // Check text in the rich runs
                assertEquals("This is the subtitle, in bold\r", rtrB.getRawText());
@@ -394,32 +390,32 @@ public final class TestTextRun {
                rtrB.setText(newBText);
                rtrC.setText(newCText);
                rtrD.setText(newDText);
-               assertEquals(newBText, rtrB.getRawText());
-               assertEquals(newCText, rtrC.getRawText());
-               assertEquals(newDText, rtrD.getRawText());
+               HSLFTextParagraph.storeText(trB);
 
-//             assertEquals(newBText + newCText + newDText, trB.getRawText());
+               assertEquals(newBText.replace('\n','\r'), rtrB.getRawText());
+               assertEquals(newCText.replace('\n','\r'), rtrC.getRawText());
+               assertEquals(newDText.replace('\n','\r'), rtrD.getRawText());
 
-               // The styles should have been updated for the new sizes
-//             assertEquals(newBText.length(), tpBC.getCharactersCovered());
-//             assertEquals(newCText.length(), tpCC.getCharactersCovered());
-//             assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger
+               assertEquals(newBText.replace('\n','\r') + newCText.replace('\n','\r') + newDText.replace('\n','\r'), HSLFTextParagraph.getRawText(trB));
 
-//             assertEquals(
-//                             newBText.length() + newCText.length() + newDText.length(),
-//                             tpBP.getCharactersCovered()
-//             );
+               // The styles should have been updated for the new sizes
+               assertEquals(newBText.length(), tpBC.getCharactersCovered());
+               assertEquals(newCText.length(), tpCC.getCharactersCovered());
+               assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger
 
-               // Paragraph style should be sum of text length
-//             assertEquals(newBText.length() + newCText.length() + newDText.length(), tpBP.getCharactersCovered());
+        // Paragraph style should be sum of text length
+               assertEquals(
+                       newBText.length() + newCText.length() + newDText.length() +1,
+                       tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered()
+               );
 
                // Check stylings still as expected
-//             TextPropCollection ntpBC = rtrB._getRawCharacterStyle();
-//             TextPropCollection ntpCC = rtrC._getRawCharacterStyle();
-//             TextPropCollection ntpDC = rtrD._getRawCharacterStyle();
-//             assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
-//             assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
-//             assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
+               TextPropCollection ntpBC = rtrB.getCharacterStyle();
+               TextPropCollection ntpCC = rtrC.getCharacterStyle();
+               TextPropCollection ntpDC = rtrD.getCharacterStyle();
+               assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
+               assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
+               assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
        }
 
 
@@ -467,82 +463,86 @@ public final class TestTextRun {
                assertEquals(0, slide.getTextParagraphs().size());
 
                HSLFTextBox shape1 = new HSLFTextBox();
-//             HSLFTextParagraph run1 = shape1.getTextParagraphs();
-//             assertSame(run1, shape1.createTextRun());
-//             run1.setText("Text 1");
+               List<HSLFTextParagraph> run1 = shape1.getTextParagraphs();
+               shape1.setText("Text 1");
                slide.addShape(shape1);
 
                //The array of Slide's text runs must be updated when new text shapes are added.
-//             HSLFTextParagraph[] runs = slide.getTextParagraphs();
-//             assertNotNull(runs);
-//             assertSame(run1, runs.get(0));
-//
-//             HSLFTextBox shape2 = new HSLFTextBox();
-//             HSLFTextParagraph run2 = shape2.getTextParagraphs();
-//             assertSame(run2, shape2.createTextRun());
-//             run2.setText("Text 2");
-//             slide.addShape(shape2);
-//
-//             runs = slide.getTextParagraphs();
-//             assertEquals(2, runs.length);
-//
-//             assertSame(run1, runs.get(0));
-//             assertSame(run2, runs.get(1));
-//
-//             //as getShapes()
-//             HSLFShape[] sh = slide.getShapes();
-//             assertEquals(2, sh.length);
-//             assertTrue(sh.get(0) instanceof HSLFTextBox);
-//             HSLFTextBox box1 = (HSLFTextBox)sh.get(0);
-//             assertSame(run1, box1.getTextParagraphs());
-//             HSLFTextBox box2 = (HSLFTextBox)sh.get(1);
-//             assertSame(run2, box2.getTextParagraphs());
-//
-//             //test Table - a complex group of shapes containing text objects
-//             HSLFSlide slide2 = ppt.createSlide();
-//             assertNull(slide2.getTextParagraphs());
-//             Table table = new Table(2, 2);
-//             slide2.addShape(table);
-//             runs = slide2.getTextParagraphs();
-//             assertNotNull(runs);
-//             assertEquals(4, runs.length);
+               List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs();
+               assertNotNull(runs);
+               assertSame(run1, runs.get(0));
+
+               HSLFTextBox shape2 = new HSLFTextBox();
+               List<HSLFTextParagraph> run2 = shape2.getTextParagraphs();
+               shape2.setText("Text 2");
+               slide.addShape(shape2);
+
+               runs = slide.getTextParagraphs();
+               assertEquals(2, runs.size());
+
+               assertSame(run1, runs.get(0));
+               assertSame(run2, runs.get(1));
+
+               // as getShapes()
+               List<HSLFShape> sh = slide.getShapes();
+               assertEquals(2, sh.size());
+               assertTrue(sh.get(0) instanceof HSLFTextBox);
+               HSLFTextBox box1 = (HSLFTextBox)sh.get(0);
+               assertSame(run1, box1.getTextParagraphs());
+               HSLFTextBox box2 = (HSLFTextBox)sh.get(1);
+               assertSame(run2, box2.getTextParagraphs());
+
+               // test Table - a complex group of shapes containing text objects
+               HSLFSlide slide2 = ppt.createSlide();
+               assertTrue(slide2.getTextParagraphs().isEmpty());
+               HSLFTable table = new HSLFTable(2, 2);
+               slide2.addShape(table);
+               runs = slide2.getTextParagraphs();
+               assertNotNull(runs);
+               assertEquals(4, runs.size());
        }
 
        @Test
        public void test48916() throws IOException {
-//        HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt"));
-//        for(HSLFSlide slide : ppt.getSlides()){
-//            for(HSLFShape sh : slide.getShapes()){
-//                if(sh instanceof HSLFTextShape){
-//                    HSLFTextShape tx = (HSLFTextShape)sh;
-//                    HSLFTextParagraph run = tx.getTextParagraphs();
-//                    //verify that records cached in  TextRun and EscherTextboxWrapper are the same
-//                    Record[] runChildren = run.getRecords();
-//                    Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords();
-//                    assertEquals(runChildren.length, txboxChildren.length);
-//                    for(int i=0; i < txboxChildren.length; i++){
-//                        assertSame(txboxChildren.get(i), runChildren.get(i));
-//                    }
-//                    //caused NPE prior to fix of Bugzilla #48916 
-//                    run.getTextRuns().get(0).setBold(true);
-//                    run.getTextRuns().get(0).setFontColor(Color.RED);
-//                }
-//            }
-//        }
-//        ByteArrayOutputStream out = new ByteArrayOutputStream();
-//        ppt.write(out);
-//        ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
-//        for(HSLFSlide slide : ppt.getSlides()){
-//            for(HSLFShape sh : slide.getShapes()){
-//                if(sh instanceof HSLFTextShape){
-//                    HSLFTextShape tx = (HSLFTextShape)sh;
-//                    HSLFTextParagraph run = tx.getTextParagraphs();
-//                    HSLFTextRun rt = run.getTextRuns().get(0);
-//                    assertTrue(rt.isBold());
-//                    assertEquals(rt.getFontColor(), Color.RED);
-//                }
-//            }
-//        }
+        HSLFSlideShow ppt = new HSLFSlideShow(_slTests.openResourceAsStream("SampleShow.ppt"));
+        List<HSLFSlide> slides = ppt.getSlides();
+        for(HSLFSlide slide : slides){
+            for(HSLFShape sh : slide.getShapes()){
+                if (!(sh instanceof HSLFTextShape)) continue;
+                HSLFTextShape tx = (HSLFTextShape)sh;
+                List<HSLFTextParagraph> paras = tx.getTextParagraphs();
+                //verify that records cached in  TextRun and EscherTextboxWrapper are the same
+                Record[] runChildren = paras.get(0).getRecords();
+                Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords();
+                assertEquals(runChildren.length, txboxChildren.length);
+                for(int i=0; i < txboxChildren.length; i++){
+                    assertSame(txboxChildren[i], runChildren[i]);
+                }
+                // caused NPE prior to fix of Bugzilla #48916
+                for (HSLFTextParagraph p : paras) {
+                    for (HSLFTextRun rt : p.getTextRuns()) {
+                        rt.setBold(true);
+                        rt.setFontColor(Color.RED);
+                    }
+                }
+                tx.storeText();
+            }
+        }
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ppt.write(out);
+        
+        ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));
+        for(HSLFSlide slide : ppt.getSlides()){
+            for(HSLFShape sh : slide.getShapes()){
+                if(sh instanceof HSLFTextShape){
+                    HSLFTextShape tx = (HSLFTextShape)sh;
+                    List<HSLFTextParagraph> run = tx.getTextParagraphs();
+                    HSLFTextRun rt = run.get(0).getTextRuns().get(0);
+                    assertTrue(rt.isBold());
+                    assertEquals(rt.getFontColor(), Color.RED);
+                }
+            }
+        }
 
     }
 
diff --git a/test-data/slideshow/54541_cropped_bitmap2.ppt b/test-data/slideshow/54541_cropped_bitmap2.ppt
new file mode 100644 (file)
index 0000000..3d79dbd
Binary files /dev/null and b/test-data/slideshow/54541_cropped_bitmap2.ppt differ
diff --git a/test-data/slideshow/sample_pptx_grouping_issues.pptx b/test-data/slideshow/sample_pptx_grouping_issues.pptx
new file mode 100644 (file)
index 0000000..bf0c702
Binary files /dev/null and b/test-data/slideshow/sample_pptx_grouping_issues.pptx differ