View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  /* ****************************************************************
27   ******************************************************************
28   ******************************************************************
29   *** COPYRIGHT (c) Eastman Kodak Company, 1997
30   *** As  an unpublished  work pursuant to Title 17 of the United
31   *** States Code.  All rights reserved.
32   ******************************************************************
33   ******************************************************************
34   ******************************************************************/
35  
36  package java.awt.image;
37  
38  import sun.java2d.StateTrackable.State;
39  import static sun.java2d.StateTrackable.State.*;
40  import sun.java2d.StateTrackableDelegate;
41  
42  import sun.awt.image.SunWritableRaster;
43  
44  import java.lang.annotation.Native;
45  
46  /**
47   * This class exists to wrap one or more data arrays.  Each data array in
48   * the DataBuffer is referred to as a bank.  Accessor methods for getting
49   * and setting elements of the DataBuffer's banks exist with and without
50   * a bank specifier.  The methods without a bank specifier use the default 0th
51   * bank.  The DataBuffer can optionally take an offset per bank, so that
52   * data in an existing array can be used even if the interesting data
53   * doesn't start at array location zero.  Getting or setting the 0th
54   * element of a bank, uses the (0+offset)th element of the array.  The
55   * size field specifies how much of the data array is available for
56   * use.  Size + offset for a given bank should never be greater
57   * than the length of the associated data array.  The data type of
58   * a data buffer indicates the type of the data array(s) and may also
59   * indicate additional semantics, e.g. storing unsigned 8-bit data
60   * in elements of a byte array.  The data type may be TYPE_UNDEFINED
61   * or one of the types defined below.  Other types may be added in
62   * the future.  Generally, an object of class DataBuffer will be cast down
63   * to one of its data type specific subclasses to access data type specific
64   * methods for improved performance.  Currently, the Java 2D(tm) API
65   * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT,
66   * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data.
67   * @see java.awt.image.Raster
68   * @see java.awt.image.SampleModel
69   */
70  public abstract class DataBuffer {
71  
72      /** Tag for unsigned byte data. */
73      @Native public static final int TYPE_BYTE  = 0;
74  
75      /** Tag for unsigned short data. */
76      @Native public static final int TYPE_USHORT = 1;
77  
78      /** Tag for signed short data.  Placeholder for future use. */
79      @Native public static final int TYPE_SHORT = 2;
80  
81      /** Tag for int data. */
82      @Native public static final int TYPE_INT   = 3;
83  
84      /** Tag for float data.  Placeholder for future use. */
85      @Native public static final int TYPE_FLOAT  = 4;
86  
87      /** Tag for double data.  Placeholder for future use. */
88      @Native public static final int TYPE_DOUBLE  = 5;
89  
90      /** Tag for undefined data. */
91      @Native public static final int TYPE_UNDEFINED = 32;
92  
93      /** The data type of this DataBuffer. */
94      protected int dataType;
95  
96      /** The number of banks in this DataBuffer. */
97      protected int banks;
98  
99      /** Offset into default (first) bank from which to get the first element. */
100     protected int offset;
101 
102     /** Usable size of all banks. */
103     protected int size;
104 
105     /** Offsets into all banks. */
106     protected int offsets[];
107 
108     /* The current StateTrackable state. */
109     StateTrackableDelegate theTrackable;
110 
111     /** Size of the data types indexed by DataType tags defined above. */
112     private static final int dataTypeSize[] = {8,16,16,32,32,64};
113 
114     /** Returns the size (in bits) of the data type, given a datatype tag.
115       * @param type the value of one of the defined datatype tags
116       * @return the size of the data type
117       * @throws IllegalArgumentException if <code>type</code> is less than
118       *         zero or greater than {@link #TYPE_DOUBLE}
119       */
120     public static int getDataTypeSize(int type) {
121         if (type < TYPE_BYTE || type > TYPE_DOUBLE) {
122             throw new IllegalArgumentException("Unknown data type "+type);
123         }
124         return dataTypeSize[type];
125     }
126 
127     /**
128      *  Constructs a DataBuffer containing one bank of the specified
129      *  data type and size.
130      *
131      *  @param dataType the data type of this <code>DataBuffer</code>
132      *  @param size the size of the banks
133      */
134     protected DataBuffer(int dataType, int size) {
135         this(UNTRACKABLE, dataType, size);
136     }
137 
138     /**
139      *  Constructs a DataBuffer containing one bank of the specified
140      *  data type and size with the indicated initial {@link State State}.
141      *
142      *  @param initialState the initial {@link State State} state of the data
143      *  @param dataType the data type of this <code>DataBuffer</code>
144      *  @param size the size of the banks
145      *  @since 1.7
146      */
147     DataBuffer(State initialState,
148                int dataType, int size)
149     {
150         this.theTrackable = StateTrackableDelegate.createInstance(initialState);
151         this.dataType = dataType;
152         this.banks = 1;
153         this.size = size;
154         this.offset = 0;
155         this.offsets = new int[1];  // init to 0 by new
156     }
157 
158     /**
159      *  Constructs a DataBuffer containing the specified number of
160      *  banks.  Each bank has the specified size and an offset of 0.
161      *
162      *  @param dataType the data type of this <code>DataBuffer</code>
163      *  @param size the size of the banks
164      *  @param numBanks the number of banks in this
165      *         <code>DataBuffer</code>
166      */
167     protected DataBuffer(int dataType, int size, int numBanks) {
168         this(UNTRACKABLE, dataType, size, numBanks);
169     }
170 
171     /**
172      *  Constructs a DataBuffer containing the specified number of
173      *  banks with the indicated initial {@link State State}.
174      *  Each bank has the specified size and an offset of 0.
175      *
176      *  @param initialState the initial {@link State State} state of the data
177      *  @param dataType the data type of this <code>DataBuffer</code>
178      *  @param size the size of the banks
179      *  @param numBanks the number of banks in this
180      *         <code>DataBuffer</code>
181      *  @since 1.7
182      */
183     DataBuffer(State initialState,
184                int dataType, int size, int numBanks)
185     {
186         this.theTrackable = StateTrackableDelegate.createInstance(initialState);
187         this.dataType = dataType;
188         this.banks = numBanks;
189         this.size = size;
190         this.offset = 0;
191         this.offsets = new int[banks]; // init to 0 by new
192     }
193 
194     /**
195      *  Constructs a DataBuffer that contains the specified number
196      *  of banks.  Each bank has the specified datatype, size and offset.
197      *
198      *  @param dataType the data type of this <code>DataBuffer</code>
199      *  @param size the size of the banks
200      *  @param numBanks the number of banks in this
201      *         <code>DataBuffer</code>
202      *  @param offset the offset for each bank
203      */
204     protected DataBuffer(int dataType, int size, int numBanks, int offset) {
205         this(UNTRACKABLE, dataType, size, numBanks, offset);
206     }
207 
208     /**
209      *  Constructs a DataBuffer that contains the specified number
210      *  of banks with the indicated initial {@link State State}.
211      *  Each bank has the specified datatype, size and offset.
212      *
213      *  @param initialState the initial {@link State State} state of the data
214      *  @param dataType the data type of this <code>DataBuffer</code>
215      *  @param size the size of the banks
216      *  @param numBanks the number of banks in this
217      *         <code>DataBuffer</code>
218      *  @param offset the offset for each bank
219      *  @since 1.7
220      */
221     DataBuffer(State initialState,
222                int dataType, int size, int numBanks, int offset)
223     {
224         this.theTrackable = StateTrackableDelegate.createInstance(initialState);
225         this.dataType = dataType;
226         this.banks = numBanks;
227         this.size = size;
228         this.offset = offset;
229         this.offsets = new int[numBanks];
230         for (int i = 0; i < numBanks; i++) {
231             this.offsets[i] = offset;
232         }
233     }
234 
235     /**
236      *  Constructs a DataBuffer which contains the specified number
237      *  of banks.  Each bank has the specified datatype and size.  The
238      *  offset for each bank is specified by its respective entry in
239      *  the offsets array.
240      *
241      *  @param dataType the data type of this <code>DataBuffer</code>
242      *  @param size the size of the banks
243      *  @param numBanks the number of banks in this
244      *         <code>DataBuffer</code>
245      *  @param offsets an array containing an offset for each bank.
246      *  @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
247      *          does not equal the length of <code>offsets</code>
248      */
249     protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) {
250         this(UNTRACKABLE, dataType, size, numBanks, offsets);
251     }
252 
253     /**
254      *  Constructs a DataBuffer which contains the specified number
255      *  of banks with the indicated initial {@link State State}.
256      *  Each bank has the specified datatype and size.  The
257      *  offset for each bank is specified by its respective entry in
258      *  the offsets array.
259      *
260      *  @param initialState the initial {@link State State} state of the data
261      *  @param dataType the data type of this <code>DataBuffer</code>
262      *  @param size the size of the banks
263      *  @param numBanks the number of banks in this
264      *         <code>DataBuffer</code>
265      *  @param offsets an array containing an offset for each bank.
266      *  @throws ArrayIndexOutOfBoundsException if <code>numBanks</code>
267      *          does not equal the length of <code>offsets</code>
268      *  @since 1.7
269      */
270     DataBuffer(State initialState,
271                int dataType, int size, int numBanks, int offsets[])
272     {
273         if (numBanks != offsets.length) {
274             throw new ArrayIndexOutOfBoundsException("Number of banks" +
275                  " does not match number of bank offsets");
276         }
277         this.theTrackable = StateTrackableDelegate.createInstance(initialState);
278         this.dataType = dataType;
279         this.banks = numBanks;
280         this.size = size;
281         this.offset = offsets[0];
282         this.offsets = (int[])offsets.clone();
283     }
284 
285     /**  Returns the data type of this DataBuffer.
286      *   @return the data type of this <code>DataBuffer</code>.
287      */
288     public int getDataType() {
289         return dataType;
290     }
291 
292     /**  Returns the size (in array elements) of all banks.
293      *   @return the size of all banks.
294      */
295     public int getSize() {
296         return size;
297     }
298 
299     /** Returns the offset of the default bank in array elements.
300      *  @return the offset of the default bank.
301      */
302     public int getOffset() {
303         return offset;
304     }
305 
306     /** Returns the offsets (in array elements) of all the banks.
307      *  @return the offsets of all banks.
308      */
309     public int[] getOffsets() {
310         return (int[])offsets.clone();
311     }
312 
313     /** Returns the number of banks in this DataBuffer.
314      *  @return the number of banks.
315      */
316     public int getNumBanks() {
317         return banks;
318     }
319 
320     /**
321      * Returns the requested data array element from the first (default) bank
322      * as an integer.
323      * @param i the index of the requested data array element
324      * @return the data array element at the specified index.
325      * @see #setElem(int, int)
326      * @see #setElem(int, int, int)
327      */
328     public int getElem(int i) {
329         return getElem(0,i);
330     }
331 
332     /**
333      * Returns the requested data array element from the specified bank
334      * as an integer.
335      * @param bank the specified bank
336      * @param i the index of the requested data array element
337      * @return the data array element at the specified index from the
338      *         specified bank at the specified index.
339      * @see #setElem(int, int)
340      * @see #setElem(int, int, int)
341      */
342     public abstract int getElem(int bank, int i);
343 
344     /**
345      * Sets the requested data array element in the first (default) bank
346      * from the given integer.
347      * @param i the specified index into the data array
348      * @param val the data to set the element at the specified index in
349      * the data array
350      * @see #getElem(int)
351      * @see #getElem(int, int)
352      */
353     public void  setElem(int i, int val) {
354         setElem(0,i,val);
355     }
356 
357     /**
358      * Sets the requested data array element in the specified bank
359      * from the given integer.
360      * @param bank the specified bank
361      * @param i the specified index into the data array
362      * @param val  the data to set the element in the specified bank
363      * at the specified index in the data array
364      * @see #getElem(int)
365      * @see #getElem(int, int)
366      */
367     public abstract void setElem(int bank, int i, int val);
368 
369     /**
370      * Returns the requested data array element from the first (default) bank
371      * as a float.  The implementation in this class is to cast getElem(i)
372      * to a float.  Subclasses may override this method if another
373      * implementation is needed.
374      * @param i the index of the requested data array element
375      * @return a float value representing the data array element at the
376      *  specified index.
377      * @see #setElemFloat(int, float)
378      * @see #setElemFloat(int, int, float)
379      */
380     public float getElemFloat(int i) {
381         return (float)getElem(i);
382     }
383 
384     /**
385      * Returns the requested data array element from the specified bank
386      * as a float.  The implementation in this class is to cast
387      * {@link #getElem(int, int)}
388      * to a float.  Subclasses can override this method if another
389      * implementation is needed.
390      * @param bank the specified bank
391      * @param i the index of the requested data array element
392      * @return a float value representing the data array element from the
393      * specified bank at the specified index.
394      * @see #setElemFloat(int, float)
395      * @see #setElemFloat(int, int, float)
396      */
397     public float getElemFloat(int bank, int i) {
398         return (float)getElem(bank,i);
399     }
400 
401     /**
402      * Sets the requested data array element in the first (default) bank
403      * from the given float.  The implementation in this class is to cast
404      * val to an int and call {@link #setElem(int, int)}.  Subclasses
405      * can override this method if another implementation is needed.
406      * @param i the specified index
407      * @param val the value to set the element at the specified index in
408      * the data array
409      * @see #getElemFloat(int)
410      * @see #getElemFloat(int, int)
411      */
412     public void setElemFloat(int i, float val) {
413         setElem(i,(int)val);
414     }
415 
416     /**
417      * Sets the requested data array element in the specified bank
418      * from the given float.  The implementation in this class is to cast
419      * val to an int and call {@link #setElem(int, int)}.  Subclasses can
420      * override this method if another implementation is needed.
421      * @param bank the specified bank
422      * @param i the specified index
423      * @param val the value to set the element in the specified bank at
424      * the specified index in the data array
425      * @see #getElemFloat(int)
426      * @see #getElemFloat(int, int)
427      */
428     public void setElemFloat(int bank, int i, float val) {
429         setElem(bank,i,(int)val);
430     }
431 
432     /**
433      * Returns the requested data array element from the first (default) bank
434      * as a double.  The implementation in this class is to cast
435      * {@link #getElem(int)}
436      * to a double.  Subclasses can override this method if another
437      * implementation is needed.
438      * @param i the specified index
439      * @return a double value representing the element at the specified
440      * index in the data array.
441      * @see #setElemDouble(int, double)
442      * @see #setElemDouble(int, int, double)
443      */
444     public double getElemDouble(int i) {
445         return (double)getElem(i);
446     }
447 
448     /**
449      * Returns the requested data array element from the specified bank as
450      * a double.  The implementation in this class is to cast getElem(bank, i)
451      * to a double.  Subclasses may override this method if another
452      * implementation is needed.
453      * @param bank the specified bank
454      * @param i the specified index
455      * @return a double value representing the element from the specified
456      * bank at the specified index in the data array.
457      * @see #setElemDouble(int, double)
458      * @see #setElemDouble(int, int, double)
459      */
460     public double getElemDouble(int bank, int i) {
461         return (double)getElem(bank,i);
462     }
463 
464     /**
465      * Sets the requested data array element in the first (default) bank
466      * from the given double.  The implementation in this class is to cast
467      * val to an int and call {@link #setElem(int, int)}.  Subclasses can
468      * override this method if another implementation is needed.
469      * @param i the specified index
470      * @param val the value to set the element at the specified index
471      * in the data array
472      * @see #getElemDouble(int)
473      * @see #getElemDouble(int, int)
474      */
475     public void setElemDouble(int i, double val) {
476         setElem(i,(int)val);
477     }
478 
479     /**
480      * Sets the requested data array element in the specified bank
481      * from the given double.  The implementation in this class is to cast
482      * val to an int and call {@link #setElem(int, int)}.  Subclasses can
483      * override this method if another implementation is needed.
484      * @param bank the specified bank
485      * @param i the specified index
486      * @param val the value to set the element in the specified bank
487      * at the specified index of the data array
488      * @see #getElemDouble(int)
489      * @see #getElemDouble(int, int)
490      */
491     public void setElemDouble(int bank, int i, double val) {
492         setElem(bank,i,(int)val);
493     }
494 
495     static int[] toIntArray(Object obj) {
496         if (obj instanceof int[]) {
497             return (int[])obj;
498         } else if (obj == null) {
499             return null;
500         } else if (obj instanceof short[]) {
501             short sdata[] = (short[])obj;
502             int idata[] = new int[sdata.length];
503             for (int i = 0; i < sdata.length; i++) {
504                 idata[i] = (int)sdata[i] & 0xffff;
505             }
506             return idata;
507         } else if (obj instanceof byte[]) {
508             byte bdata[] = (byte[])obj;
509             int idata[] = new int[bdata.length];
510             for (int i = 0; i < bdata.length; i++) {
511                 idata[i] = 0xff & (int)bdata[i];
512             }
513             return idata;
514         }
515         return null;
516     }
517 
518     static {
519         SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() {
520             public byte[] getData(DataBufferByte dbb, int bank) {
521                 return dbb.bankdata[bank];
522             }
523 
524             public short[] getData(DataBufferUShort dbus, int bank) {
525                 return dbus.bankdata[bank];
526             }
527 
528             public int[] getData(DataBufferInt dbi, int bank) {
529                 return dbi.bankdata[bank];
530             }
531 
532             public StateTrackableDelegate getTrackable(DataBuffer db) {
533                 return db.theTrackable;
534             }
535 
536             public void setTrackable(DataBuffer db,
537                                      StateTrackableDelegate trackable)
538             {
539                 db.theTrackable = trackable;
540             }
541         });
542     }
543 }