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