207 HDC hdcScreen = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 208 HDC hdcMem = ::CreateCompatibleDC(hdcScreen); 209 HBITMAP hbitmap; 210 HBITMAP hOldBitmap; 211 HPALETTE hOldPalette = NULL; 212 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 213 214 // create an offscreen bitmap 215 hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height); 216 if (hbitmap == NULL) { 217 throw std::bad_alloc(); 218 } 219 hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hbitmap); 220 221 // REMIND: not multimon-friendly... 222 int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 223 hOldPalette = 224 AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex); 225 AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex); 226 227 Devices::InstanceAccess devices; 228 AwtWin32GraphicsDevice *device = devices->GetDevice(primaryIndex); 229 int sWidth = (device == NULL) ? width : device->ScaleUpX(width); 230 int sHeight = (device == NULL) ? height : device->ScaleUpY(height); 231 232 // copy screen image to offscreen bitmap 233 // CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents 234 // correctly on Win2K/XP 235 if (width == sWidth && height == sHeight) { 236 VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y, 237 SRCCOPY | CAPTUREBLT) != 0); 238 } else { 239 int sX = (device == NULL) ? x : device->ScaleUpX(x); 240 int sY = (device == NULL) ? y : device->ScaleUpY(y); 241 VERIFY(::StretchBlt(hdcMem, 0, 0, width, height, 242 hdcScreen, sX, sY, sWidth, sHeight, 243 SRCCOPY | CAPTUREBLT) != 0); 244 } 245 246 static const int BITS_PER_PIXEL = 32; 247 static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8; 248 249 if (!IS_SAFE_SIZE_MUL(width, height)) throw std::bad_alloc(); 250 int numPixels = width*height; 251 if (!IS_SAFE_SIZE_MUL(BYTES_PER_PIXEL, numPixels)) throw std::bad_alloc(); 252 int pixelDataSize = BYTES_PER_PIXEL*numPixels; 253 DASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0); 254 // allocate memory for BITMAPINFO + pixel data 255 // 4620932: When using BI_BITFIELDS, GetDIBits expects an array of 3 256 // RGBQUADS to follow the BITMAPINFOHEADER, but we were only allocating the 257 // 1 that is included in BITMAPINFO. Thus, GetDIBits was writing off the 258 // end of our block of memory. Now we allocate sufficient memory. 259 // See MSDN docs for BITMAPINFOHEADER -bchristi 260 261 if (!IS_SAFE_SIZE_ADD(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), pixelDataSize)) { 262 throw std::bad_alloc(); 263 } 264 BITMAPINFO * pinfo = (BITMAPINFO *)(new BYTE[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD) + pixelDataSize]); | 207 HDC hdcScreen = ::CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); 208 HDC hdcMem = ::CreateCompatibleDC(hdcScreen); 209 HBITMAP hbitmap; 210 HBITMAP hOldBitmap; 211 HPALETTE hOldPalette = NULL; 212 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 213 214 // create an offscreen bitmap 215 hbitmap = ::CreateCompatibleBitmap(hdcScreen, width, height); 216 if (hbitmap == NULL) { 217 throw std::bad_alloc(); 218 } 219 hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hbitmap); 220 221 // REMIND: not multimon-friendly... 222 int primaryIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 223 hOldPalette = 224 AwtWin32GraphicsDevice::SelectPalette(hdcMem, primaryIndex); 225 AwtWin32GraphicsDevice::RealizePalette(hdcMem, primaryIndex); 226 227 // copy screen image to offscreen bitmap 228 // CAPTUREBLT flag is required to capture WS_EX_LAYERED windows' contents 229 // correctly on Win2K/XP 230 VERIFY(::BitBlt(hdcMem, 0, 0, width, height, hdcScreen, x, y, 231 SRCCOPY | CAPTUREBLT) != 0); 232 233 static const int BITS_PER_PIXEL = 32; 234 static const int BYTES_PER_PIXEL = BITS_PER_PIXEL/8; 235 236 if (!IS_SAFE_SIZE_MUL(width, height)) throw std::bad_alloc(); 237 int numPixels = width*height; 238 if (!IS_SAFE_SIZE_MUL(BYTES_PER_PIXEL, numPixels)) throw std::bad_alloc(); 239 int pixelDataSize = BYTES_PER_PIXEL*numPixels; 240 DASSERT(pixelDataSize > 0 && pixelDataSize % 4 == 0); 241 // allocate memory for BITMAPINFO + pixel data 242 // 4620932: When using BI_BITFIELDS, GetDIBits expects an array of 3 243 // RGBQUADS to follow the BITMAPINFOHEADER, but we were only allocating the 244 // 1 that is included in BITMAPINFO. Thus, GetDIBits was writing off the 245 // end of our block of memory. Now we allocate sufficient memory. 246 // See MSDN docs for BITMAPINFOHEADER -bchristi 247 248 if (!IS_SAFE_SIZE_ADD(sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD), pixelDataSize)) { 249 throw std::bad_alloc(); 250 } 251 BITMAPINFO * pinfo = (BITMAPINFO *)(new BYTE[sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD) + pixelDataSize]); |