1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  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 * @author Oleg V. Khaschansky
19 * @version $Revision$
20 */
21
22package java.awt;
23
24import java.awt.color.ColorSpace;
25import java.awt.geom.AffineTransform;
26import java.awt.geom.Rectangle2D;
27import java.awt.image.ColorModel;
28import java.awt.image.DataBufferInt;
29import java.awt.image.Raster;
30import java.awt.image.WritableRaster;
31import java.io.Serializable;
32import java.util.Arrays;
33
34import org.apache.harmony.awt.internal.nls.Messages;
35
36/**
37 * The Color class defines colors in the default sRGB color space or in the
38 * specified ColorSpace. Every Color contains alpha value. The alpha value
39 * defines the transparency of a color and can be represented by a float value
40 * in the range 0.0 - 1.0 or 0 - 255.
41 *
42 * @since Android 1.0
43 */
44public class Color implements Paint, Serializable {
45
46    /**
47     * The Constant serialVersionUID.
48     */
49    private static final long serialVersionUID = 118526816881161077L;
50
51    /*
52     * The values of the following colors are based on 1.5 release behavior
53     * which can be revealed using the following or similar code: Color c =
54     * Color.white; System.out.println(c);
55     */
56
57    /**
58     * The color white.
59     */
60    public static final Color white = new Color(255, 255, 255);
61
62    /**
63     * The color white.
64     */
65    public static final Color WHITE = white;
66
67    /**
68     * The color light gray.
69     */
70    public static final Color lightGray = new Color(192, 192, 192);
71
72    /**
73     * The color light gray.
74     */
75    public static final Color LIGHT_GRAY = lightGray;
76
77    /**
78     * The color gray.
79     */
80    public static final Color gray = new Color(128, 128, 128);
81
82    /**
83     * The color gray.
84     */
85    public static final Color GRAY = gray;
86
87    /**
88     * The color dark gray.
89     */
90    public static final Color darkGray = new Color(64, 64, 64);
91
92    /**
93     * The color dark gray.
94     */
95    public static final Color DARK_GRAY = darkGray;
96
97    /**
98     * The color black.
99     */
100    public static final Color black = new Color(0, 0, 0);
101
102    /**
103     * The color black.
104     */
105    public static final Color BLACK = black;
106
107    /**
108     * The color red.
109     */
110    public static final Color red = new Color(255, 0, 0);
111
112    /**
113     * The color red.
114     */
115    public static final Color RED = red;
116
117    /**
118     * The color pink.
119     */
120    public static final Color pink = new Color(255, 175, 175);
121
122    /**
123     * The color pink.
124     */
125    public static final Color PINK = pink;
126
127    /**
128     * The color orange.
129     */
130    public static final Color orange = new Color(255, 200, 0);
131
132    /**
133     * The color orange.
134     */
135    public static final Color ORANGE = orange;
136
137    /**
138     * The color yellow.
139     */
140    public static final Color yellow = new Color(255, 255, 0);
141
142    /**
143     * The color yellow.
144     */
145    public static final Color YELLOW = yellow;
146
147    /**
148     * The color green.
149     */
150    public static final Color green = new Color(0, 255, 0);
151
152    /**
153     * The color green.
154     */
155    public static final Color GREEN = green;
156
157    /**
158     * The color magenta.
159     */
160    public static final Color magenta = new Color(255, 0, 255);
161
162    /**
163     * The color magenta.
164     */
165    public static final Color MAGENTA = magenta;
166
167    /**
168     * The color cyan.
169     */
170    public static final Color cyan = new Color(0, 255, 255);
171
172    /**
173     * The color cyan.
174     */
175    public static final Color CYAN = cyan;
176
177    /**
178     * The color blue.
179     */
180    public static final Color blue = new Color(0, 0, 255);
181
182    /**
183     * The color blue.
184     */
185    public static final Color BLUE = blue;
186
187    /**
188     * integer RGB value.
189     */
190    int value;
191
192    /**
193     * Float sRGB value.
194     */
195    private float[] frgbvalue;
196
197    /**
198     * Color in an arbitrary color space with <code>float</code> components. If
199     * null, other value should be used.
200     */
201    private float fvalue[];
202
203    /**
204     * Float alpha value. If frgbvalue is null, this is not valid data.
205     */
206    private float falpha;
207
208    /**
209     * The color's color space if applicable.
210     */
211    private ColorSpace cs;
212
213    /*
214     * The value of the SCALE_FACTOR is based on 1.5 release behavior which can
215     * be revealed using the following code: Color c = new Color(100, 100, 100);
216     * Color bc = c.brighter(); System.out.println("Brighter factor: " +
217     * ((float)c.getRed())/((float)bc.getRed())); Color dc = c.darker();
218     * System.out.println("Darker factor: " +
219     * ((float)dc.getRed())/((float)c.getRed())); The result is the same for
220     * brighter and darker methods, so we need only one scale factor for both.
221     */
222    /**
223     * The Constant SCALE_FACTOR.
224     */
225    private static final double SCALE_FACTOR = 0.7;
226
227    /**
228     * The Constant MIN_SCALABLE.
229     */
230    private static final int MIN_SCALABLE = 3; // should increase when
231
232    // multiplied by SCALE_FACTOR
233
234    /**
235     * The current paint context.
236     */
237    transient private PaintContext currentPaintContext;
238
239    /**
240     * Creates a color in the specified ColorSpace, the specified color
241     * components and the specified alpha.
242     *
243     * @param cspace
244     *            the ColorSpace to be used to define the components.
245     * @param components
246     *            the components.
247     * @param alpha
248     *            the alpha.
249     */
250    public Color(ColorSpace cspace, float[] components, float alpha) {
251        int nComps = cspace.getNumComponents();
252        float comp;
253        fvalue = new float[nComps];
254
255        for (int i = 0; i < nComps; i++) {
256            comp = components[i];
257            if (comp < 0.0f || comp > 1.0f) {
258                // awt.107=Color parameter outside of expected range: component
259                // {0}.
260                throw new IllegalArgumentException(Messages.getString("awt.107", i)); //$NON-NLS-1$
261            }
262            fvalue[i] = components[i];
263        }
264
265        if (alpha < 0.0f || alpha > 1.0f) {
266            // awt.108=Alpha value outside of expected range.
267            throw new IllegalArgumentException(Messages.getString("awt.108")); //$NON-NLS-1$
268        }
269        falpha = alpha;
270
271        cs = cspace;
272
273        frgbvalue = cs.toRGB(fvalue);
274
275        value = ((int)(frgbvalue[2] * 255 + 0.5)) | (((int)(frgbvalue[1] * 255 + 0.5)) << 8)
276                | (((int)(frgbvalue[0] * 255 + 0.5)) << 16) | (((int)(falpha * 255 + 0.5)) << 24);
277    }
278
279    /**
280     * Instantiates a new sRGB color with the specified combined RGBA value
281     * consisting of the alpha component in bits 24-31, the red component in
282     * bits 16-23, the green component in bits 8-15, and the blue component in
283     * bits 0-7. If the hasalpha argument is false, the alpha has default value
284     * - 255.
285     *
286     * @param rgba
287     *            the RGBA components.
288     * @param hasAlpha
289     *            the alpha parameter is true if alpha bits are valid, false
290     *            otherwise.
291     */
292    public Color(int rgba, boolean hasAlpha) {
293        if (!hasAlpha) {
294            value = rgba | 0xFF000000;
295        } else {
296            value = rgba;
297        }
298    }
299
300    /**
301     * Instantiates a new color with the specified red, green, blue and alpha
302     * components.
303     *
304     * @param r
305     *            the red component.
306     * @param g
307     *            the green component.
308     * @param b
309     *            the blue component.
310     * @param a
311     *            the alpha component.
312     */
313    public Color(int r, int g, int b, int a) {
314        if ((r & 0xFF) != r || (g & 0xFF) != g || (b & 0xFF) != b || (a & 0xFF) != a) {
315            // awt.109=Color parameter outside of expected range.
316            throw new IllegalArgumentException(Messages.getString("awt.109")); //$NON-NLS-1$
317        }
318        value = b | (g << 8) | (r << 16) | (a << 24);
319    }
320
321    /**
322     * Instantiates a new opaque sRGB color with the specified red, green, and
323     * blue values. The Alpha component is set to the default - 1.0.
324     *
325     * @param r
326     *            the red component.
327     * @param g
328     *            the green component.
329     * @param b
330     *            the blue component.
331     */
332    public Color(int r, int g, int b) {
333        if ((r & 0xFF) != r || (g & 0xFF) != g || (b & 0xFF) != b) {
334            // awt.109=Color parameter outside of expected range.
335            throw new IllegalArgumentException(Messages.getString("awt.109")); //$NON-NLS-1$
336        }
337        // 0xFF for alpha channel
338        value = b | (g << 8) | (r << 16) | 0xFF000000;
339    }
340
341    /**
342     * Instantiates a new sRGB color with the specified RGB value consisting of
343     * the red component in bits 16-23, the green component in bits 8-15, and
344     * the blue component in bits 0-7. Alpha has default value - 255.
345     *
346     * @param rgb
347     *            the RGB components.
348     */
349    public Color(int rgb) {
350        value = rgb | 0xFF000000;
351    }
352
353    /**
354     * Instantiates a new color with the specified red, green, blue and alpha
355     * components.
356     *
357     * @param r
358     *            the red component.
359     * @param g
360     *            the green component.
361     * @param b
362     *            the blue component.
363     * @param a
364     *            the alpha component.
365     */
366    public Color(float r, float g, float b, float a) {
367        this((int)(r * 255 + 0.5), (int)(g * 255 + 0.5), (int)(b * 255 + 0.5), (int)(a * 255 + 0.5));
368        falpha = a;
369        fvalue = new float[3];
370        fvalue[0] = r;
371        fvalue[1] = g;
372        fvalue[2] = b;
373        frgbvalue = fvalue;
374    }
375
376    /**
377     * Instantiates a new color with the specified red, green, and blue
378     * components and default alpha value - 1.0.
379     *
380     * @param r
381     *            the red component.
382     * @param g
383     *            the green component.
384     * @param b
385     *            the blue component.
386     */
387    public Color(float r, float g, float b) {
388        this(r, g, b, 1.0f);
389    }
390
391    public PaintContext createContext(ColorModel cm, Rectangle r, Rectangle2D r2d,
392            AffineTransform xform, RenderingHints rhs) {
393        if (currentPaintContext != null) {
394            return currentPaintContext;
395        }
396        currentPaintContext = new Color.ColorPaintContext(value);
397        return currentPaintContext;
398    }
399
400    /**
401     * Returns a string representation of the Color object.
402     *
403     * @return the string representation of the Color object.
404     */
405    @Override
406    public String toString() {
407        /*
408         * The format of the string is based on 1.5 release behavior which can
409         * be revealed using the following code: Color c = new Color(1, 2, 3);
410         * System.out.println(c);
411         */
412
413        return getClass().getName() + "[r=" + getRed() + //$NON-NLS-1$
414                ",g=" + getGreen() + //$NON-NLS-1$
415                ",b=" + getBlue() + //$NON-NLS-1$
416                "]"; //$NON-NLS-1$
417    }
418
419    /**
420     * Compares the specified Object to the Color.
421     *
422     * @param obj
423     *            the Object to be compared.
424     * @return true, if the specified Object is a Color whose value is equal to
425     *         this Color, false otherwise.
426     */
427    @Override
428    public boolean equals(Object obj) {
429        if (obj instanceof Color) {
430            return ((Color)obj).value == this.value;
431        }
432        return false;
433    }
434
435    /**
436     * Returns a float array containing the color and alpha components of the
437     * Color in the specified ColorSpace.
438     *
439     * @param colorSpace
440     *            the specified ColorSpace.
441     * @param components
442     *            the results of this method will be written to this float
443     *            array. If null, a float array will be created.
444     * @return the color and alpha components in a float array.
445     */
446    public float[] getComponents(ColorSpace colorSpace, float[] components) {
447        int nComps = colorSpace.getNumComponents();
448        if (components == null) {
449            components = new float[nComps + 1];
450        }
451
452        getColorComponents(colorSpace, components);
453
454        if (frgbvalue != null) {
455            components[nComps] = falpha;
456        } else {
457            components[nComps] = getAlpha() / 255f;
458        }
459
460        return components;
461    }
462
463    /**
464     * Returns a float array containing the color components of the Color in the
465     * specified ColorSpace.
466     *
467     * @param colorSpace
468     *            the specified ColorSpace.
469     * @param components
470     *            the results of this method will be written to this float
471     *            array. If null, a float array will be created.
472     * @return the color components in a float array.
473     */
474    public float[] getColorComponents(ColorSpace colorSpace, float[] components) {
475        float[] cieXYZComponents = getColorSpace().toCIEXYZ(getColorComponents(null));
476        float[] csComponents = colorSpace.fromCIEXYZ(cieXYZComponents);
477
478        if (components == null) {
479            return csComponents;
480        }
481
482        for (int i = 0; i < csComponents.length; i++) {
483            components[i] = csComponents[i];
484        }
485
486        return components;
487    }
488
489    /**
490     * Gets the ColorSpace of this Color.
491     *
492     * @return the ColorSpace object.
493     */
494    public ColorSpace getColorSpace() {
495        if (cs == null) {
496            cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
497        }
498
499        return cs;
500    }
501
502    /**
503     * Creates a new Color which is a darker than this Color according to a
504     * fixed scale factor.
505     *
506     * @return the darker Color.
507     */
508    public Color darker() {
509        return new Color((int)(getRed() * SCALE_FACTOR), (int)(getGreen() * SCALE_FACTOR),
510                (int)(getBlue() * SCALE_FACTOR));
511    }
512
513    /**
514     * Creates a new Color which is a brighter than this Color.
515     *
516     * @return the brighter Color.
517     */
518    public Color brighter() {
519
520        int r = getRed();
521        int b = getBlue();
522        int g = getGreen();
523
524        if (r == 0 && b == 0 && g == 0) {
525            return new Color(MIN_SCALABLE, MIN_SCALABLE, MIN_SCALABLE);
526        }
527
528        if (r < MIN_SCALABLE && r != 0) {
529            r = MIN_SCALABLE;
530        } else {
531            r = (int)(r / SCALE_FACTOR);
532            r = (r > 255) ? 255 : r;
533        }
534
535        if (b < MIN_SCALABLE && b != 0) {
536            b = MIN_SCALABLE;
537        } else {
538            b = (int)(b / SCALE_FACTOR);
539            b = (b > 255) ? 255 : b;
540        }
541
542        if (g < MIN_SCALABLE && g != 0) {
543            g = MIN_SCALABLE;
544        } else {
545            g = (int)(g / SCALE_FACTOR);
546            g = (g > 255) ? 255 : g;
547        }
548
549        return new Color(r, g, b);
550    }
551
552    /**
553     * Returns a float array containing the color and alpha components of the
554     * Color in the default sRGB color space.
555     *
556     * @param components
557     *            the results of this method will be written to this float
558     *            array. A new float array will be created if this argument is
559     *            null.
560     * @return the RGB color and alpha components in a float array.
561     */
562    public float[] getRGBComponents(float[] components) {
563        if (components == null) {
564            components = new float[4];
565        }
566
567        if (frgbvalue != null) {
568            components[3] = falpha;
569        } else {
570            components[3] = getAlpha() / 255f;
571        }
572
573        getRGBColorComponents(components);
574
575        return components;
576    }
577
578    /**
579     * Returns a float array containing the color components of the Color in the
580     * default sRGB color space.
581     *
582     * @param components
583     *            the results of this method will be written to this float
584     *            array. A new float array will be created if this argument is
585     *            null.
586     * @return the RGB color components in a float array.
587     */
588    public float[] getRGBColorComponents(float[] components) {
589        if (components == null) {
590            components = new float[3];
591        }
592
593        if (frgbvalue != null) {
594            components[2] = frgbvalue[2];
595            components[1] = frgbvalue[1];
596            components[0] = frgbvalue[0];
597        } else {
598            components[2] = getBlue() / 255f;
599            components[1] = getGreen() / 255f;
600            components[0] = getRed() / 255f;
601        }
602
603        return components;
604    }
605
606    /**
607     * Returns a float array which contains the color and alpha components of
608     * the Color in the ColorSpace of the Color.
609     *
610     * @param components
611     *            the results of this method will be written to this float
612     *            array. A new float array will be created if this argument is
613     *            null.
614     * @return the color and alpha components in a float array.
615     */
616    public float[] getComponents(float[] components) {
617        if (fvalue == null) {
618            return getRGBComponents(components);
619        }
620
621        int nColorComps = fvalue.length;
622
623        if (components == null) {
624            components = new float[nColorComps + 1];
625        }
626
627        getColorComponents(components);
628
629        components[nColorComps] = falpha;
630
631        return components;
632    }
633
634    /**
635     * Returns a float array which contains the color components of the Color in
636     * the ColorSpace of the Color.
637     *
638     * @param components
639     *            the results of this method will be written to this float
640     *            array. A new float array will be created if this argument is
641     *            null.
642     * @return the color components in a float array.
643     */
644    public float[] getColorComponents(float[] components) {
645        if (fvalue == null) {
646            return getRGBColorComponents(components);
647        }
648
649        if (components == null) {
650            components = new float[fvalue.length];
651        }
652
653        for (int i = 0; i < fvalue.length; i++) {
654            components[i] = fvalue[i];
655        }
656
657        return components;
658    }
659
660    /**
661     * Returns a hash code of this Color object.
662     *
663     * @return a hash code of this Color object.
664     */
665    @Override
666    public int hashCode() {
667        return value;
668    }
669
670    public int getTransparency() {
671        switch (getAlpha()) {
672            case 0xff:
673                return Transparency.OPAQUE;
674            case 0:
675                return Transparency.BITMASK;
676            default:
677                return Transparency.TRANSLUCENT;
678        }
679    }
680
681    /**
682     * Gets the red component of the Color in the range 0-255.
683     *
684     * @return the red component of the Color.
685     */
686    public int getRed() {
687        return (value >> 16) & 0xFF;
688    }
689
690    /**
691     * Gets the RGB value that represents the color in the default sRGB
692     * ColorModel.
693     *
694     * @return the RGB color value in the default sRGB ColorModel.
695     */
696    public int getRGB() {
697        return value;
698    }
699
700    /**
701     * Gets the green component of the Color in the range 0-255.
702     *
703     * @return the green component of the Color.
704     */
705    public int getGreen() {
706        return (value >> 8) & 0xFF;
707    }
708
709    /**
710     * Gets the blue component of the Color in the range 0-255.
711     *
712     * @return the blue component of the Color.
713     */
714    public int getBlue() {
715        return value & 0xFF;
716    }
717
718    /**
719     * Gets the alpha component of the Color in the range 0-255.
720     *
721     * @return the alpha component of the Color.
722     */
723    public int getAlpha() {
724        return (value >> 24) & 0xFF;
725    }
726
727    /**
728     * Gets the Color from the specified string, or returns the Color specified
729     * by the second parameter.
730     *
731     * @param nm
732     *            the specified string.
733     * @param def
734     *            the default Color.
735     * @return the color from the specified string, or the Color specified by
736     *         the second parameter.
737     */
738    public static Color getColor(String nm, Color def) {
739        Integer integer = Integer.getInteger(nm);
740
741        if (integer == null) {
742            return def;
743        }
744
745        return new Color(integer.intValue());
746    }
747
748    /**
749     * Gets the Color from the specified string, or returns the Color converted
750     * from the second parameter.
751     *
752     * @param nm
753     *            the specified string.
754     * @param def
755     *            the default Color.
756     * @return the color from the specified string, or the Color converted from
757     *         the second parameter.
758     */
759    public static Color getColor(String nm, int def) {
760        Integer integer = Integer.getInteger(nm);
761
762        if (integer == null) {
763            return new Color(def);
764        }
765
766        return new Color(integer.intValue());
767    }
768
769    /**
770     * Gets the Color from the specified String.
771     *
772     * @param nm
773     *            the specified string.
774     * @return the Color object, or null.
775     */
776    public static Color getColor(String nm) {
777        Integer integer = Integer.getInteger(nm);
778
779        if (integer == null) {
780            return null;
781        }
782
783        return new Color(integer.intValue());
784    }
785
786    /**
787     * Decodes a String to an integer and returns the specified opaque Color.
788     *
789     * @param nm
790     *            the String which represents an opaque color as a 24-bit
791     *            integer.
792     * @return the Color object from the given String.
793     * @throws NumberFormatException
794     *             if the specified string can not be converted to an integer.
795     */
796    public static Color decode(String nm) throws NumberFormatException {
797        Integer integer = Integer.decode(nm);
798        return new Color(integer.intValue());
799    }
800
801    /**
802     * Gets a Color object using the specified values of the HSB color model.
803     *
804     * @param h
805     *            the hue component of the Color.
806     * @param s
807     *            the saturation of the Color.
808     * @param b
809     *            the brightness of the Color.
810     * @return a color object with the specified hue, saturation and brightness
811     *         values.
812     */
813    public static Color getHSBColor(float h, float s, float b) {
814        return new Color(HSBtoRGB(h, s, b));
815    }
816
817    /**
818     * Converts the Color specified by the RGB model to an equivalent color in
819     * the HSB model.
820     *
821     * @param r
822     *            the red component.
823     * @param g
824     *            the green component.
825     * @param b
826     *            the blue component.
827     * @param hsbvals
828     *            the array of result hue, saturation, brightness values or
829     *            null.
830     * @return the float array of hue, saturation, brightness values.
831     */
832    public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
833        if (hsbvals == null) {
834            hsbvals = new float[3];
835        }
836
837        int V = Math.max(b, Math.max(r, g));
838        int temp = Math.min(b, Math.min(r, g));
839
840        float H, S, B;
841
842        B = V / 255.f;
843
844        if (V == temp) {
845            H = S = 0;
846        } else {
847            S = (V - temp) / ((float)V);
848
849            float Cr = (V - r) / (float)(V - temp);
850            float Cg = (V - g) / (float)(V - temp);
851            float Cb = (V - b) / (float)(V - temp);
852
853            if (r == V) {
854                H = Cb - Cg;
855            } else if (g == V) {
856                H = 2 + Cr - Cb;
857            } else {
858                H = 4 + Cg - Cr;
859            }
860
861            H /= 6.f;
862            if (H < 0) {
863                H++;
864            }
865        }
866
867        hsbvals[0] = H;
868        hsbvals[1] = S;
869        hsbvals[2] = B;
870
871        return hsbvals;
872    }
873
874    /**
875     * Converts the Color specified by the HSB model to an equivalent color in
876     * the default RGB model.
877     *
878     * @param hue
879     *            the hue component of the Color.
880     * @param saturation
881     *            the saturation of the Color.
882     * @param brightness
883     *            the brightness of the Color.
884     * @return the RGB value of the color with the specified hue, saturation and
885     *         brightness.
886     */
887    public static int HSBtoRGB(float hue, float saturation, float brightness) {
888        float fr, fg, fb;
889
890        if (saturation == 0) {
891            fr = fg = fb = brightness;
892        } else {
893            float H = (hue - (float)Math.floor(hue)) * 6;
894            int I = (int)Math.floor(H);
895            float F = H - I;
896            float M = brightness * (1 - saturation);
897            float N = brightness * (1 - saturation * F);
898            float K = brightness * (1 - saturation * (1 - F));
899
900            switch (I) {
901                case 0:
902                    fr = brightness;
903                    fg = K;
904                    fb = M;
905                    break;
906                case 1:
907                    fr = N;
908                    fg = brightness;
909                    fb = M;
910                    break;
911                case 2:
912                    fr = M;
913                    fg = brightness;
914                    fb = K;
915                    break;
916                case 3:
917                    fr = M;
918                    fg = N;
919                    fb = brightness;
920                    break;
921                case 4:
922                    fr = K;
923                    fg = M;
924                    fb = brightness;
925                    break;
926                case 5:
927                    fr = brightness;
928                    fg = M;
929                    fb = N;
930                    break;
931                default:
932                    fr = fb = fg = 0; // impossible, to supress compiler error
933            }
934        }
935
936        int r = (int)(fr * 255. + 0.5);
937        int g = (int)(fg * 255. + 0.5);
938        int b = (int)(fb * 255. + 0.5);
939
940        return (r << 16) | (g << 8) | b | 0xFF000000;
941    }
942
943    /**
944     * The Class ColorPaintContext.
945     */
946    class ColorPaintContext implements PaintContext {
947
948        /**
949         * The RGB value.
950         */
951        int rgbValue;
952
953        /**
954         * The saved raster.
955         */
956        WritableRaster savedRaster = null;
957
958        /**
959         * Instantiates a new color paint context.
960         *
961         * @param rgb
962         *            the RGB value.
963         */
964        protected ColorPaintContext(int rgb) {
965            rgbValue = rgb;
966        }
967
968        public void dispose() {
969            savedRaster = null;
970        }
971
972        public ColorModel getColorModel() {
973            return ColorModel.getRGBdefault();
974        }
975
976        public Raster getRaster(int x, int y, int w, int h) {
977            if (savedRaster == null || w != savedRaster.getWidth() || h != savedRaster.getHeight()) {
978                savedRaster = getColorModel().createCompatibleWritableRaster(w, h);
979
980                // Suppose we have here simple INT/RGB color/sample model
981                DataBufferInt intBuffer = (DataBufferInt)savedRaster.getDataBuffer();
982                int rgbValues[] = intBuffer.getData();
983                int rgbFillValue = rgbValue;
984                Arrays.fill(rgbValues, rgbFillValue);
985            }
986
987            return savedRaster;
988        }
989    }
990}
991