comparison dwt/graphics/Image.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents db5a898b2119
children cfa563df4fdd
comparison
equal deleted inserted replaced
44:ca5e494f2bbf 45:d8635bb48c7c
1 /******************************************************************************* 1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others. 2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials 3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0 4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at 5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html 6 * http://www.eclipse.org/legal/epl-v10.html
7 * 7 *
8 * Contributors: 8 * Contributors:
9 * IBM Corporation - initial API and implementation 9 * IBM Corporation - initial API and implementation
10 * 10 *
11 * Port to the D programming language: 11 * Port to the D programming language:
12 * Jacob Carlborg <jacob.carlborg@gmail.com> 12 * Jacob Carlborg <doob@me.com>
13 *******************************************************************************/ 13 *******************************************************************************/
14 module dwt.graphics.Image; 14 module dwt.graphics.Image;
15 15
16 16
17 import dwt.dwthelper.InputStream; 17 import dwt.dwthelper.InputStream;
18 18
19 import dwt.DWT; 19 import dwt.DWT;
20 import dwt.DWTError; 20 import dwt.DWTError;
21 import dwt.DWTException; 21 import dwt.DWTException;
22 import dwt.internal.C;
22 import dwt.internal.cocoa.NSAffineTransform; 23 import dwt.internal.cocoa.NSAffineTransform;
24 import dwt.internal.cocoa.NSAutoreleasePool;
23 import dwt.internal.cocoa.NSBitmapImageRep; 25 import dwt.internal.cocoa.NSBitmapImageRep;
24 import dwt.internal.cocoa.NSGraphicsContext; 26 import dwt.internal.cocoa.NSGraphicsContext;
25 import dwt.internal.cocoa.NSImage; 27 import dwt.internal.cocoa.NSImage;
26 import dwt.internal.cocoa.NSImageRep; 28 import dwt.internal.cocoa.NSImageRep;
27 import dwt.internal.cocoa.NSSize; 29 import dwt.internal.cocoa.NSSize;
28 import dwt.internal.cocoa.NSString; 30 import dwt.internal.cocoa.NSThread;
29 import dwt.internal.cocoa.OS; 31 import dwt.internal.cocoa.OS;
30 32
31 import tango.text.convert.Format; 33 import tango.text.convert.Format;
32 34
33 import dwt.dwthelper.utils; 35 import dwt.dwthelper.utils;
88 * </p> 90 * </p>
89 * 91 *
90 * @see Color 92 * @see Color
91 * @see ImageData 93 * @see ImageData
92 * @see ImageLoader 94 * @see ImageLoader
95 * @see <a href="http://www.eclipse.org/swt/snippets/#image">Image snippets</a>
96 * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Examples: GraphicsExample, ImageAnalyzer</a>
97 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
93 */ 98 */
94 public final class Image : Resource, Drawable { 99 public final class Image : Resource, Drawable {
95 100
96 alias Resource.init_ init_; 101 alias Resource.init_ init_;
97 102
189 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> 194 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
190 * </ul> 195 * </ul>
191 */ 196 */
192 public this(Device device, int width, int height) { 197 public this(Device device, int width, int height) {
193 super(device); 198 super(device);
194 init_(width, height); 199 NSAutoreleasePool pool = null;
195 init_(); 200 if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
201 try {
202 init_(width, height);
203 init_();
204 } finally {
205 if (pool !is null) pool.release();
206 }
196 } 207 }
197 208
198 /** 209 /**
199 * Constructs a new instance of this class based on the 210 * Constructs a new instance of this class based on the
200 * provided image, with an appearance that varies depending 211 * provided image, with an appearance that varies depending
201 * on the value of the flag. The possible flag values are: 212 * on the value of the flag. The possible flag values are:
202 * <dl> 213 * <dl>
203 * <dt><b>IMAGE_COPY</b></dt> 214 * <dt><b>{@link DWT#IMAGE_COPY}</b></dt>
204 * <dd>the result is an identical copy of srcImage</dd> 215 * <dd>the result is an identical copy of srcImage</dd>
205 * <dt><b>IMAGE_DISABLE</b></dt> 216 * <dt><b>{@link DWT#IMAGE_DISABLE}</b></dt>
206 * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd> 217 * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd>
207 * <dt><b>IMAGE_GRAY</b></dt> 218 * <dt><b>{@link DWT#IMAGE_GRAY}</b></dt>
208 * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd> 219 * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd>
209 * </dl> 220 * </dl>
210 * 221 *
211 * @param device the device on which to create the image 222 * @param device the device on which to create the image
212 * @param srcImage the image to use as the source 223 * @param srcImage the image to use as the source
236 case DWT.IMAGE_GRAY: 247 case DWT.IMAGE_GRAY:
237 break; 248 break;
238 default: 249 default:
239 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 250 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
240 } 251 }
241 device = this.device; 252
242 this.type = srcImage.type; 253 NSAutoreleasePool pool = null;
243 254 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
244 /* Get source image size */ 255 try {
245 NSSize size = srcImage.handle.size(); 256 device = this.device;
257 this.type = srcImage.type;
258 /* Get source image size */
259 NSSize size = srcImage.handle.size();
246 int width = cast(int)size.width; 260 int width = cast(int)size.width;
247 int height = cast(int)size.height; 261 int height = cast(int)size.height;
248 NSBitmapImageRep srcRep = srcImage.imageRep; 262 NSBitmapImageRep srcRep = srcImage.imageRep;
249 NSInteger bpr = srcRep.bytesPerRow(); 263 NSInteger bpr = srcRep.bytesPerRow();
250 264
251 /* Copy transparent pixel and alpha data when necessary */ 265 /* Copy transparent pixel and alpha data when necessary */
252 transparentPixel = srcImage.transparentPixel; 266 transparentPixel = srcImage.transparentPixel;
253 alpha = srcImage.alpha; 267 alpha = srcImage.alpha;
254 if (srcImage.alphaData !is null) { 268 if (srcImage.alphaData !is null) {
255 alphaData = new byte[srcImage.alphaData.length]; 269 alphaData = new byte[srcImage.alphaData.length];
256 System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length); 270 System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
257 } 271 }
258 272
259 /* Create the image */ 273 /* Create the image */
260 handle = cast(NSImage)(new NSImage()).alloc(); 274 handle = cast(NSImage)(new NSImage()).alloc();
261 handle = handle.initWithSize(size); 275 handle = handle.initWithSize(size);
262 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc(); 276 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc();
263 rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(null, cast(NSInteger) width, cast(NSInteger) height, srcRep.bitsPerSample(), srcRep.samplesPerPixel(), srcRep.samplesPerPixel() is 4, srcRep.isPlanar(), OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat | NSAlphaNonpremultipliedBitmapFormat, srcRep.bytesPerRow(), srcRep.bitsPerPixel()); 277 rep = rep.initWithBitmapDataPlanes(null, width, height, srcRep.bitsPerSample(), srcRep.samplesPerPixel(), srcRep.samplesPerPixel() is 4, srcRep.isPlanar(), OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat | NSAlphaNonpremultipliedBitmapFormat, srcRep.bytesPerRow(), srcRep.bitsPerPixel());
264 handle.addRepresentation(rep); 278 handle.addRepresentation(rep);
265 279
266 objc.id data = rep.bitmapData(); 280 objc.id data = rep.bitmapData();
267 OS.memmove(data, srcImage.imageRep.bitmapData(), cast(size_t) (width * height * 4)); 281 OS.memmove(data, srcImage.imageRep.bitmapData(), width * height * 4);
268 if (flag !is DWT.IMAGE_COPY) { 282 if (flag !is DWT.IMAGE_COPY) {
269 283
270 /* Apply transformation */ 284 /* Apply transformation */
271 switch (flag) { 285 switch (flag) {
272 case DWT.IMAGE_DISABLE: { 286 case DWT.IMAGE_DISABLE: {
273 Color zeroColor = device.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW); 287 Color zeroColor = device.getSystemColor(DWT.COLOR_WIDGET_NORMAL_SHADOW);
274 RGB zeroRGB = zeroColor.getRGB(); 288 RGB zeroRGB = zeroColor.getRGB();
275 byte zeroRed = cast(byte)zeroRGB.red; 289 byte zeroRed = cast(byte)zeroRGB.red;
276 byte zeroGreen = cast(byte)zeroRGB.green; 290 byte zeroGreen = cast(byte)zeroRGB.green;
278 Color oneColor = device.getSystemColor(DWT.COLOR_WIDGET_BACKGROUND); 292 Color oneColor = device.getSystemColor(DWT.COLOR_WIDGET_BACKGROUND);
279 RGB oneRGB = oneColor.getRGB(); 293 RGB oneRGB = oneColor.getRGB();
280 byte oneRed = cast(byte)oneRGB.red; 294 byte oneRed = cast(byte)oneRGB.red;
281 byte oneGreen = cast(byte)oneRGB.green; 295 byte oneGreen = cast(byte)oneRGB.green;
282 byte oneBlue = cast(byte)oneRGB.blue; 296 byte oneBlue = cast(byte)oneRGB.blue;
283 byte[] line = new byte[bpr]; 297 byte[] line = new byte[(int)/*64*/bpr];
284 for (int y=0; y<height; y++) { 298 for (int y=0; y<height; y++) {
285 OS.memmove(line.ptr, data + (y * bpr), bpr); 299 OS.memmove(line.ptr, data + (y * bpr), bpr);
286 int offset = 0; 300 int offset = 0;
287 for (int x=0; x<width; x++) { 301 for (int x=0; x<width; x++) {
288 int red = line[offset+1] & 0xFF; 302 int red = line[offset+1] & 0xFF;
303 OS.memmove(data + (y * bpr), line.ptr, bpr); 317 OS.memmove(data + (y * bpr), line.ptr, bpr);
304 } 318 }
305 break; 319 break;
306 } 320 }
307 case DWT.IMAGE_GRAY: { 321 case DWT.IMAGE_GRAY: {
308 byte[] line = new byte[bpr]; 322 byte[] line = new byte[(int)/*64*/bpr];
309 for (int y=0; y<height; y++) { 323 for (int y=0; y<height; y++) {
310 OS.memmove(line.ptr, data + (y * bpr), bpr); 324 OS.memmove(line.ptr, data + (y * bpr), bpr);
311 int offset = 0; 325 int offset = 0;
312 for (int x=0; x<width; x++) { 326 for (int x=0; x<width; x++) {
313 int red = line[offset+1] & 0xFF; 327 int red = line[offset+1] & 0xFF;
319 } 333 }
320 OS.memmove(data + (y * bpr), line.ptr, bpr); 334 OS.memmove(data + (y * bpr), line.ptr, bpr);
321 } 335 }
322 break; 336 break;
323 } 337 }
324 } 338 }
325 } 339 }
326 init_(); 340 init_();
341 } finally {
342 if (pool !is null) pool.release();
343 }
327 } 344 }
328 345
329 /** 346 /**
330 * Constructs an empty instance of this class with the 347 * Constructs an empty instance of this class with the
331 * width and height of the specified rectangle. The result 348 * width and height of the specified rectangle. The result
357 * </ul> 374 * </ul>
358 */ 375 */
359 public this(Device device, Rectangle bounds) { 376 public this(Device device, Rectangle bounds) {
360 super(device); 377 super(device);
361 if (bounds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 378 if (bounds is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
362 init_(bounds.width, bounds.height); 379 NSAutoreleasePool pool = null;
363 init_(); 380 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
381 try {
382 init_(bounds.width, bounds.height);
383 init_();
384 } finally {
385 if (pool !is null) pool.release();
386 }
364 } 387 }
365 388
366 /** 389 /**
367 * Constructs an instance of this class from the given 390 * Constructs an instance of this class from the given
368 * <code>ImageData</code>. 391 * <code>ImageData</code>.
381 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> 404 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
382 * </ul> 405 * </ul>
383 */ 406 */
384 public this(Device device, ImageData data) { 407 public this(Device device, ImageData data) {
385 super(device); 408 super(device);
386 init_(data); 409 NSAutoreleasePool pool = null;
387 init_(); 410 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
411 try {
412 init_(data);
413 init_();
414 } finally {
415 if (pool !is null) pool.release();
416 }
388 } 417 }
389 418
390 /** 419 /**
391 * Constructs an instance of this class, whose type is 420 * Constructs an instance of this class, whose type is
392 * <code>DWT.ICON</code>, from the two given <code>ImageData</code> 421 * <code>DWT.ICON</code>, from the two given <code>ImageData</code>
417 if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 446 if (source is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
418 if (mask is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 447 if (mask is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
419 if (source.width !is mask.width || source.height !is mask.height) { 448 if (source.width !is mask.width || source.height !is mask.height) {
420 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 449 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
421 } 450 }
422 mask = ImageData.convertMask(mask); 451 NSAutoreleasePool pool = null;
423 ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data); 452 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
424 image.maskPad = mask.scanlinePad; 453 try {
425 image.maskData = mask.data; 454 mask = ImageData.convertMask(mask);
455 ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data);
456 image.maskPad = mask.scanlinePad;
457 image.maskData = mask.data;
426 init_(image); 458 init_(image);
459 } finally {
460 if (pool !is null) pool.release();
461 }
427 } 462 }
428 463
429 /** 464 /**
430 * Constructs an instance of this class by loading its representation 465 * Constructs an instance of this class by loading its representation
431 * from the specified input stream. Throws an error if an error 466 * from the specified input stream. Throws an error if an error
474 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> 509 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
475 * </ul> 510 * </ul>
476 */ 511 */
477 public this(Device device, InputStream stream) { 512 public this(Device device, InputStream stream) {
478 super(device); 513 super(device);
479 init_(new ImageData(stream)); 514 NSAutoreleasePool pool = null;
480 init_(); 515 if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
516 try {
517 init_(new ImageData(stream));
518 init_();
519 } finally {
520 if (pool !is null) pool.release();
521 }
481 } 522 }
482 523
483 /** 524 /**
484 * Constructs an instance of this class by loading its representation 525 * Constructs an instance of this class by loading its representation
485 * from the file with the specified name. Throws an error if an error 526 * from the file with the specified name. Throws an error if an error
507 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li> 548 * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
508 * </ul> 549 * </ul>
509 */ 550 */
510 public this(Device device, String filename) { 551 public this(Device device, String filename) {
511 super(device); 552 super(device);
512 init_(new ImageData(filename)); 553 NSAutoreleasePool pool = null;
513 init_(); 554 if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
555 try {
556 init_(new ImageData(filename));
557 init_();
558 } finally {
559 if (pool !is null) pool.release();
560 }
514 } 561 }
515 562
516 void createAlpha () { 563 void createAlpha () {
517 if (transparentPixel is -1 && alpha is -1 && alphaData is null) return; 564 if (transparentPixel is -1 && alpha is -1 && alphaData is null) return;
518 NSSize size = handle.size(); 565 NSAutoreleasePool pool = null;
566 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
567 try {
568 NSSize size = handle.size();
519 int height = cast(int)size.height; 569 int height = cast(int)size.height;
520 NSInteger bpr = imageRep.bytesPerRow(); 570 NSInteger bpr = imageRep.bytesPerRow();
521 size_t dataSize = height * bpr; 571 size_t dataSize = height * bpr;
522 byte[] srcData = new byte[dataSize]; 572 byte[] srcData = new byte[dataSize];
523 OS.memmove(srcData.ptr, imageRep.bitmapData(), dataSize); 573 OS.memmove(srcData.ptr, imageRep.bitmapData(), dataSize);
524 if (transparentPixel !is -1) { 574 if (transparentPixel !is -1) {
525 for (int i=0; i<dataSize; i+=4) { 575 for (int i=0; i<dataSize; i+=4) {
526 int pixel = ((srcData[i+1] & 0xFF) << 16) | ((srcData[i+2] & 0xFF) << 8) | (srcData[i+3] & 0xFF); 576 int pixel = ((srcData[i+1] & 0xFF) << 16) | ((srcData[i+2] & 0xFF) << 8) | (srcData[i+3] & 0xFF);
527 srcData[i] = cast(byte)(pixel is transparentPixel ? 0 : 0xFF); 577 srcData[i] = cast(byte)(pixel is transparentPixel ? 0 : 0xFF);
528 } 578 }
529 } else if (alpha !is -1) { 579 } else if (alpha !is -1) {
530 byte a = cast(byte)this.alpha; 580 byte a = cast(byte)this.alpha;
531 for (int i=0; i<dataSize; i+=4) { 581 for (int i=0; i<dataSize; i+=4) {
532 srcData[i] = a; 582 srcData[i] = a;
533 } 583 }
534 } else { 584 } else {
535 int width = cast(int)size.width; 585 int width = cast(int)size.width;
536 int offset = 0, alphaOffset = 0; 586 int offset = 0, alphaOffset = 0;
537 for (int y = 0; y<height; y++) { 587 for (int y = 0; y<height; y++) {
538 for (int x = 0; x<width; x++) { 588 for (int x = 0; x<width; x++) {
539 srcData[offset] = alphaData[alphaOffset]; 589 srcData[offset] = alphaData[alphaOffset];
540 offset += 4; 590 offset += 4;
541 alphaOffset += 1; 591 alphaOffset += 1;
592 }
542 } 593 }
543 } 594 }
544 }
545 OS.memmove(imageRep.bitmapData(), srcData.ptr, dataSize); 595 OS.memmove(imageRep.bitmapData(), srcData.ptr, dataSize);
596 } finally {
597 if (pool !is null) pool.release();
598 }
546 } 599 }
547 600
548 void destroy() { 601 void destroy() {
549 if (memGC !is null) memGC.dispose(); 602 if (memGC !is null) memGC.dispose();
550 if (imageRep !is null) imageRep.release(); 603 if (imageRep !is null) imageRep.release();
613 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li> 666 * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
614 * </ul> 667 * </ul>
615 */ 668 */
616 public Rectangle getBounds() { 669 public Rectangle getBounds() {
617 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 670 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
618 if (width !is -1 && height !is -1) { 671 NSAutoreleasePool pool = null;
619 return new Rectangle(0, 0, width, height); 672 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
620 } 673 try {
621 NSSize size = handle.size(); 674 if (width !is -1 && height !is -1) {
675 return new Rectangle(0, 0, width, height);
676 }
677 NSSize size = handle.size();
622 return new Rectangle(0, 0, width = cast(int)size.width, height = cast(int)size.height); 678 return new Rectangle(0, 0, width = cast(int)size.width, height = cast(int)size.height);
679 } finally {
680 if (pool !is null) pool.release();
681 }
623 } 682 }
624 683
625 /** 684 /**
626 * Returns an <code>ImageData</code> based on the receiver 685 * Returns an <code>ImageData</code> based on the receiver
627 * Modifications made to this <code>ImageData</code> will not 686 * Modifications made to this <code>ImageData</code> will not
636 * 695 *
637 * @see ImageData 696 * @see ImageData
638 */ 697 */
639 public ImageData getImageData() { 698 public ImageData getImageData() {
640 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 699 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
641 700 NSAutoreleasePool pool = null;
642 NSSize size = handle.size(); 701 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
702 try {
703 NSSize size = handle.size();
643 int width = cast(int)size.width; 704 int width = cast(int)size.width;
644 int height = cast(int)size.height; 705 int height = cast(int)size.height;
645 NSBitmapImageRep imageRep = this.imageRep; 706 NSBitmapImageRep imageRep = this.imageRep;
646 NSInteger bpr = imageRep.bytesPerRow(); 707 NSInteger bpr = imageRep.bytesPerRow();
647 NSInteger bpp = imageRep.bitsPerPixel(); 708 NSInteger bpp = imageRep.bitsPerPixel();
648 size_t dataSize = height * bpr; 709 size_t dataSize = height * bpr;
649 byte[] srcData = new byte[dataSize]; 710 byte[] srcData = new byte[dataSize];
650 OS.memmove(srcData.ptr, imageRep.bitmapData(), dataSize); 711 OS.memmove(srcData.ptr, imageRep.bitmapData(), dataSize);
651 712
652 PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF); 713 PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
653 ImageData data = new ImageData(width, height, bpp, palette); 714 ImageData data = new ImageData(width, height, (int)/*64*/bpp, palette, 4, srcData);
654 data.data = srcData; 715 data.bytesPerLine = (int)/*64*/bpr;
655 data.bytesPerLine = bpr; 716
656 717 data.transparentPixel = transparentPixel;
657 data.transparentPixel = transparentPixel; 718 if (transparentPixel is -1 && type is DWT.ICON) {
658 if (transparentPixel is -1 && type is DWT.ICON) { 719 /* Get the icon mask data */
659 /* Get the icon mask data */ 720 int maskPad = 2;
660 int maskPad = 2; 721 int maskBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
661 int maskBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; 722 byte[] maskData = new byte[height * maskBpl];
662 byte[] maskData = new byte[height * maskBpl]; 723 int offset = 0, maskOffset = 0;
663 int offset = 0, maskOffset = 0; 724 for (int y = 0; y<height; y++) {
664 for (int y = 0; y<height; y++) { 725 for (int x = 0; x<width; x++) {
665 for (int x = 0; x<width; x++) { 726 if (srcData[offset] !is 0) {
666 if (srcData[offset] !is 0) { 727 maskData[maskOffset + (x >> 3)] |= (1 << (7 - (x & 0x7)));
667 maskData[maskOffset + (x >> 3)] |= (1 << (7 - (x & 0x7))); 728 } else {
668 } else { 729 maskData[maskOffset + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
669 maskData[maskOffset + (x >> 3)] &= ~(1 << (7 - (x & 0x7))); 730 }
731 offset += 4;
670 } 732 }
671 offset += 4; 733 maskOffset += maskBpl;
672 } 734 }
673 maskOffset += maskBpl; 735 data.maskData = maskData;
674 } 736 data.maskPad = maskPad;
675 data.maskData = maskData; 737 }
676 data.maskPad = maskPad; 738 for (int i = 0; i < srcData.length; i+= 4) {
677 } 739 srcData[i] = 0;
678 for (int i = 0; i < srcData.length; i+= 4) { 740 }
679 srcData[i] = 0; 741 data.alpha = alpha;
680 } 742 if (alpha is -1 && alphaData !is null) {
681 data.alpha = alpha; 743 data.alphaData = new byte[alphaData.length];
682 if (alpha is -1 && alphaData !is null) { 744 System.arraycopy(alphaData, 0, data.alphaData, 0, alphaData.length);
683 data.alphaData = new byte[alphaData.length]; 745 }
684 System.arraycopy(alphaData, 0, data.alphaData, 0, alphaData.length); 746 return data;
685 } 747 } finally {
686 return data; 748 if (pool !is null) pool.release();
749 }
687 } 750 }
688 751
689 /** 752 /**
690 * Invokes platform specific functionality to allocate a new image. 753 * Invokes platform specific functionality to allocate a new image.
691 * <p> 754 * <p>
705 */ 768 */
706 public static Image cocoa_new(Device device, int type, NSImage nsImage) { 769 public static Image cocoa_new(Device device, int type, NSImage nsImage) {
707 Image image = new Image(device); 770 Image image = new Image(device);
708 image.type = type; 771 image.type = type;
709 image.handle = nsImage; 772 image.handle = nsImage;
710 NSImageRep rep = nsImage.bestRepresentationForDevice(null); 773 NSAutoreleasePool pool = null;
711 if (rep.isKindOfClass(NSBitmapImageRep.static_class())) { 774 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
712 image.imageRep = new NSBitmapImageRep(rep.id_); 775 try {
713 } 776 NSImageRep rep = nsImage.bestRepresentationForDevice(null);
714 return image; 777 if (rep.isKindOfClass(OS.class_NSBitmapImageRep)) {
778 rep.retain();
779 image.imageRep = new NSBitmapImageRep(rep.id_);
780 }
781 return image;
782 } finally {
783 if (pool !is null) pool.release();
784 }
715 } 785 }
716 786
717 /** 787 /**
718 * Returns an integer hash code for the receiver. Any two 788 * Returns an integer hash code for the receiver. Any two
719 * objects that return <code>true</code> when passed to 789 * objects that return <code>true</code> when passed to
742 NSSize size = NSSize(); 812 NSSize size = NSSize();
743 size.width = width; 813 size.width = width;
744 size.height = height; 814 size.height = height;
745 handle = handle.initWithSize(size); 815 handle = handle.initWithSize(size);
746 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc(); 816 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc();
747 rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_(null, cast(NSInteger) width, cast(NSInteger) height, 8, 3, false, false, OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat | NSAlphaNonpremultipliedBitmapFormat, cast(NSInteger) (width * 4), 32); 817 rep = rep.initWithBitmapDataPlanes_(null, width, height, 8, 3, false, false, OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat | NSAlphaNonpremultipliedBitmapFormat, width * 4, 32);
748 OS.memset(rep.bitmapData(), 0xFF, cast(size_t) (width * height * 4)); 818 OS.memset(rep.bitmapData(), 0xFF, cast(size_t) (width * height * 4));
749 handle.addRepresentation(rep); 819 handle.addRepresentation(rep);
750 // rep.release(); 820 // rep.release();
751 } 821 }
752 822
851 NSSize size = NSSize(); 921 NSSize size = NSSize();
852 size.width = width; 922 size.width = width;
853 size.height = height; 923 size.height = height;
854 handle = handle.initWithSize(size); 924 handle = handle.initWithSize(size);
855 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc(); 925 NSBitmapImageRep rep = imageRep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc();
856 rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_( 926 rep = rep.initWithBitmapDataPlanes(0, width, height, 8, hasAlpha ? 4 : 3, hasAlpha, false, OS.NSDeviceRGBColorSpace, OS.NSAlphaFirstBitmapFormat | OS.NSAlphaNonpremultipliedBitmapFormat, bpr, 32);
857 null, cast(NSInteger) width, cast(NSInteger) height, 8, hasAlpha ? 4 : 3, hasAlpha, false, OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat | NSAlphaNonpremultipliedBitmapFormat, cast(NSInteger) bpr, 32);
858 OS.memmove(rep.bitmapData(), buffer.ptr, dataSize); 927 OS.memmove(rep.bitmapData(), buffer.ptr, dataSize);
859 handle.addRepresentation(rep); 928 handle.addRepresentation(rep);
860 // rep.release(); 929 // rep.release();
861 } 930 }
862 931
876 public objc.id internal_new_GC (GCData data) { 945 public objc.id internal_new_GC (GCData data) {
877 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 946 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
878 if (type !is DWT.BITMAP || memGC !is null) { 947 if (type !is DWT.BITMAP || memGC !is null) {
879 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 948 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
880 } 949 }
881 NSGraphicsContext current = NSGraphicsContext.currentContext(); 950 NSAutoreleasePool pool = null;
882 NSBitmapImageRep rep = imageRep; 951 if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
883 if (imageRep.hasAlpha()) { 952 try {
953 NSBitmapImageRep rep = imageRep;
954 if (imageRep.hasAlpha()) {
884 NSInteger bpr = width * 4; 955 NSInteger bpr = width * 4;
885 rep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc(); 956 rep = cast(NSBitmapImageRep)(new NSBitmapImageRep()).alloc();
886 objc.id bitmapData = imageRep.bitmapData(); 957 objc.id bitmapData = imageRep.bitmapData();
887 if (data.bitmapDataAddress !is null) OS.free(data.bitmapDataAddress); 958 if (data.bitmapDataAddress !is null) OS.free(data.bitmapDataAddress);
888 data.bitmapDataAddress = cast(ubyte*) OS.malloc((void*).sizeof); 959 data.bitmapDataAddress = cast(ubyte*) OS.malloc(C.PTR_SIZEOF);
889 OS.memmove(data.bitmapDataAddress, bitmapData, (void*).sizeof); 960 OS.memmove(data.bitmapDataAddress, bitmapData, C.PTR_SIZEOF);
890 rep = rep.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bitmapFormat_bytesPerRow_bitsPerPixel_( 961 rep = rep.initWithBitmapDataPlanes(data.bitmapDataAddress, width, height, 8, 3, false, false, OS.NSDeviceRGBColorSpace, OS.NSAlphaFirstBitmapFormat , bpr, 32);
891 &data.bitmapDataAddress, cast(NSInteger) width, cast(NSInteger) height, 8, 3, false, false, OS.NSDeviceRGBColorSpace, NSAlphaFirstBitmapFormat , bpr, 32); 962 rep.autorelease();
892 rep.autorelease(); 963 }
893 } 964 handle.setCacheMode(OS.NSImageCacheNever);
894 NSGraphicsContext context = NSGraphicsContext.graphicsContextWithBitmapImageRep(rep); 965 NSGraphicsContext context = NSGraphicsContext.graphicsContextWithBitmapImageRep(rep);
895 NSGraphicsContext.setCurrentContext(context); 966 NSGraphicsContext.setCurrentContext(context);
896 NSAffineTransform transform = NSAffineTransform.transform(); 967 NSAffineTransform transform = NSAffineTransform.transform();
897 NSSize size = handle.size(); 968 NSSize size = handle.size();
898 transform.translateXBy(0, size.height); 969 transform.translateXBy(0, size.height);
899 transform.scaleXBy(1, -1); 970 transform.scaleXBy(1, -1);
900 transform.set(); 971 transform.set();
901 if (data !is null) { 972 if (data !is null) {
902 int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT; 973 int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
903 if ((data.style & mask) is 0) { 974 if ((data.style & mask) is 0) {
904 data.style |= DWT.LEFT_TO_RIGHT; 975 data.style |= DWT.LEFT_TO_RIGHT;
905 } 976 }
906 data.device = device; 977 data.device = device;
907 data.background = device.COLOR_WHITE.handle; 978 data.background = device.COLOR_WHITE.handle;
908 data.foreground = device.COLOR_BLACK.handle; 979 data.foreground = device.COLOR_BLACK.handle;
909 data.font = device.systemFont; 980 data.font = device.systemFont;
910 data.image = this; 981 data.image = this;
911 } 982 }
912 NSGraphicsContext.setCurrentContext(current);
913 return context.id_; 983 return context.id_;
984 } finally {
985 if (pool !is null) pool.release();
986 }
914 } 987 }
915 988
916 /** 989 /**
917 * Invokes platform specific functionality to dispose a GC handle. 990 * Invokes platform specific functionality to dispose a GC handle.
918 * <p> 991 * <p>
925 * 998 *
926 * @param hDC the platform specific GC handle 999 * @param hDC the platform specific GC handle
927 * @param data the platform specific GC data 1000 * @param data the platform specific GC data
928 */ 1001 */
929 public void internal_dispose_GC (objc.id context, GCData data) { 1002 public void internal_dispose_GC (objc.id context, GCData data) {
930 if (data.bitmapDataAddress !is null) OS.free(data.bitmapDataAddress); 1003 NSAutoreleasePool pool = null;
931 data.bitmapDataAddress = null; 1004 if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
1005 try {
1006 if (data.bitmapDataAddress !is null) OS.free(data.bitmapDataAddress);
1007 data.bitmapDataAddress = null;
1008 // handle.setCacheMode(OS.NSImageCacheDefault);
1009 } finally {
1010 if (pool !is null) pool.release();
1011 }
932 } 1012 }
933 1013
934 /** 1014 /**
935 * Returns <code>true</code> if the image has been disposed, 1015 * Returns <code>true</code> if the image has been disposed,
936 * and <code>false</code> otherwise. 1016 * and <code>false</code> otherwise.