1 /* 2 * Copyright (c) 1997, 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 23 * questions. 24 */ 25 26 package java.awt.geom; 27 28 import java.util.*; 29 30 /** 31 * A utility class to iterate over the path segments of an rounded rectangle 32 * through the PathIterator interface. 33 * 34 * @author Jim Graham 35 */ 36 class RoundRectIterator implements PathIterator { 37 double x, y, w, h, aw, ah; 38 AffineTransform affine; 39 int index; 40 41 RoundRectIterator(RoundRectangle2D rr, AffineTransform at) { 42 this.x = rr.getX(); 43 this.y = rr.getY(); 44 this.w = rr.getWidth(); 45 this.h = rr.getHeight(); 46 this.aw = Math.min(w, Math.abs(rr.getArcWidth())); 47 this.ah = Math.min(h, Math.abs(rr.getArcHeight())); 48 this.affine = at; 49 if (aw < 0 || ah < 0) { 50 // Don't draw anything... 51 index = ctrlpts.length; 52 } 53 } 54 55 /** 56 * Return the winding rule for determining the insideness of the 57 * path. 58 * @see #WIND_EVEN_ODD 59 * @see #WIND_NON_ZERO 60 */ 61 public int getWindingRule() { 62 return WIND_NON_ZERO; 63 } 64 65 /** 66 * Tests if there are more points to read. 67 * @return true if there are more points to read 68 */ 69 public boolean isDone() { 70 return index >= ctrlpts.length; 71 } 72 73 /** 74 * Moves the iterator to the next segment of the path forwards 75 * along the primary direction of traversal as long as there are 76 * more points in that direction. 77 */ 78 public void next() { 79 index++; 80 } 81 82 private static final double angle = Math.PI / 4.0; 83 private static final double a = 1.0 - Math.cos(angle); 84 private static final double b = Math.tan(angle); 85 private static final double c = Math.sqrt(1.0 + b * b) - 1 + a; 86 private static final double cv = 4.0 / 3.0 * a * b / c; 87 private static final double acv = (1.0 - cv) / 2.0; 88 89 // For each array: 90 // 4 values for each point {v0, v1, v2, v3}: 91 // point = (x + v0 * w + v1 * arcWidth, 92 // y + v2 * h + v3 * arcHeight); 93 private static double ctrlpts[][] = { 94 { 0.0, 0.0, 0.0, 0.5 }, 95 { 0.0, 0.0, 1.0, -0.5 }, 96 { 0.0, 0.0, 1.0, -acv, 97 0.0, acv, 1.0, 0.0, 98 0.0, 0.5, 1.0, 0.0 }, 99 { 1.0, -0.5, 1.0, 0.0 }, 100 { 1.0, -acv, 1.0, 0.0, 101 1.0, 0.0, 1.0, -acv, 102 1.0, 0.0, 1.0, -0.5 }, 103 { 1.0, 0.0, 0.0, 0.5 }, 104 { 1.0, 0.0, 0.0, acv, 105 1.0, -acv, 0.0, 0.0, 106 1.0, -0.5, 0.0, 0.0 }, 107 { 0.0, 0.5, 0.0, 0.0 }, 108 { 0.0, acv, 0.0, 0.0, 109 0.0, 0.0, 0.0, acv, 110 0.0, 0.0, 0.0, 0.5 }, 111 {}, 112 }; 113 private static int types[] = { 114 SEG_MOVETO, 115 SEG_LINETO, SEG_CUBICTO, 116 SEG_LINETO, SEG_CUBICTO, 117 SEG_LINETO, SEG_CUBICTO, 118 SEG_LINETO, SEG_CUBICTO, 119 SEG_CLOSE, 120 }; 121 122 /** 123 * Returns the coordinates and type of the current path segment in 124 * the iteration. 125 * The return value is the path segment type: 126 * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. 127 * A float array of length 6 must be passed in and may be used to 128 * store the coordinates of the point(s). 129 * Each point is stored as a pair of float x,y coordinates. 130 * SEG_MOVETO and SEG_LINETO types will return one point, 131 * SEG_QUADTO will return two points, 132 * SEG_CUBICTO will return 3 points 133 * and SEG_CLOSE will not return any points. 134 * @see #SEG_MOVETO 135 * @see #SEG_LINETO 136 * @see #SEG_QUADTO 137 * @see #SEG_CUBICTO 138 * @see #SEG_CLOSE 139 */ 140 public int currentSegment(float[] coords) { 141 if (isDone()) { 142 throw new NoSuchElementException("roundrect iterator out of bounds"); 143 } 144 double ctrls[] = ctrlpts[index]; 145 int nc = 0; 146 for (int i = 0; i < ctrls.length; i += 4) { 147 coords[nc++] = (float) (x + ctrls[i + 0] * w + ctrls[i + 1] * aw); 148 coords[nc++] = (float) (y + ctrls[i + 2] * h + ctrls[i + 3] * ah); 149 } 150 if (affine != null) { 151 affine.transform(coords, 0, coords, 0, nc / 2); 152 } 153 return types[index]; 154 } 155 156 /** 157 * Returns the coordinates and type of the current path segment in 158 * the iteration. 159 * The return value is the path segment type: 160 * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. 161 * A double array of length 6 must be passed in and may be used to 162 * store the coordinates of the point(s). 163 * Each point is stored as a pair of double x,y coordinates. 164 * SEG_MOVETO and SEG_LINETO types will return one point, 165 * SEG_QUADTO will return two points, 166 * SEG_CUBICTO will return 3 points 167 * and SEG_CLOSE will not return any points. 168 * @see #SEG_MOVETO 169 * @see #SEG_LINETO 170 * @see #SEG_QUADTO 171 * @see #SEG_CUBICTO 172 * @see #SEG_CLOSE 173 */ 174 public int currentSegment(double[] coords) { 175 if (isDone()) { 176 throw new NoSuchElementException("roundrect iterator out of bounds"); 177 } 178 double ctrls[] = ctrlpts[index]; 179 int nc = 0; 180 for (int i = 0; i < ctrls.length; i += 4) { 181 coords[nc++] = (x + ctrls[i + 0] * w + ctrls[i + 1] * aw); 182 coords[nc++] = (y + ctrls[i + 2] * h + ctrls[i + 3] * ah); 183 } 184 if (affine != null) { 185 affine.transform(coords, 0, coords, 0, nc / 2); 186 } 187 return types[index]; 188 } 189 }