// Copyright 2000-2003 FreeHEP package org.freehep.graphicsio.java; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.FlatteningPathIterator; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; /** * @author Mark Donszelmann * @version $Id: JAVAGeneralPath.java 12619 2007-06-07 18:07:57Z duns $ */ public class JAVAGeneralPath implements Shape { private int rule; private PathElement[] path; private float minX, minY = Float.MAX_VALUE; private float maxX, maxY = Float.MIN_VALUE; public JAVAGeneralPath(int rule, PathElement[] path) { this.rule = rule; this.path = path; for (int i = 0; i < path.length; i++) { minX = Math.min(minX, path[i].getMinX()); maxX = Math.max(maxX, path[i].getMaxX()); minY = Math.min(minY, path[i].getMinY()); maxY = Math.max(maxY, path[i].getMaxY()); } } public static abstract class PathElement { public abstract float getMinX(); public abstract float getMaxX(); public abstract float getMinY(); public abstract float getMaxY(); public abstract int currentSegment(float[] coords); public abstract int currentSegment(double[] coords); } public static abstract class Point extends PathElement { private float x, y; public Point(float x, float y) { this.x = x; this.y = y; } public float getMinX() { return x; } public float getMaxX() { return x; } public float getMinY() { return y; } public float getMaxY() { return y; } protected void fill(float[] coords) { coords[0] = x; coords[1] = y; } protected void fill(double[] coords) { coords[0] = x; coords[1] = y; } } public static class MoveTo extends Point { public MoveTo(float x, float y) { super(x, y); } public int currentSegment(float[] coords) { fill(coords); return PathIterator.SEG_MOVETO; } public int currentSegment(double[] coords) { fill(coords); return PathIterator.SEG_MOVETO; } } public static class LineTo extends Point { public LineTo(float x, float y) { super(x, y); } public int currentSegment(float[] coords) { fill(coords); return PathIterator.SEG_LINETO; } public int currentSegment(double[] coords) { fill(coords); return PathIterator.SEG_LINETO; } } public static class QuadTo extends PathElement { private float x1, y1, x2, y2; public QuadTo(float x1, float y1, float x2, float y2) { super(); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public float getMinX() { return Math.min(x1, x2); } public float getMaxX() { return Math.max(x1, x2); } public float getMinY() { return Math.min(y1, y2); } public float getMaxY() { return Math.max(y1, y2); } public int currentSegment(float[] coords) { coords[0] = x1; coords[1] = y1; coords[2] = x2; coords[3] = y2; return PathIterator.SEG_QUADTO; } public int currentSegment(double[] coords) { coords[0] = x1; coords[1] = y1; coords[2] = x2; coords[3] = y2; return PathIterator.SEG_QUADTO; } } public static class CurveTo extends PathElement { private float x1, y1, x2, y2, x3, y3; public CurveTo(float x1, float y1, float x2, float y2, float x3, float y3) { super(); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; } public float getMinX() { return Math.min(x1, Math.min(x2, x3)); } public float getMaxX() { return Math.max(x1, Math.max(x2, x3)); } public float getMinY() { return Math.min(y1, Math.min(y2, y3)); } public float getMaxY() { return Math.max(y1, Math.max(y2, y3)); } public int currentSegment(float[] coords) { coords[0] = x1; coords[1] = y1; coords[2] = x2; coords[3] = y2; coords[4] = x3; coords[5] = y3; return PathIterator.SEG_CUBICTO; } public int currentSegment(double[] coords) { coords[0] = x1; coords[1] = y1; coords[2] = x2; coords[3] = y2; coords[4] = x3; coords[5] = y3; return PathIterator.SEG_CUBICTO; } } public static class ClosePath extends PathElement { public ClosePath() { super(); } public float getMinX() { return Float.MAX_VALUE; } public float getMaxX() { return Float.MIN_VALUE; } public float getMinY() { return Float.MAX_VALUE; } public float getMaxY() { return Float.MIN_VALUE; } public int currentSegment(float[] coords) { return PathIterator.SEG_CLOSE; } public int currentSegment(double[] coords) { return PathIterator.SEG_CLOSE; } } public Rectangle getBounds() { return getBounds2D().getBounds(); } public Rectangle2D getBounds2D() { return new Rectangle2D.Float(minX, minY, maxX - minX, maxY - minY); } // approximation public boolean contains(double x, double y) { return getBounds2D().contains(x, y); } public boolean contains(Point2D p) { return contains(p.getX(), p.getY()); } // approximation public boolean intersects(double x, double y, double w, double h) { return getBounds2D().intersects(x, y, w, h); } public boolean intersects(Rectangle2D r) { return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } // approximation public boolean contains(double x, double y, double w, double h) { return getBounds2D().contains(x, y, w, h); } public boolean contains(Rectangle2D r) { return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } public PathIterator getPathIterator(final AffineTransform at) { return new PathIterator() { private int index = 0; private AffineTransform transform = at; public int getWindingRule() { return rule; } public boolean isDone() { return index >= path.length; } public void next() { if (!isDone()) index++; } public int currentSegment(float[] coords) { int type = path[index].currentSegment(coords); if (transform != null) transform.transform(coords, 0, coords, 0, coords.length / 2); return type; } public int currentSegment(double[] coords) { int type = path[index].currentSegment(coords); if (transform != null) transform.transform(coords, 0, coords, 0, coords.length / 2); return type; } }; } public PathIterator getPathIterator(AffineTransform at, double flatness) { return new FlatteningPathIterator(getPathIterator(at), flatness); } }