| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| /** |
| * @author Igor V. Stolyarov |
| * @version $Revision$ |
| * Created on 10.11.2005 |
| * |
| */ |
| package org.apache.harmony.awt.gl; |
| |
| import java.awt.color.ColorSpace; |
| import java.awt.image.BandedSampleModel; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ColorModel; |
| import java.awt.image.ComponentColorModel; |
| import java.awt.image.ComponentSampleModel; |
| import java.awt.image.DirectColorModel; |
| import java.awt.image.IndexColorModel; |
| import java.awt.image.MultiPixelPackedSampleModel; |
| import java.awt.image.PixelInterleavedSampleModel; |
| import java.awt.image.SampleModel; |
| import java.awt.image.SinglePixelPackedSampleModel; |
| import java.awt.image.WritableRaster; |
| |
| import org.apache.harmony.awt.gl.color.LUTColorConverter; |
| import org.apache.harmony.awt.gl.image.DataBufferListener; |
| import org.apache.harmony.awt.internal.nls.Messages; |
| |
| |
| /** |
| * This class represent Surface for different types of Images (BufferedImage, |
| * OffscreenImage and so on) |
| */ |
| public class ImageSurface extends Surface implements DataBufferListener { |
| |
| boolean nativeDrawable = true; |
| int surfaceType; |
| int csType; |
| ColorModel cm; |
| WritableRaster raster; |
| Object data; |
| |
| boolean needToRefresh = true; |
| boolean dataTaken = false; |
| |
| private long cachedDataPtr; // Pointer for cached Image Data |
| private boolean alphaPre; // Cached Image Data alpha premultiplied |
| |
| public ImageSurface(ColorModel cm, WritableRaster raster){ |
| this(cm, raster, Surface.getType(cm, raster)); |
| } |
| |
| public ImageSurface(ColorModel cm, WritableRaster raster, int type){ |
| if (!cm.isCompatibleRaster(raster)) { |
| // awt.4D=The raster is incompatible with this ColorModel |
| throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ |
| } |
| this.cm = cm; |
| this.raster = raster; |
| surfaceType = type; |
| |
| data = AwtImageBackdoorAccessor.getInstance(). |
| getData(raster.getDataBuffer()); |
| ColorSpace cs = cm.getColorSpace(); |
| transparency = cm.getTransparency(); |
| width = raster.getWidth(); |
| height = raster.getHeight(); |
| |
| // For the moment we can build natively only images which have |
| // sRGB, Linear_RGB, Linear_Gray Color Space and type different |
| // from BufferedImage.TYPE_CUSTOM |
| if(cs == LUTColorConverter.sRGB_CS){ |
| csType = sRGB_CS; |
| }else if(cs == LUTColorConverter.LINEAR_RGB_CS){ |
| csType = Linear_RGB_CS; |
| }else if(cs == LUTColorConverter.LINEAR_GRAY_CS){ |
| csType = Linear_Gray_CS; |
| }else{ |
| csType = Custom_CS; |
| nativeDrawable = false; |
| } |
| |
| if(type == BufferedImage.TYPE_CUSTOM){ |
| nativeDrawable = false; |
| } |
| } |
| |
| @Override |
| public ColorModel getColorModel() { |
| return cm; |
| } |
| |
| @Override |
| public WritableRaster getRaster() { |
| return raster; |
| } |
| |
| @Override |
| public long getSurfaceDataPtr() { |
| if(surfaceDataPtr == 0L && nativeDrawable){ |
| createSufaceStructure(); |
| } |
| return surfaceDataPtr; |
| } |
| |
| @Override |
| public Object getData(){ |
| return data; |
| } |
| |
| @Override |
| public boolean isNativeDrawable(){ |
| return nativeDrawable; |
| } |
| |
| @Override |
| public int getSurfaceType() { |
| return surfaceType; |
| } |
| |
| /** |
| * Creates native Surface structure which used for native blitting |
| */ |
| private void createSufaceStructure(){ |
| int cmType = 0; |
| int numComponents = cm.getNumComponents(); |
| boolean hasAlpha = cm.hasAlpha(); |
| boolean isAlphaPre = cm.isAlphaPremultiplied(); |
| int transparency = cm.getTransparency(); |
| int bits[] = cm.getComponentSize(); |
| int pixelStride = cm.getPixelSize(); |
| int masks[] = null; |
| int colorMap[] = null; |
| int colorMapSize = 0; |
| int transpPixel = -1; |
| boolean isGrayPallete = false; |
| SampleModel sm = raster.getSampleModel(); |
| int smType = 0; |
| int dataType = sm.getDataType(); |
| int scanlineStride = 0; |
| int bankIndeces[] = null; |
| int bandOffsets[] = null; |
| int offset = raster.getDataBuffer().getOffset(); |
| |
| if(cm instanceof DirectColorModel){ |
| cmType = DCM; |
| DirectColorModel dcm = (DirectColorModel) cm; |
| masks = dcm.getMasks(); |
| smType = SPPSM; |
| SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm; |
| scanlineStride = sppsm.getScanlineStride(); |
| |
| }else if(cm instanceof IndexColorModel){ |
| cmType = ICM; |
| IndexColorModel icm = (IndexColorModel) cm; |
| colorMapSize = icm.getMapSize(); |
| colorMap = new int[colorMapSize]; |
| icm.getRGBs(colorMap); |
| transpPixel = icm.getTransparentPixel(); |
| isGrayPallete = Surface.isGrayPallete(icm); |
| |
| if(sm instanceof MultiPixelPackedSampleModel){ |
| smType = MPPSM; |
| MultiPixelPackedSampleModel mppsm = |
| (MultiPixelPackedSampleModel) sm; |
| scanlineStride = mppsm.getScanlineStride(); |
| }else if(sm instanceof ComponentSampleModel){ |
| smType = CSM; |
| ComponentSampleModel csm = |
| (ComponentSampleModel) sm; |
| scanlineStride = csm.getScanlineStride(); |
| }else{ |
| // awt.4D=The raster is incompatible with this ColorModel |
| throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ |
| } |
| |
| }else if(cm instanceof ComponentColorModel){ |
| cmType = CCM; |
| if(sm instanceof ComponentSampleModel){ |
| ComponentSampleModel csm = (ComponentSampleModel) sm; |
| scanlineStride = csm.getScanlineStride(); |
| bankIndeces = csm.getBankIndices(); |
| bandOffsets = csm.getBandOffsets(); |
| if(sm instanceof PixelInterleavedSampleModel){ |
| smType = PISM; |
| }else if(sm instanceof BandedSampleModel){ |
| smType = BSM; |
| }else{ |
| smType = CSM; |
| } |
| }else{ |
| // awt.4D=The raster is incompatible with this ColorModel |
| throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ |
| } |
| |
| }else{ |
| surfaceDataPtr = 0L; |
| return; |
| } |
| surfaceDataPtr = createSurfStruct(surfaceType, width, height, cmType, csType, smType, dataType, |
| numComponents, pixelStride, scanlineStride, bits, masks, colorMapSize, |
| colorMap, transpPixel, isGrayPallete, bankIndeces, bandOffsets, |
| offset, hasAlpha, isAlphaPre, transparency); |
| } |
| |
| @Override |
| public void dispose() { |
| if(surfaceDataPtr != 0L){ |
| dispose(surfaceDataPtr); |
| surfaceDataPtr = 0L; |
| } |
| } |
| |
| public long getCachedData(boolean alphaPre){ |
| if(nativeDrawable){ |
| if(cachedDataPtr == 0L || needToRefresh || this.alphaPre != alphaPre){ |
| cachedDataPtr = updateCache(getSurfaceDataPtr(), data, alphaPre); |
| this.alphaPre = alphaPre; |
| validate(); |
| } |
| } |
| return cachedDataPtr; |
| } |
| |
| private native long createSurfStruct(int surfaceType, int width, int height, |
| int cmType, int csType, int smType, int dataType, |
| int numComponents, int pixelStride, int scanlineStride, |
| int bits[], int masks[], int colorMapSize, int colorMap[], |
| int transpPixel, boolean isGrayPalette, int bankIndeces[], |
| int bandOffsets[], int offset, boolean hasAlpha, boolean isAlphaPre, |
| int transparency); |
| |
| private native void dispose(long structPtr); |
| |
| private native void setImageSize(long structPtr, int width, int height); |
| |
| private native long updateCache(long structPtr, Object data, boolean alphaPre); |
| |
| /** |
| * Supposes that new raster is compatible with an old one |
| * @param r |
| */ |
| public void setRaster(WritableRaster r) { |
| raster = r; |
| data = AwtImageBackdoorAccessor.getInstance().getData(r.getDataBuffer()); |
| if (surfaceDataPtr != 0) { |
| setImageSize(surfaceDataPtr, r.getWidth(), r.getHeight()); |
| } |
| this.width = r.getWidth(); |
| this.height = r.getHeight(); |
| } |
| |
| @Override |
| public long lock() { |
| // TODO |
| return 0; |
| } |
| |
| @Override |
| public void unlock() { |
| //TODO |
| } |
| |
| @Override |
| public Surface getImageSurface() { |
| return this; |
| } |
| |
| public void dataChanged() { |
| needToRefresh = true; |
| clearValidCaches(); |
| } |
| |
| public void dataTaken() { |
| dataTaken = true; |
| needToRefresh = true; |
| clearValidCaches(); |
| } |
| |
| public void dataReleased(){ |
| dataTaken = false; |
| needToRefresh = true; |
| clearValidCaches(); |
| } |
| |
| @Override |
| public void invalidate(){ |
| needToRefresh = true; |
| clearValidCaches(); |
| } |
| |
| @Override |
| public void validate(){ |
| if(!needToRefresh) { |
| return; |
| } |
| if(!dataTaken){ |
| needToRefresh = false; |
| AwtImageBackdoorAccessor ba = AwtImageBackdoorAccessor.getInstance(); |
| ba.validate(raster.getDataBuffer()); |
| } |
| |
| } |
| |
| @Override |
| public boolean invalidated(){ |
| return needToRefresh; |
| } |
| } |