]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ImageTransfer.java
Merge branch 'bug-623' into release/1.43.0
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / dnd / ImageTransfer.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2017 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.dnd;
15
16 import org.eclipse.swt.*;
17 import org.eclipse.swt.graphics.*;
18 import org.eclipse.swt.internal.*;
19 import org.eclipse.swt.internal.ole.win32.*;
20 import org.eclipse.swt.internal.win32.*;
21
22 /**
23  * The class <code>ImageTransfer</code> provides a platform specific mechanism
24  * for converting an Image represented as a java <code>ImageData</code> to a
25  * platform specific representation of the data and vice versa.
26  *
27  * <p>An example of a java <code>ImageData</code> is shown below:</p>
28  *
29  * <pre><code>
30  *     Image image = new Image(display, "C:\\temp\\img1.gif");
31  *     ImageData imgData = image.getImageData();
32  * </code></pre>
33  *
34  * @see Transfer
35  *
36  * @since 3.4
37  */
38 public class ImageTransfer extends ByteArrayTransfer {
39
40         private static ImageTransfer _instance = new ImageTransfer();
41         private static final String CF_DIB = "CF_DIB"; //$NON-NLS-1$
42         private static final int CF_DIBID = COM.CF_DIB;
43
44 private ImageTransfer() {}
45
46 /**
47  * Returns the singleton instance of the ImageTransfer class.
48  *
49  * @return the singleton instance of the ImageTransfer class
50  */
51 public static ImageTransfer getInstance () {
52         return _instance;
53 }
54
55 /**
56  * This implementation of <code>javaToNative</code> converts an ImageData object represented
57  * by java <code>ImageData</code> to a platform specific representation.
58  *
59  * @param object a java <code>ImageData</code> containing the ImageData to be converted
60  * @param transferData an empty <code>TransferData</code> object that will
61  *      be filled in on return with the platform specific format of the data
62  *
63  * @see Transfer#nativeToJava
64  */
65 @Override
66 public void javaToNative(Object object, TransferData transferData) {
67         if (!checkImage(object) || !isSupportedType(transferData)) {
68                 DND.error(DND.ERROR_INVALID_DATA);
69         }
70         ImageData imgData = (ImageData)object;
71         if (imgData == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
72
73         int imageSize = imgData.data.length;
74         int imageHeight = imgData.height;
75         int bytesPerLine = imgData.bytesPerLine;
76
77         BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
78         bmiHeader.biSize = BITMAPINFOHEADER.sizeof;
79         bmiHeader.biSizeImage = imageSize;
80         bmiHeader.biWidth = imgData.width;
81         bmiHeader.biHeight = imageHeight;
82         bmiHeader.biPlanes = 1;
83         bmiHeader.biBitCount = (short)imgData.depth;
84         bmiHeader.biCompression = OS.DIB_RGB_COLORS;
85
86         int colorSize = 0;
87         if (bmiHeader.biBitCount <= 8) {
88                 colorSize += (1 << bmiHeader.biBitCount) * 4;
89         }
90         byte[] bmi = new byte[BITMAPINFOHEADER.sizeof + colorSize];
91         OS.MoveMemory(bmi, bmiHeader, BITMAPINFOHEADER.sizeof);
92
93         RGB[] rgbs = imgData.palette.getRGBs();
94         if (rgbs != null && colorSize > 0) {
95                 int offset = BITMAPINFOHEADER.sizeof;
96                 for (int j = 0; j < rgbs.length; j++) {
97                         bmi[offset] = (byte)rgbs[j].blue;
98                         bmi[offset + 1] = (byte)rgbs[j].green;
99                         bmi[offset + 2] = (byte)rgbs[j].red;
100                         bmi[offset + 3] = 0;
101                         offset += 4;
102                 }
103         }
104         long newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, BITMAPINFOHEADER.sizeof + colorSize + imageSize);
105         OS.MoveMemory(newPtr, bmi, bmi.length);
106         long pBitDest = newPtr + BITMAPINFOHEADER.sizeof + colorSize;
107
108         if (imageHeight <= 0) {
109                 OS.MoveMemory(pBitDest, imgData.data, imageSize);
110         } else {
111                 int offset = 0;
112                 pBitDest += bytesPerLine * (imageHeight - 1);
113                 byte[] scanline = new byte[bytesPerLine];
114                 for (int i = 0; i < imageHeight; i++) {
115                         System.arraycopy(imgData.data, offset, scanline, 0, bytesPerLine);
116                         OS.MoveMemory(pBitDest, scanline, bytesPerLine);
117                         offset += bytesPerLine;
118                         pBitDest -= bytesPerLine;
119                 }
120         }
121         transferData.stgmedium = new STGMEDIUM();
122         transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
123         transferData.stgmedium.unionField = newPtr;
124         transferData.stgmedium.pUnkForRelease = 0;
125         transferData.result = COM.S_OK;
126 }
127
128
129 /**
130  * This implementation of <code>nativeToJava</code> converts a platform specific
131  * representation of an image to java <code>ImageData</code>.
132  *
133  * @param transferData the platform specific representation of the data to be converted
134  * @return a java <code>ImageData</code> of the image if the conversion was successful;
135  *              otherwise null
136  *
137  * @see Transfer#javaToNative
138  */
139 @Override
140 public Object nativeToJava(TransferData transferData) {
141         if (!isSupportedType(transferData) || transferData.pIDataObject == 0) return null;
142         IDataObject dataObject = new IDataObject(transferData.pIDataObject);
143         dataObject.AddRef();
144         FORMATETC formatetc = new FORMATETC();
145         formatetc.cfFormat = COM.CF_DIB;
146         formatetc.ptd = 0;
147         formatetc.dwAspect = COM.DVASPECT_CONTENT;
148         formatetc.lindex = -1;
149         formatetc.tymed = COM.TYMED_HGLOBAL;
150         STGMEDIUM stgmedium = new STGMEDIUM();
151         stgmedium.tymed = COM.TYMED_HGLOBAL;
152         transferData.result = getData(dataObject, formatetc, stgmedium);
153
154         if (transferData.result != COM.S_OK) return null;
155         long hMem = stgmedium.unionField;
156         dataObject.Release();
157         try {
158                 long ptr = OS.GlobalLock(hMem);
159                 if (ptr == 0) return null;
160                 try {
161                         BITMAPINFOHEADER bmiHeader = new BITMAPINFOHEADER();
162                         OS.MoveMemory(bmiHeader, ptr, BITMAPINFOHEADER.sizeof);
163                         long[] pBits = new long[1];
164                         long memDib = OS.CreateDIBSection(0, ptr, OS.DIB_RGB_COLORS, pBits, 0, 0);
165                         if (memDib == 0) SWT.error(SWT.ERROR_NO_HANDLES);
166                         long bits = ptr + bmiHeader.biSize;
167                         if (bmiHeader.biBitCount <= 8) {
168                                 bits += (bmiHeader.biClrUsed == 0 ? (1 << bmiHeader.biBitCount) : bmiHeader.biClrUsed) * 4;
169                         } else if (bmiHeader.biCompression == OS.BI_BITFIELDS) {
170                                 bits += 12;
171                         }
172                         if (bmiHeader.biHeight < 0) {
173                                 OS.MoveMemory(pBits[0], bits, bmiHeader.biSizeImage);
174                         } else {
175                                 DIBSECTION dib = new DIBSECTION();
176                                 OS.GetObject(memDib, DIBSECTION.sizeof, dib);
177                                 int biHeight = dib.biHeight;
178                                 int scanline = dib.biSizeImage / biHeight;
179                                 long pDestBits = pBits[0];
180                                 long pSourceBits = bits + scanline * (biHeight - 1);
181                                 for (int i = 0; i < biHeight; i++) {
182                                         OS.MoveMemory(pDestBits, pSourceBits, scanline);
183                                         pDestBits += scanline;
184                                         pSourceBits -= scanline;
185                                 }
186                         }
187                         Image image = Image.win32_new(null, SWT.BITMAP, memDib);
188                         ImageData data = image.getImageData (DPIUtil.getDeviceZoom ());
189                         OS.DeleteObject(memDib);
190                         image.dispose();
191                         return data;
192                 } finally {
193                         OS.GlobalUnlock(hMem);
194                 }
195         } finally {
196                 OS.GlobalFree(hMem);
197         }
198 }
199
200 @Override
201 protected int[] getTypeIds(){
202         return new int[] {CF_DIBID};
203 }
204
205 @Override
206 protected String[] getTypeNames(){
207         return new String[] {CF_DIB};
208 }
209 boolean checkImage(Object object) {
210         if (object == null || !(object instanceof ImageData))  return false;
211         return true;
212 }
213
214 @Override
215 protected boolean validate(Object object) {
216         return checkImage(object);
217 }
218 }