-/*\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 java.awt.Color;\r
-import java.awt.geom.Rectangle2D;\r
-\r
-import javax.xml.stream.XMLStreamException;\r
-import javax.xml.stream.XMLStreamReader;\r
-\r
-import org.apache.poi.openxml4j.opc.PackagePart;\r
-import org.apache.poi.sl.draw.DrawPaint;\r
-import org.apache.poi.sl.draw.geom.CustomGeometry;\r
-import org.apache.poi.sl.draw.geom.Guide;\r
-import org.apache.poi.sl.draw.geom.PresetGeometries;\r
-import org.apache.poi.sl.usermodel.FillStyle;\r
-import org.apache.poi.sl.usermodel.LineDecoration;\r
-import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;\r
-import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;\r
-import org.apache.poi.sl.usermodel.PaintStyle;\r
-import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;\r
-import org.apache.poi.sl.usermodel.Placeholder;\r
-import org.apache.poi.sl.usermodel.ShapeType;\r
-import org.apache.poi.sl.usermodel.SimpleShape;\r
-import org.apache.poi.sl.usermodel.StrokeStyle;\r
-import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;\r
-import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;\r
-import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;\r
-import org.apache.poi.util.Beta;\r
-import org.apache.poi.util.POILogFactory;\r
-import org.apache.poi.util.POILogger;\r
-import org.apache.poi.util.Units;\r
-import org.apache.poi.xslf.model.PropertyFetcher;\r
-import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFEffectProperties;\r
-import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;\r
-import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFGeometryProperties;\r
-import org.apache.xmlbeans.XmlObject;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
-import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
-\r
-/**\r
- * Represents a single (non-group) shape in a .pptx slide show\r
- */\r
-@Beta\r
-public abstract class XSLFSimpleShape extends XSLFShape\r
- implements SimpleShape<XSLFShape,XSLFTextParagraph> {\r
- private static CTOuterShadowEffect NO_SHADOW = CTOuterShadowEffect.Factory.newInstance();\r
- private static final POILogger LOG = POILogFactory.getLogger(XSLFSimpleShape.class);\r
-\r
- /* package */XSLFSimpleShape(XmlObject shape, XSLFSheet sheet) {\r
- super(shape,sheet);\r
- }\r
-\r
- @Override\r
- public void setShapeType(ShapeType type) {\r
- XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());\r
- if (gp == null) {\r
- return;\r
- }\r
- if (gp.isSetCustGeom()) {\r
- gp.unsetCustGeom();\r
- }\r
- CTPresetGeometry2D prst = (gp.isSetPrstGeom()) ? gp.getPrstGeom() : gp.addNewPrstGeom();\r
- prst.setPrst(STShapeType.Enum.forInt(type.ooxmlId));\r
- }\r
-\r
- @Override\r
- public ShapeType getShapeType(){\r
- XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());\r
- if (gp != null && gp.isSetPrstGeom()) {\r
- STShapeType.Enum geom = gp.getPrstGeom().getPrst();\r
- if (geom != null) {\r
- return ShapeType.forId(geom.intValue(), true);\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- protected CTTransform2D getXfrm(boolean create) {\r
- PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {\r
- public boolean fetch(XSLFShape shape) {\r
- XmlObject xo = shape.getShapeProperties();\r
- if (xo instanceof CTShapeProperties && ((CTShapeProperties)xo).isSetXfrm()) {\r
- setValue(((CTShapeProperties)xo).getXfrm());\r
- return true;\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
- \r
- CTTransform2D xfrm = fetcher.getValue();\r
- if (!create || xfrm != null) {\r
- return xfrm;\r
- } else {\r
- XmlObject xo = getShapeProperties();\r
- if (xo instanceof CTShapeProperties) {\r
- return ((CTShapeProperties)xo).addNewXfrm();\r
- } else {\r
- // ... group shapes have their own getXfrm()\r
- LOG.log(POILogger.WARN, getClass().toString()+" doesn't have xfrm element.");\r
- return null;\r
- }\r
- }\r
- }\r
-\r
- @Override\r
- public Rectangle2D getAnchor() {\r
-\r
- CTTransform2D xfrm = getXfrm(false);\r
- if (xfrm == null) {\r
- return null;\r
- }\r
-\r
- CTPoint2D off = xfrm.getOff();\r
- double x = Units.toPoints(off.getX());\r
- double y = Units.toPoints(off.getY());\r
- CTPositiveSize2D ext = xfrm.getExt();\r
- double cx = Units.toPoints(ext.getCx());\r
- double cy = Units.toPoints(ext.getCy());\r
- return new Rectangle2D.Double(x, y, cx, cy);\r
- }\r
-\r
- @Override\r
- public void setAnchor(Rectangle2D anchor) {\r
- CTTransform2D xfrm = getXfrm(true);\r
- if (xfrm == null) {\r
- return;\r
- }\r
- CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();\r
- long x = Units.toEMU(anchor.getX());\r
- long y = Units.toEMU(anchor.getY());\r
- off.setX(x);\r
- off.setY(y);\r
- CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm\r
- .addNewExt();\r
- long cx = Units.toEMU(anchor.getWidth());\r
- long cy = Units.toEMU(anchor.getHeight());\r
- ext.setCx(cx);\r
- ext.setCy(cy);\r
- }\r
-\r
- @Override\r
- public void setRotation(double theta) {\r
- CTTransform2D xfrm = getXfrm(true);\r
- if (xfrm != null) {\r
- xfrm.setRot((int) (theta * 60000));\r
- }\r
- }\r
-\r
- @Override\r
- public double getRotation() {\r
- CTTransform2D xfrm = getXfrm(false);\r
- return (xfrm == null || !xfrm.isSetRot()) ? 0 : (xfrm.getRot() / 60000.d);\r
- }\r
-\r
- @Override\r
- public void setFlipHorizontal(boolean flip) {\r
- CTTransform2D xfrm = getXfrm(true);\r
- if (xfrm != null) {\r
- xfrm.setFlipH(flip);\r
- }\r
- }\r
-\r
- @Override\r
- public void setFlipVertical(boolean flip) {\r
- CTTransform2D xfrm = getXfrm(true);\r
- if (xfrm != null) {\r
- xfrm.setFlipV(flip);\r
- }\r
- }\r
-\r
- @Override\r
- public boolean getFlipHorizontal() {\r
- CTTransform2D xfrm = getXfrm(false);\r
- return (xfrm == null || !xfrm.isSetFlipH()) ? false : xfrm.getFlipH();\r
- }\r
-\r
- @Override\r
- public boolean getFlipVertical() {\r
- CTTransform2D xfrm = getXfrm(false);\r
- return (xfrm == null || !xfrm.isSetFlipV()) ? false : xfrm.getFlipV();\r
- }\r
-\r
-\r
- /**\r
- * Get default line properties defined in the theme (if any).\r
- * Used internally to resolve shape properties.\r
- *\r
- * @return line properties from the theme of null\r
- */\r
- CTLineProperties getDefaultLineProperties() {\r
- CTShapeStyle style = getSpStyle();\r
- if (style == null) return null;\r
- CTStyleMatrixReference lnRef = style.getLnRef();\r
- if (lnRef == null) return null;\r
- // 1-based index of a line style within the style matrix\r
- int idx = (int)lnRef.getIdx();\r
-\r
- XSLFTheme theme = getSheet().getTheme();\r
- if (theme == null) return null;\r
- CTBaseStyles styles = theme.getXmlObject().getThemeElements();\r
- if (styles == null) return null;\r
- CTStyleMatrix styleMatrix = styles.getFmtScheme();\r
- if (styleMatrix == null) return null;\r
- CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();\r
- if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;\r
-\r
- return lineStyles.getLnArray(idx - 1);\r
- }\r
-\r
- /**\r
- * @param color the color to paint the shape outline.\r
- * A <code>null</code> value turns off the shape outline.\r
- */\r
- public void setLineColor(Color color) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
-\r
- if (ln.isSetSolidFill()) {\r
- ln.unsetSolidFill();\r
- }\r
- if (ln.isSetGradFill()) {\r
- ln.unsetGradFill();\r
- }\r
- if (ln.isSetPattFill()) {\r
- ln.unsetPattFill();\r
- }\r
- if (ln.isSetNoFill()) {\r
- ln.unsetNoFill();\r
- }\r
-\r
- \r
- if (color == null) {\r
- ln.addNewNoFill();\r
- } else {\r
- CTSolidColorFillProperties fill = ln.addNewSolidFill();\r
- XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());\r
- col.setColor(color);\r
- }\r
- }\r
-\r
- /**\r
- *\r
- * @return the color of the shape outline or <code>null</code>\r
- * if outline is turned off\r
- */\r
- public Color getLineColor() {\r
- PaintStyle ps = getLinePaint();\r
- if (ps instanceof SolidPaint) {\r
- return ((SolidPaint)ps).getSolidColor().getColor();\r
- }\r
- return null;\r
- }\r
-\r
- protected PaintStyle getLinePaint() {\r
- XSLFSheet sheet = getSheet();\r
- final XSLFTheme theme = sheet.getTheme();\r
- PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {\r
- public boolean fetch(XSLFShape shape) {\r
- CTLineProperties spPr = getLn(shape, false);\r
- XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(spPr);\r
- PackagePart pp = shape.getSheet().getPackagePart();\r
- PaintStyle paint = selectPaint(fp, null, pp, theme);\r
- if (paint != null) {\r
- setValue(paint);\r
- return true;\r
- }\r
-\r
- CTShapeStyle style = shape.getSpStyle();\r
- if (style != null) {\r
- fp = XSLFPropertiesDelegate.getFillDelegate(style.getLnRef());\r
- paint = selectPaint(fp, null, pp, theme);\r
- }\r
- if (paint != null) {\r
- setValue(paint);\r
- return true;\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- PaintStyle paint = fetcher.getValue();\r
- if (paint != null) return paint;\r
-\r
- // line color was not found, check if it is defined in the theme\r
- CTShapeStyle style = getSpStyle();\r
- if (style == null) return null;\r
-\r
- // get a reference to a line style within the style matrix.\r
- CTStyleMatrixReference lnRef = style.getLnRef();\r
- int idx = (int)lnRef.getIdx();\r
- CTSchemeColor phClr = lnRef.getSchemeClr();\r
- if(idx > 0){\r
- CTLineProperties props = theme.getXmlObject().getThemeElements().getFmtScheme().getLnStyleLst().getLnArray(idx - 1);\r
- XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);\r
- PackagePart pp = sheet.getPackagePart();\r
- paint = selectPaint(fp, phClr, pp, theme);\r
- }\r
-\r
- return paint;\r
- }\r
-\r
- /**\r
- *\r
- * @param width line width in points. <code>0</code> means no line\r
- */\r
- public void setLineWidth(double width) {\r
- CTLineProperties lnPr = getLn(this, true);\r
- if (lnPr == null) {\r
- return;\r
- }\r
- \r
- if (width == 0.) {\r
- if (lnPr.isSetW()) {\r
- lnPr.unsetW();\r
- }\r
- if (!lnPr.isSetNoFill()) {\r
- lnPr.addNewNoFill();\r
- }\r
- if (lnPr.isSetSolidFill()) {\r
- lnPr.unsetSolidFill();\r
- }\r
- if (lnPr.isSetGradFill()) {\r
- lnPr.unsetGradFill();\r
- }\r
- if (lnPr.isSetPattFill()) {\r
- lnPr.unsetPattFill();\r
- }\r
- } else {\r
- if (lnPr.isSetNoFill()) {\r
- lnPr.unsetNoFill();\r
- }\r
-\r
- lnPr.setW(Units.toEMU(width));\r
- }\r
- }\r
-\r
- /**\r
- * @return line width in points. <code>0</code> means no line.\r
- */\r
- public double getLineWidth() {\r
- PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {\r
- public boolean fetch(XSLFShape shape) {\r
- CTLineProperties ln = getLn(shape, false);\r
- if (ln != null) {\r
- if (ln.isSetNoFill()) {\r
- setValue(0.);\r
- return true;\r
- }\r
-\r
- if (ln.isSetW()) {\r
- setValue(Units.toPoints(ln.getW()));\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- double lineWidth = 0;\r
- if (fetcher.getValue() == null) {\r
- CTLineProperties defaultLn = getDefaultLineProperties();\r
- if (defaultLn != null) {\r
- if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());\r
- }\r
- } else {\r
- lineWidth = fetcher.getValue();\r
- }\r
-\r
- return lineWidth;\r
- }\r
-\r
-\r
- /**\r
- * @param compound set the line compound style\r
- */\r
- public void setLineCompound(LineCompound compound) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- if (compound == null) {\r
- if (ln.isSetCmpd()) {\r
- ln.unsetCmpd();\r
- }\r
- } else {\r
- STCompoundLine.Enum xCmpd;\r
- switch (compound) {\r
- default:\r
- case SINGLE:\r
- xCmpd = STCompoundLine.SNG;\r
- break;\r
- case DOUBLE:\r
- xCmpd = STCompoundLine.DBL;\r
- break;\r
- case THICK_THIN:\r
- xCmpd = STCompoundLine.THICK_THIN;\r
- break;\r
- case THIN_THICK:\r
- xCmpd = STCompoundLine.THIN_THICK;\r
- break;\r
- case TRIPLE:\r
- xCmpd = STCompoundLine.TRI;\r
- break;\r
- }\r
- ln.setCmpd(xCmpd);\r
- }\r
- }\r
-\r
- /**\r
- * @return the line compound\r
- */\r
- public LineCompound getLineCompound() {\r
- PropertyFetcher<Integer> fetcher = new PropertyFetcher<Integer>() {\r
- public boolean fetch(XSLFShape shape) {\r
- CTLineProperties ln = getLn(shape, false);\r
- if (ln != null) {\r
- STCompoundLine.Enum stCmpd = ln.getCmpd();\r
- if (stCmpd != null) {\r
- setValue(stCmpd.intValue());\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- Integer cmpd = fetcher.getValue();\r
- if (cmpd == null) {\r
- CTLineProperties defaultLn = getDefaultLineProperties();\r
- if (defaultLn != null && defaultLn.isSetCmpd()) {\r
- switch (defaultLn.getCmpd().intValue()) {\r
- default:\r
- case STCompoundLine.INT_SNG:\r
- return LineCompound.SINGLE;\r
- case STCompoundLine.INT_DBL:\r
- return LineCompound.DOUBLE;\r
- case STCompoundLine.INT_THICK_THIN:\r
- return LineCompound.THICK_THIN;\r
- case STCompoundLine.INT_THIN_THICK:\r
- return LineCompound.THIN_THICK;\r
- case STCompoundLine.INT_TRI:\r
- return LineCompound.TRIPLE;\r
- }\r
- }\r
- }\r
-\r
- return null;\r
- }\r
-\r
- /**\r
- *\r
- * @param dash a preset line dashing scheme to stroke thr shape outline\r
- */\r
- public void setLineDash(LineDash dash) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- if (dash == null) {\r
- if (ln.isSetPrstDash()) {\r
- ln.unsetPrstDash();\r
- }\r
- } else {\r
- CTPresetLineDashProperties ldp = ln.isSetPrstDash() ? ln.getPrstDash() : ln.addNewPrstDash();\r
- ldp.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return a preset line dashing scheme to stroke the shape outline\r
- */\r
- public LineDash getLineDash() {\r
-\r
- PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>() {\r
- public boolean fetch(XSLFShape shape) {\r
- CTLineProperties ln = getLn(shape, false);\r
- if (ln == null || !ln.isSetPrstDash()) {\r
- return false;\r
- }\r
-\r
- setValue(LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue()));\r
- return true;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- LineDash dash = fetcher.getValue();\r
- if (dash == null) {\r
- CTLineProperties defaultLn = getDefaultLineProperties();\r
- if (defaultLn != null && defaultLn.isSetPrstDash()) {\r
- dash = LineDash.fromOoxmlId(defaultLn.getPrstDash().getVal().intValue());\r
- }\r
- }\r
- return dash;\r
- }\r
-\r
- /**\r
- *\r
- * @param cap the line end cap style\r
- */\r
- public void setLineCap(LineCap cap) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- \r
- if (cap == null) {\r
- if (ln.isSetCap()) {\r
- ln.unsetCap();\r
- }\r
- } else {\r
- ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- *\r
- * @return the line end cap style\r
- */\r
- public LineCap getLineCap() {\r
- PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>() {\r
- public boolean fetch(XSLFShape shape) {\r
- CTLineProperties ln = getLn(shape, false);\r
- if (ln != null && ln.isSetCap()) {\r
- setValue(LineCap.fromOoxmlId(ln.getCap().intValue()));\r
- return true;\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- LineCap cap = fetcher.getValue();\r
- if (cap == null) {\r
- CTLineProperties defaultLn = getDefaultLineProperties();\r
- if (defaultLn != null && defaultLn.isSetCap()) {\r
- cap = LineCap.fromOoxmlId(defaultLn.getCap().intValue());\r
- }\r
- }\r
- return cap;\r
- }\r
-\r
- @Override\r
- public void setFillColor(Color color) {\r
- XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(getShapeProperties());\r
- if (fp == null) {\r
- return;\r
- }\r
- if (color == null) {\r
- if (fp.isSetSolidFill()) {\r
- fp.unsetSolidFill();\r
- }\r
- \r
- if (fp.isSetGradFill()) {\r
- fp.unsetGradFill();\r
- }\r
-\r
- if (fp.isSetPattFill()) {\r
- fp.unsetGradFill();\r
- }\r
- \r
- if (fp.isSetBlipFill()) {\r
- fp.unsetBlipFill();\r
- }\r
- \r
- if (!fp.isSetNoFill()) {\r
- fp.addNewNoFill();\r
- }\r
- } else {\r
- if (fp.isSetNoFill()) {\r
- fp.unsetNoFill();\r
- }\r
-\r
- CTSolidColorFillProperties fill = fp.isSetSolidFill() ? fp.getSolidFill() : fp.addNewSolidFill();\r
- \r
- XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());\r
- col.setColor(color);\r
- }\r
- }\r
-\r
- @Override\r
- public Color getFillColor() {\r
- PaintStyle ps = getFillPaint();\r
- if (ps instanceof SolidPaint) {\r
- return DrawPaint.applyColorTransform(((SolidPaint)ps).getSolidColor());\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * @return shadow of this shape or null if shadow is disabled\r
- */\r
- public XSLFShadow getShadow() {\r
- PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>() {\r
- public boolean fetch(XSLFShape shape) {\r
- XSLFEffectProperties ep = XSLFPropertiesDelegate.getEffectDelegate(shape.getShapeProperties());\r
- if (ep != null && ep.isSetEffectLst()) {\r
- CTOuterShadowEffect obj = ep.getEffectLst().getOuterShdw();\r
- setValue(obj == null ? NO_SHADOW : obj);\r
- return true;\r
- }\r
- return false;\r
- }\r
- };\r
- fetchShapeProperty(fetcher);\r
-\r
- CTOuterShadowEffect obj = fetcher.getValue();\r
- if (obj == null) {\r
- // fill color was not found, check if it is defined in the theme\r
- CTShapeStyle style = getSpStyle();\r
- if (style != null && style.getEffectRef() != null) {\r
- // 1-based index of a shadow style within the style matrix\r
- int idx = (int) style.getEffectRef().getIdx();\r
- if(idx != 0) {\r
- CTStyleMatrix styleMatrix = getSheet().getTheme().getXmlObject().getThemeElements().getFmtScheme();\r
- CTEffectStyleItem ef = styleMatrix.getEffectStyleLst().getEffectStyleArray(idx - 1);\r
- obj = ef.getEffectLst().getOuterShdw();\r
- }\r
- }\r
- }\r
- return (obj == null || obj == NO_SHADOW) ? null : new XSLFShadow(obj, this);\r
- }\r
-\r
- /**\r
- *\r
- * @return definition of the shape geometry\r
- */\r
- public CustomGeometry getGeometry() {\r
- XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());\r
- \r
- if (gp == null) {\r
- return null;\r
- }\r
- \r
- CustomGeometry geom;\r
- PresetGeometries dict = PresetGeometries.getInstance();\r
- if(gp.isSetPrstGeom()){\r
- String name = gp.getPrstGeom().getPrst().toString();\r
- geom = dict.get(name);\r
- if(geom == null) {\r
- throw new IllegalStateException("Unknown shape geometry: " + name + ", available geometries are: " + dict.keySet());\r
- }\r
- } else if (gp.isSetCustGeom()){\r
- XMLStreamReader staxReader = gp.getCustGeom().newXMLStreamReader();\r
- geom = PresetGeometries.convertCustomGeometry(staxReader);\r
+/*
+ * ====================================================================
+ * 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 java.awt.Color;
+import java.awt.geom.Rectangle2D;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.sl.draw.DrawPaint;
+import org.apache.poi.sl.draw.geom.CustomGeometry;
+import org.apache.poi.sl.draw.geom.Guide;
+import org.apache.poi.sl.draw.geom.PresetGeometries;
+import org.apache.poi.sl.usermodel.FillStyle;
+import org.apache.poi.sl.usermodel.LineDecoration;
+import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
+import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
+import org.apache.poi.sl.usermodel.PaintStyle;
+import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
+import org.apache.poi.sl.usermodel.Placeholder;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.apache.poi.sl.usermodel.SimpleShape;
+import org.apache.poi.sl.usermodel.StrokeStyle;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCap;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineCompound;
+import org.apache.poi.sl.usermodel.StrokeStyle.LineDash;
+import org.apache.poi.util.Beta;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.poi.util.Units;
+import org.apache.poi.xslf.model.PropertyFetcher;
+import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFEffectProperties;
+import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFFillProperties;
+import org.apache.poi.xslf.usermodel.XSLFPropertiesDelegate.XSLFGeometryProperties;
+import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBaseStyles;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineEndProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTLineStyleList;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTOuterShadowEffect;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetGeometry2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTPresetLineDashProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSchemeColor;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeStyle;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTSolidColorFillProperties;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrix;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTStyleMatrixReference;
+import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
+import org.openxmlformats.schemas.drawingml.x2006.main.STCompoundLine;
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndLength;
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndType;
+import org.openxmlformats.schemas.drawingml.x2006.main.STLineEndWidth;
+import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
+import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
+import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
+
+/**
+ * Represents a single (non-group) shape in a .pptx slide show
+ */
+@Beta
+public abstract class XSLFSimpleShape extends XSLFShape
+ implements SimpleShape<XSLFShape,XSLFTextParagraph> {
+ private static CTOuterShadowEffect NO_SHADOW = CTOuterShadowEffect.Factory.newInstance();
+ private static final POILogger LOG = POILogFactory.getLogger(XSLFSimpleShape.class);
+
+ /* package */XSLFSimpleShape(XmlObject shape, XSLFSheet sheet) {
+ super(shape,sheet);
+ }
+
+ @Override
+ public void setShapeType(ShapeType type) {
+ XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
+ if (gp == null) {
+ return;
+ }
+ if (gp.isSetCustGeom()) {
+ gp.unsetCustGeom();
+ }
+ CTPresetGeometry2D prst = (gp.isSetPrstGeom()) ? gp.getPrstGeom() : gp.addNewPrstGeom();
+ prst.setPrst(STShapeType.Enum.forInt(type.ooxmlId));
+ }
+
+ @Override
+ public ShapeType getShapeType(){
+ XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
+ if (gp != null && gp.isSetPrstGeom()) {
+ STShapeType.Enum geom = gp.getPrstGeom().getPrst();
+ if (geom != null) {
+ return ShapeType.forId(geom.intValue(), true);
+ }
+ }
+ return null;
+ }
+
+ protected CTTransform2D getXfrm(boolean create) {
+ PropertyFetcher<CTTransform2D> fetcher = new PropertyFetcher<CTTransform2D>() {
+ public boolean fetch(XSLFShape shape) {
+ XmlObject xo = shape.getShapeProperties();
+ if (xo instanceof CTShapeProperties && ((CTShapeProperties)xo).isSetXfrm()) {
+ setValue(((CTShapeProperties)xo).getXfrm());
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ CTTransform2D xfrm = fetcher.getValue();
+ if (!create || xfrm != null) {
+ return xfrm;
+ } else {
+ XmlObject xo = getShapeProperties();
+ if (xo instanceof CTShapeProperties) {
+ return ((CTShapeProperties)xo).addNewXfrm();
+ } else {
+ // ... group shapes have their own getXfrm()
+ LOG.log(POILogger.WARN, getClass().toString()+" doesn't have xfrm element.");
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public Rectangle2D getAnchor() {
+
+ CTTransform2D xfrm = getXfrm(false);
+ if (xfrm == null) {
+ return null;
+ }
+
+ CTPoint2D off = xfrm.getOff();
+ double x = Units.toPoints(off.getX());
+ double y = Units.toPoints(off.getY());
+ CTPositiveSize2D ext = xfrm.getExt();
+ double cx = Units.toPoints(ext.getCx());
+ double cy = Units.toPoints(ext.getCy());
+ return new Rectangle2D.Double(x, y, cx, cy);
+ }
+
+ @Override
+ public void setAnchor(Rectangle2D anchor) {
+ CTTransform2D xfrm = getXfrm(true);
+ if (xfrm == null) {
+ return;
+ }
+ CTPoint2D off = xfrm.isSetOff() ? xfrm.getOff() : xfrm.addNewOff();
+ long x = Units.toEMU(anchor.getX());
+ long y = Units.toEMU(anchor.getY());
+ off.setX(x);
+ off.setY(y);
+ CTPositiveSize2D ext = xfrm.isSetExt() ? xfrm.getExt() : xfrm
+ .addNewExt();
+ long cx = Units.toEMU(anchor.getWidth());
+ long cy = Units.toEMU(anchor.getHeight());
+ ext.setCx(cx);
+ ext.setCy(cy);
+ }
+
+ @Override
+ public void setRotation(double theta) {
+ CTTransform2D xfrm = getXfrm(true);
+ if (xfrm != null) {
+ xfrm.setRot((int) (theta * 60000));
+ }
+ }
+
+ @Override
+ public double getRotation() {
+ CTTransform2D xfrm = getXfrm(false);
+ return (xfrm == null || !xfrm.isSetRot()) ? 0 : (xfrm.getRot() / 60000.d);
+ }
+
+ @Override
+ public void setFlipHorizontal(boolean flip) {
+ CTTransform2D xfrm = getXfrm(true);
+ if (xfrm != null) {
+ xfrm.setFlipH(flip);
+ }
+ }
+
+ @Override
+ public void setFlipVertical(boolean flip) {
+ CTTransform2D xfrm = getXfrm(true);
+ if (xfrm != null) {
+ xfrm.setFlipV(flip);
+ }
+ }
+
+ @Override
+ public boolean getFlipHorizontal() {
+ CTTransform2D xfrm = getXfrm(false);
+ return (xfrm == null || !xfrm.isSetFlipH()) ? false : xfrm.getFlipH();
+ }
+
+ @Override
+ public boolean getFlipVertical() {
+ CTTransform2D xfrm = getXfrm(false);
+ return (xfrm == null || !xfrm.isSetFlipV()) ? false : xfrm.getFlipV();
+ }
+
+
+ /**
+ * Get default line properties defined in the theme (if any).
+ * Used internally to resolve shape properties.
+ *
+ * @return line properties from the theme of null
+ */
+ CTLineProperties getDefaultLineProperties() {
+ CTShapeStyle style = getSpStyle();
+ if (style == null) return null;
+ CTStyleMatrixReference lnRef = style.getLnRef();
+ if (lnRef == null) return null;
+ // 1-based index of a line style within the style matrix
+ int idx = (int)lnRef.getIdx();
+
+ XSLFTheme theme = getSheet().getTheme();
+ if (theme == null) return null;
+ CTBaseStyles styles = theme.getXmlObject().getThemeElements();
+ if (styles == null) return null;
+ CTStyleMatrix styleMatrix = styles.getFmtScheme();
+ if (styleMatrix == null) return null;
+ CTLineStyleList lineStyles = styleMatrix.getLnStyleLst();
+ if (lineStyles == null || lineStyles.sizeOfLnArray() < idx) return null;
+
+ return lineStyles.getLnArray(idx - 1);
+ }
+
+ /**
+ * @param color the color to paint the shape outline.
+ * A <code>null</code> value turns off the shape outline.
+ */
+ public void setLineColor(Color color) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ if (ln.isSetSolidFill()) {
+ ln.unsetSolidFill();
+ }
+ if (ln.isSetGradFill()) {
+ ln.unsetGradFill();
+ }
+ if (ln.isSetPattFill()) {
+ ln.unsetPattFill();
+ }
+ if (ln.isSetNoFill()) {
+ ln.unsetNoFill();
+ }
+
+
+ if (color == null) {
+ ln.addNewNoFill();
+ } else {
+ CTSolidColorFillProperties fill = ln.addNewSolidFill();
+ XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
+ col.setColor(color);
+ }
+ }
+
+ /**
+ *
+ * @return the color of the shape outline or <code>null</code>
+ * if outline is turned off
+ */
+ public Color getLineColor() {
+ PaintStyle ps = getLinePaint();
+ if (ps instanceof SolidPaint) {
+ return ((SolidPaint)ps).getSolidColor().getColor();
+ }
+ return null;
+ }
+
+ protected PaintStyle getLinePaint() {
+ XSLFSheet sheet = getSheet();
+ final XSLFTheme theme = sheet.getTheme();
+ PropertyFetcher<PaintStyle> fetcher = new PropertyFetcher<PaintStyle>() {
+ public boolean fetch(XSLFShape shape) {
+ CTLineProperties spPr = getLn(shape, false);
+ XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(spPr);
+ PackagePart pp = shape.getSheet().getPackagePart();
+ PaintStyle paint = selectPaint(fp, null, pp, theme);
+ if (paint != null) {
+ setValue(paint);
+ return true;
+ }
+
+ CTShapeStyle style = shape.getSpStyle();
+ if (style != null) {
+ fp = XSLFPropertiesDelegate.getFillDelegate(style.getLnRef());
+ paint = selectPaint(fp, null, pp, theme);
+ }
+ if (paint != null) {
+ setValue(paint);
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ PaintStyle paint = fetcher.getValue();
+ if (paint != null) return paint;
+
+ // line color was not found, check if it is defined in the theme
+ CTShapeStyle style = getSpStyle();
+ if (style == null) return null;
+
+ // get a reference to a line style within the style matrix.
+ CTStyleMatrixReference lnRef = style.getLnRef();
+ int idx = (int)lnRef.getIdx();
+ CTSchemeColor phClr = lnRef.getSchemeClr();
+ if(idx > 0){
+ CTLineProperties props = theme.getXmlObject().getThemeElements().getFmtScheme().getLnStyleLst().getLnArray(idx - 1);
+ XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(props);
+ PackagePart pp = sheet.getPackagePart();
+ paint = selectPaint(fp, phClr, pp, theme);
+ }
+
+ return paint;
+ }
+
+ /**
+ *
+ * @param width line width in points. <code>0</code> means no line
+ */
+ public void setLineWidth(double width) {
+ CTLineProperties lnPr = getLn(this, true);
+ if (lnPr == null) {
+ return;
+ }
+
+ if (width == 0.) {
+ if (lnPr.isSetW()) {
+ lnPr.unsetW();
+ }
+ if (!lnPr.isSetNoFill()) {
+ lnPr.addNewNoFill();
+ }
+ if (lnPr.isSetSolidFill()) {
+ lnPr.unsetSolidFill();
+ }
+ if (lnPr.isSetGradFill()) {
+ lnPr.unsetGradFill();
+ }
+ if (lnPr.isSetPattFill()) {
+ lnPr.unsetPattFill();
+ }
+ } else {
+ if (lnPr.isSetNoFill()) {
+ lnPr.unsetNoFill();
+ }
+
+ lnPr.setW(Units.toEMU(width));
+ }
+ }
+
+ /**
+ * @return line width in points. <code>0</code> means no line.
+ */
+ public double getLineWidth() {
+ PropertyFetcher<Double> fetcher = new PropertyFetcher<Double>() {
+ public boolean fetch(XSLFShape shape) {
+ CTLineProperties ln = getLn(shape, false);
+ if (ln != null) {
+ if (ln.isSetNoFill()) {
+ setValue(0.);
+ return true;
+ }
+
+ if (ln.isSetW()) {
+ setValue(Units.toPoints(ln.getW()));
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ double lineWidth = 0;
+ if (fetcher.getValue() == null) {
+ CTLineProperties defaultLn = getDefaultLineProperties();
+ if (defaultLn != null) {
+ if (defaultLn.isSetW()) lineWidth = Units.toPoints(defaultLn.getW());
+ }
+ } else {
+ lineWidth = fetcher.getValue();
+ }
+
+ return lineWidth;
+ }
+
+
+ /**
+ * @param compound set the line compound style
+ */
+ public void setLineCompound(LineCompound compound) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+ if (compound == null) {
+ if (ln.isSetCmpd()) {
+ ln.unsetCmpd();
+ }
+ } else {
+ STCompoundLine.Enum xCmpd;
+ switch (compound) {
+ default:
+ case SINGLE:
+ xCmpd = STCompoundLine.SNG;
+ break;
+ case DOUBLE:
+ xCmpd = STCompoundLine.DBL;
+ break;
+ case THICK_THIN:
+ xCmpd = STCompoundLine.THICK_THIN;
+ break;
+ case THIN_THICK:
+ xCmpd = STCompoundLine.THIN_THICK;
+ break;
+ case TRIPLE:
+ xCmpd = STCompoundLine.TRI;
+ break;
+ }
+ ln.setCmpd(xCmpd);
+ }
+ }
+
+ /**
+ * @return the line compound
+ */
+ public LineCompound getLineCompound() {
+ PropertyFetcher<Integer> fetcher = new PropertyFetcher<Integer>() {
+ public boolean fetch(XSLFShape shape) {
+ CTLineProperties ln = getLn(shape, false);
+ if (ln != null) {
+ STCompoundLine.Enum stCmpd = ln.getCmpd();
+ if (stCmpd != null) {
+ setValue(stCmpd.intValue());
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ Integer cmpd = fetcher.getValue();
+ if (cmpd == null) {
+ CTLineProperties defaultLn = getDefaultLineProperties();
+ if (defaultLn != null && defaultLn.isSetCmpd()) {
+ switch (defaultLn.getCmpd().intValue()) {
+ default:
+ case STCompoundLine.INT_SNG:
+ return LineCompound.SINGLE;
+ case STCompoundLine.INT_DBL:
+ return LineCompound.DOUBLE;
+ case STCompoundLine.INT_THICK_THIN:
+ return LineCompound.THICK_THIN;
+ case STCompoundLine.INT_THIN_THICK:
+ return LineCompound.THIN_THICK;
+ case STCompoundLine.INT_TRI:
+ return LineCompound.TRIPLE;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ *
+ * @param dash a preset line dashing scheme to stroke thr shape outline
+ */
+ public void setLineDash(LineDash dash) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+ if (dash == null) {
+ if (ln.isSetPrstDash()) {
+ ln.unsetPrstDash();
+ }
+ } else {
+ CTPresetLineDashProperties ldp = ln.isSetPrstDash() ? ln.getPrstDash() : ln.addNewPrstDash();
+ ldp.setVal(STPresetLineDashVal.Enum.forInt(dash.ooxmlId));
+ }
+ }
+
+ /**
+ * @return a preset line dashing scheme to stroke the shape outline
+ */
+ public LineDash getLineDash() {
+
+ PropertyFetcher<LineDash> fetcher = new PropertyFetcher<LineDash>() {
+ public boolean fetch(XSLFShape shape) {
+ CTLineProperties ln = getLn(shape, false);
+ if (ln == null || !ln.isSetPrstDash()) {
+ return false;
+ }
+
+ setValue(LineDash.fromOoxmlId(ln.getPrstDash().getVal().intValue()));
+ return true;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ LineDash dash = fetcher.getValue();
+ if (dash == null) {
+ CTLineProperties defaultLn = getDefaultLineProperties();
+ if (defaultLn != null && defaultLn.isSetPrstDash()) {
+ dash = LineDash.fromOoxmlId(defaultLn.getPrstDash().getVal().intValue());
+ }
+ }
+ return dash;
+ }
+
+ /**
+ *
+ * @param cap the line end cap style
+ */
+ public void setLineCap(LineCap cap) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ if (cap == null) {
+ if (ln.isSetCap()) {
+ ln.unsetCap();
+ }
+ } else {
+ ln.setCap(STLineCap.Enum.forInt(cap.ooxmlId));
+ }
+ }
+
+ /**
+ *
+ * @return the line end cap style
+ */
+ public LineCap getLineCap() {
+ PropertyFetcher<LineCap> fetcher = new PropertyFetcher<LineCap>() {
+ public boolean fetch(XSLFShape shape) {
+ CTLineProperties ln = getLn(shape, false);
+ if (ln != null && ln.isSetCap()) {
+ setValue(LineCap.fromOoxmlId(ln.getCap().intValue()));
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ LineCap cap = fetcher.getValue();
+ if (cap == null) {
+ CTLineProperties defaultLn = getDefaultLineProperties();
+ if (defaultLn != null && defaultLn.isSetCap()) {
+ cap = LineCap.fromOoxmlId(defaultLn.getCap().intValue());
+ }
+ }
+ return cap;
+ }
+
+ @Override
+ public void setFillColor(Color color) {
+ XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(getShapeProperties());
+ if (fp == null) {
+ return;
+ }
+ if (color == null) {
+ if (fp.isSetSolidFill()) {
+ fp.unsetSolidFill();
+ }
+
+ if (fp.isSetGradFill()) {
+ fp.unsetGradFill();
+ }
+
+ if (fp.isSetPattFill()) {
+ fp.unsetGradFill();
+ }
+
+ if (fp.isSetBlipFill()) {
+ fp.unsetBlipFill();
+ }
+
+ if (!fp.isSetNoFill()) {
+ fp.addNewNoFill();
+ }
+ } else {
+ if (fp.isSetNoFill()) {
+ fp.unsetNoFill();
+ }
+
+ CTSolidColorFillProperties fill = fp.isSetSolidFill() ? fp.getSolidFill() : fp.addNewSolidFill();
+
+ XSLFColor col = new XSLFColor(fill, getSheet().getTheme(), fill.getSchemeClr());
+ col.setColor(color);
+ }
+ }
+
+ @Override
+ public Color getFillColor() {
+ PaintStyle ps = getFillPaint();
+ if (ps instanceof SolidPaint) {
+ return DrawPaint.applyColorTransform(((SolidPaint)ps).getSolidColor());
+ }
+ return null;
+ }
+
+ /**
+ * @return shadow of this shape or null if shadow is disabled
+ */
+ public XSLFShadow getShadow() {
+ PropertyFetcher<CTOuterShadowEffect> fetcher = new PropertyFetcher<CTOuterShadowEffect>() {
+ public boolean fetch(XSLFShape shape) {
+ XSLFEffectProperties ep = XSLFPropertiesDelegate.getEffectDelegate(shape.getShapeProperties());
+ if (ep != null && ep.isSetEffectLst()) {
+ CTOuterShadowEffect obj = ep.getEffectLst().getOuterShdw();
+ setValue(obj == null ? NO_SHADOW : obj);
+ return true;
+ }
+ return false;
+ }
+ };
+ fetchShapeProperty(fetcher);
+
+ CTOuterShadowEffect obj = fetcher.getValue();
+ if (obj == null) {
+ // fill color was not found, check if it is defined in the theme
+ CTShapeStyle style = getSpStyle();
+ if (style != null && style.getEffectRef() != null) {
+ // 1-based index of a shadow style within the style matrix
+ int idx = (int) style.getEffectRef().getIdx();
+ if(idx != 0) {
+ CTStyleMatrix styleMatrix = getSheet().getTheme().getXmlObject().getThemeElements().getFmtScheme();
+ CTEffectStyleItem ef = styleMatrix.getEffectStyleLst().getEffectStyleArray(idx - 1);
+ obj = ef.getEffectLst().getOuterShdw();
+ }
+ }
+ }
+ return (obj == null || obj == NO_SHADOW) ? null : new XSLFShadow(obj, this);
+ }
+
+ /**
+ *
+ * @return definition of the shape geometry
+ */
+ public CustomGeometry getGeometry() {
+ XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
+
+ if (gp == null) {
+ return null;
+ }
+
+ CustomGeometry geom;
+ PresetGeometries dict = PresetGeometries.getInstance();
+ if(gp.isSetPrstGeom()){
+ String name = gp.getPrstGeom().getPrst().toString();
+ geom = dict.get(name);
+ if(geom == null) {
+ throw new IllegalStateException("Unknown shape geometry: " + name + ", available geometries are: " + dict.keySet());
+ }
+ } else if (gp.isSetCustGeom()){
+ XMLStreamReader staxReader = gp.getCustGeom().newXMLStreamReader();
+ geom = PresetGeometries.convertCustomGeometry(staxReader);
try {
staxReader.close();
- }\r
+ }
catch (XMLStreamException e) {
LOG.log(POILogger.WARN,
"An error occurred while closing a Custom Geometry XML Stream Reader: " + e.getMessage());
- }\r
- } else {\r
- geom = dict.get("rect");\r
- }\r
- return geom;\r
- }\r
-\r
- @Override\r
- void copy(XSLFShape sh){\r
- super.copy(sh);\r
-\r
- XSLFSimpleShape s = (XSLFSimpleShape)sh;\r
-\r
- Color srsSolidFill = s.getFillColor();\r
- Color tgtSoliFill = getFillColor();\r
- if(srsSolidFill != null && !srsSolidFill.equals(tgtSoliFill)){\r
- setFillColor(srsSolidFill);\r
- }\r
-\r
- XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(getShapeProperties());\r
- if(fp != null && fp.isSetBlipFill()){\r
- CTBlip blip = fp.getBlipFill().getBlip();\r
- String blipId = blip.getEmbed();\r
-\r
- String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());\r
- blip.setEmbed(relId);\r
- }\r
-\r
- Color srcLineColor = s.getLineColor();\r
- Color tgtLineColor = getLineColor();\r
- if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {\r
- setLineColor(srcLineColor);\r
- }\r
-\r
- double srcLineWidth = s.getLineWidth();\r
- double tgtLineWidth = getLineWidth();\r
- if(srcLineWidth != tgtLineWidth) {\r
- setLineWidth(srcLineWidth);\r
- }\r
-\r
- LineDash srcLineDash = s.getLineDash();\r
- LineDash tgtLineDash = getLineDash();\r
- if(srcLineDash != null && srcLineDash != tgtLineDash) {\r
- setLineDash(srcLineDash);\r
- }\r
-\r
- LineCap srcLineCap = s.getLineCap();\r
- LineCap tgtLineCap = getLineCap();\r
- if(srcLineCap != null && srcLineCap != tgtLineCap) {\r
- setLineCap(srcLineCap);\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Specifies the line end decoration, such as a triangle or arrowhead.\r
- * \r
- * @param style the line end docoration style\r
- */\r
- public void setLineHeadDecoration(DecorationShape style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetType()) {\r
- lnEnd.unsetType();\r
- }\r
- } else {\r
- lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration shape\r
- */\r
- public DecorationShape getLineHeadDecoration() {\r
- CTLineProperties ln = getLn(this, false);\r
- DecorationShape ds = DecorationShape.NONE;\r
- if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetType()) {\r
- ds = DecorationShape.fromOoxmlId(ln.getHeadEnd().getType().intValue());\r
- }\r
- return ds;\r
- }\r
-\r
- /**\r
- * specifies decoration width of the head of a line.\r
- * \r
- * @param style the decoration width \r
- */\r
- public void setLineHeadWidth(DecorationSize style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetW()) {\r
- lnEnd.unsetW();\r
- }\r
- } else {\r
- lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration width\r
- */\r
- public DecorationSize getLineHeadWidth() {\r
- CTLineProperties ln = getLn(this, false);\r
- DecorationSize ds = DecorationSize.MEDIUM;\r
- if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetW()) {\r
- ds = DecorationSize.fromOoxmlId(ln.getHeadEnd().getW().intValue());\r
- }\r
- return ds;\r
- }\r
-\r
- /**\r
- * Specifies the line end width in relation to the line width.\r
- */\r
- public void setLineHeadLength(DecorationSize style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- \r
- CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetLen()) {\r
- lnEnd.unsetLen();\r
- }\r
- } else {\r
- lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration length\r
- */\r
- public DecorationSize getLineHeadLength() {\r
- CTLineProperties ln = getLn(this, false);\r
- \r
- DecorationSize ds = DecorationSize.MEDIUM;\r
- if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetLen()) {\r
- ds = DecorationSize.fromOoxmlId(ln.getHeadEnd().getLen().intValue());\r
- }\r
- return ds; \r
- }\r
-\r
- /**\r
- * Specifies the line end decoration, such as a triangle or arrowhead.\r
- */\r
- public void setLineTailDecoration(DecorationShape style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
-\r
- CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetType()) {\r
- lnEnd.unsetType();\r
- }\r
- } else {\r
- lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration shape\r
- */\r
- public DecorationShape getLineTailDecoration() {\r
- CTLineProperties ln = getLn(this, false);\r
- \r
- DecorationShape ds = DecorationShape.NONE;\r
- if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetType()) {\r
- ds = DecorationShape.fromOoxmlId(ln.getTailEnd().getType().intValue());\r
- }\r
- return ds;\r
- }\r
-\r
- /**\r
- * specifies decorations which can be added to the tail of a line.\r
- */\r
- public void setLineTailWidth(DecorationSize style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- \r
- CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetW()) {\r
- lnEnd.unsetW();\r
- }\r
- } else {\r
- lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration width\r
- */\r
- public DecorationSize getLineTailWidth() {\r
- CTLineProperties ln = getLn(this, false);\r
- DecorationSize ds = DecorationSize.MEDIUM;\r
- if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetW()) {\r
- ds = DecorationSize.fromOoxmlId(ln.getTailEnd().getW().intValue());\r
- }\r
- return ds;\r
- }\r
-\r
- /**\r
- * Specifies the line end width in relation to the line width.\r
- */\r
- public void setLineTailLength(DecorationSize style) {\r
- CTLineProperties ln = getLn(this, true);\r
- if (ln == null) {\r
- return;\r
- }\r
- \r
- CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\r
- if (style == null) {\r
- if (lnEnd.isSetLen()) {\r
- lnEnd.unsetLen();\r
- }\r
- } else {\r
- lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));\r
- }\r
- }\r
-\r
- /**\r
- * @return the line end decoration length\r
- */\r
- public DecorationSize getLineTailLength() {\r
- CTLineProperties ln = getLn(this, false);\r
- \r
- DecorationSize ds = DecorationSize.MEDIUM;\r
- if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetLen()) {\r
- ds = DecorationSize.fromOoxmlId(ln.getTailEnd().getLen().intValue());\r
- }\r
- return ds; \r
- }\r
-\r
- public boolean isPlaceholder() {\r
- CTPlaceholder ph = getCTPlaceholder();\r
- return ph != null;\r
- }\r
-\r
- public Guide getAdjustValue(String name) {\r
- XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());\r
- \r
- if (gp != null && gp.isSetPrstGeom() && gp.getPrstGeom().isSetAvLst()) {\r
- for (CTGeomGuide g : gp.getPrstGeom().getAvLst().getGdArray()) {\r
- if (g.getName().equals(name)) {\r
- return new Guide(g.getName(), g.getFmla());\r
- }\r
- }\r
- }\r
-\r
- return null;\r
- }\r
-\r
- public LineDecoration getLineDecoration() {\r
- return new LineDecoration() {\r
- public DecorationShape getHeadShape() {\r
- return getLineHeadDecoration();\r
- }\r
-\r
- public DecorationSize getHeadWidth() {\r
- return getLineHeadWidth();\r
- }\r
-\r
- public DecorationSize getHeadLength() {\r
- return getLineHeadLength();\r
- }\r
-\r
- public DecorationShape getTailShape() {\r
- return getLineTailDecoration();\r
- }\r
-\r
- public DecorationSize getTailWidth() {\r
- return getLineTailWidth();\r
- }\r
-\r
- public DecorationSize getTailLength() {\r
- return getLineTailLength();\r
- }\r
- };\r
- }\r
-\r
- /**\r
- * fetch shape fill as a java.awt.Paint\r
- *\r
- * @return either Color or GradientPaint or TexturePaint or null\r
- */\r
- public FillStyle getFillStyle() {\r
- return new FillStyle() {\r
- public PaintStyle getPaint() {\r
- return XSLFSimpleShape.this.getFillPaint();\r
- }\r
- };\r
- }\r
-\r
- public StrokeStyle getStrokeStyle() {\r
- return new StrokeStyle() {\r
- public PaintStyle getPaint() {\r
- return XSLFSimpleShape.this.getLinePaint();\r
- }\r
-\r
- public LineCap getLineCap() {\r
- return XSLFSimpleShape.this.getLineCap();\r
- }\r
-\r
- public LineDash getLineDash() {\r
- return XSLFSimpleShape.this.getLineDash();\r
- }\r
-\r
- public double getLineWidth() {\r
- return XSLFSimpleShape.this.getLineWidth();\r
- }\r
-\r
- public LineCompound getLineCompound() {\r
- return XSLFSimpleShape.this.getLineCompound();\r
- }\r
-\r
- };\r
- }\r
-\r
- @Override\r
- public void setStrokeStyle(Object... styles) {\r
- if (styles.length == 0) {\r
- // remove stroke\r
- setLineColor(null);\r
- return;\r
- }\r
- \r
- // TODO: handle PaintStyle\r
- for (Object st : styles) {\r
- if (st instanceof Number) {\r
- setLineWidth(((Number)st).doubleValue());\r
- } else if (st instanceof LineCap) {\r
- setLineCap((LineCap)st);\r
- } else if (st instanceof LineDash) {\r
- setLineDash((LineDash)st);\r
- } else if (st instanceof LineCompound) {\r
- setLineCompound((LineCompound)st);\r
- } else if (st instanceof Color) {\r
- setLineColor((Color)st);\r
- }\r
- }\r
- }\r
- \r
- @Override\r
- public void setPlaceholder(Placeholder placeholder) {\r
- super.setPlaceholder(placeholder);\r
- }\r
- \r
- @Override\r
- public XSLFHyperlink getHyperlink() {\r
- CTNonVisualDrawingProps cNvPr = getCNvPr();\r
- if (!cNvPr.isSetHlinkClick()) {\r
- return null;\r
- }\r
- return new XSLFHyperlink(cNvPr.getHlinkClick(), getSheet());\r
- }\r
- \r
- @Override\r
- public XSLFHyperlink createHyperlink() {\r
- XSLFHyperlink hl = getHyperlink();\r
- if (hl == null) {\r
- CTNonVisualDrawingProps cNvPr = getCNvPr();\r
- hl = new XSLFHyperlink(cNvPr.addNewHlinkClick(), getSheet());\r
- }\r
- return hl;\r
- }\r
-\r
- private static CTLineProperties getLn(XSLFShape shape, boolean create) {\r
- XmlObject pr = shape.getShapeProperties();\r
- if (!(pr instanceof CTShapeProperties)) {\r
- LOG.log(POILogger.WARN, shape.getClass().toString()+" doesn't have line properties");\r
- return null;\r
- }\r
- \r
- CTShapeProperties spr = (CTShapeProperties)pr;\r
- return (spr.isSetLn() || !create) ? spr.getLn() : spr.addNewLn();\r
- }\r
+ }
+ } else {
+ geom = dict.get("rect");
+ }
+ return geom;
+ }
+
+ @Override
+ void copy(XSLFShape sh){
+ super.copy(sh);
+
+ XSLFSimpleShape s = (XSLFSimpleShape)sh;
+
+ Color srsSolidFill = s.getFillColor();
+ Color tgtSoliFill = getFillColor();
+ if(srsSolidFill != null && !srsSolidFill.equals(tgtSoliFill)){
+ setFillColor(srsSolidFill);
+ }
+
+ XSLFFillProperties fp = XSLFPropertiesDelegate.getFillDelegate(getShapeProperties());
+ if(fp != null && fp.isSetBlipFill()){
+ CTBlip blip = fp.getBlipFill().getBlip();
+ String blipId = blip.getEmbed();
+
+ String relId = getSheet().importBlip(blipId, s.getSheet().getPackagePart());
+ blip.setEmbed(relId);
+ }
+
+ Color srcLineColor = s.getLineColor();
+ Color tgtLineColor = getLineColor();
+ if(srcLineColor != null && !srcLineColor.equals(tgtLineColor)) {
+ setLineColor(srcLineColor);
+ }
+
+ double srcLineWidth = s.getLineWidth();
+ double tgtLineWidth = getLineWidth();
+ if(srcLineWidth != tgtLineWidth) {
+ setLineWidth(srcLineWidth);
+ }
+
+ LineDash srcLineDash = s.getLineDash();
+ LineDash tgtLineDash = getLineDash();
+ if(srcLineDash != null && srcLineDash != tgtLineDash) {
+ setLineDash(srcLineDash);
+ }
+
+ LineCap srcLineCap = s.getLineCap();
+ LineCap tgtLineCap = getLineCap();
+ if(srcLineCap != null && srcLineCap != tgtLineCap) {
+ setLineCap(srcLineCap);
+ }
+
+ }
+
+ /**
+ * Specifies the line end decoration, such as a triangle or arrowhead.
+ *
+ * @param style the line end docoration style
+ */
+ public void setLineHeadDecoration(DecorationShape style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+ CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
+ if (style == null) {
+ if (lnEnd.isSetType()) {
+ lnEnd.unsetType();
+ }
+ } else {
+ lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration shape
+ */
+ public DecorationShape getLineHeadDecoration() {
+ CTLineProperties ln = getLn(this, false);
+ DecorationShape ds = DecorationShape.NONE;
+ if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetType()) {
+ ds = DecorationShape.fromOoxmlId(ln.getHeadEnd().getType().intValue());
+ }
+ return ds;
+ }
+
+ /**
+ * specifies decoration width of the head of a line.
+ *
+ * @param style the decoration width
+ */
+ public void setLineHeadWidth(DecorationSize style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+ CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
+ if (style == null) {
+ if (lnEnd.isSetW()) {
+ lnEnd.unsetW();
+ }
+ } else {
+ lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration width
+ */
+ public DecorationSize getLineHeadWidth() {
+ CTLineProperties ln = getLn(this, false);
+ DecorationSize ds = DecorationSize.MEDIUM;
+ if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetW()) {
+ ds = DecorationSize.fromOoxmlId(ln.getHeadEnd().getW().intValue());
+ }
+ return ds;
+ }
+
+ /**
+ * Specifies the line end width in relation to the line width.
+ */
+ public void setLineHeadLength(DecorationSize style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
+ if (style == null) {
+ if (lnEnd.isSetLen()) {
+ lnEnd.unsetLen();
+ }
+ } else {
+ lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration length
+ */
+ public DecorationSize getLineHeadLength() {
+ CTLineProperties ln = getLn(this, false);
+
+ DecorationSize ds = DecorationSize.MEDIUM;
+ if (ln != null && ln.isSetHeadEnd() && ln.getHeadEnd().isSetLen()) {
+ ds = DecorationSize.fromOoxmlId(ln.getHeadEnd().getLen().intValue());
+ }
+ return ds;
+ }
+
+ /**
+ * Specifies the line end decoration, such as a triangle or arrowhead.
+ */
+ public void setLineTailDecoration(DecorationShape style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
+ if (style == null) {
+ if (lnEnd.isSetType()) {
+ lnEnd.unsetType();
+ }
+ } else {
+ lnEnd.setType(STLineEndType.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration shape
+ */
+ public DecorationShape getLineTailDecoration() {
+ CTLineProperties ln = getLn(this, false);
+
+ DecorationShape ds = DecorationShape.NONE;
+ if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetType()) {
+ ds = DecorationShape.fromOoxmlId(ln.getTailEnd().getType().intValue());
+ }
+ return ds;
+ }
+
+ /**
+ * specifies decorations which can be added to the tail of a line.
+ */
+ public void setLineTailWidth(DecorationSize style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
+ if (style == null) {
+ if (lnEnd.isSetW()) {
+ lnEnd.unsetW();
+ }
+ } else {
+ lnEnd.setW(STLineEndWidth.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration width
+ */
+ public DecorationSize getLineTailWidth() {
+ CTLineProperties ln = getLn(this, false);
+ DecorationSize ds = DecorationSize.MEDIUM;
+ if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetW()) {
+ ds = DecorationSize.fromOoxmlId(ln.getTailEnd().getW().intValue());
+ }
+ return ds;
+ }
+
+ /**
+ * Specifies the line end width in relation to the line width.
+ */
+ public void setLineTailLength(DecorationSize style) {
+ CTLineProperties ln = getLn(this, true);
+ if (ln == null) {
+ return;
+ }
+
+ CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
+ if (style == null) {
+ if (lnEnd.isSetLen()) {
+ lnEnd.unsetLen();
+ }
+ } else {
+ lnEnd.setLen(STLineEndLength.Enum.forInt(style.ooxmlId));
+ }
+ }
+
+ /**
+ * @return the line end decoration length
+ */
+ public DecorationSize getLineTailLength() {
+ CTLineProperties ln = getLn(this, false);
+
+ DecorationSize ds = DecorationSize.MEDIUM;
+ if (ln != null && ln.isSetTailEnd() && ln.getTailEnd().isSetLen()) {
+ ds = DecorationSize.fromOoxmlId(ln.getTailEnd().getLen().intValue());
+ }
+ return ds;
+ }
+
+ public boolean isPlaceholder() {
+ CTPlaceholder ph = getCTPlaceholder();
+ return ph != null;
+ }
+
+ public Guide getAdjustValue(String name) {
+ XSLFGeometryProperties gp = XSLFPropertiesDelegate.getGeometryDelegate(getShapeProperties());
+
+ if (gp != null && gp.isSetPrstGeom() && gp.getPrstGeom().isSetAvLst()) {
+ for (CTGeomGuide g : gp.getPrstGeom().getAvLst().getGdArray()) {
+ if (g.getName().equals(name)) {
+ return new Guide(g.getName(), g.getFmla());
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public LineDecoration getLineDecoration() {
+ return new LineDecoration() {
+ public DecorationShape getHeadShape() {
+ return getLineHeadDecoration();
+ }
+
+ public DecorationSize getHeadWidth() {
+ return getLineHeadWidth();
+ }
+
+ public DecorationSize getHeadLength() {
+ return getLineHeadLength();
+ }
+
+ public DecorationShape getTailShape() {
+ return getLineTailDecoration();
+ }
+
+ public DecorationSize getTailWidth() {
+ return getLineTailWidth();
+ }
+
+ public DecorationSize getTailLength() {
+ return getLineTailLength();
+ }
+ };
+ }
+
+ /**
+ * fetch shape fill as a java.awt.Paint
+ *
+ * @return either Color or GradientPaint or TexturePaint or null
+ */
+ public FillStyle getFillStyle() {
+ return new FillStyle() {
+ public PaintStyle getPaint() {
+ return XSLFSimpleShape.this.getFillPaint();
+ }
+ };
+ }
+
+ public StrokeStyle getStrokeStyle() {
+ return new StrokeStyle() {
+ public PaintStyle getPaint() {
+ return XSLFSimpleShape.this.getLinePaint();
+ }
+
+ public LineCap getLineCap() {
+ return XSLFSimpleShape.this.getLineCap();
+ }
+
+ public LineDash getLineDash() {
+ return XSLFSimpleShape.this.getLineDash();
+ }
+
+ public double getLineWidth() {
+ return XSLFSimpleShape.this.getLineWidth();
+ }
+
+ public LineCompound getLineCompound() {
+ return XSLFSimpleShape.this.getLineCompound();
+ }
+
+ };
+ }
+
+ @Override
+ public void setStrokeStyle(Object... styles) {
+ if (styles.length == 0) {
+ // remove stroke
+ setLineColor(null);
+ return;
+ }
+
+ // TODO: handle PaintStyle
+ for (Object st : styles) {
+ if (st instanceof Number) {
+ setLineWidth(((Number)st).doubleValue());
+ } else if (st instanceof LineCap) {
+ setLineCap((LineCap)st);
+ } else if (st instanceof LineDash) {
+ setLineDash((LineDash)st);
+ } else if (st instanceof LineCompound) {
+ setLineCompound((LineCompound)st);
+ } else if (st instanceof Color) {
+ setLineColor((Color)st);
+ }
+ }
+ }
+
+ @Override
+ public void setPlaceholder(Placeholder placeholder) {
+ super.setPlaceholder(placeholder);
+ }
+
+ @Override
+ public XSLFHyperlink getHyperlink() {
+ CTNonVisualDrawingProps cNvPr = getCNvPr();
+ if (!cNvPr.isSetHlinkClick()) {
+ return null;
+ }
+ return new XSLFHyperlink(cNvPr.getHlinkClick(), getSheet());
+ }
+
+ @Override
+ public XSLFHyperlink createHyperlink() {
+ XSLFHyperlink hl = getHyperlink();
+ if (hl == null) {
+ CTNonVisualDrawingProps cNvPr = getCNvPr();
+ hl = new XSLFHyperlink(cNvPr.addNewHlinkClick(), getSheet());
+ }
+ return hl;
+ }
+
+ private static CTLineProperties getLn(XSLFShape shape, boolean create) {
+ XmlObject pr = shape.getShapeProperties();
+ if (!(pr instanceof CTShapeProperties)) {
+ LOG.log(POILogger.WARN, shape.getClass().toString()+" doesn't have line properties");
+ return null;
+ }
+
+ CTShapeProperties spr = (CTShapeProperties)pr;
+ return (spr.isSetLn() || !create) ? spr.getLn() : spr.addNewLn();
+ }
}