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 "ui/snapshot/snapshot.h" | 5 #include "ui/snapshot/snapshot.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/safe_numerics.h" | 10 #include "base/safe_numerics.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 bitmap = | 66 bitmap = |
67 skia::ImageOperations::Resize(input_bitmap, | 67 skia::ImageOperations::Resize(input_bitmap, |
68 skia::ImageOperations::RESIZE_GOOD, | 68 skia::ImageOperations::RESIZE_GOOD, |
69 target_size_pre_rotation.width(), | 69 target_size_pre_rotation.width(), |
70 target_size_pre_rotation.height(), | 70 target_size_pre_rotation.height(), |
71 static_cast<SkBitmap::Allocator*>(NULL)); | 71 static_cast<SkBitmap::Allocator*>(NULL)); |
72 RotateBitmap(&bitmap, rotation); | 72 RotateBitmap(&bitmap, rotation); |
73 return bitmap; | 73 return bitmap; |
74 } | 74 } |
75 | 75 |
| 76 scoped_refptr<base::RefCountedBytes> ScaleRotateAndEncodeBitmap( |
| 77 const SkBitmap& input_bitmap, |
| 78 gfx::Size target_size_pre_rotation, |
| 79 gfx::Display::Rotation rotation) { |
| 80 SkBitmap bitmap = |
| 81 ScaleAndRotateBitmap(input_bitmap, target_size_pre_rotation, rotation); |
| 82 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); |
| 83 unsigned char* pixels = |
| 84 reinterpret_cast<unsigned char*>(bitmap.pixelRef()->pixels()); |
| 85 if (!gfx::PNGCodec::Encode(pixels, |
| 86 gfx::PNGCodec::FORMAT_BGRA, |
| 87 gfx::Size(bitmap.width(), bitmap.height()), |
| 88 base::checked_numeric_cast<int>(bitmap.rowBytes()), |
| 89 true, |
| 90 std::vector<gfx::PNGCodec::Comment>(), |
| 91 &png_data->data())) { |
| 92 return scoped_refptr<base::RefCountedBytes>(); |
| 93 } |
| 94 return png_data; |
| 95 } |
| 96 |
76 void ScaleAndRotateCopyOutputResult( | 97 void ScaleAndRotateCopyOutputResult( |
77 const GrabWindowSnapshotAsyncCallback& callback, | 98 const GrabWindowSnapshotAsyncCallback& callback, |
78 const gfx::Size& target_size, | 99 const gfx::Size& target_size, |
79 gfx::Display::Rotation rotation, | 100 gfx::Display::Rotation rotation, |
80 scoped_refptr<base::TaskRunner> background_task_runner, | 101 scoped_refptr<base::TaskRunner> background_task_runner, |
81 scoped_ptr<cc::CopyOutputResult> result) { | 102 scoped_ptr<cc::CopyOutputResult> result) { |
82 if (result->IsEmpty()) { | 103 if (result->IsEmpty()) { |
83 callback.Run(gfx::Image()); | 104 callback.Run(gfx::Image()); |
84 return; | 105 return; |
85 } | 106 } |
86 | 107 |
87 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it | 108 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it |
88 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't | 109 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't |
89 // be used here because it's not in content/public. Move the scaling code | 110 // be used here because it's not in content/public. Move the scaling code |
90 // somewhere so that it can be reused here. | 111 // somewhere so that it can be reused here. |
91 base::PostTaskAndReplyWithResult( | 112 base::PostTaskAndReplyWithResult( |
92 background_task_runner, | 113 background_task_runner, |
93 FROM_HERE, | 114 FROM_HERE, |
94 base::Bind( | 115 base::Bind( |
95 ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation), | 116 ScaleAndRotateBitmap, *result->TakeBitmap(), target_size, rotation), |
96 base::Bind(&OnFrameScalingFinished, callback)); | 117 base::Bind(&OnFrameScalingFinished, callback)); |
97 } | 118 } |
98 | 119 |
| 120 void ScaleRotateAndEncodeCopyOutputResult( |
| 121 const GrabWindowSnapshotAsyncPNGCallback& callback, |
| 122 const gfx::Size& target_size, |
| 123 gfx::Display::Rotation rotation, |
| 124 scoped_refptr<base::TaskRunner> background_task_runner, |
| 125 scoped_ptr<cc::CopyOutputResult> result) { |
| 126 if (result->IsEmpty()) { |
| 127 callback.Run(scoped_refptr<base::RefCountedBytes>()); |
| 128 return; |
| 129 } |
| 130 |
| 131 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it |
| 132 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't |
| 133 // be used here because it's not in content/public. Move the scaling code |
| 134 // somewhere so that it can be reused here. |
| 135 base::PostTaskAndReplyWithResult(background_task_runner, |
| 136 FROM_HERE, |
| 137 base::Bind(ScaleRotateAndEncodeBitmap, |
| 138 *result->TakeBitmap(), |
| 139 target_size, |
| 140 rotation), |
| 141 callback); |
| 142 } |
| 143 |
99 gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window, | 144 gfx::Rect GetTargetBoundsFromWindow(gfx::NativeWindow window, |
100 gfx::Rect snapshot_bounds) { | 145 gfx::Rect snapshot_bounds) { |
101 gfx::RectF read_pixels_bounds = snapshot_bounds; | 146 gfx::RectF read_pixels_bounds = snapshot_bounds; |
102 | 147 |
103 // We must take into account the window's position on the desktop. | 148 // We must take into account the window's position on the desktop. |
104 read_pixels_bounds.Offset( | 149 read_pixels_bounds.Offset( |
105 window->GetBoundsInRootWindow().origin().OffsetFromOrigin()); | 150 window->GetBoundsInRootWindow().origin().OffsetFromOrigin()); |
106 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher(); | 151 aura::WindowEventDispatcher* dispatcher = window->GetDispatcher(); |
107 if (dispatcher) | 152 if (dispatcher) |
108 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds); | 153 dispatcher->host()->GetRootTransform().TransformRect(&read_pixels_bounds); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 pixels, gfx::PNGCodec::FORMAT_BGRA, | 195 pixels, gfx::PNGCodec::FORMAT_BGRA, |
151 gfx::Size(bitmap.width(), bitmap.height()), | 196 gfx::Size(bitmap.width(), bitmap.height()), |
152 base::checked_numeric_cast<int>(bitmap.rowBytes()), | 197 base::checked_numeric_cast<int>(bitmap.rowBytes()), |
153 true, std::vector<gfx::PNGCodec::Comment>(), | 198 true, std::vector<gfx::PNGCodec::Comment>(), |
154 png_representation); | 199 png_representation); |
155 } | 200 } |
156 | 201 |
157 void MakeAsyncCopyRequest( | 202 void MakeAsyncCopyRequest( |
158 gfx::NativeWindow window, | 203 gfx::NativeWindow window, |
159 const gfx::Rect& source_rect, | 204 const gfx::Rect& source_rect, |
160 const gfx::Size& target_size, | 205 const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { |
161 scoped_refptr<base::TaskRunner> background_task_runner, | |
162 const GrabWindowSnapshotAsyncCallback& callback) { | |
163 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) | |
164 ->GetDisplayNearestWindow(window) | |
165 .rotation(); | |
166 scoped_ptr<cc::CopyOutputRequest> request = | 206 scoped_ptr<cc::CopyOutputRequest> request = |
167 cc::CopyOutputRequest::CreateBitmapRequest( | 207 cc::CopyOutputRequest::CreateBitmapRequest(callback); |
168 base::Bind(&ScaleAndRotateCopyOutputResult, | |
169 callback, | |
170 target_size, | |
171 rotation, | |
172 background_task_runner)); | |
173 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); | 208 request->set_area(ui::ConvertRectToPixel(window->layer(), source_rect)); |
174 window->layer()->RequestCopyOfOutput(request.Pass()); | 209 window->layer()->RequestCopyOfOutput(request.Pass()); |
175 } | 210 } |
176 | 211 |
177 void GrabWindowSnapshotAndScaleAsync( | 212 void GrabWindowSnapshotAndScaleAsync( |
178 gfx::NativeWindow window, | 213 gfx::NativeWindow window, |
179 const gfx::Rect& source_rect, | 214 const gfx::Rect& source_rect, |
180 const gfx::Size& target_size, | 215 const gfx::Size& target_size, |
181 scoped_refptr<base::TaskRunner> background_task_runner, | 216 scoped_refptr<base::TaskRunner> background_task_runner, |
182 const GrabWindowSnapshotAsyncCallback& callback) { | 217 const GrabWindowSnapshotAsyncCallback& callback) { |
(...skipping 11 matching lines...) Expand all Loading... |
194 break; | 229 break; |
195 case gfx::Display::ROTATE_90: | 230 case gfx::Display::ROTATE_90: |
196 case gfx::Display::ROTATE_270: | 231 case gfx::Display::ROTATE_270: |
197 rotated_target_size = | 232 rotated_target_size = |
198 gfx::Size(target_size.height(), target_size.width()); | 233 gfx::Size(target_size.height(), target_size.width()); |
199 break; | 234 break; |
200 }; | 235 }; |
201 | 236 |
202 MakeAsyncCopyRequest(window, | 237 MakeAsyncCopyRequest(window, |
203 source_rect, | 238 source_rect, |
204 rotated_target_size, | 239 base::Bind(&ScaleAndRotateCopyOutputResult, |
205 background_task_runner, | 240 callback, |
206 callback); | 241 rotated_target_size, |
| 242 rotation, |
| 243 background_task_runner)); |
207 } | 244 } |
208 | 245 |
209 void GrabWindowSnapshotAsync( | 246 void GrabWindowSnapshotAsync( |
210 gfx::NativeWindow window, | 247 gfx::NativeWindow window, |
211 const gfx::Rect& source_rect, | 248 const gfx::Rect& source_rect, |
212 scoped_refptr<base::TaskRunner> background_task_runner, | 249 scoped_refptr<base::TaskRunner> background_task_runner, |
213 const GrabWindowSnapshotAsyncCallback& callback) { | 250 const GrabWindowSnapshotAsyncPNGCallback& callback) { |
214 gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size(); | 251 gfx::Size target_size = GetTargetBoundsFromWindow(window, source_rect).size(); |
215 MakeAsyncCopyRequest( | 252 gfx::Display::Rotation rotation = gfx::Screen::GetScreenFor(window) |
216 window, source_rect, target_size, background_task_runner, callback); | 253 ->GetDisplayNearestWindow(window) |
| 254 .rotation(); |
| 255 MakeAsyncCopyRequest(window, |
| 256 source_rect, |
| 257 base::Bind(&ScaleRotateAndEncodeCopyOutputResult, |
| 258 callback, |
| 259 target_size, |
| 260 rotation, |
| 261 background_task_runner)); |
217 } | 262 } |
218 | 263 |
219 } // namespace ui | 264 } // namespace ui |
OLD | NEW |