]> source.dussan.org Git - poi.git/commitdiff
more progress with PPTX2PNG
authorYegor Kozlov <yegor@apache.org>
Mon, 24 Oct 2011 11:07:59 +0000 (11:07 +0000)
committerYegor Kozlov <yegor@apache.org>
Mon, 24 Oct 2011 11:07:59 +0000 (11:07 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1188091 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java

index 6eb49b4b9c80c0b2877fcf528fbb111630733b3d..bdaa58620456c9464a307c6f2ec3a59f65039b2e 100644 (file)
@@ -33,19 +33,17 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
 import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual;\r
 \r
 import java.awt.*;\r
-import java.awt.geom.GeneralPath;\r
-import java.awt.geom.Rectangle2D;\r
+import java.awt.geom.*;\r
 \r
 /**\r
- *\r
- * Specifies a connection shape. \r
+ * Specifies a connection shape.\r
  *\r
  * @author Yegor Kozlov\r
  */\r
 @Beta\r
 public class XSLFConnectorShape extends XSLFSimpleShape {\r
 \r
-    /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet){\r
+    /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet) {\r
         super(shape, sheet);\r
     }\r
 \r
@@ -71,19 +69,19 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
     /**\r
      * Specifies the line end decoration, such as a triangle or arrowhead.\r
      */\r
-    public void setLineHeadDecoration(LineDecoration style){\r
+    public void setLineHeadDecoration(LineDecoration style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
-        if(style == null){\r
-            if(lnEnd.isSetType()) lnEnd.unsetType();\r
+        if (style == null) {\r
+            if (lnEnd.isSetType()) lnEnd.unsetType();\r
         } else {\r
             lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineDecoration getLineHeadDecoration(){\r
+    public LineDecoration getLineHeadDecoration() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetHeadEnd()) return LineDecoration.NONE;\r
+        if (ln == null || !ln.isSetHeadEnd()) return LineDecoration.NONE;\r
 \r
         STLineEndType.Enum end = ln.getHeadEnd().getType();\r
         return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];\r
@@ -92,62 +90,62 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
     /**\r
      * specifies decorations which can be added to the head of a line.\r
      */\r
-    public void setLineHeadWidth(LineEndWidth style){\r
+    public void setLineHeadWidth(LineEndWidth style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
-        if(style == null){\r
-            if(lnEnd.isSetW()) lnEnd.unsetW();\r
+        if (style == null) {\r
+            if (lnEnd.isSetW()) lnEnd.unsetW();\r
         } else {\r
             lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineEndWidth getLineHeadWidth(){\r
+    public LineEndWidth getLineHeadWidth() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetHeadEnd()) return null;\r
+        if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM;\r
 \r
         STLineEndWidth.Enum w = ln.getHeadEnd().getW();\r
-        return w == null ? null : LineEndWidth.values()[w.intValue() - 1];\r
+        return w == null ? LineEndWidth.MEDIUM : LineEndWidth.values()[w.intValue() - 1];\r
     }\r
 \r
     /**\r
      * Specifies the line end width in relation to the line width.\r
      */\r
-    public void setLineHeadLength(LineEndLength style){\r
+    public void setLineHeadLength(LineEndLength style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
 \r
-        if(style == null){\r
-            if(lnEnd.isSetLen()) lnEnd.unsetLen();\r
+        if (style == null) {\r
+            if (lnEnd.isSetLen()) lnEnd.unsetLen();\r
         } else {\r
             lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineEndLength getLineHeadLength(){\r
+    public LineEndLength getLineHeadLength() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetHeadEnd()) return null;\r
+        if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM;\r
 \r
         STLineEndLength.Enum len = ln.getHeadEnd().getLen();\r
-        return len == null ? null : LineEndLength.values()[len.intValue() - 1];\r
+        return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];\r
     }\r
 \r
     /**\r
      * Specifies the line end decoration, such as a triangle or arrowhead.\r
      */\r
-    public void setLineTailDecoration(LineDecoration style){\r
+    public void setLineTailDecoration(LineDecoration style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
-        if(style == null){\r
-            if(lnEnd.isSetType()) lnEnd.unsetType();\r
+        if (style == null) {\r
+            if (lnEnd.isSetType()) lnEnd.unsetType();\r
         } else {\r
             lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineDecoration getLineTailDecoration(){\r
+    public LineDecoration getLineTailDecoration() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetTailEnd()) return LineDecoration.NONE;\r
+        if (ln == null || !ln.isSetTailEnd()) return LineDecoration.NONE;\r
 \r
         STLineEndType.Enum end = ln.getTailEnd().getType();\r
         return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];\r
@@ -156,76 +154,193 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
     /**\r
      * specifies decorations which can be added to the tail of a line.\r
      */\r
-    public void setLineTailWidth(LineEndWidth style){\r
+    public void setLineTailWidth(LineEndWidth style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
-        if(style == null){\r
-            if(lnEnd.isSetW()) lnEnd.unsetW();\r
+        if (style == null) {\r
+            if (lnEnd.isSetW()) lnEnd.unsetW();\r
         } else {\r
             lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineEndWidth getLineTailWidth(){\r
+    public LineEndWidth getLineTailWidth() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetTailEnd()) return null;\r
+        if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM;\r
 \r
         STLineEndWidth.Enum w = ln.getTailEnd().getW();\r
-        return w == null ? null : LineEndWidth.values()[w.intValue() - 1];\r
+        return w == null ? LineEndWidth.MEDIUM : LineEndWidth.values()[w.intValue() - 1];\r
     }\r
 \r
     /**\r
      * Specifies the line end width in relation to the line width.\r
      */\r
-    public void setLineTailLength(LineEndLength style){\r
+    public void setLineTailLength(LineEndLength style) {\r
         CTLineProperties ln = getSpPr().getLn();\r
         CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
 \r
-        if(style == null){\r
-            if(lnEnd.isSetLen()) lnEnd.unsetLen();\r
+        if (style == null) {\r
+            if (lnEnd.isSetLen()) lnEnd.unsetLen();\r
         } else {\r
             lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
         }\r
     }\r
 \r
-    public LineEndLength getLineTailLength(){\r
+    public LineEndLength getLineTailLength() {\r
         CTLineProperties ln = getSpPr().getLn();\r
-        if(!ln.isSetTailEnd()) return null;\r
+        if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM;\r
 \r
         STLineEndLength.Enum len = ln.getTailEnd().getLen();\r
-        return len == null ? null : LineEndLength.values()[len.intValue() - 1];\r
+        return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];\r
     }\r
 \r
     @Override\r
-    public void draw(Graphics2D graphics){\r
+    public void draw(Graphics2D graphics) {\r
         java.awt.Shape outline = getOutline();\r
 \r
         // shadow\r
         XSLFShadow shadow = getShadow();\r
-        if(shadow != null) shadow.draw(graphics);\r
 \r
         //border\r
         Color lineColor = getLineColor();\r
-        if (lineColor != null){\r
+        if (lineColor != null) {\r
+            if (shadow != null) shadow.draw(graphics);\r
+\r
             graphics.setColor(lineColor);\r
             applyStroke(graphics);\r
             graphics.draw(outline);\r
+\r
+            Shape tailDecoration = getTailDecoration();\r
+            if (tailDecoration != null) {\r
+                graphics.draw(tailDecoration);\r
+            }\r
+\r
+            Shape headDecoration = getHeadDecoration();\r
+            if (headDecoration != null) {\r
+                graphics.draw(headDecoration);\r
+\r
+            }\r
         }\r
     }\r
 \r
     @Override\r
-    protected java.awt.Shape getOutline(){\r
+    protected java.awt.Shape getOutline() {\r
         Rectangle2D anchor = getAnchor();\r
-        double  x1 = anchor.getX(),\r
+        double x1 = anchor.getX(),\r
                 y1 = anchor.getY(),\r
                 x2 = anchor.getX() + anchor.getWidth(),\r
                 y2 = anchor.getY() + anchor.getHeight();\r
 \r
-        GeneralPath line = new GeneralPath();\r
-        line.moveTo((float)x1, (float)y1);\r
-        line.lineTo((float)x2, (float)y2);\r
 \r
-        return line;\r
+        return new Line2D.Double(x1, y1, x2, y2);\r
+    }\r
+\r
+    Shape getTailDecoration() {\r
+        LineEndLength tailLength = getLineTailLength();\r
+        LineEndWidth tailWidth = getLineTailWidth();\r
+\r
+        double lineWidth = getLineWidth();\r
+        Rectangle2D anchor = getAnchor();\r
+        double x2 = anchor.getX() + anchor.getWidth(),\r
+                y2 = anchor.getY() + anchor.getHeight();\r
+\r
+        double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());\r
+\r
+        AffineTransform at = new AffineTransform();\r
+        Shape shape = null;\r
+        Rectangle2D bounds;\r
+        double scaleY = Math.pow(2, tailWidth.ordinal());\r
+        double scaleX = Math.pow(2, tailLength.ordinal());\r
+        switch (getLineHeadDecoration()) {\r
+            case OVAL:\r
+                shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);\r
+                bounds = shape.getBounds2D();\r
+                at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2);\r
+                at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);\r
+                break;\r
+            case ARROW:\r
+                GeneralPath arrow = new GeneralPath();\r
+                arrow.moveTo(-lineWidth * 3, -lineWidth * 2);\r
+                arrow.lineTo(0, 0);\r
+                arrow.lineTo(-lineWidth * 3, lineWidth * 2);\r
+                shape = arrow;\r
+                at.translate(x2, y2);\r
+                at.rotate(alpha);\r
+                break;\r
+            case TRIANGLE:\r
+                scaleY = tailWidth.ordinal() + 1;\r
+                scaleX = tailLength.ordinal() + 1;\r
+                GeneralPath triangle = new GeneralPath();\r
+                triangle.moveTo(-lineWidth * scaleX, -lineWidth * scaleY/2);\r
+                triangle.lineTo(0, 0);\r
+                triangle.lineTo(-lineWidth * scaleX, lineWidth * scaleY/2);\r
+                triangle.closePath();\r
+                shape = triangle;\r
+                at.translate(x2, y2);\r
+                at.rotate(alpha);\r
+                break;\r
+            default:\r
+                break;\r
+        }\r
+\r
+        if (shape != null) {\r
+            shape = at.createTransformedShape(shape);\r
+        }\r
+        return shape;\r
+    }\r
+\r
+    Shape getHeadDecoration() {\r
+        LineEndLength headLength = getLineHeadLength();\r
+        LineEndWidth headWidth = getLineHeadWidth();\r
+\r
+        double lineWidth = getLineWidth();\r
+        Rectangle2D anchor = getAnchor();\r
+        double x1 = anchor.getX(),\r
+                y1 = anchor.getY();\r
+\r
+        double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());\r
+\r
+        AffineTransform at = new AffineTransform();\r
+        Shape shape = null;\r
+        Rectangle2D bounds;\r
+        double scaleY = 1;\r
+        double scaleX = 1;\r
+        switch (getLineHeadDecoration()) {\r
+            case OVAL:\r
+                scaleY = Math.pow(2, headWidth.ordinal());\r
+                scaleX = Math.pow(2, headLength.ordinal());\r
+                shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);\r
+                break;\r
+            case STEALTH:\r
+            case ARROW:\r
+                GeneralPath arrow = new GeneralPath();\r
+                arrow.moveTo(lineWidth * 3 * scaleX, -lineWidth * scaleY * 2);\r
+                arrow.lineTo(0, 0);\r
+                arrow.lineTo(lineWidth * 3 * scaleX, lineWidth * scaleY * 2);\r
+                shape = arrow;\r
+                at.translate(x1, y1);\r
+                at.rotate(alpha);\r
+                break;\r
+            case TRIANGLE:\r
+                scaleY = headWidth.ordinal() + 1;\r
+                scaleX = headLength.ordinal() + 1;\r
+                GeneralPath triangle = new GeneralPath();\r
+                triangle.moveTo(lineWidth * scaleX, -lineWidth * scaleY/2);\r
+                triangle.lineTo(0, 0);\r
+                triangle.lineTo(lineWidth * scaleX, lineWidth * scaleY/2);\r
+                triangle.closePath();\r
+                shape = triangle;\r
+                at.translate(x1, y1);\r
+                at.rotate(alpha);\r
+                break;\r
+            default:\r
+                break;\r
+        }\r
+\r
+        if (shape != null) {\r
+            shape = at.createTransformedShape(shape);\r
+        }\r
+        return shape;\r
     }\r
 \r
 }
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java
new file mode 100644 (file)
index 0000000..46fa1bf
--- /dev/null
@@ -0,0 +1,87 @@
+/*\r
+ *  ====================================================================\r
+ *    Licensed to the Apache Software Foundation (ASF) under one or more\r
+ *    contributor license agreements.  See the NOTICE file distributed with\r
+ *    this work for additional information regarding copyright ownership.\r
+ *    The ASF licenses this file to You under the Apache License, Version 2.0\r
+ *    (the "License"); you may not use this file except in compliance with\r
+ *    the License.  You may obtain a copy of the License at\r
+ *\r
+ *        http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ *    Unless required by applicable law or agreed to in writing, software\r
+ *    distributed under the License is distributed on an "AS IS" BASIS,\r
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ *    See the License for the specific language governing permissions and\r
+ *    limitations under the License.\r
+ * ====================================================================\r
+ */\r
+\r
+package org.apache.poi.xslf.usermodel;\r
+\r
+import org.apache.poi.util.Beta;\r
+\r
+import javax.imageio.ImageIO;\r
+import java.awt.Graphics2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.awt.image.BufferedImage;\r
+import java.io.ByteArrayInputStream;\r
+\r
+/**\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
+ * \r
+ * <pre>\r
+ * <code>\r
+ * @Override\r
+ * public class MyImageRendener extends XSLFImageRendener{\r
+ * public boolean drawImage(Graphics2D graphics, XSLFPictureData data, Rectangle2D anchor){\r
+ *     boolean ok = super.drawImage(graphics, data, anchor);\r
+ *     if(!ok){\r
+ *             // see what type of image we are\r
+ *             String contentType = data.getPackagePart().getContentType();\r
+ *             if(contentType.equals("image/wmf")){\r
+ *                     // use Apache Batik to handle WMF\r
+ *                     // see http://xmlgraphics.apache.org/batik/\r
+ *             }\r
+ *             \r
+ *     }\r
+ *     return ok;\r
+ * }\r
+ * }\r
+ * </code>\r
+ * </pre>\r
+ * \r
+ * and then pass this class to your instance of java.awt.Graphics2D:\r
+ * \r
+ * <pre>\r
+ * <code>\r
+ * graphics.setRenderingHint(XSLFRenderingHint.IMAGE_RENDERER, new MyImageRendener());\r
+ * </code>\r
+ * </pre>\r
+ * \r
+ * @author Yegor Kozlov\r
+ */\r
+@Beta\r
+public class XSLFImageRendener {\r
+\r
+       /**\r
+        * Render picture data into the supplied graphics\r
+        * \r
+        * @return true if the picture data was succesfully renderered\r
+        */\r
+       public boolean drawImage(Graphics2D graphics, XSLFPictureData data,\r
+                       Rectangle2D anchor) {\r
+               try {\r
+                       BufferedImage img = ImageIO.read(new ByteArrayInputStream(data\r
+                                       .getData()));\r
+                       graphics.drawImage(img, (int) anchor.getX(), (int) anchor.getY(),\r
+                                       (int) anchor.getWidth(), (int) anchor.getHeight(), null);\r
+                       return true;\r
+               } catch (Exception e) {\r
+                       return false;\r
+               }\r
+\r
+       }\r
+}
\ No newline at end of file
index 4e17d62c0592a8a07ade97e9e6c9430599fcf65c..c5c92b5dc05427439e3be2ed623e21d24a94193c 100644 (file)
@@ -117,30 +117,26 @@ public class XSLFPictureShape extends XSLFSimpleShape {
     public void draw(Graphics2D graphics){\r
         java.awt.Shape outline = getOutline();\r
 \r
+        // shadow\r
+        XSLFShadow shadow = getShadow();\r
+\r
         //fill\r
         Color fillColor = getFillColor();\r
         if (fillColor != null) {\r
-            graphics.setColor(fillColor);\r
+            if(shadow != null) shadow.draw(graphics);\r
+\r
+               graphics.setColor(fillColor);\r
             applyFill(graphics);\r
             graphics.fill(outline);\r
         }\r
-        \r
-        // text\r
-       \r
-       XSLFPictureData data = getPictureData();\r
+         \r
+        XSLFPictureData data = getPictureData();\r
        if(data == null) return;\r
        \r
-        BufferedImage img;\r
-        try {\r
-               img = ImageIO.read(new ByteArrayInputStream(data.getData()));\r
-        }\r
-        catch (Exception e){\r
-            return;\r
-        }\r
-        Rectangle2D anchor = getAnchor();\r
-        graphics.drawImage(img, (int)anchor.getX(), (int)anchor.getY(), \r
-                       (int)anchor.getWidth(), (int)anchor.getHeight(), null);\r
-\r
+        XSLFImageRendener renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER);\r
+        if(renderer == null) renderer = new XSLFImageRendener();\r
\r
+        renderer.drawImage(graphics, data, getAnchor());\r
 \r
         //border overlays the image\r
         Color lineColor = getLineColor();\r
index aff8c90c419e3cb83c1507edde187c2941b46995..cc0df0fbfd0969bc12e1b34a5a84b03729e01c1f 100644 (file)
@@ -38,5 +38,5 @@ public class XSLFRenderingHint extends RenderingHints.Key {
 \r
     public static final XSLFRenderingHint GSAVE = new XSLFRenderingHint(1);\r
     public static final XSLFRenderingHint GRESTORE = new XSLFRenderingHint(2);\r
-    public static final XSLFRenderingHint SKIP_PLACEHOLDERS = new XSLFRenderingHint(3);\r
+    public static final XSLFRenderingHint IMAGE_RENDERER = new XSLFRenderingHint(3);\r
 }
\ No newline at end of file
index e897e29fba14c090db3730de236954383166373f..837529a90b74ab5bfa759cb2d4df82d032a95d66 100644 (file)
@@ -45,9 +45,13 @@ public class XSLFShadow extends XSLFSimpleShape {
         _parent = parentShape;\r
     }\r
 \r
+     @Override\r
     public void draw(Graphics2D graphics) {\r
         Shape outline = _parent.getOutline();\r
 \r
+        Color parentFillColor = _parent.getFillColor();\r
+        Color parentLineColor = _parent.getLineColor();\r
+\r
         double angle = getAngle();\r
         double dist = getDistance();\r
         double dx = dist * Math.cos( Math.toRadians(angle));\r
@@ -55,13 +59,19 @@ public class XSLFShadow extends XSLFSimpleShape {
 \r
         graphics.translate(dx, dy);\r
 \r
-        //fill\r
         Color fillColor = getFillColor();\r
         if (fillColor != null) {\r
             graphics.setColor(fillColor);\r
-            graphics.fill(outline);\r
         }\r
 \r
+        if(parentFillColor != null) {\r
+            graphics.fill(outline);\r
+       }\r
+       if(parentLineColor != null) {\r
+            _parent.applyStroke(graphics);\r
+             graphics.draw(outline);\r
+       }\r
+\r
         graphics.translate(-dx, -dy);\r
     }\r
 \r
@@ -75,21 +85,37 @@ public class XSLFShadow extends XSLFSimpleShape {
         throw new IllegalStateException("You can't set anchor of a shadow");\r
     }\r
 \r
+    /**\r
+     * @return the offset of this shadow in points\r
+     */\r
     public double getDistance(){\r
         CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();\r
         return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0;        \r
     }\r
 \r
+    /**\r
+     * \r
+     * @return the direction to offset the shadow in angles\r
+     */\r
     public double getAngle(){\r
         CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();\r
         return ct.isSetDir() ? (double)ct.getDir() / 60000 : 0;\r
     }\r
 \r
+    /**\r
+     * \r
+     * @return the blur radius of the shadow\r
+     * TODO: figure out how to make sense of this property when rendering shadows \r
+     */\r
     public double getBlur(){\r
         CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject();\r
         return ct.isSetBlurRad() ? Units.toPoints(ct.getBlurRad()) : 0;\r
     }\r
 \r
+    /**\r
+     * @return the color of this shadow. \r
+     * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow\r
+     */\r
     @Override\r
     public Color getFillColor() {\r
         XSLFTheme theme = getSheet().getTheme();\r
@@ -100,7 +126,10 @@ public class XSLFShadow extends XSLFSimpleShape {
         else if (ct.isSetPrstClr()) {\r
             return theme.getPresetColor(ct.getPrstClr());\r
         }\r
+        else if (ct.isSetSrgbClr()) {\r
+            return theme.getSrgbColor(ct.getSrgbClr());\r
+        }\r
 \r
-        return Color.black;\r
+        return null;\r
     }\r
 }
\ No newline at end of file
index 8e3b38a2278ae30bb3c5fe221b77fa9ed303fbfc..c7efb5ff51f858a6be8152903abd39a19dcf4eec 100644 (file)
@@ -279,14 +279,14 @@ public abstract class XSLFSimpleShape extends XSLFShape {
 \r
     public Color getLineColor() {\r
         final XSLFTheme theme = _sheet.getTheme();\r
-\r
+        final Color noline = new Color(0,0,0,0);\r
         PropertyFetcher<Color> fetcher = new PropertyFetcher<Color>(){\r
             public boolean fetch(XSLFSimpleShape shape){\r
                 CTShapeProperties spPr = shape.getSpPr();\r
                 CTLineProperties ln = spPr.getLn();\r
                 if (ln != null) {\r
                     if (ln.isSetNoFill()) {\r
-                        setValue(null);\r
+                        setValue(noline);\r
                         return true;\r
                     }\r
                     CTSolidColorFillProperties solidLine = ln.getSolidFill();\r
@@ -311,7 +311,7 @@ public abstract class XSLFSimpleShape extends XSLFShape {
                 }\r
             }\r
         }\r
-        return color;\r
+        return color == noline ? null : color;\r
     }\r
 \r
     public void setLineWidth(double width) {\r
@@ -480,12 +480,12 @@ public abstract class XSLFSimpleShape extends XSLFShape {
      */\r
     public Color getFillColor() {\r
         final XSLFTheme theme = _sheet.getTheme();\r
-\r
+        final Color nofill = new Color(0,0,0,0);\r
         PropertyFetcher<Color> fetcher = new PropertyFetcher<Color>(){\r
             public boolean fetch(XSLFSimpleShape shape){\r
                 CTShapeProperties spPr = shape.getSpPr();\r
                 if (spPr.isSetNoFill()) {\r
-                    setValue(null);\r
+                    setValue(nofill); // use it as 'nofill' value\r
                     return true;\r
                 }\r
                 if (spPr.isSetSolidFill()) {\r
@@ -508,7 +508,7 @@ public abstract class XSLFSimpleShape extends XSLFShape {
                 }\r
             }\r
         }\r
-        return color;\r
+        return color == nofill ? null : color;\r
     }\r
 \r
     public XSLFShadow getShadow(){\r
@@ -608,7 +608,7 @@ public abstract class XSLFSimpleShape extends XSLFShape {
 \r
         int meter = BasicStroke.JOIN_ROUND;\r
 \r
-        Stroke stroke = new BasicStroke(lineWidth, cap, meter, 0.0f, dash,\r
+        Stroke stroke = new BasicStroke(lineWidth, cap, meter, Math.max(1, lineWidth), dash,\r
                 dash_phase);\r
         graphics.setStroke(stroke);\r
     }\r
index 3d303002e0b4964e878d4b5c654f689eec94e4cd..d17f1ce7592cf003665c6aec170a175e47577543 100644 (file)
@@ -387,18 +387,19 @@ public abstract class XSLFTextShape extends XSLFSimpleShape {
 
         // shadow
         XSLFShadow shadow = getShadow();
-        if(shadow != null) shadow.draw(graphics);
 
-        //fill
         Color fillColor = getFillColor();
+        Color lineColor = getLineColor();
+        if(shadow != null) {
+               shadow.draw(graphics);
+        }
+
         if (fillColor != null) {
-            graphics.setColor(fillColor);
+               graphics.setColor(fillColor);
             applyFill(graphics);
             graphics.fill(outline);
         }
  
-        //border
-        Color lineColor = getLineColor();
         if (lineColor != null){
             graphics.setColor(lineColor);
             applyStroke(graphics);
index 8633a326a96891c2b5b71c2da0ae15ae6320a410..dcfd479cc9f48ef173a35f640bea6bc9770b86d5 100644 (file)
@@ -69,12 +69,12 @@ public class TestXSLFConnectorShape extends TestCase {
         assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getTailEnd().getType());\r
 \r
         // line end width\r
-        assertEquals(null, shape.getLineHeadWidth());\r
-        assertEquals(null, shape.getLineTailWidth());\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth());\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth());\r
         shape.setLineHeadWidth(null);\r
         shape.setLineHeadWidth(null);\r
-        assertEquals(null, shape.getLineHeadWidth());\r
-        assertEquals(null, shape.getLineTailWidth());\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth());\r
+        assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth());\r
         assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetW());\r
         assertFalse(shape.getSpPr().getLn().getTailEnd().isSetW());\r
         shape.setLineHeadWidth(LineEndWidth.LARGE);\r
@@ -91,12 +91,12 @@ public class TestXSLFConnectorShape extends TestCase {
         assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getTailEnd().getW());\r
 \r
         // line end length\r
-        assertEquals(null, shape.getLineHeadLength());\r
-        assertEquals(null, shape.getLineTailLength());\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength());\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength());\r
         shape.setLineHeadLength(null);\r
         shape.setLineTailLength(null);\r
-        assertEquals(null, shape.getLineHeadLength());\r
-        assertEquals(null, shape.getLineTailLength());\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength());\r
+        assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength());\r
         assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetLen());\r
         assertFalse(shape.getSpPr().getLn().getTailEnd().isSetLen());\r
         shape.setLineHeadLength(LineEndLength.LARGE);\r