1 /*
2  * Copyright (c) 1997, 2014, 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} 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}
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}
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}
163      *  @param size the size of the banks
164      *  @param numBanks the number of banks in this
165      *         {@code DataBuffer}
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}
178      *  @param size the size of the banks
179      *  @param numBanks the number of banks in this
180      *         {@code DataBuffer}
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}
199      *  @param size the size of the banks
200      *  @param numBanks the number of banks in this
201      *         {@code DataBuffer}
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}
215      *  @param size the size of the banks
216      *  @param numBanks the number of banks in this
217      *         {@code DataBuffer}
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}
242      *  @param size the size of the banks
243      *  @param numBanks the number of banks in this
244      *         {@code DataBuffer}
245      *  @param offsets an array containing an offset for each bank.
246      *  @throws ArrayIndexOutOfBoundsException if {@code numBanks}
247      *          does not equal the length of {@code offsets}
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}
262      *  @param size the size of the banks
263      *  @param numBanks the number of banks in this
264      *         {@code DataBuffer}
265      *  @param offsets an array containing an offset for each bank.
266      *  @throws ArrayIndexOutOfBoundsException if {@code numBanks}
267      *          does not equal the length of {@code offsets}
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 = offsets.clone();
283     }
284
285     /**  Returns the data type of this DataBuffer.
286      *   @return the data type of this {@code DataBuffer}.
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 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(intint)
326      * @see #setElem(intintint)
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(intint)
340      * @see #setElem(intintint)
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(intint)
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(intint)
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(intfloat)
378      * @see #setElemFloat(intintfloat)
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(intint)}
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(intfloat)
395      * @see #setElemFloat(intintfloat)
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(intint)}.  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(intint)
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(intint)}.  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(intint)
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(intdouble)
442      * @see #setElemDouble(intintdouble)
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(intdouble)
458      * @see #setElemDouble(intintdouble)
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(intint)}.  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(intint)
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(intint)}.  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(intint)
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 }
544