OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #include "views/drag_utils.h" | 5 #include "views/drag_utils.h" |
6 | 6 |
7 #include <objidl.h> | 7 #include <objidl.h> |
8 #include <shlobj.h> | 8 #include <shlobj.h> |
9 #include <shobjidl.h> | 9 #include <shobjidl.h> |
10 | 10 |
11 #include "app/os_exchange_data.h" | 11 #include "app/os_exchange_data.h" |
12 #include "app/os_exchange_data_provider_win.h" | 12 #include "app/os_exchange_data_provider_win.h" |
13 #include "gfx/canvas_skia.h" | 13 #include "gfx/canvas_skia.h" |
14 #include "gfx/gdi_util.h" | 14 #include "gfx/gdi_util.h" |
| 15 #include "gfx/skbitmap_operations.h" |
15 #include "third_party/skia/include/core/SkBitmap.h" | 16 #include "third_party/skia/include/core/SkBitmap.h" |
16 | 17 |
17 namespace drag_utils { | 18 namespace drag_utils { |
18 | 19 |
19 static void SetDragImageOnDataObject(HBITMAP hbitmap, | 20 static void SetDragImageOnDataObject(HBITMAP hbitmap, |
20 const gfx::Size& size, | 21 const gfx::Size& size, |
21 const gfx::Point& cursor_offset, | 22 const gfx::Point& cursor_offset, |
22 IDataObject* data_object) { | 23 IDataObject* data_object) { |
23 IDragSourceHelper* helper = NULL; | 24 IDragSourceHelper* helper = NULL; |
24 HRESULT rv = CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, | 25 HRESULT rv = CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER, |
25 IID_IDragSourceHelper, reinterpret_cast<LPVOID*>(&helper)); | 26 IID_IDragSourceHelper, reinterpret_cast<LPVOID*>(&helper)); |
26 if (SUCCEEDED(rv)) { | 27 if (SUCCEEDED(rv)) { |
27 SHDRAGIMAGE sdi; | 28 SHDRAGIMAGE sdi; |
28 sdi.sizeDragImage = size.ToSIZE(); | 29 sdi.sizeDragImage = size.ToSIZE(); |
29 sdi.crColorKey = 0xFFFFFFFF; | 30 sdi.crColorKey = 0xFFFFFFFF; |
30 sdi.hbmpDragImage = hbitmap; | 31 sdi.hbmpDragImage = hbitmap; |
31 sdi.ptOffset = cursor_offset.ToPOINT(); | 32 sdi.ptOffset = cursor_offset.ToPOINT(); |
32 helper->InitializeFromBitmap(&sdi, data_object); | 33 helper->InitializeFromBitmap(&sdi, data_object); |
33 } | 34 } |
34 }; | 35 }; |
35 | 36 |
36 // Blit the contents of the canvas to a new HBITMAP. It is the caller's | 37 // Blit the contents of the canvas to a new HBITMAP. It is the caller's |
37 // responsibility to release the |bits| buffer. | 38 // responsibility to release the |bits| buffer. |
38 static HBITMAP CreateBitmapFromCanvas(const gfx::CanvasSkia& canvas, | 39 static HBITMAP CreateHBITMAPFromSkBitmap(const SkBitmap& sk_bitmap) { |
39 int width, | |
40 int height) { | |
41 HDC screen_dc = GetDC(NULL); | 40 HDC screen_dc = GetDC(NULL); |
42 BITMAPINFOHEADER header; | 41 BITMAPINFOHEADER header; |
43 gfx::CreateBitmapHeader(width, height, &header); | 42 gfx::CreateBitmapHeader(sk_bitmap.width(), sk_bitmap.height(), &header); |
44 void* bits; | 43 void* bits; |
45 HBITMAP bitmap = | 44 HBITMAP bitmap = |
46 CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&header), | 45 CreateDIBSection(screen_dc, reinterpret_cast<BITMAPINFO*>(&header), |
47 DIB_RGB_COLORS, &bits, NULL, 0); | 46 DIB_RGB_COLORS, &bits, NULL, 0); |
48 HDC compatible_dc = CreateCompatibleDC(screen_dc); | 47 DCHECK(sk_bitmap.rowBytes() == sk_bitmap.width() * 4); |
49 HGDIOBJ old_object = SelectObject(compatible_dc, bitmap); | 48 SkAutoLockPixels lock(sk_bitmap); |
50 BitBlt(compatible_dc, 0, 0, width, height, | 49 memcpy( |
51 canvas.getTopPlatformDevice().getBitmapDC(), | 50 bits, sk_bitmap.getPixels(), sk_bitmap.height() * sk_bitmap.rowBytes()); |
52 0, 0, SRCCOPY); | |
53 SelectObject(compatible_dc, old_object); | |
54 ReleaseDC(NULL, compatible_dc); | |
55 ReleaseDC(NULL, screen_dc); | 51 ReleaseDC(NULL, screen_dc); |
56 return bitmap; | 52 return bitmap; |
57 } | 53 } |
58 | 54 |
59 void SetDragImageOnDataObject(const SkBitmap& sk_bitmap, | 55 void SetDragImageOnDataObject(const SkBitmap& sk_bitmap, |
60 const gfx::Size& size, | 56 const gfx::Size& size, |
61 const gfx::Point& cursor_offset, | 57 const gfx::Point& cursor_offset, |
62 OSExchangeData* data_object) { | 58 OSExchangeData* data_object) { |
63 gfx::CanvasSkia canvas(sk_bitmap.width(), sk_bitmap.height(), | |
64 /*is_opaque=*/false); | |
65 canvas.DrawBitmapInt(sk_bitmap, 0, 0); | |
66 | |
67 DCHECK(data_object && !size.IsEmpty()); | 59 DCHECK(data_object && !size.IsEmpty()); |
| 60 // InitializeFromBitmap() doesn't expect an alpha channel and is confused |
| 61 // by premultiplied colors, so unpremultiply the bitmap. |
68 // SetDragImageOnDataObject(HBITMAP) takes ownership of the bitmap. | 62 // SetDragImageOnDataObject(HBITMAP) takes ownership of the bitmap. |
69 HBITMAP bitmap = CreateBitmapFromCanvas(canvas, size.width(), size.height()); | 63 HBITMAP bitmap = CreateHBITMAPFromSkBitmap( |
| 64 SkBitmapOperations::UnPreMultiply(sk_bitmap)); |
70 | 65 |
71 // Attach 'bitmap' to the data_object. | 66 // Attach 'bitmap' to the data_object. |
72 SetDragImageOnDataObject(bitmap, size, cursor_offset, | 67 SetDragImageOnDataObject(bitmap, size, cursor_offset, |
73 OSExchangeDataProviderWin::GetIDataObject(*data_object)); | 68 OSExchangeDataProviderWin::GetIDataObject(*data_object)); |
74 } | 69 } |
75 | 70 |
76 } // namespace drag_utils | 71 } // namespace drag_utils |
OLD | NEW |