Source Code Cross Referenced for MultipleGradientPaintContext.java in  » 6.0-JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2006-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.awt;
027
028        import java.awt.MultipleGradientPaint.CycleMethod;
029        import java.awt.MultipleGradientPaint.ColorSpaceType;
030        import java.awt.color.ColorSpace;
031        import java.awt.geom.AffineTransform;
032        import java.awt.geom.NoninvertibleTransformException;
033        import java.awt.geom.Rectangle2D;
034        import java.awt.image.ColorModel;
035        import java.awt.image.DataBuffer;
036        import java.awt.image.DataBufferInt;
037        import java.awt.image.DirectColorModel;
038        import java.awt.image.Raster;
039        import java.awt.image.SinglePixelPackedSampleModel;
040        import java.awt.image.WritableRaster;
041        import java.lang.ref.SoftReference;
042        import java.lang.ref.WeakReference;
043        import java.util.Arrays;
044
045        /**
046         * This is the superclass for all PaintContexts which use a multiple color
047         * gradient to fill in their raster.  It provides the actual color
048         * interpolation functionality.  Subclasses only have to deal with using
049         * the gradient to fill pixels in a raster.
050         *
051         * @author Nicholas Talian, Vincent Hardy, Jim Graham, Jerry Evans
052         */
053        abstract class MultipleGradientPaintContext implements  PaintContext {
054
055            /** 
056             * The PaintContext's ColorModel.  This is ARGB if colors are not all
057             * opaque, otherwise it is RGB.
058             */
059            protected ColorModel model;
060
061            /** Color model used if gradient colors are all opaque. */
062            private static ColorModel xrgbmodel = new DirectColorModel(24,
063                    0x00ff0000, 0x0000ff00, 0x000000ff);
064
065            /** The cached ColorModel. */
066            protected static ColorModel cachedModel;
067
068            /** The cached raster, which is reusable among instances. */
069            protected static WeakReference<Raster> cached;
070
071            /** Raster is reused whenever possible. */
072            protected Raster saved;
073
074            /** The method to use when painting out of the gradient bounds. */
075            protected CycleMethod cycleMethod;
076
077            /** The ColorSpace in which to perform the interpolation */
078            protected ColorSpaceType colorSpace;
079
080            /** Elements of the inverse transform matrix. */
081            protected float a00, a01, a10, a11, a02, a12;
082
083            /**
084             * This boolean specifies wether we are in simple lookup mode, where an
085             * input value between 0 and 1 may be used to directly index into a single
086             * array of gradient colors.  If this boolean value is false, then we have
087             * to use a 2-step process where we have to determine which gradient array
088             * we fall into, then determine the index into that array.
089             */
090            protected boolean isSimpleLookup;
091
092            /**
093             * Size of gradients array for scaling the 0-1 index when looking up
094             * colors the fast way.
095             */
096            protected int fastGradientArraySize;
097
098            /**
099             * 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, Rectangle deviceBounds,
152                    Rectangle2D userBounds, AffineTransform t,
153                    RenderingHints hints, float[] fractions, Color[] colors,
154                    CycleMethod cycleMethod, ColorSpaceType colorSpace) {
155                if (deviceBounds == null) {
156                    throw new NullPointerException(
157                            "Device bounds cannot be null");
158                }
159
160                if (userBounds == null) {
161                    throw new NullPointerException("User bounds cannot be null");
162                }
163
164                if (t == null) {
165                    throw new NullPointerException("Transform cannot be null");
166                }
167
168                if (hints == null) {
169                    throw new NullPointerException(
170                            "RenderingHints cannot be null");
171                }
172
173                // The inverse transform is needed to go from device to user space.  
174                // Get all the components of the inverse transform matrix.
175                AffineTransform tInv;
176                try {
177                    // the following assumes that the caller has copied the incoming
178                    // transform and is not concerned about it being modified
179                    t.invert();
180                    tInv = t;
181                } catch (NoninvertibleTransformException e) {
182                    // just use identity transform in this case; better to show
183                    // (incorrect) results than to throw an exception and/or no-op
184                    tInv = new AffineTransform();
185                }
186                double m[] = new double[6];
187                tInv.getMatrix(m);
188                a00 = (float) m[0];
189                a10 = (float) m[1];
190                a01 = (float) m[2];
191                a11 = (float) m[3];
192                a02 = (float) m[4];
193                a12 = (float) m[5];
194
195                // copy some flags
196                this .cycleMethod = cycleMethod;
197                this .colorSpace = colorSpace;
198
199                // we can avoid copying this array since we do not modify its values
200                this .fractions = fractions;
201
202                // note that only one of these values can ever be non-null (we either
203                // store the fast gradient array or the slow one, but never both
204                // at the same time)
205                int[] gradient = (mgp.gradient != null) ? mgp.gradient.get()
206                        : null;
207                int[][] gradients = (mgp.gradients != null) ? mgp.gradients
208                        .get() : null;
209
210                if (gradient == null && gradients == null) {
211                    // we need to (re)create the appropriate values
212                    calculateLookupData(colors);
213
214                    // now cache the calculated values in the
215                    // MultipleGradientPaint instance for future use
216                    mgp.model = this .model;
217                    mgp.normalizedIntervals = this .normalizedIntervals;
218                    mgp.isSimpleLookup = this .isSimpleLookup;
219                    if (isSimpleLookup) {
220                        // only cache the fast array
221                        mgp.fastGradientArraySize = this .fastGradientArraySize;
222                        mgp.gradient = new SoftReference<int[]>(this .gradient);
223                    } else {
224                        // only cache the slow array
225                        mgp.gradients = new SoftReference<int[][]>(
226                                this .gradients);
227                    }
228                } else {
229                    // use the values cached in the MultipleGradientPaint instance
230                    this .model = mgp.model;
231                    this .normalizedIntervals = mgp.normalizedIntervals;
232                    this .isSimpleLookup = mgp.isSimpleLookup;
233                    this .gradient = gradient;
234                    this .fastGradientArraySize = mgp.fastGradientArraySize;
235                    this .gradients = gradients;
236                }
237            }
238
239            /**
240             * This function is the meat of this class.  It calculates an array of
241             * gradient colors based on an array of fractions and color values at
242             * those fractions.
243             */
244            private void calculateLookupData(Color[] colors) {
245                Color[] normalizedColors;
246                if (colorSpace == ColorSpaceType.LINEAR_RGB) {
247                    // create a new colors array
248                    normalizedColors = new Color[colors.length];
249                    // convert the colors using the lookup table
250                    for (int i = 0; i < colors.length; i++) {
251                        int argb = colors[i].getRGB();
252                        int a = argb >>> 24;
253                        int r = SRGBtoLinearRGB[(argb >> 16) & 0xff];
254                        int g = SRGBtoLinearRGB[(argb >> 8) & 0xff];
255                        int b = SRGBtoLinearRGB[(argb) & 0xff];
256                        normalizedColors[i] = new Color(r, g, b, a);
257                    }
258                } else {
259                    // we can just use this array by reference since we do not
260                    // modify its values in the case of SRGB
261                    normalizedColors = colors;
262                }
263
264                // this will store the intervals (distances) between gradient stops
265                normalizedIntervals = new float[fractions.length - 1];
266
267                // convert from fractions into intervals
268                for (int i = 0; i < normalizedIntervals.length; i++) {
269                    // interval distance is equal to the difference in positions
270                    normalizedIntervals[i] = this .fractions[i + 1]
271                            - this .fractions[i];
272                }
273
274                // initialize to be fully opaque for ANDing with colors
275                transparencyTest = 0xff000000;
276
277                // array of interpolation arrays
278                gradients = new int[normalizedIntervals.length][];
279
280                // find smallest interval
281                float Imin = 1;
282                for (int i = 0; i < normalizedIntervals.length; i++) {
283                    Imin = (Imin > normalizedIntervals[i]) ? normalizedIntervals[i]
284                            : Imin;
285                }
286
287                // Estimate the size of the entire gradients array.
288                // This is to prevent a tiny interval from causing the size of array
289                // to explode.  If the estimated size is too large, break to using
290                // separate arrays for each interval, and using an indexing scheme at
291                // look-up time.
292                int estimatedSize = 0;
293                for (int i = 0; i < normalizedIntervals.length; i++) {
294                    estimatedSize += (normalizedIntervals[i] / Imin)
295                            * GRADIENT_SIZE;
296                }
297
298                if (estimatedSize > MAX_GRADIENT_ARRAY_SIZE) {
299                    // slow method
300                    calculateMultipleArrayGradient(normalizedColors);
301                } else {
302                    // fast method
303                    calculateSingleArrayGradient(normalizedColors, Imin);
304                }
305
306                // use the most "economical" model
307                if ((transparencyTest >>> 24) == 0xff) {
308                    model = xrgbmodel;
309                } else {
310                    model = ColorModel.getRGBdefault();
311                }
312            }
313
314            /**
315             * FAST LOOKUP METHOD
316             *
317             * This method calculates the gradient color values and places them in a 
318             * single int array, gradient[].  It does this by allocating space for 
319             * each interval based on its size relative to the smallest interval in 
320             * the array.  The smallest interval is allocated 255 interpolated values 
321             * (the maximum number of unique in-between colors in a 24 bit color 
322             * system), and all other intervals are allocated 
323             * size = (255 * the ratio of their size to the smallest interval). 
324             * 
325             * This scheme expedites a speedy retrieval because the colors are 
326             * distributed along the array according to their user-specified 
327             * distribution.  All that is needed is a relative index from 0 to 1.  
328             *
329             * The only problem with this method is that the possibility exists for 
330             * the array size to balloon in the case where there is a 
331             * disproportionately small gradient interval.  In this case the other
332             * intervals will be allocated huge space, but much of that data is 
333             * redundant.  We thus need to use the space conserving scheme below.
334             *
335             * @param Imin the size of the smallest interval
336             */
337            private void calculateSingleArrayGradient(Color[] colors, float Imin) {
338                // set the flag so we know later it is a simple (fast) lookup
339                isSimpleLookup = true;
340
341                // 2 colors to interpolate
342                int rgb1, rgb2;
343
344                //the eventual size of the single array
345                int gradientsTot = 1;
346
347                // for every interval (transition between 2 colors)
348                for (int i = 0; i < gradients.length; i++) {
349                    // create an array whose size is based on the ratio to the
350                    // smallest interval
351                    int nGradients = (int) ((normalizedIntervals[i] / Imin) * 255f);
352                    gradientsTot += nGradients;
353                    gradients[i] = new int[nGradients];
354
355                    // the 2 colors (keyframes) to interpolate between
356                    rgb1 = colors[i].getRGB();
357                    rgb2 = colors[i + 1].getRGB();
358
359                    // fill this array with the colors in between rgb1 and rgb2
360                    interpolate(rgb1, rgb2, gradients[i]);
361
362                    // if the colors are opaque, transparency should still
363                    // be 0xff000000
364                    transparencyTest &= rgb1;
365                    transparencyTest &= rgb2;
366                }
367
368                // put all gradients in a single array
369                gradient = new int[gradientsTot];
370                int curOffset = 0;
371                for (int i = 0; i < gradients.length; i++) {
372                    System.arraycopy(gradients[i], 0, gradient, curOffset,
373                            gradients[i].length);
374                    curOffset += gradients[i].length;
375                }
376                gradient[gradient.length - 1] = colors[colors.length - 1]
377                        .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] = convertEntireColorLinearRGBtoSRGB(gradients[j][i]);
440                        }
441                    }
442                }
443            }
444
445            /**
446             * Yet another helper function.  This one linearly interpolates between
447             * 2 colors, filling up the output array.
448             *
449             * @param rgb1 the start color
450             * @param rgb2 the end color
451             * @param output the output array of colors; must not be null
452             */
453            private void interpolate(int rgb1, int rgb2, int[] output) {
454                // color components
455                int a1, r1, g1, b1, da, dr, dg, db;
456
457                // step between interpolated values
458                float stepSize = 1.0f / output.length;
459
460                // extract color components from packed integer
461                a1 = (rgb1 >> 24) & 0xff;
462                r1 = (rgb1 >> 16) & 0xff;
463                g1 = (rgb1 >> 8) & 0xff;
464                b1 = (rgb1) & 0xff;
465
466                // calculate the total change in alpha, red, green, blue
467                da = ((rgb2 >> 24) & 0xff) - a1;
468                dr = ((rgb2 >> 16) & 0xff) - r1;
469                dg = ((rgb2 >> 8) & 0xff) - g1;
470                db = ((rgb2) & 0xff) - b1;
471
472                // for each step in the interval calculate the in-between color by
473                // multiplying the normalized current position by the total color
474                // change (0.5 is added to prevent truncation round-off error)
475                for (int i = 0; i < output.length; i++) {
476                    output[i] = (((int) ((a1 + i * da * stepSize) + 0.5) << 24))
477                            | (((int) ((r1 + i * dr * stepSize) + 0.5) << 16))
478                            | (((int) ((g1 + i * dg * stepSize) + 0.5) << 8))
479                            | (((int) ((b1 + i * db * stepSize) + 0.5)));
480                }
481            }
482
483            /**
484             * Yet another helper function.  This one extracts the color components
485             * of an integer RGB triple, converts them from LinearRGB to SRGB, then
486             * recompacts them into an int.
487             */
488            private int convertEntireColorLinearRGBtoSRGB(int rgb) {
489                // color components
490                int a1, r1, g1, b1;
491
492                // extract red, green, blue components
493                a1 = (rgb >> 24) & 0xff;
494                r1 = (rgb >> 16) & 0xff;
495                g1 = (rgb >> 8) & 0xff;
496                b1 = (rgb) & 0xff;
497
498                // use the lookup table
499                r1 = LinearRGBtoSRGB[r1];
500                g1 = LinearRGBtoSRGB[g1];
501                b1 = LinearRGBtoSRGB[b1];
502
503                // re-compact the components
504                return ((a1 << 24) | (r1 << 16) | (g1 << 8) | (b1));
505            }
506
507            /**
508             * Helper function to index into the gradients array.  This is necessary
509             * because each interval has an array of colors with uniform size 255.
510             * However, the color intervals are not necessarily of uniform length, so
511             * a conversion is required.
512             *
513             * @param position the unmanipulated position, which will be mapped
514             *                 into the range 0 to 1
515             * @returns integer color to display
516             */
517            protected final int indexIntoGradientsArrays(float position) {
518                // first, manipulate position value depending on the cycle method
519                if (cycleMethod == CycleMethod.NO_CYCLE) {
520                    if (position > 1) {
521                        // upper bound is 1
522                        position = 1;
523                    } else if (position < 0) {
524                        // lower bound is 0
525                        position = 0;
526                    }
527                } else if (cycleMethod == CycleMethod.REPEAT) {
528                    // get the fractional part
529                    // (modulo behavior discards integer component)
530                    position = position - (int) position;
531
532                    //position should now be between -1 and 1
533                    if (position < 0) {
534                        // force it to be in the range 0-1
535                        position = position + 1;
536                    }
537                } else { // cycleMethod == CycleMethod.REFLECT
538                    if (position < 0) {
539                        // take absolute value
540                        position = -position;
541                    }
542
543                    // get the integer part
544                    int part = (int) position;
545
546                    // get the fractional part
547                    position = position - part;
548
549                    if ((part & 1) == 1) {
550                        // integer part is odd, get reflected color instead
551                        position = 1 - position;
552                    }
553                }
554
555                // now, get the color based on this 0-1 position...
556
557                if (isSimpleLookup) {
558                    // easy to compute: just scale index by array size
559                    return gradient[(int) (position * fastGradientArraySize)];
560                } else {
561                    // more complicated computation, to save space
562
563                    // for all the gradient interval arrays
564                    for (int i = 0; i < gradients.length; i++) {
565                        if (position < fractions[i + 1]) {
566                            // this is the array we want
567                            float delta = position - fractions[i];
568
569                            // this is the interval we want
570                            int index = (int) ((delta / normalizedIntervals[i]) * (GRADIENT_SIZE_INDEX));
571
572                            return gradients[i][index];
573                        }
574                    }
575                }
576
577                return gradients[gradients.length - 1][GRADIENT_SIZE_INDEX];
578            }
579
580            /**
581             * Helper function to convert a color component in sRGB space to linear
582             * RGB space.  Used to build a static lookup table.
583             */
584            private static int convertSRGBtoLinearRGB(int color) {
585                float input, output;
586
587                input = color / 255.0f;
588                if (input <= 0.04045f) {
589                    output = input / 12.92f;
590                } else {
591                    output = (float) Math.pow((input + 0.055) / 1.055, 2.4);
592                }
593
594                return Math.round(output * 255.0f);
595            }
596
597            /**
598             * Helper function to convert a color component in linear RGB space to
599             * SRGB space.  Used to build a static lookup table.
600             */
601            private static int convertLinearRGBtoSRGB(int color) {
602                float input, output;
603
604                input = color / 255.0f;
605                if (input <= 0.0031308) {
606                    output = input * 12.92f;
607                } else {
608                    output = (1.055f * ((float) Math.pow(input, (1.0 / 2.4)))) - 0.055f;
609                }
610
611                return Math.round(output * 255.0f);
612            }
613
614            /**
615             * {@inheritDoc}
616             */
617            public final Raster getRaster(int x, int y, int w, int h) {
618                // If working raster is big enough, reuse it. Otherwise,
619                // build a large enough new one.
620                Raster raster = saved;
621                if (raster == null || raster.getWidth() < w
622                        || raster.getHeight() < h) {
623                    raster = getCachedRaster(model, w, h);
624                    saved = raster;
625                }
626
627                // Access raster internal int array. Because we use a DirectColorModel,
628                // we know the DataBuffer is of type DataBufferInt and the SampleModel
629                // is SinglePixelPackedSampleModel.
630                // Adjust for initial offset in DataBuffer and also for the scanline 
631                // stride.
632                // These calls make the DataBuffer non-acceleratable, but the
633                // Raster is never Stable long enough to accelerate anyway...
634                DataBufferInt rasterDB = (DataBufferInt) raster.getDataBuffer();
635                int[] pixels = rasterDB.getData(0);
636                int off = rasterDB.getOffset();
637                int scanlineStride = ((SinglePixelPackedSampleModel) raster
638                        .getSampleModel()).getScanlineStride();
639                int adjust = scanlineStride - w;
640
641                fillRaster(pixels, off, adjust, x, y, w, h); // delegate to subclass
642
643                return raster;
644            }
645
646            protected abstract void fillRaster(int pixels[], int off,
647                    int adjust, int x, int y, int w, int h);
648
649            /**
650             * Took this cacheRaster code from GradientPaint. It appears to recycle 
651             * rasters for use by any other instance, as long as they are sufficiently
652             * large.
653             */
654            private static synchronized Raster getCachedRaster(ColorModel cm,
655                    int w, int h) {
656                if (cm == cachedModel) {
657                    if (cached != null) {
658                        Raster ras = (Raster) cached.get();
659                        if (ras != null && ras.getWidth() >= w
660                                && ras.getHeight() >= h) {
661                            cached = null;
662                            return ras;
663                        }
664                    }
665                }
666                return cm.createCompatibleWritableRaster(w, h);
667            }
668
669            /**
670             * Took this cacheRaster code from GradientPaint. It appears to recycle
671             * rasters for use by any other instance, as long as they are sufficiently
672             * large.
673             */
674            private static synchronized void putCachedRaster(ColorModel cm,
675                    Raster ras) {
676                if (cached != null) {
677                    Raster cras = (Raster) cached.get();
678                    if (cras != null) {
679                        int cw = cras.getWidth();
680                        int ch = cras.getHeight();
681                        int iw = ras.getWidth();
682                        int ih = ras.getHeight();
683                        if (cw >= iw && ch >= ih) {
684                            return;
685                        }
686                        if (cw * ch >= iw * ih) {
687                            return;
688                        }
689                    }
690                }
691                cachedModel = cm;
692                cached = new WeakReference<Raster>(ras);
693            }
694
695            /**
696             * {@inheritDoc}
697             */
698            public final void dispose() {
699                if (saved != null) {
700                    putCachedRaster(model, saved);
701                    saved = null;
702                }
703            }
704
705            /**
706             * {@inheritDoc}
707             */
708            public final ColorModel getColorModel() {
709                return model;
710            }
711        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.