4632N/A/*
4632N/A * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
4632N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4632N/A *
4632N/A * This code is free software; you can redistribute it and/or modify it
4632N/A * under the terms of the GNU General Public License version 2 only, as
4632N/A * published by the Free Software Foundation. Oracle designates this
4632N/A * particular file as subject to the "Classpath" exception as provided
4632N/A * by Oracle in the LICENSE file that accompanied this code.
4632N/A *
4632N/A * This code is distributed in the hope that it will be useful, but WITHOUT
4632N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4632N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4632N/A * version 2 for more details (a copy is included in the LICENSE file that
4632N/A * accompanied this code).
4632N/A *
4632N/A * You should have received a copy of the GNU General Public License version
4632N/A * 2 along with this work; if not, write to the Free Software Foundation,
4632N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4632N/A *
4632N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4632N/A * or visit www.oracle.com if you need additional information or have any
4632N/A * questions.
4632N/A */
4632N/A
4632N/Apackage sun.java2d;
4632N/A
4632N/Aimport java.awt.*;
4632N/Aimport java.awt.color.*;
4632N/Aimport java.awt.image.*;
4632N/Aimport java.nio.*;
4632N/A
4632N/Aimport sun.awt.image.*;
4632N/Aimport sun.java2d.loops.*;
4632N/A
4632N/Apublic class OSXOffScreenSurfaceData extends OSXSurfaceData // implements RasterListener
4632N/A{
4632N/A private static native void initIDs();
4632N/A
4632N/A static {
4632N/A initIDs();
4632N/A }
4632N/A
4632N/A // the image associated with this surface
4632N/A BufferedImage bim;
4632N/A // the image associated with this custom surface
4632N/A BufferedImage bimBackup;
4632N/A // <rdar://problem/4177639> nio based images use ARGB_PRE
4632N/A static DirectColorModel dcmBackup = new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, true, DataBuffer.TYPE_INT);
4632N/A
4632N/A Object lock;
4632N/A
4632N/A // cached rasters for easy access
4632N/A WritableRaster bufImgRaster;
4632N/A SunWritableRaster bufImgSunRaster;
4632N/A
4632N/A // these are extra image types we can handle
4632N/A private static final int TYPE_3BYTE_RGB = BufferedImage.TYPE_BYTE_INDEXED + 1;
4632N/A
4632N/A // these are for callbacks when pixes have been touched
4632N/A protected ByteBuffer fImageInfo;
4632N/A IntBuffer fImageInfoInt;
4632N/A private static final int kNeedToSyncFromJavaPixelsIndex = 0;
4632N/A private static final int kNativePixelsChangedIndex = 1;
4632N/A private static final int kImageStolenIndex = 2;
4632N/A private static final int kSizeOfParameters = kImageStolenIndex + 1;
4632N/A
4632N/A public static native SurfaceData getSurfaceData(BufferedImage bufImg);
4632N/A
4632N/A protected static native void setSurfaceData(BufferedImage bufImg, SurfaceData sData);
4632N/A
4632N/A public static SurfaceData createData(BufferedImage bufImg) {
4632N/A /*
4632N/A * if ((bufImg.getWidth() == 32) && (bufImg.getHeight() == 32)) { Thread.dumpStack(); }
4632N/A */
4632N/A // This could be called from multiple threads. We need to synchronized on the image so that
4632N/A // we can ensure that only one surface data is created per image. (<rdar://4564873>)
4632N/A // Note: Eventually, we should switch to using the same mechanism (CachingSurfaceManager) that Sun uses
4632N/A // <rdar://4563741>
4632N/A synchronized (bufImg) {
4632N/A SurfaceData sData = getSurfaceData(bufImg);
4632N/A if (sData != null) { return sData; }
4632N/A
4632N/A OSXOffScreenSurfaceData osData = OSXOffScreenSurfaceData.createNewSurface(bufImg);
4632N/A
4632N/A OSXOffScreenSurfaceData.setSurfaceData(bufImg, osData);
4632N/A osData.cacheRasters(bufImg);
4632N/A// osData.setRasterListener();
4632N/A
4632N/A return osData;
4632N/A }
4632N/A }
4632N/A
4632N/A public static SurfaceData createData(Raster ras, ColorModel cm) {
4632N/A throw new InternalError("SurfaceData not implemented for Raster/CM");
4632N/A }
4632N/A
4632N/A static OSXOffScreenSurfaceData createNewSurface(BufferedImage bufImg) {
4632N/A SurfaceData sData = null;
4632N/A
4632N/A ColorModel cm = bufImg.getColorModel();
4632N/A int type = bufImg.getType();
4632N/A // REMIND: Check the image type and pick an appropriate subclass
4632N/A switch (type) {
4632N/A case BufferedImage.TYPE_INT_BGR:
4632N/A sData = createDataIC(bufImg, SurfaceType.IntBgr);
4632N/A break;
4632N/A case BufferedImage.TYPE_INT_RGB:
4632N/A sData = createDataIC(bufImg, SurfaceType.IntRgb);
4632N/A break;
4632N/A case BufferedImage.TYPE_INT_ARGB:
4632N/A sData = createDataIC(bufImg, SurfaceType.IntArgb);
4632N/A break;
4632N/A case BufferedImage.TYPE_INT_ARGB_PRE:
4632N/A sData = createDataIC(bufImg, SurfaceType.IntArgbPre);
4632N/A break;
4632N/A case BufferedImage.TYPE_3BYTE_BGR:
4632N/A sData = createDataBC(bufImg, SurfaceType.ThreeByteBgr, 2);
4632N/A break;
4632N/A case BufferedImage.TYPE_4BYTE_ABGR:
4632N/A sData = createDataBC(bufImg, SurfaceType.FourByteAbgr, 3);
4632N/A break;
4632N/A case BufferedImage.TYPE_4BYTE_ABGR_PRE:
4632N/A sData = createDataBC(bufImg, SurfaceType.FourByteAbgrPre, 3);
4632N/A break;
4632N/A case BufferedImage.TYPE_USHORT_565_RGB:
4632N/A sData = createDataSC(bufImg, SurfaceType.Ushort565Rgb, null);
4632N/A break;
4632N/A case BufferedImage.TYPE_USHORT_555_RGB:
4632N/A sData = createDataSC(bufImg, SurfaceType.Ushort555Rgb, null);
4632N/A break;
4632N/A case BufferedImage.TYPE_BYTE_INDEXED: {
4632N/A SurfaceType sType;
4632N/A switch (cm.getTransparency()) {
4632N/A case OPAQUE:
4632N/A if (isOpaqueGray((IndexColorModel) cm)) {
4632N/A sType = SurfaceType.Index8Gray;
4632N/A } else {
4632N/A sType = SurfaceType.ByteIndexedOpaque;
4632N/A }
4632N/A break;
4632N/A case BITMASK:
4632N/A sType = SurfaceType.ByteIndexedBm;
4632N/A break;
4632N/A case TRANSLUCENT:
4632N/A sType = SurfaceType.ByteIndexed;
4632N/A break;
4632N/A default:
4632N/A throw new InternalError("Unrecognized transparency");
4632N/A }
4632N/A sData = createDataBC(bufImg, sType, 0);
4632N/A }
4632N/A break;
4632N/A case BufferedImage.TYPE_BYTE_GRAY:
4632N/A sData = createDataBC(bufImg, SurfaceType.ByteGray, 0);
4632N/A break;
4632N/A case BufferedImage.TYPE_USHORT_GRAY:
4632N/A sData = createDataSC(bufImg, SurfaceType.UshortGray, null);
4632N/A break;
4632N/A case BufferedImage.TYPE_BYTE_BINARY:
4632N/A case BufferedImage.TYPE_CUSTOM:
4632N/A default: {
4632N/A Raster raster = bufImg.getRaster();
4632N/A
4632N/A // we try to fit a custom image into one of the predefined BufferedImages (BufferedImage does that
4632N/A // first, we further refine it here)
4632N/A // we can do that because a pointer in C is a pointer (pixel pointer not dependent on DataBuffer type)
4632N/A SampleModel sm = bufImg.getSampleModel();
4632N/A SurfaceType sType = SurfaceType.Custom;
4632N/A int transferType = cm.getTransferType();
4632N/A int pixelSize = cm.getPixelSize();
4632N/A int numOfComponents = cm.getNumColorComponents();
4632N/A if ((numOfComponents == 3) && (cm instanceof ComponentColorModel) && (sm instanceof PixelInterleavedSampleModel)) {
4632N/A int sizes[] = cm.getComponentSize();
4632N/A boolean validsizes = (sizes[0] == 8) && (sizes[1] == 8) && (sizes[2] == 8);
4632N/A int[] offs = ((ComponentSampleModel) sm).getBandOffsets();
4632N/A int numBands = raster.getNumBands();
4632N/A boolean bigendian = (offs[0] == numBands - 3) && (offs[1] == numBands - 2) && (offs[2] == numBands - 1);
4632N/A boolean littleendian = (offs[0] == numBands - 1) && (offs[1] == numBands - 2) && (offs[2] == numBands - 3);
4632N/A
4632N/A if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_INT)) {
4632N/A if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB_PRE);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_ARGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR_PRE);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_4BYTE_ABGR);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 32) && (transferType == DataBuffer.TYPE_BYTE)) {
4632N/A if (validsizes && bigendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB_PRE);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A if (validsizes && bigendian && cm.hasAlpha() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_ARGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian && cm.hasAlpha() && cm.isAlphaPremultiplied() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR_PRE);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian && cm.hasAlpha() && sizes[3] == 8) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_4BYTE_ABGR);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_BGR);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 3, BufferedImage.TYPE_INT_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_INT)) {
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian) {
4632N/A try {
4632N/A sData = createDataIC(bufImg, sType, BufferedImage.TYPE_INT_BGR);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 24) && (transferType == DataBuffer.TYPE_BYTE)) {
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 0, TYPE_3BYTE_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A } else if (validsizes && littleendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 0, BufferedImage.TYPE_3BYTE_BGR);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_USHORT)) {
4632N/A validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5);
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_565_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 16) && (transferType == DataBuffer.TYPE_BYTE)) {
4632N/A validsizes = (sizes[0] == 5) && (sizes[1] == 6) && (sizes[2] == 5);
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_565_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_USHORT)) {
4632N/A validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5);
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataSC(bufImg, sType, null, BufferedImage.TYPE_USHORT_555_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A } else if ((pixelSize == 15) && (transferType == DataBuffer.TYPE_BYTE)) {
4632N/A validsizes = (sizes[0] == 5) && (sizes[1] == 5) && (sizes[2] == 5);
4632N/A if (validsizes && bigendian) {
4632N/A try {
4632N/A sData = createDataBC(bufImg, sType, 1, BufferedImage.TYPE_USHORT_555_RGB);
4632N/A } catch (ClassCastException e) {
4632N/A sData = null;
4632N/A }
4632N/A }
4632N/A }
4632N/A }
4632N/A }
4632N/A break;
4632N/A }
4632N/A
4632N/A // we failed to match
4632N/A if (sData == null) {
4632N/A sData = new OSXOffScreenSurfaceData(bufImg, SurfaceType.Custom);
4632N/A OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) sData;
4632N/A
4632N/A // 2004_03_26 cmc: We used to use createCompatibleImage here. Now that createCompatibleImage returns
4632N/A // an INT_ARGB_PRE instead of an NIO-based image, we need to explicitly create an NIO-based image.
4632N/A IntegerNIORaster backupRaster = (IntegerNIORaster) IntegerNIORaster.createNIORaster(bufImg.getWidth(), bufImg.getHeight(), dcmBackup.getMasks(), null);
4632N/A offsd.bimBackup = new BufferedImage(dcmBackup, backupRaster, dcmBackup.isAlphaPremultiplied(), null);
4632N/A
4632N/A // the trick that makes it work - assign the raster from backup to the surface data of the original image
4632N/A offsd.initCustomRaster(backupRaster.getBuffer(),
4632N/A backupRaster.getWidth(),
4632N/A backupRaster.getHeight(),
4632N/A offsd.fGraphicsStates,
4632N/A offsd.fGraphicsStatesObject,
4632N/A offsd.fImageInfo);
4632N/A
4632N/A //offsd.checkIfLazyPixelConversionDisabled();
4632N/A offsd.fImageInfoInt.put(kImageStolenIndex, 1);
4632N/A }
4632N/A
4632N/A return (OSXOffScreenSurfaceData) sData;
4632N/A }
4632N/A
4632N/A private static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType, int iType) {
4632N/A OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);
4632N/A
4632N/A IntegerComponentRaster icRaster = (IntegerComponentRaster) bImg.getRaster();
4632N/A offsd.initRaster(icRaster.getDataStorage(),
4632N/A icRaster.getDataOffset(0) * 4,
4632N/A icRaster.getWidth(),
4632N/A icRaster.getHeight(),
4632N/A icRaster.getPixelStride() * 4,
4632N/A icRaster.getScanlineStride() * 4,
4632N/A null,
4632N/A iType,
4632N/A offsd.fGraphicsStates,
4632N/A offsd.fGraphicsStatesObject,
4632N/A offsd.fImageInfo);
4632N/A
4632N/A // offsd.checkIfLazyPixelConversionDisabled();
4632N/A offsd.fImageInfoInt.put(kImageStolenIndex, 1);
4632N/A return offsd;
4632N/A }
4632N/A
4632N/A public static SurfaceData createDataIC(BufferedImage bImg, SurfaceType sType) {
4632N/A return createDataIC(bImg, sType, bImg.getType());
4632N/A }
4632N/A
4632N/A private static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm, int iType) {
4632N/A OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);
4632N/A
4632N/A ShortComponentRaster scRaster = (ShortComponentRaster) bImg.getRaster();
4632N/A offsd.initRaster(scRaster.getDataStorage(),
4632N/A scRaster.getDataOffset(0) * 2,
4632N/A scRaster.getWidth(),
4632N/A scRaster.getHeight(),
4632N/A scRaster.getPixelStride() * 2,
4632N/A scRaster.getScanlineStride() * 2,
4632N/A icm,
4632N/A iType,
4632N/A offsd.fGraphicsStates,
4632N/A offsd.fGraphicsStatesObject,
4632N/A offsd.fImageInfo);
4632N/A
4632N/A //offsd.checkIfLazyPixelConversionDisabled();
4632N/A offsd.fImageInfoInt.put(kImageStolenIndex, 1);
4632N/A return offsd;
4632N/A }
4632N/A
4632N/A public static SurfaceData createDataSC(BufferedImage bImg, SurfaceType sType, IndexColorModel icm) {
4632N/A return createDataSC(bImg, sType, icm, bImg.getType());
4632N/A }
4632N/A
4632N/A private static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank, int iType) {
4632N/A OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);
4632N/A
4632N/A ByteComponentRaster bcRaster = (ByteComponentRaster) bImg.getRaster();
4632N/A ColorModel cm = bImg.getColorModel();
4632N/A IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null);
4632N/A offsd.initRaster(bcRaster.getDataStorage(),
4632N/A bcRaster.getDataOffset(primaryBank),
4632N/A bcRaster.getWidth(),
4632N/A bcRaster.getHeight(),
4632N/A bcRaster.getPixelStride(),
4632N/A bcRaster.getScanlineStride(),
4632N/A icm,
4632N/A iType,
4632N/A offsd.fGraphicsStates,
4632N/A offsd.fGraphicsStatesObject,
4632N/A offsd.fImageInfo);
4632N/A
4632N/A offsd.fImageInfoInt.put(kImageStolenIndex, 1);
4632N/A
4632N/A return offsd;
4632N/A }
4632N/A
4632N/A public static SurfaceData createDataBC(BufferedImage bImg, SurfaceType sType, int primaryBank) {
4632N/A return createDataBC(bImg, sType, primaryBank, bImg.getType());
4632N/A }
4632N/A
4632N/A private static SurfaceData createDataBP(BufferedImage bImg, SurfaceType sType, int iType) {
4632N/A OSXOffScreenSurfaceData offsd = new OSXOffScreenSurfaceData(bImg, sType);
4632N/A
4632N/A BytePackedRaster bpRaster = (BytePackedRaster) bImg.getRaster();
4632N/A ColorModel cm = bImg.getColorModel();
4632N/A IndexColorModel icm = ((cm instanceof IndexColorModel) ? (IndexColorModel) cm : null);
4632N/A offsd.initRaster(bpRaster.getDataStorage(),
4632N/A bpRaster.getDataBitOffset(), // in bits, NOT bytes! (needs special attention in native
4632N/A // code!)
4632N/A bpRaster.getWidth(),
4632N/A bpRaster.getHeight(),
4632N/A bpRaster.getPixelBitStride(),
4632N/A bpRaster.getScanlineStride() * 8,
4632N/A icm,
4632N/A iType,
4632N/A offsd.fGraphicsStates,
4632N/A offsd.fGraphicsStatesObject,
4632N/A offsd.fImageInfo);
4632N/A
4632N/A //offsd.checkIfLazyPixelConversionDisabled();
4632N/A offsd.fImageInfoInt.put(kImageStolenIndex, 1);
4632N/A return offsd;
4632N/A }
4632N/A
4632N/A 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);
4632N/A
4632N/A protected native void initCustomRaster(IntBuffer buffer, int width, int height, ByteBuffer graphicsStates, Object graphicsStatesObjects, ByteBuffer imageInfo);
4632N/A
4632N/A public Object getLockObject() {
4632N/A return this.lock;
4632N/A }
4632N/A
4632N/A // Makes the constructor package private instead of public.
4632N/A OSXOffScreenSurfaceData(BufferedImage bufImg, SurfaceType sType) {
4632N/A super(sType, bufImg.getColorModel());
4632N/A setBounds(0, 0, bufImg.getWidth(), bufImg.getHeight());
4632N/A
4632N/A this.bim = bufImg;
4632N/A
4632N/A this.fImageInfo = ByteBuffer.allocateDirect(4 * kSizeOfParameters);
4632N/A this.fImageInfo.order(ByteOrder.nativeOrder());
4632N/A this.fImageInfoInt = this.fImageInfo.asIntBuffer();
4632N/A
4632N/A this.fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // need to sync from Java the very first time
4632N/A this.fImageInfoInt.put(kNativePixelsChangedIndex, 0);
4632N/A this.fImageInfoInt.put(kImageStolenIndex, 0);
4632N/A
4632N/A this.lock = new Object();
4632N/A }
4632N/A
4632N/A /**
4632N/A * Performs a copyArea within this surface.
4632N/A */
4632N/A public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, int dx, int dy) {
4632N/A // <rdar://problem/4488745> For the Sun2D renderer we should rely on the implementation of the super class.
4632N/A // BufImageSurfaceData.java doesn't have an implementation of copyArea() and relies on the super class.
4632N/A
4632N/A int offsetX = 0;
4632N/A int offsetY = 0;
4632N/A if (sg2d.transformState == SunGraphics2D.TRANSFORM_ANY_TRANSLATE ||
4632N/A sg2d.transformState == SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
4632N/A offsetX = (int) sg2d.transform.getTranslateX();
4632N/A offsetY = (int) sg2d.transform.getTranslateY();
4632N/A } else if (sg2d.transformState != SunGraphics2D.TRANSFORM_ISIDENT) { return false; }
4632N/A
4632N/A // reset the clip (this is how it works on windows)
4632N/A // we actually can handle a case with any clips but windows ignores the light clip
4632N/A Shape clip = sg2d.getClip();
4632N/A sg2d.setClip(getBounds());
4632N/A
4632N/A // clip copyArea
4632N/A Rectangle clippedCopyAreaRect = clipCopyArea(sg2d, x, y, w, h, dx, dy);
4632N/A if (clippedCopyAreaRect == null) {
4632N/A // clipped out
4632N/A return true;
4632N/A }
4632N/A
4632N/A // the rectangle returned from clipCopyArea() is in the coordinate space of the surface (image)
4632N/A // we need to substract the offsetX and offsetY to move it to the coordinate space of the graphics2d.
4632N/A // sg2d.drawImage expects the destination rect to be in the coord space of the graphics2d. <rdar://3746194>
4632N/A // (vm)
4632N/A x = clippedCopyAreaRect.x - offsetX;
4632N/A y = clippedCopyAreaRect.y - offsetY;
4632N/A w = clippedCopyAreaRect.width;
4632N/A h = clippedCopyAreaRect.height;
4632N/A
4632N/A // copy (dst coordinates are in the coord space of the graphics2d, and src coordinates are
4632N/A // in the coordinate space of the image)
4632N/A sg2d.drawImage(this.bim, x + dx, y + dy, x + dx + w, y + dy + h, x + offsetX, y + offsetY, x + w + offsetX, y + h + offsetY, null);
4632N/A
4632N/A // restore the clip
4632N/A sg2d.setClip(clip);
4632N/A
4632N/A return true;
4632N/A }
4632N/A
4632N/A /**
4632N/A * Performs a copyarea from this surface to a buffered image. If null is passed in for the image a new image will be
4632N/A * created.
4632N/A *
4632N/A * Only used by compositor code (private API)
4632N/A */
4632N/A public BufferedImage copyArea(SunGraphics2D sg2d, int x, int y, int w, int h, BufferedImage dstImage) {
4632N/A // create the destination image if needed
4632N/A if (dstImage == null) {
4632N/A dstImage = getDeviceConfiguration().createCompatibleImage(w, h);
4632N/A }
4632N/A
4632N/A // copy
4632N/A Graphics g = dstImage.createGraphics();
4632N/A g.drawImage(this.bim, 0, 0, w, h, x, y, x + w, y + h, null);
4632N/A g.dispose();
4632N/A
4632N/A return dstImage;
4632N/A }
4632N/A
4632N/A public boolean xorSurfacePixels(SunGraphics2D sg2d, BufferedImage srcPixels, int x, int y, int w, int h, int colorXOR) {
4632N/A
4632N/A int type = this.bim.getType();
4632N/A
4632N/A 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); }
4632N/A
4632N/A return false;
4632N/A }
4632N/A
4632N/A native boolean xorSurfacePixels(SurfaceData src, int colorXOR, int x, int y, int w, int h);
4632N/A
4632N/A public void clearRect(BufferedImage bim, int w, int h) {
4632N/A OSXOffScreenSurfaceData offsd = (OSXOffScreenSurfaceData) (OSXOffScreenSurfaceData.createData(bim));
4632N/A // offsd.clear();
4632N/A if (offsd.clearSurfacePixels(w, h) == false) {
4632N/A Graphics2D g = bim.createGraphics();
4632N/A g.setComposite(AlphaComposite.Clear);
4632N/A g.fillRect(0, 0, w, h);
4632N/A g.dispose();
4632N/A }
4632N/A }
4632N/A
4632N/A native boolean clearSurfacePixels(int w, int h);
4632N/A
4632N/A // 04/06/04 cmc: radr://3612381 Graphics.drawImage ignores bgcolor parameter.
4632N/A // getCopyWithBgColor returns a new version of an image, drawn with a background
4632N/A // color. Called by blitImage in OSXSurfaceData.java.
4632N/A BufferedImage copyWithBgColor_cache = null;
4632N/A
4632N/A public SurfaceData getCopyWithBgColor(Color bgColor) {
4632N/A int bimW = this.bim.getWidth();
4632N/A int bimH = this.bim.getHeight();
4632N/A
4632N/A if ((this.copyWithBgColor_cache == null)
4632N/A || (this.copyWithBgColor_cache.getWidth() < bimW) || (this.copyWithBgColor_cache.getHeight() < bimH)) {
4632N/A GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
4632N/A this.copyWithBgColor_cache = gc.createCompatibleImage(bimW, bimH);
4632N/A }
4632N/A
4632N/A Graphics g2 = this.copyWithBgColor_cache.createGraphics();
4632N/A g2.setColor(bgColor);
4632N/A g2.fillRect(0, 0, bimW, bimH);
4632N/A g2.drawImage(this.bim, 0, 0, bimW, bimH, null);
4632N/A g2.dispose();
4632N/A
4632N/A return getSurfaceData(this.copyWithBgColor_cache);
4632N/A }
4632N/A
4632N/A /**
4632N/A * Invoked before the raster's contents are to be read (via one of the modifier methods in Raster such as
4632N/A * getPixel())
4632N/A */
4632N/A public void rasterRead() {
4632N/A if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
4632N/A syncToJavaPixels();
4632N/A }
4632N/A }
4632N/A
4632N/A /**
4632N/A * Invoked before the raster's contents are to be written to (via one of the modifier methods in Raster such as
4632N/A * setPixel())
4632N/A */
4632N/A public void rasterWrite() {
4632N/A if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
4632N/A syncToJavaPixels();
4632N/A }
4632N/A
4632N/A fImageInfoInt.put(kNeedToSyncFromJavaPixelsIndex, 1); // the pixels will change
4632N/A }
4632N/A
4632N/A// /**
4632N/A// * Invoked when the raster's contents will be taken (via the Raster.getDataBuffer() method)
4632N/A// */
4632N/A// public void rasterStolen() {
4632N/A// fImageInfoInt.put(kImageStolenIndex, 1); // this means we must convert between Java and native pixels every
4632N/A// // single primitive! (very expensive)
4632N/A// if (fImageInfoInt.get(kNativePixelsChangedIndex) == 1) {
4632N/A// syncToJavaPixels();
4632N/A// }
4632N/A//
4632N/A// // we know the pixels have been stolen, no need to listen for changes any more
4632N/A//// if (this.bufImgSunRaster != null) {
4632N/A//// this.bufImgSunRaster.setRasterListener(null);
4632N/A//// }
4632N/A// }
4632N/A
4632N/A private native void syncToJavaPixels();
4632N/A
4632N/A // we need to refer to rasters often, so cache them
4632N/A void cacheRasters(BufferedImage bim) {
4632N/A this.bufImgRaster = bim.getRaster();
4632N/A if (this.bufImgRaster instanceof SunWritableRaster) {
4632N/A this.bufImgSunRaster = (SunWritableRaster) this.bufImgRaster;
4632N/A }
4632N/A }
4632N/A
4632N/A// void setRasterListener() {
4632N/A// if (this.bufImgSunRaster != null) {
4632N/A// this.bufImgSunRaster.setRasterListener(this);
4632N/A//
4632N/A// Raster parentRaster = this.bufImgSunRaster.getParent();
4632N/A// if (parentRaster != null) {
4632N/A// if (parentRaster instanceof SunWritableRaster) {
4632N/A// // mark subimages stolen to turn off lazy pixel conversion (gznote: can we do better here?)
4632N/A// ((SunWritableRaster) parentRaster).notifyStolen();
4632N/A// }
4632N/A// rasterStolen();
4632N/A// }
4632N/A// } else {
4632N/A// // it's a custom image (non-natively supported) and we can not set a raster listener
4632N/A// // so mark the image as stolen - this will turn off LazyPixelConversion optimization (slow, but correct)
4632N/A// rasterStolen();
4632N/A// }
4632N/A// }
4632N/A}