summaryrefslogtreecommitdiffstats
path: root/ui/base/clipboard
diff options
context:
space:
mode:
authordcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-05 22:04:08 +0000
committerdcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-05 22:04:08 +0000
commitf900fb44fe7bd9c34e0a583bff4a43280be42878 (patch)
tree0671ac5db95bc6e8d2df35ff0279c31dca0167a4 /ui/base/clipboard
parentbdae5c11607e7162a0b9b9bca68d1dca0cf6affa (diff)
downloadchromium_src-f900fb44fe7bd9c34e0a583bff4a43280be42878.zip
chromium_src-f900fb44fe7bd9c34e0a583bff4a43280be42878.tar.gz
chromium_src-f900fb44fe7bd9c34e0a583bff4a43280be42878.tar.bz2
Properly scope ScopedPlatformPaint so that the native drawing layer and Skia are in agreement on the state of the pixels. Also fix Windows to not return completely transparent bitmaps when the source image has color depth < 32 bpp.
BUG=86085 TEST=Copy an image from MS Paint and paste it into Gmail using 32bpp for the display color depth. Review URL: http://codereview.chromium.org/7471008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95668 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base/clipboard')
-rw-r--r--ui/base/clipboard/clipboard_linux.cc10
-rw-r--r--ui/base/clipboard/clipboard_mac.mm16
-rw-r--r--ui/base/clipboard/clipboard_win.cc69
3 files changed, 63 insertions, 32 deletions
diff --git a/ui/base/clipboard/clipboard_linux.cc b/ui/base/clipboard/clipboard_linux.cc
index 718fed5..ad089ad 100644
--- a/ui/base/clipboard/clipboard_linux.cc
+++ b/ui/base/clipboard/clipboard_linux.cc
@@ -388,10 +388,12 @@ SkBitmap Clipboard::ReadImage(Buffer buffer) const {
gfx::CanvasSkia canvas(gdk_pixbuf_get_width(pixbuf.get()),
gdk_pixbuf_get_height(pixbuf.get()),
false);
- skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
- cairo_t* context = scoped_platform_paint.GetPlatformSurface();
- gdk_cairo_set_source_pixbuf(context, pixbuf.get(), 0.0, 0.0);
- cairo_paint(context);
+ {
+ skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
+ cairo_t* context = scoped_platform_paint.GetPlatformSurface();
+ gdk_cairo_set_source_pixbuf(context, pixbuf.get(), 0.0, 0.0);
+ cairo_paint(context);
+ }
return canvas.ExtractBitmap();
}
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index 9f65e79..4f6b88a 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -247,12 +247,15 @@ SkBitmap Clipboard::ReadImage(Buffer buffer) const {
scoped_nsobject<NSImage> image(
[[NSImage alloc] initWithPasteboard:GetPasteboard()]);
- if (image.get()) {
- [image setFlipped:YES];
- int width = [image size].width;
- int height = [image size].height;
+ if (!image.get())
+ return SkBitmap();
- gfx::CanvasSkia canvas(width, height, false);
+ [image setFlipped:YES];
+ int width = [image size].width;
+ int height = [image size].height;
+
+ gfx::CanvasSkia canvas(width, height, false);
+ {
skia::ScopedPlatformPaint scoped_platform_paint(&canvas);
CGContextRef gc = scoped_platform_paint.GetPlatformSurface();
NSGraphicsContext* cocoa_gc =
@@ -263,9 +266,8 @@ SkBitmap Clipboard::ReadImage(Buffer buffer) const {
operation:NSCompositeCopy
fraction:1.0];
[NSGraphicsContext restoreGraphicsState];
- return canvas.ExtractBitmap();
}
- return SkBitmap();
+ return canvas.ExtractBitmap();
}
void Clipboard::ReadBookmark(string16* title, std::string* url) const {
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index 867448a..603c14e 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();
}