|
Java example source code file (awt_DataTransferer.cpp)
The awt_DataTransferer.cpp Java example source code/* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "awt.h" #include "awt_DataTransferer.h" #include "awt_DnDDT.h" #include "awt_TextComponent.h" #include <shlobj.h> #include <shellapi.h> #include <sun_awt_windows_WDataTransferer.h> #include "locale_str.h" #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) #define WIN_TO_JAVA_PIXEL(r, g, b) (0xFF000000 | (r) << 16 | (g) << 8 | (b) << 0) DECLARE_JAVA_CLASS(dataTransfererClazz, "sun/awt/datatransfer/DataTransferer"); jobject AwtDataTransferer::GetDataTransferer(JNIEnv* env) { DECLARE_STATIC_OBJECT_JAVA_METHOD(getInstanceMethodID, dataTransfererClazz, "getInstance", "()Lsun/awt/datatransfer/DataTransferer;"); return env->CallStaticObjectMethod(clazz, getInstanceMethodID); } jbyteArray AwtDataTransferer::ConvertData(JNIEnv* env, jobject source, jobject contents, jlong format, jobject formatMap) { jobject transferer = GetDataTransferer(env); if (!JNU_IsNull(env, transferer)) { jbyteArray ret = NULL; DECLARE_OBJECT_JAVA_METHOD(convertDataMethodID, dataTransfererClazz, "convertData", "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B"); ret = (jbyteArray)env->CallObjectMethod(transferer, convertDataMethodID, source, contents, format, formatMap, AwtToolkit::IsMainThread()); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } env->DeleteLocalRef(transferer); return ret; } else { return NULL; } } jobject AwtDataTransferer::ConcatData(JNIEnv* env, jobject obj1, jobject obj2) { jobject transferer = GetDataTransferer(env); if (!JNU_IsNull(env, transferer)) { jobject ret = NULL; DECLARE_OBJECT_JAVA_METHOD(concatDataMethodID, dataTransfererClazz, "concatData", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); ret = env->CallObjectMethod(transferer, concatDataMethodID, obj1, obj2); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); } env->DeleteLocalRef(transferer); return ret; } else { return NULL; } } /** * This routine retrieves palette entries from enhanced metafile or * a logical color palette, builds appropriate LOGPALETTE structure, * writes it into a created Java byte array and returns a local * reference to the array. * This routine is used for image data transfer. * * @param hGdiObj - a handle to the GDI object to retrieve palette entries from, * it can be a handle to either a logical color palette (OBJ_PAL type) * or an enhanced metafile (OBJ_ENHMETAFILE). If it is neither of these * types the routine fails(see bFailSafe). * @param dwGdiObjType - a type of the passed GDI object. It should be specified * if the type of the passed GDI object is known to the caller. Otherwise * pass 0. * @param bFailSafe - if FALSE, the routine will return NULL in case of failure, * otherwise it will return an array with empty LOGPALETTE structure * in case of failure. * @return a local reference to Java byte array which contains LOGPALETTE * structure which defines a logical color palette or a palette of * an enhanced metafile. */ jbyteArray AwtDataTransferer::GetPaletteBytes(HGDIOBJ hGdiObj, DWORD dwGdiObjType, BOOL bFailSafe) { if (hGdiObj == NULL) { dwGdiObjType = 0; } else if (dwGdiObjType == 0) { dwGdiObjType = ::GetObjectType(hGdiObj); } else { DASSERT(::GetObjectType(hGdiObj) == dwGdiObjType); } if (!bFailSafe && dwGdiObjType == 0) { return NULL; } UINT nEntries = 0; switch (dwGdiObjType) { case OBJ_PAL: nEntries = ::GetPaletteEntries((HPALETTE)hGdiObj, 0, 0, NULL); break; case OBJ_ENHMETAFILE: nEntries = ::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, 0, NULL); break; } if (!bFailSafe && (nEntries == 0 || nEntries == GDI_ERROR)) { return NULL; } JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jsize size = sizeof(LOGPALETTE) + nEntries * sizeof(PALETTEENTRY); jbyteArray paletteBytes = env->NewByteArray(size); if (JNU_IsNull(env, paletteBytes)) { throw std::bad_alloc(); } LOGPALETTE* pLogPalette = (LOGPALETTE*)env->GetPrimitiveArrayCritical(paletteBytes, NULL); PALETTEENTRY* pPalEntries = (PALETTEENTRY*)pLogPalette->palPalEntry; pLogPalette->palVersion = 0x300; pLogPalette->palNumEntries = nEntries; switch (dwGdiObjType) { case OBJ_PAL: VERIFY(::GetPaletteEntries((HPALETTE)hGdiObj, 0, nEntries, pPalEntries) == nEntries); break; case OBJ_ENHMETAFILE: VERIFY(::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, nEntries, pPalEntries) == nEntries); break; } env->ReleasePrimitiveArrayCritical(paletteBytes, pLogPalette, 0); return paletteBytes; } jbyteArray AwtDataTransferer::LCIDToTextEncoding(JNIEnv *env, LCID lcid) { LANGID langID = LANGIDFROMLCID(lcid); const char *encoding = getEncodingFromLangID(langID); // Warning C4244. // Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit) // to jsize (long). // We assume that the encoding name length cannot exceed INT_MAX. jsize length = (jsize)strlen(encoding); jbyteArray retval = env->NewByteArray(length); if (retval == NULL) { throw std::bad_alloc(); } env->SetByteArrayRegion(retval, 0, length, (jbyte *)encoding); free((void *)encoding); return retval; } static VOID CALLBACK IdleFunc() { /* * Fix for 4485987 and 4669873. * If IdleFunc is a noop, the secondary message pump occasionally occupies * all processor time and causes drag freezes. GetQueueStatus is needed to * mark all messages that are currently in the queue as old, otherwise * WaitMessage will return immediatelly as we selectively get messages from * the queue. */ ::WaitMessage(); ::GetQueueStatus(QS_ALLINPUT); } static BOOL CALLBACK PeekMessageFunc(MSG& msg) { return ::PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE) || ::PeekMessage(&msg, NULL, WM_AWT_INVOKE_METHOD, WM_AWT_INVOKE_METHOD, PM_REMOVE) || ::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE); } void AwtDataTransferer::SecondaryMessageLoop() { DASSERT(AwtToolkit::MainThread() == ::GetCurrentThreadId()); AwtToolkit::GetInstance().MessageLoop(IdleFunc, PeekMessageFunc); } extern "C" { /* * Class: sun_awt_datatransfer_DataTransferer * Method: draqQueryFile * Signature: ([B)[Ljava/lang/String; */ JNIEXPORT jobjectArray JNICALL Java_sun_awt_windows_WDataTransferer_dragQueryFile (JNIEnv *env, jobject obj, jbyteArray bytes) { TRY; /* * Fix for the BugTraq ID 4327064 - inter-jvm DnD crashes the droping jvm. * On Win9X DragQueryFile() doesn't accept a pointer to the local help as the first * argument, so we should dump the bits into global memory. */ UINT size = env->GetArrayLength(bytes); HGLOBAL hglobal = NULL; jbyte *bBytes = NULL; HDROP hdrop = NULL; LPTSTR buffer = NULL; hglobal = ::GlobalAlloc(GALLOCFLG, size); if (hglobal == NULL) { throw std::bad_alloc(); } try { bBytes = (jbyte*)::GlobalLock(hglobal); env->GetByteArrayRegion(bytes, 0, size, bBytes); hdrop = (HDROP)bBytes; UINT nFilenames = ::DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); jclass str_clazz = env->FindClass("java/lang/String"); DASSERT(str_clazz != NULL); jobjectArray filenames = env->NewObjectArray(nFilenames, str_clazz, NULL); if (filenames == NULL) { throw std::bad_alloc(); } UINT bufsize = 512; // in characters, not in bytes buffer = (LPTSTR)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, bufsize, sizeof(TCHAR)); for (UINT i = 0; i < nFilenames; i++) { UINT size = ::DragQueryFile(hdrop, i, NULL, 0); if (size > bufsize) { bufsize = size; buffer = (LPTSTR)SAFE_SIZE_ARRAY_REALLOC(safe_Realloc, buffer, bufsize, sizeof(TCHAR)); } ::DragQueryFile(hdrop, i, buffer, bufsize); jstring name = JNU_NewStringPlatform(env, buffer); if (name == NULL) { throw std::bad_alloc(); } env->SetObjectArrayElement(filenames, i, name); } free(buffer); ::GlobalUnlock(hglobal); ::GlobalFree(hglobal); return filenames; } catch (std::bad_alloc&) { free(buffer); ::GlobalUnlock(hglobal); ::GlobalFree(hglobal); throw; } CATCH_BAD_ALLOC_RET(NULL); } /* * Class: sun_awt_windows_WDataTransferer * Method: platformImageBytesToImageData * Signature: ([BI)[I */ JNIEXPORT jintArray JNICALL Java_sun_awt_windows_WDataTransferer_platformImageBytesToImageData( JNIEnv *env, jobject self, jbyteArray bytes, jlong format) { TRY; HDC hdc = NULL; LOGPALETTE* pLogPalette = NULL; WORD uPaletteEntries = 0; SIZE_T uOffset = 0; HPALETTE hPalette = NULL; HPALETTE hOldPalette = NULL; BITMAPINFO* pSrcBmi = NULL; BITMAPINFOHEADER* pSrcBmih = NULL; LPVOID pSrcBits = NULL; BITMAPINFO* pDstBmi = NULL; BITMAPINFOHEADER* pDstBmih = NULL; LPVOID pDstBits = NULL; LPBYTE lpEnhMetaFileBits = NULL; HENHMETAFILE hEnhMetaFile = NULL; HBITMAP hDibSection = NULL; HBITMAP hOldBitmap = NULL; jintArray buffer = NULL; LONG width = 0; LONG height = 0; int numPixels = 0; if (JNU_IsNull(env, bytes)) { return NULL; } jsize size = env->GetArrayLength(bytes); if (size == 0) { return NULL; } jbyte* bBytes = (jbyte*)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, size, sizeof(jbyte)); try { env->GetByteArrayRegion(bytes, 0, size, bBytes); pLogPalette = (LOGPALETTE*)bBytes; uPaletteEntries = pLogPalette->palNumEntries; uOffset = sizeof(LOGPALETTE) + uPaletteEntries * sizeof(PALETTEENTRY); DASSERT(uOffset < (SIZE_T)size); if (uPaletteEntries == 0) { pLogPalette = NULL; } hdc = ::CreateCompatibleDC(NULL); if (hdc == NULL) { free(bBytes); return NULL; } switch (format) { case CF_DIB: pSrcBmi = (BITMAPINFO*)((LPSTR)bBytes + uOffset); pSrcBmih = &pSrcBmi->bmiHeader; width = pSrcBmih->biWidth; height = abs(pSrcBmih->biHeight); { DWORD nColorEntries = 0; switch (pSrcBmih->biBitCount) { case 0: nColorEntries = 0; break; case 1: nColorEntries = 2; break; case 4: case 8: nColorEntries = (pSrcBmih->biClrUsed != 0) ? pSrcBmih->biClrUsed : (1 << pSrcBmih->biBitCount); break; case 16: case 24: case 32: nColorEntries = pSrcBmih->biClrUsed; // If biBitCount is 16 or 32 and biCompression is // BI_BITFIELDS the color table will be prefixed with // three DWORD color masks. if (pSrcBmih->biCompression == BI_BITFIELDS && (pSrcBmih->biBitCount == 16 || pSrcBmih->biBitCount == 32)) { nColorEntries += 3; } break; default: // The header is probably corrupted. // Fail immediatelly to avoid memory access violation. free(bBytes); ::DeleteDC(hdc); return NULL; } pSrcBits = (LPSTR)pSrcBmi + pSrcBmih->biSize + nColorEntries * sizeof(RGBQUAD); } break; case CF_ENHMETAFILE: case CF_METAFILEPICT: lpEnhMetaFileBits = (BYTE*)bBytes + uOffset; // Warning C4244. size is jsize, uOffset is SIZE_T. // We assert that size > uOffset, so it is safe to cast to jsize. hEnhMetaFile = ::SetEnhMetaFileBits(size - (jsize)uOffset, lpEnhMetaFileBits); DASSERT(hEnhMetaFile != NULL); { UINT uHeaderSize = ::GetEnhMetaFileHeader(hEnhMetaFile, 0, NULL); DASSERT(uHeaderSize != 0); ENHMETAHEADER* lpemh = (ENHMETAHEADER*)safe_Malloc(uHeaderSize); VERIFY(::GetEnhMetaFileHeader(hEnhMetaFile, uHeaderSize, lpemh) == uHeaderSize); LPRECTL lpFrame = &lpemh->rclFrame; POINT p = { abs(lpFrame->right - lpFrame->left), abs(lpFrame->bottom - lpFrame->top) }; VERIFY(::SaveDC(hdc)); VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); VERIFY(::LPtoDP(hdc, &p, 1)); VERIFY(::RestoreDC(hdc, -1)); width = p.x; height = -p.y; free(lpemh); } break; default: DASSERT(FALSE); // Other formats are not supported yet. free(bBytes); ::DeleteDC(hdc); return NULL; } // JNI doesn't allow to store more than INT_MAX in a single array. // We report conversion failure in this case. if (width * height > INT_MAX) { free(bBytes); ::DeleteDC(hdc); return NULL; } numPixels = width * height; if (pLogPalette != NULL) { hPalette = ::CreatePalette(pLogPalette); if (hPalette == NULL) { free(bBytes); ::DeleteDC(hdc); return NULL; } hOldPalette = ::SelectPalette(hdc, hPalette, FALSE); ::RealizePalette(hdc); } // allocate memory for BITMAPINFO pDstBmi = (BITMAPINFO *)safe_Calloc(1, sizeof(BITMAPINFO)); pDstBmih = &pDstBmi->bmiHeader; static const int BITS_PER_PIXEL = 32; // prepare BITMAPINFO for a 32-bit RGB bitmap pDstBmih->biSize = sizeof(BITMAPINFOHEADER); pDstBmih->biWidth = width; pDstBmih->biHeight = -height; // negative height means a top-down DIB pDstBmih->biPlanes = 1; pDstBmih->biBitCount = BITS_PER_PIXEL; pDstBmih->biCompression = BI_RGB; // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps, // but this causes CreateDIBSection to allocate zero-size memory block // for DIB data. It works okay when biSizeImage is explicitly specified. pDstBmih->biSizeImage = width * height * (BITS_PER_PIXEL >> 3); hDibSection = ::CreateDIBSection(hdc, (BITMAPINFO*)pDstBmi, DIB_RGB_COLORS, &pDstBits, NULL, 0); if (hDibSection == NULL) { free(pDstBmi); pDstBmi = NULL; if (hPalette != NULL) { VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); hOldPalette = NULL; VERIFY(::DeleteObject(hPalette)); hPalette = NULL; } VERIFY(::DeleteDC(hdc)); hdc = NULL; free(bBytes); bBytes = NULL; JNU_ThrowIOException(env, "failed to get drop data"); return NULL; } hOldBitmap = (HBITMAP)::SelectObject(hdc, hDibSection); DASSERT(hOldBitmap != NULL); switch (format) { case CF_DIB: VERIFY(::StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height, pSrcBits, pSrcBmi, DIB_RGB_COLORS, SRCCOPY) != GDI_ERROR); break; case CF_ENHMETAFILE: case CF_METAFILEPICT: { RECT rect = { 0, 0, width, height }; VERIFY(::PlayEnhMetaFile(hdc, hEnhMetaFile, &rect)); VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL; break; } default: // Other formats are not supported yet. DASSERT(FALSE); break; } // convert Win32 pixel format (BGRX) to Java format (ARGB) DASSERT(sizeof(jint) == sizeof(RGBQUAD)); RGBQUAD* prgbq = (RGBQUAD*)pDstBits; for(int nPixel = 0; nPixel < numPixels; nPixel++, prgbq++) { jint jpixel = WIN_TO_JAVA_PIXEL(prgbq->rgbRed, prgbq->rgbGreen, prgbq->rgbBlue); // stuff the 32-bit pixel back into the 32-bit RGBQUAD *prgbq = *((RGBQUAD*)(&jpixel)); } buffer = env->NewIntArray(numPixels + 2); if (buffer == NULL) { throw std::bad_alloc(); } // copy pixels into Java array env->SetIntArrayRegion(buffer, 0, numPixels, (jint*)pDstBits); // copy dimensions into Java array env->SetIntArrayRegion(buffer, numPixels, 1, (jint*)&width); env->SetIntArrayRegion(buffer, numPixels + 1, 1, (jint*)&height); VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL; VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL; free(pDstBmi); pDstBmi = NULL; if (hPalette != NULL) { VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); hOldPalette = NULL; VERIFY(::DeleteObject(hPalette)); hPalette = NULL; } VERIFY(::DeleteDC(hdc)); hdc = NULL; free(bBytes); bBytes = NULL; } catch (...) { if (hdc != NULL && hOldBitmap != NULL) { VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL; } if (hDibSection != NULL) { VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL; } if (pDstBmi != NULL) { free(pDstBmi); pDstBmi = NULL; } if (hPalette != NULL) { if (hdc != NULL) { VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); hOldPalette = NULL; } VERIFY(::DeleteObject(hPalette)); hPalette = NULL; } if (hdc != NULL) { VERIFY(::DeleteDC(hdc)); hdc = NULL; } if (hEnhMetaFile != NULL) { VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL; } if (bBytes != NULL) { free(bBytes); bBytes = NULL; } throw; } return buffer; CATCH_BAD_ALLOC_RET(NULL); } /* * Class: sun_awt_windows_WDataTransferer * Method: imageDataToPlatformImageBytes * Signature: ([BIII)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_awt_windows_WDataTransferer_imageDataToPlatformImageBytes(JNIEnv *env, jobject self, jbyteArray imageData, jint width, jint height, jlong format) { TRY; if (JNU_IsNull(env, imageData)) { return NULL; } UINT size = env->GetArrayLength(imageData); if (size == 0) { return NULL; } // In the passed imageData array all lines are padded with zeroes except for // the last one, so we have to add one pad size here. int mod = (width * 3) % 4; int pad = mod > 0 ? 4 - mod : 0; int nBytes = sizeof(BITMAPINFO) + size + pad; BITMAPINFO* pinfo = (BITMAPINFO*)safe_Calloc(1, nBytes); static const int BITS_PER_PIXEL = 24; // prepare BITMAPINFO for a 24-bit BGR bitmap pinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pinfo->bmiHeader.biWidth = width; pinfo->bmiHeader.biHeight = height; // positive height means a bottom-up DIB pinfo->bmiHeader.biPlanes = 1; pinfo->bmiHeader.biBitCount = BITS_PER_PIXEL; pinfo->bmiHeader.biCompression = BI_RGB; // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps, // but some programs (e.g. Imaging for Windows NT by Wang Laboratories) // don't handle such DIBs correctly, so we specify the size explicitly. pinfo->bmiHeader.biSizeImage = size + pad; jbyte *array = (jbyte*)((LPSTR)pinfo + sizeof(BITMAPINFOHEADER)); env->GetByteArrayRegion(imageData, 0, size, array); HRESULT hr = S_OK; jbyteArray bytes = NULL; switch (format) { case CF_DIB: bytes = env->NewByteArray(nBytes); if( NULL == bytes ) { hr = E_OUTOFMEMORY; } else { env->SetByteArrayRegion(bytes, 0, nBytes, (jbyte*)pinfo); } break; case CF_ENHMETAFILE: { HDC hdc = ::GetDC(NULL); if( NULL == hdc) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { POINT p = { width, height }; //We are trying to support context-independent metafile. //To implement it we have to select correct MM_HIMETRIC map mode. VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); VERIFY(::DPtoLP(hdc, &p, 1)); //In accordance with CreateEnhMetaFile documentation the rectangle have to //be normal (left <= right, top <= bottom) RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) }; //Due to inversed row order in source bitmap the destination //height have to be negative. HDC hemfdc = ::CreateEnhMetaFile(NULL, NULL, &r, NULL); if( NULL == hemfdc) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { int iMFHeight = r.bottom - r.top; int iMFWidth = r.right - r.left; VERIFY(::SetMapMode(hemfdc, MM_HIMETRIC)); if( GDI_ERROR == ::StretchDIBits(hemfdc, 0, iMFHeight, iMFWidth, -iMFHeight, 0, 0, width, height, (LPVOID)array, pinfo, DIB_RGB_COLORS, SRCCOPY)) { hr = HRESULT_FROM_WIN32(::GetLastError()); } HENHMETAFILE hemf = ::CloseEnhMetaFile(hemfdc); if( NULL == hemf) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { if(SUCCEEDED(hr)){ UINT uEmfSize = ::GetEnhMetaFileBits(hemf, 0, NULL); if( 0 == uEmfSize) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { LPBYTE lpbEmfBuffer = NULL; try { lpbEmfBuffer = (LPBYTE)safe_Malloc(uEmfSize); VERIFY(::GetEnhMetaFileBits(hemf, uEmfSize, lpbEmfBuffer) == uEmfSize); bytes = env->NewByteArray(uEmfSize); if(NULL == bytes) { hr = E_OUTOFMEMORY; } else { env->SetByteArrayRegion(bytes, 0, uEmfSize, (jbyte*)lpbEmfBuffer); } } catch (std::bad_alloc &) { hr = E_OUTOFMEMORY; } free(lpbEmfBuffer); } } VERIFY(::DeleteEnhMetaFile(hemf)); } } VERIFY(::ReleaseDC(NULL, hdc)); } break; } case CF_METAFILEPICT: { HDC hdc = ::GetDC(NULL); if( NULL == hdc) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { POINT p = { width, height }; VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); VERIFY(::DPtoLP(hdc, &p, 1)); RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) }; HDC hmfdc = ::CreateMetaFile(NULL); if( NULL == hmfdc) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { VERIFY(::SetMapMode(hmfdc, MM_HIMETRIC)); int iMFHeight = r.bottom - r.top; int iMFWidth = r.right - r.left; //The destination Y coordinate (3d parameter in StretchDIBits call) is different for //CF_ENHMETAFILE and CF_METAFILEPICT formats due to applying MM_ANISOTROPIC map mode //at very last moment. MM_ANISOTROPIC map mode changes the Y-axis direction and can be //selected just for metafile header. if( GDI_ERROR == ::StretchDIBits(hmfdc, 0, 0, iMFWidth, -iMFHeight, 0, 0, width, height, (LPVOID)array, pinfo, DIB_RGB_COLORS, SRCCOPY)) { hr = HRESULT_FROM_WIN32(::GetLastError()); } HMETAFILE hmf = ::CloseMetaFile(hmfdc); if( NULL == hmf) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { if(SUCCEEDED(hr)){ UINT uMfSize = ::GetMetaFileBitsEx(hmf, 0, NULL); if( 0 == uMfSize) { hr = HRESULT_FROM_WIN32(::GetLastError()); } else { LPBYTE lpbMfBuffer = NULL; try { lpbMfBuffer = (LPBYTE)SAFE_SIZE_STRUCT_ALLOC(safe_Malloc, sizeof(METAFILEPICT), uMfSize, 1); const UINT uMfSizeWithHead = uMfSize + sizeof(METAFILEPICT); VERIFY(::GetMetaFileBitsEx(hmf, uMfSize, lpbMfBuffer + sizeof(METAFILEPICT)) == uMfSize); bytes = env->NewByteArray(uMfSizeWithHead); if(NULL == bytes) { hr = E_OUTOFMEMORY; } else { LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)lpbMfBuffer; lpMfp->mm = MM_ANISOTROPIC; // should use MM_ANISOTROPIC exactly (MSDN) lpMfp->xExt = iMFWidth; lpMfp->yExt = iMFHeight; env->SetByteArrayRegion(bytes, 0, uMfSizeWithHead, (jbyte*)lpbMfBuffer); } } catch (std::bad_alloc &) { hr = E_OUTOFMEMORY; } free(lpbMfBuffer); } } VERIFY(::DeleteMetaFile(hmf)); } } VERIFY(::ReleaseDC(NULL, hdc)); } break; } default: DASSERT(FALSE); // Other formats are not supported yet. hr = E_NOTIMPL; break; } free(pinfo); if(FAILED(hr)){ if(E_OUTOFMEMORY == hr) throw std::bad_alloc(); return NULL; } return bytes; CATCH_BAD_ALLOC_RET(NULL); } /* * Class: sun_awt_windows_WDataTransferer * Method: registerClipboardFormat * Signature: (Ljava/lang/String;)J */ JNIEXPORT jlong JNICALL Java_sun_awt_windows_WDataTransferer_registerClipboardFormat(JNIEnv *env, jclass cls, jstring str) { TRY; LPCTSTR cStr = JNU_GetStringPlatformChars(env, str, NULL); jlong value = ::RegisterClipboardFormat(cStr); JNU_ReleaseStringPlatformChars(env, str, cStr); return value; CATCH_BAD_ALLOC_RET(0); } /* * Class: sun_awt_windows_WDataTransferer * Method: getClipboardFormatName * Signature: (J)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_sun_awt_windows_WDataTransferer_getClipboardFormatName(JNIEnv *env, jclass cls, jlong format) { TRY; LPTSTR buf = new TCHAR[512]; // perhaps a bad idea to limit ourselves to 512 VERIFY(::GetClipboardFormatName((UINT)format, buf, 512)); jstring name = JNU_NewStringPlatform(env, buf); delete [] buf; if (name == NULL) { throw std::bad_alloc(); } return name; CATCH_BAD_ALLOC_RET(NULL); } /* * Class: sun_awt_windows_WToolkitThreadBlockedHandler * Method: startSecondaryEventLoop * Signature: ()V; */ JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkitThreadBlockedHandler_startSecondaryEventLoop(JNIEnv *env, jclass) { TRY; AwtDataTransferer::SecondaryMessageLoop(); CATCH_BAD_ALLOC; } } Other Java examples (source code examples)Here is a short list of links related to this Java awt_DataTransferer.cpp source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.