package com.kreative.paint.document.draw;
import java.awt.geom.GeneralPath;
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 PathContour implements Cloneable, List<PathPoint> {
private List<PathPoint> points;
private boolean closed;
public PathContour() {
this.points = new ArrayList<PathPoint>();
this.closed = false;
}
private PathContour(PathContour o) {
this.points = new ArrayList<PathPoint>();
for (PathPoint p : o.points) this.points.add(p.clone());
this.closed = o.closed;
}
@Override
public PathContour clone() {
return new PathContour(this);
}
public GeneralPath toAWTShape() {
GeneralPath path = new GeneralPath();
appendTo(path);
return path;
}
public void appendTo(GeneralPath path) {
if (points.isEmpty()) return;
PathPoint p1 = points.get(0);
path.moveTo(p1.getX(), p1.getY());
for (int i = 1, n = points.size(); i < n; i++) {
PathPoint p2 = points.get(i);
appendSegment(path, p1, p2);
p1 = p2;
}
if (closed) {
PathPoint p2 = points.get(0);
appendSegment(path, p1, p2);
path.closePath();
}
}
private static void appendSegment(GeneralPath path, PathPoint p1, PathPoint p2) {
if (p1.isNextLinear() && p2.isPreviousLinear()) {
path.lineTo(p2.getX(), p2.getY());
} else {
Point2D cp1 = p1.getNextCtrl();
Point2D cp2 = p2.getPreviousCtrl();
if (p1.isNextQuadratic() || p2.isPreviousQuadratic()) {
double cx = (cp1.getX() + cp2.getX()) / 2;
double cy = (cp1.getY() + cp2.getY()) / 2;
path.quadTo(cx, cy, p2.getX(), p2.getY());
} else {
path.curveTo(
cp1.getX(), cp1.getY(),
cp2.getX(), cp2.getY(),
p2.getX(), p2.getY()
);
}
}
}
@Override
public boolean add(PathPoint p) {
return points.add(p);
}
@Override
public void add(int index, PathPoint p) {
points.add(index, p);
}
@Override
public boolean addAll(Collection<? extends PathPoint> c) {
return points.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends PathPoint> c) {
return points.addAll(index, c);
}
@Override
public void clear() {
points.clear();
closed = false;
}
@Override
public boolean contains(Object o) {
return points.contains(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return points.containsAll(c);
}
@Override
public PathPoint get(int index) {
return points.get(index);
}
@Override
public int indexOf(Object o) {
return points.indexOf(o);
}
@Override
public boolean isEmpty() {
return points.isEmpty();
}
@Override
public Iterator<PathPoint> iterator() {
return points.iterator();
}
@Override
public int lastIndexOf(Object o) {
return points.lastIndexOf(o);
}
@Override
public ListIterator<PathPoint> listIterator() {
return points.listIterator();
}
@Override
public ListIterator<PathPoint> listIterator(int index) {
return points.listIterator(index);
}
@Override
public boolean remove(Object o) {
return points.remove(o);
}
@Override
public PathPoint remove(int index) {
return points.remove(index);
}
@Override
public boolean removeAll(Collection<?> c) {
return points.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return points.retainAll(c);
}
@Override
public PathPoint set(int index, PathPoint p) {
return points.set(index, p);
}
@Override
public int size() {
return points.size();
}
@Override
public List<PathPoint> subList(int start, int end) {
return points.subList(start, end);
}
@Override
public Object[] toArray() {
return points.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return points.toArray(a);
}
public boolean isClosed() {
return closed;
}
public void setClosed(boolean closed) {
this.closed = closed;
}
@Override
public boolean equals(Object that) {
if (that instanceof PathContour) {
return (this.points.equals(((PathContour)that).points))
&& (this.closed == ((PathContour)that).closed);
} else {
return false;
}
}
@Override
public int hashCode() {
return points.hashCode() ^ (closed ? -1 : 0);
}
}