diff --git a/sources/net.sf.j2s.core/META-INF/MANIFEST.MF b/sources/net.sf.j2s.core/META-INF/MANIFEST.MF index be6986b68..bac5aa6c0 100644 --- a/sources/net.sf.j2s.core/META-INF/MANIFEST.MF +++ b/sources/net.sf.j2s.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Java2Script Core Bundle-SymbolicName: net.sf.j2s.core;singleton:=true -Bundle-Version: 3.2.7 +Bundle-Version: 3.2.8 Bundle-Activator: net.sf.j2s.core.CorePlugin Bundle-Vendor: j2s.sourceforge.net Require-Bundle: org.eclipse.core.runtime, diff --git a/sources/net.sf.j2s.core/dist/examples.htm b/sources/net.sf.j2s.core/dist/examples.htm new file mode 100644 index 000000000..b1952d211 --- /dev/null +++ b/sources/net.sf.j2s.core/dist/examples.htm @@ -0,0 +1,93 @@ + +
+
+The pages listed below are a few of the thousands of implementations
+of java2script/SwingJS that can be found on the web. Phase III is the
+current phase of development, as of this writing.
+If you have a Java applet or application that you would like to see running in JavaScript
+or you have questions, feel free to contact
+the principal developer of java2script/SwingJS, Bob Hanson at hansonr@stolaf.edu.
+For more information, see also the GitHub main page for the java2script/SwingJS project
+or the main page for Jmol/JSmol.
+ + | |
+
++Phase I (2012-15): AWT Jmol applet to AWT-like JSmol (First-generation java2script transpiler) ++ | |
JSmol |
+Proteopedia - Life in 3D, a full *pedia devoted to the structure and function of biological macromolecules, with extensive contextualization of Jmol as JSmol.
+ +CheMagic Virtual Model Kit, the most fully developed on-line chemical model kit ever, deeply integrating Jmol to allow far more than just making a molecular model. + +symmetry@otterbein, one of the most beloved web pages for students of inorganic chemistry, with multiple examples of every three-dimensional point group in relation to molecular structure. + +Simple.htm, a general page for exploring biological macromolecules (proteins, nucleic acids, carbohydrates) + +Simple2.htm, a general page for exploring small molecules + +nmr_predict_1H.htm Draw or search by name for a chemical structure and +simulate its proton nuclear magnect resonance (NMR) spectrum interactively + +viewspec2, the front-end spectral viewing and analysis page for St. Olaf College's +Bruker 400 MHz cyberenabled NMR spectrometer (with 120-sample BACS autosampler) + +directory of sample JSmol pages in the +Jmol/JSmol distribution ZIP file + + |
++Phase II (2016): Expansion to Swing and other applications and applets (“java2script/SwingJS”) ++ | |
Additional applet demos |
+SwingJS Examples
+63 physics, math, and chemistry applets created over the course of six months still using the first-generation transpiler.
+ + |
++Phase III (2017-19): Second-generation transpiler and full AWT+Swing run-time environment applied to massive applet and application projects ++ | |
+Physlet Physics + | main page, with 1200 interactive simulations in 39 chapters of introductory physics
+ + |
+MathePrisma + |
+ModulK.htm, with 450 interactive applets fully embedded in more than 50 engaging introductions to the major areas of mathematics on 1300 web pages (in German; click on Verschiebungen at the bottom of the page to start the story)
+ + |
+Jalview + |
+The JalviewJS examples page illustrating ways the Jalview multisequence alignment desktop can be created within a browser
+ + |
+ImageJ/SCIFIO + |
+TestJS-core.html Our first-ever test of transpiled Java SCIFIO in JavaScript, from the December 2019 Dresden bioimaging hackathon
+ +io_scif_img_ConvertImg.html A second test, using SCIFIO to convert and download an ICS+IDS image to TIFF format (creates and downloads a TIFF file viewable in FIJI) + + |
DirectColorModel
with alpha. The color
* data in this image is considered not to be premultiplied with alpha. When
* this type is used as the imageType
argument to a
- * BufferedImage
constructor, the created image is consistent
- * with images created in the JDK1.1 and earlier releases.
+ * BufferedImage
constructor, the created image is consistent with
+ * images created in the JDK1.1 and earlier releases.
*/
public static final int TYPE_INT_ARGB = 2;
- /**
- * Represents an image with 8-bit RGBA color components packed into
- * integer pixels. The image has a DirectColorModel
- * with alpha. The color data in this image is considered to be
- * premultiplied with alpha.
+ /**
+ * Represents an image with 8-bit RGBA color components packed into integer
+ * pixels. The image has a DirectColorModel
with alpha. The color
+ * data in this image is considered to be premultiplied with alpha.
*/
- public static final int TYPE_INT_ARGB_PRE = 3;
+ public static final int TYPE_INT_ARGB_PRE = 3;
//
- /**
- * Represents an image with 8-bit RGB color components, corresponding
- * to a Windows- or Solaris- style BGR color model, with the colors
- * Blue, Green, and Red packed into integer pixels. There is no alpha.
- * The image has a {@link DirectColorModel}.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
+ /**
+ * Represents an image with 8-bit RGB color components, corresponding to a
+ * Windows- or Solaris- style BGR color model, with the colors Blue, Green, and
+ * Red packed into integer pixels. There is no alpha. The image has a
+ * {@link DirectColorModel}. When data with non-opaque alpha is stored in an
+ * image of this type, the color data must be adjusted to a non-premultiplied
+ * form and the alpha discarded, as described in the
* {@link java.awt.AlphaComposite} documentation.
*/
- public static final int TYPE_INT_BGR = 4;
-
- /**
- * Represents an image with 8-bit RGB color components, corresponding
- * to a Windows-style BGR color model) with the colors Blue, Green,
- * and Red stored in 3 bytes. There is no alpha. The image has a
- * ComponentColorModel
.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
- * {@link java.awt.AlphaComposite} documentation.
+ public static final int TYPE_INT_BGR = 4;
+
+ /**
+ * Represents an image with 8-bit RGB color components, corresponding to a
+ * Windows-style BGR color model) with the colors Blue, Green, and Red stored in
+ * 3 bytes. There is no alpha. The image has a ComponentColorModel
.
+ * When data with non-opaque alpha is stored in an image of this type, the color
+ * data must be adjusted to a non-premultiplied form and the alpha discarded, as
+ * described in the {@link java.awt.AlphaComposite} documentation.
*/
- public static final int TYPE_3BYTE_BGR = 5;
-
- /**
- * Represents an image with 8-bit RGBA color components with the colors
- * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
- * image has a ComponentColorModel
with alpha. The
- * color data in this image is considered not to be premultiplied with
- * alpha. The byte data is interleaved in a single
- * byte array in the order A, B, G, R
- * from lower to higher byte addresses within each pixel.
- */
- public static final int TYPE_4BYTE_ABGR = 6;
-
- /**
- * Represents an image with 8-bit RGBA color components with the colors
- * Blue, Green, and Red stored in 3 bytes and 1 byte of alpha. The
- * image has a ComponentColorModel
with alpha. The color
- * data in this image is considered to be premultiplied with alpha.
- * The byte data is interleaved in a single byte array in the order
- * A, B, G, R from lower to higher byte addresses within each pixel.
- */
- public static final int TYPE_4BYTE_ABGR_PRE = 7;
-
- /**
- * Represents an image with 5-6-5 RGB color components (5-bits red,
- * 6-bits green, 5-bits blue) with no alpha. This image has
- * a DirectColorModel
.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
- * {@link java.awt.AlphaComposite} documentation.
+ public static final int TYPE_3BYTE_BGR = 5;
+
+ /**
+ * Represents an image with 8-bit RGBA color components with the colors Blue,
+ * Green, and Red stored in 3 bytes and 1 byte of alpha. The image has a
+ * ComponentColorModel
with alpha. The color data in this image is
+ * considered not to be premultiplied with alpha. The byte data is interleaved
+ * in a single byte array in the order A, B, G, R from lower to higher byte
+ * addresses within each pixel.
*/
- public static final int TYPE_USHORT_565_RGB = 8;
-
- /**
- * Represents an image with 5-5-5 RGB color components (5-bits red,
- * 5-bits green, 5-bits blue) with no alpha. This image has
- * a DirectColorModel
.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
- * {@link java.awt.AlphaComposite} documentation.
+ public static final int TYPE_4BYTE_ABGR = 6;
+
+ /**
+ * Represents an image with 8-bit RGBA color components with the colors Blue,
+ * Green, and Red stored in 3 bytes and 1 byte of alpha. The image has a
+ * ComponentColorModel
with alpha. The color data in this image is
+ * considered to be premultiplied with alpha. The byte data is interleaved in a
+ * single byte array in the order A, B, G, R from lower to higher byte addresses
+ * within each pixel.
*/
- public static final int TYPE_USHORT_555_RGB = 9;
-
- /**
- * Represents a unsigned byte grayscale image, non-indexed. This
- * image has a ComponentColorModel
with a CS_GRAY
- * {@link ColorSpace}.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
+ public static final int TYPE_4BYTE_ABGR_PRE = 7;
+
+ /**
+ * Represents an image with 5-6-5 RGB color components (5-bits red, 6-bits
+ * green, 5-bits blue) with no alpha. This image has a
+ * DirectColorModel
. When data with non-opaque alpha is stored in
+ * an image of this type, the color data must be adjusted to a non-premultiplied
+ * form and the alpha discarded, as described in the
* {@link java.awt.AlphaComposite} documentation.
*/
- public static final int TYPE_BYTE_GRAY = 10;
-
- /**
- * Represents an unsigned short grayscale image, non-indexed). This
- * image has a ComponentColorModel
with a CS_GRAY
- * ColorSpace
.
- * When data with non-opaque alpha is stored
- * in an image of this type,
- * the color data must be adjusted to a non-premultiplied form
- * and the alpha discarded,
- * as described in the
+ public static final int TYPE_USHORT_565_RGB = 8;
+
+ /**
+ * Represents an image with 5-5-5 RGB color components (5-bits red, 5-bits
+ * green, 5-bits blue) with no alpha. This image has a
+ * DirectColorModel
. When data with non-opaque alpha is stored in
+ * an image of this type, the color data must be adjusted to a non-premultiplied
+ * form and the alpha discarded, as described in the
* {@link java.awt.AlphaComposite} documentation.
*/
- public static final int TYPE_USHORT_GRAY = 11;
-
- /**
- * Represents an opaque byte-packed 1, 2, or 4 bit image. The
- * image has an {@link IndexColorModel} without alpha. When this
- * type is used as the imageType
argument to the
- * BufferedImage
constructor that takes an
- * imageType
argument but no ColorModel
- * argument, a 1-bit image is created with an
- * IndexColorModel
with two colors in the default
- * sRGB ColorSpace
: {0, 0, 0} and
- * {255, 255, 255}.
+ public static final int TYPE_USHORT_555_RGB = 9;
+
+ /**
+ * Represents a unsigned byte grayscale image, non-indexed. This image has a
+ * ComponentColorModel
with a CS_GRAY {@link ColorSpace}. When data
+ * with non-opaque alpha is stored in an image of this type, the color data must
+ * be adjusted to a non-premultiplied form and the alpha discarded, as described
+ * in the {@link java.awt.AlphaComposite} documentation.
+ */
+ public static final int TYPE_BYTE_GRAY = 10;
+
+ /**
+ * Represents an unsigned short grayscale image, non-indexed). This image has a
+ * ComponentColorModel
with a CS_GRAY ColorSpace
. When
+ * data with non-opaque alpha is stored in an image of this type, the color data
+ * must be adjusted to a non-premultiplied form and the alpha discarded, as
+ * described in the {@link java.awt.AlphaComposite} documentation.
+ */
+ public static final int TYPE_USHORT_GRAY = 11;
+
+ /**
+ * Represents an opaque byte-packed 1, 2, or 4 bit image. The image has an
+ * {@link IndexColorModel} without alpha. When this type is used as the
+ * imageType
argument to the BufferedImage
constructor
+ * that takes an imageType
argument but no ColorModel
+ * argument, a 1-bit image is created with an IndexColorModel
with
+ * two colors in the default sRGB ColorSpace
: {0, 0, 0}
+ * and {255, 255, 255}.
*
- * Images with 2 or 4 bits per pixel may be constructed via
- * the BufferedImage
constructor that takes a
- * ColorModel
argument by supplying a
- * ColorModel
with an appropriate map size.
+ *
+ * Images with 2 or 4 bits per pixel may be constructed via the
+ * BufferedImage
constructor that takes a ColorModel
+ * argument by supplying a ColorModel
with an appropriate map size.
*
- *
Images with 8 bits per pixel should use the image types
- * TYPE_BYTE_INDEXED
or TYPE_BYTE_GRAY
- * depending on their ColorModel
.
-
- *
When color data is stored in an image of this type,
- * the closest color in the colormap is determined
- * by the IndexColorModel
and the resulting index is stored.
- * Approximation and loss of alpha or color components
- * can result, depending on the colors in the
- * IndexColorModel
colormap.
- */
- public static final int TYPE_BYTE_BINARY = 12;
-
- /**
+ *
+ * Images with 8 bits per pixel should use the image types
+ * TYPE_BYTE_INDEXED
or TYPE_BYTE_GRAY
depending on
+ * their ColorModel
.
+ *
+ *
+ * When color data is stored in an image of this type, the closest color in the
+ * colormap is determined by the IndexColorModel
and the resulting
+ * index is stored. Approximation and loss of alpha or color components can
+ * result, depending on the colors in the IndexColorModel
colormap.
+ */
+ public static final int TYPE_BYTE_BINARY = 12;
+
+ /**
* Represents an indexed byte image. When this type is used as the
- * imageType
argument to the BufferedImage
- * constructor that takes an imageType
argument
- * but no ColorModel
argument, an
- * IndexColorModel
is created with
- * a 256-color 6/6/6 color cube palette with the rest of the colors
- * from 216-255 populated by grayscale values in the
- * default sRGB ColorSpace.
+ * imageType
argument to the BufferedImage
constructor
+ * that takes an imageType
argument but no ColorModel
+ * argument, an IndexColorModel
is created with a 256-color 6/6/6
+ * color cube palette with the rest of the colors from 216-255 populated by
+ * grayscale values in the default sRGB ColorSpace.
*
- *
When color data is stored in an image of this type,
- * the closest color in the colormap is determined
- * by the IndexColorModel
and the resulting index is stored.
- * Approximation and loss of alpha or color components
- * can result, depending on the colors in the
- * IndexColorModel
colormap.
- */
- public static final int TYPE_BYTE_INDEXED = 13;
-
- // private static final int DCM_RED_MASK = 0x00ff0000;
- // private static final int DCM_GREEN_MASK = 0x0000ff00;
- // private static final int DCM_BLUE_MASK = 0x000000ff;
- // private static final int DCM_ALPHA_MASK = 0xff000000;
- // private static final int DCM_565_RED_MASK = 0xf800;
- // private static final int DCM_565_GRN_MASK = 0x07E0;
- // private static final int DCM_565_BLU_MASK = 0x001F;
- // private static final int DCM_555_RED_MASK = 0x7C00;
- // private static final int DCM_555_GRN_MASK = 0x03E0;
- // private static final int DCM_555_BLU_MASK = 0x001F;
- // private static final int DCM_BGR_RED_MASK = 0x0000ff;
- // private static final int DCM_BGR_GRN_MASK = 0x00ff00;
- // private static final int DCM_BGR_BLU_MASK = 0xff0000;
-
- /**
- * Constructs a BufferedImage
of one of the predefined image
- * types. The ColorSpace
for the image is the default sRGB space.
- *
- * @param width
- * width of the created image
- * @param height
- * height of the created image
- * @param imageType
- * type of the created image
+ *
+ * When color data is stored in an image of this type, the closest color in the
+ * colormap is determined by the IndexColorModel
and the resulting
+ * index is stored. Approximation and loss of alpha or color components can
+ * result, depending on the colors in the IndexColorModel
colormap.
+ */
+ public static final int TYPE_BYTE_INDEXED = 13;
+
+ private static final int DCM_RED_MASK = 0x00ff0000;
+ private static final int DCM_GREEN_MASK = 0x0000ff00;
+ private static final int DCM_BLUE_MASK = 0x000000ff;
+ private static final int DCM_ALPHA_MASK = 0xff000000;
+ private static final int DCM_565_RED_MASK = 0xf800;
+ private static final int DCM_565_GRN_MASK = 0x07E0;
+ private static final int DCM_565_BLU_MASK = 0x001F;
+ private static final int DCM_555_RED_MASK = 0x7C00;
+ private static final int DCM_555_GRN_MASK = 0x03E0;
+ private static final int DCM_555_BLU_MASK = 0x001F;
+ private static final int DCM_BGR_RED_MASK = 0x0000ff;
+ private static final int DCM_BGR_GRN_MASK = 0x00ff00;
+ private static final int DCM_BGR_BLU_MASK = 0xff0000;
+
+ /**
+ * Constructs a BufferedImage
of one of the predefined image types.
+ * The ColorSpace
for the image is the default sRGB space.
+ *
+ * @param width width of the created image
+ * @param height height of the created image
+ * @param imageType type of the created image
* @see ColorSpace
* @see #TYPE_INT_RGB
* @see #TYPE_INT_ARGB
- * @see #TYPE_INT_ARGB_PRE
+ * @see #TYPE_INT_ARGB_PRE // SwingJS not implemented
* @see #TYPE_INT_BGR
* @see #TYPE_3BYTE_BGR
* @see #TYPE_4BYTE_ABGR
@@ -317,7 +293,7 @@ public BufferedImage(int width, int height, int imageType) {
this.width = width;
this.height = height;
switch (imageType) {
- case TYPE_INT_RGB: {
+ case TYPE_INT_RGB:
colorModel = new DirectColorModel(24, 0x00ff0000, // Red
0x0000ff00, // Green
0x000000ff, // Blue
@@ -326,281 +302,198 @@ public BufferedImage(int width, int height, int imageType) {
raster = colorModel.createCompatibleWritableRaster(width, height);
raster.setImage(this);
秘pix = ((DataBufferInt) raster.getDataBuffer()).data;
- }
break;
-
- case TYPE_INT_ARGB_PRE:
- case TYPE_INT_ARGB: {
+ case TYPE_INT_ARGB:
colorModel = ColorModel.getRGBdefault();
raster = colorModel.createCompatibleWritableRaster(width, height);
raster.setImage(this);
秘pix = ((DataBufferInt) raster.getDataBuffer()).data;
+ break;
+ case TYPE_INT_ARGB_PRE:
+ colorModel = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32, 0x00ff0000, // Red
+ 0x0000ff00, // Green
+ 0x000000ff, // Blue
+ 0xff000000, // Alpha
+ true, // Alpha Premultiplied
+ DataBuffer.TYPE_INT);
+
+ raster = colorModel.createCompatibleWritableRaster(width, height);
+ break;
+ case TYPE_INT_BGR:
+ colorModel = new DirectColorModel(24, 0x000000ff, // Red
+ 0x0000ff00, // Green
+ 0x00ff0000 // Blue
+ );
+ raster = colorModel.createCompatibleWritableRaster(width, height);
+ break;
+ case TYPE_3BYTE_BGR: {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = { 8, 8, 8 };
+ int[] bOffs = { 2, 1, 0 };
+ colorModel = new ComponentColorModel(cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, width * 3, 3, bOffs, null);
+ }
+ break;
+
+ case TYPE_4BYTE_ABGR: {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = { 8, 8, 8, 8 };
+ int[] bOffs = { 3, 2, 1, 0 };
+ colorModel = new ComponentColorModel(cs, nBits, true, false, Transparency.TRANSLUCENT,
+ DataBuffer.TYPE_BYTE);
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, width * 4, 4, bOffs, null);
+ }
+ break;
+
+ case TYPE_4BYTE_ABGR_PRE: {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = { 8, 8, 8, 8 };
+ int[] bOffs = { 3, 2, 1, 0 };
+ colorModel = new ComponentColorModel(cs, nBits, true, true, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, width * 4, 4, bOffs, null);
+ }
+ break;
+
+ case TYPE_BYTE_GRAY: {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+ int[] nBits = { 8 };
+ colorModel = new ComponentColorModel(cs, nBits, false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+ raster = colorModel.createCompatibleWritableRaster(width, height);
+ }
+ break;
+
+ case TYPE_USHORT_GRAY: {
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+ int[] nBits = { 16 };
+ colorModel = new ComponentColorModel(cs, nBits, false, true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
+ raster = colorModel.createCompatibleWritableRaster(width, height);
+ }
+ break;
+
+ case TYPE_BYTE_BINARY: // B&W
+ byte[] arr = { (byte) 0, (byte) 0xff };
+ colorModel = new IndexColorModel(1, 2, arr, arr, arr);
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width, height, 1, 1, null);
+ break;
+ case TYPE_BYTE_INDEXED:
+ // Create a 6x6x6 color cube
+ int[] cmap = new int[256];
+ int i = 0;
+ for (int r = 0; r < 256; r += 51) {
+ for (int g = 0; g < 256; g += 51) {
+ for (int b = 0; b < 256; b += 51) {
+ cmap[i++] = (r << 16) | (g << 8) | b;
+ }
+ }
+ }
+ // And populate the rest of the cmap with gray values
+ int grayIncr = 256 / (256 - i);
+
+ // The gray ramp will be between 18 and 252
+ int gray = grayIncr * 3;
+ for (; i < 256; i++) {
+ cmap[i] = (gray << 16) | (gray << 8) | gray;
+ gray += grayIncr;
+ }
+ colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 1, null);
+ break;
+ case TYPE_USHORT_565_RGB: {
+ colorModel = new DirectColorModel(16, DCM_565_RED_MASK, DCM_565_GRN_MASK, DCM_565_BLU_MASK);
+ raster = colorModel.createCompatibleWritableRaster(width, height);
+ }
+ break;
+ case TYPE_USHORT_555_RGB: {
+ colorModel = new DirectColorModel(15, DCM_555_RED_MASK, DCM_555_GRN_MASK, DCM_555_BLU_MASK);
+ raster = colorModel.createCompatibleWritableRaster(width, height);
}
break;
- // case TYPE_INT_ARGB_PRE:
- // {
- // colorModel = new
- // DirectColorModel(
- // ColorSpace.getInstance(ColorSpace.CS_sRGB),
- // 32,
- // 0x00ff0000,// Red
- // 0x0000ff00,// Green
- // 0x000000ff,// Blue
- // 0xff000000,// Alpha
- // true, // Alpha Premultiplied
- // DataBuffer.TYPE_INT
- // );
- //
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
- // case TYPE_INT_BGR:
- // {
- // colorModel = new DirectColorModel(24,
- // 0x000000ff, // Red
- // 0x0000ff00, // Green
- // 0x00ff0000 // Blue
- // );
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
- // case TYPE_3BYTE_BGR:
- // {
- // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- // int[] nBits = {8, 8, 8};
- // int[] bOffs = {2, 1, 0};
- // colorModel = new ComponentColorModel(cs, nBits, false, false,
- // Transparency.OPAQUE,
- // DataBuffer.TYPE_BYTE);
- // raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
- // width, height,
- // width*3, 3,
- // bOffs, null);
- // }
- // break;
- //
- // case TYPE_4BYTE_ABGR:
- // {
- // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- // int[] nBits = {8, 8, 8, 8};
- // int[] bOffs = {3, 2, 1, 0};
- // colorModel = new ComponentColorModel(cs, nBits, true, false,
- // Transparency.TRANSLUCENT,
- // DataBuffer.TYPE_BYTE);
- // raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
- // width, height,
- // width*4, 4,
- // bOffs, null);
- // }
- // break;
- //
- // case TYPE_4BYTE_ABGR_PRE:
- // {
- // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
- // int[] nBits = {8, 8, 8, 8};
- // int[] bOffs = {3, 2, 1, 0};
- // colorModel = new ComponentColorModel(cs, nBits, true, true,
- // Transparency.TRANSLUCENT,
- // DataBuffer.TYPE_BYTE);
- // raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
- // width, height,
- // width*4, 4,
- // bOffs, null);
- // }
- // break;
- //
- // case TYPE_BYTE_GRAY:
- // {
- // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- // int[] nBits = {8};
- // colorModel = new ComponentColorModel(cs, nBits, false, true,
- // Transparency.OPAQUE,
- // DataBuffer.TYPE_BYTE);
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
- // case TYPE_USHORT_GRAY:
- // {
- // ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- // int[] nBits = {16};
- // colorModel = new ComponentColorModel(cs, nBits, false, true,
- // Transparency.OPAQUE,
- // DataBuffer.TYPE_USHORT);
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
- // case TYPE_BYTE_BINARY:
- // {
- // byte[] arr = {(byte)0, (byte)0xff};
- //
- // colorModel = new IndexColorModel(1, 2, arr, arr, arr);
- // raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
- // width, height, 1, 1, null);
- // }
- // break;
- //
- // case TYPE_BYTE_INDEXED:
- // {
- // // Create a 6x6x6 color cube
- // int[] cmap = new int[256];
- // int i=0;
- // for (int r=0; r < 256; r += 51) {
- // for (int g=0; g < 256; g += 51) {
- // for (int b=0; b < 256; b += 51) {
- // cmap[i++] = (r<<16)|(g<<8)|b;
- // }
- // }
- // }
- // // And populate the rest of the cmap with gray values
- // int grayIncr = 256/(256-i);
- //
- // // The gray ramp will be between 18 and 252
- // int gray = grayIncr*3;
- // for (; i < 256; i++) {
- // cmap[i] = (gray<<16)|(gray<<8)|gray;
- // gray += grayIncr;
- // }
- //
- // colorModel = new IndexColorModel(8, 256, cmap, 0, false, -1,
- // DataBuffer.TYPE_BYTE);
- // raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
- // width, height, 1, null);
- // }
- // break;
- //
- // case TYPE_USHORT_565_RGB:
- // {
- // colorModel = new DirectColorModel(16,
- // DCM_565_RED_MASK,
- // DCM_565_GRN_MASK,
- // DCM_565_BLU_MASK
- // );
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
- // case TYPE_USHORT_555_RGB:
- // {
- // colorModel = new DirectColorModel(15,
- // DCM_555_RED_MASK,
- // DCM_555_GRN_MASK,
- // DCM_555_BLU_MASK
- // );
- // raster = colorModel.createCompatibleWritableRaster(width,
- // height);
- // }
- // break;
- //
default:
throw new IllegalArgumentException("Unknown image type " + imageType);
}
this.imageType = imageType;
}
- /**
- * Constructs a BufferedImage
of one of the predefined
- * image types:
+ /**
+ * Constructs a BufferedImage
of one of the predefined image types:
* TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
*
- *
If the image type is TYPE_BYTE_BINARY, the number of - * entries in the color model is used to determine whether the - * image should have 1, 2, or 4 bits per pixel. If the color model - * has 1 or 2 entries, the image will have 1 bit per pixel. If it - * has 3 or 4 entries, the image with have 2 bits per pixel. If - * it has between 5 and 16 entries, the image will have 4 bits per - * pixel. Otherwise, an IllegalArgumentException will be thrown. + *
+ * If the image type is TYPE_BYTE_BINARY, the number of entries in the color
+ * model is used to determine whether the image should have 1, 2, or 4 bits per
+ * pixel. If the color model has 1 or 2 entries, the image will have 1 bit per
+ * pixel. If it has 3 or 4 entries, the image with have 2 bits per pixel. If it
+ * has between 5 and 16 entries, the image will have 4 bits per pixel.
+ * Otherwise, an IllegalArgumentException will be thrown.
*
- * @param width width of the created image
- * @param height height of the created image
+ * @param width width of the created image
+ * @param height height of the created image
* @param imageType type of the created image
- * @param cm IndexColorModel
of the created image
- * @throws IllegalArgumentException if the imageType is not
- * TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED or if the imageType is
- * TYPE_BYTE_BINARY and the color map has more than 16 entries.
+ * @param cm IndexColorModel
of the created image
+ * @throws IllegalArgumentException if the imageType is not TYPE_BYTE_BINARY or
+ * TYPE_BYTE_INDEXED or if the imageType is
+ * TYPE_BYTE_BINARY and the color map has more
+ * than 16 entries.
* @see #TYPE_BYTE_BINARY
* @see #TYPE_BYTE_INDEXED
*/
- public BufferedImage (int width,
- int height,
- int imageType,
- IndexColorModel cm) {
- if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
- throw new IllegalArgumentException("This image types do not have "+
- "premultiplied alpha.");
- }
- this.width = width;
- this.height = height;
- switch(imageType) {
- case TYPE_BYTE_BINARY:
- int bits; // Will be set below
- int mapSize = cm.getMapSize();
- if (mapSize <= 2) {
- bits = 1;
- } else if (mapSize <= 4) {
- bits = 2;
- } else if (mapSize <= 16) {
- bits = 4;
- } else {
- throw new IllegalArgumentException
- ("Color map for TYPE_BYTE_BINARY " +
- "must have no more than 16 entries");
- }
- raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE,
- width, height, 1, bits, null);
- break;
-
- case TYPE_BYTE_INDEXED:
- raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
- width, height, 1, null);
- break;
- default:
- throw new IllegalArgumentException("Invalid image type (" +
- imageType+"). Image type must"+
- " be either TYPE_BYTE_BINARY or "+
- " TYPE_BYTE_INDEXED");
- }
-
- if (!cm.isCompatibleRaster(raster)) {
- throw new
- IllegalArgumentException("Incompatible image type and IndexColorModel");
- }
-
- colorModel = cm;
- this.imageType = imageType;
- }
+ public BufferedImage(int width, int height, int imageType, IndexColorModel cm) {
+ if (cm.hasAlpha() && cm.isAlphaPremultiplied()) {
+ throw new IllegalArgumentException("This image types do not have " + "premultiplied alpha.");
+ }
+ this.width = width;
+ this.height = height;
+ switch (imageType) {
+ case TYPE_BYTE_BINARY:
+ int bits; // Will be set below
+ int mapSize = cm.getMapSize();
+ if (mapSize <= 2) {
+ bits = 1;
+ } else if (mapSize <= 4) {
+ bits = 2;
+ } else if (mapSize <= 16) {
+ bits = 4;
+ } else {
+ throw new IllegalArgumentException(
+ "Color map for TYPE_BYTE_BINARY " + "must have no more than 16 entries");
+ }
+ raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, width, height, 1, bits, null);
+ break;
+ case TYPE_BYTE_INDEXED:
+ raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 1, null);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid image type (" + imageType + "). Image type must"
+ + " be either TYPE_BYTE_BINARY or " + " TYPE_BYTE_INDEXED");
+ }
+
+ if (!cm.isCompatibleRaster(raster)) {
+ throw new IllegalArgumentException("Incompatible image type and IndexColorModel");
+ }
+
+ colorModel = cm;
+ this.imageType = imageType;
+ }
/**
* Constructs a new BufferedImage
with a specified
* ColorModel
and Raster
. If the number and types of
- * bands in the SampleModel
of the Raster
do not
- * match the number and types required by the ColorModel
to
- * represent its color and alpha components, a {@link RasterFormatException}
- * is thrown. This method can multiply or divide the color Raster
- * data by alpha to match the alphaPremultiplied
state in the
+ * bands in the SampleModel
of the Raster
do not match
+ * the number and types required by the ColorModel
to represent its
+ * color and alpha components, a {@link RasterFormatException} is thrown. This
+ * method can multiply or divide the color Raster
data by alpha to
+ * match the alphaPremultiplied
state in the
* ColorModel
. Properties for this BufferedImage
can
* be established by passing in a {@link Hashtable} of String
/
* Object
pairs.
*
- * @param cm
- * ColorModel
for the new image
- * @param raster
- * Raster
for the image data
- * @param isRasterPremultiplied
- * if true
, the data in the raster has been
- * premultiplied with alpha.
- * @param properties
- * Hashtable
of String
/Object
- * pairs.
+ * @param cm ColorModel
for the new image
+ * @param raster Raster
for the image data
+ * @param isRasterPremultiplied if true
, the data in the raster has
+ * been premultiplied with alpha.
+ * @param properties Hashtable
of
+ * String
/Object
pairs.
* @exception RasterFormatException
if the number and types of
* bands in the SampleModel
of the Raster
* do not match the number and types required by the
@@ -618,190 +511,145 @@ public BufferedImage (int width,
* FOR NOW THE CODE WHICH DEFINES THE RASTER TYPE IS DUPLICATED BY DVF SEE THE
* METHOD DEFINERASTERTYPE @ RASTEROUTPUTMANAGER
*/
- public BufferedImage(ColorModel cm, WritableRaster raster,
- boolean isRasterPremultiplied, Hashtable, ?> properties) {
- //
- // if (!cm.isCompatibleRaster(raster)) {
- // throw new
- // IllegalArgumentException("Raster "+raster+
- // " is incompatible with ColorModel "+
- // cm);
- // }
- //
+ public BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied,
+ Hashtable, ?> properties) {
+
+ if (!cm.isCompatibleRaster(raster)) {
+ throw new IllegalArgumentException("Raster " + raster + " is incompatible with ColorModel " + cm);
+ }
+
if ((raster.minX != 0) || (raster.minY != 0)) {
- throw new IllegalArgumentException("Raster " + raster
- + " has minX or minY not equal to zero: " + raster.minX + " "
- + raster.minY);
+ throw new IllegalArgumentException(
+ "Raster " + raster + " has minX or minY not equal to zero: " + raster.minX + " " + raster.minY);
}
colorModel = cm;
+
this.raster = raster;
this.width = raster.getWidth();
this.height = raster.getHeight();
raster.setImage(this);
- 秘pix = ((DataBufferInt) raster.getDataBuffer()).data;
+ if (getColorModel() == ColorModel.秘RGBdefault)
+ 秘pix = ((DataBufferInt) raster.getDataBuffer()).data;
+ else
+ 秘userRaster = true;
this.properties = properties;
- // int numBands = raster.getNumBands();
- // boolean isAlphaPre = cm.isAlphaPremultiplied();
- //ColorSpace cs;
+ int numBands = raster.getNumBands();
+ boolean isAlphaPre = cm.isAlphaPremultiplied();
+ ColorSpace cs;
// Force the raster data alpha state to match the premultiplied
// state in the color model
// coerceData(isRasterPremultiplied);
- // SampleModel sm = raster.getSampleModel();
- // cs = cm.getColorSpace();
- // int csType = cs.getType();
- // if (csType != ColorSpace.TYPE_RGB) {
- // if (csType == ColorSpace.TYPE_GRAY
- // && ComponentColorModel.class.equals(cm.getClass())) {
- // // Check if this might be a child raster (fix for bug 4240596)
- // if (sm instanceof ComponentSampleModel &&
- // ((ComponentSampleModel)sm).getPixelStride() != numBands) {
- // imageType = TYPE_CUSTOM;
- // } else if (raster instanceof ByteComponentRaster &&
- // PixelInterleavedSampleModel.class.equals(sm.getClass()) &&
- // raster.getNumBands() == 1 &&
- // cm.getComponentSize(0) == 8 &&
- // ((ByteComponentRaster)raster).getPixelStride() == 1) {
- // imageType = TYPE_BYTE_GRAY;
- // } else if (raster instanceof ShortComponentRaster &&
- // PixelInterleavedSampleModel.class.equals(sm.getClass()) &&
- // raster.getNumBands() == 1 &&
- // cm.getComponentSize(0) == 16 &&
- // ((ShortComponentRaster)raster).getPixelStride() == 1) {
- // imageType = TYPE_USHORT_GRAY;
- // }
- // } else {
- // imageType = TYPE_CUSTOM;
- // }
- // return;
- // }
+ SampleModel sm = raster.getSampleModel();
+ cs = cm.getColorSpace();
+ int csType = cs.getType();
+ if (csType != ColorSpace.TYPE_RGB) {
+ if (csType == ColorSpace.TYPE_GRAY && ComponentColorModel.class.equals(cm.getClass())) {
+ // Check if this might be a child raster (fix for bug 4240596)
+ if (sm instanceof ComponentSampleModel && ((ComponentSampleModel) sm).getPixelStride() != numBands) {
+ imageType = TYPE_CUSTOM;
+ } else if (raster instanceof ByteComponentRaster
+ && PixelInterleavedSampleModel.class.equals(sm.getClass()) && raster.getNumBands() == 1
+ && cm.getComponentSize(0) == 8 && ((ByteComponentRaster) raster).getPixelStride() == 1) {
+ imageType = TYPE_BYTE_GRAY;
+ } else if (raster instanceof ShortComponentRaster
+ && PixelInterleavedSampleModel.class.equals(sm.getClass()) && raster.getNumBands() == 1
+ && cm.getComponentSize(0) == 16 && ((ShortComponentRaster) raster).getPixelStride() == 1) {
+ imageType = TYPE_USHORT_GRAY;
+ }
+ } else {
+ imageType = TYPE_CUSTOM;
+ }
+ return;
+ }
- // if ((raster instanceof IntegerComponentRaster) &&
- // (numBands == 3 || numBands == 4)) {
- // IntegerComponentRaster iraster =
- // (IntegerComponentRaster) raster;
- // // Check if the raster params and the color model
- // // are correct
- // int pixSize = cm.getPixelSize();
- // if (iraster.getPixelStride() == 1 &&
- // DirectColorModel.class.equals(cm.getClass()) &&
- // SinglePixelPackedSampleModel.class.equals(sm.getClass()) &&
- // (pixSize == 32 || pixSize == 24))
- // {
- // // Now check on the DirectColorModel params
- // DirectColorModel dcm = (DirectColorModel) cm;
- // int rmask = dcm.getRedMask();
- // int gmask = dcm.getGreenMask();
- // int bmask = dcm.getBlueMask();
- // if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK &&
- // bmask == DCM_BLUE_MASK)
- // {
- // if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
- // imageType = (isAlphaPre
- // ? TYPE_INT_ARGB_PRE
- // : TYPE_INT_ARGB);
- // }
- // else {
- // // No Alpha
- // if (!dcm.hasAlpha()) {
- // imageType = TYPE_INT_RGB;
- // }
- // }
- // } // if (dcm.getRedMask() == DCM_RED_MASK &&
- // else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK
- // && bmask == DCM_BGR_BLU_MASK) {
- // if (!dcm.hasAlpha()) {
- // imageType = TYPE_INT_BGR;
- // }
- // } // if (rmask == DCM_BGR_RED_MASK &&
- // } // if (iraster.getPixelStride() == 1
- // } // ((raster instanceof IntegerComponentRaster) &&
- // else if ((IndexColorModel.class.equals(cm.getClass())) &&
- // (numBands == 1) &&
- // (!cm.hasAlpha() || !isAlphaPre))
- // {
- // IndexColorModel icm = (IndexColorModel) cm;
- // int pixSize = icm.getPixelSize();
- //
- // if (raster instanceof BytePackedRaster &&
- // MultiPixelPackedSampleModel.class.equals(sm.getClass()))
- // {
- // imageType = TYPE_BYTE_BINARY;
- // } // if (raster instanceof BytePackedRaster)
- // else if (raster instanceof ByteComponentRaster &&
- // PixelInterleavedSampleModel.class.equals(sm.getClass()))
- // {
- // ByteComponentRaster braster = (ByteComponentRaster) raster;
- // if (braster.getPixelStride() == 1 && pixSize <= 8) {
- // imageType = TYPE_BYTE_INDEXED;
- // }
- // }
- // } // else if (cm instanceof IndexColorModel) && (numBands == 1))
- // else if ((raster instanceof ShortComponentRaster)
- // && (DirectColorModel.class.equals(cm.getClass()))
- // && (SinglePixelPackedSampleModel.class.equals(sm.getClass()))
- // && (numBands == 3)
- // && !cm.hasAlpha())
- // {
- // DirectColorModel dcm = (DirectColorModel) cm;
- // if (dcm.getRedMask() == DCM_565_RED_MASK) {
- // if (dcm.getGreenMask() == DCM_565_GRN_MASK &&
- // dcm.getBlueMask() == DCM_565_BLU_MASK) {
- // imageType = TYPE_USHORT_565_RGB;
- // }
- // }
- // else if (dcm.getRedMask() == DCM_555_RED_MASK) {
- // if (dcm.getGreenMask() == DCM_555_GRN_MASK &&
- // dcm.getBlueMask() == DCM_555_BLU_MASK) {
- // imageType = TYPE_USHORT_555_RGB;
- // }
- // }
- // } // else if ((cm instanceof IndexColorModel) && (numBands == 1))
- // else if ((raster instanceof ByteComponentRaster)
- // && (cm instanceof ComponentColorModel)
- // && (raster.getSampleModel() instanceof PixelInterleavedSampleModel)
- // && (numBands == 3 || numBands == 4))
- // {
- // ComponentColorModel ccm = (ComponentColorModel) cm;
- // PixelInterleavedSampleModel csm =
- // (PixelInterleavedSampleModel)raster.getSampleModel();
- // ByteComponentRaster braster = (ByteComponentRaster) raster;
- // int[] offs = csm.getBandOffsets();
- // if (ccm.getNumComponents() != numBands) {
- // throw new RasterFormatException("Number of components in "+
- // "ColorModel ("+
- // ccm.getNumComponents()+
- // ") does not match # in "+
- // " Raster ("+numBands+")");
- // }
- // int[] nBits = ccm.getComponentSize();
- // boolean is8bit = true;
- // for (int i=0; i < numBands; i++) {
- // if (nBits[i] != 8) {
- // is8bit = false;
- // break;
- // }
- // }
- // if (is8bit &&
- // braster.getPixelStride() == numBands &&
- // offs[0] == numBands-1 &&
- // offs[1] == numBands-2 &&
- // offs[2] == numBands-3 &&
- // ComponentColorModel.class.equals(ccm.getClass()) &&
- // PixelInterleavedSampleModel.class.equals(csm.getClass()))
- // {
- // if (numBands == 3 && !ccm.hasAlpha()) {
- // imageType = TYPE_3BYTE_BGR;
- // }
- // else if (offs[3] == 0 && ccm.hasAlpha()) {
- // imageType = (isAlphaPre
- // ? TYPE_4BYTE_ABGR_PRE
- // : TYPE_4BYTE_ABGR);
- // }
- // }
- // } // else if ((raster instanceof ByteComponentRaster) &&
+ if ((raster instanceof IntegerComponentRaster) && (numBands == 3 || numBands == 4)) {
+ IntegerComponentRaster iraster = (IntegerComponentRaster) raster;
+ // Check if the raster params and the color model
+ // are correct
+ int pixSize = cm.getPixelSize();
+ if (iraster.getPixelStride() == 1 && DirectColorModel.class.equals(cm.getClass())
+ && SinglePixelPackedSampleModel.class.equals(sm.getClass()) && (pixSize == 32 || pixSize == 24)) {
+ // Now check on the DirectColorModel params
+ DirectColorModel dcm = (DirectColorModel) cm;
+ int rmask = dcm.getRedMask();
+ int gmask = dcm.getGreenMask();
+ int bmask = dcm.getBlueMask();
+ if (rmask == DCM_RED_MASK && gmask == DCM_GREEN_MASK && bmask == DCM_BLUE_MASK) {
+ if (dcm.getAlphaMask() == DCM_ALPHA_MASK) {
+ imageType = (isAlphaPre ? TYPE_INT_ARGB_PRE : TYPE_INT_ARGB);
+ } else {
+ // No Alpha
+ if (!dcm.hasAlpha()) {
+ imageType = TYPE_INT_RGB;
+ }
+ }
+ } // if (dcm.getRedMask() == DCM_RED_MASK &&
+ else if (rmask == DCM_BGR_RED_MASK && gmask == DCM_BGR_GRN_MASK && bmask == DCM_BGR_BLU_MASK) {
+ if (!dcm.hasAlpha()) {
+ imageType = TYPE_INT_BGR;
+ }
+ } // if (rmask == DCM_BGR_RED_MASK &&
+ } // if (iraster.getPixelStride() == 1
+ } // ((raster instanceof IntegerComponentRaster) &&
+ else if ((IndexColorModel.class.equals(cm.getClass())) && (numBands == 1) && (!cm.hasAlpha() || !isAlphaPre)) {
+ IndexColorModel icm = (IndexColorModel) cm;
+ int pixSize = icm.getPixelSize();
+
+ if (raster instanceof BytePackedRaster && MultiPixelPackedSampleModel.class.equals(sm.getClass())) {
+ imageType = TYPE_BYTE_BINARY;
+ } // if (raster instanceof BytePackedRaster)
+ else if (raster instanceof ByteComponentRaster && PixelInterleavedSampleModel.class.equals(sm.getClass())) {
+ ByteComponentRaster braster = (ByteComponentRaster) raster;
+ if (braster.getPixelStride() == 1 && pixSize <= 8) {
+ imageType = TYPE_BYTE_INDEXED;
+ }
+ }
+ } // else if (cm instanceof IndexColorModel) && (numBands == 1))
+ else if ((raster instanceof ShortComponentRaster) && (DirectColorModel.class.equals(cm.getClass()))
+ && (SinglePixelPackedSampleModel.class.equals(sm.getClass())) && (numBands == 3) && !cm.hasAlpha()) {
+ DirectColorModel dcm = (DirectColorModel) cm;
+ if (dcm.getRedMask() == DCM_565_RED_MASK) {
+ if (dcm.getGreenMask() == DCM_565_GRN_MASK && dcm.getBlueMask() == DCM_565_BLU_MASK) {
+ imageType = TYPE_USHORT_565_RGB;
+ }
+ } else if (dcm.getRedMask() == DCM_555_RED_MASK) {
+ if (dcm.getGreenMask() == DCM_555_GRN_MASK && dcm.getBlueMask() == DCM_555_BLU_MASK) {
+ imageType = TYPE_USHORT_555_RGB;
+ }
+ }
+ } // else if ((cm instanceof IndexColorModel) && (numBands == 1))
+ else if ((raster instanceof ByteComponentRaster) && (cm instanceof ComponentColorModel)
+ && (raster.getSampleModel() instanceof PixelInterleavedSampleModel)
+ && (numBands == 3 || numBands == 4)) {
+ ComponentColorModel ccm = (ComponentColorModel) cm;
+ PixelInterleavedSampleModel csm = (PixelInterleavedSampleModel) raster.getSampleModel();
+ ByteComponentRaster braster = (ByteComponentRaster) raster;
+ int[] offs = csm.getBandOffsets();
+ if (ccm.getNumComponents() != numBands) {
+ throw new RasterFormatException("Number of components in " + "ColorModel (" + ccm.getNumComponents()
+ + ") does not match # in " + " Raster (" + numBands + ")");
+ }
+ int[] nBits = ccm.getComponentSize();
+ boolean is8bit = true;
+ for (int i = 0; i < numBands; i++) {
+ if (nBits[i] != 8) {
+ is8bit = false;
+ break;
+ }
+ }
+ if (is8bit && braster.getPixelStride() == numBands && offs[0] == numBands - 1 && offs[1] == numBands - 2
+ && offs[2] == numBands - 3 && ComponentColorModel.class.equals(ccm.getClass())
+ && PixelInterleavedSampleModel.class.equals(csm.getClass())) {
+ if (numBands == 3 && !ccm.hasAlpha()) {
+ imageType = TYPE_3BYTE_BGR;
+ } else if (offs[3] == 0 && ccm.hasAlpha()) {
+ imageType = (isAlphaPre ? TYPE_4BYTE_ABGR_PRE : TYPE_4BYTE_ABGR);
+ }
+ }
+ } // else if ((raster instanceof ByteComponentRaster) &&
}
/**
@@ -835,46 +683,42 @@ public int getType() {
*/
@Override
public ColorModel getColorModel() {
+ // one of Component, Index, or Packed(Direct)
return colorModel;
}
/**
* Returns the {@link WritableRaster}.
*
- * @return the WriteableRaster
of this BufferedImage
- * .
+ * @return the WriteableRaster
of this BufferedImage
.
*/
public WritableRaster getRaster() {
return raster;
}
- /**
- * Returns a WritableRaster
representing the alpha
- * channel for BufferedImage
objects
- * with ColorModel
objects that support a separate
- * spatial alpha channel, such as ComponentColorModel
and
- * DirectColorModel
. Returns null
if there
- * is no alpha channel associated with the ColorModel
in
- * this image. This method assumes that for all
- * ColorModel
objects other than
- * IndexColorModel
, if the ColorModel
- * supports alpha, there is a separate alpha channel
- * which is stored as the last band of image data.
- * If the image uses an IndexColorModel
that
- * has alpha in the lookup table, this method returns
- * null
since there is no spatially discrete alpha
- * channel. This method creates a new
- * WritableRaster
, but shares the data array.
+ /**
+ * Returns a WritableRaster
representing the alpha channel for
+ * BufferedImage
objects with ColorModel
objects that
+ * support a separate spatial alpha channel, such as
+ * ComponentColorModel
and DirectColorModel
. Returns
+ * null
if there is no alpha channel associated with the
+ * ColorModel
in this image. This method assumes that for all
+ * ColorModel
objects other than IndexColorModel
, if
+ * the ColorModel
supports alpha, there is a separate alpha channel
+ * which is stored as the last band of image data. If the image uses an
+ * IndexColorModel
that has alpha in the lookup table, this method
+ * returns null
since there is no spatially discrete alpha channel.
+ * This method creates a new WritableRaster
, but shares the data
+ * array.
+ *
* @return a WritableRaster
or null
if this
- * BufferedImage
has no alpha channel associated
- * with its ColorModel
.
+ * BufferedImage
has no alpha channel associated with its
+ * ColorModel
.
*/
- public WritableRaster getAlphaRaster() {
- return colorModel.getAlphaRaster(raster);
- }
-
+ public WritableRaster getAlphaRaster() {
+ return colorModel.getAlphaRaster(raster);
+ }
-
/**
* Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and
* default sRGB colorspace. Color conversion takes place if this default model
@@ -887,11 +731,9 @@ public WritableRaster getAlphaRaster() {
* An ArrayOutOfBoundsException
may be thrown if the coordinates
* are not in bounds. However, explicit bounds checking is not guaranteed.
*
- * @param x
- * the X coordinate of the pixel from which to get the pixel in the
+ * @param x the X coordinate of the pixel from which to get the pixel in the
* default RGB color model and sRGB color space
- * @param y
- * the Y coordinate of the pixel from which to get the pixel in the
+ * @param y the Y coordinate of the pixel from which to get the pixel in the
* default RGB color model and sRGB color space
* @return an integer pixel in the default RGB color model and default sRGB
* colorspace.
@@ -908,11 +750,11 @@ public int getRGB(int x, int y) {
/**
* Returns an array of integer pixels in the default RGB color model
* (TYPE_INT_ARGB) and default sRGB color space, from a portion of the image
- * data. Color conversion takes place if the default model does not match
- * the image ColorModel
. There are only 8-bits of precision for
- * each color component in the returned data when using this method. With a
- * specified coordinate (x, y) in the image, the ARGB pixel can be
- * accessed in this way:
+ * data. Color conversion takes place if the default model does not match the
+ * image ColorModel
. There are only 8-bits of precision for each
+ * color component in the returned data when using this method. With a specified
+ * coordinate (x, y) in the image, the ARGB pixel can be accessed in this
+ * way:
*
@@ -921,23 +763,16 @@ public int getRGB(int x, int y) { * ** - * An
ArrayOutOfBoundsException
may be thrown if the region is - * not in bounds. However, explicit bounds checking is not guaranteed. - * - * @param startX - * the starting X coordinate - * @param startY - * the starting Y coordinate - * @param w - * width of region - * @param h - * height of region - * @param rgbArray - * if notnull
, the rgb pixels are written here - * @param offset - * offset into thergbArray
- * @param scansize - * scanline stride for thergbArray
+ * AnArrayOutOfBoundsException
may be thrown if the region is not + * in bounds. However, explicit bounds checking is not guaranteed. + * + * @param startX the starting X coordinate + * @param startY the starting Y coordinate + * @param w width of region + * @param h height of region + * @param rgbArray if notnull
, the rgb pixels are written here + * @param offset offset into thergbArray
+ * @param scansize scanline stride for thergbArray
* @return array of RGB pixels. * @see #setRGB(int, int, int) * @see #setRGB(int, int, int, int, int[], int, int) @@ -961,40 +796,36 @@ public boolean checkHavePixels() { return false; } - public int[] getRangeRGB(int startX, int startY, int w, int h, - int[] rgbArray, int offset, int scansize) { + public int[] getRangeRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) { if (秘pix == null && 秘pixSaved == null) checkHavePixels(); int[] pixels = (秘pix == null ? 秘pixSaved : 秘pix); - for (int y = startY, yoff=offset; y < startY + h; y++, yoff += scansize) + for (int y = startY, yoff = offset; y < startY + h; y++, yoff += scansize) for (int off = yoff, x = startX; x < startX + w; x++) rgbArray[off++] = pixels[y * this.width + x]; return rgbArray; } - + /** * Sets a pixel in thisBufferedImage
to the specified RGB value. - * The pixel is assumed to be in the default RGB color model, TYPE_INT_ARGB, - * and default sRGB color space. For images with an - *IndexColorModel
, the index with the nearest color is chosen. + * The pixel is assumed to be in the default RGB color model, TYPE_INT_ARGB, and + * default sRGB color space. For images with anIndexColorModel
, + * the index with the nearest color is chosen. * ** * An
ArrayOutOfBoundsException
may be thrown if the coordinates * are not in bounds. However, explicit bounds checking is not guaranteed. * - * @param x - * the X coordinate of the pixel to set - * @param y - * the Y coordinate of the pixel to set - * @param rgb - * the RGB value + * @param x the X coordinate of the pixel to set + * @param y the Y coordinate of the pixel to set + * @param rgb the RGB value * @see #getRGB(int, int) * @see #getRGB(int, int, int, int, int[], int, int) */ public synchronized void setRGB(int x, int y, int rgb) { if (checkHavePixels()) - 秘imgNode = null; + 秘imgNode = null; int[] pixels = (秘pix == null ? 秘pixSaved : 秘pix); pixels[y * this.width + x] = rgb; } @@ -1005,9 +836,9 @@ public synchronized void setRGB(int x, int y, int rgb) { * (TYPE_INT_ARGB) and default sRGB color space, into a portion of the image * data. Color conversion takes place if the default model does not match the * imageColorModel
. There are only 8-bits of precision for each - * color component in the returned data when using this method. With a - * specified coordinate (x, y) in the this image, the ARGB pixel can be - * accessed in this way: + * color component in the returned data when using this method. With a specified + * coordinate (x, y) in the this image, the ARGB pixel can be accessed in + * this way: * ** pixel = rgbArray[offset + (y - startY) * scansize + (x - startX)]; @@ -1017,41 +848,33 @@ public synchronized void setRGB(int x, int y, int rgb) { * ** - * An
ArrayOutOfBoundsException
may be thrown if the region is - * not in bounds. However, explicit bounds checking is not guaranteed. - * - * @param startX - * the starting X coordinate - * @param startY - * the starting Y coordinate - * @param w - * width of the region - * @param h - * height of the region - * @param rgbArray - * the rgb pixels - * @param offset - * offset into thergbArray
- * @param scansize - * scanline stride for thergbArray
+ * AnArrayOutOfBoundsException
may be thrown if the region is not + * in bounds. However, explicit bounds checking is not guaranteed. + * + * @param startX the starting X coordinate + * @param startY the starting Y coordinate + * @param w width of the region + * @param h height of the region + * @param rgbArray the rgb pixels + * @param offset offset into thergbArray
+ * @param scansize scanline stride for thergbArray
* @see #getRGB(int, int) * @see #getRGB(int, int, int, int, int[], int, int) */ - public void setRGB(int startX, int startY, int w, int h, int[] rgbArray, - int offset, int scansize) { + public void setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int scansize) { if (checkHavePixels()) - 秘imgNode = null; + 秘imgNode = null; int[] pixels = (秘pix == null ? 秘pixSaved : 秘pix); int width = this.width; - for (int y = startY, yoff = offset; y < startY + h; y++, yoff += scansize) - for (int x = startX, off = yoff; x < startX + w; x++) + for (int y = startY, yoff = offset; y < startY + h; y++, yoff += scansize) + for (int x = startX, off = yoff; x < startX + w; x++) pixels[y * width + x] = rgbArray[off++]; 秘pix = 秘pixSaved = pixels; // 秘pix is used by getGraphics() // 秘pixSaved is kept in case we need to do this again 秘g = null; // forces new this.秘canvas to be created in getGraphics() - getImageGraphic(); // sets 秘pix = null and creates 秘canvas - + getImageGraphic(); // sets 秘pix = null and creates 秘canvas + } /** @@ -1078,8 +901,7 @@ public int getHeight() { * * Returns the width of theBufferedImage
. * - * @param observer - * ignored + * @param observer ignored * @return the width of thisBufferedImage
*/ @Override @@ -1090,8 +912,7 @@ public int getWidth(ImageObserver observer) { /** * Returns the height of theBufferedImage
. * - * @param observer - * ignored + * @param observer ignored * @return the height of thisBufferedImage
*/ @Override @@ -1102,8 +923,8 @@ public int getHeight(ImageObserver observer) { /** * Returns the object that produces the pixels for the image. * - * @return the {@link ImageProducer} that is used to produce the pixels for - * this image. + * @return the {@link ImageProducer} that is used to produce the pixels for this + * image. * @see ImageProducer */ @SuppressWarnings("rawtypes") @@ -1128,11 +949,9 @@ public ImageProducer getSource() { * optional comment that can be presented to the user as a description of the * image, its source, or its author. * - * @param name - * the property name - * @param observer - * theImageObserver
that receives notification - * regarding image information + * @param name the property name + * @param observer theImageObserver
that receives notification + * regarding image information * @return an {@link Object} that is the property referred to by the specified *name
ornull
if the properties of this * image are not yet known. @@ -1148,8 +967,7 @@ public Object getProperty(String name, ImageObserver observer) { /** * Returns a property of the image by name. * - * @param name - * the property name + * @param name the property name * @return anObject
that is the property referred to by the * specifiedname
. * @throwsNullPointerException
if the property name is null. @@ -1174,8 +992,7 @@ public Object getProperty(String name) { * compatibility. {@link #createGraphics() createGraphics} is more convenient, * since it is declared to return aGraphics2D
. * - * @return aGraphics2D
, which can be used to draw into this - * image. + * @return aGraphics2D
, which can be used to draw into this image. */ @Override public Graphics getGraphics() { @@ -1195,27 +1012,22 @@ public Graphics2D createGraphics() { /** * Returns a subimage defined by a specified rectangular region. The returned - *BufferedImage
shares the same data array as the original - * image. + *BufferedImage
shares the same data array as the original image. * - * @param x - * the X coordinate of the upper-left corner of the specified + * @param x the X coordinate of the upper-left corner of the specified * rectangular region - * @param y - * the Y coordinate of the upper-left corner of the specified + * @param y the Y coordinate of the upper-left corner of the specified * rectangular region - * @param w - * the width of the specified rectangular region - * @param h - * the height of the specified rectangular region + * @param w the width of the specified rectangular region + * @param h the height of the specified rectangular region * @return aBufferedImage
that is the subimage of this *BufferedImage
. * @exceptionRasterFormatException
if the specified area is not * contained within thisBufferedImage
. */ public BufferedImage getSubimage(int x, int y, int w, int h) { - return new BufferedImage(colorModel, raster.createWritableChild(x, y, w, h, - 0, 0, null), colorModel.isAlphaPremultiplied(), properties); + return new BufferedImage(colorModel, raster.createWritableChild(x, y, w, h, 0, 0, null), + colorModel.isAlphaPremultiplied(), properties); } /** @@ -1255,24 +1067,23 @@ public boolean isAlphaPremultiplied() { */ @Override public String toString() { - return new String("BufferedImage@" + Integer.toHexString(hashCode()) - + ": type = " + imageType + " " + colorModel.toString() + " " + raster.toString()); + return new String("BufferedImage@" + Integer.toHexString(hashCode()) + ": type = " + imageType + " " + + colorModel.toString() + " " + raster.toString()); } /** * Returns a {@link Vector} of {@link RenderedImage} objects that are the - * immediate sources, not the sources of these immediate sources, of image - * data for thisBufferedImage
. This method returns - *null
if theBufferedImage
has no information - * about its immediate sources. It returns an emptyVector
if the + * immediate sources, not the sources of these immediate sources, of image data + * for thisBufferedImage
. This method returnsnull
if + * theBufferedImage
has no information about its immediate + * sources. It returns an emptyVector
if the *BufferedImage
has no immediate sources. * * @return aVector
containing immediate sources of this - *BufferedImage
object's image date, or - *null
if thisBufferedImage
has no - * information about its immediate sources, or an empty - *Vector
if thisBufferedImage
has no - * immediate sources. + *BufferedImage
object's image date, ornull
+ * if thisBufferedImage
has no information about its + * immediate sources, or an emptyVector
if this + *BufferedImage
has no immediate sources. */ @Override public VectorgetSources() { @@ -1284,9 +1095,9 @@ public Vector getSources() { * getProperty(String)} or null
, if no property names are * recognized. * - * @return aString
array containing all of the property names - * thatgetProperty(String)
recognizes; or - *null
if no property names are recognized. + * @return aString
array containing all of the property names that + *getProperty(String)
recognizes; ornull
if + * no property names are recognized. */ @Override public String[] getPropertyNames() { @@ -1294,8 +1105,8 @@ public String[] getPropertyNames() { } /** - * Returns the minimum x coordinate of thisBufferedImage
. This - * is always zero. + * Returns the minimum x coordinate of thisBufferedImage
. This is + * always zero. * * @return the minimum x coordinate of thisBufferedImage
. */ @@ -1305,8 +1116,8 @@ public int getMinX() { } /** - * Returns the minimum y coordinate of thisBufferedImage
. This - * is always zero. + * Returns the minimum y coordinate of thisBufferedImage
. This is + * always zero. * * @return the minimum y coordinate of thisBufferedImage
. */ @@ -1411,13 +1222,11 @@ public int getTileGridYOffset() { /** * Returns tile (tileX
,tileY
). Note that *tileX
andtileY
are indices into the tile array, - * not pixel locations. TheRaster
that is returned is live, - * which means that it is updated if the image is changed. + * not pixel locations. TheRaster
that is returned is live, which + * means that it is updated if the image is changed. * - * @param tileX - * the x index of the requested tile in the tile array - * @param tileY - * the y index of the requested tile in the tile array + * @param tileX the x index of the requested tile in the tile array + * @param tileY the y index of the requested tile in the tile array * @return aRaster
that is the tile defined by the arguments *tileX
andtileY
. * @exceptionArrayIndexOutOfBoundsException
if both @@ -1450,10 +1259,8 @@ public Raster getData() { int height = raster.getHeight(); int startX = raster.getMinX(); int startY = raster.getMinY(); - WritableRaster wr = Raster.createWritableRaster( - raster.getSampleModel(), - new Point(raster.getSampleModelTranslateX(), raster - .getSampleModelTranslateY())); + WritableRaster wr = Raster.createWritableRaster(raster.getSampleModel(), + new Point(raster.getSampleModelTranslateX(), raster.getSampleModelTranslateY())); Object tdata = null; checkHavePixels(); @@ -1469,8 +1276,7 @@ public Raster getData() { * TheRaster
returned is a copy of the image data and is not * updated if the image is changed. * - * @param rect - * the region of theBufferedImage
to be returned. + * @param rect the region of theBufferedImage
to be returned. * @return aRaster
that is a copy of the image data of the * specified region of theBufferedImage
* @see #setData(Raster) @@ -1496,16 +1302,15 @@ public Raster getData(Rectangle rect) { /** * Computes an arbitrary rectangular region of theBufferedImage
- * and copies it into a specifiedWritableRaster
. The region to - * be computed is determined from the bounds of the specified + * and copies it into a specifiedWritableRaster
. The region to be + * computed is determined from the bounds of the specified *WritableRaster
. The specifiedWritableRaster
must * have aSampleModel
that is compatible with this image. If *outRaster
isnull
, an appropriate *WritableRaster
is created. * - * @param outRaster - * aWritableRaster
to hold the returned part of the - * image, ornull
+ * @param outRaster aWritableRaster
to hold the returned part of + * the image, ornull
* @return a reference to the supplied or createdWritableRaster
. */ @Override @@ -1531,11 +1336,10 @@ public WritableRaster copyData(WritableRaster outRaster) { /** * Sets a rectangular region of the image to the contents of the specified *Raster
r
, which is assumed to be in the same - * coordinate space as theBufferedImage
. The operation is - * clipped to the bounds of theBufferedImage
. + * coordinate space as theBufferedImage
. The operation is clipped + * to the bounds of theBufferedImage
. * - * @param r - * the specifiedRaster
+ * @param r the specifiedRaster
* @see #getData * @see #getData(Rectangle) */ @@ -1604,61 +1408,62 @@ public void setData(Raster r) { // throw new IllegalArgumentException("Only 1 tile in image"); // } // - /** - * Returns an array of {@link Point} objects indicating which tiles - * are checked out for writing. Returnsnull
if none are - * checked out. - * @return aPoint
array that indicates the tiles that - * are checked out for writing, ornull
if no - * tiles are checked out for writing. - */ - public Point[] getWritableTileIndices() { - Point[] p = new Point[1]; - p[0] = new Point(0, 0); - - return p; - } - - /** - * Returns whether or not any tile is checked out for writing. - * Semantically equivalent to + /** + * Returns an array of {@link Point} objects indicating which tiles are checked + * out for writing. Returnsnull
if none are checked out. + * + * @return aPoint
array that indicates the tiles that are checked + * out for writing, ornull
if no tiles are checked out for + * writing. + */ + public Point[] getWritableTileIndices() { + Point[] p = new Point[1]; + p[0] = new Point(0, 0); + + return p; + } + + /** + * Returns whether or not any tile is checked out for writing. Semantically + * equivalent to + * ** (getWritableTileIndices() != null). *+ * * @returntrue
if any tile is checked out for writing; - *false
otherwise. - */ - public boolean hasTileWriters () { - return true; - } - - /** - * Checks out a tile for writing. All registered - *TileObservers
are notified when a tile goes from having - * no writers to having one writer. - * @param tileX the x index of the tile - * @param tileY the y index of the tile - * @return aWritableRaster
that is the tile, indicated by - * the specified indices, to be checked out for writing. - */ - public WritableRaster getWritableTile (int tileX, int tileY) { - return raster; - } - - /** - * Relinquishes permission to write to a tile. If the caller - * continues to write to the tile, the results are undefined. - * Calls to this method should only appear in matching pairs - * with calls to {@link #getWritableTile(int, int) getWritableTile(int, - int)}. Any other leads - * to undefined results. All registeredTileObservers
- * are notified when a tile goes from having one writer to having no - * writers. + *false
otherwise. + */ + public boolean hasTileWriters() { + return true; + } + + /** + * Checks out a tile for writing. All registeredTileObservers
are + * notified when a tile goes from having no writers to having one writer. + * + * @param tileX the x index of the tile + * @param tileY the y index of the tile + * @return aWritableRaster
that is the tile, indicated by the + * specified indices, to be checked out for writing. + */ + public WritableRaster getWritableTile(int tileX, int tileY) { + return raster; + } + + /** + * Relinquishes permission to write to a tile. If the caller continues to write + * to the tile, the results are undefined. Calls to this method should only + * appear in matching pairs with calls to {@link #getWritableTile(int, int) + * getWritableTile(int, int)}. Any other leads to undefined results. All + * registeredTileObservers
are notified when a tile goes from + * having one writer to having no writers. + * * @param tileX the x index of the tile * @param tileY the y index of the tile */ - public void releaseWritableTile (int tileX, int tileY) { - } + public void releaseWritableTile(int tileX, int tileY) { + } /** * Returns the transparency. Returns either OPAQUE, BITMASK, or TRANSLUCENT. @@ -1674,29 +1479,28 @@ public int getTransparency() { return colorModel.getTransparency(); } - /** * Set the underlying graphics object coming from painting this image * * */ - + public void setImageFromHTML5Canvas(JSGraphics2D g) { this.秘g = g; width = raster.width; height = raster.height; setPixels(); } - + /** - * Extract the int[] data from this image by installing it in a canvas. - * Note that if if img.complete == false, then this will result in a - * black rectangle. + * Extract the int[] data from this image by installing it in a canvas. Note + * that if img.complete == false, then this will result in a black rectangle. * */ @SuppressWarnings("unused") - public void setPixels() { - DOMNode canvas = (秘g == null ? null : /** @j2sNative this.秘g.canvas || */null); + private void setPixels() { + DOMNode canvas = (秘g == null ? null : /** @j2sNative this.秘g.canvas || */ + null); if (canvas == null) canvas = DOMNode.createElement("canvas", null); int w = width; @@ -1704,37 +1508,52 @@ public void setPixels() { int[] data = null; /** * note that setting canvas.width clears it + * * @j2sNative * - * if (!this.秘g) { - * canvas.width = w; - * canvas.height = h; - * } - * var ctx = canvas.getContext("2d"); - * if (!this.秘g) - * ctx.drawImage(this.秘imgNode, 0, 0, w, h); - * data = ctx.getImageData(0, 0, w, h).data; + * if (!this.秘g) { canvas.width = w; canvas.height = h; } var ctx = + * canvas.getContext("2d"); if (!this.秘g) + * ctx.drawImage(this.秘imgNode, 0, 0, w, h); data = + * ctx.getImageData(0, 0, w, h).data; * */ - { + DataBuffer buf = raster.getDataBuffer(); + switch (imageType) { + case TYPE_INT_RGB: +// case TYPE_INT_ARGB_PRE: + case TYPE_INT_ARGB: + DataBufferInt buffer = (DataBufferInt) buf; + toIntARGB(data, 秘pix = buffer.data); + break; + case TYPE_INT_ARGB_PRE: + case TYPE_INT_BGR: + case TYPE_3BYTE_BGR: + case TYPE_4BYTE_ABGR: + case TYPE_4BYTE_ABGR_PRE: + case TYPE_BYTE_GRAY: + case TYPE_USHORT_GRAY: + case TYPE_BYTE_BINARY: + case TYPE_USHORT_565_RGB: + case TYPE_USHORT_555_RGB: + JSUtil.notImplemented("BufferedImage type " + imageType); + break; + case TYPE_BYTE_INDEXED: + } - DataBufferInt buffer = (DataBufferInt) raster.getDataBuffer(); - toIntARGB(data, 秘pix = buffer.data); 秘imgNode = canvas; 秘havePix = true; } - @Override public void flush() { // call this method after drawing to ensure that // pixels are recreated from the HTML5 canvas - 秘pix = null; + 秘pix = null; 秘havePix = false; - // was for surfaceManager only super.flush(); } + /** - * convert [r g b a r g b a ...] into [argb argb argb ...] + * convert [r g b a r g b a ...] into [argb argb argb ...] * * currently does not respect transparency * @@ -1742,30 +1561,29 @@ public void flush() { * @return array of ARGB values * */ - void toIntARGB(int[] imgData, int[] iData) { - /* - * red=imgData.data[0]; - * green=imgData.data[1]; - * blue=imgData.data[2]; - * alpha=imgData.data[3]; - */ - int n = imgData.length / 4; - int a; - for (int i = 0, j = 0; i < n;) { - int argb = (imgData[j++] << 16) | (imgData[j++] << 8) | imgData[j++] | 0xFF000000; - iData[i++] = (imgData[j++] == 0 ? 0 : argb); - } - } - - /** - * - * Get a JSGraphics2D for this image, but don't initialize it with a state save - * the way g.create() or image.getGraphics() or image.createGraphics() do. - * So do NOT execute g.dispose() on the returned object. - * - * @author Bob Hanson - * @return a JSGraphics2D object - */ + private static void toIntARGB(int[] imgData, int[] iData) { + // red=imgData.data[0]; + // green=imgData.data[1]; + // blue=imgData.data[2]; + // alpha=imgData.data[3]; + + int n = imgData.length / 4; + int a; + for (int i = 0, j = 0; i < n;) { + int argb = (imgData[j++] << 16) | (imgData[j++] << 8) | imgData[j++] | 0xFF000000; + iData[i++] = (imgData[j++] == 0 ? 0 : argb); + } + } + + /** + * + * Get a JSGraphics2D for this image, but don't initialize it with a state save + * the way g.create() or image.getGraphics() or image.createGraphics() do. So do + * NOT execute g.dispose() on the returned object. + * + * @author Bob Hanson + * @return a JSGraphics2D object + */ @SuppressWarnings("unused") public Graphics2D getImageGraphic() { if (秘g == null) { @@ -1775,31 +1593,26 @@ public Graphics2D getImageGraphic() { /** * @j2sNative * - * canvas.width = w; - * canvas.height = h; - * + * canvas.width = w; canvas.height = h; + * */ - 秘canvas = canvas; - Object pix = 秘pix; + 秘canvas = canvas; + Object pix = 秘pix; 秘g = new JSGraphics2D(canvas); // we need to draw the image now, because it might // have pixels. Note that Java actually does not // allow creating a Graphics from MemoryImageSource - // so pixels would never be there. + // so pixels would never be there. if (pix != null) 秘g.drawImagePriv(this, 0, 0, null); /** - * @j2sNative - * if (pix) - * pix.img = this; + * @j2sNative if (pix) pix.img = this; * */ - - // 秘pix = null; + flush(); // also setting 秘havePix false - } - Graphics2D g2d = (Graphics2D) (Object)秘g; + Graphics2D g2d = (Graphics2D) (Object) 秘g; if (秘component != null) { g2d.setFont(秘component.getFont()); g2d.setBackground(秘component.getBackground()); @@ -1808,5 +1621,58 @@ public Graphics2D getImageGraphic() { return g2d; } + public boolean 秘isOpaque() { + switch (imageType) { + case TYPE_INT_ARGB: + case TYPE_INT_ARGB_PRE: + case TYPE_4BYTE_ABGR: + case TYPE_4BYTE_ABGR_PRE: + return false; + case TYPE_INT_RGB: + case TYPE_INT_BGR: + case TYPE_3BYTE_BGR: + case TYPE_BYTE_GRAY: + case TYPE_USHORT_GRAY: + case TYPE_BYTE_BINARY: + case TYPE_BYTE_INDEXED: + case TYPE_USHORT_565_RGB: + case TYPE_USHORT_555_RGB: + default: + return true; + } + } + + public int[] get秘pix() { + int[] pixels = null; + Raster r = raster; + int[] p = 秘pix; + + if (getColorModel() == ColorModel.秘RGBdefault) { + int[] rp = ((SunWritableRaster) r).秘pix; + /** + * @j2sNative + * + * return rp || p; + * + */ + } else { + int n = width * height; + int[] a = new int[n]; + getRaster().getPixels(0, 0, width, height, a); + 秘pix = pixels = new int[n * 4]; + for (int i = 0, pt = 0; i < n; i++, pt += 4) { + getColorModel().getComponents(a[i], pixels, pt); + } + } + return pixels; + } + + public DOMNode 秘updateNode(DOMNode imgNode) { + if (秘userRaster) { + Graphics g = getGraphics(); + g.drawImage(this, 0, 0, null); + } + return imgNode; + } } diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/ColorModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/ColorModel.java index e52641a5f..28c98446f 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/ColorModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/ColorModel.java @@ -30,7 +30,14 @@ import java.awt.Transparency; import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.util.Collections; import java.util.Map; +import java.util.WeakHashMap; + +import sun.java2d.cmm.CMSManager; +import sun.java2d.cmm.ColorTransform; +import sun.java2d.cmm.PCMM; /** * TheColorModel
abstract class encapsulates the @@ -173,7 +180,7 @@ public abstract class ColorModel implements Transparency{ */ protected int transferType; - private static ColorModel RGBdefault; + static ColorModel 秘RGBdefault; /** * Returns aDirectColorModel
that describes the default @@ -192,15 +199,15 @@ public abstract class ColorModel implements Transparency{ * RGB values. */ public static ColorModel getRGBdefault() { - if (RGBdefault == null) { - RGBdefault = new DirectColorModel(32, + if (秘RGBdefault == null) { + 秘RGBdefault = new DirectColorModel(32, 0x00ff0000, // Red 0x0000ff00, // Green 0x000000ff, // Blue 0xff000000 // Alpha ); } - return RGBdefault; + return 秘RGBdefault; } /** @@ -1645,18 +1652,17 @@ public String toString() { ); } - static int getDefaultTransferType(int pixel_bits) { - if (pixel_bits <= 8) { - return DataBuffer.TYPE_BYTE; - } -// else if (pixel_bits <= 16) { -// return DataBuffer.TYPE_USHORT; -// } else if (pixel_bits <= 32) { - return DataBuffer.TYPE_INT; -// } else { -// return DataBuffer.TYPE_UNDEFINED; -// } - } + static int getDefaultTransferType(int pixel_bits) { + if (pixel_bits <= 8) { + return DataBuffer.TYPE_BYTE; + } else if (pixel_bits <= 16) { + return DataBuffer.TYPE_USHORT; + } else if (pixel_bits <= 32) { + return DataBuffer.TYPE_INT; + } else { + return DataBuffer.TYPE_UNDEFINED; + } + } static byte[] l8Tos8 = null; // 8-bit linear to 8-bit non-linear sRGB LUT static byte[] s8Tol8 = null; // 8-bit non-linear sRGB to 8-bit linear LUT @@ -1677,257 +1683,257 @@ static boolean isLinearRGBspace(ColorSpace cs) { } static boolean isLinearGRAYspace(ColorSpace cs) { - return false; -// // Note: CMM.GRAYspace will be null if the linear -// // gray space has not been created yet. -// return (cs == CMSManager.GRAYspace); + // Note: CMM.GRAYspace will be null if the linear + // gray space has not been created yet. + return (cs == CMSManager.GRAYspace); + } + + + static byte[] getLinearRGB8TosRGB8LUT() { + if (l8Tos8 == null) { + l8Tos8 = new byte[256]; + float input, output; + // algorithm for linear RGB to nonlinear sRGB conversion + // is from the IEC 61966-2-1 International Standard, + // Colour Management - Default RGB colour space - sRGB, + // First Edition, 1999-10, + // avaiable for order at http://www.iec.ch + for (int i = 0; i <= 255; i++) { + input = ((float) i) / 255.0f; + if (input <= 0.0031308f) { + output = input * 12.92f; + } else { + output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) + - 0.055f; + } + l8Tos8[i] = (byte) Math.round(output * 255.0f); + } + } + return l8Tos8; + } + + static byte[] getsRGB8ToLinearRGB8LUT() { + if (s8Tol8 == null) { + s8Tol8 = new byte[256]; + float input, output; + // algorithm from IEC 61966-2-1 International Standard + for (int i = 0; i <= 255; i++) { + input = ((float) i) / 255.0f; + if (input <= 0.04045f) { + output = input / 12.92f; + } else { + output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); + } + s8Tol8[i] = (byte) Math.round(output * 255.0f); + } + } + return s8Tol8; + } + + static byte[] getLinearRGB16TosRGB8LUT() { + if (l16Tos8 == null) { + l16Tos8 = new byte[65536]; + float input, output; + // algorithm from IEC 61966-2-1 International Standard + for (int i = 0; i <= 65535; i++) { + input = ((float) i) / 65535.0f; + if (input <= 0.0031308f) { + output = input * 12.92f; + } else { + output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) + - 0.055f; + } + l16Tos8[i] = (byte) Math.round(output * 255.0f); + } + } + return l16Tos8; + } + + static short[] getsRGB8ToLinearRGB16LUT() { + if (s8Tol16 == null) { + s8Tol16 = new short[256]; + float input, output; + // algorithm from IEC 61966-2-1 International Standard + for (int i = 0; i <= 255; i++) { + input = ((float) i) / 255.0f; + if (input <= 0.04045f) { + output = input / 12.92f; + } else { + output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); + } + s8Tol16[i] = (short) Math.round(output * 65535.0f); + } + } + return s8Tol16; + } + + /* + * Return a byte LUT that converts 8-bit gray values in the grayCS + * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut + * is the byte array returned by this method and sval = lut[gval], + * then the sRGB triple (sval,sval,sval) is the best match to gval. + * Cache references to any computed LUT in a Map. + */ + static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) { + if (isLinearGRAYspace(grayCS)) { + return getLinearRGB8TosRGB8LUT(); + } + if (g8Tos8Map != null) { + byte[] g8Tos8LUT = (byte []) g8Tos8Map.get(grayCS); + if (g8Tos8LUT != null) { + return g8Tos8LUT; + } + } + byte[] g8Tos8LUT = new byte[256]; + for (int i = 0; i <= 255; i++) { + g8Tos8LUT[i] = (byte) i; + } + ColorTransform[] transformList = new ColorTransform[2]; + PCMM mdl = CMSManager.getModule(); + ICC_ColorSpace srgbCS = + (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); + transformList[0] = mdl.createTransform( + grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform( + srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + ColorTransform t = mdl.createTransform(transformList); + byte[] tmp = t.colorConvert(g8Tos8LUT, null); + for (int i = 0, j= 2; i <= 255; i++, j += 3) { + // All three components of tmp should be equal, since + // the input color space to colorConvert is a gray scale + // space. However, there are slight anomalies in the results. + // Copy tmp starting at index 2, since colorConvert seems + // to be slightly more accurate for the third component! + g8Tos8LUT[i] = tmp[j]; + } + if (g8Tos8Map == null) { + g8Tos8Map = Collections.synchronizedMap(new WeakHashMap(2)); + } + g8Tos8Map.put(grayCS, g8Tos8LUT); + return g8Tos8LUT; } -// static byte[] getLinearRGB8TosRGB8LUT() { -// if (l8Tos8 == null) { -// l8Tos8 = new byte[256]; -// float input, output; -// // algorithm for linear RGB to nonlinear sRGB conversion -// // is from the IEC 61966-2-1 International Standard, -// // Colour Management - Default RGB colour space - sRGB, -// // First Edition, 1999-10, -// // avaiable for order at http://www.iec.ch -// for (int i = 0; i <= 255; i++) { -// input = ((float) i) / 255.0f; -// if (input <= 0.0031308f) { -// output = input * 12.92f; -// } else { -// output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) -// - 0.055f; -// } -// l8Tos8[i] = (byte) Math.round(output * 255.0f); -// } -// } -// return l8Tos8; -// } -// -// static byte[] getsRGB8ToLinearRGB8LUT() { -// if (s8Tol8 == null) { -// s8Tol8 = new byte[256]; -// float input, output; -// // algorithm from IEC 61966-2-1 International Standard -// for (int i = 0; i <= 255; i++) { -// input = ((float) i) / 255.0f; -// if (input <= 0.04045f) { -// output = input / 12.92f; -// } else { -// output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); -// } -// s8Tol8[i] = (byte) Math.round(output * 255.0f); -// } -// } -// return s8Tol8; -// } -// -// static byte[] getLinearRGB16TosRGB8LUT() { -// if (l16Tos8 == null) { -// l16Tos8 = new byte[65536]; -// float input, output; -// // algorithm from IEC 61966-2-1 International Standard -// for (int i = 0; i <= 65535; i++) { -// input = ((float) i) / 65535.0f; -// if (input <= 0.0031308f) { -// output = input * 12.92f; -// } else { -// output = 1.055f * ((float) Math.pow(input, (1.0 / 2.4))) -// - 0.055f; -// } -// l16Tos8[i] = (byte) Math.round(output * 255.0f); -// } -// } -// return l16Tos8; -// } -// -// static short[] getsRGB8ToLinearRGB16LUT() { -// if (s8Tol16 == null) { -// s8Tol16 = new short[256]; -// float input, output; -// // algorithm from IEC 61966-2-1 International Standard -// for (int i = 0; i <= 255; i++) { -// input = ((float) i) / 255.0f; -// if (input <= 0.04045f) { -// output = input / 12.92f; -// } else { -// output = (float) Math.pow((input + 0.055f) / 1.055f, 2.4); -// } -// s8Tol16[i] = (short) Math.round(output * 65535.0f); -// } -// } -// return s8Tol16; -// } -// -// /* -// * Return a byte LUT that converts 8-bit gray values in the grayCS -// * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut -// * is the byte array returned by this method and sval = lut[gval], -// * then the sRGB triple (sval,sval,sval) is the best match to gval. -// * Cache references to any computed LUT in a Map. -// */ -// static byte[] getGray8TosRGB8LUT(ICC_ColorSpace grayCS) { -// if (isLinearGRAYspace(grayCS)) { -// return getLinearRGB8TosRGB8LUT(); -// } -// if (g8Tos8Map != null) { -// byte[] g8Tos8LUT = (byte []) g8Tos8Map.get(grayCS); -// if (g8Tos8LUT != null) { -// return g8Tos8LUT; -// } -// } -// byte[] g8Tos8LUT = new byte[256]; -// for (int i = 0; i <= 255; i++) { -// g8Tos8LUT[i] = (byte) i; -// } -// ColorTransform[] transformList = new ColorTransform[2]; -// PCMM mdl = CMSManager.getModule(); -// ICC_ColorSpace srgbCS = -// (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); -// transformList[0] = mdl.createTransform( -// grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); -// transformList[1] = mdl.createTransform( -// srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); -// ColorTransform t = mdl.createTransform(transformList); -// byte[] tmp = t.colorConvert(g8Tos8LUT, null); -// for (int i = 0, j= 2; i <= 255; i++, j += 3) { -// // All three components of tmp should be equal, since -// // the input color space to colorConvert is a gray scale -// // space. However, there are slight anomalies in the results. -// // Copy tmp starting at index 2, since colorConvert seems -// // to be slightly more accurate for the third component! -// g8Tos8LUT[i] = tmp[j]; -// } -// if (g8Tos8Map == null) { -// g8Tos8Map = Collections.synchronizedMap(new WeakHashMap(2)); -// } -// g8Tos8Map.put(grayCS, g8Tos8LUT); -// return g8Tos8LUT; -// } -// -// /* -// * Return a byte LUT that converts 16-bit gray values in the CS_GRAY -// * linear gray ColorSpace to the appropriate 8-bit value in the -// * grayCS ColorSpace. Cache references to any computed LUT in a Map. -// */ -// static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) { -// if (lg16Toog8Map != null) { -// byte[] lg16Toog8LUT = (byte []) lg16Toog8Map.get(grayCS); -// if (lg16Toog8LUT != null) { -// return lg16Toog8LUT; -// } -// } -// short[] tmp = new short[65536]; -// for (int i = 0; i <= 65535; i++) { -// tmp[i] = (short) i; -// } -// ColorTransform[] transformList = new ColorTransform[2]; -// PCMM mdl = CMSManager.getModule(); -// ICC_ColorSpace lgCS = -// (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); -// transformList[0] = mdl.createTransform ( -// lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); -// transformList[1] = mdl.createTransform ( -// grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); -// ColorTransform t = mdl.createTransform(transformList); -// tmp = t.colorConvert(tmp, null); -// byte[] lg16Toog8LUT = new byte[65536]; -// for (int i = 0; i <= 65535; i++) { -// // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) -// lg16Toog8LUT[i] = -// (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f); -// } -// if (lg16Toog8Map == null) { -// lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap(2)); -// } -// lg16Toog8Map.put(grayCS, lg16Toog8LUT); -// return lg16Toog8LUT; -// } -// -// /* -// * Return a byte LUT that converts 16-bit gray values in the grayCS -// * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut -// * is the byte array returned by this method and sval = lut[gval], -// * then the sRGB triple (sval,sval,sval) is the best match to gval. -// * Cache references to any computed LUT in a Map. -// */ -// static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) { -// if (isLinearGRAYspace(grayCS)) { -// return getLinearRGB16TosRGB8LUT(); -// } -// if (g16Tos8Map != null) { -// byte[] g16Tos8LUT = (byte []) g16Tos8Map.get(grayCS); -// if (g16Tos8LUT != null) { -// return g16Tos8LUT; -// } -// } -// short[] tmp = new short[65536]; -// for (int i = 0; i <= 65535; i++) { -// tmp[i] = (short) i; -// } -// ColorTransform[] transformList = new ColorTransform[2]; -// PCMM mdl = CMSManager.getModule(); -// ICC_ColorSpace srgbCS = -// (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); -// transformList[0] = mdl.createTransform ( -// grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); -// transformList[1] = mdl.createTransform ( -// srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); -// ColorTransform t = mdl.createTransform(transformList); -// tmp = t.colorConvert(tmp, null); -// byte[] g16Tos8LUT = new byte[65536]; -// for (int i = 0, j= 2; i <= 65535; i++, j += 3) { -// // All three components of tmp should be equal, since -// // the input color space to colorConvert is a gray scale -// // space. However, there are slight anomalies in the results. -// // Copy tmp starting at index 2, since colorConvert seems -// // to be slightly more accurate for the third component! -// -// // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) -// g16Tos8LUT[i] = -// (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f); -// } -// if (g16Tos8Map == null) { -// g16Tos8Map = Collections.synchronizedMap(new WeakHashMap(2)); -// } -// g16Tos8Map.put(grayCS, g16Tos8LUT); -// return g16Tos8LUT; -// } -// -// /* -// * Return a short LUT that converts 16-bit gray values in the CS_GRAY -// * linear gray ColorSpace to the appropriate 16-bit value in the -// * grayCS ColorSpace. Cache references to any computed LUT in a Map. -// */ -// static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) { -// if (lg16Toog16Map != null) { -// short[] lg16Toog16LUT = (short []) lg16Toog16Map.get(grayCS); -// if (lg16Toog16LUT != null) { -// return lg16Toog16LUT; -// } -// } -// short[] tmp = new short[65536]; -// for (int i = 0; i <= 65535; i++) { -// tmp[i] = (short) i; -// } -// ColorTransform[] transformList = new ColorTransform[2]; -// PCMM mdl = CMSManager.getModule(); -// ICC_ColorSpace lgCS = -// (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); -// transformList[0] = mdl.createTransform ( -// lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); -// transformList[1] = mdl.createTransform( -// grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); -// ColorTransform t = mdl.createTransform( -// transformList); -// short[] lg16Toog16LUT = t.colorConvert(tmp, null); -// if (lg16Toog16Map == null) { -// lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap(2)); -// } -// lg16Toog16Map.put(grayCS, lg16Toog16LUT); -// return lg16Toog16LUT; -// } + /* + * Return a byte LUT that converts 16-bit gray values in the CS_GRAY + * linear gray ColorSpace to the appropriate 8-bit value in the + * grayCS ColorSpace. Cache references to any computed LUT in a Map. + */ + static byte[] getLinearGray16ToOtherGray8LUT(ICC_ColorSpace grayCS) { + if (lg16Toog8Map != null) { + byte[] lg16Toog8LUT = (byte []) lg16Toog8Map.get(grayCS); + if (lg16Toog8LUT != null) { + return lg16Toog8LUT; + } + } + short[] tmp = new short[65536]; + for (int i = 0; i <= 65535; i++) { + tmp[i] = (short) i; + } + ColorTransform[] transformList = new ColorTransform[2]; + PCMM mdl = CMSManager.getModule(); + ICC_ColorSpace lgCS = + (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); + transformList[0] = mdl.createTransform ( + lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform ( + grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + ColorTransform t = mdl.createTransform(transformList); + tmp = t.colorConvert(tmp, null); + byte[] lg16Toog8LUT = new byte[65536]; + for (int i = 0; i <= 65535; i++) { + // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) + lg16Toog8LUT[i] = + (byte) (((float) (tmp[i] & 0xffff)) * (1.0f /257.0f) + 0.5f); + } + if (lg16Toog8Map == null) { + lg16Toog8Map = Collections.synchronizedMap(new WeakHashMap(2)); + } + lg16Toog8Map.put(grayCS, lg16Toog8LUT); + return lg16Toog8LUT; + } + + /* + * Return a byte LUT that converts 16-bit gray values in the grayCS + * ColorSpace to the appropriate 8-bit sRGB value. I.e., if lut + * is the byte array returned by this method and sval = lut[gval], + * then the sRGB triple (sval,sval,sval) is the best match to gval. + * Cache references to any computed LUT in a Map. + */ + static byte[] getGray16TosRGB8LUT(ICC_ColorSpace grayCS) { + if (isLinearGRAYspace(grayCS)) { + return getLinearRGB16TosRGB8LUT(); + } + if (g16Tos8Map != null) { + byte[] g16Tos8LUT = (byte []) g16Tos8Map.get(grayCS); + if (g16Tos8LUT != null) { + return g16Tos8LUT; + } + } + short[] tmp = new short[65536]; + for (int i = 0; i <= 65535; i++) { + tmp[i] = (short) i; + } + ColorTransform[] transformList = new ColorTransform[2]; + PCMM mdl = CMSManager.getModule(); + ICC_ColorSpace srgbCS = + (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_sRGB); + transformList[0] = mdl.createTransform ( + grayCS.getProfile(), ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform ( + srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + ColorTransform t = mdl.createTransform(transformList); + tmp = t.colorConvert(tmp, null); + byte[] g16Tos8LUT = new byte[65536]; + for (int i = 0, j= 2; i <= 65535; i++, j += 3) { + // All three components of tmp should be equal, since + // the input color space to colorConvert is a gray scale + // space. However, there are slight anomalies in the results. + // Copy tmp starting at index 2, since colorConvert seems + // to be slightly more accurate for the third component! + + // scale unsigned short (0 - 65535) to unsigned byte (0 - 255) + g16Tos8LUT[i] = + (byte) (((float) (tmp[j] & 0xffff)) * (1.0f /257.0f) + 0.5f); + } + if (g16Tos8Map == null) { + g16Tos8Map = Collections.synchronizedMap(new WeakHashMap(2)); + } + g16Tos8Map.put(grayCS, g16Tos8LUT); + return g16Tos8LUT; + } + + /* + * Return a short LUT that converts 16-bit gray values in the CS_GRAY + * linear gray ColorSpace to the appropriate 16-bit value in the + * grayCS ColorSpace. Cache references to any computed LUT in a Map. + */ + static short[] getLinearGray16ToOtherGray16LUT(ICC_ColorSpace grayCS) { + if (lg16Toog16Map != null) { + short[] lg16Toog16LUT = (short []) lg16Toog16Map.get(grayCS); + if (lg16Toog16LUT != null) { + return lg16Toog16LUT; + } + } + short[] tmp = new short[65536]; + for (int i = 0; i <= 65535; i++) { + tmp[i] = (short) i; + } + ColorTransform[] transformList = new ColorTransform[2]; + PCMM mdl = CMSManager.getModule(); + ICC_ColorSpace lgCS = + (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_GRAY); + transformList[0] = mdl.createTransform ( + lgCS.getProfile(), ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform( + grayCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + ColorTransform t = mdl.createTransform( + transformList); + short[] lg16Toog16LUT = t.colorConvert(tmp, null); + if (lg16Toog16Map == null) { + lg16Toog16Map = Collections.synchronizedMap(new WeakHashMap(2)); + } + lg16Toog16Map.put(grayCS, lg16Toog16LUT); + return lg16Toog16LUT; + } } diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/ComponentColorModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/ComponentColorModel.java index 98a039bc0..f0c93cc1c 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/ComponentColorModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/ComponentColorModel.java @@ -30,6 +30,7 @@ import java.awt.color.ColorSpace; //import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_ColorSpace; /** * AColorModel
class that works with pixel values that @@ -194,7 +195,7 @@ public class ComponentColorModel extends ColorModel { private byte[] tosRGB8LUT; private byte[] fromsRGB8LUT8; private short[] fromsRGB8LUT16; -// private byte[] fromLinearGray16ToOtherGray8LUT; + private byte[] fromLinearGray16ToOtherGray8LUT; private short[] fromLinearGray16ToOtherGray16LUT; private boolean needScaleInit; private boolean noUnnorm; @@ -288,13 +289,13 @@ public ComponentColorModel (ColorSpace colorSpace, signed = true; needScaleInit = true; break; -// case DataBuffer.TYPE_FLOAT: -// case DataBuffer.TYPE_DOUBLE: -// signed = true; -// needScaleInit = false; -// noUnnorm = true; -// nonStdScale = false; -// break; + case DataBuffer.TYPE_FLOAT: + case DataBuffer.TYPE_DOUBLE: + signed = true; + needScaleInit = false; + noUnnorm = true; + nonStdScale = false; + break; default: throw new IllegalArgumentException("This constructor is not "+ "compatible with transferType " + transferType); @@ -414,48 +415,48 @@ private void setupLUTs() { if (is_sRGB) { is_sRGB_stdScale = true; nonStdScale = false; -// } else if (ColorModel.isLinearRGBspace(colorSpace)) { -// // Note that the built-in Linear RGB space has a normalized -// // range of 0.0 - 1.0 for each coordinate. Usage of these -// // LUTs makes that assumption. -// is_LinearRGB_stdScale = true; -// nonStdScale = false; -// if (transferType == DataBuffer.TYPE_BYTE) { -// tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT(); -// fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT(); -// } else { -// tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT(); -// fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); -// } -// } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) && -// (colorSpace instanceof ICC_ColorSpace) && -// (colorSpace.getMinValue(0) == 0.0f) && -// (colorSpace.getMaxValue(0) == 1.0f)) { -// // Note that a normalized range of 0.0 - 1.0 for the gray -// // component is required, because usage of these LUTs makes -// // that assumption. -// ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace; -// is_ICCGray_stdScale = true; -// nonStdScale = false; -// fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); -// if (ColorModel.isLinearGRAYspace(ics)) { -// is_LinearGray_stdScale = true; -// if (transferType == DataBuffer.TYPE_BYTE) { -// tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); -// } else { -// tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); -// } -// } else { -// if (transferType == DataBuffer.TYPE_BYTE) { -// tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); -// fromLinearGray16ToOtherGray8LUT = -// ColorModel.getLinearGray16ToOtherGray8LUT(ics); -// } else { -// tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); -// fromLinearGray16ToOtherGray16LUT = -// ColorModel.getLinearGray16ToOtherGray16LUT(ics); -// } -// } + } else if (ColorModel.isLinearRGBspace(colorSpace)) { + // Note that the built-in Linear RGB space has a normalized + // range of 0.0 - 1.0 for each coordinate. Usage of these + // LUTs makes that assumption. + is_LinearRGB_stdScale = true; + nonStdScale = false; + if (transferType == DataBuffer.TYPE_BYTE) { + tosRGB8LUT = ColorModel.getLinearRGB8TosRGB8LUT(); + fromsRGB8LUT8 = ColorModel.getsRGB8ToLinearRGB8LUT(); + } else { + tosRGB8LUT = ColorModel.getLinearRGB16TosRGB8LUT(); + fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); + } + } else if ((colorSpaceType == ColorSpace.TYPE_GRAY) && + (colorSpace instanceof ICC_ColorSpace) && + (colorSpace.getMinValue(0) == 0.0f) && + (colorSpace.getMaxValue(0) == 1.0f)) { + // Note that a normalized range of 0.0 - 1.0 for the gray + // component is required, because usage of these LUTs makes + // that assumption. + ICC_ColorSpace ics = (ICC_ColorSpace) colorSpace; + is_ICCGray_stdScale = true; + nonStdScale = false; + fromsRGB8LUT16 = ColorModel.getsRGB8ToLinearRGB16LUT(); + if (ColorModel.isLinearGRAYspace(ics)) { + is_LinearGray_stdScale = true; + if (transferType == DataBuffer.TYPE_BYTE) { + tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); + } else { + tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); + } + } else { + if (transferType == DataBuffer.TYPE_BYTE) { + tosRGB8LUT = ColorModel.getGray8TosRGB8LUT(ics); + fromLinearGray16ToOtherGray8LUT = + ColorModel.getLinearGray16ToOtherGray8LUT(ics); + } else { + tosRGB8LUT = ColorModel.getGray16TosRGB8LUT(ics); + fromLinearGray16ToOtherGray16LUT = + ColorModel.getLinearGray16ToOtherGray16LUT(ics); + } + } } else if (needScaleInit) { // if transferType is byte, ushort, int, or short and we // don't already know the ColorSpace has minVlaue == 0.0f and @@ -822,34 +823,34 @@ private int extractComponent(Object inData, int idx, int precision) { return (int) ((sdata[idx] / 32767.0f) * scalefactor + 0.5f); } } -// case DataBuffer.TYPE_FLOAT: { -// float fdata[] = (float[]) inData; -// float scalefactor = (float) ((1 << precision) - 1); -// if (needAlpha) { -// float f = fdata[numColorComponents]; -// if (f != 0.0f) { -// return (int) (((fdata[idx] / f) * scalefactor) + 0.5f); -// } else { -// return 0; -// } -// } else { -// return (int) (fdata[idx] * scalefactor + 0.5f); -// } -// } -// case DataBuffer.TYPE_DOUBLE: { -// double ddata[] = (double[]) inData; -// double scalefactor = (double) ((1 << precision) - 1); -// if (needAlpha) { -// double d = ddata[numColorComponents]; -// if (d != 0.0) { -// return (int) (((ddata[idx] / d) * scalefactor) + 0.5); -// } else { -// return 0; -// } -// } else { -// return (int) (ddata[idx] * scalefactor + 0.5); -// } -// } + case DataBuffer.TYPE_FLOAT: { + float fdata[] = (float[]) inData; + float scalefactor = (float) ((1 << precision) - 1); + if (needAlpha) { + float f = fdata[numColorComponents]; + if (f != 0.0f) { + return (int) (((fdata[idx] / f) * scalefactor) + 0.5f); + } else { + return 0; + } + } else { + return (int) (fdata[idx] * scalefactor + 0.5f); + } + } + case DataBuffer.TYPE_DOUBLE: { + double ddata[] = (double[]) inData; + double scalefactor = (double) ((1 << precision) - 1); + if (needAlpha) { + double d = ddata[numColorComponents]; + if (d != 0.0) { + return (int) (((ddata[idx] / d) * scalefactor) + 0.5); + } else { + return 0; + } + } else { + return (int) (ddata[idx] * scalefactor + 0.5); + } + } case DataBuffer.TYPE_BYTE: byte bdata[] = (byte[])inData; comp = bdata[idx] & mask; @@ -1067,14 +1068,14 @@ public int getAlpha(Object inData) { short sdata[] = (short[])inData; alpha = (int) ((sdata[aIdx] / 32767.0f) * 255.0f + 0.5f); return alpha; -// case DataBuffer.TYPE_FLOAT: -// float fdata[] = (float[])inData; -// alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); -// return alpha; -// case DataBuffer.TYPE_DOUBLE: -// double ddata[] = (double[])inData; -// alpha = (int) (ddata[aIdx] * 255.0 + 0.5); -// return alpha; + case DataBuffer.TYPE_FLOAT: + float fdata[] = (float[])inData; + alpha = (int) (fdata[aIdx] * 255.0f + 0.5f); + return alpha; + case DataBuffer.TYPE_DOUBLE: + double ddata[] = (double[])inData; + alpha = (int) (ddata[aIdx] * 255.0 + 0.5); + return alpha; case DataBuffer.TYPE_BYTE: byte bdata[] = (byte[])inData; alpha = bdata[aIdx] & mask; @@ -1310,168 +1311,168 @@ public Object getDataElements(int rgb, Object pixel) { } return sdata; } -// case DataBuffer.TYPE_FLOAT: -// { -// float fdata[]; -// if (pixel == null) { -// fdata = new float[numComponents]; -// } else { -// fdata = (float[])pixel; -// } -// float factor; -// if (is_sRGB_stdScale || is_LinearRGB_stdScale) { -// if (is_LinearRGB_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// factor = 1.0f / 65535.0f; -// } else { -// factor = 1.0f / 255.0f; -// } -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// fdata[3] = alp * (1.0f / 255.0f); -// if (isAlphaPremultiplied) { -// factor *= fdata[3]; -// } -// } -// fdata[0] = red * factor; -// fdata[1] = grn * factor; -// fdata[2] = blu * factor; -// } else if (is_LinearGray_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// fdata[0] = ((0.2125f * red) + -// (0.7154f * grn) + -// (0.0721f * blu)) / 65535.0f; -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// fdata[1] = alp * (1.0f / 255.0f); -// if (isAlphaPremultiplied) { -// fdata[0] *= fdata[1]; -// } -// } -// } else if (is_ICCGray_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// int gray = (int) ((0.2125f * red) + -// (0.7154f * grn) + -// (0.0721f * blu) + 0.5f); -// fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & -// 0xffff) / 65535.0f; -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// fdata[1] = alp * (1.0f / 255.0f); -// if (isAlphaPremultiplied) { -// fdata[0] *= fdata[1]; -// } -// } -// } else { -// float norm[] = new float[3]; -// factor = 1.0f / 255.0f; -// norm[0] = red * factor; -// norm[1] = grn * factor; -// norm[2] = blu * factor; -// norm = colorSpace.fromRGB(norm); -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// fdata[numColorComponents] = alp * factor; -// if (isAlphaPremultiplied) { -// factor *= alp; -// for (int i = 0; i < numColorComponents; i++) { -// norm[i] *= factor; -// } -// } -// } -// for (int i = 0; i < numColorComponents; i++) { -// fdata[i] = norm[i]; -// } -// } -// return fdata; -// } -// case DataBuffer.TYPE_DOUBLE: -// { -// double ddata[]; -// if (pixel == null) { -// ddata = new double[numComponents]; -// } else { -// ddata = (double[])pixel; -// } -// if (is_sRGB_stdScale || is_LinearRGB_stdScale) { -// double factor; -// if (is_LinearRGB_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// factor = 1.0 / 65535.0; -// } else { -// factor = 1.0 / 255.0; -// } -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// ddata[3] = alp * (1.0 / 255.0); -// if (isAlphaPremultiplied) { -// factor *= ddata[3]; -// } -// } -// ddata[0] = red * factor; -// ddata[1] = grn * factor; -// ddata[2] = blu * factor; -// } else if (is_LinearGray_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// ddata[0] = ((0.2125 * red) + -// (0.7154 * grn) + -// (0.0721 * blu)) / 65535.0; -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// ddata[1] = alp * (1.0 / 255.0); -// if (isAlphaPremultiplied) { -// ddata[0] *= ddata[1]; -// } -// } -// } else if (is_ICCGray_stdScale) { -// red = fromsRGB8LUT16[red] & 0xffff; -// grn = fromsRGB8LUT16[grn] & 0xffff; -// blu = fromsRGB8LUT16[blu] & 0xffff; -// int gray = (int) ((0.2125f * red) + -// (0.7154f * grn) + -// (0.0721f * blu) + 0.5f); -// ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & -// 0xffff) / 65535.0; -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// ddata[1] = alp * (1.0 / 255.0); -// if (isAlphaPremultiplied) { -// ddata[0] *= ddata[1]; -// } -// } -// } else { -// float factor = 1.0f / 255.0f; -// float norm[] = new float[3]; -// norm[0] = red * factor; -// norm[1] = grn * factor; -// norm[2] = blu * factor; -// norm = colorSpace.fromRGB(norm); -// if (supportsAlpha) { -// alp = (rgb>>24) & 0xff; -// ddata[numColorComponents] = alp * (1.0 / 255.0); -// if (isAlphaPremultiplied) { -// factor *= alp; -// for (int i = 0; i < numColorComponents; i++) { -// norm[i] *= factor; -// } -// } -// } -// for (int i = 0; i < numColorComponents; i++) { -// ddata[i] = norm[i]; -// } -// } -// return ddata; -// } + case DataBuffer.TYPE_FLOAT: + { + float fdata[]; + if (pixel == null) { + fdata = new float[numComponents]; + } else { + fdata = (float[])pixel; + } + float factor; + if (is_sRGB_stdScale || is_LinearRGB_stdScale) { + if (is_LinearRGB_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + factor = 1.0f / 65535.0f; + } else { + factor = 1.0f / 255.0f; + } + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + fdata[3] = alp * (1.0f / 255.0f); + if (isAlphaPremultiplied) { + factor *= fdata[3]; + } + } + fdata[0] = red * factor; + fdata[1] = grn * factor; + fdata[2] = blu * factor; + } else if (is_LinearGray_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + fdata[0] = ((0.2125f * red) + + (0.7154f * grn) + + (0.0721f * blu)) / 65535.0f; + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + fdata[1] = alp * (1.0f / 255.0f); + if (isAlphaPremultiplied) { + fdata[0] *= fdata[1]; + } + } + } else if (is_ICCGray_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + int gray = (int) ((0.2125f * red) + + (0.7154f * grn) + + (0.0721f * blu) + 0.5f); + fdata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & + 0xffff) / 65535.0f; + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + fdata[1] = alp * (1.0f / 255.0f); + if (isAlphaPremultiplied) { + fdata[0] *= fdata[1]; + } + } + } else { + float norm[] = new float[3]; + factor = 1.0f / 255.0f; + norm[0] = red * factor; + norm[1] = grn * factor; + norm[2] = blu * factor; + norm = colorSpace.fromRGB(norm); + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + fdata[numColorComponents] = alp * factor; + if (isAlphaPremultiplied) { + factor *= alp; + for (int i = 0; i < numColorComponents; i++) { + norm[i] *= factor; + } + } + } + for (int i = 0; i < numColorComponents; i++) { + fdata[i] = norm[i]; + } + } + return fdata; + } + case DataBuffer.TYPE_DOUBLE: + { + double ddata[]; + if (pixel == null) { + ddata = new double[numComponents]; + } else { + ddata = (double[])pixel; + } + if (is_sRGB_stdScale || is_LinearRGB_stdScale) { + double factor; + if (is_LinearRGB_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + factor = 1.0 / 65535.0; + } else { + factor = 1.0 / 255.0; + } + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + ddata[3] = alp * (1.0 / 255.0); + if (isAlphaPremultiplied) { + factor *= ddata[3]; + } + } + ddata[0] = red * factor; + ddata[1] = grn * factor; + ddata[2] = blu * factor; + } else if (is_LinearGray_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + ddata[0] = ((0.2125 * red) + + (0.7154 * grn) + + (0.0721 * blu)) / 65535.0; + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + ddata[1] = alp * (1.0 / 255.0); + if (isAlphaPremultiplied) { + ddata[0] *= ddata[1]; + } + } + } else if (is_ICCGray_stdScale) { + red = fromsRGB8LUT16[red] & 0xffff; + grn = fromsRGB8LUT16[grn] & 0xffff; + blu = fromsRGB8LUT16[blu] & 0xffff; + int gray = (int) ((0.2125f * red) + + (0.7154f * grn) + + (0.0721f * blu) + 0.5f); + ddata[0] = (fromLinearGray16ToOtherGray16LUT[gray] & + 0xffff) / 65535.0; + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + ddata[1] = alp * (1.0 / 255.0); + if (isAlphaPremultiplied) { + ddata[0] *= ddata[1]; + } + } + } else { + float factor = 1.0f / 255.0f; + float norm[] = new float[3]; + norm[0] = red * factor; + norm[1] = grn * factor; + norm[2] = blu * factor; + norm = colorSpace.fromRGB(norm); + if (supportsAlpha) { + alp = (rgb>>24) & 0xff; + ddata[numColorComponents] = alp * (1.0 / 255.0); + if (isAlphaPremultiplied) { + factor *= alp; + for (int i = 0; i < numColorComponents; i++) { + norm[i] *= factor; + } + } + } + for (int i = 0; i < numColorComponents; i++) { + ddata[i] = norm[i]; + } + } + return ddata; + } } } @@ -2268,49 +2269,49 @@ public Object getDataElements(float[] normComponents, int normOffset, } } return spixel; -// case DataBuffer.TYPE_FLOAT: -// float[] fpixel; -// if (obj == null) { -// fpixel = new float[numComponents]; -// } else { -// fpixel = (float[]) obj; -// } -// if (needAlpha) { -// float alpha = normComponents[numColorComponents + normOffset]; -// for (int c = 0, nc = normOffset; c < numColorComponents; -// c++, nc++) { -// fpixel[c] = normComponents[nc] * alpha; -// } -// fpixel[numColorComponents] = alpha; -// } else { -// for (int c = 0, nc = normOffset; c < numComponents; -// c++, nc++) { -// fpixel[c] = normComponents[nc]; -// } -// } -// return fpixel; -// case DataBuffer.TYPE_DOUBLE: -// double[] dpixel; -// if (obj == null) { -// dpixel = new double[numComponents]; -// } else { -// dpixel = (double[]) obj; -// } -// if (needAlpha) { -// double alpha = -// (double) (normComponents[numColorComponents + normOffset]); -// for (int c = 0, nc = normOffset; c < numColorComponents; -// c++, nc++) { -// dpixel[c] = normComponents[nc] * alpha; -// } -// dpixel[numColorComponents] = alpha; -// } else { -// for (int c = 0, nc = normOffset; c < numComponents; -// c++, nc++) { -// dpixel[c] = (double) normComponents[nc]; -// } -// } -// return dpixel; + case DataBuffer.TYPE_FLOAT: + float[] fpixel; + if (obj == null) { + fpixel = new float[numComponents]; + } else { + fpixel = (float[]) obj; + } + if (needAlpha) { + float alpha = normComponents[numColorComponents + normOffset]; + for (int c = 0, nc = normOffset; c < numColorComponents; + c++, nc++) { + fpixel[c] = normComponents[nc] * alpha; + } + fpixel[numColorComponents] = alpha; + } else { + for (int c = 0, nc = normOffset; c < numComponents; + c++, nc++) { + fpixel[c] = normComponents[nc]; + } + } + return fpixel; + case DataBuffer.TYPE_DOUBLE: + double[] dpixel; + if (obj == null) { + dpixel = new double[numComponents]; + } else { + dpixel = (double[]) obj; + } + if (needAlpha) { + double alpha = + (double) (normComponents[numColorComponents + normOffset]); + for (int c = 0, nc = normOffset; c < numColorComponents; + c++, nc++) { + dpixel[c] = normComponents[nc] * alpha; + } + dpixel[numColorComponents] = alpha; + } else { + for (int c = 0, nc = normOffset; c < numComponents; + c++, nc++) { + dpixel[c] = (double) normComponents[nc]; + } + } + return dpixel; default: throw new UnsupportedOperationException("This method has not been "+ "implemented for transferType " + @@ -2397,18 +2398,18 @@ public float[] getNormalizedComponents(Object pixel, normComponents[nc] = ((float) spixel[c]) / 32767.0f; } break; -// case DataBuffer.TYPE_FLOAT: -// float[] fpixel = (float[]) pixel; -// for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { -// normComponents[nc] = fpixel[c]; -// } -// break; -// case DataBuffer.TYPE_DOUBLE: -// double[] dpixel = (double[]) pixel; -// for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { -// normComponents[nc] = (float) dpixel[c]; -// } -// break; + case DataBuffer.TYPE_FLOAT: + float[] fpixel = (float[]) pixel; + for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { + normComponents[nc] = fpixel[c]; + } + break; + case DataBuffer.TYPE_DOUBLE: + double[] dpixel = (double[]) pixel; + for (int c = 0, nc = normOffset; c < numComponents; c++, nc++) { + normComponents[nc] = (float) dpixel[c]; + } + break; default: throw new UnsupportedOperationException("This method has not been "+ "implemented for transferType " + @@ -2598,56 +2599,56 @@ public ColorModel coerceData (WritableRaster raster, } } break; -// case DataBuffer.TYPE_FLOAT: { -// float pixel[] = null; -// float zpixel[] = null; -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = (float[]) raster.getDataElements(rX, rY, -// pixel); -// normAlpha = pixel[aIdx]; -// if (normAlpha != 0.0f) { -// for (int c=0; c < aIdx; c++) { -// pixel[c] *= normAlpha; -// } -// raster.setDataElements(rX, rY, pixel); -// } else { -// if (zpixel == null) { -// zpixel = new float[numComponents]; -// java.util.Arrays.fill(zpixel, 0.0f); -// } -// raster.setDataElements(rX, rY, zpixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_DOUBLE: { -// double pixel[] = null; -// double zpixel[] = null; -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = (double[]) raster.getDataElements(rX, rY, -// pixel); -// double dnormAlpha = pixel[aIdx]; -// if (dnormAlpha != 0.0) { -// for (int c=0; c < aIdx; c++) { -// pixel[c] *= dnormAlpha; -// } -// raster.setDataElements(rX, rY, pixel); -// } else { -// if (zpixel == null) { -// zpixel = new double[numComponents]; -// java.util.Arrays.fill(zpixel, 0.0); -// } -// raster.setDataElements(rX, rY, zpixel); -// } -// } -// } -// } -// break; + case DataBuffer.TYPE_FLOAT: { + float pixel[] = null; + float zpixel[] = null; + for (int y = 0; y < h; y++, rY++) { + rX = rminX; + for (int x = 0; x < w; x++, rX++) { + pixel = (float[]) raster.getDataElements(rX, rY, + pixel); + normAlpha = pixel[aIdx]; + if (normAlpha != 0.0f) { + for (int c=0; c < aIdx; c++) { + pixel[c] *= normAlpha; + } + raster.setDataElements(rX, rY, pixel); + } else { + if (zpixel == null) { + zpixel = new float[numComponents]; + java.util.Arrays.fill(zpixel, 0.0f); + } + raster.setDataElements(rX, rY, zpixel); + } + } + } + } + break; + case DataBuffer.TYPE_DOUBLE: { + double pixel[] = null; + double zpixel[] = null; + for (int y = 0; y < h; y++, rY++) { + rX = rminX; + for (int x = 0; x < w; x++, rX++) { + pixel = (double[]) raster.getDataElements(rX, rY, + pixel); + double dnormAlpha = pixel[aIdx]; + if (dnormAlpha != 0.0) { + for (int c=0; c < aIdx; c++) { + pixel[c] *= dnormAlpha; + } + raster.setDataElements(rX, rY, pixel); + } else { + if (zpixel == null) { + zpixel = new double[numComponents]; + java.util.Arrays.fill(zpixel, 0.0); + } + raster.setDataElements(rX, rY, zpixel); + } + } + } + } + break; default: throw new UnsupportedOperationException("This method has not been "+ "implemented for transferType " + transferType); @@ -2740,44 +2741,44 @@ public ColorModel coerceData (WritableRaster raster, } } break; -// case DataBuffer.TYPE_FLOAT: { -// float pixel[] = null; -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = (float[])raster.getDataElements(rX, rY, -// pixel); -// normAlpha = pixel[aIdx]; -// if (normAlpha != 0.0f) { -// float invAlpha = 1.0f / normAlpha; -// for (int c=0; c < aIdx; c++) { -// pixel[c] *= invAlpha; -// } -// raster.setDataElements(rX, rY, pixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_DOUBLE: { -// double pixel[] = null; -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = (double[])raster.getDataElements(rX, rY, -// pixel); -// double dnormAlpha = pixel[aIdx]; -// if (dnormAlpha != 0.0) { -// double invAlpha = 1.0 / dnormAlpha; -// for (int c=0; c < aIdx; c++) { -// pixel[c] *= invAlpha; -// } -// raster.setDataElements(rX, rY, pixel); -// } -// } -// } -// } -// break; + case DataBuffer.TYPE_FLOAT: { + float pixel[] = null; + for (int y = 0; y < h; y++, rY++) { + rX = rminX; + for (int x = 0; x < w; x++, rX++) { + pixel = (float[])raster.getDataElements(rX, rY, + pixel); + normAlpha = pixel[aIdx]; + if (normAlpha != 0.0f) { + float invAlpha = 1.0f / normAlpha; + for (int c=0; c < aIdx; c++) { + pixel[c] *= invAlpha; + } + raster.setDataElements(rX, rY, pixel); + } + } + } + } + break; + case DataBuffer.TYPE_DOUBLE: { + double pixel[] = null; + for (int y = 0; y < h; y++, rY++) { + rX = rminX; + for (int x = 0; x < w; x++, rX++) { + pixel = (double[])raster.getDataElements(rX, rY, + pixel); + double dnormAlpha = pixel[aIdx]; + if (dnormAlpha != 0.0) { + double invAlpha = 1.0 / dnormAlpha; + for (int c=0; c < aIdx; c++) { + pixel[c] *= invAlpha; + } + raster.setDataElements(rX, rY, pixel); + } + } + } + } + break; default: throw new UnsupportedOperationException("This method has not been "+ "implemented for transferType " + transferType); diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/DirectColorModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/DirectColorModel.java index dac1451e6..4a1179bb0 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/DirectColorModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/DirectColorModel.java @@ -114,14 +114,14 @@ public class DirectColorModel extends PackedColorModel { private int green_mask; private int blue_mask; private int alpha_mask; -// private int red_offset; -// private int green_offset; -// private int blue_offset; -// private int alpha_offset; -// private int red_scale; -// private int green_scale; -// private int blue_scale; -// private int alpha_scale; + private int red_offset; + private int green_offset; + private int blue_offset; + private int alpha_offset; + private int red_scale; + private int green_scale; + private int blue_scale; + private int alpha_scale; private boolean is_LinearRGB; private int lRGBprecision; private byte[] tosRGB8LUT; @@ -186,7 +186,7 @@ public DirectColorModel(int bits, int rmask, int gmask, bits, rmask, gmask, bmask, amask, false, amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT, ColorModel.getDefaultTransferType(bits)); - // SwingJS setFields(); + setFields(); } /** @@ -511,10 +511,10 @@ public int getRed(Object inData) { byte bdata[] = (byte[])inData; pixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])inData; -// pixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])inData; pixel = idata[0]; @@ -565,10 +565,10 @@ public int getGreen(Object inData) { byte bdata[] = (byte[])inData; pixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])inData; -// pixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])inData; pixel = idata[0]; @@ -619,10 +619,10 @@ public int getBlue(Object inData) { byte bdata[] = (byte[])inData; pixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])inData; -// pixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])inData; pixel = idata[0]; @@ -670,10 +670,10 @@ public int getAlpha(Object inData) { byte bdata[] = (byte[])inData; pixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])inData; -// pixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])inData; pixel = idata[0]; @@ -719,10 +719,10 @@ public int getRGB(Object inData) { byte bdata[] = (byte[])inData; pixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])inData; -// pixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])inData; + pixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])inData; pixel = idata[0]; @@ -899,16 +899,16 @@ public Object getDataElements(int rgb, Object pixel) { bdata[0] = (byte)(0xff&intpixel[0]); return bdata; } -// case DataBuffer.TYPE_USHORT:{ -// short sdata[]; -// if (pixel == null) { -// sdata = new short[1]; -// } else { -// sdata = (short[])pixel; -// } -// sdata[0] = (short)(intpixel[0]&0xffff); -// return sdata; -// } + case DataBuffer.TYPE_USHORT:{ + short sdata[]; + if (pixel == null) { + sdata = new short[1]; + } else { + sdata = (short[])pixel; + } + sdata[0] = (short)(intpixel[0]&0xffff); + return sdata; + } case DataBuffer.TYPE_INT: return intpixel; } @@ -998,10 +998,10 @@ final public int[] getComponents(Object pixel, int[] components, byte bdata[] = (byte[])pixel; intpixel = bdata[0] & 0xff; break; -// case DataBuffer.TYPE_USHORT: -// short sdata[] = (short[])pixel; -// intpixel = sdata[0] & 0xffff; -// break; + case DataBuffer.TYPE_USHORT: + short sdata[] = (short[])pixel; + intpixel = sdata[0] & 0xffff; + break; case DataBuffer.TYPE_INT: int idata[] = (int[])pixel; intpixel = idata[0]; @@ -1045,14 +1045,14 @@ final public WritableRaster createCompatibleWritableRaster (int w, bandmasks[1] = green_mask; bandmasks[2] = blue_mask; - if (pixel_bits > 8) {// SwingJS 16) { + if (pixel_bits > 16) { return Raster.createPackedRaster(DataBuffer.TYPE_INT, w,h,bandmasks,null); } -// else if (pixel_bits > 8) { -// return Raster.createPackedRaster(DataBuffer.TYPE_USHORT, -// w,h,bandmasks,null); -// } + else if (pixel_bits > 8) { + return Raster.createPackedRaster(DataBuffer.TYPE_USHORT, + w,h,bandmasks,null); + } else { return Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w,h,bandmasks,null); @@ -1144,15 +1144,15 @@ public Object getDataElements(int[] components, int offset, Object obj) { byte bdata[] = {(byte)(pixel&0xff)}; return bdata; } -// case DataBuffer.TYPE_USHORT: -// if (obj instanceof short[]) { -// short sdata[] = (short[])obj; -// sdata[0] = (short)(pixel&0xffff); -// return sdata; -// } else { -// short sdata[] = {(short)(pixel&0xffff)}; -// return sdata; -// } + case DataBuffer.TYPE_USHORT: + if (obj instanceof short[]) { + short sdata[] = (short[])obj; + sdata[0] = (short)(pixel&0xffff); + return sdata; + } else { + short sdata[] = {(short)(pixel&0xffff)}; + return sdata; + } case DataBuffer.TYPE_INT: if (obj instanceof int[]) { int idata[] = (int[])obj; @@ -1168,256 +1168,256 @@ public Object getDataElements(int[] components, int offset, Object obj) { } } -// /** -// * Forces the raster data to match the state specified in the -// *isAlphaPremultiplied
variable, assuming the data is -// * currently correctly described by thisColorModel
. It -// * may multiply or divide the color raster data by alpha, or do -// * nothing if the data is in the correct state. If the data needs to -// * be coerced, this method will also return an instance of this -// *ColorModel
with theisAlphaPremultiplied
-// * flag set appropriately. This method will throw a -// *UnsupportedOperationException
if this transferType is -// * not supported by thisColorModel
. Since -// *ColorModel
can be subclassed, subclasses inherit the -// * implementation of this method and if they don't override it then -// * they throw an exception if they use an unsupported transferType. -// * -// * @param raster theWritableRaster
data -// * @param isAlphaPremultipliedtrue
if the alpha is -// * premultiplied;false
otherwise -// * @return aColorModel
object that represents the -// * coerced data. -// * @exception UnsupportedOperationException if this -// *transferType
is not supported by this -// * color model -// */ -// final public ColorModel coerceData (WritableRaster raster, -// boolean isAlphaPremultiplied) -// { -// if (!supportsAlpha || -// this.isAlphaPremultiplied() == isAlphaPremultiplied) { -// return this; -// } -// -// int w = raster.getWidth(); -// int h = raster.getHeight(); -// int aIdx = numColorComponents; -// float normAlpha; -// float alphaScale = 1.0f / ((float) ((1 << nBits[aIdx]) - 1)); -// -// int rminX = raster.getMinX(); -// int rY = raster.getMinY(); -// int rX; -// int pixel[] = null; -// int zpixel[] = null; -// -// if (isAlphaPremultiplied) { -// // Must mean that we are currently not premultiplied so -// // multiply by alpha -// switch (transferType) { -// case DataBuffer.TYPE_BYTE: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0.f) { -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * normAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } else { -// if (zpixel == null) { -// zpixel = new int[numComponents]; -// java.util.Arrays.fill(zpixel, 0); -// } -// raster.setPixel(rX, rY, zpixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_USHORT: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0.f) { -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * normAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } else { -// if (zpixel == null) { -// zpixel = new int[numComponents]; -// java.util.Arrays.fill(zpixel, 0); -// } -// raster.setPixel(rX, rY, zpixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_INT: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0.f) { -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * normAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } else { -// if (zpixel == null) { -// zpixel = new int[numComponents]; -// java.util.Arrays.fill(zpixel, 0); -// } -// raster.setPixel(rX, rY, zpixel); -// } -// } -// } -// } -// break; -// default: -// throw new UnsupportedOperationException("This method has not been "+ -// "implemented for transferType " + transferType); -// } -// } -// else { -// // We are premultiplied and want to divide it out -// switch (transferType) { -// case DataBuffer.TYPE_BYTE: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0.0f) { -// float invAlpha = 1.0f / normAlpha; -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * invAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_USHORT: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0) { -// float invAlpha = 1.0f / normAlpha; -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * invAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } -// } -// } -// } -// break; -// case DataBuffer.TYPE_INT: { -// for (int y = 0; y < h; y++, rY++) { -// rX = rminX; -// for (int x = 0; x < w; x++, rX++) { -// pixel = raster.getPixel(rX, rY, pixel); -// normAlpha = pixel[aIdx] * alphaScale; -// if (normAlpha != 0) { -// float invAlpha = 1.0f / normAlpha; -// for (int c=0; c < aIdx; c++) { -// pixel[c] = (int) (pixel[c] * invAlpha + -// 0.5f); -// } -// raster.setPixel(rX, rY, pixel); -// } -// } -// } -// } -// break; -// default: -// throw new UnsupportedOperationException("This method has not been "+ -// "implemented for transferType " + transferType); -// } -// } -// -// // Return a new color model -// return new DirectColorModel(colorSpace, pixel_bits, maskArray[0], -// maskArray[1], maskArray[2], maskArray[3], -// isAlphaPremultiplied, -// transferType); -// -// } + /** + * Forces the raster data to match the state specified in the + *isAlphaPremultiplied
variable, assuming the data is + * currently correctly described by thisColorModel
. It + * may multiply or divide the color raster data by alpha, or do + * nothing if the data is in the correct state. If the data needs to + * be coerced, this method will also return an instance of this + *ColorModel
with theisAlphaPremultiplied
+ * flag set appropriately. This method will throw a + *UnsupportedOperationException
if this transferType is + * not supported by thisColorModel
. Since + *ColorModel
can be subclassed, subclasses inherit the + * implementation of this method and if they don't override it then + * they throw an exception if they use an unsupported transferType. + * + * @param raster theWritableRaster
data + * @param isAlphaPremultipliedtrue
if the alpha is + * premultiplied;false
otherwise + * @return aColorModel
object that represents the + * coerced data. + * @exception UnsupportedOperationException if this + *transferType
is not supported by this + * color model + */ + final public ColorModel coerceData (WritableRaster raster, + boolean isAlphaPremultiplied) + { + if (!supportsAlpha || + this.isAlphaPremultiplied() == isAlphaPremultiplied) { + return this; + } -// /** -// * Returnstrue
ifraster
is compatible -// * with thisColorModel
andfalse
if it is -// * not. -// * @param raster the {@link Raster} object to test for compatibility -// * @returntrue
ifraster
is compatible -// * with thisColorModel
;false
otherwise. -// */ -// public boolean isCompatibleRaster(Raster raster) { -// SampleModel sm = raster.getSampleModel(); -// SinglePixelPackedSampleModel spsm; -// if (sm instanceof SinglePixelPackedSampleModel) { -// spsm = (SinglePixelPackedSampleModel) sm; -// } -// else { -// return false; -// } -// if (spsm.getNumBands() != getNumComponents()) { -// return false; -// } -// -// int[] bitMasks = spsm.getBitMasks(); -// for (int i=0; itrue if raster
is compatible + * with thisColorModel
andfalse
if it is + * not. + * @param raster the {@link Raster} object to test for compatibility + * @returntrue
ifraster
is compatible + * with thisColorModel
;false
otherwise. + */ + public boolean isCompatibleRaster(Raster raster) { + SampleModel sm = raster.getSampleModel(); + SinglePixelPackedSampleModel spsm; + if (sm instanceof SinglePixelPackedSampleModel) { + spsm = (SinglePixelPackedSampleModel) sm; + } + else { + return false; + } + if (spsm.getNumBands() != getNumComponents()) { + return false; + } + + int[] bitMasks = spsm.getBitMasks(); + for (int i=0; iString that represents this diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/IndexColorModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/IndexColorModel.java index eeddfc3ba..7a87c4e8b 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/IndexColorModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/IndexColorModel.java @@ -31,6 +31,7 @@ import java.awt.Transparency; import java.awt.color.ColorSpace; //import java.math.BigInteger; +import java.math.BigInteger; /** * The IndexColorModel
class is aColorModel
@@ -130,7 +131,7 @@ public class IndexColorModel extends ColorModel { private int pixel_mask; private int transparent_index = -1; private boolean allgrayopaque; -// private BigInteger validBits; + private BigInteger validBits; // private sun.awt.image.BufImgSurfaceData .ICMColorData colorData = null; @@ -433,79 +434,79 @@ public IndexColorModel(int bits, int size, calculatePixelMask(); } -// /** -// * Constructs anIndexColorModel
from an -// *int
array where eachint
is -// * comprised of red, green, blue, and alpha -// * components in the default RGB color model format. -// * The array must have enough values in it to fill all -// * of the needed component arrays of the specified size. -// * TheColorSpace
is the default sRGB space. -// * The transparency value may be any ofTransparency.OPAQUE
, -// *Transparency.BITMASK
, -// * orTransparency.TRANSLUCENT
-// * depending on the arguments, as specified -// * in the class description above. -// * The transfer type must be one ofDataBuffer.TYPE_BYTE
-// *DataBuffer.TYPE_USHORT
. -// * TheBigInteger
object specifies the valid/invalid pixels -// * in thecmap
array. A pixel is valid if the -// *BigInteger
value at that index is set, and is invalid -// * if theBigInteger
bit at that index is not set. -// * @param bits the number of bits each pixel occupies -// * @param size the size of the color component array -// * @param cmap the array of color components -// * @param start the starting offset of the first color component -// * @param transferType the specified data type -// * @param validBits aBigInteger
object. If a bit is -// * set in the BigInteger, the pixel at that index is valid. -// * If a bit is not set, the pixel at that index -// * is considered invalid. If null, all pixels are valid. -// * Only bits from 0 to the map size are considered. -// * @throws IllegalArgumentException ifbits
is less -// * than 1 or greater than 16 -// * @throws IllegalArgumentException ifsize
is less -// * than 1 -// * @throws IllegalArgumentException iftransferType
is not -// * one ofDataBuffer.TYPE_BYTE
or -// *DataBuffer.TYPE_USHORT
-// * -// * @since 1.3 -// */ -// public IndexColorModel(int bits, int size, int cmap[], int start, -// int transferType, BigInteger validBits) { -// super (bits, alphaBits, -// ColorSpace.getInstance(ColorSpace.CS_sRGB), -// true, false, TRANSLUCENT, -// transferType); -// -// if (bits < 1 || bits > 16) { -// throw new IllegalArgumentException("Number of bits must be between" -// +" 1 and 16."); -// } -// if (size < 1) { -// throw new IllegalArgumentException("Map size ("+size+ -// ") must be >= 1"); -// } -// if ((transferType != DataBuffer.TYPE_BYTE) && -// (transferType != DataBuffer.TYPE_USHORT)) { -// throw new IllegalArgumentException("transferType must be either" + -// "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); -// } -// -// if (validBits != null) { -// // Check to see if it is all valid -// for (int i=0; i < size; i++) { -// if (!validBits.testBit(i)) { -// this.validBits = validBits; -// break; -// } -// } -// } -// -// setRGBs(size, cmap, start, true); -// calculatePixelMask(); -// } + /** + * Constructs anIndexColorModel
from an + *int
array where eachint
is + * comprised of red, green, blue, and alpha + * components in the default RGB color model format. + * The array must have enough values in it to fill all + * of the needed component arrays of the specified size. + * TheColorSpace
is the default sRGB space. + * The transparency value may be any ofTransparency.OPAQUE
, + *Transparency.BITMASK
, + * orTransparency.TRANSLUCENT
+ * depending on the arguments, as specified + * in the class description above. + * The transfer type must be one ofDataBuffer.TYPE_BYTE
+ *DataBuffer.TYPE_USHORT
. + * TheBigInteger
object specifies the valid/invalid pixels + * in thecmap
array. A pixel is valid if the + *BigInteger
value at that index is set, and is invalid + * if theBigInteger
bit at that index is not set. + * @param bits the number of bits each pixel occupies + * @param size the size of the color component array + * @param cmap the array of color components + * @param start the starting offset of the first color component + * @param transferType the specified data type + * @param validBits aBigInteger
object. If a bit is + * set in the BigInteger, the pixel at that index is valid. + * If a bit is not set, the pixel at that index + * is considered invalid. If null, all pixels are valid. + * Only bits from 0 to the map size are considered. + * @throws IllegalArgumentException ifbits
is less + * than 1 or greater than 16 + * @throws IllegalArgumentException ifsize
is less + * than 1 + * @throws IllegalArgumentException iftransferType
is not + * one ofDataBuffer.TYPE_BYTE
or + *DataBuffer.TYPE_USHORT
+ * + * @since 1.3 + */ + public IndexColorModel(int bits, int size, int cmap[], int start, + int transferType, BigInteger validBits) { + super (bits, alphaBits, + ColorSpace.getInstance(ColorSpace.CS_sRGB), + true, false, TRANSLUCENT, + transferType); + + if (bits < 1 || bits > 16) { + throw new IllegalArgumentException("Number of bits must be between" + +" 1 and 16."); + } + if (size < 1) { + throw new IllegalArgumentException("Map size ("+size+ + ") must be >= 1"); + } + if ((transferType != DataBuffer.TYPE_BYTE) && + (transferType != DataBuffer.TYPE_USHORT)) { + throw new IllegalArgumentException("transferType must be either" + + "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); + } + + if (validBits != null) { + // Check to see if it is all valid + for (int i=0; i < size; i++) { + if (!validBits.testBit(i)) { + this.validBits = validBits; + break; + } + } + } + + setRGBs(size, cmap, start, true); + calculatePixelMask(); + } private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) { if (size < 1) { @@ -550,11 +551,11 @@ private void setRGBs(int size, int cmap[], int start, boolean hasalpha) { int j = start; int transparency = OPAQUE; boolean allgray = true; -// BigInteger validBits = this.validBits; + BigInteger validBits = this.validBits; for (int i = 0; i < size; i++, j++) { -// if (validBits != null && !validBits.testBit(i)) { -// continue; -// } + if (validBits != null && !validBits.testBit(i)) { + continue; + } int cmaprgb = cmap[j]; int r = (cmaprgb >> 16) & 0xff; int g = (cmaprgb >> 8) & 0xff; @@ -589,15 +590,15 @@ private int calcRealMapSize(int bits, int size) { return Math.max(newSize, 256); } -// private BigInteger getAllValid() { -// int numbytes = (map_size+7)/8; -// byte[] valid = new byte[numbytes]; -// java.util.Arrays.fill(valid, (byte)0xff); -// valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); -// -// return new BigInteger(1, valid); -// } -// + private BigInteger getAllValid() { + int numbytes = (map_size+7)/8; + byte[] valid = new byte[numbytes]; + java.util.Arrays.fill(valid, (byte)0xff); + valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); + + return new BigInteger(1, valid); + } + /** * Returns the transparency. Returns either OPAQUE, BITMASK, * or TRANSLUCENT @@ -1318,14 +1319,14 @@ public WritableRaster createCompatibleWritableRaster(int w, int h) { raster = Raster.createPackedRaster(DataBuffer.TYPE_BYTE, w, h, 1, pixel_bits, null); } -// else if (pixel_bits <= 8) { -// raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, -// w,h,1,null); -// } -// else if (pixel_bits <= 16) { -// raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, -// w,h,1,null); -// } + else if (pixel_bits <= 8) { + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + w,h,1,null); + } + else if (pixel_bits <= 16) { + raster = Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, + w,h,1,null); + } else { throw new UnsupportedOperationException("This method is not supported "+ @@ -1494,25 +1495,25 @@ public boolean isValid() { return true;//(validBits == null); } -// /** -// * Returns aBigInteger
that indicates the valid/invalid -// * pixels in the colormap. A bit is valid if the -// *BigInteger
value at that index is set, and is invalid -// * if theBigInteger
value at that index is not set. -// * The only valid ranges to query in theBigInteger
are -// * between 0 and the map size. -// * @return aBigInteger
indicating the valid/invalid pixels. -// * @since 1.3 -// */ -// public BigInteger getValidPixels() { -// if (validBits == null) { -// return getAllValid(); -// } -// else { -// return validBits; -// } -// } -// + /** + * Returns aBigInteger
that indicates the valid/invalid + * pixels in the colormap. A bit is valid if the + *BigInteger
value at that index is set, and is invalid + * if theBigInteger
value at that index is not set. + * The only valid ranges to query in theBigInteger
are + * between 0 and the map size. + * @return aBigInteger
indicating the valid/invalid pixels. + * @since 1.3 + */ + public BigInteger getValidPixels() { + if (validBits == null) { + return getAllValid(); + } + else { + return validBits; + } + } + /** * Disposes of system resources associated with this *ColorModel
once thisColorModel
is no diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/LookupOp.java b/sources/net.sf.j2s.java.core/src/java/awt/image/LookupOp.java index 2a2018e8b..8f21ae777 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/LookupOp.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/LookupOp.java @@ -30,6 +30,7 @@ package java.awt.image; import java.awt.RenderingHints; +import java.awt.Transparency; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import sun.awt.image.ImagingLib; @@ -304,10 +305,10 @@ public final WritableRaster filter (Raster src, WritableRaster dst) { byteFilter ((ByteLookupTable) ltable, src, dst, width, height, numBands); } -// else if (ltable instanceof ShortLookupTable) { -// shortFilter ((ShortLookupTable) ltable, src, dst, width, -// height, numBands); -// } + else if (ltable instanceof ShortLookupTable) { + shortFilter ((ShortLookupTable) ltable, src, dst, width, + height, numBands); + } else { // Not one we recognize so do it slowly int sminX = src.getMinX(); @@ -373,60 +374,59 @@ public BufferedImage createCompatibleDestImage (BufferedImage src, BufferedImage image; int w = src.getWidth(); int h = src.getHeight(); -// int transferType = DataBuffer.TYPE_BYTE; + int transferType = DataBuffer.TYPE_BYTE; if (destCM == null) { ColorModel cm = src.getColorModel(); -// Raster raster = src.getRaster(); -// SwingJS not supported -// if (cm instanceof ComponentColorModel) { -// DataBuffer db = raster.getDataBuffer(); -// boolean hasAlpha = cm.hasAlpha(); -// boolean isPre = cm.isAlphaPremultiplied(); -// int trans = cm.getTransparency(); -// int[] nbits = null; -// if (ltable instanceof ByteLookupTable) { -// if (db.getDataType() == db.TYPE_USHORT) { -// // Dst raster should be of type byte -// if (hasAlpha) { -// nbits = new int[2]; -// if (trans == cm.BITMASK) { -// nbits[1] = 1; -// } -// else { -// nbits[1] = 8; -// } -// } -// else { -// nbits = new int[1]; -// } -// nbits[0] = 8; -// } -// // For byte, no need to change the cm -// } -// else if (ltable instanceof ShortLookupTable) { -// transferType = DataBuffer.TYPE_USHORT; -// if (db.getDataType() == db.TYPE_BYTE) { -// if (hasAlpha) { -// nbits = new int[2]; -// if (trans == cm.BITMASK) { -// nbits[1] = 1; -// } -// else { -// nbits[1] = 16; -// } -// } -// else { -// nbits = new int[1]; -// } -// nbits[0] = 16; -// } -// } -// if (nbits != null) { -// cm = new ComponentColorModel(cm.getColorSpace(), -// nbits, hasAlpha, isPre, -// trans, transferType); -// } -// } + Raster raster = src.getRaster(); + if (cm instanceof ComponentColorModel) { + DataBuffer db = raster.getDataBuffer(); + boolean hasAlpha = cm.hasAlpha(); + boolean isPre = cm.isAlphaPremultiplied(); + int trans = cm.getTransparency(); + int[] nbits = null; + if (ltable instanceof ByteLookupTable) { + if (db.getDataType() == DataBuffer.TYPE_USHORT) { + // Dst raster should be of type byte + if (hasAlpha) { + nbits = new int[2]; + if (trans == Transparency.BITMASK) { + nbits[1] = 1; + } + else { + nbits[1] = 8; + } + } + else { + nbits = new int[1]; + } + nbits[0] = 8; + } + // For byte, no need to change the cm + } + else if (ltable instanceof ShortLookupTable) { + transferType = DataBuffer.TYPE_USHORT; + if (db.getDataType() == DataBuffer.TYPE_BYTE) { + if (hasAlpha) { + nbits = new int[2]; + if (trans == Transparency.BITMASK) { + nbits[1] = 1; + } + else { + nbits[1] = 16; + } + } + else { + nbits = new int[1]; + } + nbits[0] = 16; + } + } + if (nbits != null) { + cm = new ComponentColorModel(cm.getColorSpace(), + nbits, hasAlpha, isPre, + trans, transferType); + } + } image = new BufferedImage(cm, cm.createCompatibleWritableRaster(w, h), cm.isAlphaPremultiplied(), @@ -534,49 +534,49 @@ private final void byteFilter(ByteLookupTable lookup, Raster src, } } -// private final void shortFilter(ShortLookupTable lookup, Raster src, -// WritableRaster dst, -// int width, int height, int numBands) { -// int band; -// int[] srcPix = null; -// -// // Find the ref to the table and the offset -// short[][] table = lookup.getTable(); -// int offset = lookup.getOffset(); -// int tidx; -// int step=1; -// -// // Check if it is one lookup applied to all bands -// if (table.length == 1) { -// step=0; -// } -// -// int x = 0; -// int y = 0; -// int index; -// int maxShort = (1<<16)-1; -// // Loop through the data -// for (y=0; y < height; y++) { -// tidx = 0; -// for ( band=0; band < numBands; band++, tidx+=step) { -// // Find data for this band, scanline -// srcPix = src.getSamples(0, y, width, 1, band, srcPix); -// -// for ( x=0; x < width; x++) { -// index = srcPix[x]-offset; -// if (index < 0 || index > maxShort) { -// throw new -// IllegalArgumentException("index out of range "+ -// index+" x is "+x+ -// "srcPix[x]="+srcPix[x] -// +" offset="+ offset); -// } -// // Do the lookup -// srcPix[x] = table[tidx][index]; -// } -// // Put it back -// dst.setSamples(0, y, width, 1, band, srcPix); -// } -// } -// } + private final void shortFilter(ShortLookupTable lookup, Raster src, + WritableRaster dst, + int width, int height, int numBands) { + int band; + int[] srcPix = null; + + // Find the ref to the table and the offset + short[][] table = lookup.getTable(); + int offset = lookup.getOffset(); + int tidx; + int step=1; + + // Check if it is one lookup applied to all bands + if (table.length == 1) { + step=0; + } + + int x = 0; + int y = 0; + int index; + int maxShort = (1<<16)-1; + // Loop through the data + for (y=0; y < height; y++) { + tidx = 0; + for ( band=0; band < numBands; band++, tidx+=step) { + // Find data for this band, scanline + srcPix = src.getSamples(0, y, width, 1, band, srcPix); + + for ( x=0; x < width; x++) { + index = srcPix[x]-offset; + if (index < 0 || index > maxShort) { + throw new + IllegalArgumentException("index out of range "+ + index+" x is "+x+ + "srcPix[x]="+srcPix[x] + +" offset="+ offset); + } + // Do the lookup + srcPix[x] = table[tidx][index]; + } + // Put it back + dst.setSamples(0, y, width, 1, band, srcPix); + } + } + } } diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/MemoryImageSource.java b/sources/net.sf.j2s.java.core/src/java/awt/image/MemoryImageSource.java index 9f0f70501..6e33c3ad6 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/MemoryImageSource.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/MemoryImageSource.java @@ -28,15 +28,10 @@ package java.awt.image; -import java.awt.image.ImageConsumer; -import java.awt.image.ImageProducer; -import java.awt.Graphics; -import java.awt.image.ColorModel; +import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; -import java.util.Enumeration; -import javajs.util.AU; import swingjs.JSGraphics2D; /** @@ -111,7 +106,6 @@ * @author Animation capabilities inspired by the * MemoryAnimationSource class written by Garth Dickie */ -@SuppressWarnings({"rawtypes", "unchecked"}) public class MemoryImageSource implements ImageProducer { int width; int height; @@ -461,7 +455,7 @@ public synchronized void newPixels(int x, int y, int w, int h) { * @see #setAnimated * @see #setFullBufferUpdates */ - @SuppressWarnings({ "unused", "null" }) + @SuppressWarnings({ "unused" }) public synchronized void newPixels(int x, int y, int w, int h, boolean framenotify) { diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/MultiPixelPackedSampleModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/MultiPixelPackedSampleModel.java index 5a0a01447..4aec1b5cf 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/MultiPixelPackedSampleModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/MultiPixelPackedSampleModel.java @@ -113,7 +113,7 @@ public MultiPixelPackedSampleModel(int dataType, DataBuffer.getDataTypeSize(dataType), 0); if (dataType != DataBuffer.TYPE_BYTE && -// dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_USHORT && dataType != DataBuffer.TYPE_INT) { throw new IllegalArgumentException("Unsupported data type "+ dataType); @@ -149,7 +149,7 @@ public MultiPixelPackedSampleModel(int dataType, int w, int h, int dataBitOffset) { super(dataType, w, h, 1); if (dataType != DataBuffer.TYPE_BYTE && -// dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_USHORT && dataType != DataBuffer.TYPE_INT) { throw new IllegalArgumentException("Unsupported data type "+ dataType); @@ -208,9 +208,9 @@ public DataBuffer createDataBuffer() { case DataBuffer.TYPE_BYTE: dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8); break; -// case DataBuffer.TYPE_USHORT: -// dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16); -// break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16); + break; case DataBuffer.TYPE_INT: dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32); break; @@ -312,13 +312,12 @@ public int getDataBitOffset() { */ @Override public int getTransferType() { -// SwingJS - everything is done in ints here -// if (pixelBitStride > 16) + if (pixelBitStride > 16) return DataBuffer.TYPE_INT; -// else if (pixelBitStride > 8) -// return DataBuffer.TYPE_USHORT; -// else -// return DataBuffer.TYPE_BYTE; + else if (pixelBitStride > 8) + return DataBuffer.TYPE_USHORT; + else + return DataBuffer.TYPE_BYTE; } /** @@ -493,22 +492,22 @@ public Object getDataElements(int x, int y, Object obj, DataBuffer data) { obj = (Object)bdata; break; -// case DataBuffer.TYPE_USHORT: -// -// short[] sdata; -// -// if (obj == null) -// sdata = new short[1]; -// else -// sdata = (short[])obj; -// -// element = data.getElem(y*scanlineStride + -// bitnum/dataElementSize); -// sdata[0] = (short)((element >> shift) & bitMask); -// -// obj = (Object)sdata; -// break; -// + case DataBuffer.TYPE_USHORT: + + short[] sdata; + + if (obj == null) + sdata = new short[1]; + else + sdata = (short[])obj; + + element = data.getElem(y*scanlineStride + + bitnum/dataElementSize); + sdata[0] = (short)((element >> shift) & bitMask); + + obj = (Object)sdata; + break; + case DataBuffer.TYPE_INT: int[] idata; @@ -628,13 +627,13 @@ public void setDataElements(int x, int y, Object obj, DataBuffer data) { data.setElem(index, element); break; -// case DataBuffer.TYPE_USHORT: -// -// short[] sarray = (short[])obj; -// element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift; -// data.setElem(index, element); -// break; -// + case DataBuffer.TYPE_USHORT: + + short[] sarray = (short[])obj; + element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift; + data.setElem(index, element); + break; + case DataBuffer.TYPE_INT: int[] iarray = (int[])obj; diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/Raster.java b/sources/net.sf.j2s.java.core/src/java/awt/image/Raster.java index 4ae4868df..3072cc4e1 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/Raster.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/Raster.java @@ -412,10 +412,10 @@ public static WritableRaster createBandedRaster(int dataType, d = new DataBufferByte(size, banks); break; -// case DataBuffer.TYPE_USHORT: -// d = new DataBufferUShort(size, banks); -// break; -// + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort(size, banks); + break; + case DataBuffer.TYPE_INT: d = new DataBufferInt(size, banks); break; @@ -470,10 +470,10 @@ public static WritableRaster createPackedRaster(int dataType, d = new DataBufferByte(w*h); break; -// case DataBuffer.TYPE_USHORT: -// d = new DataBufferUShort(w*h); -// break; -// + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort(w*h); + break; + case DataBuffer.TYPE_INT: d = new DataBufferInt(w*h); break; @@ -561,7 +561,7 @@ public static WritableRaster createPackedRaster(int dataType, } switch(dataType) { case DataBuffer.TYPE_BYTE: -// case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_INT: break; default: @@ -583,10 +583,10 @@ public static WritableRaster createPackedRaster(int dataType, d = new DataBufferByte((int)(Math.ceil(fw/(8/bitsPerBand)))*h); break; -// case DataBuffer.TYPE_USHORT: -// d = new DataBufferUShort((int)(Math.ceil(fw/(16/bitsPerBand)))*h); -// break; -// + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort((int)(Math.ceil(fw/(16/bitsPerBand)))*h); + break; + case DataBuffer.TYPE_INT: d = new DataBufferInt((int)(Math.ceil(fw/(32/bitsPerBand)))*h); break; @@ -660,8 +660,7 @@ public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer, case DataBuffer.TYPE_USHORT: JSUtil.notImplemented("USHORT-interleaved raster"); - return null; -// return new ShortInterleavedRaster(csm, dataBuffer, location); + return new ShortInterleavedRaster(csm, dataBuffer, location); default: throw new IllegalArgumentException("Unsupported data type " + @@ -953,75 +952,75 @@ public static WritableRaster createWritableRaster(SampleModel sm, return createWritableRaster(sm, sm.createDataBuffer(), location); } - /** - * Creates a WritableRaster with the specified SampleModel and DataBuffer. - * The upper left corner of the Raster is given by the location argument. - * If location is null, (0, 0) will be used. - * @param sm the specifiedSampleModel
- * @param db the specifiedDataBuffer
- * @param location the upper-left corner of the - *WritableRaster
- * @return aWritableRaster
with the specified - *SampleModel
,DataBuffer
, and - * location. - * @throws RasterFormatException if computing either - *location.x + sm.getWidth()
or - *location.y + sm.getHeight()
results in integer - * overflow - * @throws RasterFormatException ifdb
has more - * than one bank andsm
is a - * PixelInterleavedSampleModel, SinglePixelPackedSampleModel, - * or MultiPixelPackedSampleModel. - * @throws NullPointerException if either SampleModel or DataBuffer is null - */ - public static WritableRaster createWritableRaster(SampleModel sm, - DataBuffer db, - Point location) { - if ((sm == null) || (db == null)) { - throw new NullPointerException("SampleModel and DataBuffer cannot be null"); - } - if (location == null) { - location = new Point(0,0); - } - - int dataType = sm.getDataType(); - - if (dataType == DataBuffer.TYPE_INT) { // SwingJS - SunWritableRaster r = new SunWritableRaster(sm,db,location); - r.秘pix = SunWritableRaster.stealData((DataBufferInt) db, 0); - return r; - } - - if (sm instanceof PixelInterleavedSampleModel) { - switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); - - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); - } - } else if (sm instanceof SinglePixelPackedSampleModel) { - switch(dataType) { - case DataBuffer.TYPE_BYTE: - return new ByteInterleavedRaster(sm, db, location); - - case DataBuffer.TYPE_USHORT: - return new ShortInterleavedRaster(sm, db, location); - - case DataBuffer.TYPE_INT: - return new IntegerInterleavedRaster(sm, db, location); - } - } else - if (sm instanceof MultiPixelPackedSampleModel && - dataType == DataBuffer.TYPE_BYTE && - sm.getSampleSize(0) < 8) { - return new BytePackedRaster(sm, db, location); - } - - // we couldn't do anything special - do the generic thing + /** + * Creates a WritableRaster with the specified SampleModel and DataBuffer. The + * upper left corner of the Raster is given by the location argument. If + * location is null, (0, 0) will be used. + * + * @param sm the specifiedSampleModel
+ * @param db the specifiedDataBuffer
+ * @param location the upper-left corner of theWritableRaster
+ * @return aWritableRaster
with the specified + *SampleModel
,DataBuffer
, and location. + * @throws RasterFormatException if computing either + *location.x + sm.getWidth()
or + *location.y + sm.getHeight()
+ * results in integer overflow + * @throws RasterFormatException ifdb
has more than one bank and + *sm
is a + * PixelInterleavedSampleModel, + * SinglePixelPackedSampleModel, or + * MultiPixelPackedSampleModel. + * @throws NullPointerException if either SampleModel or DataBuffer is null + */ + public static WritableRaster createWritableRaster(SampleModel sm, DataBuffer db, Point location) { + if ((sm == null) || (db == null)) { + throw new NullPointerException("SampleModel and DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0, 0); + } - return new BytePackedRaster(sm, db, location); - } + int dataType = sm.getDataType(); + + SunWritableRaster r = null; + + if (sm instanceof PixelInterleavedSampleModel) { + switch (dataType) { + case DataBuffer.TYPE_BYTE: + r = new ByteInterleavedRaster(sm, db, location); + break; + case DataBuffer.TYPE_USHORT: + r = new ShortInterleavedRaster(sm, db, location); + break; + } + } else if (sm instanceof SinglePixelPackedSampleModel) { + switch (dataType) { + case DataBuffer.TYPE_BYTE: + r = new ByteInterleavedRaster(sm, db, location); + break; + case DataBuffer.TYPE_USHORT: + r = new ShortInterleavedRaster(sm, db, location); + break; + case DataBuffer.TYPE_INT: + r = new IntegerInterleavedRaster(sm, db, location); + //r = new SunWritableRaster(sm, db, location); + // TODO -- THIS IS NOT GENERALLY RIGHT + r.秘pix = SunWritableRaster.stealData((DataBufferInt) db, 0); + break; + } + } else if (sm instanceof MultiPixelPackedSampleModel && dataType == DataBuffer.TYPE_BYTE + && sm.getSampleSize(0) < 8) { + r = new BytePackedRaster(sm, db, location); + } + + if (r == null) { + // we couldn't do anything special - do the generic thing + + r = new BytePackedRaster(sm, db, location); + } + return r; + } /** * Constructs a Raster with the given SampleModel. The Raster's diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/RescaleOp.java b/sources/net.sf.j2s.java.core/src/java/awt/image/RescaleOp.java index f225deda7..4ab7f0ae1 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/RescaleOp.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/RescaleOp.java @@ -268,7 +268,7 @@ private boolean canUseLookup(Raster src, Raster dst) { // int datatype = src.getDataBuffer().getDataType(); if(datatype != DataBuffer.TYPE_BYTE -// && datatype != DataBuffer.TYPE_USHORT + && datatype != DataBuffer.TYPE_USHORT ) { return false; } diff --git a/sources/net.sf.j2s.java.core/src/java/awt/image/SampleModel.java b/sources/net.sf.j2s.java.core/src/java/awt/image/SampleModel.java index 9eaee0d6d..ef14e41d3 100644 --- a/sources/net.sf.j2s.java.core/src/java/awt/image/SampleModel.java +++ b/sources/net.sf.j2s.java.core/src/java/awt/image/SampleModel.java @@ -84,6 +84,9 @@ public abstract class SampleModel { + + public int[] 秘pix; + /** Width in pixels of the region of image data that this SampleModel * describes. */ @@ -389,7 +392,7 @@ public Object getDataElements(int x, int y, int w, int h, obj = (Object)bdata; break; -// case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: short[] sdata; @@ -604,23 +607,23 @@ public void setDataElements(int x, int y, int w, int h, } break; -// case DataBuffer.TYPE_USHORT: -// case DataBuffer.TYPE_SHORT: -// -// short[] sarray = (short[])obj; -// short[] stemp = new short[numDataElems]; -// -// for (int i=y; i+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeans™ + * has been added to the java.beans
package. + * Please see {@link java.beans.XMLEncoder}. + * + * @author Scott Violet + */ + +public class FixedHeightLayoutCache extends AbstractLayoutCache { + /** Root node. */ + private FHTreeStateNode root; + + /** Number of rows currently visible. */ + private int rowCount; + + /** + * Used in getting sizes for nodes to avoid creating a new Rectangle + * every time a size is needed. + */ + private Rectangle boundsBuffer; + + /** + * Maps from TreePath to a FHTreeStateNode. + */ + private HashtabletreePathMapping; + + /** + * Used for getting path/row information. + */ + private SearchInfo info; + + private Stack > tempStacks; + + + public FixedHeightLayoutCache() { + super(); + tempStacks = new Stack >(); + boundsBuffer = new Rectangle(); + treePathMapping = new Hashtable (); + info = new SearchInfo(); + setRowHeight(1); + } + + /** + * Sets the TreeModel that will provide the data. + * + * @param newModel the TreeModel that is to provide the data + */ + public void setModel(TreeModel newModel) { + super.setModel(newModel); + rebuild(false); + } + + /** + * Determines whether or not the root node from + * the TreeModel is visible. + * + * @param rootVisible true if the root node of the tree is to be displayed + * @see #rootVisible + */ + public void setRootVisible(boolean rootVisible) { + if(isRootVisible() != rootVisible) { + super.setRootVisible(rootVisible); + if(root != null) { + if(rootVisible) { + rowCount++; + root.adjustRowBy(1); + } + else { + rowCount--; + root.adjustRowBy(-1); + } + visibleNodesChanged(); + } + } + } + + /** + * Sets the height of each cell. If rowHeight is less than or equal to + * 0 this will throw an IllegalArgumentException. + * + * @param rowHeight the height of each cell, in pixels + */ + public void setRowHeight(int rowHeight) { + if(rowHeight <= 0) + throw new IllegalArgumentException("FixedHeightLayoutCache only supports row heights greater than 0"); + if(getRowHeight() != rowHeight) { + super.setRowHeight(rowHeight); + visibleNodesChanged(); + } + } + + /** + * Returns the number of visible rows. + */ + public int getRowCount() { + return rowCount; + } + + /** + * Does nothing, FixedHeightLayoutCache doesn't cache width, and that + * is all that could change. + */ + public void invalidatePathBounds(TreePath path) { + } + + + /** + * Informs the TreeState that it needs to recalculate all the sizes + * it is referencing. + */ + public void invalidateSizes() { + // Nothing to do here, rowHeight still same, which is all + // this is interested in, visible region may have changed though. + visibleNodesChanged(); + } + + /** + * Returns true if the value identified by row is currently expanded. + */ + public boolean isExpanded(TreePath path) { + if(path != null) { + FHTreeStateNode lastNode = getNodeForPath(path, true, false); + + return (lastNode != null && lastNode.isExpanded()); + } + return false; + } + + /** + * Returns a rectangle giving the bounds needed to draw path. + * + * @param path a TreePath specifying a node + * @param placeIn a Rectangle object giving the available space + * @return a Rectangle object specifying the space to be used + */ + public Rectangle getBounds(TreePath path, Rectangle placeIn) { + if(path == null) + return null; + + FHTreeStateNode node = getNodeForPath(path, true, false); + + if(node != null) + return getBounds(node, -1, placeIn); + + // node hasn't been created yet. + TreePath parentPath = path.getParentPath(); + + node = getNodeForPath(parentPath, true, false); + if (node != null && node.isExpanded()) { + int childIndex = treeModel.getIndexOfChild + (parentPath.getLastPathComponent(), + path.getLastPathComponent()); + + if(childIndex != -1) + return getBounds(node, childIndex, placeIn); + } + return null; + } + + /** + * Returns the path for passed in row. If row is not visible + * null is returned. + */ + public TreePath getPathForRow(int row) { + if(row >= 0 && row < getRowCount()) { + if(root.getPathForRow(row, getRowCount(), info)) { + return info.getPath(); + } + } + return null; + } + + /** + * Returns the row that the last item identified in path is visible + * at. Will return -1 if any of the elements in path are not + * currently visible. + */ + public int getRowForPath(TreePath path) { + if(path == null || root == null) + return -1; + + FHTreeStateNode node = getNodeForPath(path, true, false); + + if(node != null) + return node.getRow(); + + TreePath parentPath = path.getParentPath(); + + node = getNodeForPath(parentPath, true, false); + if(node != null && node.isExpanded()) { + return node.getRowToModelIndex(treeModel.getIndexOfChild + (parentPath.getLastPathComponent(), + path.getLastPathComponent())); + } + return -1; + } + + /** + * Returns the path to the node that is closest to x,y. If + * there is nothing currently visible this will return null, otherwise + * it'll always return a valid path. If you need to test if the + * returned object is exactly at x, y you should get the bounds for + * the returned path and test x, y against that. + */ + public TreePath getPathClosestTo(int x, int y) { + if(getRowCount() == 0) + return null; + + int row = getRowContainingYLocation(y); + + return getPathForRow(row); + } + + /** + * Returns the number of visible children for row. + */ + public int getVisibleChildCount(TreePath path) { + FHTreeStateNode node = getNodeForPath(path, true, false); + + if(node == null) + return 0; + return node.getTotalChildCount(); + } + + /** + * Returns an Enumerator that increments over the visible paths + * starting at the passed in location. The ordering of the enumeration + * is based on how the paths are displayed. + */ + public Enumeration getVisiblePathsFrom(TreePath path) { + if(path == null) + return null; + + FHTreeStateNode node = getNodeForPath(path, true, false); + + if(node != null) { + return new VisibleFHTreeStateNodeEnumeration(node); + } + TreePath parentPath = path.getParentPath(); + + node = getNodeForPath(parentPath, true, false); + if(node != null && node.isExpanded()) { + return new VisibleFHTreeStateNodeEnumeration(node, + treeModel.getIndexOfChild(parentPath.getLastPathComponent(), + path.getLastPathComponent())); + } + return null; + } + + /** + * Marks the path path
expanded state to + *isExpanded
. + */ + public void setExpandedState(TreePath path, boolean isExpanded) { + if(isExpanded) + ensurePathIsExpanded(path, true); + else if(path != null) { + TreePath parentPath = path.getParentPath(); + + // YECK! Make the parent expanded. + if(parentPath != null) { + FHTreeStateNode parentNode = getNodeForPath(parentPath, + false, true); + if(parentNode != null) + parentNode.makeVisible(); + } + // And collapse the child. + FHTreeStateNode childNode = getNodeForPath(path, true, + false); + + if(childNode != null) + childNode.collapse(true); + } + } + + /** + * Returns true if the path is expanded, and visible. + */ + public boolean getExpandedState(TreePath path) { + FHTreeStateNode node = getNodeForPath(path, true, false); + + return (node != null) ? (node.isVisible() && node.isExpanded()) : + false; + } + + // + // TreeModelListener methods + // + + /** + *Invoked after a node (or a set of siblings) has changed in some + * way. The node(s) have not changed locations in the tree or + * altered their children arrays, but other attributes have + * changed and may affect presentation. Example: the name of a + * file has changed, but it is in the same location in the file + * system.
+ * + *e.path() returns the path the parent of the changed node(s).
+ * + *e.childIndices() returns the index(es) of the changed node(s).
+ */ + public void treeNodesChanged(TreeModelEvent e) { + if(e != null) { + int changedIndexs[]; + FHTreeStateNode changedParent = getNodeForPath + (SwingUtilities2.getTreePath(e, getModel()), false, false); + int maxCounter; + + changedIndexs = e.getChildIndices(); + /* Only need to update the children if the node has been + expanded once. */ + // PENDING(scott): make sure childIndexs is sorted! + if (changedParent != null) { + if (changedIndexs != null && + (maxCounter = changedIndexs.length) > 0) { + Object parentValue = changedParent.getUserObject(); + + for(int counter = 0; counter < maxCounter; counter++) { + FHTreeStateNode child = changedParent. + getChildAtModelIndex(changedIndexs[counter]); + + if(child != null) { + child.setUserObject(treeModel.getChild(parentValue, + changedIndexs[counter])); + } + } + if(changedParent.isVisible() && changedParent.isExpanded()) + visibleNodesChanged(); + } + // Null for root indicates it changed. + else if (changedParent == root && changedParent.isVisible() && + changedParent.isExpanded()) { + visibleNodesChanged(); + } + } + } + } + + /** + *Invoked after nodes have been inserted into the tree.
+ * + *e.path() returns the parent of the new nodes + *
e.childIndices() returns the indices of the new nodes in + * ascending order. + */ + public void treeNodesInserted(TreeModelEvent e) { + if(e != null) { + int changedIndexs[]; + FHTreeStateNode changedParent = getNodeForPath + (SwingUtilities2.getTreePath(e, getModel()), false, false); + int maxCounter; + + changedIndexs = e.getChildIndices(); + /* Only need to update the children if the node has been + expanded once. */ + // PENDING(scott): make sure childIndexs is sorted! + if(changedParent != null && changedIndexs != null && + (maxCounter = changedIndexs.length) > 0) { + boolean isVisible = + (changedParent.isVisible() && + changedParent.isExpanded()); + + for(int counter = 0; counter < maxCounter; counter++) { + changedParent.childInsertedAtModelIndex + (changedIndexs[counter], isVisible); + } + if(isVisible && treeSelectionModel != null) + treeSelectionModel.resetRowSelection(); + if(changedParent.isVisible()) + this.visibleNodesChanged(); + } + } + } + + /** + *
Invoked after nodes have been removed from the tree. Note that + * if a subtree is removed from the tree, this method may only be + * invoked once for the root of the removed subtree, not once for + * each individual set of siblings removed.
+ * + *e.path() returns the former parent of the deleted nodes.
+ * + *e.childIndices() returns the indices the nodes had before they were deleted in ascending order.
+ */ + public void treeNodesRemoved(TreeModelEvent e) { + if(e != null) { + int changedIndexs[]; + int maxCounter; + TreePath parentPath = SwingUtilities2.getTreePath(e, getModel()); + FHTreeStateNode changedParentNode = getNodeForPath + (parentPath, false, false); + + changedIndexs = e.getChildIndices(); + // PENDING(scott): make sure that changedIndexs are sorted in + // ascending order. + if(changedParentNode != null && changedIndexs != null && + (maxCounter = changedIndexs.length) > 0) { + Object[] children = e.getChildren(); + boolean isVisible = + (changedParentNode.isVisible() && + changedParentNode.isExpanded()); + + for(int counter = maxCounter - 1; counter >= 0; counter--) { + changedParentNode.removeChildAtModelIndex + (changedIndexs[counter], isVisible); + } + if(isVisible) { + if(treeSelectionModel != null) + treeSelectionModel.resetRowSelection(); + if (treeModel.getChildCount(changedParentNode. + getUserObject()) == 0 && + changedParentNode.isLeaf()) { + // Node has become a leaf, collapse it. + changedParentNode.collapse(false); + } + visibleNodesChanged(); + } + else if(changedParentNode.isVisible()) + visibleNodesChanged(); + } + } + } + + /** + *Invoked after the tree has drastically changed structure from a + * given node down. If the path returned by e.getPath() is of length + * one and the first element does not identify the current root node + * the first element should become the new root of the tree. + * + *
e.path() holds the path to the node.
+ *e.childIndices() returns null.
+ */ + public void treeStructureChanged(TreeModelEvent e) { + if(e != null) { + TreePath changedPath = SwingUtilities2.getTreePath(e, getModel()); + FHTreeStateNode changedNode = getNodeForPath + (changedPath, false, false); + + // Check if root has changed, either to a null root, or + // to an entirely new root. + if (changedNode == root || + (changedNode == null && + ((changedPath == null && treeModel != null && + treeModel.getRoot() == null) || + (changedPath != null && changedPath.getPathCount() <= 1)))) { + rebuild(true); + } + else if(changedNode != null) { + boolean wasExpanded, wasVisible; + FHTreeStateNode parent = (FHTreeStateNode) + changedNode.getParent(); + + wasExpanded = changedNode.isExpanded(); + wasVisible = changedNode.isVisible(); + + int index = parent.getIndex(changedNode); + changedNode.collapse(false); + parent.remove(index); + + if(wasVisible && wasExpanded) { + int row = changedNode.getRow(); + parent.resetChildrenRowsFrom(row, index, + changedNode.getChildIndex()); + changedNode = getNodeForPath(changedPath, false, true); + changedNode.expand(); + } + if(treeSelectionModel != null && wasVisible && wasExpanded) + treeSelectionModel.resetRowSelection(); + if(wasVisible) + this.visibleNodesChanged(); + } + } + } + + + // + // Local methods + // + + private void visibleNodesChanged() { + } + + /** + * Returns the bounds for the given node. IfchildIndex
+ * is -1, the bounds ofparent
are returned, otherwise + * the bounds of the node atchildIndex
are returned. + */ + private Rectangle getBounds(FHTreeStateNode parent, int childIndex, + Rectangle placeIn) { + boolean expanded; + int level; + int row; + Object value; + + if(childIndex == -1) { + // Getting bounds for parent + row = parent.getRow(); + value = parent.getUserObject(); + expanded = parent.isExpanded(); + level = parent.getLevel(); + } + else { + row = parent.getRowToModelIndex(childIndex); + value = treeModel.getChild(parent.getUserObject(), childIndex); + expanded = false; + level = parent.getLevel() + 1; + } + + Rectangle bounds = getNodeDimensions(value, row, level, + expanded, boundsBuffer); + // No node dimensions, bail. + if(bounds == null) + return null; + + if(placeIn == null) + placeIn = new Rectangle(); + + placeIn.x = bounds.x; + placeIn.height = getRowHeight(); + placeIn.y = row * placeIn.height; + placeIn.width = bounds.width; + return placeIn; + } + + /** + * Adjust the large row count of the AbstractTreeUI the receiver was + * created with. + */ + private void adjustRowCountBy(int changeAmount) { + rowCount += changeAmount; + } + + /** + * Adds a mapping for node. + */ + private void addMapping(FHTreeStateNode node) { + treePathMapping.put(node.getTreePath(), node); + } + + /** + * Removes the mapping for a previously added node. + */ + private void removeMapping(FHTreeStateNode node) { + treePathMapping.remove(node.getTreePath()); + } + + /** + * Returns the node previously added forpath
. This may + * return null, if you to create a node use getNodeForPath. + */ + private FHTreeStateNode getMapping(TreePath path) { + return treePathMapping.get(path); + } + + /** + * Sent to completely rebuild the visible tree. All nodes are collapsed. + */ + private void rebuild(boolean clearSelection) { + Object rootUO; + + treePathMapping.clear(); + if(treeModel != null && (rootUO = treeModel.getRoot()) != null) { + root = createNodeForValue(rootUO, 0); + root.path = new TreePath(rootUO); + addMapping(root); + if(isRootVisible()) { + rowCount = 1; + root.row = 0; + } + else { + rowCount = 0; + root.row = -1; + } + root.expand(); + } + else { + root = null; + rowCount = 0; + } + if(clearSelection && treeSelectionModel != null) { + treeSelectionModel.clearSelection(); + } + this.visibleNodesChanged(); + } + + /** + * Returns the index of the row containing location. If there + * are no rows, -1 is returned. If location is beyond the last + * row index, the last row index is returned. + */ + private int getRowContainingYLocation(int location) { + if(getRowCount() == 0) + return -1; + return Math.max(0, Math.min(getRowCount() - 1, + location / getRowHeight())); + } + + /** + * Ensures that all the path components in path are expanded, accept + * for the last component which will only be expanded if expandLast + * is true. + * Returns true if succesful in finding the path. + */ + private boolean ensurePathIsExpanded(TreePath aPath, + boolean expandLast) { + if(aPath != null) { + // Make sure the last entry isn't a leaf. + if(treeModel.isLeaf(aPath.getLastPathComponent())) { + aPath = aPath.getParentPath(); + expandLast = true; + } + if(aPath != null) { + FHTreeStateNode lastNode = getNodeForPath(aPath, false, + true); + + if(lastNode != null) { + lastNode.makeVisible(); + if(expandLast) + lastNode.expand(); + return true; + } + } + } + return false; + } + + /** + * Creates and returns an instance of FHTreeStateNode. + */ + private FHTreeStateNode createNodeForValue(Object value,int childIndex) { + return new FHTreeStateNode(value, childIndex, -1); + } + + /** + * Messages getTreeNodeForPage(path, onlyIfVisible, shouldCreate, + * path.length) as long as path is non-null and the length is {@literal >} 0. + * Otherwise returns null. + */ + private FHTreeStateNode getNodeForPath(TreePath path, + boolean onlyIfVisible, + boolean shouldCreate) { + if(path != null) { + FHTreeStateNode node; + + node = getMapping(path); + if(node != null) { + if(onlyIfVisible && !node.isVisible()) + return null; + return node; + } + if(onlyIfVisible) + return null; + + // Check all the parent paths, until a match is found. + Stackpaths; + + if(tempStacks.size() == 0) { + paths = new Stack (); + } + else { + paths = tempStacks.pop(); + } + + try { + paths.push(path); + path = path.getParentPath(); + node = null; + while(path != null) { + node = getMapping(path); + if(node != null) { + // Found a match, create entries for all paths in + // paths. + while(node != null && paths.size() > 0) { + path = paths.pop(); + node = node.createChildFor(path. + getLastPathComponent()); + } + return node; + } + paths.push(path); + path = path.getParentPath(); + } + } + finally { + paths.removeAllElements(); + tempStacks.push(paths); + } + // If we get here it means they share a different root! + return null; + } + return null; + } + + /** + * FHTreeStateNode is used to track what has been expanded. + * FHTreeStateNode differs from VariableHeightTreeState.TreeStateNode + * in that it is highly model intensive. That is almost all queries to a + * FHTreeStateNode result in the TreeModel being queried. And it + * obviously does not support variable sized row heights. + */ + private class FHTreeStateNode extends DefaultMutableTreeNode { + /** Is this node expanded? */ + protected boolean isExpanded; + + /** Index of this node from the model. */ + protected int childIndex; + + /** Child count of the receiver. */ + protected int childCount; + + /** Row of the receiver. This is only valid if the row is expanded. + */ + protected int row; + + /** Path of this node. */ + protected TreePath path; + + + public FHTreeStateNode(Object userObject, int childIndex, int row) { + super(userObject); + this.childIndex = childIndex; + this.row = row; + } + + // + // Overriden DefaultMutableTreeNode methods + // + + /** + * Messaged when this node is added somewhere, resets the path + * and adds a mapping from path to this node. + */ + public void setParent(MutableTreeNode parent) { + super.setParent(parent); + if(parent != null) { + path = ((FHTreeStateNode)parent).getTreePath(). + pathByAddingChild(getUserObject()); + addMapping(this); + } + } + + /** + * Messaged when this node is removed from its parent, this messages + * removedFromMapping
to remove all the children. + */ + public void remove(int childIndex) { + FHTreeStateNode node = (FHTreeStateNode)getChildAt(childIndex); + + node.removeFromMapping(); + super.remove(childIndex); + } + + /** + * Messaged to set the user object. This resets the path. + */ + public void setUserObject(Object o) { + super.setUserObject(o); + if(path != null) { + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + + if(parent != null) + resetChildrenPaths(parent.getTreePath()); + else + resetChildrenPaths(null); + } + } + + // + // + + /** + * Returns the index of the receiver in the model. + */ + public int getChildIndex() { + return childIndex; + } + + /** + * Returns theTreePath
of the receiver. + */ + public TreePath getTreePath() { + return path; + } + + /** + * Returns the child for the passed in model index, this will + * returnnull
if the child forindex
+ * has not yet been created (expanded). + */ + public FHTreeStateNode getChildAtModelIndex(int index) { + // PENDING: Make this a binary search! + for(int counter = getChildCount() - 1; counter >= 0; counter--) + if(((FHTreeStateNode)getChildAt(counter)).childIndex == index) + return (FHTreeStateNode)getChildAt(counter); + return null; + } + + /** + * Returns true if this node is visible. This is determined by + * asking all the parents if they are expanded. + */ + public boolean isVisible() { + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + + if(parent == null) + return true; + return (parent.isExpanded() && parent.isVisible()); + } + + /** + * Returns the row of the receiver. + */ + public int getRow() { + return row; + } + + /** + * Returns the row of the child with a model index of + *index
. + */ + public int getRowToModelIndex(int index) { + FHTreeStateNode child; + int lastRow = getRow() + 1; + int retValue = lastRow; + + // This too could be a binary search! + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + child = (FHTreeStateNode)getChildAt(counter); + if(child.childIndex >= index) { + if(child.childIndex == index) + return child.row; + if(counter == 0) + return getRow() + 1 + index; + return child.row - (child.childIndex - index); + } + } + // YECK! + return getRow() + 1 + getTotalChildCount() - + (childCount - index); + } + + /** + * Returns the number of children in the receiver by descending all + * expanded nodes and messaging them with getTotalChildCount. + */ + public int getTotalChildCount() { + if(isExpanded()) { + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + int pIndex; + + if(parent != null && (pIndex = parent.getIndex(this)) + 1 < + parent.getChildCount()) { + // This node has a created sibling, to calc total + // child count directly from that! + FHTreeStateNode nextSibling = (FHTreeStateNode)parent. + getChildAt(pIndex + 1); + + return nextSibling.row - row - + (nextSibling.childIndex - childIndex); + } + else { + int retCount = childCount; + + for(int counter = getChildCount() - 1; counter >= 0; + counter--) { + retCount += ((FHTreeStateNode)getChildAt(counter)) + .getTotalChildCount(); + } + return retCount; + } + } + return 0; + } + + /** + * Returns true if this node is expanded. + */ + public boolean isExpanded() { + return isExpanded; + } + + /** + * The highest visible nodes have a depth of 0. + */ + public int getVisibleLevel() { + if (isRootVisible()) { + return getLevel(); + } else { + return getLevel() - 1; + } + } + + /** + * Recreates the receivers path, and all its children's paths. + */ + protected void resetChildrenPaths(TreePath parentPath) { + removeMapping(this); + if(parentPath == null) + path = new TreePath(getUserObject()); + else + path = parentPath.pathByAddingChild(getUserObject()); + addMapping(this); + for(int counter = getChildCount() - 1; counter >= 0; counter--) + ((FHTreeStateNode)getChildAt(counter)). + resetChildrenPaths(path); + } + + /** + * Removes the receiver, and all its children, from the mapping + * table. + */ + protected void removeFromMapping() { + if(path != null) { + removeMapping(this); + for(int counter = getChildCount() - 1; counter >= 0; counter--) + ((FHTreeStateNode)getChildAt(counter)).removeFromMapping(); + } + } + + /** + * Creates a new node to representuserObject
. + * This does NOT check to ensure there isn't already a child node + * to manageuserObject
. + */ + protected FHTreeStateNode createChildFor(Object userObject) { + int newChildIndex = treeModel.getIndexOfChild + (getUserObject(), userObject); + + if(newChildIndex < 0) + return null; + + FHTreeStateNode aNode; + FHTreeStateNode child = createNodeForValue(userObject, + newChildIndex); + int childRow; + + if(isVisible()) { + childRow = getRowToModelIndex(newChildIndex); + } + else { + childRow = -1; + } + child.row = childRow; + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + aNode = (FHTreeStateNode)getChildAt(counter); + if(aNode.childIndex > newChildIndex) { + insert(child, counter); + return child; + } + } + add(child); + return child; + } + + /** + * Adjusts the receiver, and all its children rows by + *amount
. + */ + protected void adjustRowBy(int amount) { + row += amount; + if(isExpanded) { + for(int counter = getChildCount() - 1; counter >= 0; + counter--) + ((FHTreeStateNode)getChildAt(counter)).adjustRowBy(amount); + } + } + + /** + * Adjusts this node, its child, and its parent starting at + * an index ofindex
index is the index of the child + * to start adjusting from, which is not necessarily the model + * index. + */ + protected void adjustRowBy(int amount, int startIndex) { + // Could check isVisible, but probably isn't worth it. + if(isExpanded) { + // children following startIndex. + for(int counter = getChildCount() - 1; counter >= startIndex; + counter--) + ((FHTreeStateNode)getChildAt(counter)).adjustRowBy(amount); + } + // Parent + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + + if(parent != null) { + parent.adjustRowBy(amount, parent.getIndex(this) + 1); + } + } + + /** + * Messaged when the node has expanded. This updates all of + * the receivers children rows, as well as the total row count. + */ + protected void didExpand() { + int nextRow = setRowAndChildren(row); + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + int childRowCount = nextRow - row - 1; + + if(parent != null) { + parent.adjustRowBy(childRowCount, parent.getIndex(this) + 1); + } + adjustRowCountBy(childRowCount); + } + + /** + * Sets the receivers row tonextRow
and recursively + * updates all the children of the receivers rows. The index the + * next row is to be placed as is returned. + */ + protected int setRowAndChildren(int nextRow) { + row = nextRow; + + if(!isExpanded()) + return row + 1; + + int lastRow = row + 1; + int lastModelIndex = 0; + FHTreeStateNode child; + int maxCounter = getChildCount(); + + for(int counter = 0; counter < maxCounter; counter++) { + child = (FHTreeStateNode)getChildAt(counter); + lastRow += (child.childIndex - lastModelIndex); + lastModelIndex = child.childIndex + 1; + if(child.isExpanded) { + lastRow = child.setRowAndChildren(lastRow); + } + else { + child.row = lastRow++; + } + } + return lastRow + childCount - lastModelIndex; + } + + /** + * Resets the receivers children's rows. Starting with the child + * atchildIndex
(andmodelIndex
) to + *newRow
. This usessetRowAndChildren
+ * to recursively descend children, and uses + *resetRowSelection
to ascend parents. + */ + // This can be rather expensive, but is needed for the collapse + // case this is resulting from a remove (although I could fix + // that by having instances of FHTreeStateNode hold a ref to + // the number of children). I prefer this though, making determing + // the row of a particular node fast is very nice! + protected void resetChildrenRowsFrom(int newRow, int childIndex, + int modelIndex) { + int lastRow = newRow; + int lastModelIndex = modelIndex; + FHTreeStateNode node; + int maxCounter = getChildCount(); + + for(int counter = childIndex; counter < maxCounter; counter++) { + node = (FHTreeStateNode)getChildAt(counter); + lastRow += (node.childIndex - lastModelIndex); + lastModelIndex = node.childIndex + 1; + if(node.isExpanded) { + lastRow = node.setRowAndChildren(lastRow); + } + else { + node.row = lastRow++; + } + } + lastRow += childCount - lastModelIndex; + node = (FHTreeStateNode)getParent(); + if(node != null) { + node.resetChildrenRowsFrom(lastRow, node.getIndex(this) + 1, + this.childIndex + 1); + } + else { // This is the root, reset total ROWCOUNT! + rowCount = lastRow; + } + } + + /** + * Makes the receiver visible, but invoking + *expandParentAndReceiver
on the superclass. + */ + protected void makeVisible() { + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + + if(parent != null) + parent.expandParentAndReceiver(); + } + + /** + * InvokesexpandParentAndReceiver
on the parent, + * and expands the receiver. + */ + protected void expandParentAndReceiver() { + FHTreeStateNode parent = (FHTreeStateNode)getParent(); + + if(parent != null) + parent.expandParentAndReceiver(); + expand(); + } + + /** + * Expands the receiver. + */ + protected void expand() { + if(!isExpanded && !isLeaf()) { + boolean visible = isVisible(); + + isExpanded = true; + childCount = treeModel.getChildCount(getUserObject()); + + if(visible) { + didExpand(); + } + + // Update the selection model. + if(visible && treeSelectionModel != null) { + treeSelectionModel.resetRowSelection(); + } + } + } + + /** + * Collapses the receiver. IfadjustRows
is true, + * the rows of nodes after the receiver are adjusted. + */ + protected void collapse(boolean adjustRows) { + if(isExpanded) { + if(isVisible() && adjustRows) { + int childCount = getTotalChildCount(); + + isExpanded = false; + adjustRowCountBy(-childCount); + // We can do this because adjustRowBy won't descend + // the children. + adjustRowBy(-childCount, 0); + } + else + isExpanded = false; + + if(adjustRows && isVisible() && treeSelectionModel != null) + treeSelectionModel.resetRowSelection(); + } + } + + /** + * Returns true if the receiver is a leaf. + */ + public boolean isLeaf() { + TreeModel model = getModel(); + + return (model != null) ? model.isLeaf(this.getUserObject()) : + true; + } + + /** + * Adds newChild to this nodes children at the appropriate location. + * The location is determined from the childIndex of newChild. + */ + protected void addNode(FHTreeStateNode newChild) { + boolean added = false; + int childIndex = newChild.getChildIndex(); + + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + if(((FHTreeStateNode)getChildAt(counter)).getChildIndex() > + childIndex) { + added = true; + insert(newChild, counter); + counter = maxCounter; + } + } + if(!added) + add(newChild); + } + + /** + * Removes the child atmodelIndex
. + *isChildVisible
should be true if the receiver + * is visible and expanded. + */ + protected void removeChildAtModelIndex(int modelIndex, + boolean isChildVisible) { + FHTreeStateNode childNode = getChildAtModelIndex(modelIndex); + + if(childNode != null) { + int row = childNode.getRow(); + int index = getIndex(childNode); + + childNode.collapse(false); + remove(index); + adjustChildIndexs(index, -1); + childCount--; + if(isChildVisible) { + // Adjust the rows. + resetChildrenRowsFrom(row, index, modelIndex); + } + } + else { + int maxCounter = getChildCount(); + FHTreeStateNode aChild; + + for(int counter = 0; counter < maxCounter; counter++) { + aChild = (FHTreeStateNode)getChildAt(counter); + if(aChild.childIndex >= modelIndex) { + if(isChildVisible) { + adjustRowBy(-1, counter); + adjustRowCountBy(-1); + } + // Since matched and children are always sorted by + // index, no need to continue testing with the + // above. + for(; counter < maxCounter; counter++) + ((FHTreeStateNode)getChildAt(counter)). + childIndex--; + childCount--; + return; + } + } + // No children to adjust, but it was a child, so we still need + // to adjust nodes after this one. + if(isChildVisible) { + adjustRowBy(-1, maxCounter); + adjustRowCountBy(-1); + } + childCount--; + } + } + + /** + * Adjusts the child indexs of the receivers children by + *amount
, starting atindex
. + */ + protected void adjustChildIndexs(int index, int amount) { + for(int counter = index, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + ((FHTreeStateNode)getChildAt(counter)).childIndex += amount; + } + } + + /** + * Messaged when a child has been inserted at index. For all the + * children that have a childIndex ≥ index their index is incremented + * by one. + */ + protected void childInsertedAtModelIndex(int index, + boolean isExpandedAndVisible) { + FHTreeStateNode aChild; + int maxCounter = getChildCount(); + + for(int counter = 0; counter < maxCounter; counter++) { + aChild = (FHTreeStateNode)getChildAt(counter); + if(aChild.childIndex >= index) { + if(isExpandedAndVisible) { + adjustRowBy(1, counter); + adjustRowCountBy(1); + } + /* Since matched and children are always sorted by + index, no need to continue testing with the above. */ + for(; counter < maxCounter; counter++) + ((FHTreeStateNode)getChildAt(counter)).childIndex++; + childCount++; + return; + } + } + // No children to adjust, but it was a child, so we still need + // to adjust nodes after this one. + if(isExpandedAndVisible) { + adjustRowBy(1, maxCounter); + adjustRowCountBy(1); + } + childCount++; + } + + /** + * Returns true if there is a row forrow
. + *nextRow
gives the bounds of the receiver. + * Information about the found row is returned ininfo
. + * This should be invoked on root withnextRow
set + * togetRowCount
(). + */ + protected boolean getPathForRow(int row, int nextRow, + SearchInfo info) { + if(this.row == row) { + info.node = this; + info.isNodeParentNode = false; + info.childIndex = childIndex; + return true; + } + + FHTreeStateNode child; + FHTreeStateNode lastChild = null; + + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + child = (FHTreeStateNode)getChildAt(counter); + if(child.row > row) { + if(counter == 0) { + // No node exists for it, and is first. + info.node = this; + info.isNodeParentNode = true; + info.childIndex = row - this.row - 1; + return true; + } + else { + // May have been in last child's bounds. + int lastChildEndRow = 1 + child.row - + (child.childIndex - lastChild.childIndex); + + if(row < lastChildEndRow) { + return lastChild.getPathForRow(row, + lastChildEndRow, info); + } + // Between last child and child, but not in last child + info.node = this; + info.isNodeParentNode = true; + info.childIndex = row - lastChildEndRow + + lastChild.childIndex + 1; + return true; + } + } + lastChild = child; + } + + // Not in children, but we should have it, offset from + // nextRow. + if(lastChild != null) { + int lastChildEndRow = nextRow - + (childCount - lastChild.childIndex) + 1; + + if(row < lastChildEndRow) { + return lastChild.getPathForRow(row, lastChildEndRow, info); + } + // Between last child and child, but not in last child + info.node = this; + info.isNodeParentNode = true; + info.childIndex = row - lastChildEndRow + + lastChild.childIndex + 1; + return true; + } + else { + // No children. + int retChildIndex = row - this.row - 1; + + if(retChildIndex >= childCount) { + return false; + } + info.node = this; + info.isNodeParentNode = true; + info.childIndex = retChildIndex; + return true; + } + } + + /** + * Asks all the children of the receiver for their totalChildCount + * and returns this value (plus stopIndex). + */ + protected int getCountTo(int stopIndex) { + FHTreeStateNode aChild; + int retCount = stopIndex + 1; + + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + aChild = (FHTreeStateNode)getChildAt(counter); + if(aChild.childIndex >= stopIndex) + counter = maxCounter; + else + retCount += aChild.getTotalChildCount(); + } + if(parent != null) + return retCount + ((FHTreeStateNode)getParent()) + .getCountTo(childIndex); + if(!isRootVisible()) + return (retCount - 1); + return retCount; + } + + /** + * Returns the number of children that are expanded to + *stopIndex
. This does not include the number + * of children that the child atstopIndex
might + * have. + */ + protected int getNumExpandedChildrenTo(int stopIndex) { + FHTreeStateNode aChild; + int retCount = stopIndex; + + for(int counter = 0, maxCounter = getChildCount(); + counter < maxCounter; counter++) { + aChild = (FHTreeStateNode)getChildAt(counter); + if(aChild.childIndex >= stopIndex) + return retCount; + else { + retCount += aChild.getTotalChildCount(); + } + } + return retCount; + } + + /** + * Messaged when this node either expands or collapses. + */ + protected void didAdjustTree() { + } + + } // FixedHeightLayoutCache.FHTreeStateNode + + + /** + * Used as a placeholder when getting the path in FHTreeStateNodes. + */ + private class SearchInfo { + protected FHTreeStateNode node; + protected boolean isNodeParentNode; + protected int childIndex; + + protected TreePath getPath() { + if(node == null) + return null; + + if(isNodeParentNode) + return node.getTreePath().pathByAddingChild(treeModel.getChild + (node.getUserObject(), + childIndex)); + return node.path; + } + } // FixedHeightLayoutCache.SearchInfo + + + /** + * An enumerator to iterate through visible nodes. + */ + // This is very similar to + // VariableHeightTreeState.VisibleTreeStateNodeEnumeration + private class VisibleFHTreeStateNodeEnumeration + implements Enumeration+ { + /** Parent thats children are being enumerated. */ + protected FHTreeStateNode parent; + /** Index of next child. An index of -1 signifies parent should be + * visibled next. */ + protected int nextIndex; + /** Number of children in parent. */ + protected int childCount; + + protected VisibleFHTreeStateNodeEnumeration(FHTreeStateNode node) { + this(node, -1); + } + + protected VisibleFHTreeStateNodeEnumeration(FHTreeStateNode parent, + int startIndex) { + this.parent = parent; + this.nextIndex = startIndex; + this.childCount = treeModel.getChildCount(this.parent. + getUserObject()); + } + + /** + * @return true if more visible nodes. + */ + public boolean hasMoreElements() { + return (parent != null); + } + + /** + * @return next visible TreePath. + */ + public TreePath nextElement() { + if(!hasMoreElements()) + throw new NoSuchElementException("No more visible paths"); + + TreePath retObject; + + if(nextIndex == -1) + retObject = parent.getTreePath(); + else { + FHTreeStateNode node = parent.getChildAtModelIndex(nextIndex); + + if(node == null) + retObject = parent.getTreePath().pathByAddingChild + (treeModel.getChild(parent.getUserObject(), + nextIndex)); + else + retObject = node.getTreePath(); + } + updateNextObject(); + return retObject; + } + + /** + * Determines the next object by invoking updateNextIndex
+ * and if not succesfulfindNextValidParent
. + */ + protected void updateNextObject() { + if(!updateNextIndex()) { + findNextValidParent(); + } + } + + /** + * Finds the next valid parent, this should be called when nextIndex + * is beyond the number of children of the current parent. + */ + protected boolean findNextValidParent() { + if(parent == root) { + // mark as invalid! + parent = null; + return false; + } + while(parent != null) { + FHTreeStateNode newParent = (FHTreeStateNode)parent. + getParent(); + + if(newParent != null) { + nextIndex = parent.childIndex; + parent = newParent; + childCount = treeModel.getChildCount + (parent.getUserObject()); + if(updateNextIndex()) + return true; + } + else + parent = null; + } + return false; + } + + /** + * UpdatesnextIndex
returning false if it is beyond + * the number of children of parent. + */ + protected boolean updateNextIndex() { + // nextIndex == -1 identifies receiver, make sure is expanded + // before descend. + if(nextIndex == -1 && !parent.isExpanded()) { + return false; + } + + // Check that it can have kids + if(childCount == 0) { + return false; + } + // Make sure next index not beyond child count. + else if(++nextIndex >= childCount) { + return false; + } + + FHTreeStateNode child = parent.getChildAtModelIndex(nextIndex); + + if(child != null && child.isExpanded()) { + parent = child; + nextIndex = -1; + childCount = treeModel.getChildCount(child.getUserObject()); + } + return true; + } + } // FixedHeightLayoutCache.VisibleFHTreeStateNodeEnumeration +} diff --git a/sources/net.sf.j2s.java.core/src/javax/swing/tree/VariableHeightLayoutCache.java b/sources/net.sf.j2s.java.core/src/javax/swing/tree/VariableHeightLayoutCache.java new file mode 100644 index 000000000..ca60ea86c --- /dev/null +++ b/sources/net.sf.j2s.java.core/src/javax/swing/tree/VariableHeightLayoutCache.java @@ -0,0 +1,1768 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.swing.tree; + +import javax.swing.event.TreeModelEvent; +import java.awt.Rectangle; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.NoSuchElementException; +import java.util.Stack; +import java.util.Vector; + +import sun.swing.SwingUtilities2; + +/** + * NOTE: This will become more open in a future release. + *+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeans™ + * has been added to the
java.beans
package. + * Please see {@link java.beans.XMLEncoder}. + * + * @author Rob Davis + * @author Ray Ryan + * @author Scott Violet + */ + +public class VariableHeightLayoutCache extends AbstractLayoutCache { + /** + * The array of nodes that are currently visible, in the order they + * are displayed. + */ + private Vector