1 /* 2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "awt.h" 27 #include "awt_DataTransferer.h" 28 #include "awt_DnDDT.h" 29 #include "awt_TextComponent.h" 30 #include <shlobj.h> 31 #include <shellapi.h> 32 #include <sun_awt_datatransfer_DataTransferer.h> 33 #include <sun_awt_windows_WDataTransferer.h> 34 35 #include "locale_str.h" 36 37 #define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT) 38 #define WIN_TO_JAVA_PIXEL(r, g, b) (0xFF000000 | (r) << 16 | (g) << 8 | (b) << 0) 39 40 DECLARE_JAVA_CLASS(dataTransfererClazz, "sun/awt/datatransfer/DataTransferer"); 41 42 jobject 43 AwtDataTransferer::GetDataTransferer(JNIEnv* env) { 44 DECLARE_STATIC_OBJECT_JAVA_METHOD(getInstanceMethodID, dataTransfererClazz, 45 "getInstance", 46 "()Lsun/awt/datatransfer/DataTransferer;"); 47 return env->CallStaticObjectMethod(clazz, getInstanceMethodID); 48 } 49 50 jbyteArray 51 AwtDataTransferer::ConvertData(JNIEnv* env, jobject source, jobject contents, 52 jlong format, jobject formatMap) { 53 jobject transferer = GetDataTransferer(env); 54 55 if (!JNU_IsNull(env, transferer)) { 56 jbyteArray ret = NULL; 57 DECLARE_OBJECT_JAVA_METHOD(convertDataMethodID, dataTransfererClazz, 58 "convertData", 59 "(Ljava/lang/Object;Ljava/awt/datatransfer/Transferable;JLjava/util/Map;Z)[B"); 60 61 ret = (jbyteArray)env->CallObjectMethod(transferer, convertDataMethodID, 62 source, contents, format, 63 formatMap, AwtToolkit::IsMainThread()); 64 65 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 66 env->ExceptionDescribe(); 67 env->ExceptionClear(); 68 } 69 70 env->DeleteLocalRef(transferer); 71 72 return ret; 73 } else { 74 return NULL; 75 } 76 } 77 78 jobject 79 AwtDataTransferer::ConcatData(JNIEnv* env, jobject obj1, jobject obj2) { 80 jobject transferer = GetDataTransferer(env); 81 82 if (!JNU_IsNull(env, transferer)) { 83 jobject ret = NULL; 84 DECLARE_OBJECT_JAVA_METHOD(concatDataMethodID, dataTransfererClazz, 85 "concatData", 86 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 87 88 ret = env->CallObjectMethod(transferer, concatDataMethodID, obj1, obj2); 89 90 if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { 91 env->ExceptionDescribe(); 92 env->ExceptionClear(); 93 } 94 95 env->DeleteLocalRef(transferer); 96 97 return ret; 98 } else { 99 return NULL; 100 } 101 } 102 103 /** 104 * This routine retrieves palette entries from enhanced metafile or 105 * a logical color palette, builds appropriate LOGPALETTE structure, 106 * writes it into a created Java byte array and returns a local 107 * reference to the array. 108 * This routine is used for image data transfer. 109 * 110 * @param hGdiObj - a handle to the GDI object to retrieve palette entries from, 111 * it can be a handle to either a logical color palette (OBJ_PAL type) 112 * or an enhanced metafile (OBJ_ENHMETAFILE). If it is neither of these 113 * types the routine fails(see bFailSafe). 114 * @param dwGdiObjType - a type of the passed GDI object. It should be specified 115 * if the type of the passed GDI object is known to the caller. Otherwise 116 * pass 0. 117 * @param bFailSafe - if FALSE, the routine will return NULL in case of failure, 118 * otherwise it will return an array with empty LOGPALETTE structure 119 * in case of failure. 120 * @return a local reference to Java byte array which contains LOGPALETTE 121 * structure which defines a logical color palette or a palette of 122 * an enhanced metafile. 123 */ 124 jbyteArray 125 AwtDataTransferer::GetPaletteBytes(HGDIOBJ hGdiObj, DWORD dwGdiObjType, 126 BOOL bFailSafe) { 127 128 if (hGdiObj == NULL) { 129 dwGdiObjType = 0; 130 } else if (dwGdiObjType == 0) { 131 dwGdiObjType = ::GetObjectType(hGdiObj); 132 } else { 133 DASSERT(::GetObjectType(hGdiObj) == dwGdiObjType); 134 } 135 136 if (!bFailSafe && dwGdiObjType == 0) { 137 return NULL; 138 } 139 140 UINT nEntries = 0; 141 142 switch (dwGdiObjType) { 143 case OBJ_PAL: 144 nEntries = 145 ::GetPaletteEntries((HPALETTE)hGdiObj, 0, 0, NULL); 146 break; 147 case OBJ_ENHMETAFILE: 148 nEntries = 149 ::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, 0, NULL); 150 break; 151 } 152 153 if (!bFailSafe && (nEntries == 0 || nEntries == GDI_ERROR)) { 154 return NULL; 155 } 156 157 JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 158 jsize size = sizeof(LOGPALETTE) + nEntries * sizeof(PALETTEENTRY); 159 160 jbyteArray paletteBytes = env->NewByteArray(size); 161 if (JNU_IsNull(env, paletteBytes)) { 162 throw std::bad_alloc(); 163 } 164 165 LOGPALETTE* pLogPalette = 166 (LOGPALETTE*)env->GetPrimitiveArrayCritical(paletteBytes, NULL); 167 PALETTEENTRY* pPalEntries = (PALETTEENTRY*)pLogPalette->palPalEntry; 168 169 pLogPalette->palVersion = 0x300; 170 pLogPalette->palNumEntries = nEntries; 171 172 switch (dwGdiObjType) { 173 case OBJ_PAL: 174 VERIFY(::GetPaletteEntries((HPALETTE)hGdiObj, 0, nEntries, 175 pPalEntries) == nEntries); 176 break; 177 case OBJ_ENHMETAFILE: 178 VERIFY(::GetEnhMetaFilePaletteEntries((HENHMETAFILE)hGdiObj, nEntries, 179 pPalEntries) == nEntries); 180 break; 181 } 182 183 env->ReleasePrimitiveArrayCritical(paletteBytes, pLogPalette, 0); 184 185 return paletteBytes; 186 } 187 188 jbyteArray 189 AwtDataTransferer::LCIDToTextEncoding(JNIEnv *env, LCID lcid) { 190 LANGID langID = LANGIDFROMLCID(lcid); 191 const char *encoding = getEncodingFromLangID(langID); 192 193 // Warning C4244. 194 // Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit) 195 // to jsize (long). 196 // We assume that the encoding name length cannot exceed INT_MAX. 197 jsize length = (jsize)strlen(encoding); 198 199 jbyteArray retval = env->NewByteArray(length); 200 if (retval == NULL) { 201 throw std::bad_alloc(); 202 } 203 env->SetByteArrayRegion(retval, 0, length, (jbyte *)encoding); 204 free((void *)encoding); 205 return retval; 206 } 207 208 static VOID CALLBACK 209 IdleFunc() { 210 /* 211 * Fix for 4485987 and 4669873. 212 * If IdleFunc is a noop, the secondary message pump occasionally occupies 213 * all processor time and causes drag freezes. GetQueueStatus is needed to 214 * mark all messages that are currently in the queue as old, otherwise 215 * WaitMessage will return immediatelly as we selectively get messages from 216 * the queue. 217 */ 218 ::WaitMessage(); 219 ::GetQueueStatus(QS_ALLINPUT); 220 } 221 222 static BOOL CALLBACK 223 PeekMessageFunc(MSG& msg) { 224 return ::PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE) || 225 ::PeekMessage(&msg, NULL, WM_AWT_INVOKE_METHOD, WM_AWT_INVOKE_METHOD, PM_REMOVE) || 226 ::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE); 227 } 228 229 void 230 AwtDataTransferer::SecondaryMessageLoop() { 231 DASSERT(AwtToolkit::MainThread() == ::GetCurrentThreadId()); 232 233 AwtToolkit::GetInstance().MessageLoop(IdleFunc, 234 PeekMessageFunc); 235 } 236 237 extern "C" { 238 239 /* 240 * Class: sun_awt_datatransfer_DataTransferer 241 * Method: draqQueryFile 242 * Signature: ([B)[Ljava/lang/String; 243 */ 244 JNIEXPORT jobjectArray JNICALL 245 Java_sun_awt_windows_WDataTransferer_dragQueryFile 246 (JNIEnv *env, jobject obj, jbyteArray bytes) 247 { 248 TRY; 249 250 /* 251 * Fix for the BugTraq ID 4327064 - inter-jvm DnD crashes the droping jvm. 252 * On Win9X DragQueryFile() doesn't accept a pointer to the local help as the first 253 * argument, so we should dump the bits into global memory. 254 */ 255 UINT size = env->GetArrayLength(bytes); 256 HGLOBAL hglobal = NULL; 257 jbyte *bBytes = NULL; 258 HDROP hdrop = NULL; 259 LPTSTR buffer = NULL; 260 261 hglobal = ::GlobalAlloc(GALLOCFLG, size); 262 263 if (hglobal == NULL) { 264 throw std::bad_alloc(); 265 } 266 267 try { 268 269 bBytes = (jbyte*)::GlobalLock(hglobal); 270 env->GetByteArrayRegion(bytes, 0, size, bBytes); 271 272 hdrop = (HDROP)bBytes; 273 274 UINT nFilenames = ::DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); 275 276 jclass str_clazz = env->FindClass("java/lang/String"); 277 DASSERT(str_clazz != NULL); 278 jobjectArray filenames = env->NewObjectArray(nFilenames, str_clazz, 279 NULL); 280 if (filenames == NULL) { 281 throw std::bad_alloc(); 282 } 283 284 UINT bufsize = 512; // in characters, not in bytes 285 buffer = (LPTSTR)safe_Malloc(bufsize*sizeof(TCHAR)); 286 287 for (UINT i = 0; i < nFilenames; i++) { 288 UINT size = ::DragQueryFile(hdrop, i, NULL, 0); 289 if (size > bufsize) { 290 bufsize = size; 291 buffer = (LPTSTR)safe_Realloc(buffer, bufsize*sizeof(TCHAR)); 292 } 293 ::DragQueryFile(hdrop, i, buffer, bufsize); 294 295 jstring name = JNU_NewStringPlatform(env, buffer); 296 if (name == NULL) { 297 throw std::bad_alloc(); 298 } 299 300 env->SetObjectArrayElement(filenames, i, name); 301 } 302 303 free(buffer); 304 ::GlobalUnlock(hglobal); 305 ::GlobalFree(hglobal); 306 return filenames; 307 308 } catch (std::bad_alloc&) { 309 free(buffer); 310 ::GlobalUnlock(hglobal); 311 ::GlobalFree(hglobal); 312 throw; 313 } 314 315 CATCH_BAD_ALLOC_RET(NULL); 316 } 317 318 /* 319 * Class: sun_awt_windows_WDataTransferer 320 * Method: platformImageBytesToImageData 321 * Signature: ([BI)[I 322 */ 323 JNIEXPORT jintArray JNICALL 324 Java_sun_awt_windows_WDataTransferer_platformImageBytesToImageData( 325 JNIEnv *env, jobject self, jbyteArray bytes, jlong format) { 326 327 TRY; 328 329 HDC hdc = NULL; 330 331 LOGPALETTE* pLogPalette = NULL; 332 WORD uPaletteEntries = 0; 333 SIZE_T uOffset = 0; 334 HPALETTE hPalette = NULL; 335 HPALETTE hOldPalette = NULL; 336 337 BITMAPINFO* pSrcBmi = NULL; 338 BITMAPINFOHEADER* pSrcBmih = NULL; 339 LPVOID pSrcBits = NULL; 340 BITMAPINFO* pDstBmi = NULL; 341 BITMAPINFOHEADER* pDstBmih = NULL; 342 LPVOID pDstBits = NULL; 343 344 LPBYTE lpEnhMetaFileBits = NULL; 345 HENHMETAFILE hEnhMetaFile = NULL; 346 347 HBITMAP hDibSection = NULL; 348 HBITMAP hOldBitmap = NULL; 349 jintArray buffer = NULL; 350 LONG width = 0; 351 LONG height = 0; 352 int numPixels = 0; 353 354 if (JNU_IsNull(env, bytes)) { 355 return NULL; 356 } 357 358 jsize size = env->GetArrayLength(bytes); 359 if (size == 0) { 360 return NULL; 361 } 362 363 jbyte* bBytes = (jbyte*)safe_Malloc(size * sizeof(jbyte)); 364 365 try { 366 367 env->GetByteArrayRegion(bytes, 0, size, bBytes); 368 369 pLogPalette = (LOGPALETTE*)bBytes; 370 uPaletteEntries = pLogPalette->palNumEntries; 371 uOffset = sizeof(LOGPALETTE) + uPaletteEntries * sizeof(PALETTEENTRY); 372 DASSERT(uOffset < (SIZE_T)size); 373 374 if (uPaletteEntries == 0) { 375 pLogPalette = NULL; 376 } 377 378 hdc = ::CreateCompatibleDC(NULL); 379 if (hdc == NULL) { 380 free(bBytes); 381 return NULL; 382 } 383 384 switch (format) { 385 case CF_DIB: 386 387 pSrcBmi = (BITMAPINFO*)((LPSTR)bBytes + uOffset); 388 pSrcBmih = &pSrcBmi->bmiHeader; 389 390 width = pSrcBmih->biWidth; 391 height = abs(pSrcBmih->biHeight); 392 393 { 394 DWORD nColorEntries = 0; 395 396 switch (pSrcBmih->biBitCount) { 397 case 0: nColorEntries = 0; break; 398 case 1: nColorEntries = 2; break; 399 case 4: 400 case 8: 401 nColorEntries = (pSrcBmih->biClrUsed != 0) ? 402 pSrcBmih->biClrUsed : (1 << pSrcBmih->biBitCount); 403 break; 404 case 16: 405 case 24: 406 case 32: 407 nColorEntries = pSrcBmih->biClrUsed; 408 // If biBitCount is 16 or 32 and biCompression is 409 // BI_BITFIELDS the color table will be prefixed with 410 // three DWORD color masks. 411 if (pSrcBmih->biCompression == BI_BITFIELDS && 412 (pSrcBmih->biBitCount == 16 || 413 pSrcBmih->biBitCount == 32)) { 414 nColorEntries += 3; 415 } 416 break; 417 default: 418 // The header is probably corrupted. 419 // Fail immediatelly to avoid memory access violation. 420 free(bBytes); 421 ::DeleteDC(hdc); 422 return NULL; 423 } 424 425 pSrcBits = (LPSTR)pSrcBmi + pSrcBmih->biSize 426 + nColorEntries * sizeof(RGBQUAD); 427 } 428 break; 429 case CF_ENHMETAFILE: 430 case CF_METAFILEPICT: 431 lpEnhMetaFileBits = (BYTE*)bBytes + uOffset; 432 // Warning C4244. size is jsize, uOffset is SIZE_T. 433 // We assert that size > uOffset, so it is safe to cast to jsize. 434 hEnhMetaFile = ::SetEnhMetaFileBits(size - (jsize)uOffset, 435 lpEnhMetaFileBits); 436 DASSERT(hEnhMetaFile != NULL); 437 438 { 439 UINT uHeaderSize = 440 ::GetEnhMetaFileHeader(hEnhMetaFile, 0, NULL); 441 DASSERT(uHeaderSize != 0); 442 ENHMETAHEADER* lpemh = (ENHMETAHEADER*)safe_Malloc(uHeaderSize); 443 VERIFY(::GetEnhMetaFileHeader(hEnhMetaFile, uHeaderSize, 444 lpemh) == uHeaderSize); 445 LPRECTL lpFrame = &lpemh->rclFrame; 446 POINT p = { abs(lpFrame->right - lpFrame->left), 447 abs(lpFrame->bottom - lpFrame->top) }; 448 VERIFY(::SaveDC(hdc)); 449 VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); 450 VERIFY(::LPtoDP(hdc, &p, 1)); 451 VERIFY(::RestoreDC(hdc, -1)); 452 width = p.x; 453 height = -p.y; 454 455 free(lpemh); 456 } 457 break; 458 default: 459 DASSERT(FALSE); // Other formats are not supported yet. 460 free(bBytes); 461 ::DeleteDC(hdc); 462 return NULL; 463 } 464 465 // JNI doesn't allow to store more than INT_MAX in a single array. 466 // We report conversion failure in this case. 467 if (width * height > INT_MAX) { 468 free(bBytes); 469 ::DeleteDC(hdc); 470 return NULL; 471 } 472 473 numPixels = width * height; 474 475 if (pLogPalette != NULL) { 476 hPalette = ::CreatePalette(pLogPalette); 477 if (hPalette == NULL) { 478 free(bBytes); 479 ::DeleteDC(hdc); 480 return NULL; 481 } 482 hOldPalette = ::SelectPalette(hdc, hPalette, FALSE); 483 ::RealizePalette(hdc); 484 } 485 486 // allocate memory for BITMAPINFO 487 pDstBmi = (BITMAPINFO *)safe_Calloc(1, sizeof(BITMAPINFO)); 488 pDstBmih = &pDstBmi->bmiHeader; 489 490 static const int BITS_PER_PIXEL = 32; 491 492 // prepare BITMAPINFO for a 32-bit RGB bitmap 493 pDstBmih->biSize = sizeof(BITMAPINFOHEADER); 494 pDstBmih->biWidth = width; 495 pDstBmih->biHeight = -height; // negative height means a top-down DIB 496 pDstBmih->biPlanes = 1; 497 pDstBmih->biBitCount = BITS_PER_PIXEL; 498 pDstBmih->biCompression = BI_RGB; 499 // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps, 500 // but this causes CreateDIBSection to allocate zero-size memory block 501 // for DIB data. It works okay when biSizeImage is explicitly specified. 502 pDstBmih->biSizeImage = width * height * (BITS_PER_PIXEL >> 3); 503 504 hDibSection = ::CreateDIBSection(hdc, (BITMAPINFO*)pDstBmi, 505 DIB_RGB_COLORS, &pDstBits, 506 NULL, 0); 507 508 if (hDibSection == NULL) { 509 free(pDstBmi); pDstBmi = NULL; 510 if (hPalette != NULL) { 511 VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); 512 hOldPalette = NULL; 513 VERIFY(::DeleteObject(hPalette)); hPalette = NULL; 514 } 515 VERIFY(::DeleteDC(hdc)); hdc = NULL; 516 free(bBytes); bBytes = NULL; 517 518 JNU_ThrowIOException(env, "failed to get drop data"); 519 return NULL; 520 } 521 522 hOldBitmap = (HBITMAP)::SelectObject(hdc, hDibSection); 523 DASSERT(hOldBitmap != NULL); 524 525 switch (format) { 526 case CF_DIB: 527 VERIFY(::StretchDIBits(hdc, 528 0, 0, width, height, 529 0, 0, width, height, 530 pSrcBits, pSrcBmi, 531 DIB_RGB_COLORS, SRCCOPY) != GDI_ERROR); 532 break; 533 case CF_ENHMETAFILE: 534 case CF_METAFILEPICT: { 535 RECT rect = { 0, 0, width, height }; 536 537 VERIFY(::PlayEnhMetaFile(hdc, hEnhMetaFile, &rect)); 538 VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL; 539 break; 540 } 541 default: 542 // Other formats are not supported yet. 543 DASSERT(FALSE); 544 break; 545 } 546 547 // convert Win32 pixel format (BGRX) to Java format (ARGB) 548 DASSERT(sizeof(jint) == sizeof(RGBQUAD)); 549 RGBQUAD* prgbq = (RGBQUAD*)pDstBits; 550 for(int nPixel = 0; nPixel < numPixels; nPixel++, prgbq++) { 551 jint jpixel = WIN_TO_JAVA_PIXEL(prgbq->rgbRed, 552 prgbq->rgbGreen, 553 prgbq->rgbBlue); 554 // stuff the 32-bit pixel back into the 32-bit RGBQUAD 555 *prgbq = *((RGBQUAD*)(&jpixel)); 556 } 557 558 buffer = env->NewIntArray(numPixels + 2); 559 if (buffer == NULL) { 560 throw std::bad_alloc(); 561 } 562 563 // copy pixels into Java array 564 env->SetIntArrayRegion(buffer, 0, numPixels, (jint*)pDstBits); 565 566 // copy dimensions into Java array 567 env->SetIntArrayRegion(buffer, numPixels, 1, (jint*)&width); 568 env->SetIntArrayRegion(buffer, numPixels + 1, 1, (jint*)&height); 569 570 VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL; 571 VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL; 572 free(pDstBmi); pDstBmi = NULL; 573 if (hPalette != NULL) { 574 VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); 575 hOldPalette = NULL; 576 VERIFY(::DeleteObject(hPalette)); hPalette = NULL; 577 } 578 VERIFY(::DeleteDC(hdc)); hdc = NULL; 579 free(bBytes); bBytes = NULL; 580 } catch (...) { 581 if (hdc != NULL && hOldBitmap != NULL) { 582 VERIFY(::SelectObject(hdc, hOldBitmap) != NULL); hOldBitmap = NULL; 583 } 584 if (hDibSection != NULL) { 585 VERIFY(::DeleteObject(hDibSection)); hDibSection = NULL; 586 } 587 if (pDstBmi != NULL) { 588 free(pDstBmi); pDstBmi = NULL; 589 } 590 if (hPalette != NULL) { 591 if (hdc != NULL) { 592 VERIFY(::SelectPalette(hdc, hOldPalette, FALSE) != NULL); 593 hOldPalette = NULL; 594 } 595 VERIFY(::DeleteObject(hPalette)); hPalette = NULL; 596 } 597 if (hdc != NULL) { 598 VERIFY(::DeleteDC(hdc)); hdc = NULL; 599 } 600 if (hEnhMetaFile != NULL) { 601 VERIFY(::DeleteEnhMetaFile(hEnhMetaFile)); hEnhMetaFile = NULL; 602 } 603 if (bBytes != NULL) { 604 free(bBytes); bBytes = NULL; 605 } 606 throw; 607 } 608 609 return buffer; 610 611 CATCH_BAD_ALLOC_RET(NULL); 612 } 613 614 /* 615 * Class: sun_awt_windows_WDataTransferer 616 * Method: imageDataToPlatformImageBytes 617 * Signature: ([BIII)[B 618 */ 619 JNIEXPORT jbyteArray JNICALL 620 Java_sun_awt_windows_WDataTransferer_imageDataToPlatformImageBytes(JNIEnv *env, 621 jobject self, jbyteArray imageData, 622 jint width, jint height, 623 jlong format) { 624 625 TRY; 626 627 if (JNU_IsNull(env, imageData)) { 628 return NULL; 629 } 630 631 UINT size = env->GetArrayLength(imageData); 632 if (size == 0) { 633 return NULL; 634 } 635 636 // In the passed imageData array all lines are padded with zeroes except for 637 // the last one, so we have to add one pad size here. 638 int mod = (width * 3) % 4; 639 int pad = mod > 0 ? 4 - mod : 0; 640 int nBytes = sizeof(BITMAPINFO) + size + pad; 641 BITMAPINFO* pinfo = (BITMAPINFO*)safe_Calloc(1, nBytes); 642 643 static const int BITS_PER_PIXEL = 24; 644 645 // prepare BITMAPINFO for a 24-bit BGR bitmap 646 pinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 647 pinfo->bmiHeader.biWidth = width; 648 pinfo->bmiHeader.biHeight = height; // positive height means a bottom-up DIB 649 pinfo->bmiHeader.biPlanes = 1; 650 pinfo->bmiHeader.biBitCount = BITS_PER_PIXEL; 651 pinfo->bmiHeader.biCompression = BI_RGB; 652 // NOTE: MSDN says that biSizeImage may be set to 0 for BI_RGB bitmaps, 653 // but some programs (e.g. Imaging for Windows NT by Wang Laboratories) 654 // don't handle such DIBs correctly, so we specify the size explicitly. 655 pinfo->bmiHeader.biSizeImage = size + pad; 656 657 jbyte *array = (jbyte*)((LPSTR)pinfo + sizeof(BITMAPINFOHEADER)); 658 env->GetByteArrayRegion(imageData, 0, size, array); 659 HRESULT hr = S_OK; 660 661 jbyteArray bytes = NULL; 662 switch (format) { 663 case CF_DIB: 664 bytes = env->NewByteArray(nBytes); 665 if( NULL == bytes ) { 666 hr = E_OUTOFMEMORY; 667 } else { 668 env->SetByteArrayRegion(bytes, 0, nBytes, (jbyte*)pinfo); 669 } 670 break; 671 case CF_ENHMETAFILE: 672 { 673 HDC hdc = ::GetDC(NULL); 674 if( NULL == hdc) { 675 hr = HRESULT_FROM_WIN32(::GetLastError()); 676 } else { 677 POINT p = { width, height }; 678 //We are trying to support context-independent metafile. 679 //To implement it we have to select correct MM_HIMETRIC map mode. 680 VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); 681 VERIFY(::DPtoLP(hdc, &p, 1)); 682 //In accordance with CreateEnhMetaFile documentation the rectangle have to 683 //be normal (left <= right, top <= bottom) 684 RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) }; 685 //Due to inversed row order in source bitmap the destination 686 //height have to be negative. 687 HDC hemfdc = ::CreateEnhMetaFile(NULL, NULL, &r, NULL); 688 if( NULL == hemfdc) { 689 hr = HRESULT_FROM_WIN32(::GetLastError()); 690 } else { 691 int iMFHeight = r.bottom - r.top; 692 int iMFWidth = r.right - r.left; 693 VERIFY(::SetMapMode(hemfdc, MM_HIMETRIC)); 694 if( GDI_ERROR == ::StretchDIBits(hemfdc, 695 0, iMFHeight, iMFWidth, -iMFHeight, 696 0, 0, width, height, 697 (LPVOID)array, pinfo, 698 DIB_RGB_COLORS, SRCCOPY)) 699 { 700 hr = HRESULT_FROM_WIN32(::GetLastError()); 701 } 702 HENHMETAFILE hemf = ::CloseEnhMetaFile(hemfdc); 703 if( NULL == hemf) { 704 hr = HRESULT_FROM_WIN32(::GetLastError()); 705 } else { 706 if(SUCCEEDED(hr)){ 707 UINT uEmfSize = ::GetEnhMetaFileBits(hemf, 0, NULL); 708 if( 0 == uEmfSize) { 709 hr = HRESULT_FROM_WIN32(::GetLastError()); 710 } else { 711 LPBYTE lpbEmfBuffer = NULL; 712 try { 713 lpbEmfBuffer = (LPBYTE)safe_Malloc(uEmfSize); 714 VERIFY(::GetEnhMetaFileBits(hemf, uEmfSize, 715 lpbEmfBuffer) == uEmfSize); 716 bytes = env->NewByteArray(uEmfSize); 717 if(NULL == bytes) { 718 hr = E_OUTOFMEMORY; 719 } else { 720 env->SetByteArrayRegion(bytes, 0, uEmfSize, (jbyte*)lpbEmfBuffer); 721 } 722 } catch (std::bad_alloc &) { 723 hr = E_OUTOFMEMORY; 724 } 725 free(lpbEmfBuffer); 726 } 727 } 728 VERIFY(::DeleteEnhMetaFile(hemf)); 729 } 730 } 731 VERIFY(::ReleaseDC(NULL, hdc)); 732 } 733 break; 734 } 735 case CF_METAFILEPICT: 736 { 737 HDC hdc = ::GetDC(NULL); 738 if( NULL == hdc) { 739 hr = HRESULT_FROM_WIN32(::GetLastError()); 740 } else { 741 POINT p = { width, height }; 742 VERIFY(::SetMapMode(hdc, MM_HIMETRIC)); 743 VERIFY(::DPtoLP(hdc, &p, 1)); 744 RECT r = { min(0, p.x), min(0, p.y), max(0, p.x), max(0, p.y) }; 745 HDC hmfdc = ::CreateMetaFile(NULL); 746 if( NULL == hmfdc) { 747 hr = HRESULT_FROM_WIN32(::GetLastError()); 748 } else { 749 VERIFY(::SetMapMode(hmfdc, MM_HIMETRIC)); 750 int iMFHeight = r.bottom - r.top; 751 int iMFWidth = r.right - r.left; 752 //The destination Y coordinate (3d parameter in StretchDIBits call) is different for 753 //CF_ENHMETAFILE and CF_METAFILEPICT formats due to applying MM_ANISOTROPIC map mode 754 //at very last moment. MM_ANISOTROPIC map mode changes the Y-axis direction and can be 755 //selected just for metafile header. 756 if( GDI_ERROR == ::StretchDIBits(hmfdc, 757 0, 0, iMFWidth, -iMFHeight, 758 0, 0, width, height, 759 (LPVOID)array, pinfo, 760 DIB_RGB_COLORS, SRCCOPY)) 761 { 762 hr = HRESULT_FROM_WIN32(::GetLastError()); 763 } 764 HMETAFILE hmf = ::CloseMetaFile(hmfdc); 765 if( NULL == hmf) { 766 hr = HRESULT_FROM_WIN32(::GetLastError()); 767 } else { 768 if(SUCCEEDED(hr)){ 769 UINT uMfSize = ::GetMetaFileBitsEx(hmf, 0, NULL); 770 if( 0 == uMfSize) { 771 hr = HRESULT_FROM_WIN32(::GetLastError()); 772 } else { 773 LPBYTE lpbMfBuffer = NULL; 774 try { 775 UINT uMfSizeWithHead = uMfSize + sizeof(METAFILEPICT); 776 777 lpbMfBuffer = (LPBYTE)safe_Malloc(uMfSizeWithHead); 778 VERIFY(::GetMetaFileBitsEx(hmf, uMfSize, 779 lpbMfBuffer + sizeof(METAFILEPICT)) == uMfSize); 780 bytes = env->NewByteArray(uMfSizeWithHead); 781 if(NULL == bytes) { 782 hr = E_OUTOFMEMORY; 783 } else { 784 LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)lpbMfBuffer; 785 lpMfp->mm = MM_ANISOTROPIC; // should use MM_ANISOTROPIC exactly (MSDN) 786 lpMfp->xExt = iMFWidth; 787 lpMfp->yExt = iMFHeight; 788 env->SetByteArrayRegion(bytes, 0, uMfSizeWithHead, (jbyte*)lpbMfBuffer); 789 } 790 } catch (std::bad_alloc &) { 791 hr = E_OUTOFMEMORY; 792 } 793 free(lpbMfBuffer); 794 } 795 } 796 VERIFY(::DeleteMetaFile(hmf)); 797 } 798 } 799 VERIFY(::ReleaseDC(NULL, hdc)); 800 } 801 break; 802 } 803 default: 804 DASSERT(FALSE); // Other formats are not supported yet. 805 hr = E_NOTIMPL; 806 break; 807 } 808 free(pinfo); 809 if(FAILED(hr)){ 810 if(E_OUTOFMEMORY == hr) 811 throw std::bad_alloc(); 812 return NULL; 813 } 814 return bytes; 815 CATCH_BAD_ALLOC_RET(NULL); 816 } 817 818 /* 819 * Class: sun_awt_windows_WDataTransferer 820 * Method: registerClipboardFormat 821 * Signature: (Ljava/lang/String;)J 822 */ 823 JNIEXPORT jlong JNICALL 824 Java_sun_awt_windows_WDataTransferer_registerClipboardFormat(JNIEnv *env, 825 jclass cls, 826 jstring str) 827 { 828 TRY; 829 830 LPCTSTR cStr = JNU_GetStringPlatformChars(env, str, NULL); 831 jlong value = ::RegisterClipboardFormat(cStr); 832 JNU_ReleaseStringPlatformChars(env, str, cStr); 833 834 return value; 835 836 CATCH_BAD_ALLOC_RET(0); 837 } 838 839 /* 840 * Class: sun_awt_windows_WDataTransferer 841 * Method: getClipboardFormatName 842 * Signature: (J)Ljava/lang/String; 843 */ 844 JNIEXPORT jstring JNICALL 845 Java_sun_awt_windows_WDataTransferer_getClipboardFormatName(JNIEnv *env, 846 jclass cls, 847 jlong format) 848 { 849 TRY; 850 851 LPTSTR buf = new TCHAR[512]; // perhaps a bad idea to limit ourselves to 512 852 VERIFY(::GetClipboardFormatName((UINT)format, buf, 512)); 853 jstring name = JNU_NewStringPlatform(env, buf); 854 delete [] buf; 855 if (name == NULL) { 856 throw std::bad_alloc(); 857 } 858 return name; 859 860 CATCH_BAD_ALLOC_RET(NULL); 861 } 862 863 /* 864 * Class: sun_awt_windows_WToolkitThreadBlockedHandler 865 * Method: startSecondaryEventLoop 866 * Signature: ()V; 867 */ 868 JNIEXPORT void JNICALL 869 Java_sun_awt_windows_WToolkitThreadBlockedHandler_startSecondaryEventLoop(JNIEnv *env, jclass) 870 { 871 TRY; 872 873 AwtDataTransferer::SecondaryMessageLoop(); 874 875 CATCH_BAD_ALLOC; 876 } 877 878 }