001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package sec.sun.awt.geom; 006 007import armyc2.c2sd.graphics2d.PathIterator; 008 009/** 010 * 011 * @author Michael Deutch 012 */ 013public class CrossingsObject { 014 015 public static final int CROSSINGS = 0; 016 public static final int NONZERO = 1; 017 public static final int EVENODD = 2; 018 public static final boolean debug = false; 019 int limit = 0; 020 double yranges[] = new double[10]; 021 double xlo, ylo, xhi, yhi; 022 private int crosscounts[] = null; 023 024 private EvenOdd evenOdd = null; 025 private Crossings crossings = null; 026 private NonZero nonZero = null; 027 int type = -1; 028 029 public CrossingsObject(double xlo, double ylo, double xhi, double yhi, int type) { 030 //super(xlo, ylo, xhi, yhi); 031 this.xlo = xlo; 032 this.ylo = ylo; 033 this.xhi = xhi; 034 this.yhi = yhi; 035 this.type = type; 036 //crosscounts = new int[yranges.length / 2]; 037 switch (type) { 038 case CROSSINGS: 039 crossings = new Crossings(xlo, ylo, xhi, yhi); 040 break; 041 case NONZERO: 042 nonZero = new NonZero(xlo, ylo, xhi, yhi); 043 crosscounts = new int[yranges.length / 2]; 044 break; 045 case EVENODD: 046 evenOdd = new EvenOdd(xlo, ylo, xhi, yhi); 047 break; 048 } 049 } 050 051 public double getXLo() { 052 switch (type) { 053 case CROSSINGS: 054 return crossings.getXLo(); 055 case EVENODD: 056 return evenOdd.getXLo(); 057 case NONZERO: 058 return nonZero.getXLo(); 059 default: 060 return -1; 061 } 062 } 063 064 public double getYLo() { 065 switch (type) { 066 case CROSSINGS: 067 return crossings.getYLo(); 068 case EVENODD: 069 return evenOdd.getYLo(); 070 case NONZERO: 071 return nonZero.getYLo(); 072 default: 073 return -1; 074 } 075 } 076 077 public double getXHi() { 078 //return xhi; 079 switch (type) { 080 case CROSSINGS: 081 return crossings.getXHi(); 082 case EVENODD: 083 return evenOdd.getXHi(); 084 case NONZERO: 085 return nonZero.getXHi(); 086 default: 087 return -1; 088 } 089 } 090 091 public double getYHi() { 092 //return yhi; 093 switch (type) { 094 case CROSSINGS: 095 return crossings.getYHi(); 096 case EVENODD: 097 return evenOdd.getYHi(); 098 case NONZERO: 099 return nonZero.getYHi(); 100 default: 101 return -1; 102 } 103 } 104 105 public boolean isEmpty() { 106 //return (limit == 0); 107 switch (type) { 108 case CROSSINGS: 109 return crossings.isEmpty(); 110 case EVENODD: 111 return evenOdd.isEmpty(); 112 case NONZERO: 113 return nonZero.isEmpty(); 114 default: 115 return true; 116 } 117 } 118 119 public void record(double ystart, double yend, int direction) { 120 switch (type) { 121 case CROSSINGS: 122 crossings.record(ystart, yend, direction); 123 case EVENODD: 124 evenOdd.record(ystart, yend, direction); 125 case NONZERO: 126 nonZero.record(ystart, yend, direction); 127 default: 128 return; 129 } 130 131 } 132 133 public static CrossingsObject findCrossings(Vector curves, 134 double xlo, double ylo, 135 double xhi, double yhi) { 136 //Crossings cross = new EvenOdd(xlo, ylo, xhi, yhi); 137 CrossingsObject cross = new CrossingsObject(xlo, ylo, xhi, yhi, CrossingsObject.EVENODD); 138 Enumeration enum_ = curves.elements(); 139 while (enum_.hasMoreElements()) { 140 CurveObject c = (CurveObject) enum_.nextElement(); 141 if (c.accumulateCrossings(cross)) { 142 return null; 143 } 144 } 145 return cross; 146 } 147 148 public CrossingsObject findCrossings2(PathIterator pi, 149 double xlo, double ylo, 150 double xhi, double yhi) { 151 CrossingsObject cross; 152 if (pi.getWindingRule() == pi.WIND_EVEN_ODD) { 153 cross = new CrossingsObject(xlo, ylo, xhi, yhi, EVENODD); 154 } else { 155 cross = new CrossingsObject(xlo, ylo, xhi, yhi, NONZERO); 156 } 157 // coords array is big enough for holding: 158 // coordinates returned from currentSegment (6) 159 // OR 160 // two subdivided quadratic curves (2+4+4=10) 161 // AND 162 // 0-1 horizontal splitting parameters 163 // OR 164 // 2 parametric equation derivative coefficients 165 // OR 166 // three subdivided cubic curves (2+6+6+6=20) 167 // AND 168 // 0-2 horizontal splitting parameters 169 // OR 170 // 3 parametric equation derivative coefficients 171 double coords[] = new double[23]; 172 double movx = 0; 173 double movy = 0; 174 double curx = 0; 175 double cury = 0; 176 double newx, newy; 177 while (!pi.isDone()) { 178 int type = pi.currentSegment(coords); 179 switch (type) { 180 case PathIterator.SEG_MOVETO: 181 if (movy != cury 182 && cross.accumulateLine(curx, cury, movx, movy)) { 183 return null; 184 } 185 movx = curx = coords[0]; 186 movy = cury = coords[1]; 187 break; 188 case PathIterator.SEG_LINETO: 189 newx = coords[0]; 190 newy = coords[1]; 191 if (cross.accumulateLine(curx, cury, newx, newy)) { 192 return null; 193 } 194 curx = newx; 195 cury = newy; 196 break; 197 case PathIterator.SEG_QUADTO: 198 newx = coords[2]; 199 newy = coords[3]; 200 if (cross.accumulateQuad(curx, cury, coords)) { 201 return null; 202 } 203 curx = newx; 204 cury = newy; 205 break; 206 case PathIterator.SEG_CUBICTO: 207 newx = coords[4]; 208 newy = coords[5]; 209 if (cross.accumulateCubic(curx, cury, coords)) { 210 return null; 211 } 212 curx = newx; 213 cury = newy; 214 break; 215 case PathIterator.SEG_CLOSE: 216 if (movy != cury 217 && cross.accumulateLine(curx, cury, movx, movy)) { 218 return null; 219 } 220 curx = movx; 221 cury = movy; 222 break; 223 } 224 pi.next(); 225 } 226 if (movy != cury) { 227 if (cross.accumulateLine(curx, cury, movx, movy)) { 228 return null; 229 } 230 } 231 return cross; 232 } 233 234 public boolean accumulateLine(double x0, double y0, 235 double x1, double y1) { 236 switch (this.type) { 237 case CROSSINGS: 238 return crossings.accumulateLine(x0, y0, x1, y1); 239 case EVENODD: 240 return evenOdd.accumulateLine(x0, y0, x1, y1); 241 case NONZERO: 242 return nonZero.accumulateLine(x0, y0, x1, y1); 243 default: 244 return false; 245 } 246 } 247 248 public boolean accumulateLine2(double x0, double y0, 249 double x1, double y1, 250 int direction) { 251 switch (this.type) { 252 case CROSSINGS: 253 return crossings.accumulateLine2(x0, y0, x1, y1, direction); 254 case EVENODD: 255 return evenOdd.accumulateLine2(x0, y0, x1, y1, direction); 256 case NONZERO: 257 return nonZero.accumulateLine2(x0, y0, x1, y1, direction); 258 default: 259 return false; 260 } 261 262 } 263 264 private Vector tmp = new Vector(); 265 266 public boolean accumulateQuad(double x0, double y0, double coords[]) { 267 if (y0 < ylo && coords[1] < ylo && coords[3] < ylo) { 268 return false; 269 } 270 if (y0 > yhi && coords[1] > yhi && coords[3] > yhi) { 271 return false; 272 } 273 if (x0 > xhi && coords[0] > xhi && coords[2] > xhi) { 274 return false; 275 } 276 if (x0 < xlo && coords[0] < xlo && coords[2] < xlo) { 277 if (y0 < coords[3]) { 278 record(Math.max(y0, ylo), Math.min(coords[3], yhi), 1); 279 } else if (y0 > coords[3]) { 280 record(Math.max(coords[3], ylo), Math.min(y0, yhi), -1); 281 } 282 return false; 283 } 284 Curve.insertQuad(tmp, x0, y0, coords); 285 Enumeration enum_ = tmp.elements(); 286 while (enum_.hasMoreElements()) { 287 CurveObject c = (CurveObject) enum_.nextElement(); 288 if (c.accumulateCrossings(this)) { 289 return true; 290 } 291 } 292 tmp.clear(); 293 return false; 294 } 295 296 public boolean accumulateCubic(double x0, double y0, double coords[]) { 297 if (y0 < ylo && coords[1] < ylo 298 && coords[3] < ylo && coords[5] < ylo) { 299 return false; 300 } 301 if (y0 > yhi && coords[1] > yhi 302 && coords[3] > yhi && coords[5] > yhi) { 303 return false; 304 } 305 if (x0 > xhi && coords[0] > xhi 306 && coords[2] > xhi && coords[4] > xhi) { 307 return false; 308 } 309 if (x0 < xlo && coords[0] < xlo 310 && coords[2] < xlo && coords[4] < xlo) { 311 if (y0 <= coords[5]) { 312 record(Math.max(y0, ylo), Math.min(coords[5], yhi), 1); 313 } else { 314 record(Math.max(coords[5], ylo), Math.min(y0, yhi), -1); 315 } 316 return false; 317 } 318 Curve.insertCubic(tmp, x0, y0, coords); 319 Enumeration enum_ = tmp.elements(); 320 while (enum_.hasMoreElements()) { 321 CurveObject c = (CurveObject) enum_.nextElement(); 322 if (c.accumulateCrossings(this)) { 323 return true; 324 } 325 } 326 tmp.clear(); 327 return false; 328 } 329}