void initScreens(JNIEnv *env) { awt_numScreens = ::CountMonitors(); monHds = (MHND *)safe_Malloc(awt_numScreens * sizeof(MHND)); AwtWin32GraphicsDevice **tempDevArray; if (awt_numScreens != ::CollectMonitors(monHds, awt_numScreens)) { JNU_ThrowInternalError(env, "Failed to get all monitor handles."); } if (devices) { devices->RemoveReference(); // Lock access to devices array until we've created the new // array. Prevents things like accessing out-of-date color // models and partially-created devices array. } MTSafeArray *tmpDevices = new MTSafeArray(awt_numScreens); // Add reference for the overall array - don't want to delete it just // because there are no surfaceData objects referencing it tmpDevices->AddReference(); // Create all devices first, then initialize them. This allows // correct configuration of devices after contruction of the // primary device (which may not be device 0). tempDevArray = (AwtWin32GraphicsDevice**) safe_Malloc(awt_numScreens * sizeof(AwtWin32GraphicsDevice)); for (int i = 0; i < awt_numScreens; ++i) { tempDevArray[i] = new AwtWin32GraphicsDevice(i, tmpDevices); } for (i = 0; i < awt_numScreens; ++i) { tempDevArray[i]->Initialize(); tmpDevices->AddElement(tempDevArray[i], i); } free(tempDevArray); devices = tmpDevices; InitDirectX(); }
/* * Class: sun_awt_windows_WInputMethodDescriptor * Method: getNativeAvailableLocales * Signature: ()[Ljava/util/Locale; */ JNIEXPORT jobjectArray JNICALL Java_sun_awt_windows_WInputMethodDescriptor_getNativeAvailableLocales (JNIEnv *env, jclass self) { TRY; // get list of available HKLs int layoutCount = ::GetKeyboardLayoutList(0, NULL); HKL FAR * hKLList = (HKL FAR *)safe_Malloc(sizeof(HKL)*layoutCount); DASSERT(!safe_ExceptionOccurred(env)); ::GetKeyboardLayoutList(layoutCount, hKLList); // get list of Java locale names while getting rid of duplicates int srcIndex = 0; int destIndex = 0; int javaLocaleNameCount = 0; int current = 0; const char ** javaLocaleNames = (const char **)safe_Malloc(sizeof(char *)*layoutCount); DASSERT(!safe_ExceptionOccurred(env)); for (; srcIndex < layoutCount; srcIndex++) { const char * srcLocaleName = getJavaIDFromLangID(LOWORD(hKLList[srcIndex])); if (srcLocaleName == NULL) { // could not find corresponding Java locale name for this HKL. continue; } for (current = 0; current < destIndex; current++) { if (strcmp(javaLocaleNames[current], srcLocaleName) == 0) { // duplicated. ignore this HKL break; } } if (current == destIndex) { javaLocaleNameCount++; destIndex++; javaLocaleNames[current] = srcLocaleName; } } // convert it to an array of Java locale objects jclass localeClass = env->FindClass("java/util/Locale"); jobjectArray locales = env->NewObjectArray(javaLocaleNameCount, localeClass, NULL); for (current = 0; current < javaLocaleNameCount; current++) { env->SetObjectArrayElement(locales, current, CreateLocaleObject(env, javaLocaleNames[current])); } DASSERT(!safe_ExceptionOccurred(env)); env->DeleteLocalRef(localeClass); free(hKLList); free(javaLocaleNames); return locales; CATCH_BAD_ALLOC_RET(NULL); }
/** * Class: sun_awt_windows_WInputMethod * Method: getNativeIMMDescription * Signature: ()Ljava/lang/String; * * This method tries to get the information about the input method associated with * the current active thread. * */ JNIEXPORT jstring JNICALL Java_sun_awt_windows_WInputMethod_getNativeIMMDescription (JNIEnv *env, jobject self) { TRY; // Get the keyboard layout of the active thread. HKL hkl = AwtComponent::GetKeyboardLayout(); LPTSTR szImmDescription = NULL; UINT buffSize = 0; jstring infojStr = NULL; if ((buffSize = ::ImmGetDescription(hkl, szImmDescription, 0)) > 0) { szImmDescription = (LPTSTR) safe_Malloc(buffSize * sizeof(TCHAR)); if (szImmDescription != NULL) { ImmGetDescription(hkl, szImmDescription, buffSize); infojStr = JNU_NewStringPlatform(env, szImmDescription); free(szImmDescription); } } return infojStr; CATCH_BAD_ALLOC_RET(NULL); }
/** * Create a new Devices object with numDevices elements. */ Devices::Devices(int numDevices) { J2dTraceLn1(J2D_TRACE_INFO, "Devices::Devices numDevices=%d", numDevices); this->numDevices = numDevices; this->refCount = 0; devices = (AwtWin32GraphicsDevice**)safe_Malloc (numDevices * sizeof(AwtWin32GraphicsDevice *)); }
static POINT *TransformPoly(jint *xpoints, jint *ypoints, jint transx, jint transy, POINT *pPoints, jint *pNpoints, BOOL close, BOOL fixend) { int npoints = *pNpoints; int outpoints = npoints; jint x, y; // Fix for 4298688 - draw(Line) and Polygon omit last pixel // We will need to add a point if we need to close it off or // if we need to fix the endpoint to accomodate the Windows // habit of never drawing the last pixel of a Polyline. Note // that if the polyline is already closed then neither fix // is needed because the last pixel is also the first pixel // and so will be drawn just fine. // Clarification for 4298688 - regression bug 4678208 points // out that we still need to fix the endpoint if the closed // polygon never went anywhere (all vertices on same coordinate). jint mx = xpoints[0]; jint my = ypoints[0]; BOOL isclosed = (xpoints[npoints-1] == mx && ypoints[npoints-1] == my); if ((close && !isclosed) || fixend) { outpoints++; *pNpoints = outpoints; } if (outpoints > POLYTEMPSIZE) { pPoints = (POINT *) safe_Malloc(sizeof(POINT) * outpoints); } BOOL isempty = fixend; for (int i = 0; i < npoints; i++) { x = xpoints[i]; y = ypoints[i]; isempty = isempty && (x == mx && y == my); pPoints[i].x = CLAMP(x + transx); pPoints[i].y = CLAMP(y + transy); } if (close && !isclosed) { pPoints[npoints] = pPoints[0]; } else if (fixend) { if (!close || isempty) { // Fix for 4298688 - draw(Line) and Polygon omit last pixel // Fix up the last segment by adding another segment after // it that is only 1 pixel long. The first pixel of that // segment will be drawn, but the second pixel is the one // that Windows omits. pPoints[npoints] = pPoints[npoints-1]; pPoints[npoints].x++; } else { outpoints--; *pNpoints = outpoints; } } return pPoints; }
// Local function for getting values from the Windows registry // Note that it uses malloc() and returns the pointer to allocated // memory, so remember to use free() when you are done with its // result. static LPTSTR getWindowsPropFromReg(LPTSTR subKey, LPTSTR valueName, DWORD *valueType) { HKEY handle; if (RegOpenKeyEx(HKEY_CURRENT_USER, subKey, 0, KEY_READ, &handle) != 0) { return NULL; } // valueSize is in bytes, while valueChar is in characters. DWORD valueSize, valueChar; if (RegQueryValueEx((HKEY)handle, valueName, NULL, valueType, NULL, &valueSize) != 0) { RegCloseKey(handle); return NULL; } LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize); if (RegQueryValueEx((HKEY)handle, valueName, NULL, valueType, (unsigned char *)buffer, &valueSize) != 0) { free(buffer); RegCloseKey(handle); return NULL; } RegCloseKey(handle); if (*valueType == REG_EXPAND_SZ) { // Pending: buffer must be null-terminated at this point valueChar = ExpandEnvironmentStrings(buffer, NULL, 0); LPTSTR buffer2 = (LPTSTR)safe_Malloc(valueChar*sizeof(TCHAR)); ExpandEnvironmentStrings(buffer, buffer2, valueChar); free(buffer); return buffer2; } else if (*valueType == REG_SZ) { return buffer; } else if (*valueType == REG_DWORD) { return buffer; } else { free(buffer); return NULL; } }
/* * Class: sun_awt_windows_WInputMethod * Method: setNativeLocale * Signature: (Ljava/lang/String;Z)Z */ JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WInputMethod_setNativeLocale (JNIEnv *env, jclass cls, jstring localeString, jboolean onActivate) { TRY; // check if current language ID is the requested one. Note that the // current language ID (returned from 'getJavaIDFromLangID') is in // ASCII encoding, so we use 'GetStringUTFChars' to retrieve requested // language ID from the 'localeString' object. const char * current = getJavaIDFromLangID(AwtComponent::GetInputLanguage()); jboolean isCopy; const char * requested = env->GetStringUTFChars(localeString, &isCopy); if ((current != NULL) && (strcmp(current, requested) == 0)) { env->ReleaseStringUTFChars(localeString, requested); return JNI_TRUE; } // get list of available HKLs. Adding the user's preferred layout on top of the layout // list which is returned by GetKeyboardLayoutList ensures to match first when // looking up suitable layout. int layoutCount = ::GetKeyboardLayoutList(0, NULL) + 1; // +1 for user's preferred HKL HKL FAR * hKLList = (HKL FAR *)safe_Malloc(sizeof(HKL)*layoutCount); DASSERT(!safe_ExceptionOccurred(env)); ::GetKeyboardLayoutList(layoutCount - 1, &(hKLList[1])); hKLList[0] = getDefaultKeyboardLayout(); // put user's preferred layout on top of the list // lookup matching LangID jboolean retValue = JNI_FALSE; for (int i = 0; i < layoutCount; i++) { const char * supported = getJavaIDFromLangID(LOWORD(hKLList[i])); if ((supported != NULL) && (strcmp(supported, requested) == 0)) { // use special message to call ActivateKeyboardLayout() in main thread. if (AwtToolkit::GetInstance().SendMessage(WM_AWT_ACTIVATEKEYBOARDLAYOUT, (WPARAM)onActivate, (LPARAM)hKLList[i])) { //also need to change the same keyboard layout for the Java AWT-EventQueue thread AwtToolkit::activateKeyboardLayout(hKLList[i]); retValue = JNI_TRUE; } break; } } env->ReleaseStringUTFChars(localeString, requested); free(hKLList); return retValue; CATCH_BAD_ALLOC_RET(JNI_FALSE); }
static void DumpRegion(HRGN rgn) { DWORD size = ::GetRegionData(rgn, 0, NULL); char* buffer = (char *)safe_Malloc(size); memset(buffer, 0, size); LPRGNDATA rgndata = (LPRGNDATA)buffer; rgndata->rdh.dwSize = sizeof(RGNDATAHEADER); rgndata->rdh.iType = RDH_RECTANGLES; VERIFY(::GetRegionData(rgn, size, rgndata)); RECT* r = (RECT*)(buffer + rgndata->rdh.dwSize); for (DWORD i=0; i<rgndata->rdh.nCount; i++) { if ( !::IsRectEmpty(r) ) { DTrace_PrintImpl("\trect %d %d %d %d\n", r->left, r->top, r->right, r->bottom); } r++; } free(buffer); }
// Does the actual lookup for shell dialog font (MS Shell Dlg). fontName // contains the name to lookup (either MS Shell Dlg or MS Shell Dlg 2) and // handle contains a reference toe the registry entry to look in. // This will return NULL or a pointer to the resolved name. // Note that it uses malloc() and returns the pointer to allocated // memory, so remember to use free() when you are done with its // result. static LPTSTR resolveShellDialogFont(LPTSTR fontName, HKEY handle) { DWORD valueType, valueSize; if (RegQueryValueEx((HKEY)handle, fontName, NULL, &valueType, NULL, &valueSize) != 0) { // Couldn't find it return NULL; } if (valueType != REG_SZ) { // Not the expected type return NULL; } LPTSTR buffer = (LPTSTR)safe_Malloc(valueSize); if (RegQueryValueEx((HKEY)handle, fontName, NULL, &valueType, (unsigned char *)buffer, &valueSize) != 0) { // Error fetching free(buffer); return NULL; } return buffer; }
HRESULT DDraw::GetDDAvailableVidMem(DWORD *freeMem) { DDrawDisplayMode dm; HRESULT ddResult; ddResult = dxObject->GetAvailableVidMem((DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN), NULL, freeMem); if (*freeMem == 0 || ddResult != DD_OK) { // Need to check it out ourselves: allocate as much as we can // and return that amount DDSURFACEDESC ddsd; ZeroMemory (&ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof( ddsd ); HRESULT ddr = dxObject->GetDisplayMode(dm); if (ddr != DD_OK) DebugPrintDirectDrawError(ddr, "getDispMode"); int bytesPerPixel = dm.bitDepth; static int maxSurfaces = 20; DXSurface **lpDDSOffscreenVram = (DXSurface**) safe_Malloc(maxSurfaces*sizeof(DXSurface*)); DWORD dwFlags = (DWORD)(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH); DWORD ddsCaps = (DWORD)(DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN); int size = 1024; int numVramSurfaces = 0; int bitsAllocated = 0; BOOL done = FALSE; while (!done) { HRESULT hResult = dxObject->CreateSurface(dwFlags, ddsCaps, NULL, size, size, &lpDDSOffscreenVram[numVramSurfaces]); if (hResult != DD_OK) { if (size > 1) { size >>= 1; } else { done = TRUE; } } else {
/* * Create a Java locale object from its name string */ jobject CreateLocaleObject(JNIEnv *env, const char * name) { TRY; // get language, country, variant information char * language = (char *)safe_Malloc(strlen(name) + 1); char * country; char * variant; DASSERT(!safe_ExceptionOccurred(env)); strcpy(language, name); for (country = language; *country != '_' && *country != '\0'; country++); if (*country == '_') { *country++ = '\0'; for (variant = country; *variant != '_' && *variant != '\0'; variant++); if (*variant == '_') { *variant++ = '\0'; } } else { variant = country; } // create Locale object jobject langObj = env->NewStringUTF(language); jobject ctryObj = env->NewStringUTF(country); jobject vrntObj = env->NewStringUTF(variant); jobject localeObj = JNU_NewObjectByName(env, "java/util/Locale", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", langObj, ctryObj, vrntObj); free(language); env->DeleteLocalRef(langObj); env->DeleteLocalRef(ctryObj); env->DeleteLocalRef(vrntObj); return localeObj; CATCH_BAD_ALLOC_RET(NULL); }
void AwtDesktopProperties::GetOtherParameters() { // TODO BEGIN: On NT4, some setttings don't trigger WM_SETTINGCHANGE -- // check whether this has been fixed on Windows 2000 and Windows 98 // ECH 10/6/2000 seems to be fixed on NT4 SP5, but not on 98 SetBooleanProperty(TEXT("win.frame.fullWindowDragsOn"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS)); SetBooleanProperty(TEXT("win.text.fontSmoothingOn"), GetBooleanParameter(SPI_GETFONTSMOOTHING)); // TODO END if (IS_WINXP) { SetIntegerProperty(TEXT("win.text.fontSmoothingType"), GetIntegerParameter(SPI_GETFONTSMOOTHINGTYPE)); SetIntegerProperty(TEXT("win.text.fontSmoothingContrast"), GetIntegerParameter(SPI_GETFONTSMOOTHINGCONTRAST)); SetIntegerProperty(TEXT("win.text.fontSmoothingOrientation"), GetLCDSubPixelOrder()); } int cxdrag = GetSystemMetrics(SM_CXDRAG); int cydrag = GetSystemMetrics(SM_CYDRAG); SetIntegerProperty(TEXT("win.drag.width"), cxdrag); SetIntegerProperty(TEXT("win.drag.height"), cydrag); SetIntegerProperty(TEXT("DnD.gestureMotionThreshold"), max(cxdrag, cydrag)/2); SetIntegerProperty(TEXT("awt.mouse.numButtons"), GetSystemMetrics(SM_CMOUSEBUTTONS)); SetIntegerProperty(TEXT("awt.multiClickInterval"), GetDoubleClickTime()); // BEGIN cross-platform properties // Note that these are cross-platform properties, but are being stuck into // WDesktopProperties. WToolkit.lazilyLoadDesktopProperty() can find them, // but if a Toolkit subclass uses the desktopProperties // member, these properties won't be there. -bchristi, echawkes // This property is called "win.frame.fullWindowDragsOn" above // This is one of the properties that don't trigger WM_SETTINGCHANGE SetBooleanProperty(TEXT("awt.dynamicLayoutSupported"), GetBooleanParameter(SPI_GETDRAGFULLWINDOWS)); // 95 MouseWheel support // More or less copied from the MSH_MOUSEWHEEL MSDN entry if (IS_WIN95 && !IS_WIN98) { HWND hdlMSHWHEEL = NULL; UINT msgMSHWheelSupported = NULL; BOOL wheelSupported = FALSE; msgMSHWheelSupported = RegisterWindowMessage(MSH_WHEELSUPPORT); hdlMSHWHEEL = FindWindow(MSH_WHEELMODULE_CLASS, MSH_WHEELMODULE_TITLE); if (hdlMSHWHEEL && msgMSHWheelSupported) { wheelSupported = (BOOL)::SendMessage(hdlMSHWHEEL, msgMSHWheelSupported, 0, 0); } SetBooleanProperty(TEXT("awt.wheelMousePresent"), wheelSupported); } else { SetBooleanProperty(TEXT("awt.wheelMousePresent"), ::GetSystemMetrics(SM_MOUSEWHEELPRESENT)); } // END cross-platform properties if (IS_WIN98 || IS_WIN2000) { //DWORD menuShowDelay; //SystemParametersInfo(SPI_GETMENUSHOWDELAY, 0, &menuShowDelay, 0); // SetIntegerProperty(TEXT("win.menu.showDelay"), menuShowDelay); SetBooleanProperty(TEXT("win.frame.captionGradientsOn"), GetBooleanParameter(SPI_GETGRADIENTCAPTIONS)); SetBooleanProperty(TEXT("win.item.hotTrackingOn"), GetBooleanParameter(SPI_GETHOTTRACKING)); } if (IS_WIN2000) { SetBooleanProperty(TEXT("win.menu.keyboardCuesOn"), GetBooleanParameter(SPI_GETKEYBOARDCUES)); } // High contrast accessibility property HIGHCONTRAST contrast; contrast.cbSize = sizeof(HIGHCONTRAST); if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &contrast, 0) != 0 && (contrast.dwFlags & HCF_HIGHCONTRASTON) == HCF_HIGHCONTRASTON) { SetBooleanProperty(TEXT("win.highContrast.on"), TRUE); } else { SetBooleanProperty(TEXT("win.highContrast.on"), FALSE); } if (fn_SHGetSettings != NULL) { SHELLFLAGSTATE sfs; fn_SHGetSettings(&sfs, SSF_SHOWALLOBJECTS | SSF_SHOWATTRIBCOL); if (sfs.fShowAllObjects) { SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), TRUE); } else { SetBooleanProperty(TEXT("awt.file.showHiddenFiles"), FALSE); } if (sfs.fShowAttribCol) { SetBooleanProperty(TEXT("awt.file..showAttribCol"), TRUE); } else { SetBooleanProperty(TEXT("awt.file.showAttribCol"), FALSE); } } LPTSTR value; DWORD valueType; // Shell Icon BPP - only honored on platforms before XP value = getWindowsPropFromReg(TEXT("Control Panel\\Desktop\\WindowMetrics"), TEXT("Shell Icon BPP"), &valueType); if (value != NULL) { if (valueType == REG_SZ) { SetStringProperty(TEXT("win.icon.shellIconBPP"), value); } free(value); } // The following registry settings control the file chooser places bar // under the Windows L&F. These settings are not present by default, but // can be enabled using the TweakUI tool from Microsoft. For more info, // see http://msdn.microsoft.com/msdnmag/issues/1100/Registry/ // NoPlacesBar is a REG_DWORD, with values 0 or 1 value = getWindowsPropFromReg(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32"), TEXT("NoPlacesBar"), &valueType); if (value != NULL) { if (valueType == REG_DWORD) { SetBooleanProperty(TEXT("win.comdlg.noPlacesBar"), (BOOL)((int)*value != 0)); } free(value); } LPTSTR valueName = TEXT("PlaceN"); LPTSTR valueNameBuf = (LPTSTR)safe_Malloc((lstrlen(valueName) + 1) * sizeof(TCHAR)); lstrcpy(valueNameBuf, valueName); LPTSTR propKey = TEXT("win.comdlg.placesBarPlaceN"); LPTSTR propKeyBuf = (LPTSTR)safe_Malloc((lstrlen(propKey) + 1) * sizeof(TCHAR)); lstrcpy(propKeyBuf, propKey); int i = 0; do { valueNameBuf[5] = _T('0' + i++); propKeyBuf[25] = valueNameBuf[5]; LPTSTR key = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\comdlg32\\PlacesBar"); if ((value = getWindowsPropFromReg(key, valueNameBuf, &valueType)) != NULL) { if (valueType == REG_DWORD) { // Value is a CSIDL SetIntegerProperty(propKeyBuf, (int)*value); } else { // Value is a path SetStringProperty(propKeyBuf, value); } free(value); } } while (value != NULL); free(valueNameBuf); free(propKeyBuf); }
void *safe_Malloc_outofmem(size_t size, const char *file, int line) throw (std::bad_alloc) { rand_alloc_fail(file, line); return safe_Malloc(size); }
// This function exists because VC++ 5.0 currently does not conform to the // Standard C++ specification which requires that operator new throw // std::bad_alloc in an out of memory situation. Instead, VC++ 5.0 returns 0. // // This function can be safely removed when the problem is corrected. void * CDECL operator new(size_t size) throw (std::bad_alloc) { return safe_Malloc(size); }
/** * Init this device. This creates the bitmap structure * used to hold the device color data and initializes any * appropriate palette structures. */ void AwtWin32GraphicsDevice::Initialize() { unsigned int ri, gi, bi; if (colorData->bitsperpixel < 8) { // REMIND: how to handle? } // Create a BitmapInfo object for color data if (!gpBitmapInfo) { try { gpBitmapInfo = (BITMAPINFO *) safe_Malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); } catch (std::bad_alloc&) { throw; } gpBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); } gpBitmapInfo->bmiHeader.biBitCount = 0; HDC hBMDC = this->GetDC(); HBITMAP hBM = ::CreateCompatibleBitmap(hBMDC, 1, 1); VERIFY(::GetDIBits(hBMDC, hBM, 0, 1, NULL, gpBitmapInfo, DIB_RGB_COLORS)); if (colorData->bitsperpixel > 8) { if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { primaryPalettized = FALSE; } if (colorData->bitsperpixel != 24) { // 15, 16, or 32 bpp int foo; gpBitmapInfo->bmiHeader.biCompression = BI_BITFIELDS; if (::GetDIBits(hBMDC, hBM, 0, 1, &foo, gpBitmapInfo, DIB_RGB_COLORS) == 0) { // Bug 4684966: If GetDIBits returns an error, we could // get stuck in an infinite loop setting the colorData // fields. Hardcode bitColors to reasonable values instead. // These values are picked according to standard masks // for these bit depths on win9x, according to MSDN docs. switch (colorData->bitsperpixel) { case 15: ((int *)gpBitmapInfo->bmiColors)[0] = 0x7c00; ((int *)gpBitmapInfo->bmiColors)[1] = 0x03e0; ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f; break; case 16: ((int *)gpBitmapInfo->bmiColors)[0] = 0xf800; ((int *)gpBitmapInfo->bmiColors)[1] = 0x07e0; ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f; break; case 32: default: ((int *)gpBitmapInfo->bmiColors)[0] = 0xff0000; ((int *)gpBitmapInfo->bmiColors)[1] = 0x00ff00; ((int *)gpBitmapInfo->bmiColors)[2] = 0x0000ff; break; } } ri = ((unsigned int *)gpBitmapInfo->bmiColors)[0]; colorData->rOff = 0; while ((ri & 1) == 0) { colorData->rOff++; ri >>= 1; } colorData->rScale = 0; while (ri < 0x80) { colorData->rScale++; ri <<= 1; } gi = ((unsigned int *)gpBitmapInfo->bmiColors)[1]; colorData->gOff = 0; while ((gi & 1) == 0) { colorData->gOff++; gi >>= 1; } colorData->gScale = 0; while (gi < 0x80) { colorData->gScale++; gi <<= 1; } bi = ((unsigned int *)gpBitmapInfo->bmiColors)[2]; colorData->bOff = 0; while ((bi & 1) == 0) { colorData->bOff++; bi >>= 1; } colorData->bScale = 0; while (bi < 0x80) { colorData->bScale++; bi <<= 1; } if ( (0 == colorData->bOff) && (5 == colorData->gOff) && (10 == colorData->rOff) && (3 == colorData->bScale) && (3 == colorData->gScale) && (3 == colorData->rScale)) { colorData->bitsperpixel = 15; gpBitmapInfo->bmiHeader.biCompression = BI_RGB; } } else { // 24 bpp
// static BOOL Devices::UpdateInstance(JNIEnv *env) { J2dTraceLn(J2D_TRACE_INFO, "Devices::UpdateInstance"); int numScreens = ::CountMonitors(); MHND *monHds = (MHND *)safe_Malloc(numScreens * sizeof(MHND)); if (numScreens != ::CollectMonitors(monHds, numScreens)) { J2dRlsTraceLn(J2D_TRACE_ERROR, "Devices::UpdateInstance: Failed to get all "\ "monitor handles."); free(monHds); return FALSE; } Devices *newDevices = new Devices(numScreens); // This way we know that the array will not be disposed of // at least until we replaced it with a new one. newDevices->AddReference(); // Create all devices first, then initialize them. This allows // correct configuration of devices after contruction of the // primary device (which may not be device 0). AwtWin32GraphicsDevice** rawDevices = newDevices->GetRawArray(); int i; for (i = 0; i < numScreens; ++i) { J2dTraceLn2(J2D_TRACE_VERBOSE, " hmon[%d]=0x%x", i, monHds[i]); rawDevices[i] = new AwtWin32GraphicsDevice(i, monHds[i], newDevices); } for (i = 0; i < numScreens; ++i) { rawDevices[i]->Initialize(); } { CriticalSection::Lock l(arrayLock); // install the new devices array Devices *oldDevices = theInstance; theInstance = newDevices; if (oldDevices) { // Invalidate the devices with indexes out of the new set of // devices. This doesn't cover all cases when the device // might should be invalidated (like if it's not the last device // that was removed), but it will have to do for now. int oldNumScreens = oldDevices->GetNumDevices(); int newNumScreens = theInstance->GetNumDevices(); J2dTraceLn(J2D_TRACE_VERBOSE, " Invalidating removed devices"); for (int i = newNumScreens; i < oldNumScreens; i++) { // removed device, needs to be invalidated J2dTraceLn1(J2D_TRACE_WARNING, "Devices::UpdateInstance: device removed: %d", i); oldDevices->GetDevice(i)->Invalidate(env); } // Now that we have a new array in place, remove this (possibly the // last) reference to the old instance. oldDevices->Release(); } D3DPipelineManager::HandleAdaptersChange((HMONITOR*)monHds, theInstance->GetNumDevices()); } free(monHds); return TRUE; }
/* * 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: 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_java2d_windows_GDIBlitLoops * Method: nativeBlit * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;IIIIIIZ)V */ JNIEXPORT void JNICALL Java_sun_java2d_windows_GDIBlitLoops_nativeBlit (JNIEnv *env, jobject joSelf, jobject srcData, jobject dstData, jobject clip, jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height, jint rmask, jint gmask, jint bmask, jboolean needLut) { J2dTraceLn(J2D_TRACE_INFO, "GDIBlitLoops_nativeBlit"); SurfaceDataRasInfo srcInfo; SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcData); GDIWinSDOps *dstOps = GDIWindowSurfaceData_GetOps(env, dstData); jint lockFlags; HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0); if (hDC == NULL) { return; } srcInfo.bounds.x1 = srcx; srcInfo.bounds.y1 = srcy; srcInfo.bounds.x2 = srcx + width; srcInfo.bounds.y2 = srcy + height; if (needLut) { lockFlags = (SD_LOCK_READ | SD_LOCK_LUT); } else { lockFlags = SD_LOCK_READ; } if (srcOps->Lock(env, srcOps, &srcInfo, lockFlags) != SD_SUCCESS) { dstOps->ReleaseDC(env, dstOps, hDC); return; } SurfaceDataBounds dstBounds = {dstx, dsty, dstx + width, dsty + height}; // Intersect the source and dest rects. Note that the source blit bounds // will be adjusted to the surfaces's bounds if needed. SurfaceData_IntersectBlitBounds(&(srcInfo.bounds), &dstBounds, dstx - srcx, dsty - srcy); srcx = srcInfo.bounds.x1; srcy = srcInfo.bounds.y1; dstx = dstBounds.x1; dsty = dstBounds.y1; width = srcInfo.bounds.x2 - srcInfo.bounds.x1; height = srcInfo.bounds.y2 - srcInfo.bounds.y1; if (width > 0 && height > 0) { BmiType bmi; // REMIND: A performance tweak here would be to make some of this // data static. For example, we could have one structure that is // always used for ByteGray copies and we only change dynamic data // in the structure with every new copy. Also, we could store // structures with Ops or with the Java objects so that surfaces // could retain their own DIB info and we would not need to // recreate it every time. srcOps->GetRasInfo(env, srcOps, &srcInfo); void *rasBase = ((char *)srcInfo.rasBase) + srcInfo.scanStride * srcy + srcInfo.pixelStride * srcx; // If scanlines are DWORD-aligned (scanStride is a multiple of 4), // then we can do the work much faster. This is due to a constraint // in the way DIBs are structured and parsed by GDI jboolean fastBlt = ((srcInfo.scanStride & 0x03) == 0); bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biWidth = srcInfo.scanStride/srcInfo.pixelStride; // fastBlt copies whole image in one call; else copy line-by-line bmi.bmiHeader.biHeight = (fastBlt) ? -(srcInfo.bounds.y2 - srcInfo.bounds.y1) : -1; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = srcInfo.pixelStride * 8; // 1,3,4 byte use BI_RGB, 2 byte use BI_BITFIELD... // 4 byte _can_ use BI_BITFIELD, but this seems to cause a performance // penalty. Since we only ever have one format (xrgb) for 32-bit // images that enter this function, just use BI_RGB. // Could do BI_RGB for 2-byte 555 format, but no perceived // performance benefit. bmi.bmiHeader.biCompression = (srcInfo.pixelStride != 2) ? BI_RGB : BI_BITFIELDS; bmi.bmiHeader.biSizeImage = (bmi.bmiHeader.biWidth * bmi.bmiHeader.biHeight * srcInfo.pixelStride); bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; if (srcInfo.pixelStride == 1) { // Copy palette info into bitmap for 8-bit image if (needLut) { memcpy(bmi.colors.palette, srcInfo.lutBase, srcInfo.lutSize * sizeof(RGBQUAD)); if (srcInfo.lutSize != 256) { bmi.bmiHeader.biClrUsed = srcInfo.lutSize; } } else { // If no LUT needed, must be ByteGray src. If we have not // yet created the byteGrayPalette, create it now and copy // it into our temporary bmi structure. // REMIND: byteGrayPalette is a leak since we do not have // a mechansim to free it up. This should be fine, since it // is only 256 bytes for any process and only gets malloc'd // when using ByteGray surfaces. Eventually, we should use // the new Disposer mechanism to delete this native memory. if (byteGrayPalette == NULL) { byteGrayPalette = (RGBQUAD *)safe_Malloc(256 * sizeof(RGBQUAD)); for (int i = 0; i < 256; ++i) { byteGrayPalette[i].rgbRed = i; byteGrayPalette[i].rgbGreen = i; byteGrayPalette[i].rgbBlue = i; } } memcpy(bmi.colors.palette, byteGrayPalette, 256 * sizeof(RGBQUAD)); } } else if (srcInfo.pixelStride == 2) { // For 16-bit case, init the masks for the pixel depth bmi.colors.dwMasks[0] = rmask; bmi.colors.dwMasks[1] = gmask; bmi.colors.dwMasks[2] = bmask; } if (fastBlt) { // Window could go away at any time, leaving bits on the screen // from this GDI call, so make sure window still exists if (::IsWindowVisible(dstOps->window)) { // Could also call StretchDIBits. Testing showed slight // performance advantage of SetDIBits instead, so since we // have no need of scaling, might as well use SetDIBits. SetDIBitsToDevice(hDC, dstx, dsty, width, height, 0, 0, 0, height, rasBase, (BITMAPINFO*)&bmi, DIB_RGB_COLORS); } } else { // Source scanlines not DWORD-aligned - copy each scanline individually for (int i = 0; i < height; i += 1) { if (::IsWindowVisible(dstOps->window)) { SetDIBitsToDevice(hDC, dstx, dsty+i, width, 1, 0, 0, 0, 1, rasBase, (BITMAPINFO*)&bmi, DIB_RGB_COLORS); rasBase = (void*)((char*)rasBase + srcInfo.scanStride); } else { break; } } } SurfaceData_InvokeRelease(env, srcOps, &srcInfo); } SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); dstOps->ReleaseDC(env, dstOps, hDC); return; }
/* * Class: sun_awt_shell_Win32ShellFolder2 * Method: getFileChooserBitmapBits * Signature: ()[I */ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserBitmapBits (JNIEnv* env, jclass cls) { HBITMAP hBitmap = NULL; BITMAP bm; HINSTANCE libComCtl32; HINSTANCE libShell32; libShell32 = LoadLibrary(TEXT("shell32.dll")); if (libShell32 != NULL) { hBitmap = (HBITMAP)LoadImage(libShell32, MAKEINTRESOURCE(216), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); } if (hBitmap == NULL) { libComCtl32 = LoadLibrary(TEXT("comctl32.dll")); if (libComCtl32 != NULL) { hBitmap = (HBITMAP)LoadImage(libComCtl32, MAKEINTRESOURCE(124), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); } } if (hBitmap == NULL) { return NULL; } GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); // Get the screen DC HDC dc = GetDC(NULL); if (dc == NULL) { return NULL; } // Set up BITMAPINFO BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = bm.bmWidth; bmi.bmiHeader.biHeight = -bm.bmHeight; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; // Extract the color bitmap int numPixels = bm.bmWidth * bm.bmHeight; //long colorBits[192 * 16]; long *colorBits = (long*)safe_Malloc(numPixels * sizeof(long)); if (GetDIBits(dc, hBitmap, 0, bm.bmHeight, colorBits, &bmi, DIB_RGB_COLORS) == 0) { return NULL; } // Release DC ReleaseDC(NULL, dc); // The color of the first pixel defines the transparency, according // to the documentation for LR_LOADTRANSPARENT at // http://msdn.microsoft.com/library/psdk/winui/resource_9fhi.htm long transparent = colorBits[0]; for (int i=0; i < numPixels; i++) { if (colorBits[i] != transparent) { colorBits[i] |= 0xff000000; } } // Create java array jintArray bits = env->NewIntArray(numPixels); // Copy values to java array env->SetIntArrayRegion(bits, 0, numPixels, colorBits); // Fix 4745575 GDI Resource Leak ::DeleteObject(hBitmap); ::FreeLibrary(libComCtl32); return bits; }
WORD AwtPrintControl::getNearestMatchingPaper(LPTSTR printer, LPTSTR port, double origWid, double origHgt, double* newWid, double *newHgt) { const double epsilon = 0.50; const double tolerance = (1.0 * 72.0); // # inches * 72 int numPaperSizes = 0; WORD *papers = NULL; POINT *paperSizes = NULL; if ((printer== NULL) || (port == NULL)) { return 0; } SAVE_CONTROLWORD numPaperSizes = (int)DeviceCapabilities(printer, port, DC_PAPERSIZE, NULL, NULL); if (numPaperSizes > 0) { papers = (WORD*)safe_Malloc(sizeof(WORD) * numPaperSizes); paperSizes = (POINT *)safe_Malloc(sizeof(*paperSizes) * numPaperSizes); DWORD result1 = DeviceCapabilities(printer, port, DC_PAPERS, (LPTSTR) papers, NULL); DWORD result2 = DeviceCapabilities(printer, port, DC_PAPERSIZE, (LPTSTR) paperSizes, NULL); // REMIND: cache in papers and paperSizes if (result1 == -1 || result2 == -1 ) { free((LPTSTR) papers); papers = NULL; free((LPTSTR) paperSizes); paperSizes = NULL; } } RESTORE_CONTROLWORD double closestWid = 0.0; double closestHgt = 0.0; WORD closestMatch = 0; if (paperSizes != NULL) { /* Paper sizes are in 0.1mm units. Convert to 1/72" * For each paper size, compute the difference from the paper size * passed in. Use a least-squares difference, so paper much different * in x or y should score poorly */ double diffw = origWid; double diffh = origHgt; double least_square = diffw * diffw + diffh * diffh; double tmp_ls; double widpts, hgtpts; for (int i=0;i<numPaperSizes;i++) { widpts = paperSizes[i].x * LOMETRIC_TO_POINTS; hgtpts = paperSizes[i].y * LOMETRIC_TO_POINTS; if ((fabs(origWid - widpts) < epsilon) && (fabs(origHgt - hgtpts) < epsilon)) { closestWid = origWid; closestHgt = origHgt; closestMatch = papers[i]; break; } diffw = fabs(widpts - origWid); diffh = fabs(hgtpts - origHgt); tmp_ls = diffw * diffw + diffh * diffh; if ((diffw < tolerance) && (diffh < tolerance) && (tmp_ls < least_square)) { least_square = tmp_ls; closestWid = widpts; closestHgt = hgtpts; closestMatch = papers[i]; } } } if (closestWid > 0) { *newWid = closestWid; } if (closestHgt > 0) { *newHgt = closestHgt; } if (papers != NULL) { free((LPTSTR)papers); } if (paperSizes != NULL) { free((LPTSTR)paperSizes); } return closestMatch; }
/* * Class: sun_awt_windows_WClipboard * Method: getClipboardData * Signature: (J)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_awt_windows_WClipboard_getClipboardData (JNIEnv *env, jobject self, jlong format) { TRY; DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd()); HANDLE handle = ::GetClipboardData((UINT)format); if (handle == NULL) { JNU_ThrowIOException(env, "system clipboard data unavailable"); return NULL; } jbyteArray bytes = NULL; jbyteArray paletteData = NULL; switch (format) { case CF_ENHMETAFILE: case CF_METAFILEPICT: { HENHMETAFILE hemf = NULL; if (format == CF_METAFILEPICT) { HMETAFILEPICT hMetaFilePict = (HMETAFILEPICT)handle; LPMETAFILEPICT lpMetaFilePict = (LPMETAFILEPICT)::GlobalLock(hMetaFilePict); UINT uSize = ::GetMetaFileBitsEx(lpMetaFilePict->hMF, 0, NULL); DASSERT(uSize != 0); try { LPBYTE lpMfBits = (LPBYTE)safe_Malloc(uSize); VERIFY(::GetMetaFileBitsEx(lpMetaFilePict->hMF, uSize, lpMfBits) == uSize); hemf = ::SetWinMetaFileBits(uSize, lpMfBits, NULL, lpMetaFilePict); free(lpMfBits); if (hemf == NULL) { ::GlobalUnlock(hMetaFilePict); JNU_ThrowIOException(env, "failed to get system clipboard data"); return NULL; } } catch (...) { ::GlobalUnlock(hMetaFilePict); throw; } ::GlobalUnlock(hMetaFilePict); } else { hemf = (HENHMETAFILE)handle; } UINT uEmfSize = ::GetEnhMetaFileBits(hemf, 0, NULL); if (uEmfSize == 0) { JNU_ThrowIOException(env, "cannot retrieve metafile bits"); return NULL; } bytes = env->NewByteArray(uEmfSize); if (bytes == NULL) { throw std::bad_alloc(); } LPBYTE lpbEmfBuffer = (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL); if (lpbEmfBuffer == NULL) { env->DeleteLocalRef(bytes); throw std::bad_alloc(); } VERIFY(::GetEnhMetaFileBits(hemf, uEmfSize, lpbEmfBuffer) == uEmfSize); env->ReleasePrimitiveArrayCritical(bytes, lpbEmfBuffer, 0); paletteData = AwtDataTransferer::GetPaletteBytes(hemf, OBJ_ENHMETAFILE, FALSE); break; } case CF_LOCALE: { LCID *lcid = (LCID *)::GlobalLock(handle); if (lcid == NULL) { JNU_ThrowIOException(env, "invalid LCID"); return NULL; } try { bytes = AwtDataTransferer::LCIDToTextEncoding(env, *lcid); } catch (...) { ::GlobalUnlock(handle); throw; } ::GlobalUnlock(handle); break; } default: { ::SetLastError(0); // clear error // Warning C4244. // Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit) // to jsize (long). SIZE_T globalSize = ::GlobalSize(handle); jsize size = (globalSize <= INT_MAX) ? (jsize)globalSize : INT_MAX; if (::GetLastError() != 0) { JNU_ThrowIOException(env, "invalid global memory block handle"); return NULL; } bytes = env->NewByteArray(size); if (bytes == NULL) { throw std::bad_alloc(); } if (size != 0) { LPVOID data = ::GlobalLock(handle); env->SetByteArrayRegion(bytes, 0, size, (jbyte *)data); ::GlobalUnlock(handle); } break; } } switch (format) { case CF_ENHMETAFILE: case CF_METAFILEPICT: case CF_DIB: { if (JNU_IsNull(env, paletteData)) { HPALETTE hPalette = (HPALETTE)::GetClipboardData(CF_PALETTE); paletteData = AwtDataTransferer::GetPaletteBytes(hPalette, OBJ_PAL, TRUE); } DASSERT(!JNU_IsNull(env, paletteData) && !JNU_IsNull(env, bytes)); jbyteArray concat = (jbyteArray)AwtDataTransferer::ConcatData(env, paletteData, bytes); if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) { env->ExceptionDescribe(); env->ExceptionClear(); env->DeleteLocalRef(bytes); env->DeleteLocalRef(paletteData); return NULL; } env->DeleteLocalRef(bytes); env->DeleteLocalRef(paletteData); bytes = concat; break; } } return bytes; CATCH_BAD_ALLOC_RET(NULL); }