1 7 8 package java.awt; 9 10 import java.awt.MultipleGradientPaint.CycleMethod ; 11 import java.awt.MultipleGradientPaint.ColorSpaceType ; 12 import java.awt.geom.AffineTransform ; 13 import java.awt.geom.Rectangle2D ; 14 import java.awt.image.ColorModel ; 15 16 25 final class RadialGradientPaintContext extends MultipleGradientPaintContext { 26 27 28 private boolean isSimpleFocus = false; 29 30 31 private boolean isNonCyclic = false; 32 33 34 private float radius; 35 36 37 private float centerX, centerY, focusX, focusY; 38 39 40 private float radiusSq; 41 42 43 private float constA, constB; 44 45 46 private float gDeltaDelta; 47 48 52 private float trivial; 53 54 55 private static final float SCALEBACK = .99f; 56 57 91 RadialGradientPaintContext(RadialGradientPaint paint, 92 ColorModel cm, 93 Rectangle deviceBounds, 94 Rectangle2D userBounds, 95 AffineTransform t, 96 RenderingHints hints, 97 float cx, float cy, 98 float r, 99 float fx, float fy, 100 float[] fractions, 101 Color [] colors, 102 CycleMethod cycleMethod, 103 ColorSpaceType colorSpace) 104 { 105 super(paint, cm, deviceBounds, userBounds, t, hints, 106 fractions, colors, cycleMethod, colorSpace); 107 108 centerX = cx; 110 centerY = cy; 111 focusX = fx; 112 focusY = fy; 113 radius = r; 114 115 this.isSimpleFocus = (focusX == centerX) && (focusY == centerY); 116 this.isNonCyclic = (cycleMethod == CycleMethod.NO_CYCLE); 117 118 radiusSq = radius * radius; 120 121 float dX = focusX - centerX; 122 float dY = focusY - centerY; 123 124 double distSq = (dX * dX) + (dY * dY); 125 126 if (distSq > radiusSq * SCALEBACK) { 128 float scalefactor = (float)Math.sqrt(radiusSq * SCALEBACK / distSq); 130 dX = dX * scalefactor; 131 dY = dY * scalefactor; 132 focusX = centerX + dX; 133 focusY = centerY + dY; 134 } 135 136 trivial = (float)Math.sqrt(radiusSq - (dX * dX)); 139 140 constA = a02 - centerX; 142 constB = a12 - centerY; 143 144 gDeltaDelta = 2 * ( a00 * a00 + a10 * a10) / radiusSq; 146 } 147 148 155 protected void fillRaster(int pixels[], int off, int adjust, 156 int x, int y, int w, int h) 157 { 158 if (isSimpleFocus && isNonCyclic && isSimpleLookup) { 159 simpleNonCyclicFillRaster(pixels, off, adjust, x, y, w, h); 160 } else { 161 cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h); 162 } 163 } 164 165 170 private void simpleNonCyclicFillRaster(int pixels[], int off, int adjust, 171 int x, int y, int w, int h) 172 { 173 207 float rowX = (a00*x) + (a01*y) + constA; 209 float rowY = (a10*x) + (a11*y) + constB; 210 211 float gDeltaDelta = this.gDeltaDelta; 213 214 adjust += w; 216 217 int rgbclip = gradient[fastGradientArraySize]; 219 220 for (int j = 0; j < h; j++) { 221 float gRel = (rowX * rowX + rowY * rowY) / radiusSq; 223 float gDelta = (2 * ( a00 * rowX + a10 * rowY) / radiusSq + 224 gDeltaDelta/2); 225 226 241 int i = 0; 242 while (i < w && gRel >= 1.0f) { 244 pixels[off + i] = rgbclip; 245 gRel += gDelta; 246 gDelta += gDeltaDelta; 247 i++; 248 } 249 while (i < w && gRel < 1.0f) { 251 int gIndex; 252 253 if (gRel <= 0) { 254 gIndex = 0; 255 } else { 256 float fIndex = gRel * SQRT_LUT_SIZE; 257 int iIndex = (int) (fIndex); 258 float s0 = sqrtLut[iIndex]; 259 float s1 = sqrtLut[iIndex+1] - s0; 260 fIndex = s0 + (fIndex - iIndex) * s1; 261 gIndex = (int) (fIndex * fastGradientArraySize); 262 } 263 264 pixels[off + i] = gradient[gIndex]; 266 267 gRel += gDelta; 269 gDelta += gDeltaDelta; 270 i++; 271 } 272 while (i < w) { 274 pixels[off + i] = rgbclip; 275 i++; 276 } 277 278 off += adjust; 279 rowX += a01; 280 rowY += a11; 281 } 282 } 283 284 private static final int SQRT_LUT_SIZE = (1 << 11); 286 private static float sqrtLut[] = new float[SQRT_LUT_SIZE+1]; 287 static { 288 for (int i = 0; i < sqrtLut.length; i++) { 289 sqrtLut[i] = (float) Math.sqrt(i / ((float) SQRT_LUT_SIZE)); 290 } 291 } 292 293 312 private void cyclicCircularGradientFillRaster(int pixels[], int off, 313 int adjust, 314 int x, int y, 315 int w, int h) 316 { 317 final double constC = 319 -radiusSq + (centerX * centerX) + (centerY * centerY); 320 321 double A, B, C; 323 324 double slope, yintcpt; 326 327 double solutionX, solutionY; 329 330 final float constX = (a00*x) + (a01*y) + a02; 332 final float constY = (a10*x) + (a11*y) + a12; 333 334 final float precalc2 = 2 * centerY; 336 final float precalc3 = -2 * centerX; 337 338 float g; 340 341 float det; 343 344 float currentToFocusSq; 346 347 float intersectToFocusSq; 349 350 float deltaXSq, deltaYSq; 352 353 int indexer = off; 355 356 int pixInc = w+adjust; 358 359 for (int j = 0; j < h; j++) { 361 362 float X = (a01*j) + constX; 364 float Y = (a11*j) + constY; 365 366 for (int i = 0; i < w; i++) { 368 369 if (X == focusX) { 370 solutionX = focusX; 372 solutionY = centerY; 373 solutionY += (Y > focusY) ? trivial : -trivial; 374 } else { 375 slope = (Y - focusY) / (X - focusX); 377 yintcpt = Y - (slope * X); 378 379 A = (slope * slope) + 1; 382 B = precalc3 + (-2 * slope * (centerY - yintcpt)); 383 C = constC + (yintcpt* (yintcpt - precalc2)); 384 385 det = (float)Math.sqrt((B * B) - (4 * A * C)); 386 solutionX = -B; 387 388 solutionX += (X < focusX)? -det : det; 391 solutionX = solutionX / (2 * A); solutionY = (slope * solutionX) + yintcpt; 393 } 394 395 400 deltaXSq = X - focusX; 401 deltaXSq = deltaXSq * deltaXSq; 402 403 deltaYSq = Y - focusY; 404 deltaYSq = deltaYSq * deltaYSq; 405 406 currentToFocusSq = deltaXSq + deltaYSq; 407 408 deltaXSq = (float)solutionX - focusX; 409 deltaXSq = deltaXSq * deltaXSq; 410 411 deltaYSq = (float)solutionY - focusY; 412 deltaYSq = deltaYSq * deltaYSq; 413 414 intersectToFocusSq = deltaXSq + deltaYSq; 415 416 g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq); 419 420 pixels[indexer + i] = indexIntoGradientsArrays(g); 422 423 X += a00; 425 Y += a10; 426 } 428 indexer += pixInc; 429 } } 431 } 432
| Popular Tags
|