String name = def.getDomNode().getLocalName();
CTCustomGeometry2D geom = CTCustomGeometry2D.Factory.parse(def.toString());
+ if(containsKey(name)) {
+ System.out.println("Duplicate definoition of " + name) ;
+ }
put(name, new CustomGeometry(geom));
}
}
else if (obj instanceof CTGradientFillProperties) {\r
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;\r
if (gradFill.isSetLin()) {\r
- paint = createLinearGradientPaint(gradFill, anchor, theme, phClr);\r
+ paint = createLinearGradientPaint(graphics, gradFill, anchor, theme, phClr);\r
} else if (gradFill.isSetPath()){\r
CTPathShadeProperties ps = gradFill.getPath();\r
if(ps.getPath() == STPathShadeType.CIRCLE){\r
}\r
\r
private static Paint createLinearGradientPaint(\r
+ Graphics2D graphics,\r
CTGradientFillProperties gradFill, Rectangle2D anchor,\r
XSLFTheme theme, CTSchemeColor phClr) {\r
double angle = gradFill.getLin().getAng() / 60000;\r
fractions[i] = stop.getPos() / 100000.f;\r
}\r
\r
+ AffineTransform grAt;\r
+ if(gradFill.getRotWithShape()) grAt = new AffineTransform();\r
+ else {\r
+ // gradient fill is not rotated with the shape\r
+ try {\r
+ grAt = graphics.getTransform().createInverse();\r
+ } catch (Exception e){\r
+ // should not happen.\r
+ grAt = new AffineTransform();\r
+ }\r
+ }\r
+\r
// Trick to return GradientPaint on JDK 1.5 and LinearGradientPaint on JDK 1.6+\r
Paint paint;\r
try {\r
Class clz = Class.forName("java.awt.LinearGradientPaint");\r
+ Class clzCycleMethod = Class.forName("java.awt.MultipleGradientPaint$CycleMethod");\r
+ Class clzColorSpaceType = Class.forName("java.awt.MultipleGradientPaint$ColorSpaceType");\r
Constructor c =\r
- clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class);\r
- paint = (Paint) c.newInstance(p1, p2, fractions, colors);\r
+ clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class,\r
+ clzCycleMethod, clzColorSpaceType, AffineTransform.class);\r
+ paint = (Paint) c.newInstance(p1, p2, fractions, colors,\r
+ Enum.valueOf(clzCycleMethod, "NO_CYCLE"),\r
+ Enum.valueOf(clzColorSpaceType, "SRGB"), grAt);\r
} catch (ClassNotFoundException e) {\r
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);\r
} catch (Exception e) {\r
}\r
\r
private Collection<Outline> computeOutlines() {\r
- CustomGeometry geom = _shape.getGeometry();\r
\r
Collection<Outline> lst = new ArrayList<Outline>();\r
+ CustomGeometry geom = _shape.getGeometry();\r
+ if(geom == null) {\r
+ return lst;\r
+ }\r
\r
Rectangle2D anchor = _shape.getAnchor();\r
for (Path p : geom) {\r
}\r
return txBody;\r
}\r
+\r
+ @Override\r
+ public String toString(){\r
+ return "[" + getClass().getSimpleName() + "] " + getShapeName();\r
+ }\r
}\r
return ct;\r
}\r
\r
- /**\r
- * Specifies the line end decoration, such as a triangle or arrowhead.\r
- */\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
- } else {\r
- lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
- }\r
- }\r
-\r
- public LineDecoration getLineHeadDecoration() {\r
- CTLineProperties ln = getSpPr().getLn();\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
- }\r
-\r
- /**\r
- * specifies decorations which can be added to the head of a line.\r
- */\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
- } else {\r
- lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
- }\r
- }\r
-\r
- public LineEndWidth getLineHeadWidth() {\r
- CTLineProperties ln = getSpPr().getLn();\r
- if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM;\r
-\r
- STLineEndWidth.Enum w = ln.getHeadEnd().getW();\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
- 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
- } else {\r
- lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
- }\r
- }\r
-\r
- public LineEndLength getLineHeadLength() {\r
- CTLineProperties ln = getSpPr().getLn();\r
- if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM;\r
-\r
- STLineEndLength.Enum len = ln.getHeadEnd().getLen();\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
- CTLineProperties ln = getSpPr().getLn();\r
- CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\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
- CTLineProperties ln = getSpPr().getLn();\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
- }\r
-\r
- /**\r
- * specifies decorations which can be added to the tail of a line.\r
- */\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
- } else {\r
- lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
- }\r
- }\r
-\r
- public LineEndWidth getLineTailWidth() {\r
- CTLineProperties ln = getSpPr().getLn();\r
- if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM;\r
-\r
- STLineEndWidth.Enum w = ln.getTailEnd().getW();\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
- 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
- } else {\r
- lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
- }\r
- }\r
-\r
- public LineEndLength getLineTailLength() {\r
- CTLineProperties ln = getSpPr().getLn();\r
- if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM;\r
-\r
- STLineEndLength.Enum len = ln.getTailEnd().getLen();\r
- return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];\r
- }\r
-\r
- Outline getTailDecoration() {\r
- LineEndLength tailLength = getLineTailLength();\r
- LineEndWidth tailWidth = getLineTailWidth();\r
-\r
- double lineWidth = Math.max(2.5, getLineWidth());\r
-\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
- Path p = null;\r
- Rectangle2D bounds;\r
- double scaleY = Math.pow(2, tailWidth.ordinal());\r
- double scaleX = Math.pow(2, tailLength.ordinal());\r
- switch (getLineTailDecoration()) {\r
- case OVAL:\r
- p = new Path();\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
- p = new Path();\r
- GeneralPath arrow = new GeneralPath();\r
- arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2));\r
- arrow.lineTo(0, 0);\r
- arrow.lineTo((float) (-lineWidth * 3), (float) (lineWidth * 2));\r
- shape = arrow;\r
- at.translate(x2, y2);\r
- at.rotate(alpha);\r
- break;\r
- case TRIANGLE:\r
- p = new Path();\r
- scaleY = tailWidth.ordinal() + 1;\r
- scaleX = tailLength.ordinal() + 1;\r
- GeneralPath triangle = new GeneralPath();\r
- triangle.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));\r
- triangle.lineTo(0, 0);\r
- triangle.lineTo((float) (-lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);\r
- }\r
-\r
- Outline getHeadDecoration() {\r
- LineEndLength headLength = getLineHeadLength();\r
- LineEndWidth headWidth = getLineHeadWidth();\r
-\r
- double lineWidth = Math.max(2.5, 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
- Path p = null;\r
- Rectangle2D bounds;\r
- double scaleY = 1;\r
- double scaleX = 1;\r
- switch (getLineHeadDecoration()) {\r
- case OVAL:\r
- p = new Path();\r
- shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);\r
- bounds = shape.getBounds2D();\r
- at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);\r
- at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);\r
- break;\r
- case STEALTH:\r
- case ARROW:\r
- p = new Path(false, true);\r
- GeneralPath arrow = new GeneralPath();\r
- arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2));\r
- arrow.lineTo(0, 0);\r
- arrow.lineTo((float) (lineWidth * 3 * scaleX), (float) (lineWidth * scaleY * 2));\r
- shape = arrow;\r
- at.translate(x1, y1);\r
- at.rotate(alpha);\r
- break;\r
- case TRIANGLE:\r
- p = new Path();\r
- scaleY = headWidth.ordinal() + 1;\r
- scaleX = headLength.ordinal() + 1;\r
- GeneralPath triangle = new GeneralPath();\r
- triangle.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));\r
- triangle.lineTo(0, 0);\r
- triangle.lineTo((float) (lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);\r
- }\r
-\r
- private List<Outline> getDecorationOutlines(){\r
- List<Outline> lst = new ArrayList<Outline>();\r
-\r
- Outline head = getHeadDecoration();\r
- if(head != null) lst.add(head);\r
-\r
- Outline tail = getTailDecoration();\r
- if(tail != null) lst.add(tail);\r
- return lst;\r
- }\r
\r
/**\r
* YK: dashing of lines is suppressed for now.\r
return null;\r
}\r
\r
- @Override\r
- public void draw(Graphics2D graphics){\r
- super.draw(graphics);\r
-\r
- // draw line decorations\r
- Color lineColor = getLineColor();\r
- if(lineColor != null) {\r
- graphics.setPaint(lineColor);\r
- for(Outline o : getDecorationOutlines()){\r
- if(o.getPath().isFilled()){\r
- graphics.fill(o.getOutline());\r
- } \r
- if(o.getPath().isStroked()){\r
- graphics.draw(o.getOutline());\r
- }\r
- }\r
- }\r
- }\r
}
\ No newline at end of file
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
import org.apache.poi.POIXMLException;\r
import org.apache.xmlbeans.XmlObject;\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.CTLineProperties;\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.CTSRgbColor;\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.CTTransform2D;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;\r
-import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;\r
+import org.openxmlformats.schemas.drawingml.x2006.main.*;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;\r
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;\r
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;\r
import java.awt.Paint;\r
import java.awt.Shape;\r
import java.awt.geom.AffineTransform;\r
+import java.awt.geom.Ellipse2D;\r
import java.awt.geom.GeneralPath;\r
import java.awt.geom.Rectangle2D;\r
+import java.util.ArrayList;\r
import java.util.Collection;\r
import java.util.Collections;\r
import java.util.List;\r
public void draw(Graphics2D graphics) {\r
RenderableShape rShape = new RenderableShape(this);\r
rShape.render(graphics);\r
+\r
+ // draw line decorations\r
+ Color lineColor = getLineColor();\r
+ if(lineColor != null) {\r
+ graphics.setPaint(lineColor);\r
+ for(Outline o : getDecorationOutlines()){\r
+ if(o.getPath().isFilled()){\r
+ graphics.fill(o.getOutline());\r
+ }\r
+ if(o.getPath().isStroked()){\r
+ graphics.draw(o.getOutline());\r
+ }\r
+ }\r
+ }\r
}\r
\r
\r
}\r
\r
}\r
+\r
+ /**\r
+ * Specifies the line end decoration, such as a triangle or arrowhead.\r
+ */\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
+ } else {\r
+ lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ public LineDecoration getLineHeadDecoration() {\r
+ CTLineProperties ln = getSpPr().getLn();\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
+ }\r
+\r
+ /**\r
+ * specifies decorations which can be added to the head of a line.\r
+ */\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
+ } else {\r
+ lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ public LineEndWidth getLineHeadWidth() {\r
+ CTLineProperties ln = getSpPr().getLn();\r
+ if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM;\r
+\r
+ STLineEndWidth.Enum w = ln.getHeadEnd().getW();\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
+ 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
+ } else {\r
+ lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ public LineEndLength getLineHeadLength() {\r
+ CTLineProperties ln = getSpPr().getLn();\r
+ if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM;\r
+\r
+ STLineEndLength.Enum len = ln.getHeadEnd().getLen();\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
+ CTLineProperties ln = getSpPr().getLn();\r
+ CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();\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
+ CTLineProperties ln = getSpPr().getLn();\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
+ }\r
+\r
+ /**\r
+ * specifies decorations which can be added to the tail of a line.\r
+ */\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
+ } else {\r
+ lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ public LineEndWidth getLineTailWidth() {\r
+ CTLineProperties ln = getSpPr().getLn();\r
+ if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM;\r
+\r
+ STLineEndWidth.Enum w = ln.getTailEnd().getW();\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
+ 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
+ } else {\r
+ lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));\r
+ }\r
+ }\r
+\r
+ public LineEndLength getLineTailLength() {\r
+ CTLineProperties ln = getSpPr().getLn();\r
+ if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM;\r
+\r
+ STLineEndLength.Enum len = ln.getTailEnd().getLen();\r
+ return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];\r
+ }\r
+\r
+ Outline getTailDecoration() {\r
+ LineEndLength tailLength = getLineTailLength();\r
+ LineEndWidth tailWidth = getLineTailWidth();\r
+\r
+ double lineWidth = Math.max(2.5, getLineWidth());\r
+\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
+ Path p = null;\r
+ Rectangle2D bounds;\r
+ double scaleY = Math.pow(2, tailWidth.ordinal());\r
+ double scaleX = Math.pow(2, tailLength.ordinal());\r
+ switch (getLineTailDecoration()) {\r
+ case OVAL:\r
+ p = new Path();\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
+ p = new Path();\r
+ GeneralPath arrow = new GeneralPath();\r
+ arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2));\r
+ arrow.lineTo(0, 0);\r
+ arrow.lineTo((float) (-lineWidth * 3), (float) (lineWidth * 2));\r
+ shape = arrow;\r
+ at.translate(x2, y2);\r
+ at.rotate(alpha);\r
+ break;\r
+ case TRIANGLE:\r
+ p = new Path();\r
+ scaleY = tailWidth.ordinal() + 1;\r
+ scaleX = tailLength.ordinal() + 1;\r
+ GeneralPath triangle = new GeneralPath();\r
+ triangle.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));\r
+ triangle.lineTo(0, 0);\r
+ triangle.lineTo((float) (-lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);\r
+ }\r
+\r
+ Outline getHeadDecoration() {\r
+ LineEndLength headLength = getLineHeadLength();\r
+ LineEndWidth headWidth = getLineHeadWidth();\r
+\r
+ double lineWidth = Math.max(2.5, 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
+ Path p = null;\r
+ Rectangle2D bounds;\r
+ double scaleY = 1;\r
+ double scaleX = 1;\r
+ switch (getLineHeadDecoration()) {\r
+ case OVAL:\r
+ p = new Path();\r
+ shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);\r
+ bounds = shape.getBounds2D();\r
+ at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);\r
+ at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);\r
+ break;\r
+ case STEALTH:\r
+ case ARROW:\r
+ p = new Path(false, true);\r
+ GeneralPath arrow = new GeneralPath();\r
+ arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2));\r
+ arrow.lineTo(0, 0);\r
+ arrow.lineTo((float) (lineWidth * 3 * scaleX), (float) (lineWidth * scaleY * 2));\r
+ shape = arrow;\r
+ at.translate(x1, y1);\r
+ at.rotate(alpha);\r
+ break;\r
+ case TRIANGLE:\r
+ p = new Path();\r
+ scaleY = headWidth.ordinal() + 1;\r
+ scaleX = headLength.ordinal() + 1;\r
+ GeneralPath triangle = new GeneralPath();\r
+ triangle.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));\r
+ triangle.lineTo(0, 0);\r
+ triangle.lineTo((float) (lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);\r
+ }\r
+\r
+ private List<Outline> getDecorationOutlines(){\r
+ List<Outline> lst = new ArrayList<Outline>();\r
+\r
+ Outline head = getHeadDecoration();\r
+ if(head != null) lst.add(head);\r
+\r
+ Outline tail = getTailDecoration();\r
+ if(tail != null) lst.add(tail);\r
+ return lst;\r
+ }\r
+\r
}\r
public void testRead(){
Map<String, CustomGeometry> shapes = PresetGeometries.getInstance();
- assertEquals(186, shapes.size());
+ assertEquals(187, shapes.size());
for(String name : shapes.keySet()) {
</pathLst>\r
\r
</upArrowCallout>\r
- <upDownArrow>\r
+ <upArrow>\r
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">\r
<gd name="adj1" fmla="val 50000" />\r
<gd name="adj2" fmla="val 50000" />\r
<pt x="x2" y="y2" />\r
</lnTo>\r
<lnTo>\r
- <pt x="x2" y="y3" />\r
- </lnTo>\r
- <lnTo>\r
- <pt x="r" y="y3" />\r
- </lnTo>\r
- <lnTo>\r
- <pt x="hc" y="b" />\r
- </lnTo>\r
- <lnTo>\r
- <pt x="l" y="y3" />\r
+ <pt x="x2" y="b" />\r
</lnTo>\r
<lnTo>\r
- <pt x="x1" y="y3" />\r
+ <pt x="x1" y="b" />\r
</lnTo>\r
<lnTo>\r
<pt x="x1" y="y2" />\r
<close />\r
</path>\r
</pathLst>\r
- </upDownArrow>\r
+ </upArrow>\r
<upDownArrow>\r
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">\r
<gd name="adj1" fmla="val 50000" />\r