Index: ui/base/clipboard/clipboard_win.cc |
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc |
index 867448a4ee8cf30dd56e35cc70e76ae261e90548..603c14ec87ff3f14eeae8e51fafd0091de4ad92f 100644 |
--- a/ui/base/clipboard/clipboard_win.cc |
+++ b/ui/base/clipboard/clipboard_win.cc |
@@ -438,27 +438,54 @@ SkBitmap Clipboard::ReadImage(Buffer buffer) const { |
if (!clipboard.Acquire(GetClipboardWindow())) |
return SkBitmap(); |
- HBITMAP source_bitmap = static_cast<HBITMAP>(::GetClipboardData(CF_BITMAP)); |
- if (!source_bitmap) |
- return SkBitmap(); |
- |
- base::win::ScopedHDC source_dc(::CreateCompatibleDC(NULL)); |
- if (!source_dc) |
- return SkBitmap(); |
- ::SelectObject(source_dc, source_bitmap); |
- |
- // Get the dimensions of the bitmap. |
- BITMAPINFO bitmap_info = {}; |
- bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader); |
- ::GetDIBits(source_dc, source_bitmap, 0, 0, 0, &bitmap_info, DIB_RGB_COLORS); |
- int width = bitmap_info.bmiHeader.biWidth; |
- int height = bitmap_info.bmiHeader.biHeight; |
- |
- gfx::CanvasSkia canvas(width, height, false); |
- |
- skia::ScopedPlatformPaint scoped_platform_paint(&canvas); |
- HDC destination_dc = scoped_platform_paint.GetPlatformSurface(); |
- ::BitBlt(destination_dc, 0, 0, width, height, source_dc, 0, 0, SRCCOPY); |
+ // We use a DIB rather than a DDB here since ::GetObject() with the |
+ // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color |
+ // depth of 32bpp. |
+ BITMAPINFO* bitmap = static_cast<BITMAPINFO*>(::GetClipboardData(CF_DIB)); |
+ int color_table_length = 0; |
+ switch (bitmap->bmiHeader.biBitCount) { |
+ case 1: |
+ case 4: |
+ case 8: |
+ color_table_length = bitmap->bmiHeader.biClrUsed |
+ ? bitmap->bmiHeader.biClrUsed |
+ : 1 << bitmap->bmiHeader.biBitCount; |
+ break; |
+ case 16: |
+ case 32: |
+ if (bitmap->bmiHeader.biCompression == BI_BITFIELDS) |
+ color_table_length = 3; |
+ break; |
+ case 24: |
+ break; |
+ default: |
+ NOTREACHED(); |
+ } |
+ const void* bitmap_bits = reinterpret_cast<const char*>(bitmap) |
+ + bitmap->bmiHeader.biSize + color_table_length * sizeof(RGBQUAD); |
+ |
+ gfx::CanvasSkia canvas(bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, |
+ false); |
+ { |
+ skia::ScopedPlatformPaint scoped_platform_paint(&canvas); |
+ HDC dc = scoped_platform_paint.GetPlatformSurface(); |
+ ::SetDIBitsToDevice(dc, 0, 0, bitmap->bmiHeader.biWidth, |
+ bitmap->bmiHeader.biHeight, 0, 0, 0, |
+ bitmap->bmiHeader.biHeight, bitmap_bits, bitmap, |
+ DIB_RGB_COLORS); |
+ } |
+ // SetDIBitsToDevice doesn't properly set alpha values for bitmaps with |
+ // depth < 32bpp so manually fix it up. |
+ if (bitmap->bmiHeader.biBitCount < 32) { |
+ const SkBitmap& device_bitmap = canvas.getDevice()->accessBitmap(true); |
+ SkAutoLockPixels lock(device_bitmap); |
+ for (int i = 0; i < device_bitmap.height(); ++i) { |
+ for (int j = 0; j < device_bitmap.width(); ++j) { |
+ *device_bitmap.getAddr32(i, j) = |
+ SkColorSetA(*device_bitmap.getAddr32(i, j), 0xFF); |
+ } |
+ } |
+ } |
return canvas.ExtractBitmap(); |
} |