added missing definition of the upArrow shape, moved support for line decorations to XSLFSimpleShape
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1204477 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
12c58c96e3
commit
66b79be517
@ -51,6 +51,9 @@ public class PresetGeometries extends LinkedHashMap<String, CustomGeometry> {
|
|||||||
String name = def.getDomNode().getLocalName();
|
String name = def.getDomNode().getLocalName();
|
||||||
CTCustomGeometry2D geom = CTCustomGeometry2D.Factory.parse(def.toString());
|
CTCustomGeometry2D geom = CTCustomGeometry2D.Factory.parse(def.toString());
|
||||||
|
|
||||||
|
if(containsKey(name)) {
|
||||||
|
System.out.println("Duplicate definoition of " + name) ;
|
||||||
|
}
|
||||||
put(name, new CustomGeometry(geom));
|
put(name, new CustomGeometry(geom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ class RenderableShape {
|
|||||||
else if (obj instanceof CTGradientFillProperties) {
|
else if (obj instanceof CTGradientFillProperties) {
|
||||||
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;
|
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;
|
||||||
if (gradFill.isSetLin()) {
|
if (gradFill.isSetLin()) {
|
||||||
paint = createLinearGradientPaint(gradFill, anchor, theme, phClr);
|
paint = createLinearGradientPaint(graphics, gradFill, anchor, theme, phClr);
|
||||||
} else if (gradFill.isSetPath()){
|
} else if (gradFill.isSetPath()){
|
||||||
CTPathShadeProperties ps = gradFill.getPath();
|
CTPathShadeProperties ps = gradFill.getPath();
|
||||||
if(ps.getPath() == STPathShadeType.CIRCLE){
|
if(ps.getPath() == STPathShadeType.CIRCLE){
|
||||||
@ -166,6 +166,7 @@ class RenderableShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Paint createLinearGradientPaint(
|
private static Paint createLinearGradientPaint(
|
||||||
|
Graphics2D graphics,
|
||||||
CTGradientFillProperties gradFill, Rectangle2D anchor,
|
CTGradientFillProperties gradFill, Rectangle2D anchor,
|
||||||
XSLFTheme theme, CTSchemeColor phClr) {
|
XSLFTheme theme, CTSchemeColor phClr) {
|
||||||
double angle = gradFill.getLin().getAng() / 60000;
|
double angle = gradFill.getLin().getAng() / 60000;
|
||||||
@ -204,13 +205,30 @@ class RenderableShape {
|
|||||||
fractions[i] = stop.getPos() / 100000.f;
|
fractions[i] = stop.getPos() / 100000.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AffineTransform grAt;
|
||||||
|
if(gradFill.getRotWithShape()) grAt = new AffineTransform();
|
||||||
|
else {
|
||||||
|
// gradient fill is not rotated with the shape
|
||||||
|
try {
|
||||||
|
grAt = graphics.getTransform().createInverse();
|
||||||
|
} catch (Exception e){
|
||||||
|
// should not happen.
|
||||||
|
grAt = new AffineTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Trick to return GradientPaint on JDK 1.5 and LinearGradientPaint on JDK 1.6+
|
// Trick to return GradientPaint on JDK 1.5 and LinearGradientPaint on JDK 1.6+
|
||||||
Paint paint;
|
Paint paint;
|
||||||
try {
|
try {
|
||||||
Class clz = Class.forName("java.awt.LinearGradientPaint");
|
Class clz = Class.forName("java.awt.LinearGradientPaint");
|
||||||
|
Class clzCycleMethod = Class.forName("java.awt.MultipleGradientPaint$CycleMethod");
|
||||||
|
Class clzColorSpaceType = Class.forName("java.awt.MultipleGradientPaint$ColorSpaceType");
|
||||||
Constructor c =
|
Constructor c =
|
||||||
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class);
|
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class,
|
||||||
paint = (Paint) c.newInstance(p1, p2, fractions, colors);
|
clzCycleMethod, clzColorSpaceType, AffineTransform.class);
|
||||||
|
paint = (Paint) c.newInstance(p1, p2, fractions, colors,
|
||||||
|
Enum.valueOf(clzCycleMethod, "NO_CYCLE"),
|
||||||
|
Enum.valueOf(clzColorSpaceType, "SRGB"), grAt);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);
|
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -504,9 +522,12 @@ class RenderableShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Collection<Outline> computeOutlines() {
|
private Collection<Outline> computeOutlines() {
|
||||||
CustomGeometry geom = _shape.getGeometry();
|
|
||||||
|
|
||||||
Collection<Outline> lst = new ArrayList<Outline>();
|
Collection<Outline> lst = new ArrayList<Outline>();
|
||||||
|
CustomGeometry geom = _shape.getGeometry();
|
||||||
|
if(geom == null) {
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle2D anchor = _shape.getAnchor();
|
Rectangle2D anchor = _shape.getAnchor();
|
||||||
for (Path p : geom) {
|
for (Path p : geom) {
|
||||||
|
@ -80,4 +80,9 @@ public class XSLFAutoShape extends XSLFTextShape {
|
|||||||
}
|
}
|
||||||
return txBody;
|
return txBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return "[" + getClass().getSimpleName() + "] " + getShapeName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,262 +75,6 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
|||||||
return ct;
|
return ct;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the line end decoration, such as a triangle or arrowhead.
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
} else {
|
|
||||||
lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineDecoration getLineHeadDecoration() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetHeadEnd()) return LineDecoration.NONE;
|
|
||||||
|
|
||||||
STLineEndType.Enum end = ln.getHeadEnd().getType();
|
|
||||||
return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* specifies decorations which can be added to the head of a line.
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
} else {
|
|
||||||
lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineEndWidth getLineHeadWidth() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM;
|
|
||||||
|
|
||||||
STLineEndWidth.Enum w = ln.getHeadEnd().getW();
|
|
||||||
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) {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
|
|
||||||
|
|
||||||
if (style == null) {
|
|
||||||
if (lnEnd.isSetLen()) lnEnd.unsetLen();
|
|
||||||
} else {
|
|
||||||
lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineEndLength getLineHeadLength() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM;
|
|
||||||
|
|
||||||
STLineEndLength.Enum len = ln.getHeadEnd().getLen();
|
|
||||||
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) {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
|
|
||||||
if (style == null) {
|
|
||||||
if (lnEnd.isSetType()) lnEnd.unsetType();
|
|
||||||
} else {
|
|
||||||
lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineDecoration getLineTailDecoration() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetTailEnd()) return LineDecoration.NONE;
|
|
||||||
|
|
||||||
STLineEndType.Enum end = ln.getTailEnd().getType();
|
|
||||||
return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* specifies decorations which can be added to the tail of a line.
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
} else {
|
|
||||||
lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineEndWidth getLineTailWidth() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM;
|
|
||||||
|
|
||||||
STLineEndWidth.Enum w = ln.getTailEnd().getW();
|
|
||||||
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) {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
|
|
||||||
|
|
||||||
if (style == null) {
|
|
||||||
if (lnEnd.isSetLen()) lnEnd.unsetLen();
|
|
||||||
} else {
|
|
||||||
lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public LineEndLength getLineTailLength() {
|
|
||||||
CTLineProperties ln = getSpPr().getLn();
|
|
||||||
if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM;
|
|
||||||
|
|
||||||
STLineEndLength.Enum len = ln.getTailEnd().getLen();
|
|
||||||
return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
Outline getTailDecoration() {
|
|
||||||
LineEndLength tailLength = getLineTailLength();
|
|
||||||
LineEndWidth tailWidth = getLineTailWidth();
|
|
||||||
|
|
||||||
double lineWidth = Math.max(2.5, 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;
|
|
||||||
Path p = null;
|
|
||||||
Rectangle2D bounds;
|
|
||||||
double scaleY = Math.pow(2, tailWidth.ordinal());
|
|
||||||
double scaleX = Math.pow(2, tailLength.ordinal());
|
|
||||||
switch (getLineTailDecoration()) {
|
|
||||||
case OVAL:
|
|
||||||
p = new Path();
|
|
||||||
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:
|
|
||||||
p = new Path();
|
|
||||||
GeneralPath arrow = new GeneralPath();
|
|
||||||
arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2));
|
|
||||||
arrow.lineTo(0, 0);
|
|
||||||
arrow.lineTo((float) (-lineWidth * 3), (float) (lineWidth * 2));
|
|
||||||
shape = arrow;
|
|
||||||
at.translate(x2, y2);
|
|
||||||
at.rotate(alpha);
|
|
||||||
break;
|
|
||||||
case TRIANGLE:
|
|
||||||
p = new Path();
|
|
||||||
scaleY = tailWidth.ordinal() + 1;
|
|
||||||
scaleX = tailLength.ordinal() + 1;
|
|
||||||
GeneralPath triangle = new GeneralPath();
|
|
||||||
triangle.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
|
|
||||||
triangle.lineTo(0, 0);
|
|
||||||
triangle.lineTo((float) (-lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
Outline getHeadDecoration() {
|
|
||||||
LineEndLength headLength = getLineHeadLength();
|
|
||||||
LineEndWidth headWidth = getLineHeadWidth();
|
|
||||||
|
|
||||||
double lineWidth = Math.max(2.5, 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;
|
|
||||||
Path p = null;
|
|
||||||
Rectangle2D bounds;
|
|
||||||
double scaleY = 1;
|
|
||||||
double scaleX = 1;
|
|
||||||
switch (getLineHeadDecoration()) {
|
|
||||||
case OVAL:
|
|
||||||
p = new Path();
|
|
||||||
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
|
|
||||||
bounds = shape.getBounds2D();
|
|
||||||
at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
|
|
||||||
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
|
|
||||||
break;
|
|
||||||
case STEALTH:
|
|
||||||
case ARROW:
|
|
||||||
p = new Path(false, true);
|
|
||||||
GeneralPath arrow = new GeneralPath();
|
|
||||||
arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2));
|
|
||||||
arrow.lineTo(0, 0);
|
|
||||||
arrow.lineTo((float) (lineWidth * 3 * scaleX), (float) (lineWidth * scaleY * 2));
|
|
||||||
shape = arrow;
|
|
||||||
at.translate(x1, y1);
|
|
||||||
at.rotate(alpha);
|
|
||||||
break;
|
|
||||||
case TRIANGLE:
|
|
||||||
p = new Path();
|
|
||||||
scaleY = headWidth.ordinal() + 1;
|
|
||||||
scaleX = headLength.ordinal() + 1;
|
|
||||||
GeneralPath triangle = new GeneralPath();
|
|
||||||
triangle.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
|
|
||||||
triangle.lineTo(0, 0);
|
|
||||||
triangle.lineTo((float) (lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Outline> getDecorationOutlines(){
|
|
||||||
List<Outline> lst = new ArrayList<Outline>();
|
|
||||||
|
|
||||||
Outline head = getHeadDecoration();
|
|
||||||
if(head != null) lst.add(head);
|
|
||||||
|
|
||||||
Outline tail = getTailDecoration();
|
|
||||||
if(tail != null) lst.add(tail);
|
|
||||||
return lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YK: dashing of lines is suppressed for now.
|
* YK: dashing of lines is suppressed for now.
|
||||||
@ -341,22 +85,4 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(Graphics2D graphics){
|
|
||||||
super.draw(graphics);
|
|
||||||
|
|
||||||
// draw line decorations
|
|
||||||
Color lineColor = getLineColor();
|
|
||||||
if(lineColor != null) {
|
|
||||||
graphics.setPaint(lineColor);
|
|
||||||
for(Outline o : getDecorationOutlines()){
|
|
||||||
if(o.getPath().isFilled()){
|
|
||||||
graphics.fill(o.getOutline());
|
|
||||||
}
|
|
||||||
if(o.getPath().isStroked()){
|
|
||||||
graphics.draw(o.getOutline());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -35,25 +35,7 @@ import org.apache.poi.openxml4j.opc.TargetMode;
|
|||||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.apache.poi.POIXMLException;
|
import org.apache.poi.POIXMLException;
|
||||||
import org.apache.xmlbeans.XmlObject;
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
|
import org.openxmlformats.schemas.drawingml.x2006.main.*;
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomGuide;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTLineProperties;
|
|
||||||
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.CTSRgbColor;
|
|
||||||
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.CTTransform2D;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STLineCap;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetLineDashVal;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.STShapeType;
|
|
||||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
|
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
||||||
@ -63,8 +45,10 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Paint;
|
import java.awt.Paint;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
import java.awt.geom.GeneralPath;
|
import java.awt.geom.GeneralPath;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -555,6 +539,20 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||||||
public void draw(Graphics2D graphics) {
|
public void draw(Graphics2D graphics) {
|
||||||
RenderableShape rShape = new RenderableShape(this);
|
RenderableShape rShape = new RenderableShape(this);
|
||||||
rShape.render(graphics);
|
rShape.render(graphics);
|
||||||
|
|
||||||
|
// draw line decorations
|
||||||
|
Color lineColor = getLineColor();
|
||||||
|
if(lineColor != null) {
|
||||||
|
graphics.setPaint(lineColor);
|
||||||
|
for(Outline o : getDecorationOutlines()){
|
||||||
|
if(o.getPath().isFilled()){
|
||||||
|
graphics.fill(o.getOutline());
|
||||||
|
}
|
||||||
|
if(o.getPath().isStroked()){
|
||||||
|
graphics.draw(o.getOutline());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -696,4 +694,262 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the line end decoration, such as a triangle or arrowhead.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
} else {
|
||||||
|
lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineDecoration getLineHeadDecoration() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetHeadEnd()) return LineDecoration.NONE;
|
||||||
|
|
||||||
|
STLineEndType.Enum end = ln.getHeadEnd().getType();
|
||||||
|
return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* specifies decorations which can be added to the head of a line.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
} else {
|
||||||
|
lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineEndWidth getLineHeadWidth() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetHeadEnd()) return LineEndWidth.MEDIUM;
|
||||||
|
|
||||||
|
STLineEndWidth.Enum w = ln.getHeadEnd().getW();
|
||||||
|
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) {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
CTLineEndProperties lnEnd = ln.isSetHeadEnd() ? ln.getHeadEnd() : ln.addNewHeadEnd();
|
||||||
|
|
||||||
|
if (style == null) {
|
||||||
|
if (lnEnd.isSetLen()) lnEnd.unsetLen();
|
||||||
|
} else {
|
||||||
|
lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineEndLength getLineHeadLength() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetHeadEnd()) return LineEndLength.MEDIUM;
|
||||||
|
|
||||||
|
STLineEndLength.Enum len = ln.getHeadEnd().getLen();
|
||||||
|
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) {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
|
||||||
|
if (style == null) {
|
||||||
|
if (lnEnd.isSetType()) lnEnd.unsetType();
|
||||||
|
} else {
|
||||||
|
lnEnd.setType(STLineEndType.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineDecoration getLineTailDecoration() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetTailEnd()) return LineDecoration.NONE;
|
||||||
|
|
||||||
|
STLineEndType.Enum end = ln.getTailEnd().getType();
|
||||||
|
return end == null ? LineDecoration.NONE : LineDecoration.values()[end.intValue() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* specifies decorations which can be added to the tail of a line.
|
||||||
|
*/
|
||||||
|
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();
|
||||||
|
} else {
|
||||||
|
lnEnd.setW(STLineEndWidth.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineEndWidth getLineTailWidth() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetTailEnd()) return LineEndWidth.MEDIUM;
|
||||||
|
|
||||||
|
STLineEndWidth.Enum w = ln.getTailEnd().getW();
|
||||||
|
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) {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
CTLineEndProperties lnEnd = ln.isSetTailEnd() ? ln.getTailEnd() : ln.addNewTailEnd();
|
||||||
|
|
||||||
|
if (style == null) {
|
||||||
|
if (lnEnd.isSetLen()) lnEnd.unsetLen();
|
||||||
|
} else {
|
||||||
|
lnEnd.setLen(STLineEndLength.Enum.forInt(style.ordinal() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LineEndLength getLineTailLength() {
|
||||||
|
CTLineProperties ln = getSpPr().getLn();
|
||||||
|
if (ln == null || !ln.isSetTailEnd()) return LineEndLength.MEDIUM;
|
||||||
|
|
||||||
|
STLineEndLength.Enum len = ln.getTailEnd().getLen();
|
||||||
|
return len == null ? LineEndLength.MEDIUM : LineEndLength.values()[len.intValue() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
Outline getTailDecoration() {
|
||||||
|
LineEndLength tailLength = getLineTailLength();
|
||||||
|
LineEndWidth tailWidth = getLineTailWidth();
|
||||||
|
|
||||||
|
double lineWidth = Math.max(2.5, 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;
|
||||||
|
Path p = null;
|
||||||
|
Rectangle2D bounds;
|
||||||
|
double scaleY = Math.pow(2, tailWidth.ordinal());
|
||||||
|
double scaleX = Math.pow(2, tailLength.ordinal());
|
||||||
|
switch (getLineTailDecoration()) {
|
||||||
|
case OVAL:
|
||||||
|
p = new Path();
|
||||||
|
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:
|
||||||
|
p = new Path();
|
||||||
|
GeneralPath arrow = new GeneralPath();
|
||||||
|
arrow.moveTo((float) (-lineWidth * 3), (float) (-lineWidth * 2));
|
||||||
|
arrow.lineTo(0, 0);
|
||||||
|
arrow.lineTo((float) (-lineWidth * 3), (float) (lineWidth * 2));
|
||||||
|
shape = arrow;
|
||||||
|
at.translate(x2, y2);
|
||||||
|
at.rotate(alpha);
|
||||||
|
break;
|
||||||
|
case TRIANGLE:
|
||||||
|
p = new Path();
|
||||||
|
scaleY = tailWidth.ordinal() + 1;
|
||||||
|
scaleX = tailLength.ordinal() + 1;
|
||||||
|
GeneralPath triangle = new GeneralPath();
|
||||||
|
triangle.moveTo((float) (-lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
|
||||||
|
triangle.lineTo(0, 0);
|
||||||
|
triangle.lineTo((float) (-lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
Outline getHeadDecoration() {
|
||||||
|
LineEndLength headLength = getLineHeadLength();
|
||||||
|
LineEndWidth headWidth = getLineHeadWidth();
|
||||||
|
|
||||||
|
double lineWidth = Math.max(2.5, 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;
|
||||||
|
Path p = null;
|
||||||
|
Rectangle2D bounds;
|
||||||
|
double scaleY = 1;
|
||||||
|
double scaleX = 1;
|
||||||
|
switch (getLineHeadDecoration()) {
|
||||||
|
case OVAL:
|
||||||
|
p = new Path();
|
||||||
|
shape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
|
||||||
|
bounds = shape.getBounds2D();
|
||||||
|
at.translate(x1 - bounds.getWidth() / 2, y1 - bounds.getHeight() / 2);
|
||||||
|
at.rotate(alpha, bounds.getX() + bounds.getWidth() / 2, bounds.getY() + bounds.getHeight() / 2);
|
||||||
|
break;
|
||||||
|
case STEALTH:
|
||||||
|
case ARROW:
|
||||||
|
p = new Path(false, true);
|
||||||
|
GeneralPath arrow = new GeneralPath();
|
||||||
|
arrow.moveTo((float) (lineWidth * 3 * scaleX), (float) (-lineWidth * scaleY * 2));
|
||||||
|
arrow.lineTo(0, 0);
|
||||||
|
arrow.lineTo((float) (lineWidth * 3 * scaleX), (float) (lineWidth * scaleY * 2));
|
||||||
|
shape = arrow;
|
||||||
|
at.translate(x1, y1);
|
||||||
|
at.rotate(alpha);
|
||||||
|
break;
|
||||||
|
case TRIANGLE:
|
||||||
|
p = new Path();
|
||||||
|
scaleY = headWidth.ordinal() + 1;
|
||||||
|
scaleX = headLength.ordinal() + 1;
|
||||||
|
GeneralPath triangle = new GeneralPath();
|
||||||
|
triangle.moveTo((float) (lineWidth * scaleX), (float) (-lineWidth * scaleY / 2));
|
||||||
|
triangle.lineTo(0, 0);
|
||||||
|
triangle.lineTo((float) (lineWidth * scaleX), (float) (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 == null ? null : new Outline(shape, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Outline> getDecorationOutlines(){
|
||||||
|
List<Outline> lst = new ArrayList<Outline>();
|
||||||
|
|
||||||
|
Outline head = getHeadDecoration();
|
||||||
|
if(head != null) lst.add(head);
|
||||||
|
|
||||||
|
Outline tail = getTailDecoration();
|
||||||
|
if(tail != null) lst.add(tail);
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ public class TestPresetGeometries extends TestCase {
|
|||||||
public void testRead(){
|
public void testRead(){
|
||||||
|
|
||||||
Map<String, CustomGeometry> shapes = PresetGeometries.getInstance();
|
Map<String, CustomGeometry> shapes = PresetGeometries.getInstance();
|
||||||
assertEquals(186, shapes.size());
|
assertEquals(187, shapes.size());
|
||||||
|
|
||||||
|
|
||||||
for(String name : shapes.keySet()) {
|
for(String name : shapes.keySet()) {
|
||||||
|
@ -18822,7 +18822,7 @@
|
|||||||
</pathLst>
|
</pathLst>
|
||||||
|
|
||||||
</upArrowCallout>
|
</upArrowCallout>
|
||||||
<upDownArrow>
|
<upArrow>
|
||||||
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||||
<gd name="adj1" fmla="val 50000" />
|
<gd name="adj1" fmla="val 50000" />
|
||||||
<gd name="adj2" fmla="val 50000" />
|
<gd name="adj2" fmla="val 50000" />
|
||||||
@ -18890,19 +18890,10 @@
|
|||||||
<pt x="x2" y="y2" />
|
<pt x="x2" y="y2" />
|
||||||
</lnTo>
|
</lnTo>
|
||||||
<lnTo>
|
<lnTo>
|
||||||
<pt x="x2" y="y3" />
|
<pt x="x2" y="b" />
|
||||||
</lnTo>
|
</lnTo>
|
||||||
<lnTo>
|
<lnTo>
|
||||||
<pt x="r" y="y3" />
|
<pt x="x1" y="b" />
|
||||||
</lnTo>
|
|
||||||
<lnTo>
|
|
||||||
<pt x="hc" y="b" />
|
|
||||||
</lnTo>
|
|
||||||
<lnTo>
|
|
||||||
<pt x="l" y="y3" />
|
|
||||||
</lnTo>
|
|
||||||
<lnTo>
|
|
||||||
<pt x="x1" y="y3" />
|
|
||||||
</lnTo>
|
</lnTo>
|
||||||
<lnTo>
|
<lnTo>
|
||||||
<pt x="x1" y="y2" />
|
<pt x="x1" y="y2" />
|
||||||
@ -18910,7 +18901,7 @@
|
|||||||
<close />
|
<close />
|
||||||
</path>
|
</path>
|
||||||
</pathLst>
|
</pathLst>
|
||||||
</upDownArrow>
|
</upArrow>
|
||||||
<upDownArrow>
|
<upDownArrow>
|
||||||
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||||
<gd name="adj1" fmla="val 50000" />
|
<gd name="adj1" fmla="val 50000" />
|
||||||
|
Loading…
Reference in New Issue
Block a user