/*
* @(#)GrowStroke.java
*
* Copyright (c) 1996-2010 The authors and contributors of JHotDraw.
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.geom;
import java.awt.BasicStroke;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
/**
* GrowStroke can be used to grow/shrink a figure by a specified line width.
* This only works with closed convex paths having edges in clockwise direction.
* <p>
* Note: Although this is a Stroke object, it does not actually create a stroked
* shape, but one that can be used for filling.
*
* @author Werner Randelshofer.
* @version $Id$
*/
public class GrowStroke extends DoubleStroke {
private double grow;
public GrowStroke(double grow, double miterLimit) {
super(grow * 2d, 1d, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_BEVEL, miterLimit, null, 0f);
this.grow = grow;
}
@Override
public Shape createStrokedShape(Shape s) {
BezierPath bp = new BezierPath();
Path2D.Double left = new Path2D.Double();
Path2D.Double right = new Path2D.Double();
if (s instanceof Path2D.Double) {
left.setWindingRule(((Path2D.Double) s).getWindingRule());
right.setWindingRule(((Path2D.Double) s).getWindingRule());
} else if (s instanceof BezierPath) {
left.setWindingRule(((BezierPath) s).getWindingRule());
right.setWindingRule(((BezierPath) s).getWindingRule());
}
double[] coords = new double[6];
// FIXME - We only do a flattened path
for (PathIterator i = s.getPathIterator(null, 0.1d); !i.isDone(); i.next()) {
int type = i.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
if (bp.size() != 0) {
traceStroke(bp, left, right);
}
bp.clear();
bp.moveTo(coords[0], coords[1]);
break;
case PathIterator.SEG_LINETO:
if (coords[0] != bp.get(bp.size() - 1).x[0]
|| coords[1] != bp.get(bp.size() - 1).y[0]) {
bp.lineTo(coords[0], coords[1]);
}
break;
case PathIterator.SEG_QUADTO:
bp.quadTo(coords[0], coords[1], coords[2], coords[3]);
break;
case PathIterator.SEG_CUBICTO:
bp.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
break;
case PathIterator.SEG_CLOSE:
bp.setClosed(true);
break;
}
}
if (bp.size() > 1) {
traceStroke(bp, left, right);
}
if (Geom.contains(left.getBounds2D(), right.getBounds2D())) {
return (grow > 0) ? left : right;
} else {
return (grow > 0) ? right : left;
}
}
}