--- old/src/share/classes/java/awt/geom/Path2D.java 2015-05-20 10:31:48.679334430 -0700 +++ new/src/share/classes/java/awt/geom/Path2D.java 2015-05-20 10:31:48.539334435 -0700 @@ -101,6 +101,8 @@ static final int INIT_SIZE = 20; static final int EXPAND_MAX = 500; + static final int EXPAND_MAX_COORDS = EXPAND_MAX * 2; + static final int EXPAND_MIN = 10; // ensure > 6 (cubics) /** * Constructs a new empty {@code Path2D} object. @@ -141,6 +143,42 @@ abstract int rectCrossings(double rxmin, double rymin, double rxmax, double rymax); + static byte[] expandPointTypes(byte[] oldPointTypes, int needed) { + final int oldSize = oldPointTypes.length; + final int newSizeMin = oldSize + needed; + if (newSizeMin < oldSize) { + // hard overflow failure - we can't even accommodate + // new items without overflowing + throw new ArrayIndexOutOfBoundsException( + "pointTypes exceeds maximum capacity !"); + } + // growth algorithm computation + int grow = oldSize; + if (grow > EXPAND_MAX) { + grow = Math.max(EXPAND_MAX, oldSize >> 3); // 1/8th min + } else if (grow < EXPAND_MIN) { + grow = EXPAND_MIN; + } + assert grow > 0; + + int newSize = oldSize + grow; + if (newSize < newSizeMin) { + // overflow in growth algorithm computation + newSize = Integer.MAX_VALUE; + } + while (true) { + try { + // try allocating the larger array + return Arrays.copyOf(oldPointTypes, newSize); + } catch (OutOfMemoryError oome) { + if (newSize == newSizeMin) { + throw oome; + } + } + newSize = newSizeMin + (newSize - newSizeMin) / 2; + } + } + /** * The {@code Float} class defines a geometric path with * coordinates stored in single precision floating point. @@ -279,31 +317,53 @@ floatCoords[coordindex+1]); } + @Override void needRoom(boolean needMove, int newCoords) { - if (needMove && numTypes == 0) { + if ((numTypes == 0) && needMove) { throw new IllegalPathStateException("missing initial moveto "+ "in path definition"); } - int size = pointTypes.length; - if (numTypes >= size) { - int grow = size; - if (grow > EXPAND_MAX) { - grow = EXPAND_MAX; - } else if (grow == 0) { - grow = 1; - } - pointTypes = Arrays.copyOf(pointTypes, size+grow); + if (numTypes >= pointTypes.length) { + pointTypes = expandPointTypes(pointTypes, 1); } - size = floatCoords.length; - if (numCoords + newCoords > size) { - int grow = size; - if (grow > EXPAND_MAX * 2) { - grow = EXPAND_MAX * 2; - } - if (grow < newCoords) { - grow = newCoords; + if (numCoords > (floatCoords.length - newCoords)) { + floatCoords = expandCoords(floatCoords, newCoords); + } + } + + static float[] expandCoords(float[] oldCoords, int needed) { + final int oldSize = oldCoords.length; + final int newSizeMin = oldSize + needed; + if (newSizeMin < oldSize) { + // hard overflow failure - we can't even accommodate + // new items without overflowing + throw new ArrayIndexOutOfBoundsException( + "coords exceeds maximum capacity !"); + } + // growth algorithm computation + int grow = oldSize; + if (grow > EXPAND_MAX_COORDS) { + grow = Math.max(EXPAND_MAX_COORDS, oldSize >> 3); // 1/8th min + } else if (grow < EXPAND_MIN) { + grow = EXPAND_MIN; + } + assert grow > needed; + + int newSize = oldSize + grow; + if (newSize < newSizeMin) { + // overflow in growth algorithm computation + newSize = Integer.MAX_VALUE; + } + while (true) { + try { + // try allocating the larger array + return Arrays.copyOf(oldCoords, newSize); + } catch (OutOfMemoryError oome) { + if (newSize == newSizeMin) { + throw oome; + } } - floatCoords = Arrays.copyOf(floatCoords, size+grow); + newSize = newSizeMin + (newSize - newSizeMin) / 2; } } @@ -1126,31 +1186,53 @@ doubleCoords[coordindex+1]); } + @Override void needRoom(boolean needMove, int newCoords) { - if (needMove && numTypes == 0) { + if ((numTypes == 0) && needMove) { throw new IllegalPathStateException("missing initial moveto "+ "in path definition"); } - int size = pointTypes.length; - if (numTypes >= size) { - int grow = size; - if (grow > EXPAND_MAX) { - grow = EXPAND_MAX; - } else if (grow == 0) { - grow = 1; - } - pointTypes = Arrays.copyOf(pointTypes, size+grow); + if (numTypes >= pointTypes.length) { + pointTypes = expandPointTypes(pointTypes, 1); } - size = doubleCoords.length; - if (numCoords + newCoords > size) { - int grow = size; - if (grow > EXPAND_MAX * 2) { - grow = EXPAND_MAX * 2; - } - if (grow < newCoords) { - grow = newCoords; + if (numCoords > (doubleCoords.length - newCoords)) { + doubleCoords = expandCoords(doubleCoords, newCoords); + } + } + + static double[] expandCoords(double[] oldCoords, int needed) { + final int oldSize = oldCoords.length; + final int newSizeMin = oldSize + needed; + if (newSizeMin < oldSize) { + // hard overflow failure - we can't even accommodate + // new items without overflowing + throw new ArrayIndexOutOfBoundsException( + "coords exceeds maximum capacity !"); + } + // growth algorithm computation + int grow = oldSize; + if (grow > EXPAND_MAX_COORDS) { + grow = Math.max(EXPAND_MAX_COORDS, oldSize >> 3); // 1/8th min + } else if (grow < EXPAND_MIN) { + grow = EXPAND_MIN; + } + assert grow > needed; + + int newSize = oldSize + grow; + if (newSize < newSizeMin) { + // overflow in growth algorithm computation + newSize = Integer.MAX_VALUE; + } + while (true) { + try { + // try allocating the larger array + return Arrays.copyOf(oldCoords, newSize); + } catch (OutOfMemoryError oome) { + if (newSize == newSizeMin) { + throw oome; + } } - doubleCoords = Arrays.copyOf(doubleCoords, size+grow); + newSize = newSizeMin + (newSize - newSizeMin) / 2; } }