Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 2006, 2007, 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
   23    * questions.
   24    */
   25   
   26   package java.awt;
   27   
   28   import java.awt.MultipleGradientPaint.CycleMethod;
   29   import java.awt.MultipleGradientPaint.ColorSpaceType;
   30   import java.awt.color.ColorSpace;
   31   import java.awt.geom.AffineTransform;
   32   import java.awt.geom.NoninvertibleTransformException;
   33   import java.awt.geom.Rectangle2D;
   34   import java.awt.image.ColorModel;
   35   import java.awt.image.DataBuffer;
   36   import java.awt.image.DataBufferInt;
   37   import java.awt.image.DirectColorModel;
   38   import java.awt.image.Raster;
   39   import java.awt.image.SinglePixelPackedSampleModel;
   40   import java.awt.image.WritableRaster;
   41   import java.lang.ref.SoftReference;
   42   import java.lang.ref.WeakReference;
   43   import java.util.Arrays;
   44   
   45   /**
   46    * This is the superclass for all PaintContexts which use a multiple color
   47    * gradient to fill in their raster.  It provides the actual color
   48    * interpolation functionality.  Subclasses only have to deal with using
   49    * the gradient to fill pixels in a raster.
   50    *
   51    * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
   52    */
   53   abstract class MultipleGradientPaintContext implements PaintContext {
   54   
   55       /**
   56        * The PaintContext's ColorModel.  This is ARGB if colors are not all
   57        * opaque, otherwise it is RGB.
   58        */
   59       protected ColorModel model;
   60   
   61       /** Color model used if gradient colors are all opaque. */
   62       private static ColorModel xrgbmodel =
   63           new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
   64   
   65       /** The cached ColorModel. */
   66       protected static ColorModel cachedModel;
   67   
   68       /** The cached raster, which is reusable among instances. */
   69       protected static WeakReference<Raster> cached;
   70   
   71       /** Raster is reused whenever possible. */
   72       protected Raster saved;
   73   
   74       /** The method to use when painting out of the gradient bounds. */
   75       protected CycleMethod cycleMethod;
   76   
   77       /** The ColorSpace in which to perform the interpolation */
   78       protected ColorSpaceType colorSpace;
   79   
   80       /** Elements of the inverse transform matrix. */
   81       protected float a00, a01, a10, a11, a02, a12;
   82   
   83       /**
   84        * This boolean specifies wether we are in simple lookup mode, where an
   85        * input value between 0 and 1 may be used to directly index into a single
   86        * array of gradient colors.  If this boolean value is false, then we have
   87        * to use a 2-step process where we have to determine which gradient array
   88        * we fall into, then determine the index into that array.
   89        */
   90       protected boolean isSimpleLookup;
   91   
   92       /**
   93        * Size of gradients array for scaling the 0-1 index when looking up
   94        * colors the fast way.
   95        */
   96       protected int fastGradientArraySize;
   97   
   98       /**
   99        * Array which contains the interpolated color values for each interval,
  100        * used by calculateSingleArrayGradient().  It is protected for possible
  101        * direct access by subclasses.
  102        */
  103       protected int[] gradient;
  104   
  105       /**
  106        * Array of gradient arrays, one array for each interval.  Used by
  107        * calculateMultipleArrayGradient().
  108        */
  109       private int[][] gradients;
  110   
  111       /** Normalized intervals array. */
  112       private float[] normalizedIntervals;
  113   
  114       /** Fractions array. */
  115       private float[] fractions;
  116   
  117       /** Used to determine if gradient colors are all opaque. */
  118       private int transparencyTest;
  119   
  120       /** Color space conversion lookup tables. */
  121       private static final int SRGBtoLinearRGB[] = new int[256];
  122       private static final int LinearRGBtoSRGB[] = new int[256];
  123   
  124       static {
  125           // build the tables
  126           for (int k = 0; k < 256; k++) {
  127               SRGBtoLinearRGB[k] = convertSRGBtoLinearRGB(k);
  128               LinearRGBtoSRGB[k] = convertLinearRGBtoSRGB(k);
  129           }
  130       }
  131   
  132       /**
  133        * Constant number of max colors between any 2 arbitrary colors.
  134        * Used for creating and indexing gradients arrays.
  135        */
  136       protected static final int GRADIENT_SIZE = 256;
  137       protected static final int GRADIENT_SIZE_INDEX = GRADIENT_SIZE -1;
  138   
  139       /**
  140        * Maximum length of the fast single-array.  If the estimated array size
  141        * is greater than this, switch over to the slow lookup method.
  142        * No particular reason for choosing this number, but it seems to provide
  143        * satisfactory performance for the common case (fast lookup).
  144        */
  145       private static final int MAX_GRADIENT_ARRAY_SIZE = 5000;
  146   
  147       /**
  148        * Constructor for MultipleGradientPaintContext superclass.
  149        */
  150       protected MultipleGradientPaintContext(MultipleGradientPaint mgp,
  151                                              ColorModel cm,
  152                                              Rectangle deviceBounds,
  153                                              Rectangle2D userBounds,
  154                                              AffineTransform t,
  155                                              RenderingHints hints,
  156                                              float[] fractions,
  157                                              Color[] colors,
  158                                              CycleMethod cycleMethod,
  159                                              ColorSpaceType colorSpace)
  160       {
  161           if (deviceBounds == null) {
  162               throw new NullPointerException("Device bounds cannot be null");
  163           }
  164   
  165           if (userBounds == null) {
  166               throw new NullPointerException("User bounds cannot be null");
  167           }
  168   
  169           if (t == null) {
  170               throw new NullPointerException("Transform cannot be null");
  171           }
  172   
  173           if (hints == null) {
  174               throw new NullPointerException("RenderingHints cannot be null");
  175           }
  176   
  177           // The inverse transform is needed to go from device to user space.
  178           // Get all the components of the inverse transform matrix.
  179           AffineTransform tInv;
  180           try {
  181               // the following assumes that the caller has copied the incoming
  182               // transform and is not concerned about it being modified
  183               t.invert();
  184               tInv = t;
  185           } catch (NoninvertibleTransformException e) {
  186               // just use identity transform in this case; better to show
  187               // (incorrect) results than to throw an exception and/or no-op
  188               tInv = new AffineTransform();
  189           }
  190           double m[] = new double[6];
  191           tInv.getMatrix(m);
  192           a00 = (float)m[0];
  193           a10 = (float)m[1];
  194           a01 = (float)m[2];
  195           a11 = (float)m[3];
  196           a02 = (float)m[4];
  197           a12 = (float)m[5];
  198   
  199           // copy some flags
  200           this.cycleMethod = cycleMethod;
  201           this.colorSpace = colorSpace;
  202   
  203           // we can avoid copying this array since we do not modify its values
  204           this.fractions = fractions;
  205   
  206           // note that only one of these values can ever be non-null (we either
  207           // store the fast gradient array or the slow one, but never both
  208           // at the same time)
  209           int[] gradient =
  210               (mgp.gradient != null) ? mgp.gradient.get() : null;
  211           int[][] gradients =
  212               (mgp.gradients != null) ? mgp.gradients.get() : null;
  213   
  214           if (gradient == null && gradients == null) {
  215               // we need to (re)create the appropriate values
  216               calculateLookupData(colors);
  217   
  218               // now cache the calculated values in the
  219               // MultipleGradientPaint instance for future use
  220               mgp.model               = this.model;
  221               mgp.normalizedIntervals = this.normalizedIntervals;
  222               mgp.isSimpleLookup      = this.isSimpleLookup;
  223               if (isSimpleLookup) {
  224                   // only cache the fast array
  225                   mgp.fastGradientArraySize = this.fastGradientArraySize;
  226                   mgp.gradient = new SoftReference<int[]>(this.gradient);
  227               } else {
  228                   // only cache the slow array
  229                   mgp.gradients = new SoftReference<int[][]>(this.gradients);
  230               }
  231           } else {
  232               // use the values cached in the MultipleGradientPaint instance
  233               this.model                 = mgp.model;
  234               this.normalizedIntervals   = mgp.normalizedIntervals;
  235               this.isSimpleLookup        = mgp.isSimpleLookup;
  236               this.gradient              = gradient;
  237               this.fastGradientArraySize = mgp.fastGradientArraySize;
  238               this.gradients             = gradients;
  239           }
  240       }
  241   
  242       /**
  243        * This function is the meat of this class.  It calculates an array of
  244        * gradient colors based on an array of fractions and color values at
  245        * those fractions.
  246        */
  247       private void calculateLookupData(Color[] colors) {
  248           Color[] normalizedColors;
  249           if (colorSpace == ColorSpaceType.LINEAR_RGB) {
  250               // create a new colors array
  251               normalizedColors = new Color[colors.length];
  252               // convert the colors using the lookup table
  253               for (int i = 0; i < colors.length; i++) {
  254                   int argb = colors[i].getRGB();
  255                   int a = argb >>> 24;
  256                   int r = SRGBtoLinearRGB[(argb >> 16) & 0xff];
  257                   int g = SRGBtoLinearRGB[(argb >>  8) & 0xff];
  258                   int b = SRGBtoLinearRGB[(argb      ) & 0xff];
  259                   normalizedColors[i] = new Color(r, g, b, a);
  260               }
  261           } else {
  262               // we can just use this array by reference since we do not
  263               // modify its values in the case of SRGB
  264               normalizedColors = colors;
  265           }
  266   
  267           // this will store the intervals (distances) between gradient stops
  268           normalizedIntervals = new float[fractions.length-1];
  269   
  270           // convert from fractions into intervals
  271           for (int i = 0; i < normalizedIntervals.length; i++) {
  272               // interval distance is equal to the difference in positions
  273               normalizedIntervals[i] = this.fractions[i+1] - this.fractions[i];
  274           }
  275   
  276           // initialize to be fully opaque for ANDing with colors
  277           transparencyTest = 0xff000000;
  278   
  279           // array of interpolation arrays
  280           gradients = new int[normalizedIntervals.length][];
  281   
  282           // find smallest interval
  283           float Imin = 1;
  284           for (int i = 0; i < normalizedIntervals.length; i++) {
  285               Imin = (Imin > normalizedIntervals[i]) ?
  286                   normalizedIntervals[i] : Imin;
  287           }
  288   
  289           // Estimate the size of the entire gradients array.
  290           // This is to prevent a tiny interval from causing the size of array
  291           // to explode.  If the estimated size is too large, break to using
  292           // separate arrays for each interval, and using an indexing scheme at
  293           // look-up time.
  294           int estimatedSize = 0;
  295           for (int i = 0; i < normalizedIntervals.length; i++) {
  296               estimatedSize += (normalizedIntervals[i]/Imin) * GRADIENT_SIZE;
  297           }
  298   
  299           if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
  300               // slow method
  301               calculateMultipleArrayGradient(normalizedColors);
  302           } else {
  303               // fast method
  304               calculateSingleArrayGradient(normalizedColors, Imin);
  305           }
  306   
  307           // use the most "economical" model
  308           if ((transparencyTest >>> 24) == 0xff) {
  309               model = xrgbmodel;
  310           } else {
  311               model = ColorModel.getRGBdefault();
  312           }
  313       }
  314   
  315       /**
  316        * FAST LOOKUP METHOD
  317        *
  318        * This method calculates the gradient color values and places them in a
  319        * single int array, gradient[].  It does this by allocating space for
  320        * each interval based on its size relative to the smallest interval in
  321        * the array.  The smallest interval is allocated 255 interpolated values
  322        * (the maximum number of unique in-between colors in a 24 bit color
  323        * system), and all other intervals are allocated
  324        * size = (255 * the ratio of their size to the smallest interval).
  325        *
  326        * This scheme expedites a speedy retrieval because the colors are
  327        * distributed along the array according to their user-specified
  328        * distribution.  All that is needed is a relative index from 0 to 1.
  329        *
  330        * The only problem with this method is that the possibility exists for
  331        * the array size to balloon in the case where there is a
  332        * disproportionately small gradient interval.  In this case the other
  333        * intervals will be allocated huge space, but much of that data is
  334        * redundant.  We thus need to use the space conserving scheme below.
  335        *
  336        * @param Imin the size of the smallest interval
  337        */
  338       private void calculateSingleArrayGradient(Color[] colors, float Imin) {
  339           // set the flag so we know later it is a simple (fast) lookup
  340           isSimpleLookup = true;
  341   
  342           // 2 colors to interpolate
  343           int rgb1, rgb2;
  344   
  345           //the eventual size of the single array
  346           int gradientsTot = 1;
  347   
  348           // for every interval (transition between 2 colors)
  349           for (int i = 0; i < gradients.length; i++) {
  350               // create an array whose size is based on the ratio to the
  351               // smallest interval
  352               int nGradients = (int)((normalizedIntervals[i]/Imin)*255f);
  353               gradientsTot += nGradients;
  354               gradients[i] = new int[nGradients];
  355   
  356               // the 2 colors (keyframes) to interpolate between
  357               rgb1 = colors[i].getRGB();
  358               rgb2 = colors[i+1].getRGB();
  359   
  360               // fill this array with the colors in between rgb1 and rgb2
  361               interpolate(rgb1, rgb2, gradients[i]);
  362   
  363               // if the colors are opaque, transparency should still
  364               // be 0xff000000
  365               transparencyTest &= rgb1;
  366               transparencyTest &= rgb2;
  367           }
  368   
  369           // put all gradients in a single array
  370           gradient = new int[gradientsTot];
  371           int curOffset = 0;
  372           for (int i = 0; i < gradients.length; i++){
  373               System.arraycopy(gradients[i], 0, gradient,
  374                                curOffset, gradients[i].length);
  375               curOffset += gradients[i].length;
  376           }
  377           gradient[gradient.length-1] = colors[colors.length-1].getRGB();
  378   
  379           // if interpolation occurred in Linear RGB space, convert the
  380           // gradients back to sRGB using the lookup table
  381           if (colorSpace == ColorSpaceType.LINEAR_RGB) {
  382               for (int i = 0; i < gradient.length; i++) {
  383                   gradient[i] = convertEntireColorLinearRGBtoSRGB(gradient[i]);
  384               }
  385           }
  386   
  387           fastGradientArraySize = gradient.length - 1;
  388       }
  389   
  390       /**
  391        * SLOW LOOKUP METHOD
  392        *
  393        * This method calculates the gradient color values for each interval and
  394        * places each into its own 255 size array.  The arrays are stored in
  395        * gradients[][].  (255 is used because this is the maximum number of
  396        * unique colors between 2 arbitrary colors in a 24 bit color system.)
  397        *
  398        * This method uses the minimum amount of space (only 255 * number of
  399        * intervals), but it aggravates the lookup procedure, because now we
  400        * have to find out which interval to select, then calculate the index
  401        * within that interval.  This causes a significant performance hit,
  402        * because it requires this calculation be done for every point in
  403        * the rendering loop.
  404        *
  405        * For those of you who are interested, this is a classic example of the
  406        * time-space tradeoff.
  407        */
  408       private void calculateMultipleArrayGradient(Color[] colors) {
  409           // set the flag so we know later it is a non-simple lookup
  410           isSimpleLookup = false;
  411   
  412           // 2 colors to interpolate
  413           int rgb1, rgb2;
  414   
  415           // for every interval (transition between 2 colors)
  416           for (int i = 0; i < gradients.length; i++){
  417               // create an array of the maximum theoretical size for
  418               // each interval
  419               gradients[i] = new int[GRADIENT_SIZE];
  420   
  421               // get the the 2 colors
  422               rgb1 = colors[i].getRGB();
  423               rgb2 = colors[i+1].getRGB();
  424   
  425               // fill this array with the colors in between rgb1 and rgb2
  426               interpolate(rgb1, rgb2, gradients[i]);
  427   
  428               // if the colors are opaque, transparency should still
  429               // be 0xff000000
  430               transparencyTest &= rgb1;
  431               transparencyTest &= rgb2;
  432           }
  433   
  434           // if interpolation occurred in Linear RGB space, convert the
  435           // gradients back to SRGB using the lookup table
  436           if (colorSpace == ColorSpaceType.LINEAR_RGB) {
  437               for (int j = 0; j < gradients.length; j++) {
  438                   for (int i = 0; i < gradients[j].length; i++) {
  439                       gradients[j][i] =
  440                           convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
  441                   }
  442               }
  443           }
  444       }
  445   
  446       /**
  447        * Yet another helper function.  This one linearly interpolates between
  448        * 2 colors, filling up the output array.
  449        *
  450        * @param rgb1 the start color
  451        * @param rgb2 the end color
  452        * @param output the output array of colors; must not be null
  453        */
  454       private void interpolate(int rgb1, int rgb2, int[] output) {
  455           // color components
  456           int a1, r1, g1, b1, da, dr, dg, db;
  457   
  458           // step between interpolated values
  459           float stepSize = 1.0f / output.length;
  460   
  461           // extract color components from packed integer
  462           a1 = (rgb1 >> 24) & 0xff;
  463           r1 = (rgb1 >> 16) & 0xff;
  464           g1 = (rgb1 >>  8) & 0xff;
  465           b1 = (rgb1      ) & 0xff;
  466   
  467           // calculate the total change in alpha, red, green, blue
  468           da = ((rgb2 >> 24) & 0xff) - a1;
  469           dr = ((rgb2 >> 16) & 0xff) - r1;
  470           dg = ((rgb2 >>  8) & 0xff) - g1;
  471           db = ((rgb2      ) & 0xff) - b1;
  472   
  473           // for each step in the interval calculate the in-between color by
  474           // multiplying the normalized current position by the total color
  475           // change (0.5 is added to prevent truncation round-off error)
  476           for (int i = 0; i < output.length; i++) {
  477               output[i] =
  478                   (((int) ((a1 + i * da * stepSize) + 0.5) << 24)) |
  479                   (((int) ((r1 + i * dr * stepSize) + 0.5) << 16)) |
  480                   (((int) ((g1 + i * dg * stepSize) + 0.5) <<  8)) |
  481                   (((int) ((b1 + i * db * stepSize) + 0.5)      ));
  482           }
  483       }
  484   
  485       /**
  486        * Yet another helper function.  This one extracts the color components
  487        * of an integer RGB triple, converts them from LinearRGB to SRGB, then
  488        * recompacts them into an int.
  489        */
  490       private int convertEntireColorLinearRGBtoSRGB(int rgb) {
  491           // color components
  492           int a1, r1, g1, b1;
  493   
  494           // extract red, green, blue components
  495           a1 = (rgb >> 24) & 0xff;
  496           r1 = (rgb >> 16) & 0xff;
  497           g1 = (rgb >>  8) & 0xff;
  498           b1 = (rgb      ) & 0xff;
  499   
  500           // use the lookup table
  501           r1 = LinearRGBtoSRGB[r1];
  502           g1 = LinearRGBtoSRGB[g1];
  503           b1 = LinearRGBtoSRGB[b1];
  504   
  505           // re-compact the components
  506           return ((a1 << 24) |
  507                   (r1 << 16) |
  508                   (g1 <<  8) |
  509                   (b1      ));
  510       }
  511   
  512       /**
  513        * Helper function to index into the gradients array.  This is necessary
  514        * because each interval has an array of colors with uniform size 255.
  515        * However, the color intervals are not necessarily of uniform length, so
  516        * a conversion is required.
  517        *
  518        * @param position the unmanipulated position, which will be mapped
  519        *                 into the range 0 to 1
  520        * @returns integer color to display
  521        */
  522       protected final int indexIntoGradientsArrays(float position) {
  523           // first, manipulate position value depending on the cycle method
  524           if (cycleMethod == CycleMethod.NO_CYCLE) {
  525               if (position > 1) {
  526                   // upper bound is 1
  527                   position = 1;
  528               } else if (position < 0) {
  529                   // lower bound is 0
  530                   position = 0;
  531               }
  532           } else if (cycleMethod == CycleMethod.REPEAT) {
  533               // get the fractional part
  534               // (modulo behavior discards integer component)
  535               position = position - (int)position;
  536   
  537               //position should now be between -1 and 1
  538               if (position < 0) {
  539                   // force it to be in the range 0-1
  540                   position = position + 1;
  541               }
  542           } else { // cycleMethod == CycleMethod.REFLECT
  543               if (position < 0) {
  544                   // take absolute value
  545                   position = -position;
  546               }
  547   
  548               // get the integer part
  549               int part = (int)position;
  550   
  551               // get the fractional part
  552               position = position - part;
  553   
  554               if ((part & 1) == 1) {
  555                   // integer part is odd, get reflected color instead
  556                   position = 1 - position;
  557               }
  558           }
  559   
  560           // now, get the color based on this 0-1 position...
  561   
  562           if (isSimpleLookup) {
  563               // easy to compute: just scale index by array size
  564               return gradient[(int)(position * fastGradientArraySize)];
  565           } else {
  566               // more complicated computation, to save space
  567   
  568               // for all the gradient interval arrays
  569               for (int i = 0; i < gradients.length; i++) {
  570                   if (position < fractions[i+1]) {
  571                       // this is the array we want
  572                       float delta = position - fractions[i];
  573   
  574                       // this is the interval we want
  575                       int index = (int)((delta / normalizedIntervals[i])
  576                                         * (GRADIENT_SIZE_INDEX));
  577   
  578                       return gradients[i][index];
  579                   }
  580               }
  581           }
  582   
  583           return gradients[gradients.length - 1][GRADIENT_SIZE_INDEX];
  584       }
  585   
  586       /**
  587        * Helper function to convert a color component in sRGB space to linear
  588        * RGB space.  Used to build a static lookup table.
  589        */
  590       private static int convertSRGBtoLinearRGB(int color) {
  591           float input, output;
  592   
  593           input = color / 255.0f;
  594           if (input <= 0.04045f) {
  595               output = input / 12.92f;
  596           } else {
  597               output = (float)Math.pow((input + 0.055) / 1.055, 2.4);
  598           }
  599   
  600           return Math.round(output * 255.0f);
  601       }
  602   
  603       /**
  604        * Helper function to convert a color component in linear RGB space to
  605        * SRGB space.  Used to build a static lookup table.
  606        */
  607       private static int convertLinearRGBtoSRGB(int color) {
  608           float input, output;
  609   
  610           input = color/255.0f;
  611           if (input <= 0.0031308) {
  612               output = input * 12.92f;
  613           } else {
  614               output = (1.055f *
  615                   ((float) Math.pow(input, (1.0 / 2.4)))) - 0.055f;
  616           }
  617   
  618           return Math.round(output * 255.0f);
  619       }
  620   
  621       /**
  622        * {@inheritDoc}
  623        */
  624       public final Raster getRaster(int x, int y, int w, int h) {
  625           // If working raster is big enough, reuse it. Otherwise,
  626           // build a large enough new one.
  627           Raster raster = saved;
  628           if (raster == null ||
  629               raster.getWidth() < w || raster.getHeight() < h)
  630           {
  631               raster = getCachedRaster(model, w, h);
  632               saved = raster;
  633           }
  634   
  635           // Access raster internal int array. Because we use a DirectColorModel,
  636           // we know the DataBuffer is of type DataBufferInt and the SampleModel
  637           // is SinglePixelPackedSampleModel.
  638           // Adjust for initial offset in DataBuffer and also for the scanline
  639           // stride.
  640           // These calls make the DataBuffer non-acceleratable, but the
  641           // Raster is never Stable long enough to accelerate anyway...
  642           DataBufferInt rasterDB = (DataBufferInt)raster.getDataBuffer();
  643           int[] pixels = rasterDB.getData(0);
  644           int off = rasterDB.getOffset();
  645           int scanlineStride = ((SinglePixelPackedSampleModel)
  646                                 raster.getSampleModel()).getScanlineStride();
  647           int adjust = scanlineStride - w;
  648   
  649           fillRaster(pixels, off, adjust, x, y, w, h); // delegate to subclass
  650   
  651           return raster;
  652       }
  653   
  654       protected abstract void fillRaster(int pixels[], int off, int adjust,
  655                                          int x, int y, int w, int h);
  656   
  657   
  658       /**
  659        * Took this cacheRaster code from GradientPaint. It appears to recycle
  660        * rasters for use by any other instance, as long as they are sufficiently
  661        * large.
  662        */
  663       private static synchronized Raster getCachedRaster(ColorModel cm,
  664                                                          int w, int h)
  665       {
  666           if (cm == cachedModel) {
  667               if (cached != null) {
  668                   Raster ras = (Raster) cached.get();
  669                   if (ras != null &&
  670                       ras.getWidth() >= w &&
  671                       ras.getHeight() >= h)
  672                   {
  673                       cached = null;
  674                       return ras;
  675                   }
  676               }
  677           }
  678           return cm.createCompatibleWritableRaster(w, h);
  679       }
  680   
  681       /**
  682        * Took this cacheRaster code from GradientPaint. It appears to recycle
  683        * rasters for use by any other instance, as long as they are sufficiently
  684        * large.
  685        */
  686       private static synchronized void putCachedRaster(ColorModel cm,
  687                                                        Raster ras)
  688       {
  689           if (cached != null) {
  690               Raster cras = (Raster) cached.get();
  691               if (cras != null) {
  692                   int cw = cras.getWidth();
  693                   int ch = cras.getHeight();
  694                   int iw = ras.getWidth();
  695                   int ih = ras.getHeight();
  696                   if (cw >= iw && ch >= ih) {
  697                       return;
  698                   }
  699                   if (cw * ch >= iw * ih) {
  700                       return;
  701                   }
  702               }
  703           }
  704           cachedModel = cm;
  705           cached = new WeakReference<Raster>(ras);
  706       }
  707   
  708       /**
  709        * {@inheritDoc}
  710        */
  711       public final void dispose() {
  712           if (saved != null) {
  713               putCachedRaster(model, saved);
  714               saved = null;
  715           }
  716       }
  717   
  718       /**
  719        * {@inheritDoc}
  720        */
  721       public final ColorModel getColorModel() {
  722           return model;
  723       }
  724   }

Home » openjdk-7 » java » awt » [javadoc | source]