| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <windows.h> | 5 #include <windows.h> |
| 6 #include <psapi.h> | 6 #include <psapi.h> |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/debug/gdi_debug_util_win.h" | 9 #include "base/debug/gdi_debug_util_win.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/win/win_util.h" | 11 #include "base/win/win_util.h" |
| 12 #include "skia/ext/bitmap_platform_device_win.h" | 12 #include "skia/ext/bitmap_platform_device_win.h" |
| 13 #include "skia/ext/platform_canvas.h" | 13 #include "skia/ext/platform_canvas.h" |
| 14 #include "skia/ext/skia_utils_win.h" | 14 #include "skia/ext/skia_utils_win.h" |
| 15 #include "third_party/skia/include/core/SkMatrix.h" | 15 #include "third_party/skia/include/core/SkMatrix.h" |
| 16 #include "third_party/skia/include/core/SkPath.h" | 16 #include "third_party/skia/include/core/SkPath.h" |
| 17 #include "third_party/skia/include/core/SkRefCnt.h" | 17 #include "third_party/skia/include/core/SkRefCnt.h" |
| 18 #include "third_party/skia/include/core/SkRegion.h" | 18 #include "third_party/skia/include/core/SkRect.h" |
| 19 | 19 |
| 20 namespace { | 20 namespace { |
| 21 | 21 |
| 22 HBITMAP CreateHBitmap(int width, int height, bool is_opaque, | 22 HBITMAP CreateHBitmap(int width, int height, bool is_opaque, |
| 23 HANDLE shared_section, void** data) { | 23 HANDLE shared_section, void** data) { |
| 24 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so | 24 // CreateDIBSection appears to get unhappy if we create an empty bitmap, so |
| 25 // just create a minimal bitmap | 25 // just create a minimal bitmap |
| 26 if ((width == 0) || (height == 0)) { | 26 if ((width == 0) || (height == 0)) { |
| 27 width = 1; | 27 width = 1; |
| 28 height = 1; | 28 height = 1; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 59 xf.eM11 = matrix[SkMatrix::kMScaleX]; | 59 xf.eM11 = matrix[SkMatrix::kMScaleX]; |
| 60 xf.eM21 = matrix[SkMatrix::kMSkewX]; | 60 xf.eM21 = matrix[SkMatrix::kMSkewX]; |
| 61 xf.eDx = matrix[SkMatrix::kMTransX]; | 61 xf.eDx = matrix[SkMatrix::kMTransX]; |
| 62 xf.eM12 = matrix[SkMatrix::kMSkewY]; | 62 xf.eM12 = matrix[SkMatrix::kMSkewY]; |
| 63 xf.eM22 = matrix[SkMatrix::kMScaleY]; | 63 xf.eM22 = matrix[SkMatrix::kMScaleY]; |
| 64 xf.eDy = matrix[SkMatrix::kMTransY]; | 64 xf.eDy = matrix[SkMatrix::kMTransY]; |
| 65 SetWorldTransform(dc, &xf); | 65 SetWorldTransform(dc, &xf); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void LoadClippingRegionToDC(HDC context, | 68 void LoadClippingRegionToDC(HDC context, |
| 69 const SkRegion& region, | 69 const SkIRect& clip_bounds, |
| 70 const SkMatrix& transformation) { | 70 const SkMatrix& transformation) { |
| 71 HRGN hrgn; | 71 HRGN hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(clip_bounds)); |
| 72 if (region.isEmpty()) { | |
| 73 // region can be empty, in which case everything will be clipped. | |
| 74 hrgn = CreateRectRgn(0, 0, 0, 0); | |
| 75 } else if (region.isRect()) { | |
| 76 // We don't apply transformation, because the translation is already applied | |
| 77 // to the region. | |
| 78 hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(region.getBounds())); | |
| 79 } else { | |
| 80 hrgn = CreateRectRgnIndirect(&skia::SkIRectToRECT(region.getBounds())); | |
| 81 SkASSERT(!"Region clipping is being deprecated; this shouldn't fire."); | |
| 82 } | |
| 83 int result = SelectClipRgn(context, hrgn); | 72 int result = SelectClipRgn(context, hrgn); |
| 84 SkASSERT(result != ERROR); | 73 SkASSERT(result != ERROR); |
| 85 result = DeleteObject(hrgn); | 74 result = DeleteObject(hrgn); |
| 86 SkASSERT(result != 0); | 75 SkASSERT(result != 0); |
| 87 } | 76 } |
| 88 | 77 |
| 89 } // namespace | 78 } // namespace |
| 90 | 79 |
| 91 namespace skia { | 80 namespace skia { |
| 92 | 81 |
| 93 void DrawToNativeContext(SkCanvas* canvas, HDC hdc, int x, int y, | 82 void DrawToNativeContext(SkCanvas* canvas, HDC destination_hdc, int x, int y, |
| 94 const RECT* src_rect) { | 83 const RECT* src_rect) { |
| 84 ScopedPlatformPaint p(canvas); |
| 95 PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas)); | 85 PlatformDevice* platform_device = GetPlatformDevice(GetTopDevice(*canvas)); |
| 96 if (platform_device) | 86 if (platform_device) |
| 97 platform_device->DrawToHDC(hdc, x, y, src_rect); | 87 platform_device->DrawToHDC(p.GetPlatformSurface(), destination_hdc, x, y, |
| 88 src_rect, canvas->getTotalMatrix()); |
| 89 |
| 98 } | 90 } |
| 99 | 91 |
| 100 void PlatformDevice::DrawToHDC(HDC, int x, int y, const RECT* src_rect) {} | 92 void PlatformDevice::DrawToHDC(HDC, HDC, int x, int y, const RECT* src_rect, |
| 93 const SkMatrix& transform) {} |
| 101 | 94 |
| 102 HDC BitmapPlatformDevice::GetBitmapDC() { | 95 HDC BitmapPlatformDevice::GetBitmapDC(const SkMatrix& transform, |
| 96 const SkIRect& clip_bounds) { |
| 103 if (!hdc_) { | 97 if (!hdc_) { |
| 104 hdc_ = CreateCompatibleDC(NULL); | 98 hdc_ = CreateCompatibleDC(NULL); |
| 105 InitializeDC(hdc_); | 99 InitializeDC(hdc_); |
| 106 old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_)); | 100 old_hbitmap_ = static_cast<HBITMAP>(SelectObject(hdc_, hbitmap_)); |
| 107 } | 101 } |
| 108 | 102 |
| 109 LoadConfig(); | 103 LoadConfig(transform, clip_bounds); |
| 110 return hdc_; | 104 return hdc_; |
| 111 } | 105 } |
| 112 | 106 |
| 113 void BitmapPlatformDevice::ReleaseBitmapDC() { | 107 void BitmapPlatformDevice::ReleaseBitmapDC() { |
| 114 SkASSERT(hdc_); | 108 SkASSERT(hdc_); |
| 115 SelectObject(hdc_, old_hbitmap_); | 109 SelectObject(hdc_, old_hbitmap_); |
| 116 DeleteDC(hdc_); | 110 DeleteDC(hdc_); |
| 117 hdc_ = NULL; | 111 hdc_ = NULL; |
| 118 old_hbitmap_ = NULL; | 112 old_hbitmap_ = NULL; |
| 119 } | 113 } |
| 120 | 114 |
| 121 bool BitmapPlatformDevice::IsBitmapDCCreated() | 115 bool BitmapPlatformDevice::IsBitmapDCCreated() |
| 122 const { | 116 const { |
| 123 return hdc_ != NULL; | 117 return hdc_ != NULL; |
| 124 } | 118 } |
| 125 | 119 |
| 126 | 120 void BitmapPlatformDevice::LoadConfig(const SkMatrix& transform, |
| 127 void BitmapPlatformDevice::SetMatrixClip( | 121 const SkIRect& clip_bounds) { |
| 128 const SkMatrix& transform, | 122 if (!hdc_) |
| 129 const SkRegion& region) { | |
| 130 transform_ = transform; | |
| 131 clip_region_ = region; | |
| 132 config_dirty_ = true; | |
| 133 } | |
| 134 | |
| 135 void BitmapPlatformDevice::LoadConfig() { | |
| 136 if (!config_dirty_ || !hdc_) | |
| 137 return; // Nothing to do. | 123 return; // Nothing to do. |
| 138 config_dirty_ = false; | |
| 139 | 124 |
| 140 // Transform. | 125 // Transform. |
| 141 LoadTransformToDC(hdc_, transform_); | 126 LoadTransformToDC(hdc_, transform); |
| 142 LoadClippingRegionToDC(hdc_, clip_region_, transform_); | 127 LoadClippingRegionToDC(hdc_, clip_bounds, transform); |
| 143 } | 128 } |
| 144 | 129 |
| 145 static void DeleteHBitmapCallback(void* addr, void* context) { | 130 static void DeleteHBitmapCallback(void* addr, void* context) { |
| 146 // If context is not NULL then it's a valid HBITMAP to delete. | 131 // If context is not NULL then it's a valid HBITMAP to delete. |
| 147 // Otherwise we just unmap the pixel memory. | 132 // Otherwise we just unmap the pixel memory. |
| 148 if (context) | 133 if (context) |
| 149 DeleteObject(static_cast<HBITMAP>(context)); | 134 DeleteObject(static_cast<HBITMAP>(context)); |
| 150 else | 135 else |
| 151 UnmapViewOfFile(addr); | 136 UnmapViewOfFile(addr); |
| 152 } | 137 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 } | 207 } |
| 223 | 208 |
| 224 // The device will own the HBITMAP, which corresponds to also owning the pixel | 209 // The device will own the HBITMAP, which corresponds to also owning the pixel |
| 225 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap. | 210 // data. Therefore, we do not transfer ownership to the SkBitmapDevice's bitmap. |
| 226 BitmapPlatformDevice::BitmapPlatformDevice( | 211 BitmapPlatformDevice::BitmapPlatformDevice( |
| 227 HBITMAP hbitmap, | 212 HBITMAP hbitmap, |
| 228 const SkBitmap& bitmap) | 213 const SkBitmap& bitmap) |
| 229 : SkBitmapDevice(bitmap), | 214 : SkBitmapDevice(bitmap), |
| 230 hbitmap_(hbitmap), | 215 hbitmap_(hbitmap), |
| 231 old_hbitmap_(NULL), | 216 old_hbitmap_(NULL), |
| 232 hdc_(NULL), | 217 hdc_(NULL) { |
| 233 config_dirty_(true), // Want to load the config next time. | |
| 234 transform_(SkMatrix::I()) { | |
| 235 // The data object is already ref'ed for us by create(). | 218 // The data object is already ref'ed for us by create(). |
| 236 if (hbitmap) { | 219 if (hbitmap) { |
| 237 SetPlatformDevice(this, this); | 220 SetPlatformDevice(this, this); |
| 238 // Initialize the clip region to the entire bitmap. | |
| 239 BITMAP bitmap_data; | 221 BITMAP bitmap_data; |
| 240 if (GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data)) { | 222 GetObject(hbitmap_, sizeof(BITMAP), &bitmap_data); |
| 241 SkIRect rect; | |
| 242 rect.set(0, 0, bitmap_data.bmWidth, bitmap_data.bmHeight); | |
| 243 clip_region_ = SkRegion(rect); | |
| 244 } | |
| 245 } | 223 } |
| 246 } | 224 } |
| 247 | 225 |
| 248 BitmapPlatformDevice::~BitmapPlatformDevice() { | 226 BitmapPlatformDevice::~BitmapPlatformDevice() { |
| 249 if (hdc_) | 227 if (hdc_) |
| 250 ReleaseBitmapDC(); | 228 ReleaseBitmapDC(); |
| 251 } | 229 } |
| 252 | 230 |
| 253 HDC BitmapPlatformDevice::BeginPlatformPaint() { | 231 HDC BitmapPlatformDevice::BeginPlatformPaint(const SkMatrix& transform, |
| 254 return GetBitmapDC(); | 232 const SkIRect& clip_bounds) { |
| 233 return GetBitmapDC(transform, clip_bounds); |
| 255 } | 234 } |
| 256 | 235 |
| 257 void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform, | 236 void BitmapPlatformDevice::DrawToHDC(HDC source_dc, HDC destination_dc, |
| 258 const SkRegion& region, | 237 int x, int y, |
| 259 const SkClipStack&) { | 238 const RECT* src_rect, |
| 260 SetMatrixClip(transform, region); | 239 const SkMatrix& transform) { |
| 261 } | |
| 262 | |
| 263 void BitmapPlatformDevice::DrawToHDC(HDC dc, int x, int y, | |
| 264 const RECT* src_rect) { | |
| 265 bool created_dc = !IsBitmapDCCreated(); | 240 bool created_dc = !IsBitmapDCCreated(); |
| 266 HDC source_dc = BeginPlatformPaint(); | |
| 267 | 241 |
| 268 RECT temp_rect; | 242 RECT temp_rect; |
| 269 if (!src_rect) { | 243 if (!src_rect) { |
| 270 temp_rect.left = 0; | 244 temp_rect.left = 0; |
| 271 temp_rect.right = width(); | 245 temp_rect.right = width(); |
| 272 temp_rect.top = 0; | 246 temp_rect.top = 0; |
| 273 temp_rect.bottom = height(); | 247 temp_rect.bottom = height(); |
| 274 src_rect = &temp_rect; | 248 src_rect = &temp_rect; |
| 275 } | 249 } |
| 276 | 250 |
| 277 int copy_width = src_rect->right - src_rect->left; | 251 int copy_width = src_rect->right - src_rect->left; |
| 278 int copy_height = src_rect->bottom - src_rect->top; | 252 int copy_height = src_rect->bottom - src_rect->top; |
| 279 | 253 |
| 280 // We need to reset the translation for our bitmap or (0,0) won't be in the | 254 // We need to reset the translation for our bitmap or (0,0) won't be in the |
| 281 // upper left anymore | 255 // upper left anymore |
| 282 SkMatrix identity; | 256 SkMatrix identity; |
| 283 identity.reset(); | 257 identity.reset(); |
| 284 | 258 |
| 285 LoadTransformToDC(source_dc, identity); | 259 LoadTransformToDC(source_dc, identity); |
| 286 if (isOpaque()) { | 260 if (isOpaque()) { |
| 287 BitBlt(dc, | 261 BitBlt(destination_dc, |
| 288 x, | 262 x, |
| 289 y, | 263 y, |
| 290 copy_width, | 264 copy_width, |
| 291 copy_height, | 265 copy_height, |
| 292 source_dc, | 266 source_dc, |
| 293 src_rect->left, | 267 src_rect->left, |
| 294 src_rect->top, | 268 src_rect->top, |
| 295 SRCCOPY); | 269 SRCCOPY); |
| 296 } else { | 270 } else { |
| 297 SkASSERT(copy_width != 0 && copy_height != 0); | 271 SkASSERT(copy_width != 0 && copy_height != 0); |
| 298 BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; | 272 BLENDFUNCTION blend_function = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; |
| 299 GdiAlphaBlend(dc, | 273 GdiAlphaBlend(destination_dc, |
| 300 x, | 274 x, |
| 301 y, | 275 y, |
| 302 copy_width, | 276 copy_width, |
| 303 copy_height, | 277 copy_height, |
| 304 source_dc, | 278 source_dc, |
| 305 src_rect->left, | 279 src_rect->left, |
| 306 src_rect->top, | 280 src_rect->top, |
| 307 copy_width, | 281 copy_width, |
| 308 copy_height, | 282 copy_height, |
| 309 blend_function); | 283 blend_function); |
| 310 } | 284 } |
| 311 LoadTransformToDC(source_dc, transform_); | 285 LoadTransformToDC(source_dc, transform); |
| 312 | 286 |
| 313 if (created_dc) | 287 if (created_dc) |
| 314 ReleaseBitmapDC(); | 288 ReleaseBitmapDC(); |
| 315 } | 289 } |
| 316 | 290 |
| 317 const SkBitmap& BitmapPlatformDevice::onAccessBitmap() { | 291 const SkBitmap& BitmapPlatformDevice::onAccessBitmap() { |
| 318 // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI | 292 // FIXME(brettw) OPTIMIZATION: We should only flush if we know a GDI |
| 319 // operation has occurred on our DC. | 293 // operation has occurred on our DC. |
| 320 if (IsBitmapDCCreated()) | 294 if (IsBitmapDCCreated()) |
| 321 GdiFlush(); | 295 GdiFlush(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 336 int height, | 310 int height, |
| 337 bool is_opaque, | 311 bool is_opaque, |
| 338 HANDLE shared_section, | 312 HANDLE shared_section, |
| 339 OnFailureType failureType) { | 313 OnFailureType failureType) { |
| 340 sk_sp<SkBaseDevice> dev( | 314 sk_sp<SkBaseDevice> dev( |
| 341 BitmapPlatformDevice::Create(width, height, is_opaque, shared_section)); | 315 BitmapPlatformDevice::Create(width, height, is_opaque, shared_section)); |
| 342 return CreateCanvas(dev, failureType); | 316 return CreateCanvas(dev, failureType); |
| 343 } | 317 } |
| 344 | 318 |
| 345 } // namespace skia | 319 } // namespace skia |
| OLD | NEW |