|
1 /******************************************************************************* |
|
2 * Copyright (c) 2000, 2004 IBM Corporation and others. |
|
3 * All rights reserved. This program and the accompanying materials |
|
4 * are made available under the terms of the Eclipse Public License v1.0 |
|
5 * which accompanies this distribution, and is available at |
|
6 * http://www.eclipse.org/legal/epl-v10.html |
|
7 * |
|
8 * Contributors: |
|
9 * IBM Corporation - initial API and implementation |
|
10 * Lynne Kues (IBM Corp) - modified to reflect eSWT API subset |
|
11 * Nokia Corporation - S60 implementation |
|
12 *******************************************************************************/ |
|
13 package org.eclipse.swt.graphics; |
|
14 |
|
15 |
|
16 import java.io.*; |
|
17 import org.eclipse.swt.*; |
|
18 import org.eclipse.swt.internal.symbian.*; |
|
19 import org.eclipse.swt.internal.FileCompatibility; |
|
20 |
|
21 |
|
22 /** |
|
23 * Instances of this class are graphics which have been prepared |
|
24 * for display on a specific device. That is, they are ready |
|
25 * to paint using methods such as <code>GC.drawImage()</code> |
|
26 * and display on widgets with, for example, <code>Button.setImage()</code>. |
|
27 * <p> |
|
28 * If loaded from a file format that supports it, an |
|
29 * <code>Image</code> may have transparency, meaning that certain |
|
30 * pixels are specified as being transparent when drawn. Examples |
|
31 * of file formats that support transparency are GIF and PNG. |
|
32 * </p><p> |
|
33 * There are two primary ways to use <code>Images</code>. |
|
34 * The first is to load a graphic file from disk and create an |
|
35 * <code>Image</code> from it. This is done using an <code>Image</code> |
|
36 * constructor, for example: |
|
37 * <pre> |
|
38 * Image i = new Image(device, "C:\\graphic.png"); |
|
39 * </pre> |
|
40 * A graphic file may contain a color table specifying which |
|
41 * colors the image was intended to possess. In the above example, |
|
42 * these colors will be mapped to the closest available color in |
|
43 * SWT. It is possible to get more control over the mapping of |
|
44 * colors as the image is being created, using code of the form: |
|
45 * <pre> |
|
46 * ImageData data = new ImageData("C:\\graphic.png"); |
|
47 * RGB[] rgbs = data.getRGBs(); |
|
48 * // At this point, rgbs contains specifications of all |
|
49 * // the colors contained within this image. You may |
|
50 * // allocate as many of these colors as you wish by |
|
51 * // using the Color constructor Color(RGB), then |
|
52 * // create the image: |
|
53 * Image i = new Image(device, data); |
|
54 * </pre> |
|
55 * <p> |
|
56 * Application code must explicitely invoke the <code>Image.dispose()</code> |
|
57 * method to release the operating system resources managed by each instance |
|
58 * when those instances are no longer required. |
|
59 * </p> |
|
60 * |
|
61 * @see Color |
|
62 * @see ImageData |
|
63 */ |
|
64 |
|
65 public final class Image implements Drawable |
|
66 { |
|
67 |
|
68 /** |
|
69 * specifies whether the receiver is a bitmap or an icon |
|
70 * (one of <code>SWT.BITMAP</code>, <code>SWT.ICON</code>) |
|
71 */ |
|
72 public int type; |
|
73 |
|
74 /** |
|
75 * the handle to the OS image resource |
|
76 * (Warning: This field is platform dependent) |
|
77 */ |
|
78 public int handle; |
|
79 |
|
80 /** |
|
81 * the device where this image was created |
|
82 */ |
|
83 Device device; |
|
84 |
|
85 /** |
|
86 * specifies the transparent pixel |
|
87 * (Warning: This field is platform dependent) |
|
88 */ |
|
89 Color transparentPixel; |
|
90 |
|
91 /** |
|
92 * Whether this image is currently selected in a GC |
|
93 * (Warning: This field is platform dependent) |
|
94 */ |
|
95 boolean owningGc = false; |
|
96 |
|
97 /** |
|
98 * the global alpha value to be used for every pixel |
|
99 * (Warning: This field is platform dependent) |
|
100 */ |
|
101 int alpha = -1; |
|
102 |
|
103 /** |
|
104 * specifies the default scanline padding |
|
105 * (Warning: This field is platform dependent) |
|
106 */ |
|
107 static final int DEFAULT_SCANLINE_PAD = 4; |
|
108 |
|
109 /** |
|
110 * Prevents uninitialized instances from being created outside the package. |
|
111 */ |
|
112 Image() |
|
113 { |
|
114 } |
|
115 |
|
116 /** |
|
117 * Constructs an empty instance of this class with the |
|
118 * specified width and height. The result may be drawn upon |
|
119 * by creating a GC and using any of its drawing operations, |
|
120 * as shown in the following example: |
|
121 * <pre> |
|
122 * Image i = new Image(device, width, height); |
|
123 * GC gc = new GC(i); |
|
124 * gc.drawRectangle(0, 0, 50, 50); |
|
125 * gc.dispose(); |
|
126 * </pre> |
|
127 * <p> |
|
128 * Note: Some platforms may have a limitation on the size |
|
129 * of image that can be created (size depends on width, height, |
|
130 * and depth). For example, Windows 95, 98, and ME do not allow |
|
131 * images larger than 16M. |
|
132 * </p> |
|
133 * |
|
134 * @param device the device on which to create the image |
|
135 * @param width the width of the new image |
|
136 * @param height the height of the new image |
|
137 * |
|
138 * @exception IllegalArgumentException <ul> |
|
139 * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
|
140 * <li>ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero</li> |
|
141 * </ul> |
|
142 * @exception SWTError <ul> |
|
143 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> |
|
144 * </ul> |
|
145 */ |
|
146 public Image(Device device, int width, int height) |
|
147 { |
|
148 if (device == null) device = Device.getDevice(); |
|
149 if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
150 init(device, width, height); |
|
151 } |
|
152 |
|
153 /** |
|
154 * Constructs an empty instance of this class with the |
|
155 * width and height of the specified rectangle. The result |
|
156 * may be drawn upon by creating a GC and using any of its |
|
157 * drawing operations, as shown in the following example: |
|
158 * <pre> |
|
159 * Image i = new Image(device, boundsRectangle); |
|
160 * GC gc = new GC(i); |
|
161 * gc.drawRectangle(0, 0, 50, 50); |
|
162 * gc.dispose(); |
|
163 * </pre> |
|
164 * <p> |
|
165 * Note: Some platforms may have a limitation on the size |
|
166 * of image that can be created (size depends on width, height, |
|
167 * and depth). For example, Windows 95, 98, and ME do not allow |
|
168 * images larger than 16M. |
|
169 * </p> |
|
170 * |
|
171 * @param device the device on which to create the image |
|
172 * @param bounds a rectangle specifying the image's width and height (must not be null) |
|
173 * |
|
174 * @exception IllegalArgumentException <ul> |
|
175 * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
|
176 * <li>ERROR_NULL_ARGUMENT - if the bounds rectangle is null</li> |
|
177 * <li>ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative</li> |
|
178 * </ul> |
|
179 * @exception SWTError <ul> |
|
180 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> |
|
181 * </ul> |
|
182 */ |
|
183 public Image(Device device, Rectangle bounds) |
|
184 { |
|
185 if (device == null) device = Device.getDevice(); |
|
186 if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
187 if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
188 init(device, bounds.width, bounds.height); |
|
189 } |
|
190 |
|
191 /** |
|
192 * Constructs an instance of this class from the given |
|
193 * <code>ImageData</code>. |
|
194 * |
|
195 * @param device the device on which to create the image |
|
196 * @param data the image data to create the image from (must not be null) |
|
197 * |
|
198 * @exception IllegalArgumentException <ul> |
|
199 * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
|
200 * <li>ERROR_NULL_ARGUMENT - if the image data is null</li> |
|
201 * </ul> |
|
202 * @exception SWTException <ul> |
|
203 * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported</li> |
|
204 * </ul> |
|
205 * @exception SWTError <ul> |
|
206 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> |
|
207 * </ul> |
|
208 */ |
|
209 public Image(Device device, ImageData data) |
|
210 { |
|
211 if (device == null) device = Device.getDevice(); |
|
212 if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
213 init(device, data); |
|
214 } |
|
215 |
|
216 /** |
|
217 * Constructs an instance of this class by loading its representation |
|
218 * from the specified input stream. Throws an error if an error |
|
219 * occurs while loading the image, or if the result is an image |
|
220 * of an unsupported type. Application code is still responsible |
|
221 * for closing the input stream. |
|
222 * <p> |
|
223 * This constructor may be used to load a resource as follows: |
|
224 * </p> |
|
225 * <pre> |
|
226 * new Image(device, clazz.getResourceAsStream("file.png")); |
|
227 * </pre> |
|
228 * |
|
229 * @param device the device on which to create the image |
|
230 * @param stream the input stream to load the image from |
|
231 * |
|
232 * @exception IllegalArgumentException <ul> |
|
233 * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
|
234 * <li>ERROR_NULL_ARGUMENT - if the stream is null</li> |
|
235 * </ul> |
|
236 * @exception SWTException <ul> |
|
237 * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li> |
|
238 * <li>ERROR_IO - if an IO error occurs while reading data</li> |
|
239 * <li>ERROR_UNSUPPORTED_DEPTH - if the InputStream describes an image with an unsupported depth</li> |
|
240 * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li> |
|
241 * * </ul> |
|
242 * </ul> |
|
243 * @exception SWTError <ul> |
|
244 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> |
|
245 * </ul> |
|
246 */ |
|
247 public Image(Device device, InputStream stream) |
|
248 { |
|
249 if (device == null) device = Device.getDevice(); |
|
250 if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
251 init(device, new ImageData(stream)); |
|
252 } |
|
253 |
|
254 /** |
|
255 * Constructs an instance of this class by loading its representation |
|
256 * from the file with the specified name. Throws an error if an error |
|
257 * occurs while loading the image, or if the result is an image |
|
258 * of an unsupported type. |
|
259 * <p> |
|
260 * This constructor is provided for convenience when loading |
|
261 * a single image only. If the specified file contains |
|
262 * multiple images, only the first one will be used. |
|
263 * |
|
264 * @param device the device on which to create the image |
|
265 * @param filename the name of the file to load the image from |
|
266 * |
|
267 * @exception IllegalArgumentException <ul> |
|
268 * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li> |
|
269 * <li>ERROR_NULL_ARGUMENT - if the file name is null</li> |
|
270 * </ul> |
|
271 * @exception SWTException <ul> |
|
272 * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li> |
|
273 * <li>ERROR_IO - if an IO error occurs while reading data</li> |
|
274 * <li>ERROR_UNSUPPORTED_DEPTH - if the image file has an unsupported depth</li> |
|
275 * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li> |
|
276 * </ul> |
|
277 * @exception SWTError <ul> |
|
278 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> |
|
279 * </ul> |
|
280 */ |
|
281 public Image(Device device, String filename) |
|
282 { |
|
283 if (device == null) device = Device.getDevice(); |
|
284 if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
285 init(device, new ImageData(filename)); |
|
286 } |
|
287 |
|
288 /** |
|
289 * Disposes of the operating system resources associated with |
|
290 * the image. Applications must dispose of all images which |
|
291 * they allocate. |
|
292 */ |
|
293 public void dispose() |
|
294 { |
|
295 if (handle == 0) return; |
|
296 if (device.isDisposed()) return; |
|
297 OS.Image_Dispose(device.handle, handle); |
|
298 handle = 0; |
|
299 if (transparentPixel != null) transparentPixel.dispose(); |
|
300 if (device.tracking) device.dispose_Object(this); |
|
301 device = null; |
|
302 } |
|
303 |
|
304 /** |
|
305 * Compares the argument to the receiver, and returns true |
|
306 * if they represent the <em>same</em> object using a class |
|
307 * specific comparison. |
|
308 * |
|
309 * @param object the object to compare with this object |
|
310 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise |
|
311 * |
|
312 * @see #hashCode |
|
313 */ |
|
314 public boolean equals(Object object) |
|
315 { |
|
316 if (object == this) return true; |
|
317 if (!(object instanceof Image)) return false; |
|
318 Image image = (Image) object; |
|
319 return device == image.device && handle == image.handle; |
|
320 } |
|
321 |
|
322 /** |
|
323 * Returns the bounds of the receiver. The rectangle will always |
|
324 * have x and y values of 0, and the width and height of the |
|
325 * image. |
|
326 * |
|
327 * @return a rectangle specifying the image's bounds |
|
328 * |
|
329 * @exception SWTException <ul> |
|
330 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> |
|
331 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li> |
|
332 * </ul> |
|
333 */ |
|
334 public Rectangle getBounds() |
|
335 { |
|
336 if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); |
|
337 switch (type) |
|
338 { |
|
339 case SWT.BITMAP: |
|
340 case SWT.ICON: |
|
341 return OS.Image_GetBounds(handle); |
|
342 default: |
|
343 SWT.error(SWT.ERROR_INVALID_IMAGE); |
|
344 return null; |
|
345 } |
|
346 } |
|
347 |
|
348 /** |
|
349 * Returns an <code>ImageData</code> based on the receiver |
|
350 * Modifications made to this <code>ImageData</code> will not |
|
351 * affect the Image. |
|
352 * |
|
353 * @return an <code>ImageData</code> containing the image's data and attributes |
|
354 * |
|
355 * @exception SWTException <ul> |
|
356 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> |
|
357 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li> |
|
358 * </ul> |
|
359 * |
|
360 * @see ImageData |
|
361 */ |
|
362 public ImageData getImageData() |
|
363 { |
|
364 if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); |
|
365 switch (type) |
|
366 { |
|
367 case SWT.BITMAP: |
|
368 case SWT.ICON: |
|
369 return OS.Image_GetData(handle); |
|
370 default: |
|
371 SWT.error(SWT.ERROR_INVALID_IMAGE); |
|
372 return null; |
|
373 } |
|
374 } |
|
375 |
|
376 /** |
|
377 * Returns an integer hash code for the receiver. Any two |
|
378 * objects which return <code>true</code> when passed to |
|
379 * <code>equals</code> must return the same value for this |
|
380 * method. |
|
381 * |
|
382 * @return the receiver's hash |
|
383 * |
|
384 * @see #equals |
|
385 */ |
|
386 public int hashCode() |
|
387 { |
|
388 return handle; |
|
389 } |
|
390 |
|
391 void init(Device device, int width, int height) |
|
392 { |
|
393 if (width <= 0 || height <= 0) |
|
394 { |
|
395 SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
|
396 } |
|
397 this.device = device; |
|
398 type = SWT.BITMAP; |
|
399 handle = OS.Image_New(device.handle, width, height); |
|
400 if (handle == 0) |
|
401 { |
|
402 SWT.error(SWT.ERROR_NO_HANDLES, null, device.getLastError()); |
|
403 } |
|
404 try |
|
405 { |
|
406 if (device.tracking) device.new_Object(this); |
|
407 } |
|
408 catch (Error e) |
|
409 { |
|
410 OS.Image_Dispose(device.handle, handle); |
|
411 throw e; |
|
412 } |
|
413 } |
|
414 |
|
415 static void init(Device device, Image image, ImageData i) |
|
416 { |
|
417 if (image != null) image.device = device; |
|
418 image.handle = OS.Image_NewFromData(device.handle, i); |
|
419 image.alpha = i.alpha; |
|
420 |
|
421 try |
|
422 { |
|
423 if (i.transparentPixel != -1) |
|
424 { |
|
425 image.transparentPixel = new Color(device, i.palette.getRGB(i.transparentPixel)); |
|
426 } |
|
427 if (device.tracking) device.new_Object(image); |
|
428 } |
|
429 catch (Error e) |
|
430 { |
|
431 OS.Image_Dispose(device.handle, image.handle); |
|
432 throw e; |
|
433 } |
|
434 } |
|
435 |
|
436 static void init(Device device, Image image, ImageData source, ImageData mask) |
|
437 { |
|
438 /* Create a temporary image and locate the black pixel */ |
|
439 ImageData imageData; |
|
440 int blackIndex = 0; |
|
441 if (source.palette.isDirect) |
|
442 { |
|
443 imageData = new ImageData(source.width, source.height, source.depth, source.palette); |
|
444 } |
|
445 else |
|
446 { |
|
447 RGB black = new RGB(0, 0, 0); |
|
448 RGB[] rgbs = source.getRGBs(); |
|
449 if (source.transparentPixel != -1) |
|
450 { |
|
451 /* |
|
452 * The source had transparency, so we can use the transparent pixel |
|
453 * for black. |
|
454 */ |
|
455 RGB[] newRGBs = new RGB[rgbs.length]; |
|
456 System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length); |
|
457 if (source.transparentPixel >= newRGBs.length) |
|
458 { |
|
459 /* Grow the palette with black */ |
|
460 rgbs = new RGB[source.transparentPixel + 1]; |
|
461 System.arraycopy(newRGBs, 0, rgbs, 0, newRGBs.length); |
|
462 for (int i = newRGBs.length; i <= source.transparentPixel; i++) |
|
463 { |
|
464 rgbs[i] = new RGB(0, 0, 0); |
|
465 } |
|
466 } |
|
467 else |
|
468 { |
|
469 newRGBs[source.transparentPixel] = black; |
|
470 rgbs = newRGBs; |
|
471 } |
|
472 blackIndex = source.transparentPixel; |
|
473 imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs)); |
|
474 } |
|
475 else |
|
476 { |
|
477 while (blackIndex < rgbs.length) |
|
478 { |
|
479 if (rgbs[blackIndex].equals(black)) break; |
|
480 blackIndex++; |
|
481 } |
|
482 if (blackIndex == rgbs.length) |
|
483 { |
|
484 /* |
|
485 * We didn't find black in the palette, and there is no transparent |
|
486 * pixel we can use. |
|
487 */ |
|
488 if ((1 << source.depth) > rgbs.length) |
|
489 { |
|
490 /* We can grow the palette and add black */ |
|
491 RGB[] newRGBs = new RGB[rgbs.length + 1]; |
|
492 System.arraycopy(rgbs, 0, newRGBs, 0, rgbs.length); |
|
493 newRGBs[rgbs.length] = black; |
|
494 rgbs = newRGBs; |
|
495 } |
|
496 else |
|
497 { |
|
498 /* No room to grow the palette */ |
|
499 blackIndex = -1; |
|
500 } |
|
501 } |
|
502 imageData = new ImageData(source.width, source.height, source.depth, new PaletteData(rgbs)); |
|
503 } |
|
504 } |
|
505 if (blackIndex == -1) |
|
506 { |
|
507 /* There was no black in the palette, so just copy the data over */ |
|
508 System.arraycopy(source.data, 0, imageData.data, 0, imageData.data.length); |
|
509 } |
|
510 else |
|
511 { |
|
512 /* Modify the source image to contain black wherever the mask is 0 */ |
|
513 int[] imagePixels = new int[imageData.width]; |
|
514 int[] maskPixels = new int[mask.width]; |
|
515 for (int y = 0; y < imageData.height; y++) |
|
516 { |
|
517 source.getPixels(0, y, imageData.width, imagePixels, 0); |
|
518 mask.getPixels(0, y, mask.width, maskPixels, 0); |
|
519 for (int i = 0; i < imagePixels.length; i++) |
|
520 { |
|
521 if (maskPixels[i] == 0) imagePixels[i] = blackIndex; |
|
522 } |
|
523 imageData.setPixels(0, y, source.width, imagePixels, 0); |
|
524 } |
|
525 } |
|
526 imageData.maskPad = mask.scanlinePad; |
|
527 imageData.maskData = mask.data; |
|
528 init(device, image, imageData); |
|
529 } |
|
530 |
|
531 void init(Device device, ImageData i) |
|
532 { |
|
533 if (i == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); |
|
534 init(device, this, i); |
|
535 } |
|
536 |
|
537 /** |
|
538 * Invokes platform specific functionality to allocate a new GC handle. |
|
539 * <p> |
|
540 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public |
|
541 * API for <code>Image</code>. It is marked public only so that it |
|
542 * can be shared within the packages provided by SWT. It is not |
|
543 * available on all platforms, and should never be called from |
|
544 * application code. |
|
545 * </p> |
|
546 * |
|
547 * @param data the platform specific GC data |
|
548 * @return the platform specific GC handle |
|
549 */ |
|
550 public int internal_new_GC(GCData data) |
|
551 { |
|
552 synchronized (this) |
|
553 { |
|
554 if (owningGc) |
|
555 { |
|
556 SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
|
557 } |
|
558 owningGc = true; |
|
559 } |
|
560 |
|
561 if ((type != SWT.BITMAP) && (type != SWT.ICON)) |
|
562 { |
|
563 SWT.error(SWT.ERROR_INVALID_ARGUMENT); |
|
564 } |
|
565 |
|
566 return OS.Drawable_NewGc(handle); |
|
567 } |
|
568 |
|
569 /** |
|
570 * Invokes platform specific functionality to dispose a GC handle. |
|
571 * <p> |
|
572 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public |
|
573 * API for <code>Image</code>. It is marked public only so that it |
|
574 * can be shared within the packages provided by SWT. It is not |
|
575 * available on all platforms, and should never be called from |
|
576 * application code. |
|
577 * </p> |
|
578 * |
|
579 * @param hDC the platform specific GC handle |
|
580 * @param data the platform specific GC data |
|
581 */ |
|
582 public void internal_dispose_GC(int gcHandle, GCData data) |
|
583 { |
|
584 OS.GC_Dispose(gcHandle); |
|
585 |
|
586 synchronized (this) |
|
587 { |
|
588 owningGc = false; |
|
589 } |
|
590 } |
|
591 |
|
592 /** |
|
593 * Returns <code>true</code> if the receiver is visible, and |
|
594 * <code>false</code> otherwise. |
|
595 * <p> |
|
596 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public |
|
597 * API for <code>Drawable</code>. It is marked public only so that it |
|
598 * can be shared within the packages provided by SWT. It is not |
|
599 * available on all platforms, and should never be called from |
|
600 * application code. |
|
601 * </p> |
|
602 * |
|
603 * @return the receiver's visibility state |
|
604 */ |
|
605 public boolean internal_isVisible() |
|
606 { |
|
607 return true; |
|
608 } |
|
609 |
|
610 /** |
|
611 * Returns <code>true</code> if the receiver has been disposed, |
|
612 * and <code>false</code> otherwise. |
|
613 * <p> |
|
614 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public |
|
615 * API for <code>Drawable</code>. It is marked public only so that it |
|
616 * can be shared within the packages provided by SWT. It is not |
|
617 * available on all platforms, and should never be called from |
|
618 * application code. |
|
619 * </p> |
|
620 * |
|
621 * @return <code>true</code> when the receiver is disposed and <code>false</code> otherwise |
|
622 */ |
|
623 public boolean internal_isDisposed() |
|
624 { |
|
625 return isDisposed(); |
|
626 } |
|
627 |
|
628 /** |
|
629 * Returns <code>true</code> if the image has been disposed, |
|
630 * and <code>false</code> otherwise. |
|
631 * <p> |
|
632 * This method gets the dispose state for the image. |
|
633 * When an image has been disposed, it is an error to |
|
634 * invoke any other method using the image. |
|
635 * |
|
636 * @return <code>true</code> when the image is disposed and <code>false</code> otherwise |
|
637 */ |
|
638 public boolean isDisposed() |
|
639 { |
|
640 return handle == 0; |
|
641 } |
|
642 |
|
643 /** |
|
644 * Returns a string containing a concise, human-readable |
|
645 * description of the receiver. |
|
646 * |
|
647 * @return a string representation of the receiver |
|
648 */ |
|
649 public String toString() |
|
650 { |
|
651 if (isDisposed()) return "Image {*DISPOSED*}"; |
|
652 return "Image {" + handle + "}"; |
|
653 } |
|
654 |
|
655 |
|
656 |
|
657 |
|
658 /** |
|
659 * The following functions are not part of the eSWT public api |
|
660 * @param fileName |
|
661 * @return |
|
662 */ |
|
663 static int imageFormat(String fileName) |
|
664 { |
|
665 InputStream stream = null; |
|
666 try |
|
667 { |
|
668 stream = FileCompatibility.getInputStreamFromFile(fileName); |
|
669 byte[] buffer = new byte[32]; |
|
670 stream.read(buffer, 0, buffer.length); |
|
671 stream.close(); |
|
672 return Image.imageFormat(buffer); |
|
673 } |
|
674 catch (IOException e) |
|
675 { |
|
676 SWT.error(SWT.ERROR_IO, e); |
|
677 } |
|
678 finally |
|
679 { |
|
680 try |
|
681 { |
|
682 if (stream != null) stream.close(); |
|
683 } |
|
684 catch (IOException e) |
|
685 { |
|
686 // Ignore error |
|
687 } |
|
688 } |
|
689 return SWT.IMAGE_UNDEFINED; |
|
690 } |
|
691 static int imageFormat(byte[] streamBytes) |
|
692 { |
|
693 if (isPNGFormat(streamBytes)) return SWT.IMAGE_PNG; |
|
694 if (isGIFFormat(streamBytes)) return SWT.IMAGE_GIF; |
|
695 if (isJPEGFormat(streamBytes)) return SWT.IMAGE_JPEG; |
|
696 return SWT.IMAGE_UNDEFINED; |
|
697 } |
|
698 static boolean isPNGFormat(byte[] streamBytes) |
|
699 { |
|
700 if (streamBytes.length < 8) return false; |
|
701 if ((streamBytes[0] & 0xFF) != 137) return false; //137 |
|
702 if ((streamBytes[1] & 0xFF) != 80) return false; //P |
|
703 if ((streamBytes[2] & 0xFF) != 78) return false; //N |
|
704 if ((streamBytes[3] & 0xFF) != 71) return false; //G |
|
705 if ((streamBytes[4] & 0xFF) != 13) return false; //<RETURN> |
|
706 if ((streamBytes[5] & 0xFF) != 10) return false; //<LINEFEED> |
|
707 if ((streamBytes[6] & 0xFF) != 26) return false; //<CTRL/Z> |
|
708 if ((streamBytes[7] & 0xFF) != 10) return false; //<LINEFEED> |
|
709 return true; |
|
710 } |
|
711 static boolean isGIFFormat(byte[] streamBytes) |
|
712 { |
|
713 if (streamBytes.length < 3) return false; |
|
714 if (streamBytes[0] != 'G') return false; |
|
715 if (streamBytes[1] != 'I') return false; |
|
716 if (streamBytes[2] != 'F') return false; |
|
717 return true; |
|
718 } |
|
719 static boolean isJPEGFormat(byte[] streamBytes) |
|
720 { |
|
721 if (streamBytes.length < 2) return false; |
|
722 if ((streamBytes[0] & 0xFF) != 0xFF) return false; |
|
723 if ((streamBytes[1] & 0xFF) != 0xD8) return false; |
|
724 return true; |
|
725 } |
|
726 /** |
|
727 * Reads the specified stream and returns the contents as a byte |
|
728 * array. |
|
729 * |
|
730 * @param stream the raw image data stream |
|
731 * @return image data buffer |
|
732 */ |
|
733 static byte[] readImageStream(InputStream stream) |
|
734 { |
|
735 byte[] buffer = new byte[512]; |
|
736 ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); |
|
737 if (buffer == null || baoStream == null) |
|
738 { |
|
739 SWT.error(SWT.ERROR_IO); |
|
740 } |
|
741 try |
|
742 { |
|
743 boolean done = false; |
|
744 while (!done) |
|
745 { |
|
746 int length = stream.read(buffer); |
|
747 if (-1 == length) |
|
748 { |
|
749 done = true; |
|
750 } |
|
751 else |
|
752 { |
|
753 baoStream.write(buffer,0,length); |
|
754 } |
|
755 } |
|
756 } |
|
757 catch (IOException e) |
|
758 { |
|
759 SWT.error(SWT.ERROR_IO, e); |
|
760 } |
|
761 finally |
|
762 { |
|
763 try |
|
764 { |
|
765 baoStream.close(); |
|
766 } |
|
767 catch (IOException e) |
|
768 { |
|
769 // ignore for the close |
|
770 } |
|
771 } |
|
772 |
|
773 return baoStream.toByteArray(); |
|
774 } |
|
775 } |