OSDN Git Service

auto import from //depot/cupcake/@135843
[android-x86/frameworks-native.git] / awt / org / apache / harmony / awt / gl / image / OffscreenImage.java
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  */
21 /*
22  * Created on 22.12.2004
23  *
24  */
25 package org.apache.harmony.awt.gl.image;
26
27 import java.awt.Graphics;
28 import java.awt.Image;
29 import java.awt.image.BufferedImage;
30 import java.awt.image.ColorModel;
31 import java.awt.image.ComponentColorModel;
32 import java.awt.image.DataBuffer;
33 import java.awt.image.DataBufferByte;
34 import java.awt.image.DataBufferInt;
35 import java.awt.image.DirectColorModel;
36 import java.awt.image.ImageConsumer;
37 import java.awt.image.ImageObserver;
38 import java.awt.image.ImageProducer;
39 import java.awt.image.IndexColorModel;
40 import java.awt.image.WritableRaster;
41 import java.util.Hashtable;
42 import java.util.Vector;
43
44 import org.apache.harmony.awt.gl.ImageSurface;
45 import org.apache.harmony.awt.internal.nls.Messages;
46
47
48 /**
49  * This class represent implementation of abstract Image class
50  */
51 public class OffscreenImage extends Image implements ImageConsumer {
52
53     static final ColorModel rgbCM = ColorModel.getRGBdefault();
54     ImageProducer src;
55     BufferedImage image;
56     ColorModel cm;
57     WritableRaster raster;
58     boolean isIntRGB;
59     Hashtable<?, ?> properties;
60     Vector<ImageObserver> observers;
61     int width;
62     int height;
63     int imageState;
64     int hints;
65     private boolean producing;
66     private ImageSurface imageSurf;
67
68     public OffscreenImage(ImageProducer ip){
69         imageState = 0;
70         src = ip;
71         width = -1;
72         height = -1;
73         observers = new Vector<ImageObserver>();
74         producing = false;
75     }
76
77     @Override
78     public Object getProperty(String name, ImageObserver observer) {
79         if(name == null) {
80             // awt.38=Property name is not defined
81             throw new NullPointerException(Messages.getString("awt.38")); //$NON-NLS-1$
82         }
83         if(properties == null){
84             addObserver(observer);
85             startProduction();
86             if(properties == null) {
87                 return null;
88             }
89         }
90         Object prop = properties.get(name);
91         if(prop == null) {
92             prop = UndefinedProperty;
93         }
94         return prop;
95     }
96
97     @Override
98     public ImageProducer getSource() {
99         return src;
100     }
101
102     @Override
103     public int getWidth(ImageObserver observer) {
104         if((imageState & ImageObserver.WIDTH) == 0){
105             addObserver(observer);
106             startProduction();
107             if((imageState & ImageObserver.WIDTH) == 0) {
108                 return -1;
109             }
110         }
111         return width;
112     }
113
114     @Override
115     public int getHeight(ImageObserver observer) {
116         if((imageState & ImageObserver.HEIGHT) == 0){
117             addObserver(observer);
118             startProduction();
119             if((imageState & ImageObserver.HEIGHT) == 0) {
120                 return -1;
121             }
122         }
123         return height;
124     }
125
126     @Override
127     public Graphics getGraphics() {
128         // awt.39=This method is not implemented for image obtained from ImageProducer
129         throw new UnsupportedOperationException(Messages.getString("awt.39")); //$NON-NLS-1$
130     }
131
132     @Override
133     public void flush() {
134         stopProduction();
135         imageUpdate(this, ImageObserver.ABORT, -1, -1, -1, -1);
136         imageState &= ~ImageObserver.ERROR;
137         imageState = 0;
138         image = null;
139         cm = null;
140         raster = null;
141         hints = 0;
142         width = -1;
143         height = -1;
144     }
145
146     public void setProperties(Hashtable<?, ?> properties) {
147         this.properties = properties;
148         imageUpdate(this, ImageObserver.PROPERTIES, 0, 0, width, height);
149     }
150
151     public void setColorModel(ColorModel cm) {
152         this.cm = cm;
153     }
154
155     /*
156      * We suppose what in case loading JPEG image then image has DirectColorModel
157      * and for infill image Raster will use setPixels method with int array.
158      *
159      * In case loading GIF image, for raster infill, is used setPixels method with
160      * byte array and Color Model is IndexColorModel. But Color Model may
161      * be changed during this process. Then is called setPixels method with
162      * int array and image force to default color model - int ARGB. The rest
163      * pixels are sending in DirectColorModel.
164      */
165     public void setPixels(int x, int y, int w, int h, ColorModel model,
166             int[] pixels, int off, int scansize) {
167         if(raster == null){
168             if(cm == null){
169                 if(model == null) {
170                     // awt.3A=Color Model is null
171                     throw new NullPointerException(Messages.getString("awt.3A")); //$NON-NLS-1$
172                 }
173                 cm = model;
174             }
175             createRaster();
176         }
177
178         if(model == null) {
179             model = cm;
180         }
181         if(cm != model){
182             forceToIntARGB();
183         }
184
185         if(cm == model && model.getTransferType() == DataBuffer.TYPE_INT &&
186                 raster.getNumDataElements() == 1){
187
188             DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer();
189             int data[] = dbi.getData();
190             int scanline = raster.getWidth();
191             int rof = dbi.getOffset() + y * scanline + x;
192             for(int lineOff = off, line = y; line < y + h;
193                 line++, lineOff += scansize, rof += scanline){
194
195                 System.arraycopy(pixels, lineOff, data, rof, w);
196             }
197
198         }else if(isIntRGB){
199             int buff[] = new int[w];
200             DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer();
201             int data[] = dbi.getData();
202             int scanline = raster.getWidth();
203             int rof = dbi.getOffset() + y * scanline + x;
204             for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize,
205                 rof += scanline) {
206
207                 for (int sx = x, idx = 0; sx < x + w; sx++, idx++) {
208                     buff[idx] = model.getRGB(pixels[sOff + idx]);
209                 }
210                 System.arraycopy(buff, 0, data, rof, w);
211             }
212         }else{
213             Object buf = null;
214             for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) {
215                 for (int sx = x, idx = 0; sx < x + w; sx++, idx++) {
216                     int rgb = model.getRGB(pixels[sOff + idx]);
217                     buf = cm.getDataElements(rgb, buf);
218                     raster.setDataElements(sx, sy, buf);
219                 }
220             }
221         }
222
223         if (imageSurf != null) {
224             imageSurf.invalidate();
225         }
226
227         imageUpdate(this, ImageObserver.SOMEBITS, 0, 0, width, height);
228     }
229
230     public void setPixels(int x, int y, int w, int h, ColorModel model,
231             byte[] pixels, int off, int scansize) {
232
233         if(raster == null){
234             if(cm == null){
235                 if(model == null) {
236                     // awt.3A=Color Model is null
237                     throw new NullPointerException(Messages.getString("awt.3A")); //$NON-NLS-1$
238                 }
239                 cm = model;
240             }
241             createRaster();
242         }
243         if(model == null) {
244             model = cm;
245         }
246         if(model != cm){
247             forceToIntARGB();
248         }
249
250         if(isIntRGB){
251             int buff[] = new int[w];
252             IndexColorModel icm = (IndexColorModel) model;
253             int colorMap[] = new int[icm.getMapSize()];
254             icm.getRGBs(colorMap);
255             DataBufferInt dbi = (DataBufferInt) raster.getDataBuffer();
256             int data[] = dbi.getData();
257             int scanline = raster.getWidth();
258             int rof = dbi.getOffset() + y * scanline + x;
259             if(model instanceof IndexColorModel){
260
261                 for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize,
262                     rof += scanline) {
263                     for (int sx = x, idx = 0; sx < x + w; sx++, idx++) {
264                         buff[idx] = colorMap[pixels[sOff + idx] & 0xff];
265                     }
266                     System.arraycopy(buff, 0, data, rof, w);
267                 }
268             }else{
269
270                 for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize,
271                     rof += scanline) {
272                     for (int sx = x, idx = 0; sx < x + w; sx++, idx++) {
273                         buff[idx] = model.getRGB(pixels[sOff + idx] & 0xff);
274                     }
275                     System.arraycopy(buff, 0, data, rof, w);
276                 }
277             }
278         }else if(model == cm && model.getTransferType() == DataBuffer.TYPE_BYTE &&
279                 raster.getNumDataElements() == 1){
280
281             DataBufferByte dbb = (DataBufferByte)raster.getDataBuffer();
282             byte data[] = dbb.getData();
283             int scanline = raster.getWidth();
284             int rof = dbb.getOffset() + y * scanline + x;
285             for(int lineOff = off, line = y; line < y + h;
286                 line++, lineOff += scansize, rof += scanline){
287                 System.arraycopy(pixels, lineOff, data, rof, w);
288             }
289         // BEGIN android-added (taken from newer Harmony)
290         }else if(model == cm && model.getTransferType() == DataBuffer.TYPE_BYTE &&
291                 cm instanceof ComponentColorModel){
292
293             int nc = cm.getNumComponents();
294             byte stride[] = new byte[scansize];
295             for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) {
296                 System.arraycopy(pixels, sOff, stride, 0, scansize);
297                 
298                 raster.setDataElements(x, sy, w, 1, stride);
299             }
300         // END android-added
301         }else {
302             for (int sy = y, sOff = off; sy < y + h; sy++, sOff += scansize) {
303                 for (int sx = x, idx = 0; sx < x + w; sx++, idx++) {
304                     int rgb = model.getRGB(pixels[sOff + idx] & 0xff);
305                     raster.setDataElements(sx, sy, cm.getDataElements(rgb, null));
306                 }
307             }
308         }
309
310         if (imageSurf != null) {
311             imageSurf.invalidate();
312         }
313
314         imageUpdate(this, ImageObserver.SOMEBITS, 0, 0, width, height);
315     }
316
317     public void setDimensions(int width, int height) {
318         if(width <= 0 || height <= 0){
319             imageComplete(ImageObserver.ERROR);
320             return;
321         }
322
323         this.width = width;
324         this.height = height;
325         imageUpdate(this, (ImageObserver.HEIGHT | ImageObserver.WIDTH),
326                 0, 0, width, height);
327     }
328
329     public void setHints(int hints) {
330         this.hints = hints;
331     }
332
333     public void imageComplete(int state) {
334         int flag;
335         switch(state){
336         case IMAGEABORTED:
337             flag = ImageObserver.ABORT;
338             break;
339         case IMAGEERROR:
340             flag = ImageObserver.ERROR | ImageObserver.ABORT;
341             break;
342         case SINGLEFRAMEDONE:
343             flag = ImageObserver.FRAMEBITS;
344             break;
345         case STATICIMAGEDONE:
346             flag = ImageObserver.ALLBITS;
347             break;
348         default:
349             // awt.3B=Incorrect ImageConsumer completion status
350             throw new IllegalArgumentException(Messages.getString("awt.3B")); //$NON-NLS-1$
351         }
352         imageUpdate(this, flag, 0, 0, width, height);
353
354         if((flag & (ImageObserver.ERROR | ImageObserver.ABORT |
355                 ImageObserver.ALLBITS)) != 0 ) {
356             stopProduction();
357             observers.removeAllElements();
358         }
359     }
360
361     public /*synchronized*/ BufferedImage getBufferedImage(){
362         if(image == null){
363             ColorModel model = getColorModel();
364             WritableRaster wr = getRaster();
365             if(model != null && wr != null) {
366                 image = new BufferedImage(model, wr, model.isAlphaPremultiplied(), null);
367             }
368         }
369         return image;
370     }
371
372     public /*synchronized*/ int checkImage(ImageObserver observer){
373         addObserver(observer);
374         return imageState;
375     }
376
377     public /*synchronized*/ boolean prepareImage(ImageObserver observer){
378         if((imageState & ImageObserver.ERROR) != 0){
379             if(observer != null){
380                 observer.imageUpdate(this, ImageObserver.ERROR |
381                         ImageObserver.ABORT, -1, -1, -1, -1);
382             }
383             return false;
384         }
385         if((imageState & ImageObserver.ALLBITS) != 0) {
386             return true;
387         }
388         addObserver(observer);
389         startProduction();
390         return ((imageState & ImageObserver.ALLBITS) != 0);
391     }
392
393     public /*synchronized*/ ColorModel getColorModel(){
394         if(cm == null) {
395             startProduction();
396         }
397         return cm;
398     }
399
400     public /*synchronized*/ WritableRaster getRaster(){
401         if(raster == null) {
402             startProduction();
403         }
404         return raster;
405     }
406
407     public int getState(){
408         return imageState;
409     }
410
411     private /*synchronized*/ void addObserver(ImageObserver observer){
412         if(observer != null){
413           if(observers.contains(observer)) {
414             return;
415         }
416           if((imageState & ImageObserver.ERROR) != 0){
417               observer.imageUpdate(this, ImageObserver.ERROR |
418                       ImageObserver.ABORT, -1, -1, -1, -1);
419               return;
420           }
421           if((imageState & ImageObserver.ALLBITS) != 0){
422               observer.imageUpdate(this, imageState, 0, 0, width, height);
423               return;
424           }
425           observers.addElement(observer);
426         }
427     }
428
429     private synchronized void startProduction(){
430         if(!producing){
431             imageState &= ~ImageObserver.ABORT;
432             producing = true;
433             src.startProduction(this);
434         }
435     }
436
437     private synchronized void stopProduction(){
438         producing = false;
439         src.removeConsumer(this);
440     }
441
442     private void createRaster(){
443         try{
444             raster = cm.createCompatibleWritableRaster(width, height);
445             isIntRGB = false;
446             if(cm instanceof DirectColorModel){
447                 DirectColorModel dcm = (DirectColorModel) cm;
448                 if(dcm.getTransferType() == DataBuffer.TYPE_INT &&
449                         dcm.getRedMask() == 0xff0000 &&
450                         dcm.getGreenMask() == 0xff00 &&
451                         dcm.getBlueMask() == 0xff){
452                     isIntRGB = true;
453                 }
454             }
455         }catch(Exception e){
456             cm = ColorModel.getRGBdefault();
457             raster = cm.createCompatibleWritableRaster(width, height);
458             isIntRGB = true;
459         }
460     }
461
462     private /*synchronized*/ void imageUpdate(Image img, int infoflags, int x, int y,
463             int width, int height){
464
465         imageState |= infoflags;
466         for (ImageObserver observer : observers) {
467             observer.imageUpdate(this, infoflags, x, y, width, height);
468         }
469
470 //            notifyAll();
471     }
472
473     private void forceToIntARGB(){
474
475         int w = raster.getWidth();
476         int h = raster.getHeight();
477
478         WritableRaster destRaster = rgbCM.createCompatibleWritableRaster(w, h);
479
480         Object obj = null;
481         int pixels[] = new int[w];
482
483         if(cm instanceof IndexColorModel){
484             IndexColorModel icm = (IndexColorModel) cm;
485             int colorMap[] = new int[icm.getMapSize()];
486             icm.getRGBs(colorMap);
487
488             for (int y = 0; y < h; y++) {
489                 obj = raster.getDataElements(0, y, w, 1, obj);
490                 byte ba[] = (byte[]) obj;
491                 for (int x = 0; x < ba.length; x++) {
492                     pixels[x] = colorMap[ba[x] & 0xff];
493                 }
494                 destRaster.setDataElements(0, y, w, 1, pixels);
495             }
496
497         }else{
498             for(int y = 0; y < h; y++){
499                 for(int x = 0; x < w; x++){
500                     obj = raster.getDataElements(x, y, obj);
501                     pixels[x] = cm.getRGB(obj);
502                 }
503                 destRaster.setDataElements(0, y, w, 1, pixels);
504             }
505         }
506
507         synchronized(this){
508             if(imageSurf != null){
509                 imageSurf.dispose();
510                 imageSurf = null;
511             }
512             if(image != null){
513                 image.flush();
514                 image = null;
515             }
516             cm = rgbCM;
517             raster = destRaster;
518             isIntRGB = true;
519         }
520     }
521
522     public ImageSurface getImageSurface() {
523         if (imageSurf == null) {
524             ColorModel model = getColorModel();
525             WritableRaster wr = getRaster();
526             if(model != null && wr != null) {
527                 imageSurf = new ImageSurface(model, wr);
528             }
529         }
530         return imageSurf;
531     }
532 }