| /* | 
 |  * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. | 
 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
 |  * | 
 |  * This code is free software; you can redistribute it and/or modify it | 
 |  * under the terms of the GNU General Public License version 2 only, as | 
 |  * published by the Free Software Foundation. | 
 |  * | 
 |  * This code is distributed in the hope that it will be useful, but WITHOUT | 
 |  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
 |  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
 |  * version 2 for more details (a copy is included in the LICENSE file that | 
 |  * accompanied this code). | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License version | 
 |  * 2 along with this work; if not, write to the Free Software Foundation, | 
 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
 |  * | 
 |  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
 |  * or visit www.oracle.com if you need additional information or have any | 
 |  * questions. | 
 |  * | 
 |  */ | 
 |  | 
 | /** | 
 |  * @test | 
 |  * @bug 7047069 | 
 |  * @summary Array can dynamically change size when assigned to an object field | 
 |  * | 
 |  * @run main/othervm -Xbatch Test7047069 | 
 |  */ | 
 |  | 
 | import java.util.*; | 
 | import java.awt.geom.*; | 
 |  | 
 | public class Test7047069 { | 
 |     static boolean verbose; | 
 |  | 
 |     static final int GROW_SIZE = 24;    // Multiple of cubic & quad curve size | 
 |  | 
 |     float squareflat;           // Square of the flatness parameter | 
 |                     // for testing against squared lengths | 
 |  | 
 |     int limit;              // Maximum number of recursion levels | 
 |  | 
 |     float hold[] = new float[14];   // The cache of interpolated coords | 
 |                     // Note that this must be long enough | 
 |                     // to store a full cubic segment and | 
 |                     // a relative cubic segment to avoid | 
 |                     // aliasing when copying the coords | 
 |                     // of a curve to the end of the array. | 
 |                     // This is also serendipitously equal | 
 |                     // to the size of a full quad segment | 
 |                     // and 2 relative quad segments. | 
 |  | 
 |     int holdEnd;            // The index of the last curve segment | 
 |                     // being held for interpolation | 
 |  | 
 |     int holdIndex;          // The index of the curve segment | 
 |                     // that was last interpolated.  This | 
 |                     // is the curve segment ready to be | 
 |                     // returned in the next call to | 
 |                     // currentSegment(). | 
 |  | 
 |     int levels[];           // The recursion level at which | 
 |                     // each curve being held in storage | 
 |                     // was generated. | 
 |  | 
 |     int levelIndex;         // The index of the entry in the | 
 |                     // levels array of the curve segment | 
 |                     // at the holdIndex | 
 |  | 
 |     public static void subdivide(float src[], int srcoff, | 
 |                                  float left[], int leftoff, | 
 |                                  float right[], int rightoff) | 
 |     { | 
 |         float x1 = src[srcoff + 0]; | 
 |         float y1 = src[srcoff + 1]; | 
 |         float ctrlx = src[srcoff + 2]; | 
 |         float ctrly = src[srcoff + 3]; | 
 |         float x2 = src[srcoff + 4]; | 
 |         float y2 = src[srcoff + 5]; | 
 |         if (left != null) { | 
 |             left[leftoff + 0] = x1; | 
 |             left[leftoff + 1] = y1; | 
 |         } | 
 |         if (right != null) { | 
 |             right[rightoff + 4] = x2; | 
 |             right[rightoff + 5] = y2; | 
 |         } | 
 |         x1 = (x1 + ctrlx) / 2f; | 
 |         y1 = (y1 + ctrly) / 2f; | 
 |         x2 = (x2 + ctrlx) / 2f; | 
 |         y2 = (y2 + ctrly) / 2f; | 
 |         ctrlx = (x1 + x2) / 2f; | 
 |         ctrly = (y1 + y2) / 2f; | 
 |         if (left != null) { | 
 |             left[leftoff + 2] = x1; | 
 |             left[leftoff + 3] = y1; | 
 |             left[leftoff + 4] = ctrlx; | 
 |             left[leftoff + 5] = ctrly; | 
 |         } | 
 |         if (right != null) { | 
 |             right[rightoff + 0] = ctrlx; | 
 |             right[rightoff + 1] = ctrly; | 
 |             right[rightoff + 2] = x2; | 
 |             right[rightoff + 3] = y2; | 
 |         } | 
 |     } | 
 |  | 
 |     public static double getFlatnessSq(float coords[], int offset) { | 
 |         return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1], | 
 |                                   coords[offset + 4], coords[offset + 5], | 
 |                                   coords[offset + 2], coords[offset + 3]); | 
 |     } | 
 |  | 
 |     public Test7047069() { | 
 |         this.squareflat = .0001f * .0001f; | 
 |         holdIndex = hold.length - 6; | 
 |         holdEnd = hold.length - 2; | 
 |         hold[holdIndex + 0] = (float) (Math.random() * 100); | 
 |         hold[holdIndex + 1] = (float) (Math.random() * 100); | 
 |         hold[holdIndex + 2] = (float) (Math.random() * 100); | 
 |         hold[holdIndex + 3] = (float) (Math.random() * 100); | 
 |         hold[holdIndex + 4] = (float) (Math.random() * 100); | 
 |         hold[holdIndex + 5] = (float) (Math.random() * 100); | 
 |         levelIndex = 0; | 
 |         this.limit = 10; | 
 |         this.levels = new int[limit + 1]; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Ensures that the hold array can hold up to (want) more values. | 
 |      * It is currently holding (hold.length - holdIndex) values. | 
 |      */ | 
 |     void ensureHoldCapacity(int want) { | 
 |         if (holdIndex - want < 0) { | 
 |             int have = hold.length - holdIndex; | 
 |             int newsize = hold.length + GROW_SIZE; | 
 |             float newhold[] = new float[newsize]; | 
 |             System.arraycopy(hold, holdIndex, | 
 |                      newhold, holdIndex + GROW_SIZE, | 
 |                      have); | 
 |             if (verbose) System.err.println("old hold = "+hold+"["+hold.length+"]"); | 
 |             if (verbose) System.err.println("replacement hold = "+newhold+"["+newhold.length+"]"); | 
 |             hold = newhold; | 
 |             if (verbose) System.err.println("new hold = "+hold+"["+hold.length+"]"); | 
 |             if (verbose) System.err.println("replacement hold still = "+newhold+"["+newhold.length+"]"); | 
 |             holdIndex += GROW_SIZE; | 
 |             holdEnd += GROW_SIZE; | 
 |         } | 
 |     } | 
 |  | 
 |     private boolean next() { | 
 |         if (holdIndex >= holdEnd) { | 
 |             return false; | 
 |         } | 
 |  | 
 |         int level = levels[levelIndex]; | 
 |         while (level < limit) { | 
 |             if (getFlatnessSq(hold, holdIndex) < squareflat) { | 
 |                 break; | 
 |             } | 
 |  | 
 |             ensureHoldCapacity(4); | 
 |             subdivide(hold, holdIndex, | 
 |                       hold, holdIndex - 4, | 
 |                       hold, holdIndex); | 
 |             holdIndex -= 4; | 
 |  | 
 |             // Now that we have subdivided, we have constructed | 
 |             // two curves of one depth lower than the original | 
 |             // curve.  One of those curves is in the place of | 
 |             // the former curve and one of them is in the next | 
 |             // set of held coordinate slots.  We now set both | 
 |             // curves level values to the next higher level. | 
 |             level++; | 
 |             levels[levelIndex] = level; | 
 |             levelIndex++; | 
 |             levels[levelIndex] = level; | 
 |         } | 
 |  | 
 |         // This curve segment is flat enough, or it is too deep | 
 |         // in recursion levels to try to flatten any more.  The | 
 |         // two coordinates at holdIndex+4 and holdIndex+5 now | 
 |         // contain the endpoint of the curve which can be the | 
 |         // endpoint of an approximating line segment. | 
 |         holdIndex += 4; | 
 |         levelIndex--; | 
 |         return true; | 
 |     } | 
 |  | 
 |     public static void main(String argv[]) { | 
 |         verbose = (argv.length > 0); | 
 |         for (int i = 0; i < 100000; i++) { | 
 |             Test7047069 st = new Test7047069(); | 
 |             while (st.next()) {} | 
 |         } | 
 |     } | 
 | } |