2017-02-08 07:47:30 +00:00
|
|
|
/* ====================================================================
|
|
|
|
|
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.sl.draw;
|
|
|
|
|
|
2018-12-10 16:18:49 +00:00
|
|
|
import static org.apache.poi.sl.draw.DrawPaint.fillPaintWorkaround;
|
|
|
|
|
|
2017-02-08 07:47:30 +00:00
|
|
|
import java.awt.BasicStroke;
|
|
|
|
|
import java.awt.Color;
|
|
|
|
|
import java.awt.Graphics2D;
|
|
|
|
|
import java.awt.Paint;
|
2019-09-11 21:24:06 +00:00
|
|
|
import java.awt.Stroke;
|
2017-02-08 07:47:30 +00:00
|
|
|
import java.awt.geom.AffineTransform;
|
|
|
|
|
import java.awt.geom.Ellipse2D;
|
|
|
|
|
import java.awt.geom.Path2D;
|
|
|
|
|
import java.awt.geom.Rectangle2D;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.List;
|
2019-07-22 21:29:55 +00:00
|
|
|
import java.util.function.Consumer;
|
2017-02-08 07:47:30 +00:00
|
|
|
|
|
|
|
|
import org.apache.poi.sl.draw.geom.Context;
|
|
|
|
|
import org.apache.poi.sl.draw.geom.CustomGeometry;
|
|
|
|
|
import org.apache.poi.sl.draw.geom.Outline;
|
|
|
|
|
import org.apache.poi.sl.draw.geom.Path;
|
|
|
|
|
import org.apache.poi.sl.usermodel.LineDecoration;
|
|
|
|
|
import org.apache.poi.sl.usermodel.LineDecoration.DecorationShape;
|
|
|
|
|
import org.apache.poi.sl.usermodel.LineDecoration.DecorationSize;
|
2019-07-22 21:29:55 +00:00
|
|
|
import org.apache.poi.sl.usermodel.PaintStyle;
|
|
|
|
|
import org.apache.poi.sl.usermodel.PaintStyle.PaintModifier;
|
2017-02-08 07:47:30 +00:00
|
|
|
import org.apache.poi.sl.usermodel.PaintStyle.SolidPaint;
|
|
|
|
|
import org.apache.poi.sl.usermodel.Shadow;
|
|
|
|
|
import org.apache.poi.sl.usermodel.SimpleShape;
|
|
|
|
|
import org.apache.poi.util.Units;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class DrawSimpleShape extends DrawShape {
|
2017-05-30 09:33:28 +00:00
|
|
|
|
2017-02-08 07:47:30 +00:00
|
|
|
private static final double DECO_SIZE_POW = 1.5d;
|
|
|
|
|
|
|
|
|
|
public DrawSimpleShape(SimpleShape<?,?> shape) {
|
|
|
|
|
super(shape);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void draw(Graphics2D graphics) {
|
2018-12-18 22:52:36 +00:00
|
|
|
if (getAnchor(graphics, getShape()) == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 21:24:06 +00:00
|
|
|
Paint oldPaint = graphics.getPaint();
|
|
|
|
|
Stroke oldStroke = graphics.getStroke();
|
|
|
|
|
Color oldColor = graphics.getColor();
|
|
|
|
|
|
2019-07-22 21:29:55 +00:00
|
|
|
Paint fill = getFillPaint(graphics);
|
|
|
|
|
Paint line = getLinePaint(graphics);
|
2017-02-08 07:47:30 +00:00
|
|
|
BasicStroke stroke = getStroke(); // the stroke applies both to the shadow and the shape
|
|
|
|
|
graphics.setStroke(stroke);
|
|
|
|
|
|
|
|
|
|
Collection<Outline> elems = computeOutlines(graphics);
|
|
|
|
|
|
|
|
|
|
// first paint the shadow
|
|
|
|
|
drawShadow(graphics, elems, fill, line);
|
|
|
|
|
|
|
|
|
|
// then fill the shape interior
|
|
|
|
|
if (fill != null) {
|
2019-07-22 21:29:55 +00:00
|
|
|
final Path2D area = new Path2D.Double();
|
|
|
|
|
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, area);
|
|
|
|
|
|
|
|
|
|
Consumer<PaintModifier> fun = (pm) -> fillArea(graphics, pm, area);
|
|
|
|
|
|
|
|
|
|
PaintModifier pm = null;
|
2017-02-08 07:47:30 +00:00
|
|
|
for (Outline o : elems) {
|
2019-07-22 21:29:55 +00:00
|
|
|
Path path = o.getPath();
|
|
|
|
|
if (path.isFilled()) {
|
|
|
|
|
PaintModifier pmOld = pm;
|
|
|
|
|
pm = path.getFill();
|
|
|
|
|
if (pmOld != null && pmOld != pm) {
|
|
|
|
|
fun.accept(pmOld);
|
|
|
|
|
area.reset();
|
|
|
|
|
} else {
|
|
|
|
|
area.append(o.getOutline(), false);
|
2017-05-30 09:33:28 +00:00
|
|
|
}
|
2017-02-08 07:47:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-07-22 21:29:55 +00:00
|
|
|
|
|
|
|
|
if (area.getCurrentPoint() != null) {
|
|
|
|
|
fun.accept(pm);
|
|
|
|
|
}
|
2017-02-08 07:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// then draw any content within this shape (text, image, etc.)
|
|
|
|
|
drawContent(graphics);
|
|
|
|
|
|
|
|
|
|
// then stroke the shape outline
|
|
|
|
|
if(line != null) {
|
|
|
|
|
graphics.setPaint(line);
|
|
|
|
|
graphics.setStroke(stroke);
|
|
|
|
|
for(Outline o : elems){
|
|
|
|
|
if(o.getPath().isStroked()){
|
|
|
|
|
java.awt.Shape s = o.getOutline();
|
|
|
|
|
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
|
|
|
|
|
graphics.draw(s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 21:24:06 +00:00
|
|
|
// draw line decorations
|
2017-02-08 07:47:30 +00:00
|
|
|
drawDecoration(graphics, line, stroke);
|
2019-09-11 21:24:06 +00:00
|
|
|
|
|
|
|
|
graphics.setColor(oldColor);
|
|
|
|
|
graphics.setPaint(oldPaint);
|
|
|
|
|
graphics.setStroke(oldStroke);
|
2017-02-08 07:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
2019-07-22 21:29:55 +00:00
|
|
|
private void fillArea(Graphics2D graphics, PaintModifier pm, Path2D area) {
|
|
|
|
|
final SimpleShape<?, ?> ss = getShape();
|
|
|
|
|
final PaintStyle ps = ss.getFillStyle().getPaint();
|
|
|
|
|
final DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(ss);
|
|
|
|
|
final Paint fillMod = drawPaint.getPaint(graphics, ps, pm);
|
|
|
|
|
if (fillMod != null) {
|
|
|
|
|
graphics.setPaint(fillMod);
|
|
|
|
|
fillPaintWorkaround(graphics, area);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Paint getFillPaint(Graphics2D graphics) {
|
|
|
|
|
DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape());
|
2020-03-21 18:25:38 +00:00
|
|
|
return drawPaint.getPaint(graphics, getShape().getFillStyle().getPaint());
|
2019-07-22 21:29:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Paint getLinePaint(Graphics2D graphics) {
|
|
|
|
|
DrawPaint drawPaint = DrawFactory.getInstance(graphics).getPaint(getShape());
|
|
|
|
|
return drawPaint.getPaint(graphics, getShape().getStrokeStyle().getPaint());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-02-08 07:47:30 +00:00
|
|
|
protected void drawDecoration(Graphics2D graphics, Paint line, BasicStroke stroke) {
|
|
|
|
|
if(line == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
graphics.setPaint(line);
|
|
|
|
|
|
2017-09-16 08:27:23 +00:00
|
|
|
List<Outline> lst = new ArrayList<>();
|
2017-02-08 07:47:30 +00:00
|
|
|
LineDecoration deco = getShape().getLineDecoration();
|
|
|
|
|
Outline head = getHeadDecoration(graphics, deco, stroke);
|
|
|
|
|
if (head != null) {
|
|
|
|
|
lst.add(head);
|
|
|
|
|
}
|
|
|
|
|
Outline tail = getTailDecoration(graphics, deco, stroke);
|
|
|
|
|
if (tail != null) {
|
|
|
|
|
lst.add(tail);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(Outline o : lst){
|
|
|
|
|
java.awt.Shape s = o.getOutline();
|
|
|
|
|
Path p = o.getPath();
|
|
|
|
|
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
|
|
|
|
|
|
|
|
|
|
if(p.isFilled()) {
|
|
|
|
|
graphics.fill(s);
|
|
|
|
|
}
|
|
|
|
|
if(p.isStroked()) {
|
|
|
|
|
graphics.draw(s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Outline getTailDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) {
|
|
|
|
|
if (deco == null || stroke == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
DecorationSize tailLength = deco.getTailLength();
|
|
|
|
|
if (tailLength == null) {
|
|
|
|
|
tailLength = DecorationSize.MEDIUM;
|
|
|
|
|
}
|
|
|
|
|
DecorationSize tailWidth = deco.getTailWidth();
|
|
|
|
|
if (tailWidth == null) {
|
|
|
|
|
tailWidth = DecorationSize.MEDIUM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double lineWidth = Math.max(2.5, stroke.getLineWidth());
|
|
|
|
|
|
|
|
|
|
Rectangle2D anchor = getAnchor(graphics, getShape());
|
|
|
|
|
double x2 = anchor.getX() + anchor.getWidth(),
|
|
|
|
|
y2 = anchor.getY() + anchor.getHeight();
|
|
|
|
|
|
|
|
|
|
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
|
|
|
|
|
|
|
|
|
|
AffineTransform at = new AffineTransform();
|
|
|
|
|
java.awt.Shape tailShape = null;
|
|
|
|
|
Path p = null;
|
|
|
|
|
Rectangle2D bounds;
|
|
|
|
|
final double scaleY = Math.pow(DECO_SIZE_POW, tailWidth.ordinal()+1.);
|
|
|
|
|
final double scaleX = Math.pow(DECO_SIZE_POW, tailLength.ordinal()+1.);
|
|
|
|
|
|
|
|
|
|
DecorationShape tailShapeEnum = deco.getTailShape();
|
|
|
|
|
|
|
|
|
|
if (tailShapeEnum == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (tailShapeEnum) {
|
|
|
|
|
case OVAL:
|
|
|
|
|
p = new Path();
|
|
|
|
|
tailShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
|
|
|
|
|
bounds = tailShape.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 STEALTH:
|
|
|
|
|
case ARROW:
|
|
|
|
|
p = new Path(false, true);
|
|
|
|
|
Path2D.Double arrow = new Path2D.Double();
|
|
|
|
|
arrow.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2));
|
|
|
|
|
arrow.lineTo(0, 0);
|
|
|
|
|
arrow.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2));
|
|
|
|
|
tailShape = arrow;
|
|
|
|
|
at.translate(x2, y2);
|
|
|
|
|
at.rotate(alpha);
|
|
|
|
|
break;
|
|
|
|
|
case TRIANGLE:
|
|
|
|
|
p = new Path();
|
|
|
|
|
Path2D.Double triangle = new Path2D.Double();
|
|
|
|
|
triangle.moveTo((-lineWidth * scaleX), (-lineWidth * scaleY / 2));
|
|
|
|
|
triangle.lineTo(0, 0);
|
|
|
|
|
triangle.lineTo((-lineWidth * scaleX), (lineWidth * scaleY / 2));
|
|
|
|
|
triangle.closePath();
|
|
|
|
|
tailShape = triangle;
|
|
|
|
|
at.translate(x2, y2);
|
|
|
|
|
at.rotate(alpha);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tailShape != null) {
|
|
|
|
|
tailShape = at.createTransformedShape(tailShape);
|
|
|
|
|
}
|
|
|
|
|
return tailShape == null ? null : new Outline(tailShape, p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Outline getHeadDecoration(Graphics2D graphics, LineDecoration deco, BasicStroke stroke) {
|
|
|
|
|
if (deco == null || stroke == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
DecorationSize headLength = deco.getHeadLength();
|
|
|
|
|
if (headLength == null) {
|
|
|
|
|
headLength = DecorationSize.MEDIUM;
|
|
|
|
|
}
|
|
|
|
|
DecorationSize headWidth = deco.getHeadWidth();
|
|
|
|
|
if (headWidth == null) {
|
|
|
|
|
headWidth = DecorationSize.MEDIUM;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double lineWidth = Math.max(2.5, stroke.getLineWidth());
|
|
|
|
|
|
|
|
|
|
Rectangle2D anchor = getAnchor(graphics, getShape());
|
|
|
|
|
double x1 = anchor.getX(), y1 = anchor.getY();
|
|
|
|
|
|
|
|
|
|
double alpha = Math.atan(anchor.getHeight() / anchor.getWidth());
|
|
|
|
|
|
|
|
|
|
AffineTransform at = new AffineTransform();
|
|
|
|
|
java.awt.Shape headShape = null;
|
|
|
|
|
Path p = null;
|
|
|
|
|
Rectangle2D bounds;
|
|
|
|
|
final double scaleY = Math.pow(DECO_SIZE_POW, headWidth.ordinal()+1.);
|
|
|
|
|
final double scaleX = Math.pow(DECO_SIZE_POW, headLength.ordinal()+1.);
|
|
|
|
|
DecorationShape headShapeEnum = deco.getHeadShape();
|
|
|
|
|
|
|
|
|
|
if (headShapeEnum == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (headShapeEnum) {
|
|
|
|
|
case OVAL:
|
|
|
|
|
p = new Path();
|
|
|
|
|
headShape = new Ellipse2D.Double(0, 0, lineWidth * scaleX, lineWidth * scaleY);
|
|
|
|
|
bounds = headShape.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);
|
|
|
|
|
Path2D.Double arrow = new Path2D.Double();
|
|
|
|
|
arrow.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2));
|
|
|
|
|
arrow.lineTo(0, 0);
|
|
|
|
|
arrow.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2));
|
|
|
|
|
headShape = arrow;
|
|
|
|
|
at.translate(x1, y1);
|
|
|
|
|
at.rotate(alpha);
|
|
|
|
|
break;
|
|
|
|
|
case TRIANGLE:
|
|
|
|
|
p = new Path();
|
|
|
|
|
Path2D.Double triangle = new Path2D.Double();
|
|
|
|
|
triangle.moveTo((lineWidth * scaleX), (-lineWidth * scaleY / 2));
|
|
|
|
|
triangle.lineTo(0, 0);
|
|
|
|
|
triangle.lineTo((lineWidth * scaleX), (lineWidth * scaleY / 2));
|
|
|
|
|
triangle.closePath();
|
|
|
|
|
headShape = triangle;
|
|
|
|
|
at.translate(x1, y1);
|
|
|
|
|
at.rotate(alpha);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (headShape != null) {
|
|
|
|
|
headShape = at.createTransformedShape(headShape);
|
|
|
|
|
}
|
|
|
|
|
return headShape == null ? null : new Outline(headShape, p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public BasicStroke getStroke() {
|
|
|
|
|
return getStroke(getShape().getStrokeStyle());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void drawShadow(
|
|
|
|
|
Graphics2D graphics
|
|
|
|
|
, Collection<Outline> outlines
|
|
|
|
|
, Paint fill
|
|
|
|
|
, Paint line
|
|
|
|
|
) {
|
2019-05-10 20:55:24 +00:00
|
|
|
Shadow<?,?> shadow = getShape().getShadow();
|
|
|
|
|
if (shadow == null || (fill == null && line == null)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-02-08 07:47:30 +00:00
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
SolidPaint shadowPaint = shadow.getFillStyle();
|
|
|
|
|
Color shadowColor = DrawPaint.applyColorTransform(shadowPaint.getSolidColor());
|
2017-02-08 07:47:30 +00:00
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
double shapeRotation = getShape().getRotation();
|
|
|
|
|
if (getShape().getFlipVertical()) {
|
|
|
|
|
shapeRotation += 180;
|
|
|
|
|
}
|
|
|
|
|
double angle = shadow.getAngle() - shapeRotation;
|
|
|
|
|
double dist = shadow.getDistance();
|
|
|
|
|
double dx = dist * Math.cos(Math.toRadians(angle));
|
|
|
|
|
double dy = dist * Math.sin(Math.toRadians(angle));
|
2017-02-08 07:47:30 +00:00
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
graphics.translate(dx, dy);
|
2017-02-08 07:47:30 +00:00
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
for (Outline o : outlines) {
|
|
|
|
|
java.awt.Shape s = o.getOutline();
|
|
|
|
|
Path p = o.getPath();
|
|
|
|
|
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
|
|
|
|
|
graphics.setPaint(shadowColor);
|
2017-05-30 09:33:28 +00:00
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
if (fill != null && p.isFilled()) {
|
|
|
|
|
fillPaintWorkaround(graphics, s);
|
|
|
|
|
} else if (line != null && p.isStroked()) {
|
|
|
|
|
graphics.draw(s);
|
2017-02-08 07:47:30 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-10 20:55:24 +00:00
|
|
|
graphics.translate(-dx, -dy);
|
2017-02-08 07:47:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Collection<Outline> computeOutlines(Graphics2D graphics) {
|
2017-05-30 09:33:28 +00:00
|
|
|
final SimpleShape<?,?> sh = getShape();
|
2017-02-08 07:47:30 +00:00
|
|
|
|
2017-09-16 08:27:23 +00:00
|
|
|
List<Outline> lst = new ArrayList<>();
|
2017-05-30 09:33:28 +00:00
|
|
|
CustomGeometry geom = sh.getGeometry();
|
2017-02-08 07:47:30 +00:00
|
|
|
if(geom == null) {
|
|
|
|
|
return lst;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-30 09:33:28 +00:00
|
|
|
Rectangle2D anchor = getAnchor(graphics, sh);
|
2018-04-04 19:40:54 +00:00
|
|
|
if(anchor == null) {
|
|
|
|
|
return lst;
|
|
|
|
|
}
|
2017-02-08 07:47:30 +00:00
|
|
|
for (Path p : geom) {
|
|
|
|
|
|
2018-12-09 01:06:15 +00:00
|
|
|
double w = p.getW(), h = p.getH(), scaleX, scaleY;
|
2017-05-30 09:33:28 +00:00
|
|
|
if (w == -1) {
|
|
|
|
|
w = Units.toEMU(anchor.getWidth());
|
2018-12-09 01:06:15 +00:00
|
|
|
scaleX = Units.toPoints(1);
|
|
|
|
|
} else if (anchor.getWidth() == 0) {
|
|
|
|
|
scaleX = 1;
|
2017-05-30 09:33:28 +00:00
|
|
|
} else {
|
|
|
|
|
scaleX = anchor.getWidth() / w;
|
|
|
|
|
}
|
|
|
|
|
if (h == -1) {
|
|
|
|
|
h = Units.toEMU(anchor.getHeight());
|
2018-12-09 01:06:15 +00:00
|
|
|
scaleY = Units.toPoints(1);
|
|
|
|
|
} else if (anchor.getHeight() == 0) {
|
|
|
|
|
scaleY = 1;
|
2017-05-30 09:33:28 +00:00
|
|
|
} else {
|
|
|
|
|
scaleY = anchor.getHeight() / h;
|
|
|
|
|
}
|
2017-02-08 07:47:30 +00:00
|
|
|
|
|
|
|
|
// the guides in the shape definitions are all defined relative to each other,
|
|
|
|
|
// so we build the path starting from (0,0).
|
|
|
|
|
final Rectangle2D pathAnchor = new Rectangle2D.Double(0,0,w,h);
|
|
|
|
|
|
2017-05-30 09:33:28 +00:00
|
|
|
Context ctx = new Context(geom, pathAnchor, sh);
|
2017-02-08 07:47:30 +00:00
|
|
|
|
|
|
|
|
java.awt.Shape gp = p.getPath(ctx);
|
|
|
|
|
|
|
|
|
|
// translate the result to the canvas coordinates in points
|
|
|
|
|
AffineTransform at = new AffineTransform();
|
|
|
|
|
at.translate(anchor.getX(), anchor.getY());
|
|
|
|
|
at.scale(scaleX, scaleY);
|
|
|
|
|
|
|
|
|
|
java.awt.Shape canvasShape = at.createTransformedShape(gp);
|
|
|
|
|
|
|
|
|
|
lst.add(new Outline(canvasShape, p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected SimpleShape<?,?> getShape() {
|
|
|
|
|
return (SimpleShape<?,?>)shape;
|
|
|
|
|
}
|
|
|
|
|
}
|