1 /* 2 * Copyright (c) 1997, 2003, 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 ellipse 32 * through the PathIterator interface. 33 * 34 * @author Jim Graham 35 */ 36 class EllipseIterator implements PathIterator { 37 double x, y, w, h; 38 AffineTransform affine; 39 int index; 40 41 EllipseIterator(Ellipse2D e, AffineTransform at) { 42 this.x = e.getX(); 43 this.y = e.getY(); 44 this.w = e.getWidth(); 45 this.h = e.getHeight(); 46 this.affine = at; 47 if (w < 0 || h < 0) { 48 index = 6; 49 } 50 } 51 52 /** 53 * Return the winding rule for determining the insideness of the 54 * path. 55 * @see #WIND_EVEN_ODD 56 * @see #WIND_NON_ZERO 57 */ 58 public int getWindingRule() { 59 return WIND_NON_ZERO; 60 } 61 62 /** 63 * Tests if there are more points to read. 64 * @return true if there are more points to read 65 */ 66 public boolean isDone() { 67 return index > 5; 68 } 69 70 /** 71 * Moves the iterator to the next segment of the path forwards 72 * along the primary direction of traversal as long as there are 73 * more points in that direction. 74 */ 75 public void next() { 76 index++; 77 } 78 79 // ArcIterator.btan(Math.PI/2) 80 public static final double CtrlVal = 0.5522847498307933; 81 82 /* 83 * ctrlpts contains the control points for a set of 4 cubic 84 * bezier curves that approximate a circle of radius 0.5 85 * centered at 0.5, 0.5 86 */ 87 private static final double pcv = 0.5 + CtrlVal * 0.5; 88 private static final double ncv = 0.5 - CtrlVal * 0.5; 89 private static double ctrlpts[][] = { 90 { 1.0, pcv, pcv, 1.0, 0.5, 1.0 }, 91 { ncv, 1.0, 0.0, pcv, 0.0, 0.5 }, 92 { 0.0, ncv, ncv, 0.0, 0.5, 0.0 }, 93 { pcv, 0.0, 1.0, ncv, 1.0, 0.5 } 94 }; 95 96 /** 97 * Returns the coordinates and type of the current path segment in 98 * the iteration. 99 * The return value is the path segment type: 100 * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. 101 * A float array of length 6 must be passed in and may be used to 102 * store the coordinates of the point(s). 103 * Each point is stored as a pair of float x,y coordinates. 104 * SEG_MOVETO and SEG_LINETO types will return one point, 105 * SEG_QUADTO will return two points, 106 * SEG_CUBICTO will return 3 points 107 * and SEG_CLOSE will not return any points. 108 * @see #SEG_MOVETO 109 * @see #SEG_LINETO 110 * @see #SEG_QUADTO 111 * @see #SEG_CUBICTO 112 * @see #SEG_CLOSE 113 */ 114 public int currentSegment(float[] coords) { 115 if (isDone()) { 116 throw new NoSuchElementException("ellipse iterator out of bounds"); 117 } 118 if (index == 5) { 119 return SEG_CLOSE; 120 } 121 if (index == 0) { 122 double ctrls[] = ctrlpts[3]; 123 coords[0] = (float) (x + ctrls[4] * w); 124 coords[1] = (float) (y + ctrls[5] * h); 125 if (affine != null) { 126 affine.transform(coords, 0, coords, 0, 1); 127 } 128 return SEG_MOVETO; 129 } 130 double ctrls[] = ctrlpts[index - 1]; 131 coords[0] = (float) (x + ctrls[0] * w); 132 coords[1] = (float) (y + ctrls[1] * h); 133 coords[2] = (float) (x + ctrls[2] * w); 134 coords[3] = (float) (y + ctrls[3] * h); 135 coords[4] = (float) (x + ctrls[4] * w); 136 coords[5] = (float) (y + ctrls[5] * h); 137 if (affine != null) { 138 affine.transform(coords, 0, coords, 0, 3); 139 } 140 return SEG_CUBICTO; 141 } 142 143 /** 144 * Returns the coordinates and type of the current path segment in 145 * the iteration. 146 * The return value is the path segment type: 147 * SEG_MOVETO, SEG_LINETO, SEG_QUADTO, SEG_CUBICTO, or SEG_CLOSE. 148 * A double array of length 6 must be passed in and may be used to 149 * store the coordinates of the point(s). 150 * Each point is stored as a pair of double x,y coordinates. 151 * SEG_MOVETO and SEG_LINETO types will return one point, 152 * SEG_QUADTO will return two points, 153 * SEG_CUBICTO will return 3 points 154 * and SEG_CLOSE will not return any points. 155 * @see #SEG_MOVETO 156 * @see #SEG_LINETO 157 * @see #SEG_QUADTO 158 * @see #SEG_CUBICTO 159 * @see #SEG_CLOSE 160 */ 161 public int currentSegment(double[] coords) { 162 if (isDone()) { 163 throw new NoSuchElementException("ellipse iterator out of bounds"); 164 } 165 if (index == 5) { 166 return SEG_CLOSE; 167 } 168 if (index == 0) { 169 double ctrls[] = ctrlpts[3]; 170 coords[0] = x + ctrls[4] * w; 171 coords[1] = y + ctrls[5] * h; 172 if (affine != null) { 173 affine.transform(coords, 0, coords, 0, 1); 174 } 175 return SEG_MOVETO; 176 } 177 double ctrls[] = ctrlpts[index - 1]; 178 coords[0] = x + ctrls[0] * w; 179 coords[1] = y + ctrls[1] * h; 180 coords[2] = x + ctrls[2] * w; 181 coords[3] = y + ctrls[3] * h; 182 coords[4] = x + ctrls[4] * w; 183 coords[5] = y + ctrls[5] * h; 184 if (affine != null) { 185 affine.transform(coords, 0, coords, 0, 3); 186 } 187 return SEG_CUBICTO; 188 } 189 }