Chromium Code Reviews| Index: ui/snapshot/snapshot_aura.cc |
| diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc |
| index 5fdd4dc519110e8b747685dc03420d019a4ceeaf..e009f57d6815b67338f137f4ffce17533cbbc8b1 100644 |
| --- a/ui/snapshot/snapshot_aura.cc |
| +++ b/ui/snapshot/snapshot_aura.cc |
| @@ -40,9 +40,43 @@ void OnFrameScalingFinished( |
| callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); |
| } |
| -void ScaleCopyOutputResult( |
| +void RotateBitmap(SkBitmap* bitmap, gfx::Display::Rotation rotation) { |
| + switch (rotation) { |
| + case gfx::Display::ROTATE_0: |
| + break; |
| + case gfx::Display::ROTATE_90: |
| + *bitmap = SkBitmapOperations::Rotate(*bitmap, |
| + SkBitmapOperations::ROTATION_270_CW); |
| + break; |
| + case gfx::Display::ROTATE_180: |
| + *bitmap = SkBitmapOperations::Rotate(*bitmap, |
| + SkBitmapOperations::ROTATION_180_CW); |
| + break; |
| + case gfx::Display::ROTATE_270: |
| + *bitmap = SkBitmapOperations::Rotate(*bitmap, |
| + SkBitmapOperations::ROTATION_90_CW); |
| + break; |
| + } |
| +} |
| + |
| +SkBitmap ScaleAndRotateBitmap(const SkBitmap& input_bitmap, |
| + gfx::Size target_size_pre_rotation, |
| + gfx::Display::Rotation rotation) { |
| + SkBitmap bitmap; |
| + bitmap = |
| + skia::ImageOperations::Resize(input_bitmap, |
| + skia::ImageOperations::RESIZE_GOOD, |
| + target_size_pre_rotation.width(), |
| + target_size_pre_rotation.height(), |
| + static_cast<SkBitmap::Allocator*>(NULL)); |
| + RotateBitmap(&bitmap, rotation); |
| + return bitmap; |
| +} |
| + |
| +void ScaleAndRotateCopyOutputResult( |
| const GrabWindowSnapshotAsyncCallback& callback, |
| const gfx::Size& target_size, |
| + gfx::Display::Rotation rotation, |
| scoped_refptr<base::TaskRunner> background_task_runner, |
| scoped_ptr<cc::CopyOutputResult> result) { |
| if (result->IsEmpty()) { |
| @@ -50,40 +84,20 @@ void ScaleCopyOutputResult( |
| return; |
| } |
| - // There are two overrides for skia::ImageOperations::Resize(), so we need get |
| - // pointer to the right override explicitly (otherwise the base::Bind() call |
| - // below won't compile). |
| - SkBitmap (*resize_function)(const SkBitmap&, |
| - skia::ImageOperations::ResizeMethod, int, int, |
| - SkBitmap::Allocator* allocator) = |
| - &skia::ImageOperations::Resize; |
| - |
| // TODO(sergeyu): Potentially images can be scaled on GPU before reading it |
| // from GPU. Image scaling is implemented in content::GlHelper, but it's can't |
| // be used here because it's not in content/public. Move the scaling code |
| // somewhere so that it can be reused here. |
| base::PostTaskAndReplyWithResult( |
| - background_task_runner, FROM_HERE, |
| - base::Bind(resize_function, *result->TakeBitmap(), |
| - skia::ImageOperations::RESIZE_GOOD, |
| - target_size.width(), target_size.height(), |
| - static_cast<SkBitmap::Allocator*>(NULL)), |
| + background_task_runner, |
| + FROM_HERE, |
| + base::Bind( |
| + ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation), |
| base::Bind(&OnFrameScalingFinished, callback)); |
| } |
| -} // namespace |
| - |
| -bool GrabViewSnapshot(gfx::NativeView view, |
| - std::vector<unsigned char>* png_representation, |
| - const gfx::Rect& snapshot_bounds) { |
| - return GrabWindowSnapshot(view, png_representation, snapshot_bounds); |
| -} |
| - |
| -bool GrabWindowSnapshot(gfx::NativeWindow window, |
| - std::vector<unsigned char>* png_representation, |
| - const gfx::Rect& snapshot_bounds) { |
| - ui::Compositor* compositor = window->layer()->GetCompositor(); |
| - |
| +gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window, |
| + gfx::Rect snapshot_bounds) { |
| gfx::RectF read_pixels_bounds = snapshot_bounds; |
| // We must take into account the window's position on the desktop. |
| @@ -98,33 +112,37 @@ bool GrabWindowSnapshot(gfx::NativeWindow window, |
| // Sometimes (i.e. when using Aero on Windows) the compositor's size is |
| // smaller than the window bounds. So trim appropriately. |
| + ui::Compositor* compositor = window->layer()->GetCompositor(); |
| read_pixels_bounds_in_pixel.Intersect(gfx::Rect(compositor->size())); |
| DCHECK_LE(0, read_pixels_bounds.x()); |
| DCHECK_LE(0, read_pixels_bounds.y()); |
| + return read_pixels_bounds_in_pixel; |
| +} |
| + |
| +} // namespace |
| + |
| +bool GrabViewSnapshot(gfx::NativeView view, |
| + std::vector<unsigned char>* png_representation, |
| + const gfx::Rect& snapshot_bounds) { |
| + return GrabWindowSnapshot(view, png_representation, snapshot_bounds); |
| +} |
| + |
| +bool GrabWindowSnapshot(gfx::NativeWindow window, |
| + std::vector<unsigned char>* png_representation, |
| + const gfx::Rect& snapshot_bounds) { |
| + gfx::Rect read_pixels_bounds_in_pixel = |
| + GetTargetBoundsFromWindow(window, snapshot_bounds); |
| + |
| + ui::Compositor* compositor = window->layer()->GetCompositor(); |
| SkBitmap bitmap; |
| if (!compositor->ReadPixels(&bitmap, read_pixels_bounds_in_pixel)) |
| return false; |
| gfx::Display display = |
| gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window); |
| - switch (display.rotation()) { |
| - case gfx::Display::ROTATE_0: |
| - break; |
| - case gfx::Display::ROTATE_90: |
| - bitmap = SkBitmapOperations::Rotate( |
| - bitmap, SkBitmapOperations::ROTATION_270_CW); |
| - break; |
| - case gfx::Display::ROTATE_180: |
| - bitmap = SkBitmapOperations::Rotate( |
| - bitmap, SkBitmapOperations::ROTATION_180_CW); |
| - break; |
| - case gfx::Display::ROTATE_270: |
| - bitmap = SkBitmapOperations::Rotate( |
| - bitmap, SkBitmapOperations::ROTATION_90_CW); |
| - break; |
| - } |
| + RotateBitmap(&bitmap, display.rotation()); |
| unsigned char* pixels = reinterpret_cast<unsigned char*>( |
| bitmap.pixelRef()->pixels()); |
| @@ -136,15 +154,57 @@ bool GrabWindowSnapshot(gfx::NativeWindow window, |
| png_representation); |
| } |
| -SNAPSHOT_EXPORT void GrabWindowSnapshotAsync( |
| +void GrabWindowSnapshotAndScaleAsync( |
| gfx::NativeWindow window, |
| const gfx::Rect& source_rect, |
| const gfx::Size& target_size, |
| scoped_refptr<base::TaskRunner> background_task_runner, |
| const GrabWindowSnapshotAsyncCallback& callback) { |
| + // target_size is post-rotation, and so logically this is a rotate and then |
| + // scale operation. However, it will usually be more efficient to scale first |
| + // (given that this is mostly used for thumbnails) and then rotate. |
| + gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) |
| + ->GetDisplayNearestWindow(window) |
| + .rotation(); |
| + gfx::Size rotated_target_size; |
| + switch (rotation) { |
| + case gfx::Display::ROTATE_0: |
| + case gfx::Display::ROTATE_180: |
| + rotated_target_size = target_size; |
| + break; |
| + case gfx::Display::ROTATE_90: |
| + case gfx::Display::ROTATE_270: |
| + rotated_target_size = |
| + gfx::Size(target_size.height(), target_size.width()); |
| + break; |
| + }; |
| + |
| + scoped_ptr<cc::CopyOutputRequest> request = |
| + cc::CopyOutputRequest::CreateBitmapRequest( |
| + base::Bind(&ScaleAndRotateCopyOutputResult, |
| + callback, |
| + rotated_target_size, |
| + rotation, |
| + background_task_runner)); |
| + request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); |
| + window->layer()->RequestCopyOfOutput(request.Pass()); |
| +} |
| + |
| +void GrabWindowSnapshotAsync( |
| + gfx::NativeWindow window, |
| + const gfx::Rect& source_rect, |
| + scoped_refptr<base::TaskRunner> background_task_runner, |
| + const GrabWindowSnapshotAsyncCallback& callback) { |
| + gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size(); |
| + gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) |
| + ->GetDisplayNearestWindow(window) |
| + .rotation(); |
| scoped_ptr<cc::CopyOutputRequest> request = |
|
Sergey Ulanov
2014/01/08 02:24:16
It looks like a lot of code in this function is du
enne (OOO)
2014/01/08 18:50:48
Done. Can't call GrabWindowSnapshotAndScaleAsync
|
| cc::CopyOutputRequest::CreateBitmapRequest( |
| - base::Bind(&ScaleCopyOutputResult, callback, target_size, |
| + base::Bind(&ScaleAndRotateCopyOutputResult, |
| + callback, |
| + target_size, |
| + rotation, |
| background_task_runner)); |
| request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); |
| window->layer()->RequestCopyOfOutput(request.Pass()); |