| 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 |