Chromium Code Reviews| Index: content/browser/media/capture/cursor_renderer_mac.mm |
| diff --git a/content/browser/media/capture/cursor_renderer_mac.mm b/content/browser/media/capture/cursor_renderer_mac.mm |
| index c7c85f6ea087b229f33fcb3aea86dde3febeafb7..318895b9ffe548ff8c66878a2d19aa94cf0e5fbc 100644 |
| --- a/content/browser/media/capture/cursor_renderer_mac.mm |
| +++ b/content/browser/media/capture/cursor_renderer_mac.mm |
| @@ -28,6 +28,26 @@ inline int alpha_blend(int alpha, int src, int dst) { |
| return (src * alpha + dst * (255 - alpha)) / 255; |
| } |
| +CGImageRef ResizeCGImage(CGImageRef image, int width, int height) { |
| + // create context, keeping original image properties |
| + CGColorSpaceRef colorspace = CGImageGetColorSpace(image); |
| + CGContextRef context = CGBitmapContextCreate( |
| + NULL, width, height, CGImageGetBitsPerComponent(image), width * 4, |
| + colorspace, CGImageGetBitmapInfo(image)); |
| + CGColorSpaceRelease(colorspace); |
| + |
| + if (context == NULL) |
| + return nil; |
| + |
| + // draw image to context (resizing it) |
| + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); |
| + // extract resulting image from context |
| + CGImageRef imgRef = CGBitmapContextCreateImage(context); |
| + CGContextRelease(context); |
| + |
| + return imgRef; |
| +} |
| + |
| } // namespace |
| // static |
| @@ -65,11 +85,19 @@ bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) { |
| NSPoint mouse_tab_location = |
|
miu
2016/12/06 22:06:23
This variable must be renamed. Code in src/content
|
| [view_ convertPoint:mouse_window_location fromView:nil]; |
| + // The |view_| is in window coordinates. And the |region_in_frame| is in |
| + // physical coordinates, which also might be clamped by the configured |
| + // |max_capture_size|. So we need to get the final scale ratio and unify |
| + // all the comparison and calculation below. |
| + NSRect frame_rect = [view_ bounds]; |
| + float x_scale = region_in_frame.width() / frame_rect.size.width; |
|
miu
2016/12/06 22:06:23
Please add divide-by-zero checks here, since it's
|
| + float y_scale = region_in_frame.height() / frame_rect.size.height; |
| + |
|
miu
2016/12/06 22:06:23
Instead of multiplying by these scaling factors ev
|
| // Mouse co-ordinates directly comparable against frame co-ordinates |
| // after translation. |
| if (mouse_tab_location.x < 0 || mouse_tab_location.y < 0 || |
| - mouse_tab_location.x > region_in_frame.width() || |
| - mouse_tab_location.y > region_in_frame.height()) { |
| + mouse_tab_location.x * x_scale > region_in_frame.width() || |
| + mouse_tab_location.y * y_scale > region_in_frame.height()) { |
| VLOG(2) << "Mouse outside content region"; |
| return false; |
| } |
| @@ -91,8 +119,8 @@ bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) { |
| // Mouse cursor position within the frame. |
| cursor_position_in_frame_ = |
| - gfx::Point(region_in_frame.x() + mouse_tab_location.x, |
| - region_in_frame.y() + mouse_tab_location.y); |
| + gfx::Point(region_in_frame.x() + mouse_tab_location.x * x_scale, |
| + region_in_frame.y() + mouse_tab_location.y * y_scale); |
| // Grab system cursor. |
| NSCursor* nscursor = [NSCursor currentSystemCursor]; |
| @@ -100,16 +128,23 @@ bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) { |
| NSImage* nsimage = [nscursor image]; |
| NSSize nssize = [nsimage size]; |
| + gfx::Point scaled_hotspot = |
| + gfx::Point(nshotspot.x * x_scale, nshotspot.y * y_scale); |
| + last_cursor_width_ = nssize.width * x_scale; |
|
miu
2016/12/06 22:06:23
To simplify the code after this point, let's make
braveyao
2016/12/07 00:56:03
I don't think we should divide the |nssize| by |de
miu
2016/12/07 20:53:43
Sounds good. I didn't realize nssize was in view c
|
| + last_cursor_height_ = nssize.height * y_scale; |
| + |
| // The cursor co-ordinates in the window and the video frame co-ordinates are |
| // inverted along y-axis. We render the cursor inverse vertically on the |
| // frame. Hence the inversion on hotspot offset here. |
| - cursor_position_in_frame_.Offset(-nshotspot.x, |
| - -(nssize.height - nshotspot.y)); |
| - last_cursor_width_ = nssize.width; |
| - last_cursor_height_ = nssize.height; |
| + cursor_position_in_frame_.Offset(-scaled_hotspot.x(), |
| + -(last_cursor_height_ - scaled_hotspot.y())); |
| + // Since OSX Sierra (10.12), the CGImageRef of the cursor image is |
| + // double-size with Retina display. So we give a half-size hint to get the |
| + // CGImageRef with orignal cursor image size on both Retina and non-Retina. |
| + NSRect image_rect = NSMakeRect(0, 0, nssize.width / 2, nssize.height / 2); |
|
miu
2016/12/06 22:06:23
Instead of doing this here, just allow the higher-
|
| CGImageRef cg_image = |
| - [nsimage CGImageForProposedRect:NULL context:nil hints:nil]; |
| + [nsimage CGImageForProposedRect:&image_rect context:nil hints:nil]; |
| if (!cg_image) |
| return false; |
| @@ -120,6 +155,13 @@ bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) { |
| return false; |
| } |
| + if (x_scale != 1.0f || y_scale != 1.0f) { |
|
miu
2016/12/06 22:06:23
Now, the only reason to resize is if the cursor im
|
| + // Resize the cursor image to fit in the scaled target frame. |
| + cg_image = ResizeCGImage(cg_image, last_cursor_width_, last_cursor_height_); |
|
miu
2016/12/06 22:06:23
This is not super-expensive, but not cheap either.
braveyao
2016/12/07 00:56:03
What does 'caching' mean?
I suppose what I should
miu
2016/12/07 20:53:43
I mean 'memoize': Only resize the image whenever t
|
| + if (!cg_image) |
| + return false; |
| + } |
| + |
| CGDataProviderRef provider = CGImageGetDataProvider(cg_image); |
| CFDataRef image_data_ref = CGDataProviderCopyData(provider); |
| if (!image_data_ref) |