Mercurial > projects > dwt-win
diff dwt/dnd/ImageTransfer.d @ 213:36f5cb12e1a2
Update to SWT 3.4M7
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 17 May 2008 17:34:28 +0200 |
parents | |
children | e2affbeb686d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/ImageTransfer.d Sat May 17 17:34:28 2008 +0200 @@ -0,0 +1,224 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwt.dnd.ImageTransfer; + +import dwt.DWT; +import dwt.graphics.Image; +import dwt.graphics.ImageData; +import dwt.graphics.RGB; +import dwt.internal.win32.OS; +import dwt.internal.ole.win32.COM; +import dwt.internal.ole.win32.OBJIDL; + +import dwt.dnd.ByteArrayTransfer; +import dwt.dnd.TransferData; +import dwt.dnd.DND; + +import dwt.dwthelper.utils; + +/** + * The class <code>ImageTransfer</code> provides a platform specific mechanism + * for converting a Image represented as a java <code>ImageData</code> to a + * platform specific representation of the data and vice versa. + * See <code>Transfer</code> for additional information. + * + * <p>An example of a java <code>ImageData</code> is shown + * below:</p> + * + * <code><pre> + * Image image = new Image("C:\temp\img1.gif"); + * ImageData imgData = image.getImageData(); + * </code></pre> + * + * @since 3.4 + */ +public class ImageTransfer : ByteArrayTransfer { + + private static ImageTransfer _instance; + private static const String CF_DIB = "CF_DIB"; //$NON-NLS-1$ + private static const int CF_DIBID = COM.CF_DIB; + +static this(){ + _instance = new ImageTransfer(); +} + +private 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 java <code>ImageData</code> to a platform specific representation. + * For additional information see <code>Transfer#javaToNative</code>. + * + * @param object a java <code>ImageData</code> containing the ImageData to be + * converted + * @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); + } + ImageData imgData = cast(ImageData)object; + if (imgData is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + + int imageSize = imgData.data.length; + int imageHeight = imgData.height; + int bytesPerLine = imgData.bytesPerLine; + + BITMAPINFOHEADER bmiHeader; + bmiHeader.biSize = BITMAPINFOHEADER.sizeof; + bmiHeader.biSizeImage = imageSize; + bmiHeader.biWidth = imgData.width; + bmiHeader.biHeight = imageHeight; + bmiHeader.biPlanes = 1; + bmiHeader.biBitCount = cast(short)imgData.depth; + bmiHeader.biCompression = OS.DIB_RGB_COLORS; + + int colorSize = 0; + if (bmiHeader.biBitCount <= 8) { + colorSize += (1 << bmiHeader.biBitCount) * 4; + } + byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize]; + OS.MoveMemory(bmi.ptr, &bmiHeader, BITMAPINFOHEADER.sizeof); + + RGB[] rgbs = imgData.palette.getRGBs(); + if (rgbs !is null && colorSize > 0) { + int offset = BITMAPINFOHEADER.sizeof; + for (int j = 0; j < rgbs.length; j++) { + bmi[offset] = cast(byte)rgbs[j].blue; + bmi[offset + 1] = cast(byte)rgbs[j].green; + bmi[offset + 2] = cast(byte)rgbs[j].red; + bmi[offset + 3] = 0; + offset += 4; + } + } + auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize); + OS.MoveMemory(newPtr, bmi.ptr, bmi.length); + auto pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize; + + if (imageHeight <= 0) { + OS.MoveMemory(pBitDest, imgData.data.ptr, imageSize); + } else { + int offset = 0; + pBitDest += bytesPerLine * (imageHeight - 1); + byte[] scanline = new byte[bytesPerLine]; + for (int i = 0; i < imageHeight; i++) { + System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine); + OS.MoveMemory(pBitDest, scanline.ptr, bytesPerLine); + offset += bytesPerLine; + pBitDest -= bytesPerLine; + } + } + transferData.stgmedium = new STGMEDIUM(); + transferData.stgmedium.tymed = COM.TYMED_HGLOBAL; + transferData.stgmedium.unionField = newPtr; + transferData.stgmedium.pUnkForRelease = null; + transferData.result = COM.S_OK; +} + + +/** + * This implementation of <code>nativeToJava</code> converts a platform specific + * representation of an image to java <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> of the image if + * conversion was successful; otherwise null + */ +public Object nativeToJava(TransferData transferData) { + if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null; + IDataObject dataObject = cast(IDataObject)(transferData.pIDataObject); + dataObject.AddRef(); + FORMATETC* formatetc = new FORMATETC(); + formatetc.cfFormat = COM.CF_DIB; + formatetc.ptd = null; + formatetc.dwAspect = COM.DVASPECT_CONTENT; + formatetc.lindex = -1; + formatetc.tymed = COM.TYMED_HGLOBAL; + STGMEDIUM* stgmedium = new STGMEDIUM(); + stgmedium.tymed = COM.TYMED_HGLOBAL; + transferData.result = dataObject.GetData(formatetc, stgmedium); + + if (transferData.result !is COM.S_OK) return null; + HANDLE hMem = stgmedium.unionField; + dataObject.Release(); + try { + auto ptr = OS.GlobalLock(hMem); + if (ptr is null) return null; + try { + BITMAPINFOHEADER bmiHeader; + OS.MoveMemory(&bmiHeader, ptr, BITMAPINFOHEADER.sizeof); + void* pBits; + auto memDib = OS.CreateDIBSection(null, cast(BITMAPINFO*)ptr, OS.DIB_RGB_COLORS, &pBits, null, 0); + if (memDib is null) DWT.error(DWT.ERROR_NO_HANDLES); + void* bits = ptr + bmiHeader.biSize; + if (bmiHeader.biBitCount <= 8) { + bits += (1 << bmiHeader.biBitCount) * 4; + } else if (bmiHeader.biCompression is OS.BI_BITFIELDS) { + bits += 12; + } + if (bmiHeader.biHeight < 0) { + OS.MoveMemory(pBits, bits, bmiHeader.biSizeImage); + } else { + DIBSECTION dib; + OS.GetObject(memDib, DIBSECTION.sizeof, &dib); + int biHeight = dib.biHeight; + int scanline = dib.biSizeImage / biHeight; + auto pDestBits = pBits; + auto pSourceBits = bits + scanline * (biHeight - 1); + for (int i = 0; i < biHeight; i++) { + OS.MoveMemory(pDestBits, pSourceBits, scanline); + pDestBits += scanline; + pSourceBits -= scanline; + } + } + Image image = Image.win32_new(null, DWT.BITMAP, memDib); + ImageData data = image.getImageData(); + OS.DeleteObject(memDib); + image.dispose(); + return data; + } finally { + OS.GlobalUnlock(hMem); + } + } finally { + OS.GlobalFree(hMem); + } +} + +protected int[] getTypeIds(){ + return [CF_DIBID]; +} + +protected String[] getTypeNames(){ + return [CF_DIB]; +} +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); +} +} +