< prev index next >

src/java.desktop/share/classes/java/awt/geom/Path2D.java

Print this page


   1 /*
   2  * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 170         while (true) {
 171             try {
 172                 // try allocating the larger array
 173                 return Arrays.copyOf(oldPointTypes, newSize);
 174             } catch (OutOfMemoryError oome) {
 175                 if (newSize == newSizeMin) {
 176                     throw oome;
 177                 }
 178             }
 179             newSize = newSizeMin + (newSize - newSizeMin) / 2;
 180         }
 181     }
 182 
 183     /**
 184      * The {@code Float} class defines a geometric path with
 185      * coordinates stored in single precision floating point.
 186      *
 187      * @since 1.6
 188      */
 189     public static class Float extends Path2D implements Serializable {
 190         transient float floatCoords[];
 191 
 192         /**
 193          * Constructs a new empty single precision {@code Path2D} object
 194          * with a default winding rule of {@link #WIND_NON_ZERO}.
 195          *
 196          * @since 1.6
 197          */
 198         public Float() {
 199             this(WIND_NON_ZERO, INIT_SIZE);
 200         }
 201 
 202         /**
 203          * Constructs a new empty single precision {@code Path2D} object
 204          * with the specified winding rule to control operations that
 205          * require the interior of the path to be defined.
 206          *
 207          * @param rule the winding rule
 208          * @see #WIND_EVEN_ODD
 209          * @see #WIND_NON_ZERO
 210          * @since 1.6


 273                 this.pointTypes = new byte[INIT_SIZE];
 274                 this.floatCoords = new float[INIT_SIZE * 2];
 275                 append(pi, false);
 276             }
 277         }
 278 
 279         @Override
 280         public final void trimToSize() {
 281             // trim arrays:
 282             if (numTypes < pointTypes.length) {
 283                 this.pointTypes = Arrays.copyOf(pointTypes, numTypes);
 284             }
 285             if (numCoords < floatCoords.length) {
 286                 this.floatCoords = Arrays.copyOf(floatCoords, numCoords);
 287             }
 288         }
 289 
 290         @Override
 291         float[] cloneCoordsFloat(AffineTransform at) {
 292             // trim arrays:
 293             float ret[];
 294             if (at == null) {
 295                 ret = Arrays.copyOf(floatCoords, numCoords);
 296             } else {
 297                 ret = new float[numCoords];
 298                 at.transform(floatCoords, 0, ret, 0, numCoords / 2);
 299             }
 300             return ret;
 301         }
 302 
 303         @Override
 304         double[] cloneCoordsDouble(AffineTransform at) {
 305             // trim arrays:
 306             double ret[] = new double[numCoords];
 307             if (at == null) {
 308                 for (int i = 0; i < numCoords; i++) {
 309                     ret[i] = floatCoords[i];
 310                 }
 311             } else {
 312                 at.transform(floatCoords, 0, ret, 0, numCoords / 2);
 313             }
 314             return ret;
 315         }
 316 
 317         void append(float x, float y) {
 318             floatCoords[numCoords++] = x;
 319             floatCoords[numCoords++] = y;
 320         }
 321 
 322         void append(double x, double y) {
 323             floatCoords[numCoords++] = (float) x;
 324             floatCoords[numCoords++] = (float) y;
 325         }
 326 


 538          */
 539         public final synchronized void curveTo(float x1, float y1,
 540                                                float x2, float y2,
 541                                                float x3, float y3)
 542         {
 543             needRoom(true, 6);
 544             pointTypes[numTypes++] = SEG_CUBICTO;
 545             floatCoords[numCoords++] = x1;
 546             floatCoords[numCoords++] = y1;
 547             floatCoords[numCoords++] = x2;
 548             floatCoords[numCoords++] = y2;
 549             floatCoords[numCoords++] = x3;
 550             floatCoords[numCoords++] = y3;
 551         }
 552 
 553         int pointCrossings(double px, double py) {
 554             if (numTypes == 0) {
 555                 return 0;
 556             }
 557             double movx, movy, curx, cury, endx, endy;
 558             float coords[] = floatCoords;
 559             curx = movx = coords[0];
 560             cury = movy = coords[1];
 561             int crossings = 0;
 562             int ci = 2;
 563             for (int i = 1; i < numTypes; i++) {
 564                 switch (pointTypes[i]) {
 565                 case PathIterator.SEG_MOVETO:
 566                     if (cury != movy) {
 567                         crossings +=
 568                             Curve.pointCrossingsForLine(px, py,
 569                                                         curx, cury,
 570                                                         movx, movy);
 571                     }
 572                     movx = curx = coords[ci++];
 573                     movy = cury = coords[ci++];
 574                     break;
 575                 case PathIterator.SEG_LINETO:
 576                     crossings +=
 577                         Curve.pointCrossingsForLine(px, py,
 578                                                     curx, cury,


 617                     curx = movx;
 618                     cury = movy;
 619                     break;
 620                 }
 621             }
 622             if (cury != movy) {
 623                 crossings +=
 624                     Curve.pointCrossingsForLine(px, py,
 625                                                 curx, cury,
 626                                                 movx, movy);
 627             }
 628             return crossings;
 629         }
 630 
 631         int rectCrossings(double rxmin, double rymin,
 632                           double rxmax, double rymax)
 633         {
 634             if (numTypes == 0) {
 635                 return 0;
 636             }
 637             float coords[] = floatCoords;
 638             double curx, cury, movx, movy, endx, endy;
 639             curx = movx = coords[0];
 640             cury = movy = coords[1];
 641             int crossings = 0;
 642             int ci = 2;
 643             for (int i = 1;
 644                  crossings != Curve.RECT_INTERSECTS && i < numTypes;
 645                  i++)
 646             {
 647                 switch (pointTypes[i]) {
 648                 case PathIterator.SEG_MOVETO:
 649                     if (curx != movx || cury != movy) {
 650                         crossings =
 651                             Curve.rectCrossingsForLine(crossings,
 652                                                        rxmin, rymin,
 653                                                        rxmax, rymax,
 654                                                        curx, cury,
 655                                                        movx, movy);
 656                     }
 657                     // Count should always be a multiple of 2 here.


 719             if (crossings != Curve.RECT_INTERSECTS &&
 720                 (curx != movx || cury != movy))
 721             {
 722                 crossings =
 723                     Curve.rectCrossingsForLine(crossings,
 724                                                rxmin, rymin,
 725                                                rxmax, rymax,
 726                                                curx, cury,
 727                                                movx, movy);
 728             }
 729             // Count should always be a multiple of 2 here.
 730             // assert((crossings & 1) != 0);
 731             return crossings;
 732         }
 733 
 734         /**
 735          * {@inheritDoc}
 736          * @since 1.6
 737          */
 738         public final void append(PathIterator pi, boolean connect) {
 739             float coords[] = new float[6];
 740             while (!pi.isDone()) {
 741                 switch (pi.currentSegment(coords)) {
 742                 case SEG_MOVETO:
 743                     if (!connect || numTypes < 1 || numCoords < 1) {
 744                         moveTo(coords[0], coords[1]);
 745                         break;
 746                     }
 747                     if (pointTypes[numTypes - 1] != SEG_CLOSE &&
 748                         floatCoords[numCoords-2] == coords[0] &&
 749                         floatCoords[numCoords-1] == coords[1])
 750                     {
 751                         // Collapse out initial moveto/lineto
 752                         break;
 753                     }
 754                     lineTo(coords[0], coords[1]);
 755                     break;
 756                 case SEG_LINETO:
 757                     lineTo(coords[0], coords[1]);
 758                     break;
 759                 case SEG_QUADTO:


 987         /**
 988          * Reads the default serializable fields from the
 989          * {@code ObjectInputStream} followed by an explicit
 990          * serialization of the path segments stored in this
 991          * path.
 992          * <p>
 993          * There are no default serializable fields as of 1.6.
 994          * <p>
 995          * The serial data for this object is described in the
 996          * writeObject method.
 997          *
 998          * @since 1.6
 999          */
1000         private void readObject(java.io.ObjectInputStream s)
1001             throws java.lang.ClassNotFoundException, java.io.IOException
1002         {
1003             super.readObject(s, false);
1004         }
1005 
1006         static class CopyIterator extends Path2D.Iterator {
1007             float floatCoords[];
1008 
1009             CopyIterator(Path2D.Float p2df) {
1010                 super(p2df);
1011                 this.floatCoords = p2df.floatCoords;
1012             }
1013 
1014             public int currentSegment(float[] coords) {
1015                 int type = path.pointTypes[typeIdx];
1016                 int numCoords = curvecoords[type];
1017                 if (numCoords > 0) {
1018                     System.arraycopy(floatCoords, pointIdx,
1019                                      coords, 0, numCoords);
1020                 }
1021                 return type;
1022             }
1023 
1024             public int currentSegment(double[] coords) {
1025                 int type = path.pointTypes[typeIdx];
1026                 int numCoords = curvecoords[type];
1027                 if (numCoords > 0) {
1028                     for (int i = 0; i < numCoords; i++) {
1029                         coords[i] = floatCoords[pointIdx + i];
1030                     }
1031                 }
1032                 return type;
1033             }
1034         }
1035 
1036         static class TxIterator extends Path2D.Iterator {
1037             float floatCoords[];
1038             AffineTransform affine;
1039 
1040             TxIterator(Path2D.Float p2df, AffineTransform at) {
1041                 super(p2df);
1042                 this.floatCoords = p2df.floatCoords;
1043                 this.affine = at;
1044             }
1045 
1046             public int currentSegment(float[] coords) {
1047                 int type = path.pointTypes[typeIdx];
1048                 int numCoords = curvecoords[type];
1049                 if (numCoords > 0) {
1050                     affine.transform(floatCoords, pointIdx,
1051                                      coords, 0, numCoords / 2);
1052                 }
1053                 return type;
1054             }
1055 
1056             public int currentSegment(double[] coords) {
1057                 int type = path.pointTypes[typeIdx];
1058                 int numCoords = curvecoords[type];
1059                 if (numCoords > 0) {
1060                     affine.transform(floatCoords, pointIdx,
1061                                      coords, 0, numCoords / 2);
1062                 }
1063                 return type;
1064             }
1065         }
1066 
1067     }
1068 
1069     /**
1070      * The {@code Double} class defines a geometric path with
1071      * coordinates stored in double precision floating point.
1072      *
1073      * @since 1.6
1074      */
1075     public static class Double extends Path2D implements Serializable {
1076         transient double doubleCoords[];
1077 
1078         /**
1079          * Constructs a new empty double precision {@code Path2D} object
1080          * with a default winding rule of {@link #WIND_NON_ZERO}.
1081          *
1082          * @since 1.6
1083          */
1084         public Double() {
1085             this(WIND_NON_ZERO, INIT_SIZE);
1086         }
1087 
1088         /**
1089          * Constructs a new empty double precision {@code Path2D} object
1090          * with the specified winding rule to control operations that
1091          * require the interior of the path to be defined.
1092          *
1093          * @param rule the winding rule
1094          * @see #WIND_EVEN_ODD
1095          * @see #WIND_NON_ZERO
1096          * @since 1.6


1159                 this.pointTypes = new byte[INIT_SIZE];
1160                 this.doubleCoords = new double[INIT_SIZE * 2];
1161                 append(pi, false);
1162             }
1163         }
1164 
1165         @Override
1166         public final void trimToSize() {
1167             // trim arrays:
1168             if (numTypes < pointTypes.length) {
1169                 this.pointTypes = Arrays.copyOf(pointTypes, numTypes);
1170             }
1171             if (numCoords < doubleCoords.length) {
1172                 this.doubleCoords = Arrays.copyOf(doubleCoords, numCoords);
1173             }
1174         }
1175 
1176         @Override
1177         float[] cloneCoordsFloat(AffineTransform at) {
1178             // trim arrays:
1179             float ret[] = new float[numCoords];
1180             if (at == null) {
1181                 for (int i = 0; i < numCoords; i++) {
1182                     ret[i] = (float) doubleCoords[i];
1183                 }
1184             } else {
1185                 at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1186             }
1187             return ret;
1188         }
1189 
1190         @Override
1191         double[] cloneCoordsDouble(AffineTransform at) {
1192             // trim arrays:
1193             double ret[];
1194             if (at == null) {
1195                 ret = Arrays.copyOf(doubleCoords, numCoords);
1196             } else {
1197                 ret = new double[numCoords];
1198                 at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1199             }
1200             return ret;
1201         }
1202 
1203         void append(float x, float y) {
1204             doubleCoords[numCoords++] = x;
1205             doubleCoords[numCoords++] = y;
1206         }
1207 
1208         void append(double x, double y) {
1209             doubleCoords[numCoords++] = x;
1210             doubleCoords[numCoords++] = y;
1211         }
1212 
1213         Point2D getPoint(int coordindex) {


1313          */
1314         public final synchronized void curveTo(double x1, double y1,
1315                                                double x2, double y2,
1316                                                double x3, double y3)
1317         {
1318             needRoom(true, 6);
1319             pointTypes[numTypes++] = SEG_CUBICTO;
1320             doubleCoords[numCoords++] = x1;
1321             doubleCoords[numCoords++] = y1;
1322             doubleCoords[numCoords++] = x2;
1323             doubleCoords[numCoords++] = y2;
1324             doubleCoords[numCoords++] = x3;
1325             doubleCoords[numCoords++] = y3;
1326         }
1327 
1328         int pointCrossings(double px, double py) {
1329             if (numTypes == 0) {
1330                 return 0;
1331             }
1332             double movx, movy, curx, cury, endx, endy;
1333             double coords[] = doubleCoords;
1334             curx = movx = coords[0];
1335             cury = movy = coords[1];
1336             int crossings = 0;
1337             int ci = 2;
1338             for (int i = 1; i < numTypes; i++) {
1339                 switch (pointTypes[i]) {
1340                 case PathIterator.SEG_MOVETO:
1341                     if (cury != movy) {
1342                         crossings +=
1343                             Curve.pointCrossingsForLine(px, py,
1344                                                         curx, cury,
1345                                                         movx, movy);
1346                     }
1347                     movx = curx = coords[ci++];
1348                     movy = cury = coords[ci++];
1349                     break;
1350                 case PathIterator.SEG_LINETO:
1351                     crossings +=
1352                         Curve.pointCrossingsForLine(px, py,
1353                                                     curx, cury,


1392                     curx = movx;
1393                     cury = movy;
1394                     break;
1395                 }
1396             }
1397             if (cury != movy) {
1398                 crossings +=
1399                     Curve.pointCrossingsForLine(px, py,
1400                                                 curx, cury,
1401                                                 movx, movy);
1402             }
1403             return crossings;
1404         }
1405 
1406         int rectCrossings(double rxmin, double rymin,
1407                           double rxmax, double rymax)
1408         {
1409             if (numTypes == 0) {
1410                 return 0;
1411             }
1412             double coords[] = doubleCoords;
1413             double curx, cury, movx, movy, endx, endy;
1414             curx = movx = coords[0];
1415             cury = movy = coords[1];
1416             int crossings = 0;
1417             int ci = 2;
1418             for (int i = 1;
1419                  crossings != Curve.RECT_INTERSECTS && i < numTypes;
1420                  i++)
1421             {
1422                 switch (pointTypes[i]) {
1423                 case PathIterator.SEG_MOVETO:
1424                     if (curx != movx || cury != movy) {
1425                         crossings =
1426                             Curve.rectCrossingsForLine(crossings,
1427                                                        rxmin, rymin,
1428                                                        rxmax, rymax,
1429                                                        curx, cury,
1430                                                        movx, movy);
1431                     }
1432                     // Count should always be a multiple of 2 here.


1495             if (crossings != Curve.RECT_INTERSECTS &&
1496                 (curx != movx || cury != movy))
1497             {
1498                 crossings =
1499                     Curve.rectCrossingsForLine(crossings,
1500                                                rxmin, rymin,
1501                                                rxmax, rymax,
1502                                                curx, cury,
1503                                                movx, movy);
1504             }
1505             // Count should always be a multiple of 2 here.
1506             // assert((crossings & 1) != 0);
1507             return crossings;
1508         }
1509 
1510         /**
1511          * {@inheritDoc}
1512          * @since 1.6
1513          */
1514         public final void append(PathIterator pi, boolean connect) {
1515             double coords[] = new double[6];
1516             while (!pi.isDone()) {
1517                 switch (pi.currentSegment(coords)) {
1518                 case SEG_MOVETO:
1519                     if (!connect || numTypes < 1 || numCoords < 1) {
1520                         moveTo(coords[0], coords[1]);
1521                         break;
1522                     }
1523                     if (pointTypes[numTypes - 1] != SEG_CLOSE &&
1524                         doubleCoords[numCoords-2] == coords[0] &&
1525                         doubleCoords[numCoords-1] == coords[1])
1526                     {
1527                         // Collapse out initial moveto/lineto
1528                         break;
1529                     }
1530                     lineTo(coords[0], coords[1]);
1531                     break;
1532                 case SEG_LINETO:
1533                     lineTo(coords[0], coords[1]);
1534                     break;
1535                 case SEG_QUADTO:


1762         /**
1763          * Reads the default serializable fields from the
1764          * {@code ObjectInputStream} followed by an explicit
1765          * serialization of the path segments stored in this
1766          * path.
1767          * <p>
1768          * There are no default serializable fields as of 1.6.
1769          * <p>
1770          * The serial data for this object is described in the
1771          * writeObject method.
1772          *
1773          * @since 1.6
1774          */
1775         private void readObject(java.io.ObjectInputStream s)
1776             throws java.lang.ClassNotFoundException, java.io.IOException
1777         {
1778             super.readObject(s, true);
1779         }
1780 
1781         static class CopyIterator extends Path2D.Iterator {
1782             double doubleCoords[];
1783 
1784             CopyIterator(Path2D.Double p2dd) {
1785                 super(p2dd);
1786                 this.doubleCoords = p2dd.doubleCoords;
1787             }
1788 
1789             public int currentSegment(float[] coords) {
1790                 int type = path.pointTypes[typeIdx];
1791                 int numCoords = curvecoords[type];
1792                 if (numCoords > 0) {
1793                     for (int i = 0; i < numCoords; i++) {
1794                         coords[i] = (float) doubleCoords[pointIdx + i];
1795                     }
1796                 }
1797                 return type;
1798             }
1799 
1800             public int currentSegment(double[] coords) {
1801                 int type = path.pointTypes[typeIdx];
1802                 int numCoords = curvecoords[type];
1803                 if (numCoords > 0) {
1804                     System.arraycopy(doubleCoords, pointIdx,
1805                                      coords, 0, numCoords);
1806                 }
1807                 return type;
1808             }
1809         }
1810 
1811         static class TxIterator extends Path2D.Iterator {
1812             double doubleCoords[];
1813             AffineTransform affine;
1814 
1815             TxIterator(Path2D.Double p2dd, AffineTransform at) {
1816                 super(p2dd);
1817                 this.doubleCoords = p2dd.doubleCoords;
1818                 this.affine = at;
1819             }
1820 
1821             public int currentSegment(float[] coords) {
1822                 int type = path.pointTypes[typeIdx];
1823                 int numCoords = curvecoords[type];
1824                 if (numCoords > 0) {
1825                     affine.transform(doubleCoords, pointIdx,
1826                                      coords, 0, numCoords / 2);
1827                 }
1828                 return type;
1829             }
1830 
1831             public int currentSegment(double[] coords) {
1832                 int type = path.pointTypes[typeIdx];


2520     private static final byte SERIAL_STORAGE_DBL_ARRAY = 0x31;
2521 
2522     private static final byte SERIAL_SEG_FLT_MOVETO    = 0x40;
2523     private static final byte SERIAL_SEG_FLT_LINETO    = 0x41;
2524     private static final byte SERIAL_SEG_FLT_QUADTO    = 0x42;
2525     private static final byte SERIAL_SEG_FLT_CUBICTO   = 0x43;
2526 
2527     private static final byte SERIAL_SEG_DBL_MOVETO    = 0x50;
2528     private static final byte SERIAL_SEG_DBL_LINETO    = 0x51;
2529     private static final byte SERIAL_SEG_DBL_QUADTO    = 0x52;
2530     private static final byte SERIAL_SEG_DBL_CUBICTO   = 0x53;
2531 
2532     private static final byte SERIAL_SEG_CLOSE         = 0x60;
2533     private static final byte SERIAL_PATH_END          = 0x61;
2534 
2535     final void writeObject(java.io.ObjectOutputStream s, boolean isdbl)
2536         throws java.io.IOException
2537     {
2538         s.defaultWriteObject();
2539 
2540         float fCoords[];
2541         double dCoords[];
2542 
2543         if (isdbl) {
2544             dCoords = ((Path2D.Double) this).doubleCoords;
2545             fCoords = null;
2546         } else {
2547             fCoords = ((Path2D.Float) this).floatCoords;
2548             dCoords = null;
2549         }
2550 
2551         int numTypes = this.numTypes;
2552 
2553         s.writeByte(isdbl
2554                     ? SERIAL_STORAGE_DBL_ARRAY
2555                     : SERIAL_STORAGE_FLT_ARRAY);
2556         s.writeInt(numTypes);
2557         s.writeInt(numCoords);
2558         s.writeByte((byte) windingRule);
2559 
2560         int cindex = 0;
2561         for (int i = 0; i < numTypes; i++) {


2709                 while (--npoints >= 0) {
2710                     append(s.readDouble(), s.readDouble());
2711                 }
2712             } else {
2713                 while (--npoints >= 0) {
2714                     append(s.readFloat(), s.readFloat());
2715                 }
2716             }
2717             pointTypes[numTypes++] = segtype;
2718         }
2719         if (nT >= 0 && s.readByte() != SERIAL_PATH_END) {
2720             throw new StreamCorruptedException("missing PATH_END");
2721         }
2722     }
2723 
2724     abstract static class Iterator implements PathIterator {
2725         int typeIdx;
2726         int pointIdx;
2727         Path2D path;
2728 
2729         static final int curvecoords[] = {2, 2, 4, 6, 0};
2730 
2731         Iterator(Path2D path) {
2732             this.path = path;
2733         }
2734 
2735         public int getWindingRule() {
2736             return path.getWindingRule();
2737         }
2738 
2739         public boolean isDone() {
2740             return (typeIdx >= path.numTypes);
2741         }
2742 
2743         public void next() {
2744             int type = path.pointTypes[typeIdx++];
2745             pointIdx += curvecoords[type];
2746         }
2747     }
2748 }
   1 /*
   2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


 170         while (true) {
 171             try {
 172                 // try allocating the larger array
 173                 return Arrays.copyOf(oldPointTypes, newSize);
 174             } catch (OutOfMemoryError oome) {
 175                 if (newSize == newSizeMin) {
 176                     throw oome;
 177                 }
 178             }
 179             newSize = newSizeMin + (newSize - newSizeMin) / 2;
 180         }
 181     }
 182 
 183     /**
 184      * The {@code Float} class defines a geometric path with
 185      * coordinates stored in single precision floating point.
 186      *
 187      * @since 1.6
 188      */
 189     public static class Float extends Path2D implements Serializable {
 190         transient float[] floatCoords;
 191 
 192         /**
 193          * Constructs a new empty single precision {@code Path2D} object
 194          * with a default winding rule of {@link #WIND_NON_ZERO}.
 195          *
 196          * @since 1.6
 197          */
 198         public Float() {
 199             this(WIND_NON_ZERO, INIT_SIZE);
 200         }
 201 
 202         /**
 203          * Constructs a new empty single precision {@code Path2D} object
 204          * with the specified winding rule to control operations that
 205          * require the interior of the path to be defined.
 206          *
 207          * @param rule the winding rule
 208          * @see #WIND_EVEN_ODD
 209          * @see #WIND_NON_ZERO
 210          * @since 1.6


 273                 this.pointTypes = new byte[INIT_SIZE];
 274                 this.floatCoords = new float[INIT_SIZE * 2];
 275                 append(pi, false);
 276             }
 277         }
 278 
 279         @Override
 280         public final void trimToSize() {
 281             // trim arrays:
 282             if (numTypes < pointTypes.length) {
 283                 this.pointTypes = Arrays.copyOf(pointTypes, numTypes);
 284             }
 285             if (numCoords < floatCoords.length) {
 286                 this.floatCoords = Arrays.copyOf(floatCoords, numCoords);
 287             }
 288         }
 289 
 290         @Override
 291         float[] cloneCoordsFloat(AffineTransform at) {
 292             // trim arrays:
 293             float[] ret;
 294             if (at == null) {
 295                 ret = Arrays.copyOf(floatCoords, numCoords);
 296             } else {
 297                 ret = new float[numCoords];
 298                 at.transform(floatCoords, 0, ret, 0, numCoords / 2);
 299             }
 300             return ret;
 301         }
 302 
 303         @Override
 304         double[] cloneCoordsDouble(AffineTransform at) {
 305             // trim arrays:
 306             double[] ret = new double[numCoords];
 307             if (at == null) {
 308                 for (int i = 0; i < numCoords; i++) {
 309                     ret[i] = floatCoords[i];
 310                 }
 311             } else {
 312                 at.transform(floatCoords, 0, ret, 0, numCoords / 2);
 313             }
 314             return ret;
 315         }
 316 
 317         void append(float x, float y) {
 318             floatCoords[numCoords++] = x;
 319             floatCoords[numCoords++] = y;
 320         }
 321 
 322         void append(double x, double y) {
 323             floatCoords[numCoords++] = (float) x;
 324             floatCoords[numCoords++] = (float) y;
 325         }
 326 


 538          */
 539         public final synchronized void curveTo(float x1, float y1,
 540                                                float x2, float y2,
 541                                                float x3, float y3)
 542         {
 543             needRoom(true, 6);
 544             pointTypes[numTypes++] = SEG_CUBICTO;
 545             floatCoords[numCoords++] = x1;
 546             floatCoords[numCoords++] = y1;
 547             floatCoords[numCoords++] = x2;
 548             floatCoords[numCoords++] = y2;
 549             floatCoords[numCoords++] = x3;
 550             floatCoords[numCoords++] = y3;
 551         }
 552 
 553         int pointCrossings(double px, double py) {
 554             if (numTypes == 0) {
 555                 return 0;
 556             }
 557             double movx, movy, curx, cury, endx, endy;
 558             float[] coords = floatCoords;
 559             curx = movx = coords[0];
 560             cury = movy = coords[1];
 561             int crossings = 0;
 562             int ci = 2;
 563             for (int i = 1; i < numTypes; i++) {
 564                 switch (pointTypes[i]) {
 565                 case PathIterator.SEG_MOVETO:
 566                     if (cury != movy) {
 567                         crossings +=
 568                             Curve.pointCrossingsForLine(px, py,
 569                                                         curx, cury,
 570                                                         movx, movy);
 571                     }
 572                     movx = curx = coords[ci++];
 573                     movy = cury = coords[ci++];
 574                     break;
 575                 case PathIterator.SEG_LINETO:
 576                     crossings +=
 577                         Curve.pointCrossingsForLine(px, py,
 578                                                     curx, cury,


 617                     curx = movx;
 618                     cury = movy;
 619                     break;
 620                 }
 621             }
 622             if (cury != movy) {
 623                 crossings +=
 624                     Curve.pointCrossingsForLine(px, py,
 625                                                 curx, cury,
 626                                                 movx, movy);
 627             }
 628             return crossings;
 629         }
 630 
 631         int rectCrossings(double rxmin, double rymin,
 632                           double rxmax, double rymax)
 633         {
 634             if (numTypes == 0) {
 635                 return 0;
 636             }
 637             float[] coords = floatCoords;
 638             double curx, cury, movx, movy, endx, endy;
 639             curx = movx = coords[0];
 640             cury = movy = coords[1];
 641             int crossings = 0;
 642             int ci = 2;
 643             for (int i = 1;
 644                  crossings != Curve.RECT_INTERSECTS && i < numTypes;
 645                  i++)
 646             {
 647                 switch (pointTypes[i]) {
 648                 case PathIterator.SEG_MOVETO:
 649                     if (curx != movx || cury != movy) {
 650                         crossings =
 651                             Curve.rectCrossingsForLine(crossings,
 652                                                        rxmin, rymin,
 653                                                        rxmax, rymax,
 654                                                        curx, cury,
 655                                                        movx, movy);
 656                     }
 657                     // Count should always be a multiple of 2 here.


 719             if (crossings != Curve.RECT_INTERSECTS &&
 720                 (curx != movx || cury != movy))
 721             {
 722                 crossings =
 723                     Curve.rectCrossingsForLine(crossings,
 724                                                rxmin, rymin,
 725                                                rxmax, rymax,
 726                                                curx, cury,
 727                                                movx, movy);
 728             }
 729             // Count should always be a multiple of 2 here.
 730             // assert((crossings & 1) != 0);
 731             return crossings;
 732         }
 733 
 734         /**
 735          * {@inheritDoc}
 736          * @since 1.6
 737          */
 738         public final void append(PathIterator pi, boolean connect) {
 739             float[] coords = new float[6];
 740             while (!pi.isDone()) {
 741                 switch (pi.currentSegment(coords)) {
 742                 case SEG_MOVETO:
 743                     if (!connect || numTypes < 1 || numCoords < 1) {
 744                         moveTo(coords[0], coords[1]);
 745                         break;
 746                     }
 747                     if (pointTypes[numTypes - 1] != SEG_CLOSE &&
 748                         floatCoords[numCoords-2] == coords[0] &&
 749                         floatCoords[numCoords-1] == coords[1])
 750                     {
 751                         // Collapse out initial moveto/lineto
 752                         break;
 753                     }
 754                     lineTo(coords[0], coords[1]);
 755                     break;
 756                 case SEG_LINETO:
 757                     lineTo(coords[0], coords[1]);
 758                     break;
 759                 case SEG_QUADTO:


 987         /**
 988          * Reads the default serializable fields from the
 989          * {@code ObjectInputStream} followed by an explicit
 990          * serialization of the path segments stored in this
 991          * path.
 992          * <p>
 993          * There are no default serializable fields as of 1.6.
 994          * <p>
 995          * The serial data for this object is described in the
 996          * writeObject method.
 997          *
 998          * @since 1.6
 999          */
1000         private void readObject(java.io.ObjectInputStream s)
1001             throws java.lang.ClassNotFoundException, java.io.IOException
1002         {
1003             super.readObject(s, false);
1004         }
1005 
1006         static class CopyIterator extends Path2D.Iterator {
1007             float[] floatCoords;
1008 
1009             CopyIterator(Path2D.Float p2df) {
1010                 super(p2df);
1011                 this.floatCoords = p2df.floatCoords;
1012             }
1013 
1014             public int currentSegment(float[] coords) {
1015                 int type = path.pointTypes[typeIdx];
1016                 int numCoords = curvecoords[type];
1017                 if (numCoords > 0) {
1018                     System.arraycopy(floatCoords, pointIdx,
1019                                      coords, 0, numCoords);
1020                 }
1021                 return type;
1022             }
1023 
1024             public int currentSegment(double[] coords) {
1025                 int type = path.pointTypes[typeIdx];
1026                 int numCoords = curvecoords[type];
1027                 if (numCoords > 0) {
1028                     for (int i = 0; i < numCoords; i++) {
1029                         coords[i] = floatCoords[pointIdx + i];
1030                     }
1031                 }
1032                 return type;
1033             }
1034         }
1035 
1036         static class TxIterator extends Path2D.Iterator {
1037             float[] floatCoords;
1038             AffineTransform affine;
1039 
1040             TxIterator(Path2D.Float p2df, AffineTransform at) {
1041                 super(p2df);
1042                 this.floatCoords = p2df.floatCoords;
1043                 this.affine = at;
1044             }
1045 
1046             public int currentSegment(float[] coords) {
1047                 int type = path.pointTypes[typeIdx];
1048                 int numCoords = curvecoords[type];
1049                 if (numCoords > 0) {
1050                     affine.transform(floatCoords, pointIdx,
1051                                      coords, 0, numCoords / 2);
1052                 }
1053                 return type;
1054             }
1055 
1056             public int currentSegment(double[] coords) {
1057                 int type = path.pointTypes[typeIdx];
1058                 int numCoords = curvecoords[type];
1059                 if (numCoords > 0) {
1060                     affine.transform(floatCoords, pointIdx,
1061                                      coords, 0, numCoords / 2);
1062                 }
1063                 return type;
1064             }
1065         }
1066 
1067     }
1068 
1069     /**
1070      * The {@code Double} class defines a geometric path with
1071      * coordinates stored in double precision floating point.
1072      *
1073      * @since 1.6
1074      */
1075     public static class Double extends Path2D implements Serializable {
1076         transient double[] doubleCoords;
1077 
1078         /**
1079          * Constructs a new empty double precision {@code Path2D} object
1080          * with a default winding rule of {@link #WIND_NON_ZERO}.
1081          *
1082          * @since 1.6
1083          */
1084         public Double() {
1085             this(WIND_NON_ZERO, INIT_SIZE);
1086         }
1087 
1088         /**
1089          * Constructs a new empty double precision {@code Path2D} object
1090          * with the specified winding rule to control operations that
1091          * require the interior of the path to be defined.
1092          *
1093          * @param rule the winding rule
1094          * @see #WIND_EVEN_ODD
1095          * @see #WIND_NON_ZERO
1096          * @since 1.6


1159                 this.pointTypes = new byte[INIT_SIZE];
1160                 this.doubleCoords = new double[INIT_SIZE * 2];
1161                 append(pi, false);
1162             }
1163         }
1164 
1165         @Override
1166         public final void trimToSize() {
1167             // trim arrays:
1168             if (numTypes < pointTypes.length) {
1169                 this.pointTypes = Arrays.copyOf(pointTypes, numTypes);
1170             }
1171             if (numCoords < doubleCoords.length) {
1172                 this.doubleCoords = Arrays.copyOf(doubleCoords, numCoords);
1173             }
1174         }
1175 
1176         @Override
1177         float[] cloneCoordsFloat(AffineTransform at) {
1178             // trim arrays:
1179             float[] ret = new float[numCoords];
1180             if (at == null) {
1181                 for (int i = 0; i < numCoords; i++) {
1182                     ret[i] = (float) doubleCoords[i];
1183                 }
1184             } else {
1185                 at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1186             }
1187             return ret;
1188         }
1189 
1190         @Override
1191         double[] cloneCoordsDouble(AffineTransform at) {
1192             // trim arrays:
1193             double[] ret;
1194             if (at == null) {
1195                 ret = Arrays.copyOf(doubleCoords, numCoords);
1196             } else {
1197                 ret = new double[numCoords];
1198                 at.transform(doubleCoords, 0, ret, 0, numCoords / 2);
1199             }
1200             return ret;
1201         }
1202 
1203         void append(float x, float y) {
1204             doubleCoords[numCoords++] = x;
1205             doubleCoords[numCoords++] = y;
1206         }
1207 
1208         void append(double x, double y) {
1209             doubleCoords[numCoords++] = x;
1210             doubleCoords[numCoords++] = y;
1211         }
1212 
1213         Point2D getPoint(int coordindex) {


1313          */
1314         public final synchronized void curveTo(double x1, double y1,
1315                                                double x2, double y2,
1316                                                double x3, double y3)
1317         {
1318             needRoom(true, 6);
1319             pointTypes[numTypes++] = SEG_CUBICTO;
1320             doubleCoords[numCoords++] = x1;
1321             doubleCoords[numCoords++] = y1;
1322             doubleCoords[numCoords++] = x2;
1323             doubleCoords[numCoords++] = y2;
1324             doubleCoords[numCoords++] = x3;
1325             doubleCoords[numCoords++] = y3;
1326         }
1327 
1328         int pointCrossings(double px, double py) {
1329             if (numTypes == 0) {
1330                 return 0;
1331             }
1332             double movx, movy, curx, cury, endx, endy;
1333             double[] coords = doubleCoords;
1334             curx = movx = coords[0];
1335             cury = movy = coords[1];
1336             int crossings = 0;
1337             int ci = 2;
1338             for (int i = 1; i < numTypes; i++) {
1339                 switch (pointTypes[i]) {
1340                 case PathIterator.SEG_MOVETO:
1341                     if (cury != movy) {
1342                         crossings +=
1343                             Curve.pointCrossingsForLine(px, py,
1344                                                         curx, cury,
1345                                                         movx, movy);
1346                     }
1347                     movx = curx = coords[ci++];
1348                     movy = cury = coords[ci++];
1349                     break;
1350                 case PathIterator.SEG_LINETO:
1351                     crossings +=
1352                         Curve.pointCrossingsForLine(px, py,
1353                                                     curx, cury,


1392                     curx = movx;
1393                     cury = movy;
1394                     break;
1395                 }
1396             }
1397             if (cury != movy) {
1398                 crossings +=
1399                     Curve.pointCrossingsForLine(px, py,
1400                                                 curx, cury,
1401                                                 movx, movy);
1402             }
1403             return crossings;
1404         }
1405 
1406         int rectCrossings(double rxmin, double rymin,
1407                           double rxmax, double rymax)
1408         {
1409             if (numTypes == 0) {
1410                 return 0;
1411             }
1412             double[] coords = doubleCoords;
1413             double curx, cury, movx, movy, endx, endy;
1414             curx = movx = coords[0];
1415             cury = movy = coords[1];
1416             int crossings = 0;
1417             int ci = 2;
1418             for (int i = 1;
1419                  crossings != Curve.RECT_INTERSECTS && i < numTypes;
1420                  i++)
1421             {
1422                 switch (pointTypes[i]) {
1423                 case PathIterator.SEG_MOVETO:
1424                     if (curx != movx || cury != movy) {
1425                         crossings =
1426                             Curve.rectCrossingsForLine(crossings,
1427                                                        rxmin, rymin,
1428                                                        rxmax, rymax,
1429                                                        curx, cury,
1430                                                        movx, movy);
1431                     }
1432                     // Count should always be a multiple of 2 here.


1495             if (crossings != Curve.RECT_INTERSECTS &&
1496                 (curx != movx || cury != movy))
1497             {
1498                 crossings =
1499                     Curve.rectCrossingsForLine(crossings,
1500                                                rxmin, rymin,
1501                                                rxmax, rymax,
1502                                                curx, cury,
1503                                                movx, movy);
1504             }
1505             // Count should always be a multiple of 2 here.
1506             // assert((crossings & 1) != 0);
1507             return crossings;
1508         }
1509 
1510         /**
1511          * {@inheritDoc}
1512          * @since 1.6
1513          */
1514         public final void append(PathIterator pi, boolean connect) {
1515             double[] coords = new double[6];
1516             while (!pi.isDone()) {
1517                 switch (pi.currentSegment(coords)) {
1518                 case SEG_MOVETO:
1519                     if (!connect || numTypes < 1 || numCoords < 1) {
1520                         moveTo(coords[0], coords[1]);
1521                         break;
1522                     }
1523                     if (pointTypes[numTypes - 1] != SEG_CLOSE &&
1524                         doubleCoords[numCoords-2] == coords[0] &&
1525                         doubleCoords[numCoords-1] == coords[1])
1526                     {
1527                         // Collapse out initial moveto/lineto
1528                         break;
1529                     }
1530                     lineTo(coords[0], coords[1]);
1531                     break;
1532                 case SEG_LINETO:
1533                     lineTo(coords[0], coords[1]);
1534                     break;
1535                 case SEG_QUADTO:


1762         /**
1763          * Reads the default serializable fields from the
1764          * {@code ObjectInputStream} followed by an explicit
1765          * serialization of the path segments stored in this
1766          * path.
1767          * <p>
1768          * There are no default serializable fields as of 1.6.
1769          * <p>
1770          * The serial data for this object is described in the
1771          * writeObject method.
1772          *
1773          * @since 1.6
1774          */
1775         private void readObject(java.io.ObjectInputStream s)
1776             throws java.lang.ClassNotFoundException, java.io.IOException
1777         {
1778             super.readObject(s, true);
1779         }
1780 
1781         static class CopyIterator extends Path2D.Iterator {
1782             double[] doubleCoords;
1783 
1784             CopyIterator(Path2D.Double p2dd) {
1785                 super(p2dd);
1786                 this.doubleCoords = p2dd.doubleCoords;
1787             }
1788 
1789             public int currentSegment(float[] coords) {
1790                 int type = path.pointTypes[typeIdx];
1791                 int numCoords = curvecoords[type];
1792                 if (numCoords > 0) {
1793                     for (int i = 0; i < numCoords; i++) {
1794                         coords[i] = (float) doubleCoords[pointIdx + i];
1795                     }
1796                 }
1797                 return type;
1798             }
1799 
1800             public int currentSegment(double[] coords) {
1801                 int type = path.pointTypes[typeIdx];
1802                 int numCoords = curvecoords[type];
1803                 if (numCoords > 0) {
1804                     System.arraycopy(doubleCoords, pointIdx,
1805                                      coords, 0, numCoords);
1806                 }
1807                 return type;
1808             }
1809         }
1810 
1811         static class TxIterator extends Path2D.Iterator {
1812             double[] doubleCoords;
1813             AffineTransform affine;
1814 
1815             TxIterator(Path2D.Double p2dd, AffineTransform at) {
1816                 super(p2dd);
1817                 this.doubleCoords = p2dd.doubleCoords;
1818                 this.affine = at;
1819             }
1820 
1821             public int currentSegment(float[] coords) {
1822                 int type = path.pointTypes[typeIdx];
1823                 int numCoords = curvecoords[type];
1824                 if (numCoords > 0) {
1825                     affine.transform(doubleCoords, pointIdx,
1826                                      coords, 0, numCoords / 2);
1827                 }
1828                 return type;
1829             }
1830 
1831             public int currentSegment(double[] coords) {
1832                 int type = path.pointTypes[typeIdx];


2520     private static final byte SERIAL_STORAGE_DBL_ARRAY = 0x31;
2521 
2522     private static final byte SERIAL_SEG_FLT_MOVETO    = 0x40;
2523     private static final byte SERIAL_SEG_FLT_LINETO    = 0x41;
2524     private static final byte SERIAL_SEG_FLT_QUADTO    = 0x42;
2525     private static final byte SERIAL_SEG_FLT_CUBICTO   = 0x43;
2526 
2527     private static final byte SERIAL_SEG_DBL_MOVETO    = 0x50;
2528     private static final byte SERIAL_SEG_DBL_LINETO    = 0x51;
2529     private static final byte SERIAL_SEG_DBL_QUADTO    = 0x52;
2530     private static final byte SERIAL_SEG_DBL_CUBICTO   = 0x53;
2531 
2532     private static final byte SERIAL_SEG_CLOSE         = 0x60;
2533     private static final byte SERIAL_PATH_END          = 0x61;
2534 
2535     final void writeObject(java.io.ObjectOutputStream s, boolean isdbl)
2536         throws java.io.IOException
2537     {
2538         s.defaultWriteObject();
2539 
2540         float[] fCoords;
2541         double[] dCoords;
2542 
2543         if (isdbl) {
2544             dCoords = ((Path2D.Double) this).doubleCoords;
2545             fCoords = null;
2546         } else {
2547             fCoords = ((Path2D.Float) this).floatCoords;
2548             dCoords = null;
2549         }
2550 
2551         int numTypes = this.numTypes;
2552 
2553         s.writeByte(isdbl
2554                     ? SERIAL_STORAGE_DBL_ARRAY
2555                     : SERIAL_STORAGE_FLT_ARRAY);
2556         s.writeInt(numTypes);
2557         s.writeInt(numCoords);
2558         s.writeByte((byte) windingRule);
2559 
2560         int cindex = 0;
2561         for (int i = 0; i < numTypes; i++) {


2709                 while (--npoints >= 0) {
2710                     append(s.readDouble(), s.readDouble());
2711                 }
2712             } else {
2713                 while (--npoints >= 0) {
2714                     append(s.readFloat(), s.readFloat());
2715                 }
2716             }
2717             pointTypes[numTypes++] = segtype;
2718         }
2719         if (nT >= 0 && s.readByte() != SERIAL_PATH_END) {
2720             throw new StreamCorruptedException("missing PATH_END");
2721         }
2722     }
2723 
2724     abstract static class Iterator implements PathIterator {
2725         int typeIdx;
2726         int pointIdx;
2727         Path2D path;
2728 
2729         static final int[] curvecoords = {2, 2, 4, 6, 0};
2730 
2731         Iterator(Path2D path) {
2732             this.path = path;
2733         }
2734 
2735         public int getWindingRule() {
2736             return path.getWindingRule();
2737         }
2738 
2739         public boolean isDone() {
2740             return (typeIdx >= path.numTypes);
2741         }
2742 
2743         public void next() {
2744             int type = path.pointTypes[typeIdx++];
2745             pointIdx += curvecoords[type];
2746         }
2747     }
2748 }
< prev index next >