From 3f6ff945054e6d846f182b8f56d4ad1fe9605fd5 Mon Sep 17 00:00:00 2001 From: mkoch Date: Wed, 22 Oct 2003 08:54:19 +0000 Subject: [PATCH] 2003-10-22 Sascha Brawer * java/awt/geom/QuadCurve2D.java (subdivide): Added documentation. java/awt/geom/doc-files/QuadCurve2D-3.png: New illustration. 2003-10-22 Sascha Brawer * java/awt/geom/QuadCurve2D.java: Reformatted, wrote Javadoc. * java/awt/geom/doc-files: New directory. * java/awt/geom/doc-files/QuadCurve2D-1.png, java/awt/geom/doc-files/QuadCurve2D-2.png: New illustrations. 2003-10-22 Sascha Brawer * java/awt/geom/QuadCurve2D.java (subdivide): Implement. 2003-10-22 Sascha Brawer * java/awt/geom/QuadCurve2D.java (getFlatness, getFlatnessSq): Implement. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72791 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 20 + libjava/java/awt/geom/QuadCurve2D.java | 779 +++++++++++++++++++--- libjava/java/awt/geom/doc-files/QuadCurve2D-1.png | Bin 0 -> 6363 bytes libjava/java/awt/geom/doc-files/QuadCurve2D-2.png | Bin 0 -> 5872 bytes libjava/java/awt/geom/doc-files/QuadCurve2D-3.png | Bin 0 -> 12334 bytes 5 files changed, 706 insertions(+), 93 deletions(-) create mode 100644 libjava/java/awt/geom/doc-files/QuadCurve2D-1.png create mode 100644 libjava/java/awt/geom/doc-files/QuadCurve2D-2.png create mode 100644 libjava/java/awt/geom/doc-files/QuadCurve2D-3.png diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 7f53a36..1d3e7bb 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,23 @@ +2003-10-22 Sascha Brawer + + * java/awt/geom/QuadCurve2D.java (subdivide): Added documentation. + java/awt/geom/doc-files/QuadCurve2D-3.png: New illustration. + +2003-10-22 Sascha Brawer + + * java/awt/geom/QuadCurve2D.java: Reformatted, wrote Javadoc. + * java/awt/geom/doc-files: New directory. + * java/awt/geom/doc-files/QuadCurve2D-1.png, + java/awt/geom/doc-files/QuadCurve2D-2.png: New illustrations. + +2003-10-22 Sascha Brawer + + * java/awt/geom/QuadCurve2D.java (subdivide): Implement. + +2003-10-22 Sascha Brawer + + * java/awt/geom/QuadCurve2D.java (getFlatness, getFlatnessSq): Implement. + 2003-10-22 Michael Koch * java/io/File.java diff --git a/libjava/java/awt/geom/QuadCurve2D.java b/libjava/java/awt/geom/QuadCurve2D.java index 6aed059..e737ec1 100644 --- a/libjava/java/awt/geom/QuadCurve2D.java +++ b/libjava/java/awt/geom/QuadCurve2D.java @@ -1,5 +1,5 @@ /* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space - Copyright (C) 2002 Free Software Foundation + Copyright (C) 2002, 2003 Free Software Foundation This file is part of GNU Classpath. @@ -42,124 +42,361 @@ import java.awt.Rectangle; import java.awt.Shape; import java.util.NoSuchElementException; + /** - * STUBS ONLY - * XXX Implement and document. + * A two-dimensional curve that is parameterized with a quadratic + * function. + * + *

A drawing of a QuadCurve2D + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) + * + * @since 1.2 */ -public abstract class QuadCurve2D implements Shape, Cloneable +public abstract class QuadCurve2D + implements Shape, Cloneable { + /** + * Constructs a new QuadCurve2D. Typical users will want to + * construct instances of a subclass, such as {@link + * QuadCurve2D.Float} or {@link QuadCurve2D.Double}. + */ protected QuadCurve2D() { } + + /** + * Returns the x coordinate of the curve’s start + * point. + */ public abstract double getX1(); + + + /** + * Returns the y coordinate of the curve’s start + * point. + */ public abstract double getY1(); + + + /** + * Returns the curve’s start point. + */ public abstract Point2D getP1(); + + + /** + * Returns the x coordinate of the curve’s control + * point. + */ public abstract double getCtrlX(); + + + /** + * Returns the y coordinate of the curve’s control + * point. + */ public abstract double getCtrlY(); + + + /** + * Returns the curve’s control point. + */ public abstract Point2D getCtrlPt(); + + + /** + * Returns the x coordinate of the curve’s end + * point. + */ public abstract double getX2(); + + + /** + * Returns the y coordinate of the curve’s end + * point. + */ public abstract double getY2(); + + + /** + * Returns the curve’s end point. + */ public abstract Point2D getP2(); + + /** + * Changes the geometry of the curve. + * + * @param x1 the x coordinate of the curve’s new start + * point. + * + * @param y1 the y coordinate of the curve’s new start + * point. + * + * @param cx the x coordinate of the curve’s new + * control point. + * + * @param cy the y coordinate of the curve’s new + * control point. + * + * @param x2 the x coordinate of the curve’s new end + * point. + * + * @param y2 the y coordinate of the curve’s new end + * point. + */ public abstract void setCurve(double x1, double y1, double cx, double cy, double x2, double y2); + + public void setCurve(double[] coords, int offset) { setCurve(coords[offset++], coords[offset++], coords[offset++], coords[offset++], coords[offset++], coords[offset++]); } + + public void setCurve(Point2D p1, Point2D c, Point2D p2) { setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY()); } + + public void setCurve(Point2D[] pts, int offset) { setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY()); } + + + /** + * Changes the geometry of the curve to that of another curve. + * + * @param c the curve whose coordinates will be copied. + */ public void setCurve(QuadCurve2D c) { setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(), c.getY2()); } + + public static double getFlatnessSq(double x1, double y1, double cx, double cy, double x2, double y2) { - // XXX Implement. - throw new Error("not implemented"); + return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy); } + + public static double getFlatness(double x1, double y1, double cx, double cy, double x2, double y2) { - return Math.sqrt(getFlatnessSq(x1, y1, cx, cy, x2, y2)); + return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy); } + + public static double getFlatnessSq(double[] coords, int offset) { - return getFlatnessSq(coords[offset++], coords[offset++], - coords[offset++], coords[offset++], - coords[offset++], coords[offset++]); + return Line2D.ptSegDistSq(coords[offset], coords[offset + 1], + coords[offset + 4], coords[offset + 5], + coords[offset + 2], coords[offset + 3]); } + + public static double getFlatness(double[] coords, int offset) { - return Math.sqrt(getFlatnessSq(coords[offset++], coords[offset++], - coords[offset++], coords[offset++], - coords[offset++], coords[offset++])); + return Line2D.ptSegDist(coords[offset], coords[offset + 1], + coords[offset + 4], coords[offset + 5], + coords[offset + 2], coords[offset + 3]); } + + public double getFlatnessSq() { - return getFlatnessSq(getX1(), getY1(), getCtrlX(), getCtrlY(), - getX2(), getY2()); + return Line2D.ptSegDistSq(getX1(), getY1(), + getX2(), getY2(), + getCtrlX(), getCtrlY()); } + + public double getFlatness() { - return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX(), getCtrlY(), - getX2(), getY2())); + return Line2D.ptSegDist(getX1(), getY1(), + getX2(), getY2(), + getCtrlX(), getCtrlY()); } - public void subdivide(QuadCurve2D l, QuadCurve2D r) + + /** + * Subdivides this curve into two halves. + * + *

A drawing that illustrates the effects of
+   * subdividing a QuadCurve2D + * + * @param left a curve whose geometry will be set to the left half + * of this curve, or null if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of this curve, or null if the caller is not + * interested in the right half. + */ + public void subdivide(QuadCurve2D left, QuadCurve2D right) { - if (l == null) - l = new QuadCurve2D.Double(); - if (r == null) - r = new QuadCurve2D.Double(); // Use empty slots at end to share single array. double[] d = new double[] { getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(), 0, 0, 0, 0 }; subdivide(d, 0, d, 0, d, 4); - l.setCurve(d, 0); - r.setCurve(d, 4); + if (left != null) + left.setCurve(d, 0); + if (right != null) + right.setCurve(d, 4); } - public static void subdivide(QuadCurve2D src, QuadCurve2D l, QuadCurve2D r) + + + /** + * Subdivides a quadratic curve into two halves. + * + *

A drawing that illustrates the effects of
+   * subdividing a QuadCurve2D + * + * @param src the curve to be subdivided. + * + * @param left a curve whose geometry will be set to the left half + * of src, or null if the caller is not + * interested in the left half. + * + * @param right a curve whose geometry will be set to the right half + * of src, or null if the caller is not + * interested in the right half. + */ + public static void subdivide(QuadCurve2D src, QuadCurve2D left, + QuadCurve2D right) { - src.subdivide(l, r); + src.subdivide(left, right); } + + + /** + * Subdivides a quadratic curve into two halves, passing all + * coordinates in an array. + * + *

A drawing that illustrates the effects of
+   * subdividing a QuadCurve2D + * + *

The left end point and the right start point will always be + * identical. Memory-concious programmers thus may want to pass the + * same array for both left and right, and + * set rightOff to leftOff + 4. + * + * @param src an array containing the coordinates of the curve to be + * subdivided. The x coordinate of the start point is + * located at src[srcOff], its y at + * src[srcOff + 1]. The x coordinate of the + * control point is located at src[srcOff + 2], its + * y at src[srcOff + 3]. The x + * coordinate of the end point is located at src[srcOff + + * 4], its y at src[srcOff + 5]. + * + * @param srcOff an offset into src, specifying + * the index of the start point’s x coordinate. + * + * @param left an array that will receive the coordinates of the + * left half of src. It is acceptable to pass + * src. A caller who is not interested in the left half + * can pass null. + * + * @param leftOff an offset into left, specifying the + * index where the start point’s x coordinate will be + * stored. + * + * @param right an array that will receive the coordinates of the + * right half of src. It is acceptable to pass + * src or left. A caller who is not + * interested in the right half can pass null. + * + * @param rightOff an offset into right, specifying the + * index where the start point’s x coordinate will be + * stored. + */ public static void subdivide(double[] src, int srcOff, double[] left, int leftOff, double[] right, int rightOff) { - // XXX Implement. - throw new Error("not implemented"); + double x1, y1, xc, yc, x2, y2; + + x1 = src[srcOff]; + y1 = src[srcOff + 1]; + xc = src[srcOff + 2]; + yc = src[srcOff + 3]; + x2 = src[srcOff + 4]; + y2 = src[srcOff + 5]; + + if (left != null) + { + left[leftOff] = x1; + left[leftOff + 1] = y1; + } + + if (right != null) + { + right[rightOff + 4] = x2; + right[rightOff + 5] = y2; + } + + x1 = (x1 + xc) / 2; + x2 = (xc + x2) / 2; + xc = (x1 + x2) / 2; + y1 = (y1 + yc) / 2; + y2 = (y2 + yc) / 2; + yc = (y1 + y2) / 2; + + if (left != null) + { + left[leftOff + 2] = x1; + left[leftOff + 3] = y1; + left[leftOff + 4] = xc; + left[leftOff + 5] = yc; + } + + if (right != null) + { + right[rightOff] = xc; + right[rightOff + 1] = yc; + right[rightOff + 2] = x2; + right[rightOff + 3] = y2; + } } + + public static int solveQuadratic(double[] eqn) { return solveQuadratic(eqn, eqn); } + + public static int solveQuadratic(double[] eqn, double[] res) { double c = eqn[0]; double b = eqn[1]; double a = eqn[2]; if (a == 0) - { - if (b == 0) - return -1; - res[0] = -c / b; - return 1; - } + { + if (b == 0) + return -1; + res[0] = -c / b; + return 1; + } c /= a; b /= a * 2; double det = Math.sqrt(b * b - c); @@ -167,49 +404,74 @@ public abstract class QuadCurve2D implements Shape, Cloneable return 0; // For fewer rounding errors, we calculate the two roots differently. if (b > 0) - { - res[0] = -b - det; - res[1] = -c / (b + det); - } + { + res[0] = -b - det; + res[1] = -c / (b + det); + } else - { - res[0] = -c / (b - det); - res[1] = -b + det; - } + { + res[0] = -c / (b - det); + res[1] = -b + det; + } return 2; } + public boolean contains(double x, double y) { // XXX Implement. throw new Error("not implemented"); } + + public boolean contains(Point2D p) { return contains(p.getX(), p.getY()); } + + public boolean intersects(double x, double y, double w, double h) { // XXX Implement. throw new Error("not implemented"); } + + public boolean intersects(Rectangle2D r) { return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } + + public boolean contains(double x, double y, double w, double h) { // XXX Implement. throw new Error("not implemented"); } + + public boolean contains(Rectangle2D r) { return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } + + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the illustration + * below shows, the invisible control point may cause the bounds to + * be much larger than the area that is actually covered by the + * curve. + * + *

An illustration of the bounds of a QuadCurve2D + */ public Rectangle getBounds() { return getBounds2D().getBounds(); } + + public PathIterator getPathIterator(final AffineTransform at) { return new PathIterator() @@ -217,115 +479,190 @@ public abstract class QuadCurve2D implements Shape, Cloneable /** Current coordinate. */ private int current = 0; + public int getWindingRule() { return WIND_NON_ZERO; } + public boolean isDone() { return current >= 2; } + public void next() { current++; } + public int currentSegment(float[] coords) { int result; switch (current) - { - case 0: - coords[0] = (float) getX1(); - coords[1] = (float) getY1(); - result = SEG_MOVETO; - break; - case 1: - coords[0] = (float) getCtrlX(); - coords[1] = (float) getCtrlY(); - coords[2] = (float) getX2(); - coords[3] = (float) getY2(); - result = SEG_QUADTO; - break; - default: - throw new NoSuchElementException("quad iterator out of bounds"); - } + { + case 0: + coords[0] = (float) getX1(); + coords[1] = (float) getY1(); + result = SEG_MOVETO; + break; + + case 1: + coords[0] = (float) getCtrlX(); + coords[1] = (float) getCtrlY(); + coords[2] = (float) getX2(); + coords[3] = (float) getY2(); + result = SEG_QUADTO; + break; + + default: + throw new NoSuchElementException("quad iterator out of bounds"); + } if (at != null) at.transform(coords, 0, coords, 0, 2); return result; } + public int currentSegment(double[] coords) { int result; switch (current) - { - case 0: - coords[0] = getX1(); - coords[1] = getY1(); - result = SEG_MOVETO; - break; - case 1: - coords[0] = getCtrlX(); - coords[1] = getCtrlY(); - coords[2] = getX2(); - coords[3] = getY2(); - result = SEG_QUADTO; - break; - default: - throw new NoSuchElementException("quad iterator out of bounds"); - } + { + case 0: + coords[0] = getX1(); + coords[1] = getY1(); + result = SEG_MOVETO; + break; + + case 1: + coords[0] = getCtrlX(); + coords[1] = getCtrlY(); + coords[2] = getX2(); + coords[3] = getY2(); + result = SEG_QUADTO; + break; + + default: + throw new NoSuchElementException("quad iterator out of bounds"); + } if (at != null) at.transform(coords, 0, coords, 0, 2); return result; } }; } + + public PathIterator getPathIterator(AffineTransform at, double flatness) { return new FlatteningPathIterator(getPathIterator(at), flatness); } + /** - * Create a new curve of the same run-time type with the same contents as + * Creates a new curve with the same contents as * this one. * - * @return the clone - * - * @exception OutOfMemoryError If there is not enough memory available. - * - * @since 1.2 + * @return the clone. */ public Object clone() { try - { - return super.clone(); - } + { + return super.clone(); + } catch (CloneNotSupportedException e) - { - throw (Error) new InternalError().initCause(e); // Impossible - } + { + throw (Error) new InternalError().initCause(e); // Impossible + } } + /** - * STUBS ONLY + * A two-dimensional curve that is parameterized with a quadratic + * function and stores coordinate values in double-precision + * floating-point format. + * + * @see QuadCurve2D.Float + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) */ - public static class Double extends QuadCurve2D + public static class Double + extends QuadCurve2D { + /** + * The x coordinate of the curve’s start point. + */ public double x1; + + + /** + * The y coordinate of the curve’s start point. + */ public double y1; + + + /** + * The x coordinate of the curve’s control point. + */ public double ctrlx; + + + /** + * The y coordinate of the curve’s control point. + */ public double ctrly; + + + /** + * The x coordinate of the curve’s end point. + */ public double x2; + + + /** + * The y coordinate of the curve’s end point. + */ public double y2; + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in double-precision floating-point format. All points are + * initially at position (0, 0). + */ public Double() { } + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in double-precision floating-point format, specifying the + * initial position of each point. + * + * @param x1 the x coordinate of the curve’s start + * point. + * + * @param y1 the y coordinate of the curve’s start + * point. + * + * @param cx the x coordinate of the curve’s control + * point. + * + * @param cy the y coordinate of the curve’s control + * point. + * + * @param x2 the x coordinate of the curve’s end + * point. + * + * @param y2 the y coordinate of the curve’s end + * point. + */ public Double(double x1, double y1, double cx, double cy, double x2, double y2) { @@ -337,45 +674,115 @@ public abstract class QuadCurve2D implements Shape, Cloneable this.y2 = y2; } + + /** + * Returns the x coordinate of the curve’s start + * point. + */ public double getX1() { return x1; } + + + /** + * Returns the y coordinate of the curve’s start + * point. + */ public double getY1() { return y1; } + + + /** + * Returns the curve’s start point. + */ public Point2D getP1() { return new Point2D.Double(x1, y1); } + + /** + * Returns the x coordinate of the curve’s control + * point. + */ public double getCtrlX() { return ctrlx; } + + + /** + * Returns the y coordinate of the curve’s control + * point. + */ public double getCtrlY() { return ctrly; } + + + /** + * Returns the curve’s control point. + */ public Point2D getCtrlPt() { return new Point2D.Double(ctrlx, ctrly); } + + /** + * Returns the x coordinate of the curve’s end + * point. + */ public double getX2() { return x2; } + + + /** + * Returns the y coordinate of the curve’s end + * point. + */ public double getY2() { return y2; } + + + /** + * Returns the curve’s end point. + */ public Point2D getP2() { return new Point2D.Double(x2, y2); } + + /** + * Changes the geometry of the curve. + * + * @param x1 the x coordinate of the curve’s new + * start point. + * + * @param y1 the y coordinate of the curve’s new + * start point. + * + * @param cx the x coordinate of the curve’s new + * control point. + * + * @param cy the y coordinate of the curve’s new + * control point. + * + * @param x2 the x coordinate of the curve’s new + * end point. + * + * @param y2 the y coordinate of the curve’s new + * end point. + */ public void setCurve(double x1, double y1, double cx, double cy, double x2, double y2) { @@ -386,6 +793,18 @@ public abstract class QuadCurve2D implements Shape, Cloneable this.x2 = x2; this.y2 = y2; } + + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the + * illustration below shows, the invisible control point may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + *

An illustration of the bounds of a QuadCurve2D + */ public Rectangle2D getBounds2D() { double nx1 = Math.min(Math.min(x1, ctrlx), x2); @@ -394,24 +813,91 @@ public abstract class QuadCurve2D implements Shape, Cloneable double ny2 = Math.max(Math.max(y1, ctrly), y2); return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1); } - } // class Double + } + /** - * STUBS ONLY + * A two-dimensional curve that is parameterized with a quadratic + * function and stores coordinate values in single-precision + * floating-point format. + * + * @see QuadCurve2D.Double + * + * @author Eric Blake (ebb9@email.byu.edu) + * @author Sascha Brawer (brawer@dandelis.ch) */ - public static class Float extends QuadCurve2D + public static class Float + extends QuadCurve2D { + /** + * The x coordinate of the curve’s start point. + */ public float x1; + + + /** + * The y coordinate of the curve’s start point. + */ public float y1; + + + /** + * The x coordinate of the curve’s control point. + */ public float ctrlx; + + + /** + * The y coordinate of the curve’s control point. + */ public float ctrly; + + + /** + * The x coordinate of the curve’s end point. + */ public float x2; + + + /** + * The y coordinate of the curve’s end point. + */ public float y2; + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in single-precision floating-point format. All points are + * initially at position (0, 0). + */ public Float() { } + + /** + * Constructs a new QuadCurve2D that stores its coordinate values + * in single-precision floating-point format, specifying the + * initial position of each point. + * + * @param x1 the x coordinate of the curve’s start + * point. + * + * @param y1 the y coordinate of the curve’s start + * point. + * + * @param cx the x coordinate of the curve’s control + * point. + * + * @param cy the y coordinate of the curve’s control + * point. + * + * @param x2 the x coordinate of the curve’s end + * point. + * + * @param y2 the y coordinate of the curve’s end + * point. + */ public Float(float x1, float y1, float cx, float cy, float x2, float y2) { @@ -423,45 +909,116 @@ public abstract class QuadCurve2D implements Shape, Cloneable this.y2 = y2; } + + /** + * Returns the x coordinate of the curve’s start + * point. + */ public double getX1() { return x1; } + + + /** + * Returns the y coordinate of the curve’s start + * point. + */ public double getY1() { return y1; } + + + /** + * Returns the curve’s start point. + */ public Point2D getP1() { return new Point2D.Float(x1, y1); } + + /** + * Returns the x coordinate of the curve’s control + * point. + */ public double getCtrlX() { return ctrlx; } + + + /** + * Returns the y coordinate of the curve’s control + * point. + */ public double getCtrlY() { return ctrly; } + + + /** + * Returns the curve’s control point. + */ public Point2D getCtrlPt() { return new Point2D.Float(ctrlx, ctrly); } + + /** + * Returns the x coordinate of the curve’s end + * point. + */ public double getX2() { return x2; } + + + /** + * Returns the y coordinate of the curve’s end + * point. + */ public double getY2() { return y2; } + + + /** + * Returns the curve’s end point. + */ public Point2D getP2() { return new Point2D.Float(x2, y2); } + + /** + * Changes the geometry of the curve, specifying coordinate values + * as double-precision floating-point numbers. + * + * @param x1 the x coordinate of the curve’s new + * start point. + * + * @param y1 the y coordinate of the curve’s new + * start point. + * + * @param cx the x coordinate of the curve’s new + * control point. + * + * @param cy the y coordinate of the curve’s new + * control point. + * + * @param x2 the x coordinate of the curve’s new + * end point. + * + * @param y2 the y coordinate of the curve’s new + * end point. + */ public void setCurve(double x1, double y1, double cx, double cy, double x2, double y2) { @@ -472,6 +1029,30 @@ public abstract class QuadCurve2D implements Shape, Cloneable this.x2 = (float) x2; this.y2 = (float) y2; } + + + /** + * Changes the geometry of the curve, specifying coordinate values + * as single-precision floating-point numbers. + * + * @param x1 the x coordinate of the curve’s new + * start point. + * + * @param y1 the y coordinate of the curve’s new + * start point. + * + * @param cx the x coordinate of the curve’s new + * control point. + * + * @param cy the y coordinate of the curve’s new + * control point. + * + * @param x2 the x coordinate of the curve’s new + * end point. + * + * @param y2 the y coordinate of the curve’s new + * end point. + */ public void setCurve(float x1, float y1, float cx, float cy, float x2, float y2) { @@ -482,6 +1063,18 @@ public abstract class QuadCurve2D implements Shape, Cloneable this.x2 = x2; this.y2 = y2; } + + + /** + * Determines the smallest rectangle that encloses the + * curve’s start, end and control point. As the + * illustration below shows, the invisible control point may cause + * the bounds to be much larger than the area that is actually + * covered by the curve. + * + *

An illustration of the bounds of a QuadCurve2D + */ public Rectangle2D getBounds2D() { float nx1 = (float) Math.min(Math.min(x1, ctrlx), x2); @@ -490,5 +1083,5 @@ public abstract class QuadCurve2D implements Shape, Cloneable float ny2 = (float) Math.max(Math.max(y1, ctrly), y2); return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1); } - } // class Float -} // class CubicCurve2D + } +} diff --git a/libjava/java/awt/geom/doc-files/QuadCurve2D-1.png b/libjava/java/awt/geom/doc-files/QuadCurve2D-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7c2ec0ea9cbc4bb0516c12cd357ba63b0aa27404 GIT binary patch literal 6363 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 O9hK$PVKuVm;r|0 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