package com.kreative.paint.document.draw;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Path implements Cloneable, List<PathContour> {
private List<PathContour> contours;
public Path() {
this.contours = new ArrayList<PathContour>();
}
private Path(Path o) {
this.contours = new ArrayList<PathContour>();
for (PathContour c : o.contours) this.contours.add(c.clone());
}
@Override
public Path clone() {
return new Path(this);
}
public GeneralPath toAWTShape() {
GeneralPath path = new GeneralPath();
appendTo(path);
return path;
}
public void appendTo(GeneralPath path) {
for (PathContour c : contours) c.appendTo(path);
}
public void appendAWTShape(Shape s) {
if (s == null) return;
PathPoint firstPoint = new PathPoint(0, 0);
PathPoint currPoint = firstPoint;
PathContour currContour = null;
double[] coords = new double[6];
for (PathIterator p = s.getPathIterator(null); !p.isDone(); p.next()) {
int type = p.currentSegment(coords);
switch (type) {
case PathIterator.SEG_MOVETO:
firstPoint = new PathPoint(coords[0], coords[1]);
currPoint = firstPoint;
currContour = null;
break;
case PathIterator.SEG_CLOSE:
if (currContour != null) {
currContour.setClosed(true);
firstPoint = new PathPoint(firstPoint.getX(), firstPoint.getY());
currPoint = firstPoint;
currContour = null;
}
break;
default:
if (currContour == null) {
contours.add(currContour = new PathContour());
currContour.add(currPoint);
}
Point2D ep = getSegmentEndpoint(type, coords);
if (ep.getX() == firstPoint.getX() && ep.getY() == firstPoint.getY()) {
setSegmentControlPoints(type, coords, currPoint, firstPoint);
currContour.setClosed(true);
firstPoint = new PathPoint(firstPoint.getX(), firstPoint.getY());
currPoint = firstPoint;
currContour = null;
} else {
PathPoint nextPoint = new PathPoint(ep.getX(), ep.getY());
setSegmentControlPoints(type, coords, currPoint, nextPoint);
currContour.add(currPoint = nextPoint);
}
break;
}
}
}
private static Point2D getSegmentEndpoint(int type, double[] coords) {
switch (type) {
case PathIterator.SEG_LINETO:
return new Point2D.Double(coords[0], coords[1]);
case PathIterator.SEG_QUADTO:
return new Point2D.Double(coords[2], coords[3]);
case PathIterator.SEG_CUBICTO:
return new Point2D.Double(coords[4], coords[5]);
default:
return null;
}
}
private static void setSegmentControlPoints(int type, double[] coords, PathPoint p1, PathPoint p2) {
switch (type) {
case PathIterator.SEG_LINETO:
p1.setNextLinear();
p2.setPreviousLinear();
break;
case PathIterator.SEG_QUADTO:
p1.setNextCtrl(coords[0], coords[1]);
p1.setNextQuadratic(true);
p2.setPreviousCtrl(coords[0], coords[1]);
p2.setPreviousQuadratic(true);
break;
case PathIterator.SEG_CUBICTO:
p1.setNextCtrl(coords[0], coords[1]);
p1.setNextQuadratic(false);
p2.setPreviousCtrl(coords[2], coords[3]);
p2.setPreviousQuadratic(false);
break;
}
}
@Override
public boolean add(PathContour c) {
return contours.add(c);
}
@Override
public void add(int index, PathContour c) {
contours.add(index, c);
}
@Override
public boolean addAll(Collection<? extends PathContour> c) {
return contours.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends PathContour> c) {
return contours.addAll(index, c);
}
@Override
public void clear() {
contours.clear();
}
@Override
public boolean contains(Object o) {
return contours.contains(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return contours.containsAll(c);
}
@Override
public PathContour get(int index) {
return contours.get(index);
}
@Override
public int indexOf(Object o) {
return contours.indexOf(o);
}
@Override
public boolean isEmpty() {
return contours.isEmpty();
}
@Override
public Iterator<PathContour> iterator() {
return contours.iterator();
}
@Override
public int lastIndexOf(Object o) {
return contours.lastIndexOf(o);
}
@Override
public ListIterator<PathContour> listIterator() {
return contours.listIterator();
}
@Override
public ListIterator<PathContour> listIterator(int index) {
return contours.listIterator(index);
}
@Override
public boolean remove(Object o) {
return contours.remove(o);
}
@Override
public PathContour remove(int index) {
return contours.remove(index);
}
@Override
public boolean removeAll(Collection<?> c) {
return contours.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return contours.retainAll(c);
}
@Override
public PathContour set(int index, PathContour c) {
return contours.set(index, c);
}
@Override
public int size() {
return contours.size();
}
@Override
public List<PathContour> subList(int start, int end) {
return contours.subList(start, end);
}
@Override
public Object[] toArray() {
return contours.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return contours.toArray(a);
}
@Override
public boolean equals(Object that) {
if (that instanceof Path) {
return this.contours.equals(((Path)that).contours);
} else {
return false;
}
}
@Override
public int hashCode() {
return contours.hashCode();
}
}