1 18 package org.apache.batik.ext.awt; 19 20 import java.awt.Color ; 21 import java.awt.Rectangle ; 22 import java.awt.RenderingHints ; 23 import java.awt.geom.AffineTransform ; 24 import java.awt.geom.NoninvertibleTransformException ; 25 import java.awt.geom.Point2D ; 26 import java.awt.geom.Rectangle2D ; 27 import java.awt.image.ColorModel ; 28 29 40 final class LinearGradientPaintContext extends MultipleGradientPaintContext { 41 42 47 private float dgdX, dgdY, gc, pixSz; 48 49 private static final int DEFAULT_IMPL = 1; 50 private static final int ANTI_ALIAS_IMPL = 3; 51 52 private int fillMethod; 53 54 87 public LinearGradientPaintContext(ColorModel cm, 88 Rectangle deviceBounds, 89 Rectangle2D userBounds, 90 AffineTransform t, 91 RenderingHints hints, 92 Point2D dStart, 93 Point2D dEnd, 94 float[] fractions, 95 Color [] colors, 96 MultipleGradientPaint.CycleMethodEnum 97 cycleMethod, 98 MultipleGradientPaint.ColorSpaceEnum 99 colorSpace) 100 throws NoninvertibleTransformException 101 { 102 super(cm, deviceBounds, userBounds, t, hints, fractions, 103 colors, cycleMethod, colorSpace); 104 105 Point2D.Float start = new Point2D.Float ((float)dStart.getX(), 107 (float)dStart.getY()); 108 Point2D.Float end = new Point2D.Float ((float)dEnd.getX(), 109 (float)dEnd.getY()); 110 111 120 float dx = end.x - start.x; float dy = end.y - start.y; float dSq = dx*dx + dy*dy; 124 float constX = dx/dSq; 126 float constY = dy/dSq; 127 128 dgdX = a00*constX + a10*constY; 130 dgdY = a01*constX + a11*constY; 132 133 float dgdXAbs = Math.abs(dgdX); 134 float dgdYAbs = Math.abs(dgdY); 135 if (dgdXAbs > dgdYAbs) pixSz = dgdXAbs; 136 else pixSz = dgdYAbs; 137 138 gc = (a02-start.x)*constX + (a12-start.y)*constY; 140 141 Object colorRend = hints.get(RenderingHints.KEY_COLOR_RENDERING); 142 Object rend = hints.get(RenderingHints.KEY_RENDERING); 143 144 fillMethod = DEFAULT_IMPL; 145 146 if ((cycleMethod == MultipleGradientPaint.REPEAT) || 147 hasDiscontinuity) { 148 if (rend == RenderingHints.VALUE_RENDER_QUALITY) 149 fillMethod = ANTI_ALIAS_IMPL; 150 if (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED) 152 fillMethod = DEFAULT_IMPL; 153 else if (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY) 154 fillMethod = ANTI_ALIAS_IMPL; 155 } 156 } 157 158 protected void fillHardNoCycle(int[] pixels, int off, int adjust, 159 int x, int y, int w, int h) { 160 161 final float initConst = (dgdX*x) + gc; 163 164 for(int i=0; i<h; i++) { float g = initConst + dgdY*(y+i); 167 final int rowLimit = off+w; 169 if (dgdX == 0) { 170 final int val; 172 if (g <= 0) 173 val = gradientUnderflow; 174 else if (g >= 1) 175 val = gradientOverflow; 176 else { 177 int gradIdx = 0; 179 while (gradIdx < gradientsLength-1) { 180 if (g < fractions[gradIdx+1]) 181 break; 182 gradIdx++; 183 } 184 float delta = (g-fractions[gradIdx]); 185 float idx = ((delta*GRADIENT_SIZE_INDEX) 186 /normalizedIntervals[gradIdx])+0.5f; 187 val = gradients[gradIdx][(int)idx]; 188 } 189 190 while (off < rowLimit) { 191 pixels[off++] = val; 192 } 193 } else { 194 int gradSteps; 196 int preGradSteps; 197 final int preVal, postVal; 198 199 float gradStepsF; 200 float preGradStepsF; 201 if (dgdX >= 0) { 202 gradStepsF = ((1-g)/dgdX); 203 preGradStepsF = (float)Math.ceil((0-g)/dgdX); 204 preVal = gradientUnderflow; 205 postVal = gradientOverflow; 206 } else { gradStepsF = ((0-g)/dgdX); 208 preGradStepsF = (float)Math.ceil((1-g)/dgdX); 209 preVal = gradientOverflow; 210 postVal = gradientUnderflow; 211 } 212 213 if (gradStepsF > w) gradSteps = w; 214 else gradSteps = (int)gradStepsF; 215 if (preGradStepsF > w) preGradSteps = w; 216 else preGradSteps = (int)preGradStepsF; 217 218 final int gradLimit = off + gradSteps; 219 if (preGradSteps > 0) { 220 final int preGradLimit = off + preGradSteps; 221 222 while (off < preGradLimit) { 223 pixels[off++] = preVal; 224 } 225 g += dgdX*preGradSteps; 226 } 227 228 if (dgdX > 0) { 229 int gradIdx = 0; 231 while (gradIdx < gradientsLength-1) { 232 if (g < fractions[gradIdx+1]) 233 break; 234 gradIdx++; 235 } 236 237 while (off < gradLimit) { 238 float delta = (g-fractions[gradIdx]); 239 final int [] grad = gradients[gradIdx]; 240 241 double stepsD = Math.ceil 242 ((fractions[gradIdx+1]-g)/dgdX); 243 int steps; 244 if (stepsD > w) steps = w; 245 else steps = (int)stepsD; 246 int subGradLimit = off + steps; 247 if (subGradLimit > gradLimit) 248 subGradLimit = gradLimit; 249 250 int idx = (int)(((delta*GRADIENT_SIZE_INDEX) 251 /normalizedIntervals[gradIdx]) 252 *(1<<16)) + (1<<15); 253 int step = (int)(((dgdX*GRADIENT_SIZE_INDEX) 254 /normalizedIntervals[gradIdx]) 255 *(1<<16)); 256 while (off < subGradLimit) { 257 pixels[off++] = grad[idx>>16]; 258 idx += step; 259 } 260 g+=dgdX*stepsD; 261 gradIdx++; 262 } 263 } else { 264 int gradIdx = gradientsLength-1; 266 while (gradIdx > 0) { 267 if (g > fractions[gradIdx]) 268 break; 269 gradIdx--; 270 } 271 272 while (off < gradLimit) { 273 float delta = (g-fractions[gradIdx]); 274 final int [] grad = gradients[gradIdx]; 275 276 double stepsD = Math.ceil(delta/-dgdX); 277 int steps; 278 if (stepsD > w) steps = w; 279 else steps = (int)stepsD; 280 int subGradLimit = off + steps; 281 if (subGradLimit > gradLimit) 282 subGradLimit = gradLimit; 283 284 int idx = (int)(((delta*GRADIENT_SIZE_INDEX) 285 /normalizedIntervals[gradIdx]) 286 *(1<<16)) + (1<<15); 287 int step = (int)(((dgdX*GRADIENT_SIZE_INDEX) 288 /normalizedIntervals[gradIdx]) 289 *(1<<16)); 290 while (off < subGradLimit) { 291 pixels[off++] = grad[idx>>16]; 292 idx += step; 293 } 294 g+=dgdX*stepsD; 295 gradIdx--; 296 } 297 } 298 299 while (off < rowLimit) { 300 pixels[off++] = postVal; 301 } 302 } 303 off += adjust; } 305 } 306 307 protected void fillSimpleNoCycle(int[] pixels, int off, int adjust, 308 int x, int y, int w, int h) { 309 final float initConst = (dgdX*x) + gc; 311 final float step = dgdX*fastGradientArraySize; 312 final int fpStep = (int)(step*(1<<16)); 314 final int [] grad = gradient; 315 316 for(int i=0; i<h; i++){ float g = initConst + dgdY*(y+i); 319 g *= fastGradientArraySize; 320 g += 0.5; 322 final int rowLimit = off+w; 324 float check = dgdX*fastGradientArraySize*w; 325 if (check < 0) check = -check; 326 if (check < .3) { 327 final int val; 329 if (g<=0) 330 val = gradientUnderflow; 331 else if (g>=fastGradientArraySize) 332 val = gradientOverflow; 333 else 334 val = grad[(int)g]; 335 while (off < rowLimit) { 336 pixels[off++] = val; 337 } 338 } else { 339 int gradSteps; 341 int preGradSteps; 342 final int preVal, postVal; 343 if (dgdX > 0) { 344 gradSteps = (int)((fastGradientArraySize-g)/step); 345 preGradSteps = (int)Math.ceil(0-g/step); 346 preVal = gradientUnderflow; 347 postVal = gradientOverflow; 348 349 } else { gradSteps = (int)((0-g)/step); 351 preGradSteps = 352 (int)Math.ceil((fastGradientArraySize-g)/step); 353 preVal = gradientOverflow; 354 postVal = gradientUnderflow; 355 } 356 357 if (gradSteps > w) 358 gradSteps = w; 359 final int gradLimit = off + gradSteps; 360 361 if (preGradSteps > 0) { 362 if (preGradSteps > w) 363 preGradSteps = w; 364 final int preGradLimit = off + preGradSteps; 365 366 while (off < preGradLimit) { 367 pixels[off++] = preVal; 368 } 369 g += step*preGradSteps; 370 } 371 372 int fpG = (int)(g*(1<<16)); 373 while (off < gradLimit) { 374 pixels[off++] = grad[fpG>>16]; 375 fpG += fpStep; 376 } 377 378 while (off < rowLimit) { 379 pixels[off++] = postVal; 380 } 381 } 382 off += adjust; } 384 } 385 386 protected void fillSimpleRepeat(int[] pixels, int off, int adjust, 387 int x, int y, int w, int h) { 388 389 final float initConst = (dgdX*x) + gc; 390 391 float step = (dgdX - (int)dgdX)*fastGradientArraySize; 396 397 if (step < 0) 401 step += fastGradientArraySize; 402 403 final int [] grad = gradient; 404 405 for(int i=0; i<h; i++) { float g = initConst + dgdY*(y+i); 408 409 g = g-(int)g; 411 if (g < 0) 413 g += 1; 414 415 g *= fastGradientArraySize; 417 g += 0.5; final int rowLimit = off+w; while (off < rowLimit) { 420 int idx = (int)g; 421 if (idx >= fastGradientArraySize) { 422 g -= fastGradientArraySize; 423 idx -= fastGradientArraySize; 424 } 425 pixels[off++] = grad[idx]; 426 g += step; 427 } 428 429 off += adjust; } 431 } 432 433 434 protected void fillSimpleReflect(int[] pixels, int off, int adjust, 435 int x, int y, int w, int h) { 436 final float initConst = (dgdX*x) + gc; 437 438 final int [] grad = gradient; 439 440 for (int i=0; i<h; i++) { float g = initConst + dgdY*(y+i); 443 444 g = g - 2*((int)(g/2.0f)); 446 447 float step = dgdX; 448 if (g < 0) { 450 g = -g; step = - step; } 453 454 step = step - 2*((int)step/2.0f); 462 if (step < 0) 463 step += 2.0; 464 final int reflectMax = 2*fastGradientArraySize; 465 466 g *= fastGradientArraySize; 468 g += 0.5; 469 step *= fastGradientArraySize; 470 final int rowLimit = off+w; while (off < rowLimit) { 472 int idx = (int)g; 473 if (idx >= reflectMax) { 474 g -= reflectMax; 475 idx -= reflectMax; 476 } 477 478 if (idx <= fastGradientArraySize) 479 pixels[off++] = grad[idx]; 480 else 481 pixels[off++] = grad[reflectMax-idx]; 482 g+= step; 483 } 484 485 off += adjust; } 487 } 488 489 498 protected void fillRaster(int[] pixels, int off, int adjust, 499 int x, int y, int w, int h) { 500 501 final float initConst = (dgdX*x) + gc; 503 504 if (fillMethod == ANTI_ALIAS_IMPL) { 505 for(int i=0; i<h; i++){ float g = initConst + dgdY*(y+i); 508 509 final int rowLimit = off+w; while(off < rowLimit){ pixels[off++] = indexGradientAntiAlias(g, pixSz); 513 g += dgdX; } 515 off += adjust; } 517 } 518 else if (!isSimpleLookup) { 519 if (cycleMethod == MultipleGradientPaint.NO_CYCLE) { 520 fillHardNoCycle(pixels, off, adjust, x, y, w, h); 521 } 522 else { 523 for(int i=0; i<h; i++){ float g = initConst + dgdY*(y+i); 526 527 final int rowLimit = off+w; while(off < rowLimit){ pixels[off++] = indexIntoGradientsArrays(g); 531 g += dgdX; } 533 off += adjust; } 535 } 536 } else { 537 539 if (cycleMethod == MultipleGradientPaint.NO_CYCLE) 540 fillSimpleNoCycle(pixels, off, adjust, x, y, w, h); 541 else if (cycleMethod == MultipleGradientPaint.REPEAT) 542 fillSimpleRepeat(pixels, off, adjust, x, y, w, h); 543 else fillSimpleReflect(pixels, off, adjust, x, y, w, h); 545 } 546 } 547 548 549 } 550 | Popular Tags |