KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > RadialGradientPaintContext


1 /*
2
3    Copyright 2001-2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt;
19
20 import java.awt.Color JavaDoc;
21 import java.awt.Rectangle JavaDoc;
22 import java.awt.RenderingHints JavaDoc;
23 import java.awt.geom.AffineTransform JavaDoc;
24 import java.awt.geom.NoninvertibleTransformException JavaDoc;
25 import java.awt.geom.Rectangle2D JavaDoc;
26 import java.awt.image.ColorModel JavaDoc;
27
28 /**
29  * Provides the actual implementation for the RadialGradientPaint.
30  * This is where the pixel processing is done. A RadialGradienPaint
31  * only supports circular gradients, but it should be possible to scale
32  * the circle to look approximately elliptical, by means of a
33  * gradient transform passed into the RadialGradientPaint constructor.
34  *
35  * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
36  * @author <a HREF="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
37  * @version $Id: RadialGradientPaintContext.java,v 1.11 2004/08/18 07:13:41 vhardy Exp $
38  *
39  */

40 final class RadialGradientPaintContext extends MultipleGradientPaintContext {
41     
42     /** True when (focus == center) */
43     private boolean isSimpleFocus = false;
44
45     /** True when (cycleMethod == NO_CYCLE) */
46     private boolean isNonCyclic = false;
47        
48     /** Radius of the outermost circle defining the 100% gradient stop. */
49     private float radius;
50     
51     /** Variables representing center and focus points. */
52     private float centerX, centerY, focusX, focusY;
53
54     /** Radius of the gradient circle squared. */
55     private float radiusSq;
56         
57     /** Constant part of X, Y user space coordinates. */
58     private float constA, constB;
59        
60     /** This value represents the solution when focusX == X. It is called
61      * trivial because it is easier to calculate than the general case.
62      */

63     private float trivial;
64
65     private static final int FIXED_POINT_IMPL = 1;
66     private static final int DEFAULT_IMPL = 2;
67     private static final int ANTI_ALIAS_IMPL = 3;
68
69     private int fillMethod;
70     
71     /** Amount for offset when clamping focus. */
72     private static final float SCALEBACK = .97f;
73     
74     /**
75      * Constructor for RadialGradientPaintContext.
76      *
77      * @param cm {@link ColorModel} that receives
78      * the <code>Paint</code> data. This is used only as a hint.
79      *
80      * @param deviceBounds the device space bounding box of the
81      * graphics primitive being rendered
82      *
83      * @param userBounds the user space bounding box of the
84      * graphics primitive being rendered
85      *
86      * @param t the {@link AffineTransform} from user
87      * space into device space (gradientTransform should be
88      * concatenated with this)
89      *
90      * @param hints the hints that the context object uses to choose
91      * between rendering alternatives
92      *
93      * @param cx the center point in user space of the circle defining
94      * the gradient. The last color of the gradient is mapped to the
95      * perimeter of this circle X coordinate
96      *
97      * @param cy the center point in user space of the circle defining
98      * the gradient. The last color of the gradient is mapped to the
99      * perimeter of this circle Y coordinate
100      *
101      * @param r the radius of the circle defining the extents of the
102      * color gradient
103      *
104      * @param fx the point in user space to which the first color is mapped
105      * X coordinate
106      *
107      * @param fy the point in user space to which the first color is mapped
108      * Y coordinate
109      *
110      * @param fractions the fractions specifying the gradient distribution
111      *
112      * @param colors the gradient colors
113      *
114      * @param cycleMethod either NO_CYCLE, REFLECT, or REPEAT
115      *
116      * @param colorSpace which colorspace to use for interpolation,
117      * either SRGB or LINEAR_RGB
118      *
119      */

120     public RadialGradientPaintContext(ColorModel JavaDoc cm,
121                                       Rectangle JavaDoc deviceBounds,
122                                       Rectangle2D JavaDoc userBounds,
123                                       AffineTransform JavaDoc t,
124                                       RenderingHints JavaDoc hints,
125                                       float cx, float cy,
126                                       float r,
127                                       float fx, float fy,
128                                       float[] fractions,
129                                       Color JavaDoc[] colors,
130                                       MultipleGradientPaint.CycleMethodEnum
131                                       cycleMethod,
132                                       MultipleGradientPaint.ColorSpaceEnum
133                                       colorSpace)
134         throws NoninvertibleTransformException JavaDoc
135     {
136         super(cm, deviceBounds, userBounds, t, hints, fractions, colors,
137               cycleMethod, colorSpace);
138
139         //copy some parameters.
140
centerX = cx;
141         centerY = cy;
142         focusX = fx;
143         focusY = fy;
144         radius = r;
145
146         this.isSimpleFocus = (focusX == centerX) && (focusY == centerY);
147         this.isNonCyclic = (cycleMethod == RadialGradientPaint.NO_CYCLE);
148     
149         //for use in the quadractic equation
150
radiusSq = radius * radius;
151
152         float dX = focusX - centerX;
153         float dY = focusY - centerY;
154
155         double dist = Math.sqrt((dX * dX) + (dY * dY));
156
157         //test if distance from focus to center is greater than the radius
158
if (dist > radius* SCALEBACK) { //clamp focus to radius
159
double angle = Math.atan2(dY, dX);
160             
161           //x = r cos theta, y = r sin theta
162
focusX = (float)(SCALEBACK * radius * Math.cos(angle)) + centerX;
163           
164           focusY = (float)(SCALEBACK * radius * Math.sin(angle)) + centerY;
165         }
166
167         //calculate the solution to be used in the case where X == focusX
168
//in cyclicCircularGradientFillRaster
169
dX = focusX - centerX;
170         trivial = (float)Math.sqrt(radiusSq - (dX * dX));
171
172         // constant parts of X, Y user space coordinates
173
constA = a02 - centerX;
174         constB = a12 - centerY;
175
176         Object JavaDoc colorRend = hints.get(RenderingHints.KEY_COLOR_RENDERING);
177         Object JavaDoc rend = hints.get(RenderingHints.KEY_RENDERING);
178
179         fillMethod = 0;
180
181         if ((rend == RenderingHints.VALUE_RENDER_QUALITY) ||
182             (colorRend == RenderingHints.VALUE_COLOR_RENDER_QUALITY)) {
183             // System.out.println("AAHints set: " + rend + ", " + colorRend);
184
fillMethod = ANTI_ALIAS_IMPL;
185         }
186
187         if ((rend == RenderingHints.VALUE_RENDER_SPEED) ||
188             (colorRend == RenderingHints.VALUE_COLOR_RENDER_SPEED)) {
189             // System.out.println("SPHints set: " + rend + ", " + colorRend);
190
fillMethod = DEFAULT_IMPL;
191         }
192
193         // We are in the 'default' case, no hint or hint set to
194
// DEFAULT values...
195
if (fillMethod == 0) {
196             // For now we will always use the 'default' impl if
197
// one is not specified.
198
fillMethod = DEFAULT_IMPL;
199
200             if (false) {
201                 // This could be used for a 'smart' choice in
202
// the default case, if the gradient has obvious
203
// discontinuites use AA, otherwise default
204
if (hasDiscontinuity) {
205                     fillMethod = ANTI_ALIAS_IMPL;
206                 } else {
207                     fillMethod = DEFAULT_IMPL;
208                 }
209             }
210         }
211
212         if ((fillMethod == DEFAULT_IMPL) &&
213             (isSimpleFocus && isNonCyclic && isSimpleLookup)) {
214             this.calculateFixedPointSqrtLookupTable();
215             fillMethod = FIXED_POINT_IMPL;
216         }
217     }
218     
219     /**
220      * Return a Raster containing the colors generated for the graphics
221      * operation.
222      * @param x,y,w,h The area in device space for which colors are
223      * generated.
224      */

225     protected void fillRaster(int pixels[], int off, int adjust,
226                               int x, int y, int w, int h) {
227         switch(fillMethod) {
228         case FIXED_POINT_IMPL:
229             // System.out.println("Calling FP");
230
fixedPointSimplestCaseNonCyclicFillRaster(pixels, off, adjust, x,
231                                                       y, w, h);
232             break;
233         case ANTI_ALIAS_IMPL:
234             // System.out.println("Calling AA");
235
antiAliasFillRaster(pixels, off, adjust, x, y, w, h);
236             break;
237         case DEFAULT_IMPL:
238         default:
239             // System.out.println("Calling Default");
240
cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h);
241         }
242     }
243     
244     /**
245      * This code works in the simplest of cases, where the focus == center
246      * point, the gradient is noncyclic, and the gradient lookup method is
247      * fast (single array index, no conversion necessary).
248      *
249      */

250     private void fixedPointSimplestCaseNonCyclicFillRaster(int pixels[],
251                                                            int off,
252                                                            int adjust,
253                                                            int x, int y,
254                                                            int w, int h) {
255         float iSq=0; // Square distance index
256
final float indexFactor = fastGradientArraySize / radius;
257
258         //constant part of X and Y coordinates for the entire raster
259
final float constX = (a00*x) + (a01*y) + constA;
260         final float constY = (a10*x) + (a11*y) + constB;
261         final float deltaX = indexFactor * a00; //incremental change in dX
262
final float deltaY = indexFactor * a10; //incremental change in dY
263
float dX, dY; //the current distance from center
264
final int fixedArraySizeSq=
265             (fastGradientArraySize * fastGradientArraySize);
266         float g, gDelta, gDeltaDelta, temp; //gradient square value
267
int gIndex; // integer number used to index gradient array
268
int iSqInt; // Square distance index
269

270         int end, j; //indexing variables
271
int indexer = off;//used to index pixels array
272

273         temp = ((deltaX * deltaX) + (deltaY * deltaY));
274         gDeltaDelta = ((temp * 2));
275
276         if (temp > fixedArraySizeSq) {
277             // This combination of scale and circle radius means
278
// essentially no pixels will be anything but the end
279
// stop color. This also avoids math problems.
280
final int val = gradientOverflow;
281             for(j = 0; j < h; j++){ //for every row
282
//for every column (inner loop begins here)
283
for (end = indexer+w; indexer < end; indexer++)
284                     pixels[indexer] = val;
285                 indexer += adjust;
286             }
287             return;
288         }
289
290         // For every point in the raster, calculate the color at that point
291
for(j = 0; j < h; j++){ //for every row
292
//x and y (in user space) of the first pixel of this row
293
dX = indexFactor * ((a01*j) + constX);
294             dY = indexFactor * ((a11*j) + constY);
295
296             // these values below here allow for an incremental calculation
297
// of dX^2 + dY^2
298

299             //initialize to be equal to distance squared
300
g = (((dY * dY) + (dX * dX)) );
301             gDelta = (((((deltaY * dY) + (deltaX * dX))* 2) +
302                         temp));
303         
304             //for every column (inner loop begins here)
305
for (end = indexer+w; indexer < end; indexer++) {
306                 //determine the distance to the center
307

308                 //since this is a non cyclic fill raster, crop at "1" and 0
309
if (g >= fixedArraySizeSq) {
310                     pixels[indexer] = gradientOverflow;
311                 }
312         
313                 // This should not happen as gIndex is a square
314
// quantity. Code commented out on purpose, can't underflow.
315
// else if (g < 0) {
316
// gIndex = 0;
317
// }
318

319                 else {
320                     iSq = (g * invSqStepFloat);
321                     
322                     iSqInt = (int)iSq; //chop off fractional part
323
iSq -= iSqInt;
324                     gIndex = sqrtLutFixed[iSqInt];
325                     gIndex += (int)(iSq * (sqrtLutFixed[iSqInt + 1]-gIndex));
326                     pixels[indexer] = gradient[gIndex];
327                 }
328         
329                 
330                 //incremental calculation
331
g += gDelta;
332                 gDelta += gDeltaDelta;
333             }
334             indexer += adjust;
335         }
336     }
337
338     /** Length of a square distance intervale in the lookup table */
339     private float invSqStepFloat;
340     
341     /** Used to limit the size of the square root lookup table */
342     private int MAX_PRECISION = 256;
343     
344     /** Square root lookup table */
345     private int sqrtLutFixed[] = new int[MAX_PRECISION];
346     
347     /**
348      * Build square root lookup table
349      */

350     private void calculateFixedPointSqrtLookupTable() {
351         float sqStepFloat;
352         sqStepFloat = ((fastGradientArraySize * fastGradientArraySize)
353                        / (MAX_PRECISION - 2));
354     
355         // The last two values are the same so that linear square root
356
// interpolation can happen on the maximum reachable element in the
357
// lookup table (precision-2)
358
int i;
359         for (i = 0; i < MAX_PRECISION - 1; i++) {
360             sqrtLutFixed[i] = (int)(Math.sqrt(i*sqStepFloat));
361         }
362         sqrtLutFixed[i] = sqrtLutFixed[i-1];
363         invSqStepFloat = 1/sqStepFloat;
364     }
365     
366     /** Fill the raster, cycling the gradient colors when a point falls outside
367      * of the perimeter of the 100% stop circle.
368      *
369      * This calculation first computes the intersection point of the line
370      * from the focus through the current point in the raster, and the
371      * perimeter of the gradient circle.
372      *
373      * Then it determines the percentage distance of the current point along
374      * that line (focus is 0%, perimeter is 100%).
375      *
376      * Equation of a circle centered at (a,b) with radius r:
377      * (x-a)^2 + (y-b)^2 = r^2
378      * Equation of a line with slope m and y-intercept b
379      * y = mx + b
380      * replacing y in the cirlce equation and solving using the quadratic
381      * formula produces the following set of equations. Constant factors have
382      * been extracted out of the inner loop.
383      *
384      */

385     private void cyclicCircularGradientFillRaster(int pixels[], int off,
386                                                   int adjust,
387                                                   int x, int y,
388                                                   int w, int h) {
389         // Constant part of the C factor of the quadratic equation
390
final double constC =
391             -(radiusSq) + (centerX * centerX) + (centerY * centerY);
392         double A; //coefficient of the quadratic equation (Ax^2 + Bx + C = 0)
393
double B; //coefficient of the quadratic equation
394
double C; //coefficient of the quadratic equation
395
double slope; //slope of the focus-perimeter line
396
double yintcpt; //y-intercept of the focus-perimeter line
397
double solutionX;//intersection with circle X coordinate
398
double solutionY;//intersection with circle Y coordinate
399
final float constX = (a00*x) + (a01*y) + a02;//const part of X coord
400
final float constY = (a10*x) + (a11*y) + a12; //const part of Y coord
401
final float precalc2 = 2 * centerY;//const in inner loop quad. formula
402
final float precalc3 =-2 * centerX;//const in inner loop quad. formula
403
float X; // User space point X coordinate
404
float Y; // User space point Y coordinate
405
float g;//value between 0 and 1 specifying position in the gradient
406
float det; //determinant of quadratic formula (should always be >0)
407
float currentToFocusSq;//sq distance from the current pt. to focus
408
float intersectToFocusSq;//sq distance from the intersect pt. to focus
409
float deltaXSq; //temp variable for a change in X squared.
410
float deltaYSq; //temp variable for a change in Y squared.
411
int indexer = off; //index variable for pixels array
412
int i, j; //indexing variables for FOR loops
413
int pixInc = w+adjust;//incremental index change for pixels array
414

415         for (j = 0; j < h; j++) { //for every row
416

417             X = (a01*j) + constX; //constants from column to column
418
Y = (a11*j) + constY;
419         
420             //for every column (inner loop begins here)
421
for (i = 0; i < w; i++) {
422     
423                 // special case to avoid divide by zero or very near zero
424
if (((X-focusX)>-0.000001) &&
425                     ((X-focusX)< 0.000001)) {
426                     solutionX = focusX;
427             
428                     solutionY = centerY;
429             
430                     solutionY += (Y > focusY)?trivial:-trivial;
431                 }
432         
433                 else {
434             
435                     //slope of the focus-current line
436
slope = (Y - focusY) / (X - focusX);
437             
438                     yintcpt = Y - (slope * X); //y-intercept of that same line
439

440                     //use the quadratic formula to calculate the intersection
441
//point
442
A = (slope * slope) + 1;
443             
444                     B = precalc3 + (-2 * slope * (centerY - yintcpt));
445             
446                     C = constC + (yintcpt* (yintcpt - precalc2));
447             
448                     det = (float)Math.sqrt((B * B) - ( 4 * A * C));
449             
450                     solutionX = -B;
451             
452                     //choose the positive or negative root depending
453
//on where the X coord lies with respect to the focus.
454
solutionX += (X < focusX)?-det:det;
455             
456                     solutionX = solutionX / (2 * A);//divisor
457

458                     solutionY = (slope * solutionX) + yintcpt;
459                 }
460
461                 //calculate the square of the distance from the current point
462
//to the focus and the square of the distance from the
463
//intersection point to the focus. Want the squares so we can
464
//do 1 square root after division instead of 2 before.
465

466                 deltaXSq = (float)solutionX - focusX;
467                 deltaXSq = deltaXSq * deltaXSq;
468
469                 deltaYSq = (float)solutionY - focusY;
470                 deltaYSq = deltaYSq * deltaYSq;
471
472                 intersectToFocusSq = deltaXSq + deltaYSq;
473
474                 deltaXSq = X - focusX;
475                 deltaXSq = deltaXSq * deltaXSq;
476
477                 deltaYSq = Y - focusY;
478                 deltaYSq = deltaYSq * deltaYSq;
479
480                 currentToFocusSq = deltaXSq + deltaYSq;
481
482                 //want the percentage (0-1) of the current point along the
483
//focus-circumference line
484
g = (float)Math.sqrt(currentToFocusSq / intersectToFocusSq);
485
486                 //Get the color at this point
487
pixels[indexer + i] = indexIntoGradientsArrays(g);
488         
489                 X += a00; //incremental change in X, Y
490
Y += a10;
491             } //end inner loop
492
indexer += pixInc;
493         } //end outer loop
494
}
495
496
497     /** Fill the raster, cycling the gradient colors when a point
498      * falls outside of the perimeter of the 100% stop circle. Use
499      * the anti-aliased gradient lookup.
500      *
501      * This calculation first computes the intersection point of the line
502      * from the focus through the current point in the raster, and the
503      * perimeter of the gradient circle.
504      *
505      * Then it determines the percentage distance of the current point along
506      * that line (focus is 0%, perimeter is 100%).
507      *
508      * Equation of a circle centered at (a,b) with radius r:
509      * (x-a)^2 + (y-b)^2 = r^2
510      * Equation of a line with slope m and y-intercept b
511      * y = mx + b
512      * replacing y in the cirlce equation and solving using the quadratic
513      * formula produces the following set of equations. Constant factors have
514      * been extracted out of the inner loop.
515      * */

516     private void antiAliasFillRaster(int pixels[], int off,
517                                      int adjust,
518                                      int x, int y,
519                                      int w, int h) {
520         // Constant part of the C factor of the quadratic equation
521
final double constC =
522             -(radiusSq) + (centerX * centerX) + (centerY * centerY);
523         //coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
524
final float precalc2 = 2 * centerY;//const in inner loop quad. formula
525
final float precalc3 =-2 * centerX;//const in inner loop quad. formula
526

527         //const part of X,Y coord (shifted to bottom left corner of pixel.
528
final float constX = (a00*(x-.5f)) + (a01*(y+.5f)) + a02;
529         final float constY = (a10*(x-.5f)) + (a11*(y+.5f)) + a12;
530         float X; // User space point X coordinate
531
float Y; // User space point Y coordinate
532
int i, j; //indexing variables for FOR loops
533
int indexer = off-1; //index variable for pixels array
534

535         double [] prevGs = new double[w+1];
536         double deltaXSq, deltaYSq;
537         double solutionX, solutionY;
538         double slope, yintcpt, A, B, C, det;
539         double intersectToFocusSq, currentToFocusSq;
540         double g00, g01, g10, g11;
541
542         // Set X,Y to top left corner of first pixel of first row.
543
X = constX - a01;
544         Y = constY - a11;
545
546         // Calc top row of g's.
547
for (i=0; i <= w; i++) {
548             // special case to avoid divide by zero or very near zero
549
if (((X-focusX)>-0.000001) &&
550                 ((X-focusX)< 0.000001)) {
551                 solutionX = focusX;
552                 solutionY = centerY;
553                 solutionY += (Y > focusY)?trivial:-trivial;
554             }
555             else {
556                 // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
557
// Formula line: Y = Slope*x + Y0;
558
//
559
// So you substitue line into Circle and apply
560
// Quadradic formula.
561

562
563                 //slope of the focus-current line
564
slope = (Y - focusY) / (X - focusX);
565             
566                 yintcpt = Y - (slope * X); //y-intercept of that same line
567

568                 //use the quadratic formula to calculate the intersection
569
//point
570
A = (slope * slope) + 1;
571             
572                 B = precalc3 + (-2 * slope * (centerY - yintcpt));
573             
574                 C = constC + (yintcpt* (yintcpt - precalc2));
575             
576                 det = Math.sqrt((B * B) - ( 4 * A * C));
577             
578                 solutionX = -B;
579             
580                 //choose the positive or negative root depending
581
//on where the X coord lies with respect to the focus.
582
solutionX += (X < focusX)?-det:det;
583             
584                 solutionX = solutionX / (2 * A);//divisor
585

586                 solutionY = (slope * solutionX) + yintcpt;
587             }
588
589             //calculate the square of the distance from the current point
590
//to the focus and the square of the distance from the
591
//intersection point to the focus. Want the squares so we can
592
//do 1 square root after division instead of 2 before.
593
deltaXSq = solutionX - focusX;
594             deltaXSq = deltaXSq * deltaXSq;
595         
596             deltaYSq = solutionY - focusY;
597             deltaYSq = deltaYSq * deltaYSq;
598         
599             intersectToFocusSq = deltaXSq + deltaYSq;
600         
601             deltaXSq = X - focusX;
602             deltaXSq = deltaXSq * deltaXSq;
603         
604             deltaYSq = Y - focusY;
605             deltaYSq = deltaYSq * deltaYSq;
606         
607             currentToFocusSq = deltaXSq + deltaYSq;
608         
609             //want the percentage (0-1) of the current point along the
610
//focus-circumference line
611
prevGs[i] = Math.sqrt(currentToFocusSq / intersectToFocusSq);
612
613             X += a00; //incremental change in X, Y
614
Y += a10;
615         }
616
617         for (j = 0; j < h; j++) { //for every row
618

619             // Set X,Y to bottom edge of pixel row.
620
X = (a01*j) + constX; //constants from row to row
621
Y = (a11*j) + constY;
622
623             g10 = prevGs[0];
624             // special case to avoid divide by zero or very near zero
625
if (((X-focusX)>-0.000001) &&
626                 ((X-focusX)< 0.000001)) {
627                 solutionX = focusX;
628                 solutionY = centerY;
629                 solutionY += (Y > focusY)?trivial:-trivial;
630             }
631             else {
632                 // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
633
// Formula line: Y = Slope*x + Y0;
634
//
635
// So you substitue line into Circle and apply
636
// Quadradic formula.
637

638
639                 //slope of the focus-current line
640
slope = (Y - focusY) / (X - focusX);
641             
642                 yintcpt = Y - (slope * X); //y-intercept of that same line
643

644                 //use the quadratic formula to calculate the intersection
645
//point
646
A = (slope * slope) + 1;
647             
648                 B = precalc3 + (-2 * slope * (centerY - yintcpt));
649             
650                 C = constC + (yintcpt* (yintcpt - precalc2));
651             
652                 det = Math.sqrt((B * B) - ( 4 * A * C));
653             
654                 solutionX = -B;
655             
656                 //choose the positive or negative root depending
657
//on where the X coord lies with respect to the focus.
658
solutionX += (X < focusX)?-det:det;
659             
660                 solutionX = solutionX / (2 * A);//divisor
661

662                 solutionY = (slope * solutionX) + yintcpt;
663             }
664
665             //calculate the square of the distance from the current point
666
//to the focus and the square of the distance from the
667
//intersection point to the focus. Want the squares so we can
668
//do 1 square root after division instead of 2 before.
669
deltaXSq = solutionX - focusX;
670             deltaXSq = deltaXSq * deltaXSq;
671         
672             deltaYSq = solutionY - focusY;
673             deltaYSq = deltaYSq * deltaYSq;
674         
675             intersectToFocusSq = deltaXSq + deltaYSq;
676         
677             deltaXSq = X - focusX;
678             deltaXSq = deltaXSq * deltaXSq;
679         
680             deltaYSq = Y - focusY;
681             deltaYSq = deltaYSq * deltaYSq;
682                 
683             currentToFocusSq = deltaXSq + deltaYSq;
684             g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
685             prevGs[0] = g11;
686             
687             X += a00; //incremental change in X, Y
688
Y += a10;
689
690             //for every column (inner loop begins here)
691
for (i=1; i <= w; i++) {
692                 g00 = g10;
693                 g01 = g11;
694                 g10 = prevGs[i];
695
696                 // special case to avoid divide by zero or very near zero
697
if (((X-focusX)>-0.000001) &&
698                     ((X-focusX)< 0.000001)) {
699                     solutionX = focusX;
700                     solutionY = centerY;
701                     solutionY += (Y > focusY)?trivial:-trivial;
702                 }
703                 else {
704                     // Formula for Circle: (X-Xc)^2 + (Y-Yc)^2 - R^2 = 0
705
// Formula line: Y = Slope*x + Y0;
706
//
707
// So you substitue line into Circle and apply
708
// Quadradic formula.
709

710
711                     //slope of the focus-current line
712
slope = (Y - focusY) / (X - focusX);
713             
714                     yintcpt = Y - (slope * X); //y-intercept of that same line
715

716                     //use the quadratic formula to calculate the intersection
717
//point
718
A = (slope * slope) + 1;
719             
720                     B = precalc3 + (-2 * slope * (centerY - yintcpt));
721             
722                     C = constC + (yintcpt* (yintcpt - precalc2));
723             
724                     det = Math.sqrt((B * B) - ( 4 * A * C));
725             
726                     solutionX = -B;
727             
728                     //choose the positive or negative root depending
729
//on where the X coord lies with respect to the focus.
730
solutionX += (X < focusX)?-det:det;
731             
732                     solutionX = solutionX / (2 * A);//divisor
733

734                     solutionY = (slope * solutionX) + yintcpt;
735                 }
736
737                 //calculate the square of the distance from the current point
738
//to the focus and the square of the distance from the
739
//intersection point to the focus. Want the squares so we can
740
//do 1 square root after division instead of 2 before.
741
deltaXSq = solutionX - focusX;
742                 deltaXSq = deltaXSq * deltaXSq;
743         
744                 deltaYSq = solutionY - focusY;
745                 deltaYSq = deltaYSq * deltaYSq;
746         
747                 intersectToFocusSq = deltaXSq + deltaYSq;
748         
749                 deltaXSq = X - focusX;
750                 deltaXSq = deltaXSq * deltaXSq;
751         
752                 deltaYSq = Y - focusY;
753                 deltaYSq = deltaYSq * deltaYSq;
754         
755                 currentToFocusSq = deltaXSq + deltaYSq;
756                 g11 = Math.sqrt(currentToFocusSq / intersectToFocusSq);
757                 prevGs[i] = g11;
758
759                 //Get the color at this point
760
pixels[indexer+i] = indexGradientAntiAlias
761                     ((float)((g00+g01+g10+g11)/4),
762                      (float)Math.max(Math.abs(g11-g00),
763                                      Math.abs(g10-g01)));
764
765                 X += a00; //incremental change in X, Y
766
Y += a10;
767             } //end inner loop
768
indexer += (w+adjust);
769         } //end outer loop
770
}
771 }
772
Popular Tags