From 1413a045213b57f207955ecf498ec365dd6520b1 Mon Sep 17 00:00:00 2001 From: tromey Date: Fri, 11 May 2001 01:03:45 +0000 Subject: [PATCH] * Makefile.in: Rebuilt. * Makefile.am (awt_java_source_files): Added Polygon.java. * java/awt/Polygon.java: New file. * java/awt/geom/AffineTransform.java (setToRotation(double,double,double)): New method. (AffineTransform): Set type to TYPE_GENERAL_TRANSFORM. (setToShear): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41954 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 11 + libjava/java/awt/Polygon.java | 422 +++++++++++++++++++++++++++++ libjava/java/awt/geom/AffineTransform.java | 20 +- 3 files changed, 450 insertions(+), 3 deletions(-) create mode 100644 libjava/java/awt/Polygon.java diff --git a/libjava/ChangeLog b/libjava/ChangeLog index c803cd6..bb22501 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,16 @@ 2001-05-10 Tom Tromey + * Makefile.in: Rebuilt. + * Makefile.am (awt_java_source_files): Added Polygon.java. + * java/awt/Polygon.java: New file. + + * java/awt/geom/AffineTransform.java + (setToRotation(double,double,double)): New method. + (AffineTransform): Set type to TYPE_GENERAL_TRANSFORM. + (setToShear): Likewise. + +2001-05-10 Tom Tromey + * java/util/GregorianCalendar.java: Imported from Classpath. * gnu/java/locale/LocaleInformation_nl.java: New file from Classpath. diff --git a/libjava/java/awt/Polygon.java b/libjava/java/awt/Polygon.java new file mode 100644 index 0000000..ad4df2c --- /dev/null +++ b/libjava/java/awt/Polygon.java @@ -0,0 +1,422 @@ +/* Copyright (C) 2001 Free Software Foundation + + This file is part of libjava. + +This software is copyrighted work licensed under the terms of the +Libjava License. Please consult the file "LIBJAVA_LICENSE" for +details. */ + +package java.awt; + +import java.awt.geom.*; +import java.io.Serializable; +import java.util.Arrays; + +/** + * @author Tom Tromey + * @date May 10, 2001 + */ + +/** The Polygon class represents a closed region whose boundary is + made of line segments. The Polygon is defined by its vertices. */ +public class Polygon implements Shape, Serializable +{ + /** The bounds of the polygon. This is null until the bounds have + * been computed for the first time; then it is correctly + * maintained whenever it is modified. */ + protected Rectangle bounds; + + /** The number of points in the polygon. */ + public int npoints; + + /** The x coordinates of the points. */ + public int[] xpoints; + + /** The y coordinates of the points. */ + public int[] ypoints; + + /** Create a new, empty Polygon. */ + public Polygon () + { + this.xpoints = new int[0]; + this.ypoints = new int[0]; + this.npoints = 0; + } + + /** Create a new Polygon from the given vertices. + * @param xpoints The x coordinates + * @param ypoints The y coordinates + * @param npoints The number of points + */ + public Polygon (int[] xpoints, int[] ypoints, int npoints) + { + // We make explicit copies instead of relying on clone so that we + // ensure the new arrays are the same size. + this.xpoints = new int[npoints]; + this.ypoints = new int[npoints]; + System.arraycopy (xpoints, 0, this.xpoints, 0, npoints); + System.arraycopy (ypoints, 0, this.ypoints, 0, npoints); + } + + /** Append the specified point to this Polygon. + * @param x The x coordinate + * @param y The y coordinate + */ + public void addPoint (int x, int y) + { + int[] newx = new int[npoints + 1]; + System.arraycopy (xpoints, 0, newx, 0, npoints); + int[] newy = new int[npoints + 1]; + System.arraycopy (ypoints, 0, newy, 0, npoints); + newx[npoints] = x; + newy[npoints] = y; + ++npoints; + xpoints = newx; + ypoints = newy; + + // It is simpler to just recompute. + if (bounds != null) + computeBoundingBox (); + } + + /** Return true if the indicated point is inside this Polygon. + * This uses an even-odd rule to determine insideness. + * @param x The x coordinate + * @param y The y coordinate + * @returns true if the point is contained by this Polygon. + */ + public boolean contains (double x, double y) + { + // What we do is look at each line segment. If the line segment + // crosses the "scan line" at y at a point x' < x, then we + // increment our counter. At the end, an even number means the + // point is outside the polygon. Instead of a number, though, we + // use a boolean. + boolean inside = false; + for (int i = 0; i < npoints; ++i) + { + // Handle the wrap case. + int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1]; + int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1]; + + if (ypoints[i] == y2) + { + // We ignore horizontal lines. This might give weird + // results in some situations -- ? + continue; + } + + double t = (y - ypoints[i]) / (double) (y2 - ypoints[i]); + double x3 = xpoints[i] + t * (x2 - xpoints[i]); + if (x3 < x) + inside = ! inside; + } + + return inside; + } + + /** Return true if the indicated rectangle is entirely inside this + * Polygon. + * This uses an even-odd rule to determine insideness. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + * @returns true if the rectangle is contained by this Polygon. + */ + public boolean contains (double x, double y, double w, double h) + { + return intersectOrContains (x, y, w, h, false); + } + + /** Return true if the indicated point is inside this Polygon. + * This uses an even-odd rule to determine insideness. + * @param x The x coordinate + * @param y The y coordinate + * @returns true if the point is contained by this Polygon. + */ + public boolean contains (int x, int y) + { + return contains ((double) x, (double) y); + } + + /** Return true if the indicated point is inside this Polygon. + * This uses an even-odd rule to determine insideness. + * @param p The point + * @returns true if the point is contained by this Polygon. + */ + public boolean contains (Point p) + { + return contains (p.x, p.y); + } + + /** Return true if the indicated point is inside this Polygon. + * This uses an even-odd rule to determine insideness. + * @param p The point + * @returns true if the point is contained by this Polygon. + */ + public boolean contains (Point2D p) + { + return contains (p.getX (), p.getY ()); + } + + /** Return true if the indicated rectangle is entirely inside this + * Polygon. This uses an even-odd rule to determine insideness. + * @param r The rectangle + * @returns true if the rectangle is contained by this Polygon. + */ + public boolean contains (Rectangle2D r) + { + return contains (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); + } + + /** Returns the bounds of this Polygon. + * @deprecated Use getBounds() instead. + */ + public Rectangle getBoundingBox () + { + if (bounds == null) + computeBoundingBox (); + return bounds; + } + + /** Returns the bounds of this Polygon. */ + public Rectangle getBounds () + { + if (bounds == null) + computeBoundingBox (); + return bounds; + } + + /** Returns the bounds of this Polygon. */ + public Rectangle2D getBounds2D () + { + if (bounds == null) + computeBoundingBox (); + return bounds; // Why not? + } + + /** Return an iterator for the boundary of this Polygon. + * @param at A transform to apply to the coordinates. + * @returns A path iterator for the Polygon's boundary. + */ + public PathIterator getPathIterator (AffineTransform at) + { + return new Iterator (at); + } + + /** Return an iterator for the boundary of this Polygon. + * @param at A transform to apply to the coordinates. + * @param flatness The flatness of the result; it is ignored by + * this class. + * @returns A path iterator for the Polygon's boundary. + */ + public PathIterator getPathIterator (AffineTransform at, double flatness) + { + // We ignore the flatness. + return new Iterator (at); + } + + /** @deprecated use contains(int,int). */ + public boolean inside (int x, int y) + { + return contains (x, y); + } + + /** Return true if this Polygon's interior intersects the given + * rectangle's interior. + * @param x The x coordinate + * @param y The y coordinate + * @param w The width + * @param h The height + */ + public boolean intersects (double x, double y, double w, double h) + { + return intersectOrContains (x, y, w, h, true); + } + + /** Return true if this Polygon's interior intersects the given + * rectangle's interior. + * @param r The rectangle + */ + public boolean intersects (Rectangle2D r) + { + return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ()); + } + + // This tests for intersection with or containment of a rectangle, + // depending on the INTERSECT argument. + private boolean intersectOrContains (double x, double y, double w, double h, + boolean intersect) + { + // First compute the rectangle of possible intersection points. + Rectangle r = getBounds (); + int minx = Math.max (r.x, (int) x); + int maxx = Math.min (r.x + r.width, (int) (x + w)); + int miny = Math.max (r.y, (int) y); + int maxy = Math.min (r.y + r.height, (int) (y + h)); + + if (miny > maxy) + return false; + + double[] crosses = new double[npoints + 1]; + + for (; miny < maxy; ++miny) + { + // First compute every place where the polygon might intersect + // the scan line at Y. + int ins = 0; + for (int i = 0; i < npoints; ++i) + { + // Handle the wrap case. + int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1]; + int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1]; + + if (ypoints[i] == y2) + { + // We ignore horizontal lines. This might give weird + // results in some situations -- ? + continue; + } + + double t = (((double) miny - ypoints[i]) + / (double) (y2 - ypoints[i])); + double x3 = xpoints[i] + t * (x2 - xpoints[i]); + crosses[ins++] = x3; + } + + // Now we can sort into increasing order and look to see if + // any point in the rectangle is in the polygon. We examine + // every other pair due to our even-odd rule. + Arrays.sort (crosses, 0, ins); + int i = intersect ? 0 : 1; + for (; i < ins - 1; i += 2) + { + // Pathological case. + if (crosses[i] == crosses[i + 1]) + continue; + + // Found a point on the inside. + if ((crosses[i] >= x && crosses[i] < x + w) + || (crosses[i + 1] >= x && crosses[i + 1] < x + w)) + { + // If we're checking containment then we just lost. + // But if we're checking intersection then we just + // won. + return intersect; + } + } + } + + return false; + } + + /** Translates all the vertices of the polygon via a given vector. + * @param deltaX The X offset + * @param deltaY The Y offset + */ + public void translate (int deltaX, int deltaY) + { + for (int i = 0; i < npoints; ++i) + { + xpoints[i] += deltaX; + ypoints[i] += deltaY; + } + + if (bounds != null) + { + bounds.x += deltaX; + bounds.y += deltaY; + } + } + + // This computes the bounding box if required. + private void computeBoundingBox () + { + if (npoints == 0) + { + // This is wrong if the user adds a new point, but we + // account for that in addPoint(). + bounds = new Rectangle (0, 0, 0, 0); + } + else + { + int maxx = xpoints[0]; + int minx = xpoints[0]; + int maxy = ypoints[0]; + int miny = ypoints[0]; + + for (int i = 1; i < npoints; ++i) + { + maxx = Math.max (maxx, xpoints[i]); + minx = Math.min (minx, xpoints[i]); + maxy = Math.max (maxy, ypoints[i]); + miny = Math.min (miny, ypoints[i]); + } + + bounds = new Rectangle (minx, miny, maxx - minx, maxy - miny); + } + } + + private class Iterator implements PathIterator + { + public AffineTransform xform; + public int where; + + public Iterator (AffineTransform xform) + { + this.xform = xform; + where = 0; + } + + public int currentSegment (double[] coords) + { + int r; + + if (where < npoints) + { + coords[0] = xpoints[where]; + coords[1] = ypoints[where]; + r = (where == 0) ? SEG_MOVETO : SEG_LINETO; + xform.transform (coords, 0, coords, 0, 1); + ++where; + } + else + r = SEG_CLOSE; + + return r; + } + + public int currentSegment (float[] coords) + { + int r; + + if (where < npoints) + { + coords[0] = xpoints[where]; + coords[1] = ypoints[where]; + r = (where == 0) ? SEG_MOVETO : SEG_LINETO; + xform.transform (coords, 0, coords, 0, 1); + } + else + r = SEG_CLOSE; + + return r; + } + + public int getWindingRule () + { + return WIND_EVEN_ODD; + } + + public boolean isDone () + { + return where == npoints + 1; + } + + public void next () + { + ++where; + } + } +} diff --git a/libjava/java/awt/geom/AffineTransform.java b/libjava/java/awt/geom/AffineTransform.java index 3e9bb8a..8e9b8f0 100644 --- a/libjava/java/awt/geom/AffineTransform.java +++ b/libjava/java/awt/geom/AffineTransform.java @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 Free Software Foundation +/* Copyright (C) 2000, 2001 Free Software Foundation This file is part of libjava. @@ -51,7 +51,7 @@ public class AffineTransform implements Cloneable, Serializable this.m11 = m11; this.m02 = m02; this.m12 = m12; - this.type = 0; // fixme; + this.type = TYPE_GENERAL_TRANSFORM; } public AffineTransform (float[] flatmatrix) @@ -260,6 +260,20 @@ public class AffineTransform implements Cloneable, Serializable type = TYPE_GENERAL_ROTATION; } + public void setToRotation (double theta, double x, double y) + { + double c = Math.cos (theta); + double s = Math.sin (theta); + + m00 = c; + m01 = -s; + m02 = x - x * c + y * s; + m10 = s; + m11 = c; + m12 = y - x * s - y * c; + type = TYPE_GENERAL_TRANSFORM; + } + public void setToScale (double sx, double sy) { m00 = sx; @@ -274,7 +288,7 @@ public class AffineTransform implements Cloneable, Serializable m01 = shx; m10 = shy; m02 = m12 = 0; - type = 0; // FIXME + type = TYPE_GENERAL_TRANSFORM; } public void setTransform (AffineTransform tx) -- 2.7.4