1 /* 2 * Copyright (c) 1997, 2018, 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 }