package com.kreative.paint.material.shape; import java.awt.Shape; import java.awt.geom.Arc2D; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; public abstract class ParameterizedShape { public abstract Shape awtShape(Bindings bindings); public static class Arc extends ParameterizedShape { public final ParameterizedValue cx, cy, rx, ry; public final ParameterizedValue start, extent; public final ArcType type; public Arc( ParameterizedValue cx, ParameterizedValue cy, ParameterizedValue rx, ParameterizedValue ry, ParameterizedValue start, ParameterizedValue extent, ArcType type ) { this.cx = cx; this.cy = cy; this.rx = rx; this.ry = ry; this.start = start; this.extent = extent; this.type = type; } @Override public Arc2D awtShape(Bindings bindings) { double cx = this.cx.value(bindings), cy = this.cy.value(bindings); double rx = this.rx.value(bindings), ry = this.ry.value(bindings); double start = this.start.value(bindings), extent = this.extent.value(bindings); int type = (this.type != null) ? this.type.awtValue : Arc2D.OPEN; return new Arc2D.Double(cx-rx, cy-ry, rx+rx, ry+ry, start, extent, type); } @Override public boolean equals(Object that) { return (that instanceof Arc) && (this.cx.equals(((Arc)that).cx)) && (this.cy.equals(((Arc)that).cy)) && (this.rx.equals(((Arc)that).rx)) && (this.ry.equals(((Arc)that).ry)) && (this.start.equals(((Arc)that).start)) && (this.extent.equals(((Arc)that).extent)) && (this.type == ((Arc)that).type); } @Override public int hashCode() { return cx.hashCode() ^ cy.hashCode() ^ rx.hashCode() ^ ry.hashCode() ^ start.hashCode() ^ extent.hashCode(); } } public static class Circle extends ParameterizedShape { public final ParameterizedValue cx, cy, r; public Circle(ParameterizedValue cx, ParameterizedValue cy, ParameterizedValue r) { this.cx = cx; this.cy = cy; this.r = r; } @Override public Ellipse2D awtShape(Bindings bindings) { double cx = this.cx.value(bindings); double cy = this.cy.value(bindings); double r = this.r.value(bindings); return new Ellipse2D.Double(cx-r, cy-r, r+r, r+r); } @Override public boolean equals(Object that) { return (that instanceof Circle) && (this.cx.equals(((Circle)that).cx)) && (this.cy.equals(((Circle)that).cy)) && (this.r.equals(((Circle)that).r)); } @Override public int hashCode() { return cx.hashCode() ^ cy.hashCode() ^ r.hashCode(); } } public static class Ellipse extends ParameterizedShape { public final ParameterizedValue cx, cy, rx, ry; public Ellipse( ParameterizedValue cx, ParameterizedValue cy, ParameterizedValue rx, ParameterizedValue ry ) { this.cx = cx; this.cy = cy; this.rx = rx; this.ry = ry; } @Override public Ellipse2D awtShape(Bindings bindings) { double cx = this.cx.value(bindings), cy = this.cy.value(bindings); double rx = this.rx.value(bindings), ry = this.ry.value(bindings); return new Ellipse2D.Double(cx-rx, cy-ry, rx+rx, ry+ry); } @Override public boolean equals(Object that) { return (that instanceof Ellipse) && (this.cx.equals(((Ellipse)that).cx)) && (this.cy.equals(((Ellipse)that).cy)) && (this.rx.equals(((Ellipse)that).rx)) && (this.ry.equals(((Ellipse)that).ry)); } @Override public int hashCode() { return cx.hashCode() ^ cy.hashCode() ^ rx.hashCode() ^ ry.hashCode(); } } public static class Line extends ParameterizedShape { public final ParameterizedValue x1, y1, x2, y2; public Line( ParameterizedValue x1, ParameterizedValue y1, ParameterizedValue x2, ParameterizedValue y2 ) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } @Override public Line2D awtShape(Bindings bindings) { double x1 = this.x1.value(bindings), y1 = this.y1.value(bindings); double x2 = this.x2.value(bindings), y2 = this.y2.value(bindings); return new Line2D.Double(x1, y1, x2, y2); } @Override public boolean equals(Object that) { return (that instanceof Line) && (this.x1.equals(((Line)that).x1)) && (this.y1.equals(((Line)that).y1)) && (this.x2.equals(((Line)that).x2)) && (this.y2.equals(((Line)that).y2)); } @Override public int hashCode() { return x1.hashCode() ^ y1.hashCode() ^ x2.hashCode() ^ y2.hashCode(); } } public static class Polygon extends ParameterizedShape { public final ParameterizedValue[] points; public Polygon(ParameterizedValue[] points) { this.points = points; } @Override public Shape awtShape(Bindings bindings) { GeneralPath p = new GeneralPath(); if (points.length >= 2) { double x = points[0].value(bindings); double y = points[1].value(bindings); p.moveTo(x, y); for (int i = 2, j = 1, n = points.length / 2; j < n; j++) { x = points[i++].value(bindings); y = points[i++].value(bindings); p.lineTo(x, y); } p.closePath(); } return p; } @Override public boolean equals(Object that) { if (that instanceof Polygon) { ParameterizedValue[] thisPoints = this.points; ParameterizedValue[] thatPoints = ((Polygon)that).points; if (thisPoints.length != thatPoints.length) return false; for (int i = 0; i < thisPoints.length; i++) { if (!thisPoints[i].equals(thatPoints[i])) { return false; } } return true; } else { return false; } } @Override public int hashCode() { int hashCode = 0; for (ParameterizedValue point : points) { hashCode ^= point.hashCode(); } return hashCode; } } public static class PolyLine extends ParameterizedShape { public final ParameterizedValue[] points; public PolyLine(ParameterizedValue[] points) { this.points = points; } @Override public Shape awtShape(Bindings bindings) { GeneralPath p = new GeneralPath(); if (points.length >= 2) { double x = points[0].value(bindings); double y = points[1].value(bindings); p.moveTo(x, y); for (int i = 2, j = 1, n = points.length / 2; j < n; j++) { x = points[i++].value(bindings); y = points[i++].value(bindings); p.lineTo(x, y); } } return p; } @Override public boolean equals(Object that) { if (that instanceof PolyLine) { ParameterizedValue[] thisPoints = this.points; ParameterizedValue[] thatPoints = ((PolyLine)that).points; if (thisPoints.length != thatPoints.length) return false; for (int i = 0; i < thisPoints.length; i++) { if (!thisPoints[i].equals(thatPoints[i])) { return false; } } return true; } else { return false; } } @Override public int hashCode() { int hashCode = 0; for (ParameterizedValue point : points) { hashCode ^= point.hashCode(); } return hashCode; } } public static class Rect extends ParameterizedShape { public final ParameterizedValue x, y, width, height, rx, ry; public Rect( ParameterizedValue x, ParameterizedValue y, ParameterizedValue width, ParameterizedValue height, ParameterizedValue rx, ParameterizedValue ry ) { this.x = x; this.y = y; this.width = width; this.height = height; this.rx = rx; this.ry = ry; } @Override public Shape awtShape(Bindings bindings) { double x = this.x.value(bindings), y = this.y.value(bindings); double width = this.width.value(bindings), height = this.height.value(bindings); double rx = this.rx.value(bindings), ry = this.ry.value(bindings); if (rx == 0 && ry == 0) { return new Rectangle2D.Double(x, y, width, height); } else { return new RoundRectangle2D.Double(x, y, width, height, rx, ry); } } @Override public boolean equals(Object that) { return (that instanceof Rect) && (this.x.equals(((Rect)that).x)) && (this.y.equals(((Rect)that).y)) && (this.width.equals(((Rect)that).width)) && (this.height.equals(((Rect)that).height)) && (this.rx.equals(((Rect)that).rx)) && (this.ry.equals(((Rect)that).ry)); } @Override public int hashCode() { return x.hashCode() ^ y.hashCode() ^ width.hashCode() ^ height.hashCode() ^ rx.hashCode() ^ ry.hashCode(); } } }