summaryrefslogtreecommitdiff
path: root/gtk/gtkquartz.c
diff options
context:
space:
mode:
authorChristoph Reiter <reiter.christoph@gmail.com>2015-07-24 15:09:48 +0200
committerChristoph Reiter <creiter@src.gnome.org>2015-07-27 17:28:14 +0200
commit4b23ba53c51a087851788c67f852281b085c9c33 (patch)
tree4ce856a9c8ad3a59d733cb285cb347cc5f37952d /gtk/gtkquartz.c
parent5003b5873a5e727a2b194bb5c4d8d784cc25b1e4 (diff)
downloadgtk+-4b23ba53c51a087851788c67f852281b085c9c33.tar.gz
quartz dnd: add hidpi support for gtk_drag_set_icon_surface()
Instead of storing the dnd icon as a pixbuf store it as a cairo surface and transfer the device scale when converting it to a NSImage. In the pixbuf/stock/named setters convert to a surface instead (no hidpi support yet)
Diffstat (limited to 'gtk/gtkquartz.c')
-rw-r--r--gtk/gtkquartz.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/gtk/gtkquartz.c b/gtk/gtkquartz.c
index acd1f182fe..253e8a9a59 100644
--- a/gtk/gtkquartz.c
+++ b/gtk/gtkquartz.c
@@ -22,6 +22,106 @@
#include "gtkselectionprivate.h"
#include <gdk/quartz/gdkquartz.h>
+
+static gboolean
+_cairo_surface_extents (cairo_surface_t *surface,
+ GdkRectangle *extents)
+{
+ double x1, x2, y1, y2;
+ cairo_t *cr;
+
+ g_return_val_if_fail (surface != NULL, FALSE);
+ g_return_val_if_fail (extents != NULL, FALSE);
+
+ cr = cairo_create (surface);
+ cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
+
+ x1 = floor (x1);
+ y1 = floor (y1);
+ x2 = ceil (x2);
+ y2 = ceil (y2);
+ x2 -= x1;
+ y2 -= y1;
+
+ if (x1 < G_MININT || x1 > G_MAXINT ||
+ y1 < G_MININT || y1 > G_MAXINT ||
+ x2 > G_MAXINT || y2 > G_MAXINT)
+ {
+ extents->x = extents->y = extents->width = extents->height = 0;
+ return FALSE;
+ }
+
+ extents->x = x1;
+ extents->y = y1;
+ extents->width = x2;
+ extents->height = y2;
+
+ return TRUE;
+}
+
+static void
+_data_provider_release_cairo_surface (void* info, const void* data, size_t size)
+{
+ cairo_surface_destroy ((cairo_surface_t *)info);
+}
+
+/* Returns a new NSImage or %NULL in case of an error.
+ * The device scale factor will be transfered to the NSImage (hidpi)
+ */
+NSImage *
+_gtk_quartz_create_image_from_surface (cairo_surface_t *surface)
+{
+ CGColorSpaceRef colorspace;
+ CGDataProviderRef data_provider;
+ CGImageRef image;
+ void *data;
+ NSImage *nsimage;
+ double sx, sy;
+ cairo_t *cr;
+ cairo_surface_t *img_surface;
+ cairo_rectangle_int_t extents;
+ int width, height, rowstride;
+
+ if (!_cairo_surface_extents (surface, &extents))
+ return NULL;
+
+ cairo_surface_get_device_scale (surface, &sx, &sy);
+ width = extents.width * sx;
+ height = extents.height * sy;
+
+ img_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ cr = cairo_create (img_surface);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+ cairo_scale (cr, sx, sy);
+ cairo_set_source_surface (cr, surface, -extents.x, -extents.y);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cairo_surface_flush (img_surface);
+ rowstride = cairo_image_surface_get_stride (img_surface);
+ data = cairo_image_surface_get_data (img_surface);
+
+ colorspace = CGColorSpaceCreateDeviceRGB ();
+ /* Note: the release callback will only be called after NSImage below dies */
+ data_provider = CGDataProviderCreateWithData (surface, data, height * rowstride,
+ _data_provider_release_cairo_surface);
+
+ image = CGImageCreate (width, height, 8,
+ 32, rowstride,
+ colorspace,
+ /* XXX: kCGBitmapByteOrderDefault gives wrong colors..?? */
+ kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst,
+ data_provider, NULL, FALSE,
+ kCGRenderingIntentDefault);
+ CGDataProviderRelease (data_provider);
+ CGColorSpaceRelease (colorspace);
+
+ nsimage = [[NSImage alloc] initWithCGImage:image size:NSMakeSize (extents.width, extents.height)];
+ CGImageRelease (image);
+
+ return nsimage;
+}
+
NSImage *
_gtk_quartz_create_image_from_pixbuf (GdkPixbuf *pixbuf)
{