diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java index 6eb49b4b9..bdaa58620 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFConnectorShape.java @@ -33,19 +33,17 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnectorNonVisual; import java.awt.*; -import java.awt.geom.GeneralPath; -import java.awt.geom.Rectangle2D; +import java.awt.geom.*; /** - * - * Specifies a connection shape. + * Specifies a connection shape. * * @author Yegor Kozlov */ @Beta public class XSLFConnectorShape extends XSLFSimpleShape { - /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet){ + /*package*/ XSLFConnectorShape(CTConnector shape, XSLFSheet sheet) { super(shape, sheet); } @@ -71,19 +69,19 @@ public class XSLFConnectorShape extends XSLFSimpleShape { /** * Specifies the line end decoration, such as a triangle or arrowhead. */ - public void setLineHeadDecoration(LineDecoration style){ + public void setLineHeadDecoration(LineDecoration style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); - if(style == null){ - if(lnEnd.isSetType()) lnEnd.unsetType(); + if (style == null) { + if (lnEnd.isSetType()) lnEnd.unsetType(); } else { lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1)); } } - public LineDecoration getLineHeadDecoration(){ + public LineDecoration getLineHeadDecoration() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetHeadEnd()) return LineDecoration.NONE; + if (ln == null || !ln.isSetHeadEnd()) return LineDecoration.NONE; STLineEndType.Enum end = ln.getHeadEnd().getType(); return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1]; @@ -92,62 +90,62 @@ public class XSLFConnectorShape extends XSLFSimpleShape { /** * specifies decorations which can be added to the head of a line. */ - public void setLineHeadWidth(LineEndWidth style){ + public void setLineHeadWidth(LineEndWidth style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); - if(style == null){ - if(lnEnd.isSetW()) lnEnd.unsetW(); + if (style == null) { + if (lnEnd.isSetW()) lnEnd.unsetW(); } else { lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1)); } } - public LineEndWidth getLineHeadWidth(){ + public LineEndWidth getLineHeadWidth() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetHeadEnd()) return null; + if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM; STLineEndWidth.Enum w = ln.getHeadEnd().getW(); - return w == null ? null : LineEndWidth.values()[w.intValue() - 1]; + return w == null ? LineEndWidth.MEDIUM : LineEndWidth.values()[w.intValue() - 1]; } /** * Specifies the line end width in relation to the line width. */ - public void setLineHeadLength(LineEndLength style){ + public void setLineHeadLength(LineEndLength style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd(); - if(style == null){ - if(lnEnd.isSetLen()) lnEnd.unsetLen(); + if (style == null) { + if (lnEnd.isSetLen()) lnEnd.unsetLen(); } else { lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1)); } } - public LineEndLength getLineHeadLength(){ + public LineEndLength getLineHeadLength() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetHeadEnd()) return null; + if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM; STLineEndLength.Enum len = ln.getHeadEnd().getLen(); - return len == null ? null : LineEndLength.values()[len.intValue() - 1]; + return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1]; } /** * Specifies the line end decoration, such as a triangle or arrowhead. */ - public void setLineTailDecoration(LineDecoration style){ + public void setLineTailDecoration(LineDecoration style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); - if(style == null){ - if(lnEnd.isSetType()) lnEnd.unsetType(); + if (style == null) { + if (lnEnd.isSetType()) lnEnd.unsetType(); } else { lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1)); } } - public LineDecoration getLineTailDecoration(){ + public LineDecoration getLineTailDecoration() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetTailEnd()) return LineDecoration.NONE; + if (ln == null || !ln.isSetTailEnd()) return LineDecoration.NONE; STLineEndType.Enum end = ln.getTailEnd().getType(); return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1]; @@ -156,76 +154,193 @@ public class XSLFConnectorShape extends XSLFSimpleShape { /** * specifies decorations which can be added to the tail of a line. */ - public void setLineTailWidth(LineEndWidth style){ + public void setLineTailWidth(LineEndWidth style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); - if(style == null){ - if(lnEnd.isSetW()) lnEnd.unsetW(); + if (style == null) { + if (lnEnd.isSetW()) lnEnd.unsetW(); } else { lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1)); } } - public LineEndWidth getLineTailWidth(){ + public LineEndWidth getLineTailWidth() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetTailEnd()) return null; + if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM; STLineEndWidth.Enum w = ln.getTailEnd().getW(); - return w == null ? null : LineEndWidth.values()[w.intValue() - 1]; + return w == null ? LineEndWidth.MEDIUM : LineEndWidth.values()[w.intValue() - 1]; } /** * Specifies the line end width in relation to the line width. */ - public void setLineTailLength(LineEndLength style){ + public void setLineTailLength(LineEndLength style) { CTLineProperties ln = getSpPr().getLn(); CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd(); - if(style == null){ - if(lnEnd.isSetLen()) lnEnd.unsetLen(); + if (style == null) { + if (lnEnd.isSetLen()) lnEnd.unsetLen(); } else { lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1)); } } - public LineEndLength getLineTailLength(){ + public LineEndLength getLineTailLength() { CTLineProperties ln = getSpPr().getLn(); - if(!ln.isSetTailEnd()) return null; + if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM; STLineEndLength.Enum len = ln.getTailEnd().getLen(); - return len == null ? null : LineEndLength.values()[len.intValue() - 1]; + return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1]; } @Override - public void draw(Graphics2D graphics){ + public void draw(Graphics2D graphics) { java.awt.Shape outline = getOutline(); // shadow XSLFShadow shadow = getShadow(); - if(shadow != null) shadow.draw(graphics); //border Color lineColor = getLineColor(); - if (lineColor != null){ + if (lineColor != null) { + if (shadow != null) shadow.draw(graphics); + graphics.setColor(lineColor); applyStroke(graphics); graphics.draw(outline); + + Shape tailDecoration = getTailDecoration(); + if (tailDecoration != null) { + graphics.draw(tailDecoration); + } + + Shape headDecoration = getHeadDecoration(); + if (headDecoration != null) { + graphics.draw(headDecoration); + + } } } @Override - protected java.awt.Shape getOutline(){ + protected java.awt.Shape getOutline() { Rectangle2D anchor = getAnchor(); - double x1 = anchor.getX(), + double x1 = anchor.getX(), y1 = anchor.getY(), x2 = anchor.getX() + anchor.getWidth(), y2 = anchor.getY() + anchor.getHeight(); - GeneralPath line = new GeneralPath(); - line.moveTo((float)x1, (float)y1); - line.lineTo((float)x2, (float)y2); - return line; + return new Line2D.Double(x1, y1, x2, y2); + } + + Shape getTailDecoration() { + LineEndLength tailLength = getLineTailLength(); + LineEndWidth tailWidth = getLineTailWidth(); + + double lineWidth = getLineWidth(); + Rectangle2D anchor = getAnchor(); + double x2 = anchor.getX() + anchor.getWidth(), + y2 = anchor.getY() + anchor.getHeight(); + + double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); + + AffineTransform at = new AffineTransform(); + Shape shape = null; + Rectangle2D bounds; + double scaleY = Math.pow(2, tailWidth.ordinal()); + double scaleX = Math.pow(2, tailLength.ordinal()); + switch (getLineHeadDecoration()) { + case OVAL: + shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); + bounds = shape.getBounds2D(); + at.translate(x2 - bounds.getWidth() / 2, y2 - bounds.getHeight() / 2); + at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2); + break; + case ARROW: + GeneralPath arrow = new GeneralPath(); + arrow.moveTo(-lineWidth * 3, -lineWidth * 2); + arrow.lineTo(0, 0); + arrow.lineTo(-lineWidth * 3, lineWidth * 2); + shape = arrow; + at.translate(x2, y2); + at.rotate(alpha); + break; + case TRIANGLE: + scaleY = tailWidth.ordinal() + 1; + scaleX = tailLength.ordinal() + 1; + GeneralPath triangle = new GeneralPath(); + triangle.moveTo(-lineWidth * scaleX, -lineWidth * scaleY/2); + triangle.lineTo(0, 0); + triangle.lineTo(-lineWidth * scaleX, lineWidth * scaleY/2); + triangle.closePath(); + shape = triangle; + at.translate(x2, y2); + at.rotate(alpha); + break; + default: + break; + } + + if (shape != null) { + shape = at.createTransformedShape(shape); + } + return shape; + } + + Shape getHeadDecoration() { + LineEndLength headLength = getLineHeadLength(); + LineEndWidth headWidth = getLineHeadWidth(); + + double lineWidth = getLineWidth(); + Rectangle2D anchor = getAnchor(); + double x1 = anchor.getX(), + y1 = anchor.getY(); + + double alpha = Math.atan(anchor.getHeight() / anchor.getWidth()); + + AffineTransform at = new AffineTransform(); + Shape shape = null; + Rectangle2D bounds; + double scaleY = 1; + double scaleX = 1; + switch (getLineHeadDecoration()) { + case OVAL: + scaleY = Math.pow(2, headWidth.ordinal()); + scaleX = Math.pow(2, headLength.ordinal()); + shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY); + break; + case STEALTH: + case ARROW: + GeneralPath arrow = new GeneralPath(); + arrow.moveTo(lineWidth * 3 * scaleX, -lineWidth * scaleY * 2); + arrow.lineTo(0, 0); + arrow.lineTo(lineWidth * 3 * scaleX, lineWidth * scaleY * 2); + shape = arrow; + at.translate(x1, y1); + at.rotate(alpha); + break; + case TRIANGLE: + scaleY = headWidth.ordinal() + 1; + scaleX = headLength.ordinal() + 1; + GeneralPath triangle = new GeneralPath(); + triangle.moveTo(lineWidth * scaleX, -lineWidth * scaleY/2); + triangle.lineTo(0, 0); + triangle.lineTo(lineWidth * scaleX, lineWidth * scaleY/2); + triangle.closePath(); + shape = triangle; + at.translate(x1, y1); + at.rotate(alpha); + break; + default: + break; + } + + if (shape != null) { + shape = at.createTransformedShape(shape); + } + return shape; } } \ 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 index 000000000..46fa1bf17 --- /dev/null +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFImageRendener.java @@ -0,0 +1,87 @@ +/* + * ==================================================================== + * 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.xslf.usermodel; + +import org.apache.poi.util.Beta; + +import javax.imageio.ImageIO; +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; + +/** + * For now this class renders only images supported by the javax.imageio.ImageIO + * framework. Subclasses can override this class to support other formats, for + * example, Use Apache batik to render WMF: + * + *
+ * 
+ * @Override
+ * public class MyImageRendener extends XSLFImageRendener{
+ * public boolean drawImage(Graphics2D graphics, XSLFPictureData data, Rectangle2D anchor){
+ * 	boolean ok = super.drawImage(graphics, data, anchor);
+ * 	if(!ok){
+ * 		// see what type of image we are
+ * 		String contentType = data.getPackagePart().getContentType();
+ * 		if(contentType.equals("image/wmf")){
+ * 			// use Apache Batik to handle WMF
+ * 			// see http://xmlgraphics.apache.org/batik/
+ * 		}
+ * 		
+ * 	}
+ * 	return ok;
+ * }
+ * }
+ * 
+ * 
+ * + * and then pass this class to your instance of java.awt.Graphics2D: + * + *
+ * 
+ * graphics.setRenderingHint(XSLFRenderingHint.IMAGE_RENDERER, new MyImageRendener());
+ * 
+ * 
+ * + * @author Yegor Kozlov + */ +@Beta +public class XSLFImageRendener { + + /** + * Render picture data into the supplied graphics + * + * @return true if the picture data was succesfully renderered + */ + public boolean drawImage(Graphics2D graphics, XSLFPictureData data, + Rectangle2D anchor) { + try { + BufferedImage img = ImageIO.read(new ByteArrayInputStream(data + .getData())); + graphics.drawImage(img, (int) anchor.getX(), (int) anchor.getY(), + (int) anchor.getWidth(), (int) anchor.getHeight(), null); + return true; + } catch (Exception e) { + return false; + } + + } +} \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java index 4e17d62c0..c5c92b5dc 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFPictureShape.java @@ -117,30 +117,26 @@ public class XSLFPictureShape extends XSLFSimpleShape { public void draw(Graphics2D graphics){ java.awt.Shape outline = getOutline(); + // shadow + XSLFShadow shadow = getShadow(); + //fill Color fillColor = getFillColor(); if (fillColor != null) { - graphics.setColor(fillColor); + if(shadow != null) shadow.draw(graphics); + + graphics.setColor(fillColor); applyFill(graphics); graphics.fill(outline); } - - // text - - XSLFPictureData data = getPictureData(); + + XSLFPictureData data = getPictureData(); if(data == null) return; - BufferedImage img; - try { - img = ImageIO.read(new ByteArrayInputStream(data.getData())); - } - catch (Exception e){ - return; - } - Rectangle2D anchor = getAnchor(); - graphics.drawImage(img, (int)anchor.getX(), (int)anchor.getY(), - (int)anchor.getWidth(), (int)anchor.getHeight(), null); - + XSLFImageRendener renderer = (XSLFImageRendener)graphics.getRenderingHint(XSLFRenderingHint.IMAGE_RENDERER); + if(renderer == null) renderer = new XSLFImageRendener(); + + renderer.drawImage(graphics, data, getAnchor()); //border overlays the image Color lineColor = getLineColor(); diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java index aff8c90c4..cc0df0fbf 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFRenderingHint.java @@ -38,5 +38,5 @@ public class XSLFRenderingHint extends RenderingHints.Key { public static final XSLFRenderingHint GSAVE = new XSLFRenderingHint(1); public static final XSLFRenderingHint GRESTORE = new XSLFRenderingHint(2); - public static final XSLFRenderingHint SKIP_PLACEHOLDERS = new XSLFRenderingHint(3); + public static final XSLFRenderingHint IMAGE_RENDERER = new XSLFRenderingHint(3); } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java index e897e29fb..837529a90 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShadow.java @@ -45,9 +45,13 @@ public class XSLFShadow extends XSLFSimpleShape { _parent = parentShape; } + @Override public void draw(Graphics2D graphics) { Shape outline = _parent.getOutline(); + Color parentFillColor = _parent.getFillColor(); + Color parentLineColor = _parent.getLineColor(); + double angle = getAngle(); double dist = getDistance(); double dx = dist * Math.cos( Math.toRadians(angle)); @@ -55,13 +59,19 @@ public class XSLFShadow extends XSLFSimpleShape { graphics.translate(dx, dy); - //fill Color fillColor = getFillColor(); if (fillColor != null) { graphics.setColor(fillColor); - graphics.fill(outline); } + if(parentFillColor != null) { + graphics.fill(outline); + } + if(parentLineColor != null) { + _parent.applyStroke(graphics); + graphics.draw(outline); + } + graphics.translate(-dx, -dy); } @@ -75,21 +85,37 @@ public class XSLFShadow extends XSLFSimpleShape { throw new IllegalStateException("You can't set anchor of a shadow"); } + /** + * @return the offset of this shadow in points + */ public double getDistance(){ CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); return ct.isSetDist() ? Units.toPoints(ct.getDist()) : 0; } + /** + * + * @return the direction to offset the shadow in angles + */ public double getAngle(){ CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); return ct.isSetDir() ? (double)ct.getDir() / 60000 : 0; } + /** + * + * @return the blur radius of the shadow + * TODO: figure out how to make sense of this property when rendering shadows + */ public double getBlur(){ CTOuterShadowEffect ct = (CTOuterShadowEffect)getXmlObject(); return ct.isSetBlurRad() ? Units.toPoints(ct.getBlurRad()) : 0; } + /** + * @return the color of this shadow. + * Depending whether the parent shape is filled or stroked, this color is used to fill or stroke this shadow + */ @Override public Color getFillColor() { XSLFTheme theme = getSheet().getTheme(); @@ -100,7 +126,10 @@ public class XSLFShadow extends XSLFSimpleShape { else if (ct.isSetPrstClr()) { return theme.getPresetColor(ct.getPrstClr()); } + else if (ct.isSetSrgbClr()) { + return theme.getSrgbColor(ct.getSrgbClr()); + } - return Color.black; + return null; } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java index 8e3b38a22..c7efb5ff5 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java @@ -279,14 +279,14 @@ public abstract class XSLFSimpleShape extends XSLFShape { public Color getLineColor() { final XSLFTheme theme = _sheet.getTheme(); - + final Color noline = new Color(0,0,0,0); PropertyFetcher fetcher = new PropertyFetcher(){ public boolean fetch(XSLFSimpleShape shape){ CTShapeProperties spPr = shape.getSpPr(); CTLineProperties ln = spPr.getLn(); if (ln != null) { if (ln.isSetNoFill()) { - setValue(null); + setValue(noline); return true; } CTSolidColorFillProperties solidLine = ln.getSolidFill(); @@ -311,7 +311,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { } } } - return color; + return color == noline ? null : color; } public void setLineWidth(double width) { @@ -480,12 +480,12 @@ public abstract class XSLFSimpleShape extends XSLFShape { */ public Color getFillColor() { final XSLFTheme theme = _sheet.getTheme(); - + final Color nofill = new Color(0,0,0,0); PropertyFetcher fetcher = new PropertyFetcher(){ public boolean fetch(XSLFSimpleShape shape){ CTShapeProperties spPr = shape.getSpPr(); if (spPr.isSetNoFill()) { - setValue(null); + setValue(nofill); // use it as 'nofill' value return true; } if (spPr.isSetSolidFill()) { @@ -508,7 +508,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { } } } - return color; + return color == nofill ? null : color; } public XSLFShadow getShadow(){ @@ -608,7 +608,7 @@ public abstract class XSLFSimpleShape extends XSLFShape { int meter = BasicStroke.JOIN_ROUND; - Stroke stroke = new BasicStroke(lineWidth, cap, meter, 0.0f, dash, + Stroke stroke = new BasicStroke(lineWidth, cap, meter, Math.max(1, lineWidth), dash, dash_phase); graphics.setStroke(stroke); } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java index 3d303002e..d17f1ce75 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTextShape.java @@ -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); diff --git a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java index 8633a326a..dcfd479cc 100644 --- a/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java +++ b/src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFConnectorShape.java @@ -69,12 +69,12 @@ public class TestXSLFConnectorShape extends TestCase { assertEquals(STLineEndType.ARROW, shape.getSpPr().getLn().getTailEnd().getType()); // line end width - assertEquals(null, shape.getLineHeadWidth()); - assertEquals(null, shape.getLineTailWidth()); + assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); + assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); shape.setLineHeadWidth(null); shape.setLineHeadWidth(null); - assertEquals(null, shape.getLineHeadWidth()); - assertEquals(null, shape.getLineTailWidth()); + assertEquals(LineEndWidth.MEDIUM, shape.getLineHeadWidth()); + assertEquals(LineEndWidth.MEDIUM, shape.getLineTailWidth()); assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetW()); assertFalse(shape.getSpPr().getLn().getTailEnd().isSetW()); shape.setLineHeadWidth(LineEndWidth.LARGE); @@ -91,12 +91,12 @@ public class TestXSLFConnectorShape extends TestCase { assertEquals(STLineEndWidth.LG, shape.getSpPr().getLn().getTailEnd().getW()); // line end length - assertEquals(null, shape.getLineHeadLength()); - assertEquals(null, shape.getLineTailLength()); + assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); + assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); shape.setLineHeadLength(null); shape.setLineTailLength(null); - assertEquals(null, shape.getLineHeadLength()); - assertEquals(null, shape.getLineTailLength()); + assertEquals(LineEndLength.MEDIUM, shape.getLineHeadLength()); + assertEquals(LineEndLength.MEDIUM, shape.getLineTailLength()); assertFalse(shape.getSpPr().getLn().getHeadEnd().isSetLen()); assertFalse(shape.getSpPr().getLn().getTailEnd().isSetLen()); shape.setLineHeadLength(LineEndLength.LARGE);