< prev index next >

src/java.desktop/share/classes/java/awt/RadialGradientPaintContext.java

Print this page


   1 /*
   2  * Copyright (c) 2006, 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


 153 
 154         // calculate the solution to be used in the case where X == focusX
 155         // in cyclicCircularGradientFillRaster()
 156         trivial = (float)Math.sqrt(radiusSq - (dX * dX));
 157 
 158         // constant parts of X, Y user space coordinates
 159         constA = a02 - centerX;
 160         constB = a12 - centerY;
 161 
 162         // constant second order delta for simple loop
 163         gDeltaDelta = 2 * ( a00 *  a00 +  a10 *  a10) / radiusSq;
 164     }
 165 
 166     /**
 167      * Return a Raster containing the colors generated for the graphics
 168      * operation.
 169      *
 170      * @param x,y,w,h the area in device space for which colors are
 171      * generated.
 172      */
 173     protected void fillRaster(int pixels[], int off, int adjust,
 174                               int x, int y, int w, int h)
 175     {
 176         if (isSimpleFocus && isNonCyclic && isSimpleLookup) {
 177             simpleNonCyclicFillRaster(pixels, off, adjust, x, y, w, h);
 178         } else {
 179             cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h);
 180         }
 181     }
 182 
 183     /**
 184      * This code works in the simplest of cases, where the focus == center
 185      * point, the gradient is noncyclic, and the gradient lookup method is
 186      * fast (single array index, no conversion necessary).
 187      */
 188     private void simpleNonCyclicFillRaster(int pixels[], int off, int adjust,
 189                                            int x, int y, int w, int h)
 190     {
 191         /* We calculate sqrt(X^2 + Y^2) relative to the radius
 192          * size to get the fraction for the color to use.
 193          *
 194          * Each step along the scanline adds (a00, a10) to (X, Y).
 195          * If we precalculate:
 196          *   gRel = X^2+Y^2
 197          * for the start of the row, then for each step we need to
 198          * calculate:
 199          *   gRel' = (X+a00)^2 + (Y+a10)^2
 200          *         = X^2 + 2*X*a00 + a00^2 + Y^2 + 2*Y*a10 + a10^2
 201          *         = (X^2+Y^2) + 2*(X*a00+Y*a10) + (a00^2+a10^2)
 202          *         = gRel + 2*(X*a00+Y*a10) + (a00^2+a10^2)
 203          *         = gRel + 2*DP + SD
 204          * (where DP = dot product between X,Y and a00,a10
 205          *  and   SD = dot product square of the delta vector)
 206          * For the step after that we get:
 207          *   gRel'' = (X+2*a00)^2 + (Y+2*a10)^2
 208          *          = X^2 + 4*X*a00 + 4*a00^2 + Y^2 + 4*Y*a10 + 4*a10^2


 284 
 285                 // incremental calculation
 286                 gRel += gDelta;
 287                 gDelta += gDeltaDelta;
 288                 i++;
 289             }
 290             // Quick fill to end of line for "out to the right"
 291             while (i < w) {
 292                 pixels[off + i] = rgbclip;
 293                 i++;
 294             }
 295 
 296             off += adjust;
 297             rowX += a01;
 298             rowY += a11;
 299         }
 300     }
 301 
 302     // SQRT_LUT_SIZE must be a power of 2 for the test above to work.
 303     private static final int SQRT_LUT_SIZE = (1 << 11);
 304     private static float sqrtLut[] = new float[SQRT_LUT_SIZE+1];
 305     static {
 306         for (int i = 0; i < sqrtLut.length; i++) {
 307             sqrtLut[i] = (float) Math.sqrt(i / ((float) SQRT_LUT_SIZE));
 308         }
 309     }
 310 
 311     /**
 312      * Fill the raster, cycling the gradient colors when a point falls outside
 313      * of the perimeter of the 100% stop circle.
 314      *
 315      * This calculation first computes the intersection point of the line
 316      * from the focus through the current point in the raster, and the
 317      * perimeter of the gradient circle.
 318      *
 319      * Then it determines the percentage distance of the current point along
 320      * that line (focus is 0%, perimeter is 100%).
 321      *
 322      * Equation of a circle centered at (a,b) with radius r:
 323      *     (x-a)^2 + (y-b)^2 = r^2
 324      * Equation of a line with slope m and y-intercept b:
 325      *     y = mx + b
 326      * Replacing y in the circle equation and solving using the quadratic
 327      * formula produces the following set of equations.  Constant factors have
 328      * been extracted out of the inner loop.
 329      */
 330     private void cyclicCircularGradientFillRaster(int pixels[], int off,
 331                                                   int adjust,
 332                                                   int x, int y,
 333                                                   int w, int h)
 334     {
 335         // constant part of the C factor of the quadratic equation
 336         final double constC =
 337             -radiusSq + (centerX * centerX) + (centerY * centerY);
 338 
 339         // coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
 340         double A, B, C;
 341 
 342         // slope and y-intercept of the focus-perimeter line
 343         double slope, yintcpt;
 344 
 345         // intersection with circle X,Y coordinate
 346         double solutionX, solutionY;
 347 
 348         // constant parts of X, Y coordinates
 349         final float constX = (a00*x) + (a01*y) + a02;
 350         final float constY = (a10*x) + (a11*y) + a12;


   1 /*
   2  * Copyright (c) 2006, 2018, 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


 153 
 154         // calculate the solution to be used in the case where X == focusX
 155         // in cyclicCircularGradientFillRaster()
 156         trivial = (float)Math.sqrt(radiusSq - (dX * dX));
 157 
 158         // constant parts of X, Y user space coordinates
 159         constA = a02 - centerX;
 160         constB = a12 - centerY;
 161 
 162         // constant second order delta for simple loop
 163         gDeltaDelta = 2 * ( a00 *  a00 +  a10 *  a10) / radiusSq;
 164     }
 165 
 166     /**
 167      * Return a Raster containing the colors generated for the graphics
 168      * operation.
 169      *
 170      * @param x,y,w,h the area in device space for which colors are
 171      * generated.
 172      */
 173     protected void fillRaster(int[] pixels, int off, int adjust,
 174                               int x, int y, int w, int h)
 175     {
 176         if (isSimpleFocus && isNonCyclic && isSimpleLookup) {
 177             simpleNonCyclicFillRaster(pixels, off, adjust, x, y, w, h);
 178         } else {
 179             cyclicCircularGradientFillRaster(pixels, off, adjust, x, y, w, h);
 180         }
 181     }
 182 
 183     /**
 184      * This code works in the simplest of cases, where the focus == center
 185      * point, the gradient is noncyclic, and the gradient lookup method is
 186      * fast (single array index, no conversion necessary).
 187      */
 188     private void simpleNonCyclicFillRaster(int[] pixels, int off, int adjust,
 189                                            int x, int y, int w, int h)
 190     {
 191         /* We calculate sqrt(X^2 + Y^2) relative to the radius
 192          * size to get the fraction for the color to use.
 193          *
 194          * Each step along the scanline adds (a00, a10) to (X, Y).
 195          * If we precalculate:
 196          *   gRel = X^2+Y^2
 197          * for the start of the row, then for each step we need to
 198          * calculate:
 199          *   gRel' = (X+a00)^2 + (Y+a10)^2
 200          *         = X^2 + 2*X*a00 + a00^2 + Y^2 + 2*Y*a10 + a10^2
 201          *         = (X^2+Y^2) + 2*(X*a00+Y*a10) + (a00^2+a10^2)
 202          *         = gRel + 2*(X*a00+Y*a10) + (a00^2+a10^2)
 203          *         = gRel + 2*DP + SD
 204          * (where DP = dot product between X,Y and a00,a10
 205          *  and   SD = dot product square of the delta vector)
 206          * For the step after that we get:
 207          *   gRel'' = (X+2*a00)^2 + (Y+2*a10)^2
 208          *          = X^2 + 4*X*a00 + 4*a00^2 + Y^2 + 4*Y*a10 + 4*a10^2


 284 
 285                 // incremental calculation
 286                 gRel += gDelta;
 287                 gDelta += gDeltaDelta;
 288                 i++;
 289             }
 290             // Quick fill to end of line for "out to the right"
 291             while (i < w) {
 292                 pixels[off + i] = rgbclip;
 293                 i++;
 294             }
 295 
 296             off += adjust;
 297             rowX += a01;
 298             rowY += a11;
 299         }
 300     }
 301 
 302     // SQRT_LUT_SIZE must be a power of 2 for the test above to work.
 303     private static final int SQRT_LUT_SIZE = (1 << 11);
 304     private static float[] sqrtLut = new float[SQRT_LUT_SIZE+1];
 305     static {
 306         for (int i = 0; i < sqrtLut.length; i++) {
 307             sqrtLut[i] = (float) Math.sqrt(i / ((float) SQRT_LUT_SIZE));
 308         }
 309     }
 310 
 311     /**
 312      * Fill the raster, cycling the gradient colors when a point falls outside
 313      * of the perimeter of the 100% stop circle.
 314      *
 315      * This calculation first computes the intersection point of the line
 316      * from the focus through the current point in the raster, and the
 317      * perimeter of the gradient circle.
 318      *
 319      * Then it determines the percentage distance of the current point along
 320      * that line (focus is 0%, perimeter is 100%).
 321      *
 322      * Equation of a circle centered at (a,b) with radius r:
 323      *     (x-a)^2 + (y-b)^2 = r^2
 324      * Equation of a line with slope m and y-intercept b:
 325      *     y = mx + b
 326      * Replacing y in the circle equation and solving using the quadratic
 327      * formula produces the following set of equations.  Constant factors have
 328      * been extracted out of the inner loop.
 329      */
 330     private void cyclicCircularGradientFillRaster(int[] pixels, int off,
 331                                                   int adjust,
 332                                                   int x, int y,
 333                                                   int w, int h)
 334     {
 335         // constant part of the C factor of the quadratic equation
 336         final double constC =
 337             -radiusSq + (centerX * centerX) + (centerY * centerY);
 338 
 339         // coefficients of the quadratic equation (Ax^2 + Bx + C = 0)
 340         double A, B, C;
 341 
 342         // slope and y-intercept of the focus-perimeter line
 343         double slope, yintcpt;
 344 
 345         // intersection with circle X,Y coordinate
 346         double solutionX, solutionY;
 347 
 348         // constant parts of X, Y coordinates
 349         final float constX = (a00*x) + (a01*y) + a02;
 350         final float constY = (a10*x) + (a11*y) + a12;


< prev index next >