/*
 * Copyright (c) 2011, 2018, 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 sun.java2d;

import java.awt.*;
import java.awt.color.*;
import java.awt.image.*;
import java.nio.*;

import sun.awt.image.*;
import sun.java2d.loops.*;

public class OSXOffScreenSurfaceData extends OSXSurfaceData // implements RasterListener
{
    private static native void initIDs();

    static {
        initIDs();
    }

    // the image associated with this surface
    BufferedImage bim;
    // the image associated with this custom surface
    BufferedImage bimBackup;
    // <rdar://problem/4177639> nio based images use ARGB_PRE
    static DirectColorModel dcmBackup = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, true, DataBuffer.TYPE_INT);

    Object lock;

    // cached rasters for easy access
    WritableRaster bufImgRaster;
    SunWritableRaster bufImgSunRaster;

    // these are extra image types we can handle
    private static final int TYPE_3BYTE_RGB = BufferedImage.TYPE_BYTE_INDEXED + 1;

    // these are for callbacks when pixels have been touched
    protected ByteBuffer fImageInfo;
    IntBuffer fImageInfoInt;
    private static final int kNeedToSyncFromJavaPixelsIndex = 0;
    private static final int kNativePixelsChangedIndex = 1;
    private static final int kImageStolenIndex = 2;
    private static final int kSizeOfParameters = kImageStolenIndex + 1;

    public static native SurfaceData getSurfaceData(BufferedImage bufImg);

    protected static native void setSurfaceData(BufferedImage bufImg, SurfaceData sData);

    public static SurfaceData createData(BufferedImage bufImg) {
        /*
         * if ((bufImg.getWidth() == 32) && (bufImg.getHeight() == 32)) { Thread.dumpStack(); }
         */
        // This could be called from multiple threads. We need to synchronized on the image so that
        // we can ensure that only one surface data is created per image. (<rdar://4564873>)
        // Note: Eventually, we should switch to using the same mechanism (CachingSurfaceManager) that Sun uses
        // <rdar://4563741>
        synchronized (bufImg) {
            SurfaceData sData = getSurfaceData(bufImg);
            if (sData != null) { return sData; }

            OSXOffScreenSurfaceData osData = OSXOffScreenSurfaceData.createNewSurface(bufImg);

            OSXOffScreenSurfaceData.setSurfaceData(bufImg, osData);
            osData.cacheRasters(bufImg);
//            osData.setRasterListener();

            return osData;
        }
    }

    public static SurfaceData createData(Raster ras, ColorModel cm) {
        throw new InternalError("SurfaceData not implemented for Raster/CM");
    }

    static OSXOffScreenSurfaceData createNewSurface(BufferedImage bufImg) {
        SurfaceData sData = null;

        ColorModel cm = bufImg.getColorModel();
        int type = bufImg.getType();
        // REMIND: Check the image type and pick an appropriate subclass
        switch (type) {
            case BufferedImage.TYPE_INT_BGR:
                sData = createDataIC(bufImg, SurfaceType.IntBgr);
                break;
            case BufferedImage.TYPE_INT_RGB:
                sData = createDataIC(bufImg, SurfaceType.IntRgb);
                break;
            case BufferedImage.TYPE_INT_ARGB:
                sData = createDataIC(bufImg, SurfaceType.IntArgb);
                break;
            case BufferedImage.TYPE_INT_ARGB_PRE:
                sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
                break;
            case BufferedImage.TYPE_3BYTE_BGR:
                sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
                break;
            case BufferedImage.TYPE_4BYTE_ABGR:
                sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
                break;
            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
                sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
                break;
            case BufferedImage.TYPE_USHORT_565_RGB:
                sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
                break;
            case BufferedImage.TYPE_USHORT_555_RGB:
                sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
                break;
            case BufferedImage.TYPE_BYTE_INDEXED: {
                SurfaceType sType;
                switch (cm.getTransparency()) {
                    case OPAQUE:
                        if (isOpaqueGray((IndexColorModel) cm)) {
                            sType = SurfaceType.Index8Gray;
                        } else {
                            sType = SurfaceType.ByteIndexedOpaque;
                        }
                        break;
                    case BITMASK:
                        sType = SurfaceType.ByteIndexedBm;
                        break;
                    case TRANSLUCENT:
                        sType = SurfaceType.ByteIndexed;
                        break;
                    default:
                        throw new InternalError("Unrecognized transparency");
                }
                sData = createDataBC(bufImg, sType, 0);
            }
                break;
            case BufferedImage.TYPE_BYTE_GRAY:
                sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
                break;
            case BufferedImage.TYPE_USHORT_GRAY:
                sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
                break;
            case BufferedImage.TYPE_BYTE_BINARY:
            case BufferedImage.TYPE_CUSTOM:
            default: {
                Raster raster = bufImg.getRaster();

                // we try to fit a custom image into one of the predefined BufferedImages (BufferedImage does that
                // first, we further refine it here)
                // we can do that because a pointer in C is a pointer (pixel pointer not dependent on DataBuffer type)
                SampleModel sm = bufImg.getSampleModel();
                SurfaceType sType = SurfaceType.Custom;
                int transferType = cm.getTransferType();
                int pixelSize = cm.getPixelSize();
                int numOfComponents = cm.getNumColorComponents();
                if ((numOfComponents == 3) && (cm instanceof ComponentColorModel) && (sm instanceof PixelInterleavedSampleModel)) {
                    int[] sizes = cm.getComponentSize();
                    boolean validsizes = (sizes[0] == 8) && (sizes[1] == 8) && (sizes[2] == 8);
                    int[] offs = ((ComponentSampleModel) sm).getBandOffsets();
                    int numBands = raster.getNumBands();
                    boolean bigendian = (offs[0] == numBands - 3) && (offs[1] == numBands - 2) && (offs[2] == numBands - 1);
                    boolean littleendian = (offs[0] == numBands - 1) && (offs[1] == numBands - 2) && (offs[2] == numBands - 3);

                    if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_INT)) {
                        if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB_PRE);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR_PRE);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && bigendian) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_BYTE)) {
                        if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB_PRE);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                        if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR_PRE);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_BGR);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && bigendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_INT)) {
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian) {
                            try {
                                sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_BGR);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_BYTE)) {
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 0, TYPE_3BYTE_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        } else if (validsizes && littleendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 0, BufferedImage.TYPE_3BYTE_BGR);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_USHORT)) {
                        validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5);
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_565_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_BYTE)) {
                        validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5);
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_565_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_USHORT)) {
                        validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5);
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_555_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_BYTE)) {
                        validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5);
                        if (validsizes && bigendian) {
                            try {
                                sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_555_RGB);
                            } catch (ClassCastException e) {
                                sData = null;
                            }
                        }
                    }
                }
            }
                break;
        }

        // we failed to match
        if (sData == null) {
            sData = new OSXOffScreenSurfaceData(bufImg, SurfaceType.Custom);
            OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) sData;

            // 2004_03_26 cmc: We used to use createCompatibleImage here. Now that createCompatibleImage returns
            // an INT_ARGB_PRE instead of an NIO-based image, we need to explicitly create an NIO-based image.
            IntegerNIORaster backupRaster = (IntegerNIORaster) IntegerNIORaster.createNIORaster(bufImg.getWidth(), bufImg.getHeight(), dcmBackup.getMasks(), null);
            offsd.bimBackup = new BufferedImage(dcmBackup, backupRaster, dcmBackup.isAlphaPremultiplied(), null);

            // the trick that makes it work - assign the raster from backup to the surface data of the original image
            offsd.initCustomRaster(backupRaster.getBuffer(),
                                    backupRaster.getWidth(),
                                    backupRaster.getHeight(),
                                    offsd.fGraphicsStates,
                                    offsd.fGraphicsStatesObject,
                                    offsd.fImageInfo);

            //offsd.checkIfLazyPixelConversionDisabled();
            offsd.fImageInfoInt.put(kImageStolenIndex, 1);
        }

        return (OSXOffScreenSurfaceData) sData;
    }

    private static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType, int iType) {
        OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);

        IntegerComponentRaster icRaster = (IntegerComponentRaster) bImg.getRaster();
        offsd.initRaster(icRaster.getDataStorage(),
                            icRaster.getDataOffset(0) * 4,
                            icRaster.getWidth(),
                            icRaster.getHeight(),
                            icRaster.getPixelStride() * 4,
                            icRaster.getScanlineStride() * 4,
                            null,
                            iType,
                            offsd.fGraphicsStates,
                            offsd.fGraphicsStatesObject,
                            offsd.fImageInfo);

       // offsd.checkIfLazyPixelConversionDisabled();
        offsd.fImageInfoInt.put(kImageStolenIndex, 1);
        return offsd;
    }

    public static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType) {
        return createDataIC(bImg, sType, bImg.getType());
    }

    private static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm, int iType) {
        OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);

        ShortComponentRaster scRaster = (ShortComponentRaster) bImg.getRaster();
        offsd.initRaster(scRaster.getDataStorage(),
                            scRaster.getDataOffset(0) * 2,
                            scRaster.getWidth(),
                            scRaster.getHeight(),
                            scRaster.getPixelStride() * 2,
                            scRaster.getScanlineStride() * 2,
                            icm,
                            iType,
                            offsd.fGraphicsStates,
                            offsd.fGraphicsStatesObject,
                            offsd.fImageInfo);

        //offsd.checkIfLazyPixelConversionDisabled();
        offsd.fImageInfoInt.put(kImageStolenIndex, 1);
        return offsd;
    }

    public static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm) {
        return createDataSC(bImg, sType, icm, bImg.getType());
    }

    private static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank, int iType) {
        OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);

        ByteComponentRaster bcRaster = (ByteComponentRaster) bImg.getRaster();
        ColorModel cm = bImg.getColorModel();
        IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null);
        offsd.initRaster(bcRaster.getDataStorage(),
                            bcRaster.getDataOffset(primaryBank),
                            bcRaster.getWidth(),
                            bcRaster.getHeight(),
                            bcRaster.getPixelStride(),
                            bcRaster.getScanlineStride(),
                            icm,
                            iType,
                            offsd.fGraphicsStates,
                            offsd.fGraphicsStatesObject,
                            offsd.fImageInfo);

        offsd.fImageInfoInt.put(kImageStolenIndex, 1);

        return offsd;
    }

    public static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank) {
        return createDataBC(bImg, sType, primaryBank, bImg.getType());
    }

    private static SurfaceData createDataBP(BufferedImage bImg, SurfaceType sType, int iType) {
        OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);

        BytePackedRaster bpRaster = (BytePackedRaster) bImg.getRaster();
        ColorModel cm = bImg.getColorModel();
        IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null);
        offsd.initRaster(bpRaster.getDataStorage(),
                            bpRaster.getDataBitOffset(), // in bits, NOT bytes! (needs special attention in native
                                                         // code!)
                bpRaster.getWidth(),
                            bpRaster.getHeight(),
                            bpRaster.getPixelBitStride(),
                            bpRaster.getScanlineStride() * 8,
                            icm,
                            iType,
                            offsd.fGraphicsStates,
                            offsd.fGraphicsStatesObject,
                            offsd.fImageInfo);

        //offsd.checkIfLazyPixelConversionDisabled();
        offsd.fImageInfoInt.put(kImageStolenIndex, 1);
        return offsd;
    }

    protected native void initRaster(Object theArray, int offset, int width, int height, int pixStr, int scanStr, IndexColorModel icm, int type, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo);

    protected native void initCustomRaster(IntBuffer buffer, int width, int height, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo);

    public Object getLockObject() {
        return this.lock;
    }

    // Makes the constructor package private instead of public.
    OSXOffScreenSurfaceData(BufferedImage bufImg, SurfaceType sType) {
        super(sType, bufImg.getColorModel());
        setBounds(0, 0, bufImg.getWidth(), bufImg.getHeight());

        this.bim = bufImg;

        this.fImageInfo = ByteBuffer.allocateDirect(4 * kSizeOfParameters);
        this.fImageInfo.order(ByteOrder.nativeOrder());
        this.fImageInfoInt = this.fImageInfo.asIntBuffer();

        this.fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // need to sync from Java the very first time
        this.fImageInfoInt.put(kNativePixelsChangedIndex, 0);
        this.fImageInfoInt.put(kImageStolenIndex, 0);

        this.lock = new Object();
    }

    /**
     * Performs a copyArea within this surface.
     */
    public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
        // <rdar://problem/4488745> For the Sun2D renderer we should rely on the implementation of the super class.
        // BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class.

        if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
            return false;
        }

        // reset the clip (this is how it works on windows)
        // we actually can handle a case with any clips but windows ignores the light clip
        Shape clip = sg2d.getClip();
        sg2d.setClip(getBounds());

        // clip copyArea
        Rectangle clippedCopyAreaRect = clipCopyArea(sg2d, x, y, w, h, dx, dy);
        if (clippedCopyAreaRect == null) {
            // clipped out
            return true;
        }

        // the rectangle returned from clipCopyArea() is in the coordinate space
        // of the surface (image)
        x = clippedCopyAreaRect.x;
        y = clippedCopyAreaRect.y;
        w = clippedCopyAreaRect.width;
        h = clippedCopyAreaRect.height;

        // copy (dst coordinates are in the coord space of the graphics2d, and
        // src coordinates are in the coordinate space of the image)
        // sg2d.drawImage expects the destination rect to be in the coord space
        // of the graphics2d. <rdar://3746194> (vm)
        // we need to subtract the transX and transY to move it
        // to the coordinate space of the graphics2d.
        int dstX = x + dx - sg2d.transX;
        int dstY = y + dy - sg2d.transY;
        sg2d.drawImage(this.bim, dstX, dstY, dstX + w, dstY + h,
                       x, y, x + w, y + h, null);

        // restore the clip
        sg2d.setClip(clip);

        return true;
    }

    /**
     * Performs a copyarea from this surface to a buffered image. If null is passed in for the image a new image will be
     * created.
     *
     * Only used by compositor code (private API)
     */
    public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage) {
        // create the destination image if needed
        if (dstImage == null) {
            dstImage = getDeviceConfiguration().createCompatibleImage(w, h);
        }

        // copy
        Graphics g = dstImage.createGraphics();
        g.drawImage(this.bim, 0, 0, w, h, x, y, x + w, y + h, null);
        g.dispose();

        return dstImage;
    }

    public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR) {

        int type = this.bim.getType();

        if ((type == BufferedImage.TYPE_INT_ARGB_PRE) || (type == BufferedImage.TYPE_INT_ARGB) || (type == BufferedImage.TYPE_INT_RGB)) { return xorSurfacePixels(createData(srcPixels), colorXOR, x, y, w, h); }

        return false;
    }

    native boolean xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h);

    public void clearRect(BufferedImage bim, int w, int h) {
        OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) (OSXOffScreenSurfaceData.createData(bim));
        // offsd.clear();
        if (offsd.clearSurfacePixels(w, h) == false) {
            Graphics2D g = bim.createGraphics();
            g.setComposite(AlphaComposite.Clear);
            g.fillRect(0, 0, w, h);
            g.dispose();
        }
    }

    native boolean clearSurfacePixels(int w, int h);

    // 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter.
    // getCopyWithBgColor returns a new version of an image, drawn with a background
    // color. Called by blitImage in OSXSurfaceData.java.
    BufferedImage copyWithBgColor_cache = null;

    public SurfaceData getCopyWithBgColor(Color bgColor) {
        int bimW = this.bim.getWidth();
        int bimH = this.bim.getHeight();

        if ((this.copyWithBgColor_cache == null)
                || (this.copyWithBgColor_cache.getWidth() < bimW) || (this.copyWithBgColor_cache.getHeight() < bimH)) {
            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
            this.copyWithBgColor_cache = gc.createCompatibleImage(bimW, bimH);
        }

        Graphics g2 = this.copyWithBgColor_cache.createGraphics();
        g2.setColor(bgColor);
        g2.fillRect(0, 0, bimW, bimH);
        g2.drawImage(this.bim, 0, 0, bimW, bimH, null);
        g2.dispose();

        return getSurfaceData(this.copyWithBgColor_cache);
    }

    /**
     * Invoked before the raster's contents are to be read (via one of the modifier methods in Raster such as
     * getPixel())
     */
    public void rasterRead() {
        if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
            syncToJavaPixels();
        }
    }

    /**
     * Invoked before the raster's contents are to be written to (via one of the modifier methods in Raster such as
     * setPixel())
     */
    public void rasterWrite() {
        if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
            syncToJavaPixels();
        }

        fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // the pixels will change
    }

    private void syncFromCustom() {

    }

    private void syncToCustom() {

    }
//    /**
//     * Invoked when the raster's contents will be taken (via the Raster.getDataBuffer() method)
//     */
//    public void rasterStolen() {
//        fImageInfoInt.put(kImageStolenIndex, 1); // this means we must convert between Java and native pixels every
//                                                 // single primitive! (very expensive)
//        if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
//            syncToJavaPixels();
//        }
//
//        // we know the pixels have been stolen, no need to listen for changes any more
////        if (this.bufImgSunRaster != null) {
////            this.bufImgSunRaster.setRasterListener(null);
////        }
//    }

    private native void syncToJavaPixels();

    // we need to refer to rasters often, so cache them
    void cacheRasters(BufferedImage bim) {
        this.bufImgRaster = bim.getRaster();
        if (this.bufImgRaster instanceof SunWritableRaster) {
            this.bufImgSunRaster = (SunWritableRaster) this.bufImgRaster;
        }
    }

//    void setRasterListener() {
//        if (this.bufImgSunRaster != null) {
//            this.bufImgSunRaster.setRasterListener(this);
//
//            Raster parentRaster = this.bufImgSunRaster.getParent();
//            if (parentRaster != null) {
//                if (parentRaster instanceof SunWritableRaster) {
//                    // mark subimages stolen to turn off lazy pixel conversion (gznote: can we do better here?)
//                    ((SunWritableRaster) parentRaster).notifyStolen();
//                }
//                rasterStolen();
//            }
//        } else {
//            // it's a custom image (non-natively supported) and we can not set a raster listener
//            // so mark the image as stolen - this will turn off LazyPixelConversion optimization (slow, but correct)
//            rasterStolen();
//        }
//    }
}
