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();
|
||||
CTCustomGeometry2D geom = CTCustomGeometry2D.Factory.parse(def.toString());
|
||||
|
||||
if(containsKey(name)) {
|
||||
System.out.println("Duplicate definoition of " + name) ;
|
||||
}
|
||||
put(name, new CustomGeometry(geom));
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class RenderableShape {
|
||||
else if (obj instanceof CTGradientFillProperties) {
|
||||
CTGradientFillProperties gradFill = (CTGradientFillProperties) obj;
|
||||
if (gradFill.isSetLin()) {
|
||||
paint = createLinearGradientPaint(gradFill, anchor, theme, phClr);
|
||||
paint = createLinearGradientPaint(graphics, gradFill, anchor, theme, phClr);
|
||||
} else if (gradFill.isSetPath()){
|
||||
CTPathShadeProperties ps = gradFill.getPath();
|
||||
if(ps.getPath() == STPathShadeType.CIRCLE){
|
||||
@ -166,6 +166,7 @@ class RenderableShape {
|
||||
}
|
||||
|
||||
private static Paint createLinearGradientPaint(
|
||||
Graphics2D graphics,
|
||||
CTGradientFillProperties gradFill, Rectangle2D anchor,
|
||||
XSLFTheme theme, CTSchemeColor phClr) {
|
||||
double angle = gradFill.getLin().getAng() / 60000;
|
||||
@ -204,13 +205,30 @@ class RenderableShape {
|
||||
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+
|
||||
Paint paint;
|
||||
try {
|
||||
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 =
|
||||
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class);
|
||||
paint = (Paint) c.newInstance(p1, p2, fractions, colors);
|
||||
clz.getConstructor(Point2D.class, Point2D.class, float[].class, Color[].class,
|
||||
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) {
|
||||
paint = new GradientPaint(p1, colors[0], p2, colors[colors.length - 1]);
|
||||
} catch (Exception e) {
|
||||
@ -504,9 +522,12 @@ class RenderableShape {
|
||||
}
|
||||
|
||||
private Collection<Outline> computeOutlines() {
|
||||
CustomGeometry geom = _shape.getGeometry();
|
||||
|
||||
Collection<Outline> lst = new ArrayList<Outline>();
|
||||
CustomGeometry geom = _shape.getGeometry();
|
||||
if(geom == null) {
|
||||
return lst;
|
||||
}
|
||||
|
||||
Rectangle2D anchor = _shape.getAnchor();
|
||||
for (Path p : geom) {
|
||||
|
@ -80,4 +80,9 @@ public class XSLFAutoShape extends XSLFTextShape {
|
||||
}
|
||||
return txBody;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "[" + getClass().getSimpleName() + "] " + getShapeName();
|
||||
}
|
||||
}
|
||||
|
@ -75,262 +75,6 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
||||
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.
|
||||
@ -341,22 +85,4 @@ public class XSLFConnectorShape extends XSLFSimpleShape {
|
||||
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.POIXMLException;
|
||||
import org.apache.xmlbeans.XmlObject;
|
||||
import org.openxmlformats.schemas.drawingml.x2006.main.CTEffectStyleItem;
|
||||
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.drawingml.x2006.main.*;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPlaceholder;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.STPlaceholderType;
|
||||
import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture;
|
||||
@ -63,8 +45,10 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -555,6 +539,20 @@ public abstract class XSLFSimpleShape extends XSLFShape {
|
||||
public void draw(Graphics2D graphics) {
|
||||
RenderableShape rShape = new RenderableShape(this);
|
||||
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(){
|
||||
|
||||
Map<String, CustomGeometry> shapes = PresetGeometries.getInstance();
|
||||
assertEquals(186, shapes.size());
|
||||
assertEquals(187, shapes.size());
|
||||
|
||||
|
||||
for(String name : shapes.keySet()) {
|
||||
|
@ -18822,7 +18822,7 @@
|
||||
</pathLst>
|
||||
|
||||
</upArrowCallout>
|
||||
<upDownArrow>
|
||||
<upArrow>
|
||||
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||
<gd name="adj1" fmla="val 50000" />
|
||||
<gd name="adj2" fmla="val 50000" />
|
||||
@ -18890,19 +18890,10 @@
|
||||
<pt x="x2" y="y2" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="x2" y="y3" />
|
||||
<pt x="x2" y="b" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="r" y="y3" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="hc" y="b" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="l" y="y3" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="x1" y="y3" />
|
||||
<pt x="x1" y="b" />
|
||||
</lnTo>
|
||||
<lnTo>
|
||||
<pt x="x1" y="y2" />
|
||||
@ -18910,7 +18901,7 @@
|
||||
<close />
|
||||
</path>
|
||||
</pathLst>
|
||||
</upDownArrow>
|
||||
</upArrow>
|
||||
<upDownArrow>
|
||||
<avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||
<gd name="adj1" fmla="val 50000" />
|
||||
|
Loading…
Reference in New Issue
Block a user