Source Code Cross Referenced for Path2D.java in  » 6.0-JDK-Core » AWT » java » awt » geom » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt.geom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.awt.geom;
0027
0028        import java.awt.Shape;
0029        import java.awt.Rectangle;
0030        import sun.awt.geom.Curve;
0031        import java.io.Serializable;
0032        import java.io.StreamCorruptedException;
0033        import java.util.Arrays;
0034
0035        /**
0036         * The {@code Path2D} class provides a simple, yet flexible
0037         * shape which represents an arbitrary geometric path.
0038         * It can fully represent any path which can be iterated by the
0039         * {@link PathIterator} interface including all of its segment
0040         * types and winding rules and it implements all of the
0041         * basic hit testing methods of the {@link Shape} interface.
0042         * <p>
0043         * Use {@link Path2D.Float} when dealing with data that can be represented
0044         * and used with floating point precision.  Use {@link Path2D.Double}
0045         * for data that requires the accuracy or range of double precision.
0046         * <p>
0047         * {@code Path2D} provides exactly those facilities required for
0048         * basic construction and management of a geometric path and
0049         * implementation of the above interfaces with little added
0050         * interpretation.
0051         * If it is useful to manipulate the interiors of closed
0052         * geometric shapes beyond simple hit testing then the
0053         * {@link Area} class provides additional capabilities
0054         * specifically targeted at closed figures.
0055         * While both classes nominally implement the {@code Shape}
0056         * interface, they differ in purpose and together they provide
0057         * two useful views of a geometric shape where {@code Path2D}
0058         * deals primarily with a trajectory formed by path segments
0059         * and {@code Area} deals more with interpretation and manipulation
0060         * of enclosed regions of 2D geometric space.
0061         * <p>
0062         * The {@link PathIterator} interface has more detailed descriptions
0063         * of the types of segments that make up a path and the winding rules
0064         * that control how to determine which regions are inside or outside
0065         * the path.
0066         * 
0067         * @version 1.10, 05/05/07
0068         * @author Jim Graham
0069         * @since 1.6
0070         */
0071        public abstract class Path2D implements  Shape, Cloneable {
0072            /**
0073             * An even-odd winding rule for determining the interior of
0074             * a path.  
0075             *
0076             * @see PathIterator#WIND_EVEN_ODD
0077             * @since 1.6
0078             */
0079            public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD;
0080
0081            /**
0082             * A non-zero winding rule for determining the interior of a
0083             * path.  
0084             *
0085             * @see PathIterator#WIND_NON_ZERO
0086             * @since 1.6
0087             */
0088            public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
0089
0090            // For code simplicity, copy these constants to our namespace
0091            // and cast them to byte constants for easy storage.
0092            private static final byte SEG_MOVETO = (byte) PathIterator.SEG_MOVETO;
0093            private static final byte SEG_LINETO = (byte) PathIterator.SEG_LINETO;
0094            private static final byte SEG_QUADTO = (byte) PathIterator.SEG_QUADTO;
0095            private static final byte SEG_CUBICTO = (byte) PathIterator.SEG_CUBICTO;
0096            private static final byte SEG_CLOSE = (byte) PathIterator.SEG_CLOSE;
0097
0098            transient byte[] pointTypes;
0099            transient int numTypes;
0100            transient int numCoords;
0101            transient int windingRule;
0102
0103            static final int INIT_SIZE = 20;
0104            static final int EXPAND_MAX = 500;
0105
0106            /**
0107             * Constructs a new empty {@code Path2D} object.
0108             * It is assumed that the package sibling subclass that is
0109             * defaulting to this constructor will fill in all values.
0110             *
0111             * @since 1.6
0112             */
0113            /* private protected */
0114            Path2D() {
0115            }
0116
0117            /**
0118             * Constructs a new {@code Path2D} object from the given
0119             * specified initial values.
0120             * This method is only intended for internal use and should
0121             * not be made public if the other constructors for this class
0122             * are ever exposed.
0123             *
0124             * @param rule the winding rule
0125             * @param initialTypes the size to make the initial array to
0126             *                     store the path segment types
0127             * @since 1.6
0128             */
0129            /* private protected */
0130            Path2D(int rule, int initialTypes) {
0131                setWindingRule(rule);
0132                this .pointTypes = new byte[initialTypes];
0133            }
0134
0135            abstract float[] cloneCoordsFloat(AffineTransform at);
0136
0137            abstract double[] cloneCoordsDouble(AffineTransform at);
0138
0139            abstract void append(float x, float y);
0140
0141            abstract void append(double x, double y);
0142
0143            abstract Point2D getPoint(int coordindex);
0144
0145            abstract void needRoom(boolean needMove, int newCoords);
0146
0147            abstract int pointCrossings(double px, double py);
0148
0149            abstract int rectCrossings(double rxmin, double rymin,
0150                    double rxmax, double rymax);
0151
0152            /**
0153             * The {@code Float} class defines a geometric path with
0154             * coordinates stored in single precision floating point.
0155             *
0156             * @since 1.6
0157             */
0158            public static class Float extends Path2D implements  Serializable {
0159                transient float floatCoords[];
0160
0161                /**
0162                 * Constructs a new empty single precision {@code Path2D} object
0163                 * with a default winding rule of {@link #WIND_NON_ZERO}.
0164                 *
0165                 * @since 1.6
0166                 */
0167                public Float() {
0168                    this (WIND_NON_ZERO, INIT_SIZE);
0169                }
0170
0171                /**
0172                 * Constructs a new empty single precision {@code Path2D} object
0173                 * with the specified winding rule to control operations that
0174                 * require the interior of the path to be defined.
0175                 *
0176                 * @param rule the winding rule
0177                 * @see #WIND_EVEN_ODD
0178                 * @see #WIND_NON_ZERO
0179                 * @since 1.6
0180                 */
0181                public Float(int rule) {
0182                    this (rule, INIT_SIZE);
0183                }
0184
0185                /**
0186                 * Constructs a new empty single precision {@code Path2D} object
0187                 * with the specified winding rule and the specified initial
0188                 * capacity to store path segments.
0189                 * This number is an initial guess as to how many path segments
0190                 * will be added to the path, but the storage is expanded as
0191                 * needed to store whatever path segments are added.
0192                 *
0193                 * @param rule the winding rule
0194                 * @param initialCapacity the estimate for the number of path segments
0195                 *                        in the path
0196                 * @see #WIND_EVEN_ODD
0197                 * @see #WIND_NON_ZERO
0198                 * @since 1.6
0199                 */
0200                public Float(int rule, int initialCapacity) {
0201                    super (rule, initialCapacity);
0202                    floatCoords = new float[initialCapacity * 2];
0203                }
0204
0205                /**
0206                 * Constructs a new single precision {@code Path2D} object
0207                 * from an arbitrary {@link Shape} object.
0208                 * All of the initial geometry and the winding rule for this path are
0209                 * taken from the specified {@code Shape} object.
0210                 *
0211                 * @param s the specified {@code Shape} object
0212                 * @since 1.6
0213                 */
0214                public Float(Shape s) {
0215                    this (s, null);
0216                }
0217
0218                /**
0219                 * Constructs a new single precision {@code Path2D} object
0220                 * from an arbitrary {@link Shape} object, transformed by an
0221                 * {@link AffineTransform} object.
0222                 * All of the initial geometry and the winding rule for this path are
0223                 * taken from the specified {@code Shape} object and transformed
0224                 * by the specified {@code AffineTransform} object.
0225                 *
0226                 * @param s the specified {@code Shape} object
0227                 * @param at the specified {@code AffineTransform} object
0228                 * @since 1.6
0229                 */
0230                public Float(Shape s, AffineTransform at) {
0231                    if (s instanceof  Path2D) {
0232                        Path2D p2d = (Path2D) s;
0233                        setWindingRule(p2d.windingRule);
0234                        this .numTypes = p2d.numTypes;
0235                        this .pointTypes = Arrays.copyOf(p2d.pointTypes,
0236                                p2d.pointTypes.length);
0237                        this .numCoords = p2d.numCoords;
0238                        this .floatCoords = p2d.cloneCoordsFloat(at);
0239                    } else {
0240                        PathIterator pi = s.getPathIterator(at);
0241                        setWindingRule(pi.getWindingRule());
0242                        this .pointTypes = new byte[INIT_SIZE];
0243                        this .floatCoords = new float[INIT_SIZE * 2];
0244                        append(pi, false);
0245                    }
0246                }
0247
0248                float[] cloneCoordsFloat(AffineTransform at) {
0249                    float ret[];
0250                    if (at == null) {
0251                        ret = Arrays.copyOf(this .floatCoords,
0252                                this .floatCoords.length);
0253                    } else {
0254                        ret = new float[floatCoords.length];
0255                        at.transform(floatCoords, 0, ret, 0, numCoords / 2);
0256                    }
0257                    return ret;
0258                }
0259
0260                double[] cloneCoordsDouble(AffineTransform at) {
0261                    double ret[] = new double[floatCoords.length];
0262                    if (at == null) {
0263                        for (int i = 0; i < numCoords; i++) {
0264                            ret[i] = floatCoords[i];
0265                        }
0266                    } else {
0267                        at.transform(floatCoords, 0, ret, 0, numCoords / 2);
0268                    }
0269                    return ret;
0270                }
0271
0272                void append(float x, float y) {
0273                    floatCoords[numCoords++] = x;
0274                    floatCoords[numCoords++] = y;
0275                }
0276
0277                void append(double x, double y) {
0278                    floatCoords[numCoords++] = (float) x;
0279                    floatCoords[numCoords++] = (float) y;
0280                }
0281
0282                Point2D getPoint(int coordindex) {
0283                    return new Point2D.Float(floatCoords[coordindex],
0284                            floatCoords[coordindex + 1]);
0285                }
0286
0287                void needRoom(boolean needMove, int newCoords) {
0288                    if (needMove && numTypes == 0) {
0289                        throw new IllegalPathStateException(
0290                                "missing initial moveto "
0291                                        + "in path definition");
0292                    }
0293                    int size = pointTypes.length;
0294                    if (numTypes >= size) {
0295                        int grow = size;
0296                        if (grow > EXPAND_MAX) {
0297                            grow = EXPAND_MAX;
0298                        }
0299                        pointTypes = Arrays.copyOf(pointTypes, size + grow);
0300                    }
0301                    size = floatCoords.length;
0302                    if (numCoords + newCoords > size) {
0303                        int grow = size;
0304                        if (grow > EXPAND_MAX * 2) {
0305                            grow = EXPAND_MAX * 2;
0306                        }
0307                        if (grow < newCoords) {
0308                            grow = newCoords;
0309                        }
0310                        floatCoords = Arrays.copyOf(floatCoords, size + grow);
0311                    }
0312                }
0313
0314                /**
0315                 * {@inheritDoc}
0316                 * @since 1.6
0317                 */
0318                public final synchronized void moveTo(double x, double y) {
0319                    if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) {
0320                        floatCoords[numCoords - 2] = (float) x;
0321                        floatCoords[numCoords - 1] = (float) y;
0322                    } else {
0323                        needRoom(false, 2);
0324                        pointTypes[numTypes++] = SEG_MOVETO;
0325                        floatCoords[numCoords++] = (float) x;
0326                        floatCoords[numCoords++] = (float) y;
0327                    }
0328                }
0329
0330                /**
0331                 * Adds a point to the path by moving to the specified
0332                 * coordinates specified in float precision.
0333                 * <p>
0334                 * This method provides a single precision variant of
0335                 * the double precision {@code moveTo()} method on the
0336                 * base {@code Path2D} class.
0337                 *
0338                 * @param x the specified X coordinate
0339                 * @param y the specified Y coordinate
0340                 * @see Path2D#moveTo
0341                 * @since 1.6
0342                 */
0343                public final synchronized void moveTo(float x, float y) {
0344                    if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) {
0345                        floatCoords[numCoords - 2] = x;
0346                        floatCoords[numCoords - 1] = y;
0347                    } else {
0348                        needRoom(false, 2);
0349                        pointTypes[numTypes++] = SEG_MOVETO;
0350                        floatCoords[numCoords++] = x;
0351                        floatCoords[numCoords++] = y;
0352                    }
0353                }
0354
0355                /**
0356                 * {@inheritDoc}
0357                 * @since 1.6
0358                 */
0359                public final synchronized void lineTo(double x, double y) {
0360                    needRoom(true, 2);
0361                    pointTypes[numTypes++] = SEG_LINETO;
0362                    floatCoords[numCoords++] = (float) x;
0363                    floatCoords[numCoords++] = (float) y;
0364                }
0365
0366                /**
0367                 * Adds a point to the path by drawing a straight line from the
0368                 * current coordinates to the new specified coordinates
0369                 * specified in float precision.
0370                 * <p>
0371                 * This method provides a single precision variant of
0372                 * the double precision {@code lineTo()} method on the
0373                 * base {@code Path2D} class.
0374                 *
0375                 * @param x the specified X coordinate
0376                 * @param y the specified Y coordinate
0377                 * @see Path2D#lineTo
0378                 * @since 1.6
0379                 */
0380                public final synchronized void lineTo(float x, float y) {
0381                    needRoom(true, 2);
0382                    pointTypes[numTypes++] = SEG_LINETO;
0383                    floatCoords[numCoords++] = x;
0384                    floatCoords[numCoords++] = y;
0385                }
0386
0387                /**
0388                 * {@inheritDoc}
0389                 * @since 1.6
0390                 */
0391                public final synchronized void quadTo(double x1, double y1,
0392                        double x2, double y2) {
0393                    needRoom(true, 4);
0394                    pointTypes[numTypes++] = SEG_QUADTO;
0395                    floatCoords[numCoords++] = (float) x1;
0396                    floatCoords[numCoords++] = (float) y1;
0397                    floatCoords[numCoords++] = (float) x2;
0398                    floatCoords[numCoords++] = (float) y2;
0399                }
0400
0401                /**
0402                 * Adds a curved segment, defined by two new points, to the path by
0403                 * drawing a Quadratic curve that intersects both the current
0404                 * coordinates and the specified coordinates {@code (x2,y2)},
0405                 * using the specified point {@code (x1,y1)} as a quadratic
0406                 * parametric control point.
0407                 * All coordinates are specified in float precision.
0408                 * <p>
0409                 * This method provides a single precision variant of
0410                 * the double precision {@code quadTo()} method on the
0411                 * base {@code Path2D} class.
0412                 *
0413                 * @param x1 the X coordinate of the quadratic control point
0414                 * @param y1 the Y coordinate of the quadratic control point
0415                 * @param x2 the X coordinate of the final end point
0416                 * @param y2 the Y coordinate of the final end point
0417                 * @see Path2D#quadTo
0418                 * @since 1.6
0419                 */
0420                public final synchronized void quadTo(float x1, float y1,
0421                        float x2, float y2) {
0422                    needRoom(true, 4);
0423                    pointTypes[numTypes++] = SEG_QUADTO;
0424                    floatCoords[numCoords++] = x1;
0425                    floatCoords[numCoords++] = y1;
0426                    floatCoords[numCoords++] = x2;
0427                    floatCoords[numCoords++] = y2;
0428                }
0429
0430                /**
0431                 * {@inheritDoc}
0432                 * @since 1.6
0433                 */
0434                public final synchronized void curveTo(double x1, double y1,
0435                        double x2, double y2, double x3, double y3) {
0436                    needRoom(true, 6);
0437                    pointTypes[numTypes++] = SEG_CUBICTO;
0438                    floatCoords[numCoords++] = (float) x1;
0439                    floatCoords[numCoords++] = (float) y1;
0440                    floatCoords[numCoords++] = (float) x2;
0441                    floatCoords[numCoords++] = (float) y2;
0442                    floatCoords[numCoords++] = (float) x3;
0443                    floatCoords[numCoords++] = (float) y3;
0444                }
0445
0446                /**
0447                 * Adds a curved segment, defined by three new points, to the path by
0448                 * drawing a B&eacute;zier curve that intersects both the current
0449                 * coordinates and the specified coordinates {@code (x3,y3)},
0450                 * using the specified points {@code (x1,y1)} and {@code (x2,y2)} as
0451                 * B&eacute;zier control points.
0452                 * All coordinates are specified in float precision.
0453                 * <p>
0454                 * This method provides a single precision variant of
0455                 * the double precision {@code curveTo()} method on the
0456                 * base {@code Path2D} class.
0457                 *
0458                 * @param x1 the X coordinate of the first B&eacute;zier control point
0459                 * @param y1 the Y coordinate of the first B&eacute;zier control point
0460                 * @param x2 the X coordinate of the second B&eacute;zier control point
0461                 * @param y2 the Y coordinate of the second B&eacute;zier control point
0462                 * @param x3 the X coordinate of the final end point
0463                 * @param y3 the Y coordinate of the final end point
0464                 * @see Path2D#curveTo
0465                 * @since 1.6
0466                 */
0467                public final synchronized void curveTo(float x1, float y1,
0468                        float x2, float y2, float x3, float y3) {
0469                    needRoom(true, 6);
0470                    pointTypes[numTypes++] = SEG_CUBICTO;
0471                    floatCoords[numCoords++] = x1;
0472                    floatCoords[numCoords++] = y1;
0473                    floatCoords[numCoords++] = x2;
0474                    floatCoords[numCoords++] = y2;
0475                    floatCoords[numCoords++] = x3;
0476                    floatCoords[numCoords++] = y3;
0477                }
0478
0479                int pointCrossings(double px, double py) {
0480                    double movx, movy, curx, cury, endx, endy;
0481                    float coords[] = floatCoords;
0482                    curx = movx = coords[0];
0483                    cury = movy = coords[1];
0484                    int crossings = 0;
0485                    int ci = 2;
0486                    for (int i = 1; i < numTypes; i++) {
0487                        switch (pointTypes[i]) {
0488                        case PathIterator.SEG_MOVETO:
0489                            if (cury != movy) {
0490                                crossings += Curve.pointCrossingsForLine(px,
0491                                        py, curx, cury, movx, movy);
0492                            }
0493                            movx = curx = coords[ci++];
0494                            movy = cury = coords[ci++];
0495                            break;
0496                        case PathIterator.SEG_LINETO:
0497                            crossings += Curve.pointCrossingsForLine(px, py,
0498                                    curx, cury, endx = coords[ci++],
0499                                    endy = coords[ci++]);
0500                            curx = endx;
0501                            cury = endy;
0502                            break;
0503                        case PathIterator.SEG_QUADTO:
0504                            crossings += Curve
0505                                    .pointCrossingsForQuad(px, py, curx, cury,
0506                                            coords[ci++], coords[ci++],
0507                                            endx = coords[ci++],
0508                                            endy = coords[ci++], 0);
0509                            curx = endx;
0510                            cury = endy;
0511                            break;
0512                        case PathIterator.SEG_CUBICTO:
0513                            crossings += Curve
0514                                    .pointCrossingsForCubic(px, py, curx, cury,
0515                                            coords[ci++], coords[ci++],
0516                                            coords[ci++], coords[ci++],
0517                                            endx = coords[ci++],
0518                                            endy = coords[ci++], 0);
0519                            curx = endx;
0520                            cury = endy;
0521                            break;
0522                        case PathIterator.SEG_CLOSE:
0523                            if (cury != movy) {
0524                                crossings += Curve.pointCrossingsForLine(px,
0525                                        py, curx, cury, movx, movy);
0526                            }
0527                            curx = movx;
0528                            cury = movy;
0529                            break;
0530                        }
0531                    }
0532                    if (cury != movy) {
0533                        crossings += Curve.pointCrossingsForLine(px, py, curx,
0534                                cury, movx, movy);
0535                    }
0536                    return crossings;
0537                }
0538
0539                int rectCrossings(double rxmin, double rymin, double rxmax,
0540                        double rymax) {
0541                    float coords[] = floatCoords;
0542                    double curx, cury, movx, movy, endx, endy;
0543                    curx = movx = coords[0];
0544                    cury = movy = coords[1];
0545                    int crossings = 0;
0546                    int ci = 2;
0547                    for (int i = 1; crossings != Curve.RECT_INTERSECTS
0548                            && i < numTypes; i++) {
0549                        switch (pointTypes[i]) {
0550                        case PathIterator.SEG_MOVETO:
0551                            if (curx != movx || cury != movy) {
0552                                crossings = Curve.rectCrossingsForLine(
0553                                        crossings, rxmin, rymin, rxmax, rymax,
0554                                        curx, cury, movx, movy);
0555                            }
0556                            // Count should always be a multiple of 2 here.
0557                            // assert((crossings & 1) != 0);
0558                            movx = curx = coords[ci++];
0559                            movy = cury = coords[ci++];
0560                            break;
0561                        case PathIterator.SEG_LINETO:
0562                            crossings = Curve.rectCrossingsForLine(crossings,
0563                                    rxmin, rymin, rxmax, rymax, curx, cury,
0564                                    endx = coords[ci++], endy = coords[ci++]);
0565                            curx = endx;
0566                            cury = endy;
0567                            break;
0568                        case PathIterator.SEG_QUADTO:
0569                            crossings = Curve
0570                                    .rectCrossingsForQuad(crossings, rxmin,
0571                                            rymin, rxmax, rymax, curx, cury,
0572                                            coords[ci++], coords[ci++],
0573                                            endx = coords[ci++],
0574                                            endy = coords[ci++], 0);
0575                            curx = endx;
0576                            cury = endy;
0577                            break;
0578                        case PathIterator.SEG_CUBICTO:
0579                            crossings = Curve.rectCrossingsForCubic(crossings,
0580                                    rxmin, rymin, rxmax, rymax, curx, cury,
0581                                    coords[ci++], coords[ci++], coords[ci++],
0582                                    coords[ci++], endx = coords[ci++],
0583                                    endy = coords[ci++], 0);
0584                            curx = endx;
0585                            cury = endy;
0586                            break;
0587                        case PathIterator.SEG_CLOSE:
0588                            if (curx != movx || cury != movy) {
0589                                crossings = Curve.rectCrossingsForLine(
0590                                        crossings, rxmin, rymin, rxmax, rymax,
0591                                        curx, cury, movx, movy);
0592                            }
0593                            curx = movx;
0594                            cury = movy;
0595                            // Count should always be a multiple of 2 here.
0596                            // assert((crossings & 1) != 0);
0597                            break;
0598                        }
0599                    }
0600                    if (crossings != Curve.RECT_INTERSECTS
0601                            && (curx != movx || cury != movy)) {
0602                        crossings = Curve.rectCrossingsForLine(crossings,
0603                                rxmin, rymin, rxmax, rymax, curx, cury, movx,
0604                                movy);
0605                    }
0606                    // Count should always be a multiple of 2 here.
0607                    // assert((crossings & 1) != 0);
0608                    return crossings;
0609                }
0610
0611                /**
0612                 * {@inheritDoc}
0613                 * @since 1.6
0614                 */
0615                public final void append(PathIterator pi, boolean connect) {
0616                    float coords[] = new float[6];
0617                    while (!pi.isDone()) {
0618                        switch (pi.currentSegment(coords)) {
0619                        case SEG_MOVETO:
0620                            if (!connect || numTypes < 1 || numCoords < 1) {
0621                                moveTo(coords[0], coords[1]);
0622                                break;
0623                            }
0624                            if (pointTypes[numTypes - 1] != SEG_CLOSE
0625                                    && floatCoords[numCoords - 2] == coords[0]
0626                                    && floatCoords[numCoords - 1] == coords[1]) {
0627                                // Collapse out initial moveto/lineto
0628                                break;
0629                            }
0630                            // NO BREAK;
0631                        case SEG_LINETO:
0632                            lineTo(coords[0], coords[1]);
0633                            break;
0634                        case SEG_QUADTO:
0635                            quadTo(coords[0], coords[1], coords[2], coords[3]);
0636                            break;
0637                        case SEG_CUBICTO:
0638                            curveTo(coords[0], coords[1], coords[2], coords[3],
0639                                    coords[4], coords[5]);
0640                            break;
0641                        case SEG_CLOSE:
0642                            closePath();
0643                            break;
0644                        }
0645                        pi.next();
0646                        connect = false;
0647                    }
0648                }
0649
0650                /**
0651                 * {@inheritDoc}
0652                 * @since 1.6
0653                 */
0654                public final void transform(AffineTransform at) {
0655                    at.transform(floatCoords, 0, floatCoords, 0, numCoords / 2);
0656                }
0657
0658                /**
0659                 * {@inheritDoc}
0660                 * @since 1.6
0661                 */
0662                public final synchronized Rectangle2D getBounds2D() {
0663                    float x1, y1, x2, y2;
0664                    int i = numCoords;
0665                    if (i > 0) {
0666                        y1 = y2 = floatCoords[--i];
0667                        x1 = x2 = floatCoords[--i];
0668                        while (i > 0) {
0669                            float y = floatCoords[--i];
0670                            float x = floatCoords[--i];
0671                            if (x < x1)
0672                                x1 = x;
0673                            if (y < y1)
0674                                y1 = y;
0675                            if (x > x2)
0676                                x2 = x;
0677                            if (y > y2)
0678                                y2 = y;
0679                        }
0680                    } else {
0681                        x1 = y1 = x2 = y2 = 0.0f;
0682                    }
0683                    return new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1);
0684                }
0685
0686                /**
0687                 * {@inheritDoc}
0688                 * <p>
0689                 * The iterator for this class is not multi-threaded safe,
0690                 * which means that the {@code Path2D} class does not
0691                 * guarantee that modifications to the geometry of this
0692                 * {@code Path2D} object do not affect any iterations of
0693                 * that geometry that are already in process.
0694                 *
0695                 * @since 1.6
0696                 */
0697                public PathIterator getPathIterator(AffineTransform at) {
0698                    if (at == null) {
0699                        return new CopyIterator(this );
0700                    } else {
0701                        return new TxIterator(this , at);
0702                    }
0703                }
0704
0705                /**
0706                 * Creates a new object of the same class as this object.
0707                 *
0708                 * @return     a clone of this instance.
0709                 * @exception  OutOfMemoryError    if there is not enough memory.
0710                 * @see        java.lang.Cloneable
0711                 * @since      1.6
0712                 */
0713                public final Object clone() {
0714                    // Note: It would be nice to have this return Path2D
0715                    // but one of our subclasses (GeneralPath) needs to
0716                    // offer "public Object clone()" for backwards
0717                    // compatibility so we cannot restrict it further.
0718                    // REMIND: Can we do both somehow?
0719                    if (this  instanceof  GeneralPath) {
0720                        return new GeneralPath(this );
0721                    } else {
0722                        return new Path2D.Float(this );
0723                    }
0724                }
0725
0726                /*
0727                 * JDK 1.6 serialVersionUID
0728                 */
0729                private static final long serialVersionUID = 6990832515060788886L;
0730
0731                /**
0732                 * Writes the default serializable fields to the
0733                 * {@code ObjectOutputStream} followed by an explicit
0734                 * serialization of the path segments stored in this
0735                 * path.
0736                 *
0737                 * @serialData
0738                 * <a name="Path2DSerialData"><!-- --></a>
0739                 * <ol>
0740                 * <li>The default serializable fields.
0741                 * There are no default serializable fields as of 1.6.
0742                 * <li>followed by
0743                 * a byte indicating the storage type of the original object
0744                 * as a hint (SERIAL_STORAGE_FLT_ARRAY)
0745                 * <li>followed by
0746                 * an integer indicating the number of path segments to follow (NP)
0747                 * or -1 to indicate an unknown number of path segments follows
0748                 * <li>followed by
0749                 * an integer indicating the total number of coordinates to follow (NC)
0750                 * or -1 to indicate an unknown number of coordinates follows
0751                 * (NC should always be even since coordinates always appear in pairs
0752                 *  representing an x,y pair)
0753                 * <li>followed by
0754                 * a byte indicating the winding rule
0755                 * ({@link #WIND_EVEN_ODD WIND_EVEN_ODD} or
0756                 *  {@link #WIND_NON_ZERO WIND_NON_ZERO})
0757                 * <li>followed by
0758                 * NP (or unlimited if NP < 0) sets of values consisting of
0759                 * a single byte indicating a path segment type
0760                 * followed by one or more pairs of float or double
0761                 * values representing the coordinates of the path segment
0762                 * <li>followed by
0763                 * a byte indicating the end of the path (SERIAL_PATH_END).
0764                 * </ol>
0765                 * <p>
0766                 * The following byte value constants are used in the serialized form
0767                 * of {@code Path2D} objects:
0768                 * <table>
0769                 * <tr>
0770                 * <th>Constant Name</th>
0771                 * <th>Byte Value</th>
0772                 * <th>Followed by</th>
0773                 * <th>Description</th>
0774                 * </tr>
0775                 * <tr>
0776                 * <td>{@code SERIAL_STORAGE_FLT_ARRAY}</td>
0777                 * <td>0x30</td>
0778                 * <td></td>
0779                 * <td>A hint that the original {@code Path2D} object stored
0780                 * the coordinates in a Java array of floats.</td>
0781                 * </tr>
0782                 * <tr>
0783                 * <td>{@code SERIAL_STORAGE_DBL_ARRAY}</td>
0784                 * <td>0x31</td>
0785                 * <td></td>
0786                 * <td>A hint that the original {@code Path2D} object stored
0787                 * the coordinates in a Java array of doubles.</td>
0788                 * </tr>
0789                 * <tr>
0790                 * <td>{@code SERIAL_SEG_FLT_MOVETO}</td>
0791                 * <td>0x40</td>
0792                 * <td>2 floats</td>
0793                 * <td>A {@link #moveTo moveTo} path segment follows.</td>
0794                 * </tr>
0795                 * <tr>
0796                 * <td>{@code SERIAL_SEG_FLT_LINETO}</td>
0797                 * <td>0x41</td>
0798                 * <td>2 floats</td>
0799                 * <td>A {@link #lineTo lineTo} path segment follows.</td>
0800                 * </tr>
0801                 * <tr>
0802                 * <td>{@code SERIAL_SEG_FLT_QUADTO}</td>
0803                 * <td>0x42</td>
0804                 * <td>4 floats</td>
0805                 * <td>A {@link #quadTo quadTo} path segment follows.</td>
0806                 * </tr>
0807                 * <tr>
0808                 * <td>{@code SERIAL_SEG_FLT_CUBICTO}</td>
0809                 * <td>0x43</td>
0810                 * <td>6 floats</td>
0811                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
0812                 * </tr>
0813                 * <tr>
0814                 * <td>{@code SERIAL_SEG_DBL_MOVETO}</td>
0815                 * <td>0x50</td>
0816                 * <td>2 doubles</td>
0817                 * <td>A {@link #moveTo moveTo} path segment follows.</td>
0818                 * </tr>
0819                 * <tr>
0820                 * <td>{@code SERIAL_SEG_DBL_LINETO}</td>
0821                 * <td>0x51</td>
0822                 * <td>2 doubles</td>
0823                 * <td>A {@link #lineTo lineTo} path segment follows.</td>
0824                 * </tr>
0825                 * <tr>
0826                 * <td>{@code SERIAL_SEG_DBL_QUADTO}</td>
0827                 * <td>0x52</td>
0828                 * <td>4 doubles</td>
0829                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
0830                 * </tr>
0831                 * <tr>
0832                 * <td>{@code SERIAL_SEG_DBL_CUBICTO}</td>
0833                 * <td>0x53</td>
0834                 * <td>6 doubles</td>
0835                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
0836                 * </tr>
0837                 * <tr>
0838                 * <td>{@code SERIAL_SEG_CLOSE}</td>
0839                 * <td>0x60</td>
0840                 * <td></td>
0841                 * <td>A {@link #closePath closePath} path segment.</td>
0842                 * </tr>
0843                 * <tr>
0844                 * <td>{@code SERIAL_PATH_END}</td>
0845                 * <td>0x61</td>
0846                 * <td></td>
0847                 * <td>There are no more path segments following.</td>
0848                 * </table>
0849                 *
0850                 * @since 1.6
0851                 */
0852                private void writeObject(java.io.ObjectOutputStream s)
0853                        throws java.io.IOException {
0854                    super .writeObject(s, false);
0855                }
0856
0857                /**
0858                 * Reads the default serializable fields from the
0859                 * {@code ObjectInputStream} followed by an explicit
0860                 * serialization of the path segments stored in this
0861                 * path.
0862                 * <p>
0863                 * There are no default serializable fields as of 1.6.
0864                 * <p>
0865                 * The serial data for this object is described in the
0866                 * writeObject method.
0867                 *
0868                 * @since 1.6
0869                 */
0870                private void readObject(java.io.ObjectInputStream s)
0871                        throws java.lang.ClassNotFoundException,
0872                        java.io.IOException {
0873                    super .readObject(s, false);
0874                }
0875
0876                static class CopyIterator extends Path2D.Iterator {
0877                    float floatCoords[];
0878
0879                    CopyIterator(Path2D.Float p2df) {
0880                        super (p2df);
0881                        this .floatCoords = p2df.floatCoords;
0882                    }
0883
0884                    public int currentSegment(float[] coords) {
0885                        int type = path.pointTypes[typeIdx];
0886                        int numCoords = curvecoords[type];
0887                        if (numCoords > 0) {
0888                            System.arraycopy(floatCoords, pointIdx, coords, 0,
0889                                    numCoords);
0890                        }
0891                        return type;
0892                    }
0893
0894                    public int currentSegment(double[] coords) {
0895                        int type = path.pointTypes[typeIdx];
0896                        int numCoords = curvecoords[type];
0897                        if (numCoords > 0) {
0898                            for (int i = 0; i < numCoords; i++) {
0899                                coords[i] = floatCoords[pointIdx + i];
0900                            }
0901                        }
0902                        return type;
0903                    }
0904                }
0905
0906                static class TxIterator extends Path2D.Iterator {
0907                    float floatCoords[];
0908                    AffineTransform affine;
0909
0910                    TxIterator(Path2D.Float p2df, AffineTransform at) {
0911                        super (p2df);
0912                        this .floatCoords = p2df.floatCoords;
0913                        this .affine = at;
0914                    }
0915
0916                    public int currentSegment(float[] coords) {
0917                        int type = path.pointTypes[typeIdx];
0918                        int numCoords = curvecoords[type];
0919                        if (numCoords > 0) {
0920                            affine.transform(floatCoords, pointIdx, coords, 0,
0921                                    numCoords / 2);
0922                        }
0923                        return type;
0924                    }
0925
0926                    public int currentSegment(double[] coords) {
0927                        int type = path.pointTypes[typeIdx];
0928                        int numCoords = curvecoords[type];
0929                        if (numCoords > 0) {
0930                            affine.transform(floatCoords, pointIdx, coords, 0,
0931                                    numCoords / 2);
0932                        }
0933                        return type;
0934                    }
0935                }
0936
0937            }
0938
0939            /**
0940             * The {@code Double} class defines a geometric path with
0941             * coordinates stored in double precision floating point.
0942             *
0943             * @since 1.6
0944             */
0945            public static class Double extends Path2D implements  Serializable {
0946                transient double doubleCoords[];
0947
0948                /**
0949                 * Constructs a new empty double precision {@code Path2D} object
0950                 * with a default winding rule of {@link #WIND_NON_ZERO}.
0951                 *
0952                 * @since 1.6
0953                 */
0954                public Double() {
0955                    this (WIND_NON_ZERO, INIT_SIZE);
0956                }
0957
0958                /**
0959                 * Constructs a new empty double precision {@code Path2D} object
0960                 * with the specified winding rule to control operations that
0961                 * require the interior of the path to be defined.
0962                 *
0963                 * @param rule the winding rule
0964                 * @see #WIND_EVEN_ODD
0965                 * @see #WIND_NON_ZERO
0966                 * @since 1.6
0967                 */
0968                public Double(int rule) {
0969                    this (rule, INIT_SIZE);
0970                }
0971
0972                /**
0973                 * Constructs a new empty double precision {@code Path2D} object
0974                 * with the specified winding rule and the specified initial
0975                 * capacity to store path segments.
0976                 * This number is an initial guess as to how many path segments
0977                 * are in the path, but the storage is expanded as needed to store
0978                 * whatever path segments are added to this path.
0979                 *
0980                 * @param rule the winding rule
0981                 * @param initialCapacity the estimate for the number of path segments
0982                 *                        in the path
0983                 * @see #WIND_EVEN_ODD
0984                 * @see #WIND_NON_ZERO
0985                 * @since 1.6
0986                 */
0987                public Double(int rule, int initialCapacity) {
0988                    super (rule, initialCapacity);
0989                    doubleCoords = new double[initialCapacity * 2];
0990                }
0991
0992                /**
0993                 * Constructs a new double precision {@code Path2D} object
0994                 * from an arbitrary {@link Shape} object.
0995                 * All of the initial geometry and the winding rule for this path are
0996                 * taken from the specified {@code Shape} object.
0997                 *
0998                 * @param s the specified {@code Shape} object
0999                 * @since 1.6
1000                 */
1001                public Double(Shape s) {
1002                    this (s, null);
1003                }
1004
1005                /**
1006                 * Constructs a new double precision {@code Path2D} object
1007                 * from an arbitrary {@link Shape} object, transformed by an
1008                 * {@link AffineTransform} object.
1009                 * All of the initial geometry and the winding rule for this path are
1010                 * taken from the specified {@code Shape} object and transformed
1011                 * by the specified {@code AffineTransform} object.
1012                 *
1013                 * @param s the specified {@code Shape} object
1014                 * @param at the specified {@code AffineTransform} object
1015                 * @since 1.6
1016                 */
1017                public Double(Shape s, AffineTransform at) {
1018                    if (s instanceof  Path2D) {
1019                        Path2D p2d = (Path2D) s;
1020                        setWindingRule(p2d.windingRule);
1021                        this .numTypes = p2d.numTypes;
1022                        this .pointTypes = Arrays.copyOf(p2d.pointTypes,
1023                                p2d.pointTypes.length);
1024                        this .numCoords = p2d.numCoords;
1025                        this .doubleCoords = p2d.cloneCoordsDouble(at);
1026                    } else {
1027                        PathIterator pi = s.getPathIterator(at);
1028                        setWindingRule(pi.getWindingRule());
1029                        this .pointTypes = new byte[INIT_SIZE];
1030                        this .doubleCoords = new double[INIT_SIZE * 2];
1031                        append(pi, false);
1032                    }
1033                }
1034
1035                float[] cloneCoordsFloat(AffineTransform at) {
1036                    float ret[] = new float[doubleCoords.length];
1037                    if (at == null) {
1038                        for (int i = 0; i < numCoords; i++) {
1039                            ret[i] = (float) doubleCoords[i];
1040                        }
1041                    } else {
1042                        at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1043                    }
1044                    return ret;
1045                }
1046
1047                double[] cloneCoordsDouble(AffineTransform at) {
1048                    double ret[];
1049                    if (at == null) {
1050                        ret = Arrays.copyOf(this .doubleCoords,
1051                                this .doubleCoords.length);
1052                    } else {
1053                        ret = new double[doubleCoords.length];
1054                        at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1055                    }
1056                    return ret;
1057                }
1058
1059                void append(float x, float y) {
1060                    doubleCoords[numCoords++] = x;
1061                    doubleCoords[numCoords++] = y;
1062                }
1063
1064                void append(double x, double y) {
1065                    doubleCoords[numCoords++] = x;
1066                    doubleCoords[numCoords++] = y;
1067                }
1068
1069                Point2D getPoint(int coordindex) {
1070                    return new Point2D.Double(doubleCoords[coordindex],
1071                            doubleCoords[coordindex + 1]);
1072                }
1073
1074                void needRoom(boolean needMove, int newCoords) {
1075                    if (needMove && numTypes == 0) {
1076                        throw new IllegalPathStateException(
1077                                "missing initial moveto "
1078                                        + "in path definition");
1079                    }
1080                    int size = pointTypes.length;
1081                    if (numTypes >= size) {
1082                        int grow = size;
1083                        if (grow > EXPAND_MAX) {
1084                            grow = EXPAND_MAX;
1085                        }
1086                        pointTypes = Arrays.copyOf(pointTypes, size + grow);
1087                    }
1088                    size = doubleCoords.length;
1089                    if (numCoords + newCoords > size) {
1090                        int grow = size;
1091                        if (grow > EXPAND_MAX * 2) {
1092                            grow = EXPAND_MAX * 2;
1093                        }
1094                        if (grow < newCoords) {
1095                            grow = newCoords;
1096                        }
1097                        doubleCoords = Arrays.copyOf(doubleCoords, size + grow);
1098                    }
1099                }
1100
1101                /**
1102                 * {@inheritDoc}
1103                 * @since 1.6
1104                 */
1105                public final synchronized void moveTo(double x, double y) {
1106                    if (numTypes > 0 && pointTypes[numTypes - 1] == SEG_MOVETO) {
1107                        doubleCoords[numCoords - 2] = x;
1108                        doubleCoords[numCoords - 1] = y;
1109                    } else {
1110                        needRoom(false, 2);
1111                        pointTypes[numTypes++] = SEG_MOVETO;
1112                        doubleCoords[numCoords++] = x;
1113                        doubleCoords[numCoords++] = y;
1114                    }
1115                }
1116
1117                /**
1118                 * {@inheritDoc}
1119                 * @since 1.6
1120                 */
1121                public final synchronized void lineTo(double x, double y) {
1122                    needRoom(true, 2);
1123                    pointTypes[numTypes++] = SEG_LINETO;
1124                    doubleCoords[numCoords++] = x;
1125                    doubleCoords[numCoords++] = y;
1126                }
1127
1128                /**
1129                 * {@inheritDoc}
1130                 * @since 1.6
1131                 */
1132                public final synchronized void quadTo(double x1, double y1,
1133                        double x2, double y2) {
1134                    needRoom(true, 4);
1135                    pointTypes[numTypes++] = SEG_QUADTO;
1136                    doubleCoords[numCoords++] = x1;
1137                    doubleCoords[numCoords++] = y1;
1138                    doubleCoords[numCoords++] = x2;
1139                    doubleCoords[numCoords++] = y2;
1140                }
1141
1142                /**
1143                 * {@inheritDoc}
1144                 * @since 1.6
1145                 */
1146                public final synchronized void curveTo(double x1, double y1,
1147                        double x2, double y2, double x3, double y3) {
1148                    needRoom(true, 6);
1149                    pointTypes[numTypes++] = SEG_CUBICTO;
1150                    doubleCoords[numCoords++] = x1;
1151                    doubleCoords[numCoords++] = y1;
1152                    doubleCoords[numCoords++] = x2;
1153                    doubleCoords[numCoords++] = y2;
1154                    doubleCoords[numCoords++] = x3;
1155                    doubleCoords[numCoords++] = y3;
1156                }
1157
1158                int pointCrossings(double px, double py) {
1159                    double movx, movy, curx, cury, endx, endy;
1160                    double coords[] = doubleCoords;
1161                    curx = movx = coords[0];
1162                    cury = movy = coords[1];
1163                    int crossings = 0;
1164                    int ci = 2;
1165                    for (int i = 1; i < numTypes; i++) {
1166                        switch (pointTypes[i]) {
1167                        case PathIterator.SEG_MOVETO:
1168                            if (cury != movy) {
1169                                crossings += Curve.pointCrossingsForLine(px,
1170                                        py, curx, cury, movx, movy);
1171                            }
1172                            movx = curx = coords[ci++];
1173                            movy = cury = coords[ci++];
1174                            break;
1175                        case PathIterator.SEG_LINETO:
1176                            crossings += Curve.pointCrossingsForLine(px, py,
1177                                    curx, cury, endx = coords[ci++],
1178                                    endy = coords[ci++]);
1179                            curx = endx;
1180                            cury = endy;
1181                            break;
1182                        case PathIterator.SEG_QUADTO:
1183                            crossings += Curve
1184                                    .pointCrossingsForQuad(px, py, curx, cury,
1185                                            coords[ci++], coords[ci++],
1186                                            endx = coords[ci++],
1187                                            endy = coords[ci++], 0);
1188                            curx = endx;
1189                            cury = endy;
1190                            break;
1191                        case PathIterator.SEG_CUBICTO:
1192                            crossings += Curve
1193                                    .pointCrossingsForCubic(px, py, curx, cury,
1194                                            coords[ci++], coords[ci++],
1195                                            coords[ci++], coords[ci++],
1196                                            endx = coords[ci++],
1197                                            endy = coords[ci++], 0);
1198                            curx = endx;
1199                            cury = endy;
1200                            break;
1201                        case PathIterator.SEG_CLOSE:
1202                            if (cury != movy) {
1203                                crossings += Curve.pointCrossingsForLine(px,
1204                                        py, curx, cury, movx, movy);
1205                            }
1206                            curx = movx;
1207                            cury = movy;
1208                            break;
1209                        }
1210                    }
1211                    if (cury != movy) {
1212                        crossings += Curve.pointCrossingsForLine(px, py, curx,
1213                                cury, movx, movy);
1214                    }
1215                    return crossings;
1216                }
1217
1218                int rectCrossings(double rxmin, double rymin, double rxmax,
1219                        double rymax) {
1220                    double coords[] = doubleCoords;
1221                    double curx, cury, movx, movy, endx, endy;
1222                    curx = movx = coords[0];
1223                    cury = movy = coords[1];
1224                    int crossings = 0;
1225                    int ci = 2;
1226                    for (int i = 1; crossings != Curve.RECT_INTERSECTS
1227                            && i < numTypes; i++) {
1228                        switch (pointTypes[i]) {
1229                        case PathIterator.SEG_MOVETO:
1230                            if (curx != movx || cury != movy) {
1231                                crossings = Curve.rectCrossingsForLine(
1232                                        crossings, rxmin, rymin, rxmax, rymax,
1233                                        curx, cury, movx, movy);
1234                            }
1235                            // Count should always be a multiple of 2 here.
1236                            // assert((crossings & 1) != 0);
1237                            movx = curx = coords[ci++];
1238                            movy = cury = coords[ci++];
1239                            break;
1240                        case PathIterator.SEG_LINETO:
1241                            endx = coords[ci++];
1242                            endy = coords[ci++];
1243                            crossings = Curve.rectCrossingsForLine(crossings,
1244                                    rxmin, rymin, rxmax, rymax, curx, cury,
1245                                    endx, endy);
1246                            curx = endx;
1247                            cury = endy;
1248                            break;
1249                        case PathIterator.SEG_QUADTO:
1250                            crossings = Curve
1251                                    .rectCrossingsForQuad(crossings, rxmin,
1252                                            rymin, rxmax, rymax, curx, cury,
1253                                            coords[ci++], coords[ci++],
1254                                            endx = coords[ci++],
1255                                            endy = coords[ci++], 0);
1256                            curx = endx;
1257                            cury = endy;
1258                            break;
1259                        case PathIterator.SEG_CUBICTO:
1260                            crossings = Curve.rectCrossingsForCubic(crossings,
1261                                    rxmin, rymin, rxmax, rymax, curx, cury,
1262                                    coords[ci++], coords[ci++], coords[ci++],
1263                                    coords[ci++], endx = coords[ci++],
1264                                    endy = coords[ci++], 0);
1265                            curx = endx;
1266                            cury = endy;
1267                            break;
1268                        case PathIterator.SEG_CLOSE:
1269                            if (curx != movx || cury != movy) {
1270                                crossings = Curve.rectCrossingsForLine(
1271                                        crossings, rxmin, rymin, rxmax, rymax,
1272                                        curx, cury, movx, movy);
1273                            }
1274                            curx = movx;
1275                            cury = movy;
1276                            // Count should always be a multiple of 2 here.
1277                            // assert((crossings & 1) != 0);
1278                            break;
1279                        }
1280                    }
1281                    if (crossings != Curve.RECT_INTERSECTS
1282                            && (curx != movx || cury != movy)) {
1283                        crossings = Curve.rectCrossingsForLine(crossings,
1284                                rxmin, rymin, rxmax, rymax, curx, cury, movx,
1285                                movy);
1286                    }
1287                    // Count should always be a multiple of 2 here.
1288                    // assert((crossings & 1) != 0);
1289                    return crossings;
1290                }
1291
1292                /**
1293                 * {@inheritDoc}
1294                 * @since 1.6
1295                 */
1296                public final void append(PathIterator pi, boolean connect) {
1297                    double coords[] = new double[6];
1298                    while (!pi.isDone()) {
1299                        switch (pi.currentSegment(coords)) {
1300                        case SEG_MOVETO:
1301                            if (!connect || numTypes < 1 || numCoords < 1) {
1302                                moveTo(coords[0], coords[1]);
1303                                break;
1304                            }
1305                            if (pointTypes[numTypes - 1] != SEG_CLOSE
1306                                    && doubleCoords[numCoords - 2] == coords[0]
1307                                    && doubleCoords[numCoords - 1] == coords[1]) {
1308                                // Collapse out initial moveto/lineto
1309                                break;
1310                            }
1311                            // NO BREAK;
1312                        case SEG_LINETO:
1313                            lineTo(coords[0], coords[1]);
1314                            break;
1315                        case SEG_QUADTO:
1316                            quadTo(coords[0], coords[1], coords[2], coords[3]);
1317                            break;
1318                        case SEG_CUBICTO:
1319                            curveTo(coords[0], coords[1], coords[2], coords[3],
1320                                    coords[4], coords[5]);
1321                            break;
1322                        case SEG_CLOSE:
1323                            closePath();
1324                            break;
1325                        }
1326                        pi.next();
1327                        connect = false;
1328                    }
1329                }
1330
1331                /**
1332                 * {@inheritDoc}
1333                 * @since 1.6
1334                 */
1335                public final void transform(AffineTransform at) {
1336                    at.transform(doubleCoords, 0, doubleCoords, 0,
1337                            numCoords / 2);
1338                }
1339
1340                /**
1341                 * {@inheritDoc}
1342                 * @since 1.6
1343                 */
1344                public final synchronized Rectangle2D getBounds2D() {
1345                    double x1, y1, x2, y2;
1346                    int i = numCoords;
1347                    if (i > 0) {
1348                        y1 = y2 = doubleCoords[--i];
1349                        x1 = x2 = doubleCoords[--i];
1350                        while (i > 0) {
1351                            double y = doubleCoords[--i];
1352                            double x = doubleCoords[--i];
1353                            if (x < x1)
1354                                x1 = x;
1355                            if (y < y1)
1356                                y1 = y;
1357                            if (x > x2)
1358                                x2 = x;
1359                            if (y > y2)
1360                                y2 = y;
1361                        }
1362                    } else {
1363                        x1 = y1 = x2 = y2 = 0.0;
1364                    }
1365                    return new Rectangle2D.Double(x1, y1, x2 - x1, y2 - y1);
1366                }
1367
1368                /**
1369                 * {@inheritDoc}
1370                 * <p>
1371                 * The iterator for this class is not multi-threaded safe,
1372                 * which means that the {@code Path2D} class does not
1373                 * guarantee that modifications to the geometry of this
1374                 * {@code Path2D} object do not affect any iterations of
1375                 * that geometry that are already in process.
1376                 *
1377                 * @param at an {@code AffineTransform} 
1378                 * @return a new {@code PathIterator} that iterates along the boundary
1379                 *         of this {@code Shape} and provides access to the geometry
1380                 *         of this {@code Shape}'s outline
1381                 * @since 1.6
1382                 */
1383                public PathIterator getPathIterator(AffineTransform at) {
1384                    if (at == null) {
1385                        return new CopyIterator(this );
1386                    } else {
1387                        return new TxIterator(this , at);
1388                    }
1389                }
1390
1391                /**
1392                 * Creates a new object of the same class as this object.
1393                 *
1394                 * @return     a clone of this instance.
1395                 * @exception  OutOfMemoryError    if there is not enough memory.
1396                 * @see        java.lang.Cloneable
1397                 * @since      1.6
1398                 */
1399                public final Object clone() {
1400                    // Note: It would be nice to have this return Path2D
1401                    // but one of our subclasses (GeneralPath) needs to
1402                    // offer "public Object clone()" for backwards
1403                    // compatibility so we cannot restrict it further.
1404                    // REMIND: Can we do both somehow?
1405                    return new Path2D.Double(this );
1406                }
1407
1408                /*
1409                 * JDK 1.6 serialVersionUID
1410                 */
1411                private static final long serialVersionUID = 1826762518450014216L;
1412
1413                /**
1414                 * Writes the default serializable fields to the
1415                 * {@code ObjectOutputStream} followed by an explicit
1416                 * serialization of the path segments stored in this
1417                 * path.
1418                 *
1419                 * @serialData
1420                 * <a name="Path2DSerialData"><!-- --></a>
1421                 * <ol>
1422                 * <li>The default serializable fields.
1423                 * There are no default serializable fields as of 1.6.
1424                 * <li>followed by
1425                 * a byte indicating the storage type of the original object
1426                 * as a hint (SERIAL_STORAGE_DBL_ARRAY)
1427                 * <li>followed by
1428                 * an integer indicating the number of path segments to follow (NP)
1429                 * or -1 to indicate an unknown number of path segments follows
1430                 * <li>followed by
1431                 * an integer indicating the total number of coordinates to follow (NC)
1432                 * or -1 to indicate an unknown number of coordinates follows
1433                 * (NC should always be even since coordinates always appear in pairs
1434                 *  representing an x,y pair)
1435                 * <li>followed by
1436                 * a byte indicating the winding rule
1437                 * ({@link #WIND_EVEN_ODD WIND_EVEN_ODD} or
1438                 *  {@link #WIND_NON_ZERO WIND_NON_ZERO})
1439                 * <li>followed by
1440                 * NP (or unlimited if NP < 0) sets of values consisting of
1441                 * a single byte indicating a path segment type
1442                 * followed by one or more pairs of float or double
1443                 * values representing the coordinates of the path segment
1444                 * <li>followed by
1445                 * a byte indicating the end of the path (SERIAL_PATH_END).
1446                 * </ol>
1447                 * <p>
1448                 * The following byte value constants are used in the serialized form
1449                 * of {@code Path2D} objects:
1450                 * <table>
1451                 * <tr>
1452                 * <th>Constant Name</th>
1453                 * <th>Byte Value</th>
1454                 * <th>Followed by</th>
1455                 * <th>Description</th>
1456                 * </tr>
1457                 * <tr>
1458                 * <td>{@code SERIAL_STORAGE_FLT_ARRAY}</td>
1459                 * <td>0x30</td>
1460                 * <td></td>
1461                 * <td>A hint that the original {@code Path2D} object stored
1462                 * the coordinates in a Java array of floats.</td>
1463                 * </tr>
1464                 * <tr>
1465                 * <td>{@code SERIAL_STORAGE_DBL_ARRAY}</td>
1466                 * <td>0x31</td>
1467                 * <td></td>
1468                 * <td>A hint that the original {@code Path2D} object stored
1469                 * the coordinates in a Java array of doubles.</td>
1470                 * </tr>
1471                 * <tr>
1472                 * <td>{@code SERIAL_SEG_FLT_MOVETO}</td>
1473                 * <td>0x40</td>
1474                 * <td>2 floats</td>
1475                 * <td>A {@link #moveTo moveTo} path segment follows.</td>
1476                 * </tr>
1477                 * <tr>
1478                 * <td>{@code SERIAL_SEG_FLT_LINETO}</td>
1479                 * <td>0x41</td>
1480                 * <td>2 floats</td>
1481                 * <td>A {@link #lineTo lineTo} path segment follows.</td>
1482                 * </tr>
1483                 * <tr>
1484                 * <td>{@code SERIAL_SEG_FLT_QUADTO}</td>
1485                 * <td>0x42</td>
1486                 * <td>4 floats</td>
1487                 * <td>A {@link #quadTo quadTo} path segment follows.</td>
1488                 * </tr>
1489                 * <tr>
1490                 * <td>{@code SERIAL_SEG_FLT_CUBICTO}</td>
1491                 * <td>0x43</td>
1492                 * <td>6 floats</td>
1493                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
1494                 * </tr>
1495                 * <tr>
1496                 * <td>{@code SERIAL_SEG_DBL_MOVETO}</td>
1497                 * <td>0x50</td>
1498                 * <td>2 doubles</td>
1499                 * <td>A {@link #moveTo moveTo} path segment follows.</td>
1500                 * </tr>
1501                 * <tr>
1502                 * <td>{@code SERIAL_SEG_DBL_LINETO}</td>
1503                 * <td>0x51</td>
1504                 * <td>2 doubles</td>
1505                 * <td>A {@link #lineTo lineTo} path segment follows.</td>
1506                 * </tr>
1507                 * <tr>
1508                 * <td>{@code SERIAL_SEG_DBL_QUADTO}</td>
1509                 * <td>0x52</td>
1510                 * <td>4 doubles</td>
1511                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
1512                 * </tr>
1513                 * <tr>
1514                 * <td>{@code SERIAL_SEG_DBL_CUBICTO}</td>
1515                 * <td>0x53</td>
1516                 * <td>6 doubles</td>
1517                 * <td>A {@link #curveTo curveTo} path segment follows.</td>
1518                 * </tr>
1519                 * <tr>
1520                 * <td>{@code SERIAL_SEG_CLOSE}</td>
1521                 * <td>0x60</td>
1522                 * <td></td>
1523                 * <td>A {@link #closePath closePath} path segment.</td>
1524                 * </tr>
1525                 * <tr>
1526                 * <td>{@code SERIAL_PATH_END}</td>
1527                 * <td>0x61</td>
1528                 * <td></td>
1529                 * <td>There are no more path segments following.</td>
1530                 * </table>
1531                 *
1532                 * @since 1.6
1533                 */
1534                private void writeObject(java.io.ObjectOutputStream s)
1535                        throws java.io.IOException {
1536                    super .writeObject(s, true);
1537                }
1538
1539                /**
1540                 * Reads the default serializable fields from the
1541                 * {@code ObjectInputStream} followed by an explicit
1542                 * serialization of the path segments stored in this
1543                 * path.
1544                 * <p>
1545                 * There are no default serializable fields as of 1.6.
1546                 * <p>
1547                 * The serial data for this object is described in the
1548                 * writeObject method.
1549                 *
1550                 * @since 1.6
1551                 */
1552                private void readObject(java.io.ObjectInputStream s)
1553                        throws java.lang.ClassNotFoundException,
1554                        java.io.IOException {
1555                    super .readObject(s, true);
1556                }
1557
1558                static class CopyIterator extends Path2D.Iterator {
1559                    double doubleCoords[];
1560
1561                    CopyIterator(Path2D.Double p2dd) {
1562                        super (p2dd);
1563                        this .doubleCoords = p2dd.doubleCoords;
1564                    }
1565
1566                    public int currentSegment(float[] coords) {
1567                        int type = path.pointTypes[typeIdx];
1568                        int numCoords = curvecoords[type];
1569                        if (numCoords > 0) {
1570                            for (int i = 0; i < numCoords; i++) {
1571                                coords[i] = (float) doubleCoords[pointIdx + i];
1572                            }
1573                        }
1574                        return type;
1575                    }
1576
1577                    public int currentSegment(double[] coords) {
1578                        int type = path.pointTypes[typeIdx];
1579                        int numCoords = curvecoords[type];
1580                        if (numCoords > 0) {
1581                            System.arraycopy(doubleCoords, pointIdx, coords, 0,
1582                                    numCoords);
1583                        }
1584                        return type;
1585                    }
1586                }
1587
1588                static class TxIterator extends Path2D.Iterator {
1589                    double doubleCoords[];
1590                    AffineTransform affine;
1591
1592                    TxIterator(Path2D.Double p2dd, AffineTransform at) {
1593                        super (p2dd);
1594                        this .doubleCoords = p2dd.doubleCoords;
1595                        this .affine = at;
1596                    }
1597
1598                    public int currentSegment(float[] coords) {
1599                        int type = path.pointTypes[typeIdx];
1600                        int numCoords = curvecoords[type];
1601                        if (numCoords > 0) {
1602                            affine.transform(doubleCoords, pointIdx, coords, 0,
1603                                    numCoords / 2);
1604                        }
1605                        return type;
1606                    }
1607
1608                    public int currentSegment(double[] coords) {
1609                        int type = path.pointTypes[typeIdx];
1610                        int numCoords = curvecoords[type];
1611                        if (numCoords > 0) {
1612                            affine.transform(doubleCoords, pointIdx, coords, 0,
1613                                    numCoords / 2);
1614                        }
1615                        return type;
1616                    }
1617                }
1618            }
1619
1620            /**
1621             * Adds a point to the path by moving to the specified
1622             * coordinates specified in double precision.
1623             *
1624             * @param x the specified X coordinate
1625             * @param y the specified Y coordinate
1626             * @since 1.6
1627             */
1628            public abstract void moveTo(double x, double y);
1629
1630            /**
1631             * Adds a point to the path by drawing a straight line from the
1632             * current coordinates to the new specified coordinates
1633             * specified in double precision.
1634             *
1635             * @param x the specified X coordinate
1636             * @param y the specified Y coordinate
1637             * @since 1.6
1638             */
1639            public abstract void lineTo(double x, double y);
1640
1641            /**
1642             * Adds a curved segment, defined by two new points, to the path by
1643             * drawing a Quadratic curve that intersects both the current
1644             * coordinates and the specified coordinates {@code (x2,y2)},
1645             * using the specified point {@code (x1,y1)} as a quadratic
1646             * parametric control point.
1647             * All coordinates are specified in double precision.
1648             *
1649             * @param x1 the X coordinate of the quadratic control point
1650             * @param y1 the Y coordinate of the quadratic control point
1651             * @param x2 the X coordinate of the final end point
1652             * @param y2 the Y coordinate of the final end point
1653             * @since 1.6
1654             */
1655            public abstract void quadTo(double x1, double y1, double x2,
1656                    double y2);
1657
1658            /**
1659             * Adds a curved segment, defined by three new points, to the path by
1660             * drawing a B&eacute;zier curve that intersects both the current
1661             * coordinates and the specified coordinates {@code (x3,y3)},
1662             * using the specified points {@code (x1,y1)} and {@code (x2,y2)} as
1663             * B&eacute;zier control points.
1664             * All coordinates are specified in double precision.
1665             *
1666             * @param x1 the X coordinate of the first B&eacute;zier control point
1667             * @param y1 the Y coordinate of the first B&eacute;zier control point
1668             * @param x2 the X coordinate of the second B&eacute;zier control point
1669             * @param y2 the Y coordinate of the second B&eacute;zier control point
1670             * @param x3 the X coordinate of the final end point
1671             * @param y3 the Y coordinate of the final end point
1672             * @since 1.6
1673             */
1674            public abstract void curveTo(double x1, double y1, double x2,
1675                    double y2, double x3, double y3);
1676
1677            /**
1678             * Closes the current subpath by drawing a straight line back to
1679             * the coordinates of the last {@code moveTo}.  If the path is already
1680             * closed then this method has no effect.
1681             *
1682             * @since 1.6
1683             */
1684            public final synchronized void closePath() {
1685                if (numTypes == 0 || pointTypes[numTypes - 1] != SEG_CLOSE) {
1686                    needRoom(true, 0);
1687                    pointTypes[numTypes++] = SEG_CLOSE;
1688                }
1689            }
1690
1691            /**
1692             * Appends the geometry of the specified {@code Shape} object to the
1693             * path, possibly connecting the new geometry to the existing path
1694             * segments with a line segment.
1695             * If the {@code connect} parameter is {@code true} and the 
1696             * path is not empty then any initial {@code moveTo} in the
1697             * geometry of the appended {@code Shape}
1698             * is turned into a {@code lineTo} segment.
1699             * If the destination coordinates of such a connecting {@code lineTo}
1700             * segment match the ending coordinates of a currently open
1701             * subpath then the segment is omitted as superfluous.
1702             * The winding rule of the specified {@code Shape} is ignored
1703             * and the appended geometry is governed by the winding
1704             * rule specified for this path.
1705             *
1706             * @param s the {@code Shape} whose geometry is appended 
1707             *          to this path
1708             * @param connect a boolean to control whether or not to turn an initial
1709             *                {@code moveTo} segment into a {@code lineTo} segment
1710             *                to connect the new geometry to the existing path
1711             * @since 1.6
1712             */
1713            public final void append(Shape s, boolean connect) {
1714                append(s.getPathIterator(null), connect);
1715            }
1716
1717            /**
1718             * Appends the geometry of the specified
1719             * {@link PathIterator} object 
1720             * to the path, possibly connecting the new geometry to the existing
1721             * path segments with a line segment.
1722             * If the {@code connect} parameter is {@code true} and the 
1723             * path is not empty then any initial {@code moveTo} in the
1724             * geometry of the appended {@code Shape} is turned into a
1725             * {@code lineTo} segment.
1726             * If the destination coordinates of such a connecting {@code lineTo}
1727             * segment match the ending coordinates of a currently open
1728             * subpath then the segment is omitted as superfluous.
1729             * The winding rule of the specified {@code Shape} is ignored
1730             * and the appended geometry is governed by the winding
1731             * rule specified for this path.
1732             *
1733             * @param pi the {@code PathIterator} whose geometry is appended to 
1734             *           this path
1735             * @param connect a boolean to control whether or not to turn an initial
1736             *                {@code moveTo} segment into a {@code lineTo} segment
1737             *                to connect the new geometry to the existing path
1738             * @since 1.6
1739             */
1740            public abstract void append(PathIterator pi, boolean connect);
1741
1742            /**
1743             * Returns the fill style winding rule.
1744             *
1745             * @return an integer representing the current winding rule.
1746             * @see #WIND_EVEN_ODD  
1747             * @see #WIND_NON_ZERO
1748             * @see #setWindingRule
1749             * @since 1.6
1750             */
1751            public final synchronized int getWindingRule() {
1752                return windingRule;
1753            }
1754
1755            /**
1756             * Sets the winding rule for this path to the specified value.
1757             *
1758             * @param rule an integer representing the specified 
1759             *             winding rule
1760             * @exception IllegalArgumentException if 
1761             *		{@code rule} is not either 
1762             *		{@link #WIND_EVEN_ODD} or
1763             *		{@link #WIND_NON_ZERO}
1764             * @see #getWindingRule
1765             * @since 1.6
1766             */
1767            public final void setWindingRule(int rule) {
1768                if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) {
1769                    throw new IllegalArgumentException("winding rule must be "
1770                            + "WIND_EVEN_ODD or " + "WIND_NON_ZERO");
1771                }
1772                windingRule = rule;
1773            }
1774
1775            /**
1776             * Returns the coordinates most recently added to the end of the path
1777             * as a {@link Point2D} object.
1778             *
1779             * @return a {@code Point2D} object containing the ending coordinates of
1780             *         the path or {@code null} if there are no points in the path.
1781             * @since 1.6
1782             */
1783            public final synchronized Point2D getCurrentPoint() {
1784                int index = numCoords;
1785                if (numTypes < 1 || index < 1) {
1786                    return null;
1787                }
1788                if (pointTypes[numTypes - 1] == SEG_CLOSE) {
1789                    loop: for (int i = numTypes - 2; i > 0; i--) {
1790                        switch (pointTypes[i]) {
1791                        case SEG_MOVETO:
1792                            break loop;
1793                        case SEG_LINETO:
1794                            index -= 2;
1795                            break;
1796                        case SEG_QUADTO:
1797                            index -= 4;
1798                            break;
1799                        case SEG_CUBICTO:
1800                            index -= 6;
1801                            break;
1802                        case SEG_CLOSE:
1803                            break;
1804                        }
1805                    }
1806                }
1807                return getPoint(index - 2);
1808            }
1809
1810            /**
1811             * Resets the path to empty.  The append position is set back to the
1812             * beginning of the path and all coordinates and point types are
1813             * forgotten.
1814             *
1815             * @since 1.6
1816             */
1817            public final synchronized void reset() {
1818                numTypes = numCoords = 0;
1819            }
1820
1821            /**
1822             * Transforms the geometry of this path using the specified 
1823             * {@link AffineTransform}.
1824             * The geometry is transformed in place, which permanently changes the
1825             * boundary defined by this object.
1826             *
1827             * @param at the {@code AffineTransform} used to transform the area
1828             * @since 1.6
1829             */
1830            public abstract void transform(AffineTransform at);
1831
1832            /**
1833             * Returns a new {@code Shape} representing a transformed version
1834             * of this {@code Path2D}.
1835             * Note that the exact type and coordinate precision of the return
1836             * value is not specified for this method.
1837             * The method will return a Shape that contains no less precision
1838             * for the transformed geometry than this {@code Path2D} currently
1839             * maintains, but it may contain no more precision either.
1840             * If the tradeoff of precision vs. storage size in the result is
1841             * important then the convenience constructors in the
1842             * {@link Path2D.Float#Path2D.Float(Shape, AffineTransform) Path2D.Float}
1843             * and
1844             * {@link Path2D.Double#Path2D.Double(Shape, AffineTransform) Path2D.Double}
1845             * subclasses should be used to make the choice explicit.
1846             *
1847             * @param at the {@code AffineTransform} used to transform a 
1848             *           new {@code Shape}.
1849             * @return a new {@code Shape}, transformed with the specified 
1850             *         {@code AffineTransform}.
1851             * @since 1.6
1852             */
1853            public final synchronized Shape createTransformedShape(
1854                    AffineTransform at) {
1855                Path2D p2d = (Path2D) clone();
1856                if (at != null) {
1857                    p2d.transform(at);
1858                }
1859                return p2d;
1860            }
1861
1862            /**
1863             * {@inheritDoc}
1864             * @since 1.6
1865             */
1866            public final Rectangle getBounds() {
1867                return getBounds2D().getBounds();
1868            }
1869
1870            /**
1871             * Tests if the specified coordinates are inside the closed
1872             * boundary of the specified {@link PathIterator}.
1873             * <p>
1874             * This method provides a basic facility for implementors of
1875             * the {@link Shape} interface to implement support for the
1876             * {@link Shape#contains(double, double)} method.
1877             *
1878             * @param pi the specified {@code PathIterator}
1879             * @param x the specified X coordinate
1880             * @param y the specified Y coordinate
1881             * @return {@code true} if the specified coordinates are inside the
1882             *         specified {@code PathIterator}; {@code false} otherwise
1883             * @since 1.6
1884             */
1885            public static boolean contains(PathIterator pi, double x, double y) {
1886                if (x * 0.0 + y * 0.0 == 0.0) {
1887                    /* N * 0.0 is 0.0 only if N is finite.
1888                     * Here we know that both x and y are finite.
1889                     */
1890                    int mask = (pi.getWindingRule() == WIND_NON_ZERO ? -1 : 1);
1891                    int cross = Curve.pointCrossingsForPath(pi, x, y);
1892                    return ((cross & mask) != 0);
1893                } else {
1894                    /* Either x or y was infinite or NaN.
1895                     * A NaN always produces a negative response to any test
1896                     * and Infinity values cannot be "inside" any path so
1897                     * they should return false as well.
1898                     */
1899                    return false;
1900                }
1901            }
1902
1903            /**
1904             * Tests if the specified {@link Point2D} is inside the closed
1905             * boundary of the specified {@link PathIterator}.
1906             * <p>
1907             * This method provides a basic facility for implementors of
1908             * the {@link Shape} interface to implement support for the
1909             * {@link Shape#contains(Point2D)} method.
1910             *
1911             * @param pi the specified {@code PathIterator}
1912             * @param p the specified {@code Point2D}
1913             * @return {@code true} if the specified coordinates are inside the
1914             *         specified {@code PathIterator}; {@code false} otherwise
1915             * @since 1.6
1916             */
1917            public static boolean contains(PathIterator pi, Point2D p) {
1918                return contains(pi, p.getX(), p.getY());
1919            }
1920
1921            /**
1922             * {@inheritDoc}
1923             * @since 1.6
1924             */
1925            public final boolean contains(double x, double y) {
1926                if (x * 0.0 + y * 0.0 == 0.0) {
1927                    /* N * 0.0 is 0.0 only if N is finite.
1928                     * Here we know that both x and y are finite.
1929                     */
1930                    if (numTypes < 2) {
1931                        return false;
1932                    }
1933                    int mask = (windingRule == WIND_NON_ZERO ? -1 : 1);
1934                    return ((pointCrossings(x, y) & mask) != 0);
1935                } else {
1936                    /* Either x or y was infinite or NaN.
1937                     * A NaN always produces a negative response to any test
1938                     * and Infinity values cannot be "inside" any path so
1939                     * they should return false as well.
1940                     */
1941                    return false;
1942                }
1943            }
1944
1945            /**
1946             * {@inheritDoc}
1947             * @since 1.6
1948             */
1949            public final boolean contains(Point2D p) {
1950                return contains(p.getX(), p.getY());
1951            }
1952
1953            /**
1954             * Tests if the specified rectangular area is entirely inside the
1955             * closed boundary of the specified {@link PathIterator}.
1956             * <p>
1957             * This method provides a basic facility for implementors of
1958             * the {@link Shape} interface to implement support for the
1959             * {@link Shape#contains(double, double, double, double)} method.
1960             * <p>
1961             * This method object may conservatively return false in
1962             * cases where the specified rectangular area intersects a
1963             * segment of the path, but that segment does not represent a
1964             * boundary between the interior and exterior of the path.
1965             * Such segments could lie entirely within the interior of the
1966             * path if they are part of a path with a {@link #WIND_NON_ZERO}
1967             * winding rule or if the segments are retraced in the reverse
1968             * direction such that the two sets of segments cancel each
1969             * other out without any exterior area falling between them.
1970             * To determine whether segments represent true boundaries of
1971             * the interior of the path would require extensive calculations
1972             * involving all of the segments of the path and the winding
1973             * rule and are thus beyond the scope of this implementation.
1974             *
1975             * @param pi the specified {@code PathIterator}
1976             * @param x the specified X coordinate
1977             * @param y the specified Y coordinate
1978             * @param w the width of the specified rectangular area
1979             * @param h the height of the specified rectangular area
1980             * @return {@code true} if the specified {@code PathIterator} contains
1981             *         the specified rectangluar area; {@code false} otherwise.
1982             * @since 1.6
1983             */
1984            public static boolean contains(PathIterator pi, double x, double y,
1985                    double w, double h) {
1986                if (java.lang.Double.isNaN(x + w)
1987                        || java.lang.Double.isNaN(y + h)) {
1988                    /* [xy]+[wh] is NaN if any of those values are NaN,
1989                     * or if adding the two together would produce NaN
1990                     * by virtue of adding opposing Infinte values.
1991                     * Since we need to add them below, their sum must
1992                     * not be NaN.
1993                     * We return false because NaN always produces a
1994                     * negative response to tests
1995                     */
1996                    return false;
1997                }
1998                if (w <= 0 || h <= 0) {
1999                    return false;
2000                }
2001                int mask = (pi.getWindingRule() == WIND_NON_ZERO ? -1 : 2);
2002                int crossings = Curve.rectCrossingsForPath(pi, x, y, x + w, y
2003                        + h);
2004                return (crossings != Curve.RECT_INTERSECTS && (crossings & mask) != 0);
2005            }
2006
2007            /**
2008             * Tests if the specified {@link Rectangle2D} is entirely inside the
2009             * closed boundary of the specified {@link PathIterator}.
2010             * <p>
2011             * This method provides a basic facility for implementors of
2012             * the {@link Shape} interface to implement support for the
2013             * {@link Shape#contains(Rectangle2D)} method.
2014             * <p>
2015             * This method object may conservatively return false in
2016             * cases where the specified rectangular area intersects a
2017             * segment of the path, but that segment does not represent a
2018             * boundary between the interior and exterior of the path.
2019             * Such segments could lie entirely within the interior of the
2020             * path if they are part of a path with a {@link #WIND_NON_ZERO}
2021             * winding rule or if the segments are retraced in the reverse
2022             * direction such that the two sets of segments cancel each
2023             * other out without any exterior area falling between them.
2024             * To determine whether segments represent true boundaries of
2025             * the interior of the path would require extensive calculations
2026             * involving all of the segments of the path and the winding
2027             * rule and are thus beyond the scope of this implementation.
2028             *
2029             * @param pi the specified {@code PathIterator}
2030             * @param r a specified {@code Rectangle2D}
2031             * @return {@code true} if the specified {@code PathIterator} contains
2032             *         the specified {@code Rectangle2D}; {@code false} otherwise.
2033             * @since 1.6
2034             */
2035            public static boolean contains(PathIterator pi, Rectangle2D r) {
2036                return contains(pi, r.getX(), r.getY(), r.getWidth(), r
2037                        .getHeight());
2038            }
2039
2040            /**
2041             * {@inheritDoc}
2042             * <p>
2043             * This method object may conservatively return false in
2044             * cases where the specified rectangular area intersects a
2045             * segment of the path, but that segment does not represent a
2046             * boundary between the interior and exterior of the path.
2047             * Such segments could lie entirely within the interior of the
2048             * path if they are part of a path with a {@link #WIND_NON_ZERO}
2049             * winding rule or if the segments are retraced in the reverse
2050             * direction such that the two sets of segments cancel each
2051             * other out without any exterior area falling between them.
2052             * To determine whether segments represent true boundaries of
2053             * the interior of the path would require extensive calculations
2054             * involving all of the segments of the path and the winding
2055             * rule and are thus beyond the scope of this implementation.
2056             *
2057             * @since 1.6
2058             */
2059            public final boolean contains(double x, double y, double w, double h) {
2060                if (java.lang.Double.isNaN(x + w)
2061                        || java.lang.Double.isNaN(y + h)) {
2062                    /* [xy]+[wh] is NaN if any of those values are NaN,
2063                     * or if adding the two together would produce NaN
2064                     * by virtue of adding opposing Infinte values.
2065                     * Since we need to add them below, their sum must
2066                     * not be NaN.
2067                     * We return false because NaN always produces a
2068                     * negative response to tests
2069                     */
2070                    return false;
2071                }
2072                if (w <= 0 || h <= 0) {
2073                    return false;
2074                }
2075                int mask = (windingRule == WIND_NON_ZERO ? -1 : 2);
2076                int crossings = rectCrossings(x, y, x + w, y + h);
2077                return (crossings != Curve.RECT_INTERSECTS && (crossings & mask) != 0);
2078            }
2079
2080            /**
2081             * {@inheritDoc}
2082             * <p>
2083             * This method object may conservatively return false in
2084             * cases where the specified rectangular area intersects a
2085             * segment of the path, but that segment does not represent a
2086             * boundary between the interior and exterior of the path.
2087             * Such segments could lie entirely within the interior of the
2088             * path if they are part of a path with a {@link #WIND_NON_ZERO}
2089             * winding rule or if the segments are retraced in the reverse
2090             * direction such that the two sets of segments cancel each
2091             * other out without any exterior area falling between them.
2092             * To determine whether segments represent true boundaries of
2093             * the interior of the path would require extensive calculations
2094             * involving all of the segments of the path and the winding
2095             * rule and are thus beyond the scope of this implementation.
2096             *
2097             * @since 1.6
2098             */
2099            public final boolean contains(Rectangle2D r) {
2100                return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
2101            }
2102
2103            /**
2104             * Tests if the interior of the specified {@link PathIterator}
2105             * intersects the interior of a specified set of rectangular
2106             * coordinates.
2107             * <p>
2108             * This method provides a basic facility for implementors of
2109             * the {@link Shape} interface to implement support for the
2110             * {@link Shape#intersects(double, double, double, double)} method.
2111             * <p>
2112             * This method object may conservatively return true in
2113             * cases where the specified rectangular area intersects a
2114             * segment of the path, but that segment does not represent a
2115             * boundary between the interior and exterior of the path.
2116             * Such a case may occur if some set of segments of the
2117             * path are retraced in the reverse direction such that the
2118             * two sets of segments cancel each other out without any
2119             * interior area between them.
2120             * To determine whether segments represent true boundaries of
2121             * the interior of the path would require extensive calculations
2122             * involving all of the segments of the path and the winding
2123             * rule and are thus beyond the scope of this implementation.
2124             *
2125             * @param pi the specified {@code PathIterator}
2126             * @param x the specified X coordinate
2127             * @param y the specified Y coordinate
2128             * @param w the width of the specified rectangular coordinates
2129             * @param h the height of the specified rectangular coordinates
2130             * @return {@code true} if the specified {@code PathIterator} and
2131             *         the interior of the specified set of rectangular
2132             *         coordinates intersect each other; {@code false} otherwise.
2133             * @since 1.6
2134             */
2135            public static boolean intersects(PathIterator pi, double x,
2136                    double y, double w, double h) {
2137                if (java.lang.Double.isNaN(x + w)
2138                        || java.lang.Double.isNaN(y + h)) {
2139                    /* [xy]+[wh] is NaN if any of those values are NaN,
2140                     * or if adding the two together would produce NaN
2141                     * by virtue of adding opposing Infinte values.
2142                     * Since we need to add them below, their sum must
2143                     * not be NaN.
2144                     * We return false because NaN always produces a
2145                     * negative response to tests
2146                     */
2147                    return false;
2148                }
2149                if (w <= 0 || h <= 0) {
2150                    return false;
2151                }
2152                int mask = (pi.getWindingRule() == WIND_NON_ZERO ? -1 : 2);
2153                int crossings = Curve.rectCrossingsForPath(pi, x, y, x + w, y
2154                        + h);
2155                return (crossings == Curve.RECT_INTERSECTS || (crossings & mask) != 0);
2156            }
2157
2158            /**
2159             * Tests if the interior of the specified {@link PathIterator}
2160             * intersects the interior of a specified {@link Rectangle2D}.
2161             * <p>
2162             * This method provides a basic facility for implementors of
2163             * the {@link Shape} interface to implement support for the
2164             * {@link Shape#intersects(Rectangle2D)} method.
2165             * <p>
2166             * This method object may conservatively return true in
2167             * cases where the specified rectangular area intersects a
2168             * segment of the path, but that segment does not represent a
2169             * boundary between the interior and exterior of the path.
2170             * Such a case may occur if some set of segments of the
2171             * path are retraced in the reverse direction such that the
2172             * two sets of segments cancel each other out without any
2173             * interior area between them.
2174             * To determine whether segments represent true boundaries of
2175             * the interior of the path would require extensive calculations
2176             * involving all of the segments of the path and the winding
2177             * rule and are thus beyond the scope of this implementation.
2178             *
2179             * @param pi the specified {@code PathIterator}
2180             * @param r the specified {@code Rectangle2D}
2181             * @return {@code true} if the specified {@code PathIterator} and
2182             *         the interior of the specified {@code Rectangle2D}
2183             *         intersect each other; {@code false} otherwise.
2184             * @since 1.6
2185             */
2186            public static boolean intersects(PathIterator pi, Rectangle2D r) {
2187                return intersects(pi, r.getX(), r.getY(), r.getWidth(), r
2188                        .getHeight());
2189            }
2190
2191            /**
2192             * {@inheritDoc}
2193             * <p>
2194             * This method object may conservatively return true in
2195             * cases where the specified rectangular area intersects a
2196             * segment of the path, but that segment does not represent a
2197             * boundary between the interior and exterior of the path.
2198             * Such a case may occur if some set of segments of the
2199             * path are retraced in the reverse direction such that the
2200             * two sets of segments cancel each other out without any
2201             * interior area between them.
2202             * To determine whether segments represent true boundaries of
2203             * the interior of the path would require extensive calculations
2204             * involving all of the segments of the path and the winding
2205             * rule and are thus beyond the scope of this implementation.
2206             *
2207             * @since 1.6
2208             */
2209            public final boolean intersects(double x, double y, double w,
2210                    double h) {
2211                if (java.lang.Double.isNaN(x + w)
2212                        || java.lang.Double.isNaN(y + h)) {
2213                    /* [xy]+[wh] is NaN if any of those values are NaN,
2214                     * or if adding the two together would produce NaN
2215                     * by virtue of adding opposing Infinte values.
2216                     * Since we need to add them below, their sum must
2217                     * not be NaN.
2218                     * We return false because NaN always produces a
2219                     * negative response to tests
2220                     */
2221                    return false;
2222                }
2223                if (w <= 0 || h <= 0) {
2224                    return false;
2225                }
2226                int mask = (windingRule == WIND_NON_ZERO ? -1 : 2);
2227                int crossings = rectCrossings(x, y, x + w, y + h);
2228                return (crossings == Curve.RECT_INTERSECTS || (crossings & mask) != 0);
2229            }
2230
2231            /**
2232             * {@inheritDoc}
2233             * <p>
2234             * This method object may conservatively return true in
2235             * cases where the specified rectangular area intersects a
2236             * segment of the path, but that segment does not represent a
2237             * boundary between the interior and exterior of the path.
2238             * Such a case may occur if some set of segments of the
2239             * path are retraced in the reverse direction such that the
2240             * two sets of segments cancel each other out without any
2241             * interior area between them.
2242             * To determine whether segments represent true boundaries of
2243             * the interior of the path would require extensive calculations
2244             * involving all of the segments of the path and the winding
2245             * rule and are thus beyond the scope of this implementation.
2246             *
2247             * @since 1.6
2248             */
2249            public final boolean intersects(Rectangle2D r) {
2250                return intersects(r.getX(), r.getY(), r.getWidth(), r
2251                        .getHeight());
2252            }
2253
2254            /**
2255             * {@inheritDoc}
2256             * <p>
2257             * The iterator for this class is not multi-threaded safe,
2258             * which means that this {@code Path2D} class does not
2259             * guarantee that modifications to the geometry of this
2260             * {@code Path2D} object do not affect any iterations of
2261             * that geometry that are already in process. 
2262             *
2263             * @since 1.6
2264             */
2265            public PathIterator getPathIterator(AffineTransform at,
2266                    double flatness) {
2267                return new FlatteningPathIterator(getPathIterator(at), flatness);
2268            }
2269
2270            /**
2271             * Creates a new object of the same class as this object.
2272             *
2273             * @return     a clone of this instance.
2274             * @exception  OutOfMemoryError            if there is not enough memory.
2275             * @see        java.lang.Cloneable
2276             * @since      1.6
2277             */
2278            public abstract Object clone();
2279
2280            // Note: It would be nice to have this return Path2D
2281            // but one of our subclasses (GeneralPath) needs to
2282            // offer "public Object clone()" for backwards
2283            // compatibility so we cannot restrict it further.
2284            // REMIND: Can we do both somehow?
2285
2286            /*
2287             * Support fields and methods for serializing the subclasses.
2288             */
2289            private static final byte SERIAL_STORAGE_FLT_ARRAY = 0x30;
2290            private static final byte SERIAL_STORAGE_DBL_ARRAY = 0x31;
2291
2292            private static final byte SERIAL_SEG_FLT_MOVETO = 0x40;
2293            private static final byte SERIAL_SEG_FLT_LINETO = 0x41;
2294            private static final byte SERIAL_SEG_FLT_QUADTO = 0x42;
2295            private static final byte SERIAL_SEG_FLT_CUBICTO = 0x43;
2296
2297            private static final byte SERIAL_SEG_DBL_MOVETO = 0x50;
2298            private static final byte SERIAL_SEG_DBL_LINETO = 0x51;
2299            private static final byte SERIAL_SEG_DBL_QUADTO = 0x52;
2300            private static final byte SERIAL_SEG_DBL_CUBICTO = 0x53;
2301
2302            private static final byte SERIAL_SEG_CLOSE = 0x60;
2303            private static final byte SERIAL_PATH_END = 0x61;
2304
2305            final void writeObject(java.io.ObjectOutputStream s, boolean isdbl)
2306                    throws java.io.IOException {
2307                s.defaultWriteObject();
2308
2309                float fCoords[];
2310                double dCoords[];
2311
2312                if (isdbl) {
2313                    dCoords = ((Path2D.Double) this ).doubleCoords;
2314                    fCoords = null;
2315                } else {
2316                    fCoords = ((Path2D.Float) this ).floatCoords;
2317                    dCoords = null;
2318                }
2319
2320                int numTypes = this .numTypes;
2321
2322                s.writeByte(isdbl ? SERIAL_STORAGE_DBL_ARRAY
2323                        : SERIAL_STORAGE_FLT_ARRAY);
2324                s.writeInt(numTypes);
2325                s.writeInt(numCoords);
2326                s.writeByte((byte) windingRule);
2327
2328                int cindex = 0;
2329                for (int i = 0; i < numTypes; i++) {
2330                    int npoints;
2331                    byte serialtype;
2332                    switch (pointTypes[i]) {
2333                    case SEG_MOVETO:
2334                        npoints = 1;
2335                        serialtype = (isdbl ? SERIAL_SEG_DBL_MOVETO
2336                                : SERIAL_SEG_FLT_MOVETO);
2337                        break;
2338                    case SEG_LINETO:
2339                        npoints = 1;
2340                        serialtype = (isdbl ? SERIAL_SEG_DBL_LINETO
2341                                : SERIAL_SEG_FLT_LINETO);
2342                        break;
2343                    case SEG_QUADTO:
2344                        npoints = 2;
2345                        serialtype = (isdbl ? SERIAL_SEG_DBL_QUADTO
2346                                : SERIAL_SEG_FLT_QUADTO);
2347                        break;
2348                    case SEG_CUBICTO:
2349                        npoints = 3;
2350                        serialtype = (isdbl ? SERIAL_SEG_DBL_CUBICTO
2351                                : SERIAL_SEG_FLT_CUBICTO);
2352                        break;
2353                    case SEG_CLOSE:
2354                        npoints = 0;
2355                        serialtype = SERIAL_SEG_CLOSE;
2356                        break;
2357
2358                    default:
2359                        // Should never happen
2360                        throw new InternalError("unrecognized path type");
2361                    }
2362                    s.writeByte(serialtype);
2363                    while (--npoints >= 0) {
2364                        if (isdbl) {
2365                            s.writeDouble(dCoords[cindex++]);
2366                            s.writeDouble(dCoords[cindex++]);
2367                        } else {
2368                            s.writeFloat(fCoords[cindex++]);
2369                            s.writeFloat(fCoords[cindex++]);
2370                        }
2371                    }
2372                }
2373                s.writeByte((byte) SERIAL_PATH_END);
2374            }
2375
2376            final void readObject(java.io.ObjectInputStream s, boolean storedbl)
2377                    throws java.lang.ClassNotFoundException,
2378                    java.io.IOException {
2379                s.defaultReadObject();
2380
2381                // The subclass calls this method with the storage type that
2382                // they want us to use (storedbl) so we ignore the storage
2383                // method hint from the stream.
2384                s.readByte();
2385                int nT = s.readInt();
2386                int nC = s.readInt();
2387                try {
2388                    setWindingRule(s.readByte());
2389                } catch (IllegalArgumentException iae) {
2390                    throw new java.io.InvalidObjectException(iae.getMessage());
2391                }
2392
2393                pointTypes = new byte[(nT < 0) ? INIT_SIZE : nT];
2394                if (nC < 0) {
2395                    nC = INIT_SIZE * 2;
2396                }
2397                if (storedbl) {
2398                    ((Path2D.Double) this ).doubleCoords = new double[nC];
2399                } else {
2400                    ((Path2D.Float) this ).floatCoords = new float[nC];
2401                }
2402
2403                PATHDONE: for (int i = 0; nT < 0 || i < nT; i++) {
2404                    boolean isdbl;
2405                    int npoints;
2406                    byte segtype;
2407
2408                    byte serialtype = s.readByte();
2409                    switch (serialtype) {
2410                    case SERIAL_SEG_FLT_MOVETO:
2411                        isdbl = false;
2412                        npoints = 1;
2413                        segtype = SEG_MOVETO;
2414                        break;
2415                    case SERIAL_SEG_FLT_LINETO:
2416                        isdbl = false;
2417                        npoints = 1;
2418                        segtype = SEG_LINETO;
2419                        break;
2420                    case SERIAL_SEG_FLT_QUADTO:
2421                        isdbl = false;
2422                        npoints = 2;
2423                        segtype = SEG_QUADTO;
2424                        break;
2425                    case SERIAL_SEG_FLT_CUBICTO:
2426                        isdbl = false;
2427                        npoints = 3;
2428                        segtype = SEG_CUBICTO;
2429                        break;
2430
2431                    case SERIAL_SEG_DBL_MOVETO:
2432                        isdbl = true;
2433                        npoints = 1;
2434                        segtype = SEG_MOVETO;
2435                        break;
2436                    case SERIAL_SEG_DBL_LINETO:
2437                        isdbl = true;
2438                        npoints = 1;
2439                        segtype = SEG_LINETO;
2440                        break;
2441                    case SERIAL_SEG_DBL_QUADTO:
2442                        isdbl = true;
2443                        npoints = 2;
2444                        segtype = SEG_QUADTO;
2445                        break;
2446                    case SERIAL_SEG_DBL_CUBICTO:
2447                        isdbl = true;
2448                        npoints = 3;
2449                        segtype = SEG_CUBICTO;
2450                        break;
2451
2452                    case SERIAL_SEG_CLOSE:
2453                        isdbl = false;
2454                        npoints = 0;
2455                        segtype = SEG_CLOSE;
2456                        break;
2457
2458                    case SERIAL_PATH_END:
2459                        if (nT < 0) {
2460                            break PATHDONE;
2461                        }
2462                        throw new StreamCorruptedException(
2463                                "unexpected PATH_END");
2464
2465                    default:
2466                        throw new StreamCorruptedException(
2467                                "unrecognized path type");
2468                    }
2469                    needRoom(segtype != SEG_MOVETO, npoints * 2);
2470                    if (isdbl) {
2471                        while (--npoints >= 0) {
2472                            append(s.readDouble(), s.readDouble());
2473                        }
2474                    } else {
2475                        while (--npoints >= 0) {
2476                            append(s.readFloat(), s.readFloat());
2477                        }
2478                    }
2479                    pointTypes[numTypes++] = segtype;
2480                }
2481                if (nT >= 0 && s.readByte() != SERIAL_PATH_END) {
2482                    throw new StreamCorruptedException("missing PATH_END");
2483                }
2484            }
2485
2486            static abstract class Iterator implements  PathIterator {
2487                int typeIdx;
2488                int pointIdx;
2489                Path2D path;
2490
2491                static final int curvecoords[] = { 2, 2, 4, 6, 0 };
2492
2493                Iterator(Path2D path) {
2494                    this .path = path;
2495                }
2496
2497                public int getWindingRule() {
2498                    return path.getWindingRule();
2499                }
2500
2501                public boolean isDone() {
2502                    return (typeIdx >= path.numTypes);
2503                }
2504
2505                public void next() {
2506                    int type = path.pointTypes[typeIdx++];
2507                    pointIdx += curvecoords[type];
2508                }
2509            }
2510        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.