42 |
import java.awt.geom.AffineTransform; |
import java.awt.geom.AffineTransform; |
43 |
import java.awt.geom.Rectangle2D; |
import java.awt.geom.Rectangle2D; |
44 |
import java.awt.image.ColorModel; |
import java.awt.image.ColorModel; |
|
import java.awt.image.Raster; |
|
45 |
import java.io.Serializable; |
import java.io.Serializable; |
46 |
|
|
47 |
/** |
/** |
205 |
/** Internal mask for blue. */ |
/** Internal mask for blue. */ |
206 |
private static final int BLUE_MASK = 255; |
private static final int BLUE_MASK = 255; |
207 |
|
|
208 |
/** Internal mask for alpha. */ |
/** Internal mask for alpha. Package visible for use in subclass. */ |
209 |
private static final int ALPHA_MASK = 255 << 24; |
static final int ALPHA_MASK = 255 << 24; |
210 |
|
|
211 |
/** Amount to scale a color by when brightening or darkening. */ |
/** Amount to scale a color by when brightening or darkening. */ |
212 |
private static final float BRIGHT_SCALE = 0.7f; |
private static final float BRIGHT_SCALE = 0.7f; |
213 |
|
|
214 |
/** |
/** |
215 |
* The color value, in sRGB. Note that the actual color may be more |
* The color value, in sRGB. Note that the actual color may be more |
216 |
* precise if frgbvalue or fvalue is non-null. This stores alpha, red, |
* precise if frgbvalue or fvalue is non-null. This class stores alpha, red, |
217 |
* green, and blue, each 0-255, packed in an int. |
* green, and blue, each 0-255, packed in an int. However, the subclass |
218 |
|
* SystemColor stores an index into an array. Therefore, for serial |
219 |
|
* compatibility (and because of poor design on Sun's part), this value |
220 |
|
* cannot be used directly; instead you must use <code>getRGB()</code>. |
221 |
* |
* |
222 |
* @see #getRGB() |
* @see #getRGB() |
223 |
* @serial the RGB value of the color |
* @serial the value of the color, whether an RGB literal or array index |
224 |
*/ |
*/ |
225 |
private final int value; |
final int value; |
226 |
|
|
227 |
/** |
/** |
228 |
* The color value, in sRGB. This may be null if the color was constructed |
* The color value, in sRGB. This may be null if the color was constructed |
249 |
private float[] fvalue; |
private float[] fvalue; |
250 |
|
|
251 |
/** |
/** |
252 |
* The alpha value. This is in the range 0.0f - 1.0f. |
* The alpha value. This is in the range 0.0f - 1.0f, but is invalid if |
253 |
|
* deserialized as 0.0 when frgbvalue is null. |
254 |
* |
* |
255 |
* @see #getRGBComponents(float[]) |
* @see #getRGBComponents(float[]) |
256 |
* @see #getComponents(float[]) |
* @see #getComponents(float[]) |
257 |
* @serial the alpha component of this color. |
* @serial the alpha component of this color |
258 |
* @since 1.2 |
* @since 1.2 |
259 |
*/ |
*/ |
260 |
private final float falpha; |
private final float falpha; |
270 |
*/ |
*/ |
271 |
private final ColorSpace cs; |
private final ColorSpace cs; |
272 |
|
|
273 |
/** The paint context for this solid color. */ |
/** |
274 |
private transient PaintContext context; |
* The paint context for this solid color. Package visible for use in |
275 |
|
* subclass. |
276 |
|
*/ |
277 |
|
transient ColorPaintContext context; |
278 |
|
|
279 |
/** |
/** |
280 |
* Initializes a new instance of <code>Color</code> using the specified |
* Initializes a new instance of <code>Color</code> using the specified |
363 |
*/ |
*/ |
364 |
public Color(int value, boolean hasalpha) |
public Color(int value, boolean hasalpha) |
365 |
{ |
{ |
366 |
|
// Note: SystemColor calls this constructor, setting falpha to 0; but |
367 |
|
// code in getRGBComponents correctly reports falpha as 1.0 to the user |
368 |
|
// for all instances of SystemColor since frgbvalue is left null here. |
369 |
if (hasalpha) |
if (hasalpha) |
370 |
falpha = ((value & ALPHA_MASK) >> 24) / 255f; |
falpha = ((value & ALPHA_MASK) >> 24) / 255f; |
371 |
else |
else |
457 |
*/ |
*/ |
458 |
public int getRed() |
public int getRed() |
459 |
{ |
{ |
460 |
return (value & RED_MASK) >> 16; |
// Do not inline getRGB() to value, because of SystemColor. |
461 |
|
return (getRGB() & RED_MASK) >> 16; |
462 |
} |
} |
463 |
|
|
464 |
/** |
/** |
470 |
*/ |
*/ |
471 |
public int getGreen() |
public int getGreen() |
472 |
{ |
{ |
473 |
return (value & GREEN_MASK) >> 8; |
// Do not inline getRGB() to value, because of SystemColor. |
474 |
|
return (getRGB() & GREEN_MASK) >> 8; |
475 |
} |
} |
476 |
|
|
477 |
/** |
/** |
483 |
*/ |
*/ |
484 |
public int getBlue() |
public int getBlue() |
485 |
{ |
{ |
486 |
return value & BLUE_MASK; |
// Do not inline getRGB() to value, because of SystemColor. |
487 |
|
return getRGB() & BLUE_MASK; |
488 |
} |
} |
489 |
|
|
490 |
/** |
/** |
495 |
*/ |
*/ |
496 |
public int getAlpha() |
public int getAlpha() |
497 |
{ |
{ |
498 |
return (value & ALPHA_MASK) >> 24; |
// Do not inline getRGB() to value, because of SystemColor. |
499 |
|
return (getRGB() & ALPHA_MASK) >> 24; |
500 |
} |
} |
501 |
|
|
502 |
/** |
/** |
527 |
*/ |
*/ |
528 |
public Color brighter() |
public Color brighter() |
529 |
{ |
{ |
530 |
// We have to special case 0-2 because they won't scale by division. |
// Do not inline getRGB() to this.value, because of SystemColor. |
531 |
|
int value = getRGB(); |
532 |
int red = (value & RED_MASK) >> 16; |
int red = (value & RED_MASK) >> 16; |
533 |
int green = (value & GREEN_MASK) >> 8; |
int green = (value & GREEN_MASK) >> 8; |
534 |
int blue = value & BLUE_MASK; |
int blue = value & BLUE_MASK; |
535 |
|
// We have to special case 0-2 because they won't scale by division. |
536 |
red = red < 3 ? 3 : (int) Math.min(255, red / BRIGHT_SCALE); |
red = red < 3 ? 3 : (int) Math.min(255, red / BRIGHT_SCALE); |
537 |
green = green < 3 ? 3 : (int) Math.min(255, green / BRIGHT_SCALE); |
green = green < 3 ? 3 : (int) Math.min(255, green / BRIGHT_SCALE); |
538 |
blue = blue < 3 ? 3 : (int) Math.min(255, blue / BRIGHT_SCALE); |
blue = blue < 3 ? 3 : (int) Math.min(255, blue / BRIGHT_SCALE); |
550 |
*/ |
*/ |
551 |
public Color darker() |
public Color darker() |
552 |
{ |
{ |
553 |
|
// Do not inline getRGB() to this.value, because of SystemColor. |
554 |
|
int value = getRGB(); |
555 |
return new Color((int) (((value & RED_MASK) >> 16) * BRIGHT_SCALE), |
return new Color((int) (((value & RED_MASK) >> 16) * BRIGHT_SCALE), |
556 |
(int) (((value & GREEN_MASK) >> 8) * BRIGHT_SCALE), |
(int) (((value & GREEN_MASK) >> 8) * BRIGHT_SCALE), |
557 |
(int) ((value & BLUE_MASK) * BRIGHT_SCALE), 255); |
(int) ((value & BLUE_MASK) * BRIGHT_SCALE), 255); |
573 |
* be true if and only if the specified object is an instance of |
* be true if and only if the specified object is an instance of |
574 |
* <code>Color</code> and has the same 8-bit integer red, green, and blue |
* <code>Color</code> and has the same 8-bit integer red, green, and blue |
575 |
* values as this object. Note that two colors may be slightly different |
* values as this object. Note that two colors may be slightly different |
576 |
* as float values, but round to the same integer values. |
* as float values, but round to the same integer values. Also note that |
577 |
|
* this does not accurately compare SystemColors, since that class does |
578 |
|
* not store its internal data in RGB format like regular colors. |
579 |
* |
* |
580 |
* @param obj the object to compare to |
* @param obj the object to compare to |
581 |
* @return true if the specified object is equal to this one |
* @return true if the specified object is semantically equal to this one |
582 |
*/ |
*/ |
583 |
public boolean equals(Object obj) |
public boolean equals(Object obj) |
584 |
{ |
{ |
807 |
if (array == null) |
if (array == null) |
808 |
array = new float[4]; |
array = new float[4]; |
809 |
getRGBColorComponents(array); |
getRGBColorComponents(array); |
810 |
array[3] = falpha; |
// Stupid serialization issues require this check. |
811 |
|
array[3] = (falpha == 0 && frgbvalue == null |
812 |
|
? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); |
813 |
return array; |
return array; |
814 |
} |
} |
815 |
|
|
830 |
return array; // Optimization for getColorComponents(float[]). |
return array; // Optimization for getColorComponents(float[]). |
831 |
if (frgbvalue == null) |
if (frgbvalue == null) |
832 |
{ |
{ |
833 |
|
// Do not inline getRGB() to this.value, because of SystemColor. |
834 |
|
int value = getRGB(); |
835 |
frgbvalue = new float[] { ((value & RED_MASK) >> 16) / 255f, |
frgbvalue = new float[] { ((value & RED_MASK) >> 16) / 255f, |
836 |
((value & GREEN_MASK) >> 8) / 255f, |
((value & GREEN_MASK) >> 8) / 255f, |
837 |
(value & BLUE_MASK) / 255f }; |
(value & BLUE_MASK) / 255f }; |
859 |
if (array == null) |
if (array == null) |
860 |
array = new float[1 + numComponents]; |
array = new float[1 + numComponents]; |
861 |
getColorComponents(array); |
getColorComponents(array); |
862 |
array[numComponents] = falpha; |
// Stupid serialization issues require this check. |
863 |
|
array[numComponents] = (falpha == 0 && frgbvalue == null |
864 |
|
? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); |
865 |
return array; |
return array; |
866 |
} |
} |
867 |
|
|
905 |
if (array == null) |
if (array == null) |
906 |
array = new float[1 + numComponents]; |
array = new float[1 + numComponents]; |
907 |
getColorComponents(space, array); |
getColorComponents(space, array); |
908 |
array[numComponents] = falpha; |
// Stupid serialization issues require this check. |
909 |
|
array[numComponents] = (falpha == 0 && frgbvalue == null |
910 |
|
? ((getRGB() & ALPHA_MASK) >> 24) / 255f : falpha); |
911 |
return array; |
return array; |
912 |
} |
} |
913 |
|
|
946 |
/** |
/** |
947 |
* Returns a paint context, used for filling areas of a raster scan with |
* Returns a paint context, used for filling areas of a raster scan with |
948 |
* this color. Since the color is constant across the entire rectangle, and |
* this color. Since the color is constant across the entire rectangle, and |
949 |
* since it is always in sRGB space, this returns the same object, regardless |
* since it is always in sRGB space, this implementation returns the same |
950 |
* of the parameters. |
* object, regardless of the parameters. Subclasses, however, may have a |
951 |
|
* mutable result. |
952 |
* |
* |
953 |
* @param cm the requested color model, ignored |
* @param cm the requested color model, ignored |
954 |
* @param deviceBounds the bounding box in device coordinates, ignored |
* @param deviceBounds the bounding box in device coordinates, ignored |
955 |
* @param userBounds the bounding box in user coordinates, ignored |
* @param userBounds the bounding box in user coordinates, ignored |
956 |
* @param xform the bounds transformation, ignored |
* @param xform the bounds transformation, ignored |
957 |
* @param hints any rendering hints, ignored |
* @param hints any rendering hints, ignored |
958 |
|
* @return a context for painting this solid color |
959 |
*/ |
*/ |
960 |
public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, |
public PaintContext createContext(ColorModel cm, Rectangle deviceBounds, |
961 |
Rectangle2D userBounds, |
Rectangle2D userBounds, |
963 |
RenderingHints hints) |
RenderingHints hints) |
964 |
{ |
{ |
965 |
if (context == null) |
if (context == null) |
966 |
context = new ColorPaintContext(this); |
context = new ColorPaintContext(value); |
967 |
return context; |
return context; |
968 |
} |
} |
969 |
|
|
974 |
*/ |
*/ |
975 |
public int getTransparency() |
public int getTransparency() |
976 |
{ |
{ |
977 |
int alpha = value & ALPHA_MASK; |
// Do not inline getRGB() to this.value, because of SystemColor. |
978 |
|
int alpha = getRGB() & ALPHA_MASK; |
979 |
return alpha == (255 << 24) ? OPAQUE : alpha == 0 ? BITMASK : TRANSLUCENT; |
return alpha == (255 << 24) ? OPAQUE : alpha == 0 ? BITMASK : TRANSLUCENT; |
980 |
} |
} |
981 |
|
|
1001 |
return (alphaval << 24) | (redval << 16) | (greenval << 8) | blueval; |
return (alphaval << 24) | (redval << 16) | (greenval << 8) | blueval; |
1002 |
} |
} |
1003 |
} // class Color |
} // class Color |
|
|
|
|
/** |
|
|
* This class provides a paint context which will fill a rectanglar region of |
|
|
* a raster scan with the given color. However, it is not yet implemented. |
|
|
* |
|
|
* @author Eric Blake <ebb9@email.byu.edu> |
|
|
*/ |
|
|
class ColorPaintContext implements PaintContext |
|
|
{ |
|
|
/** The color to fill any raster with. */ |
|
|
private final Color color; |
|
|
|
|
|
/** |
|
|
* Create the context for a given color. |
|
|
*/ |
|
|
ColorPaintContext(Color c) |
|
|
{ |
|
|
color = c; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Release the resources allocated for the paint. As the color is constant, |
|
|
* there aren't any resources. |
|
|
*/ |
|
|
public void dispose() |
|
|
{ |
|
|
} |
|
|
|
|
|
/** |
|
|
* Return the color model of this context. This ignores the model passed |
|
|
* in the request, since colors are always in sRGB. |
|
|
* |
|
|
* @return the context color model |
|
|
*/ |
|
|
public ColorModel getColorModel() |
|
|
{ |
|
|
return ColorModel.getRGBdefault(); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Return a raster containing the colors for the graphics operation. |
|
|
* |
|
|
* @param x the x-coordinate, in device space |
|
|
* @param y the y-coordinate, in device space |
|
|
* @param w the width, in device space |
|
|
* @param h the height, in device space |
|
|
* @return a raster for the given area and color |
|
|
*/ |
|
|
public Raster getRaster(int x, int y, int w, int h) |
|
|
{ |
|
|
// XXX Implement. Sun uses undocumented implementation class |
|
|
// sun.awt.image.IntegerInterleavedRaster. |
|
|
throw new Error("not implemented"); |
|
|
} |
|
|
} // class ColorPaintContext |
|