package com.kreative.paint.document.draw; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Area; import java.awt.geom.CubicCurve2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.QuadCurve2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import com.kreative.paint.document.undo.Atom; public abstract class ShapeDrawObject extends DrawObject { public static ShapeDrawObject forShape(PaintSettings ps, Shape s) { if (s instanceof Line2D) { Line2D l = (Line2D)s; return new Line(ps, l.getX1(), l.getY1(), l.getX2(), l.getY2()); } else if (s instanceof Rectangle2D) { Rectangle2D r = (Rectangle2D)s; return new Rectangle(ps, r.getX(), r.getY(), r.getWidth(), r.getHeight()); } else if (s instanceof RoundRectangle2D) { RoundRectangle2D r = (RoundRectangle2D)s; return new RoundRectangle(ps, r.getX(), r.getY(), r.getWidth(), r.getHeight(), r.getArcWidth(), r.getArcHeight()); } else if (s instanceof Ellipse2D) { Ellipse2D e = (Ellipse2D)s; return new Ellipse(ps, e.getX(), e.getY(), e.getWidth(), e.getHeight()); } else if (s instanceof Arc2D) { Arc2D a = (Arc2D)s; return new Arc(ps, a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(), a.getAngleExtent(), ArcType.forAWTValue(a.getArcType())); } else if (s instanceof QuadCurve2D) { QuadCurve2D q = (QuadCurve2D)s; return new QuadCurve(ps, q.getX1(), q.getY1(), q.getCtrlX(), q.getCtrlY(), q.getX2(), q.getY2()); } else if (s instanceof CubicCurve2D) { CubicCurve2D c = (CubicCurve2D)s; return new CubicCurve(ps, c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(), c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); } else if (s instanceof java.awt.Polygon) { java.awt.Polygon p = (java.awt.Polygon)s; return new Polygon(ps, p.xpoints, p.ypoints, p.npoints, true); } else { return new PathDrawObject(ps, s); } } protected ShadowSettings shadow; protected ShapeDrawObject(PaintSettings ps) { super(ps); this.shadow = null; } protected ShapeDrawObject(ShapeDrawObject original) { super(original); this.shadow = original.shadow; } public ShadowSettings getShadowSettings() { return shadow; } private static class ShadowSettingsAtom implements Atom { private ShapeDrawObject d; private ShadowSettings oldShadow; private ShadowSettings newShadow; public ShadowSettingsAtom(ShapeDrawObject d, ShadowSettings newShadow) { this.d = d; this.oldShadow = d.shadow; this.newShadow = newShadow; } @Override public boolean canBuildUpon(Atom prev) { return (prev instanceof ShadowSettingsAtom) && (((ShadowSettingsAtom)prev).d == this.d); } @Override public Atom buildUpon(Atom prev) { this.oldShadow = ((ShadowSettingsAtom)prev).oldShadow; return this; } @Override public void undo() { d.shadow = oldShadow; d.notifyDrawObjectListeners(DrawObjectEvent.DRAW_OBJECT_IMPLEMENTATION_PROPERTY_CHANGED); } @Override public void redo() { d.shadow = newShadow; d.notifyDrawObjectListeners(DrawObjectEvent.DRAW_OBJECT_IMPLEMENTATION_PROPERTY_CHANGED); } } public void setShadowSettings(ShadowSettings shadow) { if (equals(this.shadow, shadow)) return; if (history != null) history.add(new ShadowSettingsAtom(this, shadow)); this.shadow = shadow; this.notifyDrawObjectListeners(DrawObjectEvent.DRAW_OBJECT_IMPLEMENTATION_PROPERTY_CHANGED); } @Override public abstract ShapeDrawObject clone(); public abstract Shape getShape(); @Override protected Shape getBoundaryImpl() { return getShape(); } @Override protected Shape getPostTxHitAreaImpl(AffineTransform tx) { Shape s = getShape(); if (tx != null) { try { s = tx.createTransformedShape(s); } catch (Exception e) { s = getShape(); } } Area a = new Area(); if (ps.isFilled()) { a.add(new Area(s)); } if (ps.isDrawn()) { try { a.add(new Area(ps.drawStroke.createStrokedShape(s))); } catch (Exception e) {} } return a; } @Override protected void preTxPaintImpl(Graphics2D g, AffineTransform tx) { Shape s = getShape(); if (tx != null) { try { s = tx.createTransformedShape(s); } catch (Exception e) { s = getShape(); } } if (shadow != null && shadow.isShadowed()) { AffineTransform t = g.getTransform(); shadow.apply(g, ps); Area a = new Area(); if (ps.isFilled()) { a.add(new Area(s)); } if (ps.isDrawn()) { try { a.add(new Area(ps.drawStroke.createStrokedShape(s))); } catch (Exception e) {} } g.fill(a); g.setTransform(t); } if (ps.isFilled()) { ps.applyFill(g); g.fill(s); } if (ps.isDrawn()) { ps.applyDraw(g); g.draw(s); } } public static class Line extends ShapeDrawObject { private double x1, y1, x2, y2; public Line(PaintSettings ps, double x1, double y1, double x2, double y2) { super(ps); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } private Line(Line o) { super(o); this.x1 = o.x1; this.y1 = o.y1; this.x2 = o.x2; this.y2 = o.y2; } @Override public Line clone() { return new Line(this); } @Override public Line2D getShape() { return new Line2D.Double(x1, y1, x2, y2); } @Override protected Object getControlState() { return new double[]{ x1, y1, x2, y2 }; } @Override protected void setControlState(Object o) { double[] state = (double[])o; x1 = state[0]; y1 = state[1]; x2 = state[2]; y2 = state[3]; } @Override public int getControlPointCount() { return 2; } @Override protected ControlPoint getControlPointImpl(int i) { switch (i) { case 0: return new ControlPoint(ControlPointType.ENDPOINT, x1, y1); case 1: return new ControlPoint(ControlPointType.ENDPOINT, x2, y2); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x1, y1)); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x2, y2)); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { return null; } @Override protected int setControlPointImpl(int i, double x, double y) { switch (i) { case 0: this.x1 = x; this.y1 = y; break; case 1: this.x2 = x; this.y2 = y; break; } return i; } @Override protected Point2D getLocationImpl() { return new Point2D.Double(x1, y1); } @Override protected void setLocationImpl(double x, double y) { this.x2 = x + (this.x2 - this.x1); this.y2 = y + (this.y2 - this.y1); this.x1 = x; this.y1 = y; } } public static abstract class RectangularShape extends ShapeDrawObject { protected double x1, y1, x2, y2; protected RectangularShape(PaintSettings ps, double x1, double y1, double x2, double y2) { super(ps); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } protected RectangularShape(RectangularShape o) { super(o); this.x1 = o.x1; this.y1 = o.y1; this.x2 = o.x2; this.y2 = o.y2; } @Override public abstract RectangularShape clone(); @Override public abstract Shape getShape(); @Override protected Object getControlState() { return new double[]{ x1, y1, x2, y2 }; } @Override protected void setControlState(Object o) { double[] state = (double[])o; x1 = state[0]; y1 = state[1]; x2 = state[2]; y2 = state[3]; } @Override public int getControlPointCount() { return 9; } @Override protected ControlPoint getControlPointImpl(int i) { switch (i) { case 0: return new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2); case 1: return new ControlPoint(ControlPointType.NORTHWEST, x1, y1); case 2: return new ControlPoint(ControlPointType.NORTHEAST, x2, y1); case 3: return new ControlPoint(ControlPointType.SOUTHWEST, x1, y2); case 4: return new ControlPoint(ControlPointType.SOUTHEAST, x2, y2); case 5: return new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1); case 6: return new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2); case 7: return new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2); case 8: return new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); cpts.add(new ControlPoint(ControlPointType.CENTER, (x1 + x2) / 2, (y1 + y2) / 2)); cpts.add(new ControlPoint(ControlPointType.NORTHWEST, x1, y1)); cpts.add(new ControlPoint(ControlPointType.NORTHEAST, x2, y1)); cpts.add(new ControlPoint(ControlPointType.SOUTHWEST, x1, y2)); cpts.add(new ControlPoint(ControlPointType.SOUTHEAST, x2, y2)); cpts.add(new ControlPoint(ControlPointType.NORTH, (x1 + x2) / 2, y1)); cpts.add(new ControlPoint(ControlPointType.SOUTH, (x1 + x2) / 2, y2)); cpts.add(new ControlPoint(ControlPointType.WEST, x1, (y1 + y2) / 2)); cpts.add(new ControlPoint(ControlPointType.EAST, x2, (y1 + y2) / 2)); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { return null; } @Override protected int setControlPointImpl(int i, double x, double y) { switch (i) { case 0: double width2 = (x2 - x1) / 2; double height2 = (y2 - y1) / 2; x1 = x - width2; y1 = y - height2; x2 = x + width2; y2 = y + height2; break; case 1: x1 = x; y1 = y; break; case 2: x2 = x; y1 = y; break; case 3: x1 = x; y2 = y; break; case 4: x2 = x; y2 = y; break; case 5: y1 = y; break; case 6: y2 = y; break; case 7: x1 = x; break; case 8: x2 = x; break; } return i; } @Override protected Point2D getLocationImpl() { return new Point2D.Double(x1, y1); } @Override protected void setLocationImpl(double x, double y) { this.x2 = x + (this.x2 - this.x1); this.y2 = y + (this.y2 - this.y1); this.x1 = x; this.y1 = y; } } public static class Rectangle extends RectangularShape { public Rectangle(PaintSettings ps, double x, double y, double width, double height) { super(ps, x, y, x + width, y + height); } private Rectangle(Rectangle o) { super(o); } @Override public Rectangle clone() { return new Rectangle(this); } @Override public Rectangle2D getShape() { return new Rectangle2D.Double( Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1) ); } } public static class RoundRectangle extends RectangularShape { private double rx, ry; public RoundRectangle(PaintSettings ps, double x, double y, double width, double height, double rx, double ry) { super(ps, x, y, x + width, y + height); this.rx = rx; this.ry = ry; } private RoundRectangle(RoundRectangle o) { super(o); this.rx = o.rx; this.ry = o.ry; } @Override public RoundRectangle clone() { return new RoundRectangle(this); } @Override public RoundRectangle2D getShape() { return new RoundRectangle2D.Double( Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), rx, ry ); } } public static class Ellipse extends RectangularShape { public Ellipse(PaintSettings ps, double x, double y, double width, double height) { super(ps, x, y, x + width, y + height); } private Ellipse(Ellipse o) { super(o); } @Override public Ellipse clone() { return new Ellipse(this); } @Override public Ellipse2D getShape() { return new Ellipse2D.Double( Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1) ); } } public static class Arc extends RectangularShape { private double arcStart; private double arcExtent; private ArcType arcType; public Arc( PaintSettings ps, double x, double y, double width, double height, double arcStart, double arcExtent, ArcType arcType ) { super(ps, x, y, x + width, y + height); this.arcStart = arcStart; this.arcExtent = arcExtent; this.arcType = arcType; } private Arc(Arc o) { super(o); this.arcStart = o.arcStart; this.arcExtent = o.arcExtent; this.arcType = o.arcType; } @Override public Arc clone() { return new Arc(this); } @Override public Arc2D getShape() { return new Arc2D.Double( Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2 - x1), Math.abs(y2 - y1), arcStart, arcExtent, arcType.awtValue ); } @Override protected Object getControlState() { return new Object[]{ super.getControlState(), Double.valueOf(arcStart), Double.valueOf(arcExtent), arcType }; } @Override protected void setControlState(Object o) { Object[] state = (Object[])o; super.setControlState(state[0]); arcStart = ((Number)state[1]).doubleValue(); arcExtent = ((Number)state[2]).doubleValue(); arcType = (ArcType)state[3]; } @Override public int getControlPointCount() { int n = super.getControlPointCount(); return n + 2; } @Override protected ControlPoint getControlPointImpl(int i) { int n = super.getControlPointCount(); if (i < n) return super.getControlPointImpl(i); switch (i - n) { case 0: return new ControlPoint( ControlPointType.RADIUS, ((x1 + x2) / 2) + (Math.abs(x2 - x1) / 2) * Math.cos(Math.toRadians(arcStart)), ((y1 + y2) / 2) + (Math.abs(y2 - y1) / 2) * Math.sin(Math.toRadians(arcStart)) ); case 1: return new ControlPoint( ControlPointType.RADIUS, ((x1 + x2) / 2) + (Math.abs(x2 - x1) / 2) * Math.cos(Math.toRadians(arcStart + arcExtent)), ((y1 + y2) / 2) + (Math.abs(y2 - y1) / 2) * Math.sin(Math.toRadians(arcStart + arcExtent)) ); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = super.getControlPointsImpl(); cpts.add(new ControlPoint( ControlPointType.RADIUS, ((x1 + x2) / 2) + (Math.abs(x2 - x1) / 2) * Math.cos(Math.toRadians(arcStart)), ((y1 + y2) / 2) + (Math.abs(y2 - y1) / 2) * Math.sin(Math.toRadians(arcStart)) )); cpts.add(new ControlPoint( ControlPointType.RADIUS, ((x1 + x2) / 2) + (Math.abs(x2 - x1) / 2) * Math.cos(Math.toRadians(arcStart + arcExtent)), ((y1 + y2) / 2) + (Math.abs(y2 - y1) / 2) * Math.sin(Math.toRadians(arcStart + arcExtent)) )); return cpts; } @Override protected int setControlPointImpl(int i, double x, double y) { int n = super.getControlPointCount(); if (i < n) return super.setControlPointImpl(i, x, y); double a = Math.toDegrees(Math.atan2(y - (y1 + y2) / 2, x - (x1 + x2) / 2)); if (Double.isNaN(a) || Double.isInfinite(a)) return i; boolean negative = (arcExtent < 0); switch (i - n) { case 0: arcExtent = arcStart + arcExtent - a; arcStart = a; break; case 1: arcExtent = a - arcStart; break; } if (negative) { while (arcExtent < -360) arcExtent += 360; while (arcExtent > 0) arcExtent -= 360; } else { while (arcExtent < 0) arcExtent += 360; while (arcExtent > 360) arcExtent -= 360; } return i; } } public static abstract class CircularShape extends ShapeDrawObject { protected double cx, cy, ax, ay; protected CircularShape(PaintSettings ps, double cx, double cy, double ax, double ay) { super(ps); this.cx = cx; this.cy = cy; this.ax = ax; this.ay = ay; } protected CircularShape(CircularShape o) { super(o); this.cx = o.cx; this.cy = o.cy; this.ax = o.ax; this.ay = o.ay; } @Override public abstract CircularShape clone(); @Override public abstract Shape getShape(); @Override protected Object getControlState() { return new double[]{ cx, cy, ax, ay }; } @Override protected void setControlState(Object o) { double[] state = (double[])o; cx = state[0]; cy = state[1]; ax = state[2]; ay = state[3]; } @Override public int getControlPointCount() { return 2; } @Override protected ControlPoint getControlPointImpl(int i) { switch (i) { case 0: return new ControlPoint(ControlPointType.CENTER, cx, cy); case 1: return new ControlPoint(ControlPointType.RADIUS, ax, ay); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); cpts.add(new ControlPoint(ControlPointType.CENTER, cx, cy)); cpts.add(new ControlPoint(ControlPointType.RADIUS, ax, ay)); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { return null; } @Override protected int setControlPointImpl(int i, double x, double y) { switch (i) { case 0: ax = x + (ax - cx); ay = y + (ay - cy); cx = x; cy = y; break; case 1: ax = x; ay = y; break; } return i; } @Override protected Point2D getLocationImpl() { return new Point2D.Double(cx, cy); } @Override protected void setLocationImpl(double x, double y) { ax = x + (ax - cx); ay = y + (ay - cy); cx = x; cy = y; } } public static class QuadCurve extends ShapeDrawObject { private double x1, y1, cx, cy, x2, y2; public QuadCurve(PaintSettings ps, double x1, double y1, double cx, double cy, double x2, double y2) { super(ps); this.x1 = x1; this.y1 = y1; this.cx = cx; this.cy = cy; this.x2 = x2; this.y2 = y2; } private QuadCurve(QuadCurve o) { super(o); this.x1 = o.x1; this.y1 = o.y1; this.cx = o.cx; this.cy = o.cy; this.x2 = o.x2; this.y2 = o.y2; } @Override public QuadCurve clone() { return new QuadCurve(this); } @Override public QuadCurve2D getShape() { return new QuadCurve2D.Double(x1, y1, cx, cy, x2, y2); } @Override protected Object getControlState() { return new double[]{ x1, y1, cx, cy, x2, y2 }; } @Override protected void setControlState(Object o) { double[] state = (double[])o; x1 = state[0]; y1 = state[1]; cx = state[2]; cy = state[3]; x2 = state[4]; y2 = state[5]; } @Override public int getControlPointCount() { return 3; } @Override protected ControlPoint getControlPointImpl(int i) { switch (i) { case 0: return new ControlPoint(ControlPointType.ENDPOINT, x1, y1); case 1: return new ControlPoint(ControlPointType.CONTROL_POINT, cx, cy); case 2: return new ControlPoint(ControlPointType.ENDPOINT, x2, y2); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x1, y1)); cpts.add(new ControlPoint(ControlPointType.CONTROL_POINT, cx, cy)); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x2, y2)); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { Collection<Line2D> lines = new HashSet<Line2D>(); lines.add(new Line2D.Double(x1, y1, cx, cy)); lines.add(new Line2D.Double(x2, y2, cx, cy)); return lines; } @Override protected int setControlPointImpl(int i, double x, double y) { switch (i) { case 0: this.x1 = x; this.y1 = y; break; case 1: this.cx = x; this.cy = y; break; case 2: this.x2 = x; this.y2 = y; break; } return i; } @Override protected Point2D getLocationImpl() { return new Point2D.Double(x1, y1); } @Override protected void setLocationImpl(double x, double y) { this.x2 = x + (this.x2 - this.x1); this.y2 = y + (this.y2 - this.y1); this.cx = x + (this.cx - this.x1); this.cy = y + (this.cy - this.y1); this.x1 = x; this.y1 = y; } } public static class CubicCurve extends ShapeDrawObject { private double x1, y1, cx1, cy1, cx2, cy2, x2, y2; public CubicCurve(PaintSettings ps, double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2) { super(ps); this.x1 = x1; this.y1 = y1; this.cx1 = cx1; this.cy1 = cy1; this.cx2 = cx2; this.cy2 = cy2; this.x2 = x2; this.y2 = y2; } private CubicCurve(CubicCurve o) { super(o); this.x1 = o.x1; this.y1 = o.y1; this.cx1 = o.cx1; this.cy1 = o.cy1; this.cx2 = o.cx2; this.cy2 = o.cy2; this.x2 = o.x2; this.y2 = o.y2; } @Override public CubicCurve clone() { return new CubicCurve(this); } @Override public CubicCurve2D getShape() { return new CubicCurve2D.Double(x1, y1, cx1, cy1, cx2, cy2, x2, y2); } @Override protected Object getControlState() { return new double[]{ x1, y1, cx1, cy1, cx2, cy2, x2, y2 }; } @Override protected void setControlState(Object o) { double[] state = (double[])o; x1 = state[0]; y1 = state[1]; cx1 = state[2]; cy1 = state[3]; cx2 = state[4]; cy2 = state[5]; x2 = state[6]; y2 = state[7]; } @Override public int getControlPointCount() { return 4; } @Override protected ControlPoint getControlPointImpl(int i) { switch (i) { case 0: return new ControlPoint(ControlPointType.ENDPOINT, x1, y1); case 1: return new ControlPoint(ControlPointType.CONTROL_POINT, cx1, cy1); case 2: return new ControlPoint(ControlPointType.CONTROL_POINT, cx2, cy2); case 3: return new ControlPoint(ControlPointType.ENDPOINT, x2, y2); default: return null; } } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x1, y1)); cpts.add(new ControlPoint(ControlPointType.CONTROL_POINT, cx1, cy1)); cpts.add(new ControlPoint(ControlPointType.CONTROL_POINT, cx2, cy2)); cpts.add(new ControlPoint(ControlPointType.ENDPOINT, x2, y2)); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { Collection<Line2D> lines = new HashSet<Line2D>(); lines.add(new Line2D.Double(x1, y1, cx1, cy1)); lines.add(new Line2D.Double(x2, y2, cx2, cy2)); return lines; } @Override protected int setControlPointImpl(int i, double x, double y) { switch (i) { case 0: this.cx1 = x + (this.cx1 - this.x1); this.cy1 = y + (this.cy1 - this.y1); this.x1 = x; this.y1 = y; break; case 1: this.cx1 = x; this.cy1 = y; break; case 2: this.cx2 = x; this.cy2 = y; break; case 3: this.cx2 = x + (this.cx2 - this.x2); this.cy2 = y + (this.cy2 - this.y2); this.x2 = x; this.y2 = y; break; } return i; } @Override protected Point2D getLocationImpl() { return new Point2D.Double(x1, y1); } @Override protected void setLocationImpl(double x, double y) { this.x2 = x + (this.x2 - this.x1); this.y2 = y + (this.y2 - this.y1); this.cx2 = x + (this.cx2 - this.x1); this.cy2 = y + (this.cy2 - this.y1); this.cx1 = x + (this.cx1 - this.x1); this.cy1 = y + (this.cy1 - this.y1); this.x1 = x; this.y1 = y; } } public static class Polygon extends ShapeDrawObject { private double[] x; private double[] y; private int n; private boolean closed; public Polygon(PaintSettings ps, int[] x, int[] y, int n, boolean expClosed) { super(ps); boolean impClosed = ((n > 0) && (x[0] == x[n-1]) && (y[0] == y[n-1])); this.closed = impClosed || expClosed; this.n = impClosed ? (n - 1) : n; this.x = new double[this.n]; this.y = new double[this.n]; for (int i = 0; i < this.n; i++) { this.x[i] = x[i]; this.y[i] = y[i]; } } public Polygon(PaintSettings ps, double[] x, double[] y, int n, boolean expClosed) { super(ps); boolean impClosed = ((n > 0) && (x[0] == x[n-1]) && (y[0] == y[n-1])); this.closed = impClosed || expClosed; this.n = impClosed ? (n - 1) : n; this.x = new double[this.n]; this.y = new double[this.n]; for (int i = 0; i < this.n; i++) { this.x[i] = x[i]; this.y[i] = y[i]; } } private Polygon(Polygon o) { super(o); this.closed = o.closed; this.n = o.n; this.x = new double[this.n]; this.y = new double[this.n]; for (int i = 0; i < this.n; i++) { this.x[i] = o.x[i]; this.y[i] = o.y[i]; } } @Override public Polygon clone() { return new Polygon(this); } public int getPointCount() { return n; } public double getPointX(int i) { return x[i % n]; } public double getPointY(int i) { return y[i % n]; } public boolean isClosed() { return closed; } @Override public GeneralPath getShape() { GeneralPath g = new GeneralPath(); if (n > 0) g.moveTo(x[0], y[0]); for (int i = 1; i < n; i++) g.lineTo(x[i], y[i]); if (closed) g.closePath(); return g; } @Override protected Object getControlState() { double[] state = new double[n * 2]; for (int i = 0; i < n; i++) { state[i * 2 + 0] = x[i]; state[i * 2 + 1] = y[i]; } return state; } @Override protected void setControlState(Object o) { double[] state = (double[])o; for (int i = 0; i < n; i++) { x[i] = state[i * 2 + 0]; y[i] = state[i * 2 + 1]; } } @Override public int getControlPointCount() { return n; } @Override protected ControlPoint getControlPointImpl(int i) { return new ControlPoint(ControlPointType.STRAIGHT_MIDPOINT, x[i], y[i]); } @Override protected List<ControlPoint> getControlPointsImpl() { List<ControlPoint> cpts = new ArrayList<ControlPoint>(); for (int i = 0; i < n; i++) cpts.add(new ControlPoint(ControlPointType.STRAIGHT_MIDPOINT, x[i], y[i])); return cpts; } @Override protected Collection<Line2D> getControlLinesImpl() { return null; } @Override protected int setControlPointImpl(int i, double x, double y) { this.x[i] = x; this.y[i] = y; return i; } @Override protected Point2D getLocationImpl() { if (n > 0) return new Point2D.Double(x[0], y[0]); else return new Point2D.Double(0, 0); } @Override protected void setLocationImpl(double x, double y) { for (int i = n - 1; i > 0; i--) { this.x[i] = x + (this.x[i] - this.x[0]); this.y[i] = y + (this.y[i] - this.y[0]); } if (n > 0) { this.x[0] = x; this.y[0] = y; } } } private static boolean equals(Object dis, Object dat) { if (dis == null) return (dat == null); if (dat == null) return (dis == null); return dis.equals(dat); } }