gdk_pixbuf_get_from_window: honor device scale

gdk_pixbuf_get_from_window() paints the given window onto a new cairo
surface. Create that new surface with the same device scale as the
window so that the result is not scaled down on hidpi screens.

https://bugzilla.gnome.org/show_bug.cgi?id=757147
This commit is contained in:
Lars Uebernickel 2015-10-26 10:12:34 +01:00
parent 46e834cf3e
commit 657a43e54e

View File

@ -47,8 +47,8 @@
* @window: Source window * @window: Source window
* @src_x: Source X coordinate within @window * @src_x: Source X coordinate within @window
* @src_y: Source Y coordinate within @window * @src_y: Source Y coordinate within @window
* @width: Width in pixels of region to get * @width: Width in logical pixels of region to get
* @height: Height in pixels of region to get * @height: Height in logical pixels of region to get
* *
* Transfers image data from a #GdkWindow and converts it to an RGB(A) * Transfers image data from a #GdkWindow and converts it to an RGB(A)
* representation inside a #GdkPixbuf. In other words, copies * representation inside a #GdkPixbuf. In other words, copies
@ -88,10 +88,13 @@ gdk_pixbuf_get_from_window (GdkWindow *src,
{ {
cairo_surface_t *surface; cairo_surface_t *surface;
GdkPixbuf *dest; GdkPixbuf *dest;
gint scale;
g_return_val_if_fail (GDK_IS_WINDOW (src), NULL); g_return_val_if_fail (GDK_IS_WINDOW (src), NULL);
g_return_val_if_fail (gdk_window_is_viewable (src), NULL); g_return_val_if_fail (gdk_window_is_viewable (src), NULL);
scale = gdk_window_get_scale_factor (src);
surface = _gdk_window_ref_cairo_surface (src); surface = _gdk_window_ref_cairo_surface (src);
/* We do not know what happened to this surface outside of GDK. /* We do not know what happened to this surface outside of GDK.
@ -102,8 +105,8 @@ gdk_pixbuf_get_from_window (GdkWindow *src,
cairo_surface_mark_dirty (surface); cairo_surface_mark_dirty (surface);
dest = gdk_pixbuf_get_from_surface (surface, dest = gdk_pixbuf_get_from_surface (surface,
src_x, src_y, scale * src_x, scale * src_y,
width, height); scale * width, scale * height);
cairo_surface_destroy (surface); cairo_surface_destroy (surface);
return dest; return dest;
@ -116,7 +119,6 @@ gdk_cairo_format_for_content (cairo_content_t content)
{ {
case CAIRO_CONTENT_COLOR: case CAIRO_CONTENT_COLOR:
return CAIRO_FORMAT_RGB24; return CAIRO_FORMAT_RGB24;
case CAIRO_CONTENT_ALPHA:
return CAIRO_FORMAT_A8; return CAIRO_FORMAT_A8;
case CAIRO_CONTENT_COLOR_ALPHA: case CAIRO_CONTENT_COLOR_ALPHA:
default: default:
@ -134,11 +136,16 @@ gdk_cairo_surface_coerce_to_image (cairo_surface_t *surface,
{ {
cairo_surface_t *copy; cairo_surface_t *copy;
cairo_t *cr; cairo_t *cr;
double sx, sy;
cairo_surface_get_device_scale (surface, &sx, &sy);
copy = cairo_image_surface_create (gdk_cairo_format_for_content (content), copy = cairo_image_surface_create (gdk_cairo_format_for_content (content),
width, width,
height); height);
cairo_surface_set_device_scale (copy, sx, sy);
cr = cairo_create (copy); cr = cairo_create (copy);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, surface, -src_x, -src_y); cairo_set_source_surface (cr, surface, -src_x, -src_y);