OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Many of these functions are based on those found in | 5 // Many of these functions are based on those found in |
6 // webkit/port/platform/PasteboardWin.cpp | 6 // webkit/port/platform/PasteboardWin.cpp |
7 | 7 |
8 #include "ui/base/clipboard/clipboard.h" | 8 #include "ui/base/clipboard/clipboard.h" |
9 | 9 |
10 #include <shlobj.h> | 10 #include <shlobj.h> |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 } | 431 } |
432 | 432 |
433 SkBitmap Clipboard::ReadImage(Buffer buffer) const { | 433 SkBitmap Clipboard::ReadImage(Buffer buffer) const { |
434 DCHECK_EQ(buffer, BUFFER_STANDARD); | 434 DCHECK_EQ(buffer, BUFFER_STANDARD); |
435 | 435 |
436 // Acquire the clipboard. | 436 // Acquire the clipboard. |
437 ScopedClipboard clipboard; | 437 ScopedClipboard clipboard; |
438 if (!clipboard.Acquire(GetClipboardWindow())) | 438 if (!clipboard.Acquire(GetClipboardWindow())) |
439 return SkBitmap(); | 439 return SkBitmap(); |
440 | 440 |
441 HBITMAP source_bitmap = static_cast<HBITMAP>(::GetClipboardData(CF_BITMAP)); | 441 // We use a DIB rather than a DDB here since ::GetObject() with the |
442 if (!source_bitmap) | 442 // HBITMAP returned from ::GetClipboardData(CF_BITMAP) always reports a color |
443 return SkBitmap(); | 443 // depth of 32bpp. |
Wez
2011/08/05 00:12:58
The reason for using a DIB is really that DIBs are
dcheng
2011/08/05 20:33:08
Not having to deal with the palette makes things e
| |
444 BITMAPINFO* bitmap = static_cast<BITMAPINFO*>(::GetClipboardData(CF_DIB)); | |
445 int color_table_length = 0; | |
446 switch (bitmap->bmiHeader.biBitCount) { | |
447 case 1: | |
448 case 4: | |
449 case 8: | |
450 color_table_length = bitmap->bmiHeader.biClrUsed | |
451 ? bitmap->bmiHeader.biClrUsed | |
452 : 1 << bitmap->bmiHeader.biBitCount; | |
453 break; | |
454 case 16: | |
455 case 32: | |
456 if (bitmap->bmiHeader.biCompression == BI_BITFIELDS) | |
457 color_table_length = 3; | |
458 break; | |
459 case 24: | |
tony
2011/08/04 22:06:56
The msdn page about BITMAPINFOHEADER says, "The bm
dcheng
2011/08/04 22:13:54
It also says it's NULL right before that. Honestly
tony
2011/08/04 22:20:52
So it does. That's really confusing. Ok, LGTM.
Wez
2011/08/05 00:12:58
For bit counts of >=16, I think biClrUsed is suppo
dcheng
2011/08/05 20:33:08
Hmm. All the code I can find treats BI_RGB identic
| |
460 break; | |
461 default: | |
462 NOTREACHED(); | |
463 } | |
464 const void* bitmap_bits = reinterpret_cast<const char*>(bitmap) | |
465 + bitmap->bmiHeader.biSize + color_table_length * sizeof(RGBQUAD); | |
444 | 466 |
445 base::win::ScopedHDC source_dc(::CreateCompatibleDC(NULL)); | 467 gfx::CanvasSkia canvas(bitmap->bmiHeader.biWidth, bitmap->bmiHeader.biHeight, |
446 if (!source_dc) | 468 true); |
447 return SkBitmap(); | 469 { |
448 ::SelectObject(source_dc, source_bitmap); | 470 skia::ScopedPlatformPaint scoped_platform_paint(&canvas); |
449 | 471 HDC dc = scoped_platform_paint.GetPlatformSurface(); |
450 // Get the dimensions of the bitmap. | 472 ::SetDIBitsToDevice(dc, 0, 0, bitmap->bmiHeader.biWidth, |
451 BITMAPINFO bitmap_info = {}; | 473 bitmap->bmiHeader.biHeight, 0, 0, 0, |
452 bitmap_info.bmiHeader.biSize = sizeof(bitmap_info.bmiHeader); | 474 bitmap->bmiHeader.biHeight, bitmap_bits, bitmap, |
453 ::GetDIBits(source_dc, source_bitmap, 0, 0, 0, &bitmap_info, DIB_RGB_COLORS); | 475 DIB_RGB_COLORS); |
454 int width = bitmap_info.bmiHeader.biWidth; | 476 } |
455 int height = bitmap_info.bmiHeader.biHeight; | 477 // SetDIBitsToDevice doesn't properly set alpha values for bitmaps with |
456 | 478 // depth < 32bpp so manually fix it up. |
457 gfx::CanvasSkia canvas(width, height, false); | 479 if (bitmap->bmiHeader.biBitCount < 32) { |
458 | 480 const SkBitmap& device_bitmap = canvas.getDevice()->accessBitmap(true); |
459 skia::ScopedPlatformPaint scoped_platform_paint(&canvas); | 481 SkAutoLockPixels lock(device_bitmap); |
460 HDC destination_dc = scoped_platform_paint.GetPlatformSurface(); | 482 for (int i = 0; i < device_bitmap.height(); ++i) { |
461 ::BitBlt(destination_dc, 0, 0, width, height, source_dc, 0, 0, SRCCOPY); | 483 for (int j = 0; j < device_bitmap.width(); ++j) { |
484 *device_bitmap.getAddr32(i, j) = | |
485 SkColorSetA(*device_bitmap.getAddr32(i, j), 0xFF); | |
486 } | |
487 } | |
488 } | |
462 return canvas.ExtractBitmap(); | 489 return canvas.ExtractBitmap(); |
463 } | 490 } |
464 | 491 |
465 void Clipboard::ReadBookmark(string16* title, std::string* url) const { | 492 void Clipboard::ReadBookmark(string16* title, std::string* url) const { |
466 if (title) | 493 if (title) |
467 title->clear(); | 494 title->clear(); |
468 | 495 |
469 if (url) | 496 if (url) |
470 url->clear(); | 497 url->clear(); |
471 | 498 |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
659 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", | 686 clipboard_owner_ = ::CreateWindow(L"ClipboardOwnerWindowClass", |
660 L"ClipboardOwnerWindow", | 687 L"ClipboardOwnerWindow", |
661 0, 0, 0, 0, 0, | 688 0, 0, 0, 0, 0, |
662 HWND_MESSAGE, | 689 HWND_MESSAGE, |
663 0, 0, 0); | 690 0, 0, 0); |
664 } | 691 } |
665 return clipboard_owner_; | 692 return clipboard_owner_; |
666 } | 693 } |
667 | 694 |
668 } // namespace ui | 695 } // namespace ui |
OLD | NEW |