001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Igor V. Stolyarov
019: * @version $Revision$
020: * Created on 10.11.2005
021: *
022: */package org.apache.harmony.awt.gl;
023:
024: import java.awt.Rectangle;
025: import java.awt.color.ColorSpace;
026: import java.awt.image.BandedSampleModel;
027: import java.awt.image.BufferedImage;
028: import java.awt.image.ColorModel;
029: import java.awt.image.ComponentColorModel;
030: import java.awt.image.ComponentSampleModel;
031: import java.awt.image.DataBuffer;
032: import java.awt.image.DirectColorModel;
033: import java.awt.image.IndexColorModel;
034: import java.awt.image.MultiPixelPackedSampleModel;
035: import java.awt.image.PixelInterleavedSampleModel;
036: import java.awt.image.SampleModel;
037: import java.awt.image.SinglePixelPackedSampleModel;
038: import java.awt.image.WritableRaster;
039:
040: import org.apache.harmony.awt.gl.color.LUTColorConverter;
041: import org.apache.harmony.awt.gl.image.DataBufferListener;
042: import org.apache.harmony.awt.internal.nls.Messages;
043:
044: /**
045: * This class represent Surface for different types of Images (BufferedImage,
046: * OffscreenImage and so on)
047: */
048: public class ImageSurface extends Surface implements DataBufferListener {
049:
050: boolean nativeDrawable = true;
051: int surfaceType;
052: int csType;
053: ColorModel cm;
054: WritableRaster raster;
055: Object data;
056:
057: boolean needToRefresh = true;
058: boolean dataTaken = false;
059:
060: private long cachedDataPtr; // Pointer for cached Image Data
061: private boolean alphaPre; // Cached Image Data alpha premultiplied
062:
063: AwtImageBackdoorAccessor ba = AwtImageBackdoorAccessor
064: .getInstance();
065:
066: public ImageSurface(ColorModel cm, WritableRaster raster) {
067: this (cm, raster, Surface.getType(cm, raster));
068: }
069:
070: public ImageSurface(ColorModel cm, WritableRaster raster, int type) {
071: if (!cm.isCompatibleRaster(raster)) {
072: // awt.4D=The raster is incompatible with this ColorModel
073: throw new IllegalArgumentException(Messages
074: .getString("awt.4D")); //$NON-NLS-1$
075: }
076: this .cm = cm;
077: this .raster = raster;
078: surfaceType = type;
079:
080: DataBuffer db = raster.getDataBuffer();
081: data = ba.getData(db);
082: ba.addDataBufferListener(db, this );
083: ColorSpace cs = cm.getColorSpace();
084: transparency = cm.getTransparency();
085: width = raster.getWidth();
086: height = raster.getHeight();
087: addDirtyRegion(new Rectangle(0, 0, width, height));
088:
089: // For the moment we can build natively only images which have
090: // sRGB, Linear_RGB, Linear_Gray Color Space and type different
091: // from BufferedImage.TYPE_CUSTOM
092: if (cs == LUTColorConverter.sRGB_CS) {
093: csType = sRGB_CS;
094: } else if (cs == LUTColorConverter.LINEAR_RGB_CS) {
095: csType = Linear_RGB_CS;
096: } else if (cs == LUTColorConverter.LINEAR_GRAY_CS) {
097: csType = Linear_Gray_CS;
098: } else {
099: csType = Custom_CS;
100: nativeDrawable = false;
101: }
102:
103: if (type == BufferedImage.TYPE_CUSTOM) {
104: nativeDrawable = false;
105: }
106:
107: }
108:
109: @Override
110: public ColorModel getColorModel() {
111: return cm;
112: }
113:
114: @Override
115: public WritableRaster getRaster() {
116: return raster;
117: }
118:
119: @Override
120: public long getSurfaceDataPtr() {
121: if (surfaceDataPtr == 0L && nativeDrawable) {
122: createSufaceStructure();
123: }
124: return surfaceDataPtr;
125: }
126:
127: @Override
128: public Object getData() {
129: return data;
130: }
131:
132: @Override
133: public boolean isNativeDrawable() {
134: return nativeDrawable;
135: }
136:
137: @Override
138: public int getSurfaceType() {
139: return surfaceType;
140: }
141:
142: /**
143: * Creates native Surface structure which used for native blitting
144: */
145: private void createSufaceStructure() {
146: int cmType = 0;
147: int numComponents = cm.getNumComponents();
148: boolean hasAlpha = cm.hasAlpha();
149: boolean isAlphaPre = cm.isAlphaPremultiplied();
150: int transparency = cm.getTransparency();
151: int bits[] = cm.getComponentSize();
152: int pixelStride = cm.getPixelSize();
153: int masks[] = null;
154: int colorMap[] = null;
155: int colorMapSize = 0;
156: int transpPixel = -1;
157: boolean isGrayPallete = false;
158: SampleModel sm = raster.getSampleModel();
159: int smType = 0;
160: int dataType = sm.getDataType();
161: int scanlineStride = 0;
162: int bankIndeces[] = null;
163: int bandOffsets[] = null;
164: int offset = raster.getDataBuffer().getOffset();
165:
166: if (cm instanceof DirectColorModel) {
167: cmType = DCM;
168: DirectColorModel dcm = (DirectColorModel) cm;
169: masks = dcm.getMasks();
170: smType = SPPSM;
171: SinglePixelPackedSampleModel sppsm = (SinglePixelPackedSampleModel) sm;
172: scanlineStride = sppsm.getScanlineStride();
173:
174: } else if (cm instanceof IndexColorModel) {
175: cmType = ICM;
176: IndexColorModel icm = (IndexColorModel) cm;
177: colorMapSize = icm.getMapSize();
178: colorMap = new int[colorMapSize];
179: icm.getRGBs(colorMap);
180: transpPixel = icm.getTransparentPixel();
181: isGrayPallete = Surface.isGrayPallete(icm);
182:
183: if (sm instanceof MultiPixelPackedSampleModel) {
184: smType = MPPSM;
185: MultiPixelPackedSampleModel mppsm = (MultiPixelPackedSampleModel) sm;
186: scanlineStride = mppsm.getScanlineStride();
187: } else if (sm instanceof ComponentSampleModel) {
188: smType = CSM;
189: ComponentSampleModel csm = (ComponentSampleModel) sm;
190: scanlineStride = csm.getScanlineStride();
191: } else {
192: // awt.4D=The raster is incompatible with this ColorModel
193: throw new IllegalArgumentException(Messages
194: .getString("awt.4D")); //$NON-NLS-1$
195: }
196:
197: } else if (cm instanceof ComponentColorModel) {
198: cmType = CCM;
199: if (sm instanceof ComponentSampleModel) {
200: ComponentSampleModel csm = (ComponentSampleModel) sm;
201: scanlineStride = csm.getScanlineStride();
202: bankIndeces = csm.getBankIndices();
203: bandOffsets = csm.getBandOffsets();
204: if (sm instanceof PixelInterleavedSampleModel) {
205: smType = PISM;
206: } else if (sm instanceof BandedSampleModel) {
207: smType = BSM;
208: } else {
209: smType = CSM;
210: }
211: } else {
212: // awt.4D=The raster is incompatible with this ColorModel
213: throw new IllegalArgumentException(Messages
214: .getString("awt.4D")); //$NON-NLS-1$
215: }
216:
217: } else {
218: surfaceDataPtr = 0L;
219: return;
220: }
221: surfaceDataPtr = createSurfStruct(surfaceType, width, height,
222: cmType, csType, smType, dataType, numComponents,
223: pixelStride, scanlineStride, bits, masks, colorMapSize,
224: colorMap, transpPixel, isGrayPallete, bankIndeces,
225: bandOffsets, offset, hasAlpha, isAlphaPre, transparency);
226: }
227:
228: @Override
229: public synchronized void dispose() {
230: ba.removeDataBufferListener(raster.getDataBuffer());
231: if (surfaceDataPtr != 0L) {
232: dispose(surfaceDataPtr);
233: surfaceDataPtr = 0L;
234: }
235: }
236:
237: public long getCachedData(boolean alphaPre) {
238: if (nativeDrawable) {
239: if (cachedDataPtr == 0L || needToRefresh
240: || this .alphaPre != alphaPre) {
241: cachedDataPtr = updateCache(getSurfaceDataPtr(), data,
242: alphaPre);
243: this .alphaPre = alphaPre;
244: validate();
245: }
246: }
247: return cachedDataPtr;
248: }
249:
250: private native long createSurfStruct(int surfaceType, int width,
251: int height, int cmType, int csType, int smType,
252: int dataType, int numComponents, int pixelStride,
253: int scanlineStride, int bits[], int masks[],
254: int colorMapSize, int colorMap[], int transpPixel,
255: boolean isGrayPalette, int bankIndeces[],
256: int bandOffsets[], int offset, boolean hasAlpha,
257: boolean isAlphaPre, int transparency);
258:
259: private native void dispose(long structPtr);
260:
261: private native void setImageSize(long structPtr, int width,
262: int height);
263:
264: private native long updateCache(long structPtr, Object data,
265: boolean alphaPre);
266:
267: /**
268: * Supposes that new raster is compatible with an old one
269: * @param r
270: */
271: public void setRaster(WritableRaster r) {
272: raster = r;
273: DataBuffer db = r.getDataBuffer();
274: data = ba.getData(db);
275: ba.addDataBufferListener(db, this );
276: if (surfaceDataPtr != 0) {
277: setImageSize(surfaceDataPtr, r.getWidth(), r.getHeight());
278: }
279: this .width = r.getWidth();
280: this .height = r.getHeight();
281: }
282:
283: @Override
284: public long lock() {
285: // TODO
286: return 0;
287: }
288:
289: @Override
290: public void unlock() {
291: //TODO
292: }
293:
294: @Override
295: public Surface getImageSurface() {
296: return this ;
297: }
298:
299: public void dataChanged() {
300: needToRefresh = true;
301: clearValidCaches();
302: }
303:
304: public void dataTaken() {
305: dataTaken = true;
306: needToRefresh = true;
307: clearValidCaches();
308: }
309:
310: public void dataReleased() {
311: dataTaken = false;
312: needToRefresh = true;
313: clearValidCaches();
314: }
315:
316: @Override
317: public void invalidate() {
318: needToRefresh = true;
319: clearValidCaches();
320: }
321:
322: @Override
323: public void validate() {
324: if (!needToRefresh) {
325: return;
326: }
327: if (!dataTaken) {
328: needToRefresh = false;
329: AwtImageBackdoorAccessor ba = AwtImageBackdoorAccessor
330: .getInstance();
331: ba.validate(raster.getDataBuffer());
332: }
333: releaseDurtyRegions();
334:
335: }
336:
337: @Override
338: public boolean invalidated() {
339: return needToRefresh | dataTaken;
340: }
341: }
|