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