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(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 }
544