view dwt/dnd/ImageTransfer.d @ 8:a9ab4c738ed8

Fix: instanceof
author Frank Benoit <benoit@tionex.de>
date Wed, 27 Aug 2008 14:32:39 +0200
parents e831403a80a9
children d8635bb48c7c
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Outhink - support for typeFileURL
 *******************************************************************************/
module dwt.dnd;

import dwt.DWT;
import dwt.graphics.*;
import dwt.internal.carbon.*;
import dwt.widgets.*;

/**
 * The class <code>ImageTransfer</code> provides a platform specific mechanism
 * for converting an Image represented as a java <code>ImageData</code> to a
 * platform specific representation of the data and vice versa. The
 * <code>ImageData</code> contains infomration about the Image. See
 * <code>Transfer</code> for additional information.
 * 
 * <p>
 * An example of a java <code>Image</code> containing an ImageData is shown
 * below:
 * </p>
 * 
 * <code><pre>
 * Image image = new Image(display, fileName);
 * ImageData imgData = image.getImageData();
 * </code></pre>
 */
public class ImageTransfer : ByteArrayTransfer {

static ImageTransfer _instance = new ImageTransfer();
static final String PICT = "PICT"; //$NON-NLS-1$
static final String TIFF = "TIFF"; //$NON-NLS-1$
static final int PICTID = registerType(PICT);
static final int TIFFID = registerType(TIFF);

this() {
}

/**
 * Returns the singleton instance of the ImageTransfer class.
 * 
 * @return the singleton instance of the ImageTransfer class
 */
public static ImageTransfer getInstance() {
    return _instance;
}

/**
 * This implementation of <code>javaToNative</code> converts an ImageData
 * object represented by a java <code>ImageData</code> to a platform
 * specific representation. For additional information see
 * <code>Transfer#javaToNative</code>.
 * 
 * @param object
 *            a java <code>ImageData</code>
 * @param transferData
 *            an empty <code>TransferData</code> object; this object will
 *            be filled in on return with the platform specific format of
 *            the data
 */
public void javaToNative(Object object, TransferData transferData) {
    if (!checkImage(object) || !isSupportedType(transferData)) {
        DND.error(DND.ERROR_INVALID_DATA);
    }
    transferData.result = -1;

    ImageData imgData = cast(ImageData) object;
    Image image = new Image(Display.getCurrent(), imgData);
    int handle = image.handle;
    int width = OS.CGImageGetWidth(handle);
    int height = OS.CGImageGetHeight(handle);
    int alphaInfo = OS.CGImageGetAlphaInfo(handle);
    int bpr = OS.CGImageGetBytesPerRow(handle);

    Rect rect = new Rect();
    rect.left = 0;
    rect.top = 0;
    rect.right = cast(short) width;
    rect.bottom = cast(short) height;

    int[] gWorld = new int[1];
    int format = OS.k24RGBPixelFormat;
    if (alphaInfo !is OS.kCGImageAlphaNoneSkipFirst) {
        format = OS.k32ARGBPixelFormat;
    }
    OS.NewGWorldFromPtr(gWorld, format, rect, 0, 0, 0, image.data, bpr);
    int[] curPort = new int[1];
    int[] curGWorld = new int[1];
    OS.GetGWorld(curPort, curGWorld);
    OS.SetGWorld(gWorld[0], curGWorld[0]);
    int pictHandle = OS.OpenPicture(rect);
    int portBitMap = OS.GetPortBitMapForCopyBits(gWorld[0]);
    OS.CopyBits(portBitMap, portBitMap, rect, rect, cast(short) OS.srcCopy, 0);
    OS.ClosePicture();
    OS.SetGWorld(curPort[0], curGWorld[0]);
    OS.DisposeGWorld(gWorld[0]);
    int length = OS.GetHandleSize(pictHandle);
    OS.HLock(pictHandle);
    int[] buffer = new int[1];
    OS.memmove(buffer, pictHandle, 4);
    byte[] pictData = new byte[length];
    OS.memmove(pictData, buffer[0], length);
    OS.HUnlock(pictHandle);
    OS.KillPicture(pictHandle);
    image.dispose();

    transferData.data = new byte[][] { pictData };
    transferData.result = OS.noErr;
}

/**
 * This implementation of <code>nativeToJava</code> converts a platform
 * specific representation of an ImageData <code>ImageData</code>. For
 * additional information see <code>Transfer#nativeToJava</code>.
 * 
 * @param transferData
 *            the platform specific representation of the data to be been
 *            converted
 * @return a java <code>ImageData</code> object if the conversion was
 *         successful; otherwise null
 */
public Object nativeToJava(TransferData transferData) {
    if (!isSupportedType(transferData) || transferData.data is null)
        return null;
    if (transferData.data.length is 0)
        return null;
    byte[] dataArr = transferData.data[0];
    int size = dataArr.length;
    int pictPtr = OS.NewPtr(size);
    OS.memmove(pictPtr, dataArr, size);
    int dataProvider = OS.CGDataProviderCreateWithData(0, pictPtr, size, 0);
    if (dataProvider !is 0) {
        int pictDataRef = OS.QDPictCreateWithProvider(dataProvider);
        // get bounds for the image
        CGRect rect = new CGRect();
        OS.QDPictGetBounds(pictDataRef, rect);
        int width = cast(int) rect.width;
        int height = cast(int) rect.height;

        /* Create the image */
        int bpr = width * 4;
        int dataSize = height * bpr;
        int data = OS.NewPtr(dataSize);
        if (data is 0)
            DWT.error(DWT.ERROR_NO_HANDLES);
        int provider = OS
                .CGDataProviderCreateWithData(0, data, dataSize, 0);
        if (provider is 0) {
            OS.DisposePtr(data);
            DWT.error(DWT.ERROR_NO_HANDLES);
        }
        int colorspace = OS.CGColorSpaceCreateDeviceRGB();
        if (colorspace is 0)
            DWT.error(DWT.ERROR_NO_HANDLES);
        int handle = OS.CGImageCreate(width, height, 8, 32, bpr,
                colorspace, OS.kCGImageAlphaNoneSkipFirst, provider, null,
                true, 0);
        OS.CGDataProviderRelease(provider);
        if (handle is 0) {
            OS.DisposePtr(data);
            DWT.error(DWT.ERROR_NO_HANDLES);
        }
        int bpc = OS.CGImageGetBitsPerComponent(handle);
        int context = OS.CGBitmapContextCreate(data, width, height, bpc,
                bpr, colorspace, OS.kCGImageAlphaNoneSkipFirst);
        if (context is 0) {
            OS.CGImageRelease(handle);
            OS.DisposePtr(data);
            DWT.error(DWT.ERROR_NO_HANDLES);
        }
        int status = OS.QDPictDrawToCGContext(context, rect, pictDataRef);
        ImageData imgData = null;
        if (status is 0) {
            Image image = Image.carbon_new(Display.getCurrent(),
                    DWT.BITMAP, handle, data);
            imgData = image.getImageData();
            image.dispose();
        }
        OS.CGContextRelease(context);
        OS.QDPictRelease(pictDataRef);
        return imgData;
    }
    return null;
}

protected int[] getTypeIds() {
    return new int[] { PICTID };
}

protected String[] getTypeNames() {
    return new String[] { PICT };
}

bool checkImage(Object object) {
    if (object is null || !( null !is cast(ImageData)object )) return false;
    return true;
}

protected bool validate(Object object) {
    return checkImage(object);
}
}