1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17/** 18 * @author Igor V. Stolyarov 19 * @version $Revision$ 20 * Created on 10.11.2005 21 * 22 */ 23package org.apache.harmony.awt.gl; 24 25import java.awt.color.ColorSpace; 26import java.awt.image.BandedSampleModel; 27import java.awt.image.BufferedImage; 28import java.awt.image.ColorModel; 29import java.awt.image.ComponentColorModel; 30import java.awt.image.ComponentSampleModel; 31import java.awt.image.DirectColorModel; 32import java.awt.image.IndexColorModel; 33import java.awt.image.MultiPixelPackedSampleModel; 34import java.awt.image.PixelInterleavedSampleModel; 35import java.awt.image.SampleModel; 36import java.awt.image.SinglePixelPackedSampleModel; 37import java.awt.image.WritableRaster; 38 39import org.apache.harmony.awt.gl.color.LUTColorConverter; 40import org.apache.harmony.awt.gl.image.DataBufferListener; 41import org.apache.harmony.awt.internal.nls.Messages; 42 43 44/** 45 * This class represent Surface for different types of Images (BufferedImage, 46 * OffscreenImage and so on) 47 */ 48public class ImageSurface extends Surface implements DataBufferListener { 49 50 boolean nativeDrawable = true; 51 int surfaceType; 52 int csType; 53 ColorModel cm; 54 WritableRaster raster; 55 Object data; 56 57 boolean needToRefresh = true; 58 boolean dataTaken = false; 59 60 private long cachedDataPtr; // Pointer for cached Image Data 61 private boolean alphaPre; // Cached Image Data alpha premultiplied 62 63 public ImageSurface(ColorModel cm, WritableRaster raster){ 64 this(cm, raster, Surface.getType(cm, raster)); 65 } 66 67 public ImageSurface(ColorModel cm, WritableRaster raster, int type){ 68 if (!cm.isCompatibleRaster(raster)) { 69 // awt.4D=The raster is incompatible with this ColorModel 70 throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ 71 } 72 this.cm = cm; 73 this.raster = raster; 74 surfaceType = type; 75 76 data = AwtImageBackdoorAccessor.getInstance(). 77 getData(raster.getDataBuffer()); 78 ColorSpace cs = cm.getColorSpace(); 79 transparency = cm.getTransparency(); 80 width = raster.getWidth(); 81 height = raster.getHeight(); 82 83 // For the moment we can build natively only images which have 84 // sRGB, Linear_RGB, Linear_Gray Color Space and type different 85 // from BufferedImage.TYPE_CUSTOM 86 if(cs == LUTColorConverter.sRGB_CS){ 87 csType = sRGB_CS; 88 }else if(cs == LUTColorConverter.LINEAR_RGB_CS){ 89 csType = Linear_RGB_CS; 90 }else if(cs == LUTColorConverter.LINEAR_GRAY_CS){ 91 csType = Linear_Gray_CS; 92 }else{ 93 csType = Custom_CS; 94 nativeDrawable = false; 95 } 96 97 if(type == BufferedImage.TYPE_CUSTOM){ 98 nativeDrawable = false; 99 } 100 } 101 102 @Override 103 public ColorModel getColorModel() { 104 return cm; 105 } 106 107 @Override 108 public WritableRaster getRaster() { 109 return raster; 110 } 111 112 @Override 113 public long getSurfaceDataPtr() { 114 if(surfaceDataPtr == 0L && nativeDrawable){ 115 createSufaceStructure(); 116 } 117 return surfaceDataPtr; 118 } 119 120 @Override 121 public Object getData(){ 122 return data; 123 } 124 125 @Override 126 public boolean isNativeDrawable(){ 127 return nativeDrawable; 128 } 129 130 @Override 131 public int getSurfaceType() { 132 return surfaceType; 133 } 134 135 /** 136 * Creates native Surface structure which used for native blitting 137 */ 138 private void createSufaceStructure(){ 139 int cmType = 0; 140 int numComponents = cm.getNumComponents(); 141 boolean hasAlpha = cm.hasAlpha(); 142 boolean isAlphaPre = cm.isAlphaPremultiplied(); 143 int transparency = cm.getTransparency(); 144 int bits[] = cm.getComponentSize(); 145 int pixelStride = cm.getPixelSize(); 146 int masks[] = null; 147 int colorMap[] = null; 148 int colorMapSize = 0; 149 int transpPixel = -1; 150 boolean isGrayPallete = false; 151 SampleModel sm = raster.getSampleModel(); 152 int smType = 0; 153 int dataType = sm.getDataType(); 154 int scanlineStride = 0; 155 int bankIndeces[] = null; 156 int bandOffsets[] = null; 157 int offset = raster.getDataBuffer().getOffset(); 158 159 if(cm instanceof DirectColorModel){ 160 cmType = DCM; 161 DirectColorModel dcm = (DirectColorModel) cm; 162 masks = dcm.getMasks(); 163 smType = SPPSM; 164 SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm; 165 scanlineStride = sppsm.getScanlineStride(); 166 167 }else if(cm instanceof IndexColorModel){ 168 cmType = ICM; 169 IndexColorModel icm = (IndexColorModel) cm; 170 colorMapSize = icm.getMapSize(); 171 colorMap = new int[colorMapSize]; 172 icm.getRGBs(colorMap); 173 transpPixel = icm.getTransparentPixel(); 174 isGrayPallete = Surface.isGrayPallete(icm); 175 176 if(sm instanceof MultiPixelPackedSampleModel){ 177 smType = MPPSM; 178 MultiPixelPackedSampleModel mppsm = 179 (MultiPixelPackedSampleModel) sm; 180 scanlineStride = mppsm.getScanlineStride(); 181 }else if(sm instanceof ComponentSampleModel){ 182 smType = CSM; 183 ComponentSampleModel csm = 184 (ComponentSampleModel) sm; 185 scanlineStride = csm.getScanlineStride(); 186 }else{ 187 // awt.4D=The raster is incompatible with this ColorModel 188 throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ 189 } 190 191 }else if(cm instanceof ComponentColorModel){ 192 cmType = CCM; 193 if(sm instanceof ComponentSampleModel){ 194 ComponentSampleModel csm = (ComponentSampleModel) sm; 195 scanlineStride = csm.getScanlineStride(); 196 bankIndeces = csm.getBankIndices(); 197 bandOffsets = csm.getBandOffsets(); 198 if(sm instanceof PixelInterleavedSampleModel){ 199 smType = PISM; 200 }else if(sm instanceof BandedSampleModel){ 201 smType = BSM; 202 }else{ 203 smType = CSM; 204 } 205 }else{ 206 // awt.4D=The raster is incompatible with this ColorModel 207 throw new IllegalArgumentException(Messages.getString("awt.4D")); //$NON-NLS-1$ 208 } 209 210 }else{ 211 surfaceDataPtr = 0L; 212 return; 213 } 214 surfaceDataPtr = createSurfStruct(surfaceType, width, height, cmType, csType, smType, dataType, 215 numComponents, pixelStride, scanlineStride, bits, masks, colorMapSize, 216 colorMap, transpPixel, isGrayPallete, bankIndeces, bandOffsets, 217 offset, hasAlpha, isAlphaPre, transparency); 218 } 219 220 @Override 221 public void dispose() { 222 if(surfaceDataPtr != 0L){ 223 dispose(surfaceDataPtr); 224 surfaceDataPtr = 0L; 225 } 226 } 227 228 public long getCachedData(boolean alphaPre){ 229 if(nativeDrawable){ 230 if(cachedDataPtr == 0L || needToRefresh || this.alphaPre != alphaPre){ 231 cachedDataPtr = updateCache(getSurfaceDataPtr(), data, alphaPre); 232 this.alphaPre = alphaPre; 233 validate(); 234 } 235 } 236 return cachedDataPtr; 237 } 238 239 private native long createSurfStruct(int surfaceType, int width, int height, 240 int cmType, int csType, int smType, int dataType, 241 int numComponents, int pixelStride, int scanlineStride, 242 int bits[], int masks[], int colorMapSize, int colorMap[], 243 int transpPixel, boolean isGrayPalette, int bankIndeces[], 244 int bandOffsets[], int offset, boolean hasAlpha, boolean isAlphaPre, 245 int transparency); 246 247 private native void dispose(long structPtr); 248 249 private native void setImageSize(long structPtr, int width, int height); 250 251 private native long updateCache(long structPtr, Object data, boolean alphaPre); 252 253 /** 254 * Supposes that new raster is compatible with an old one 255 * @param r 256 */ 257 public void setRaster(WritableRaster r) { 258 raster = r; 259 data = AwtImageBackdoorAccessor.getInstance().getData(r.getDataBuffer()); 260 if (surfaceDataPtr != 0) { 261 setImageSize(surfaceDataPtr, r.getWidth(), r.getHeight()); 262 } 263 this.width = r.getWidth(); 264 this.height = r.getHeight(); 265 } 266 267 @Override 268 public long lock() { 269 // TODO 270 return 0; 271 } 272 273 @Override 274 public void unlock() { 275 //TODO 276 } 277 278 @Override 279 public Surface getImageSurface() { 280 return this; 281 } 282 283 public void dataChanged() { 284 needToRefresh = true; 285 clearValidCaches(); 286 } 287 288 public void dataTaken() { 289 dataTaken = true; 290 needToRefresh = true; 291 clearValidCaches(); 292 } 293 294 public void dataReleased(){ 295 dataTaken = false; 296 needToRefresh = true; 297 clearValidCaches(); 298 } 299 300 @Override 301 public void invalidate(){ 302 needToRefresh = true; 303 clearValidCaches(); 304 } 305 306 @Override 307 public void validate(){ 308 if(!needToRefresh) { 309 return; 310 } 311 if(!dataTaken){ 312 needToRefresh = false; 313 AwtImageBackdoorAccessor ba = AwtImageBackdoorAccessor.getInstance(); 314 ba.validate(raster.getDataBuffer()); 315 } 316 317 } 318 319 @Override 320 public boolean invalidated(){ 321 return needToRefresh; 322 } 323} 324