1 /* This file contains gdk_pixbuf_get_from_surface() and its
2 * dependencies, copy & pasted from gdk/deprecated/gdkpixbuf.c.
3 * Having it inline means that we don't have to link against a
4 * specific version of GTK, risking that (say) a gtk4-linked
5 * pixbuf loader gets used on a gtk3 desktop environment.
7 * Note: the gdk_pixbuf_get_from_surface() function has been
11 gdk_cairo_format_for_content (cairo_content_t content
)
15 case CAIRO_CONTENT_COLOR
:
16 return CAIRO_FORMAT_RGB24
;
17 case CAIRO_CONTENT_ALPHA
:
18 return CAIRO_FORMAT_A8
;
19 case CAIRO_CONTENT_COLOR_ALPHA
:
21 return CAIRO_FORMAT_ARGB32
;
26 static cairo_surface_t
*
27 gdk_cairo_surface_coerce_to_image (cairo_surface_t
*surface
,
28 cairo_content_t content
,
34 cairo_surface_t
*copy
;
37 copy
= cairo_image_surface_create (gdk_cairo_format_for_content (content
),
41 cr
= cairo_create (copy
);
42 cairo_set_operator (cr
, CAIRO_OPERATOR_SOURCE
);
43 cairo_set_source_surface (cr
, surface
, -src_x
, -src_y
);
52 convert_alpha (guchar
*dest_data
,
63 src_data
+= src_stride
* src_y
+ src_x
* 4;
65 for (y
= 0; y
< height
; y
++) {
66 guint32
*src
= (guint32
*) src_data
;
68 for (x
= 0; x
< width
; x
++) {
69 guint alpha
= src
[x
] >> 24;
73 dest_data
[x
* 4 + 0] = 0;
74 dest_data
[x
* 4 + 1] = 0;
75 dest_data
[x
* 4 + 2] = 0;
79 dest_data
[x
* 4 + 0] = (((src
[x
] & 0xff0000) >> 16) * 255 + alpha
/ 2) / alpha
;
80 dest_data
[x
* 4 + 1] = (((src
[x
] & 0x00ff00) >> 8) * 255 + alpha
/ 2) / alpha
;
81 dest_data
[x
* 4 + 2] = (((src
[x
] & 0x0000ff) >> 0) * 255 + alpha
/ 2) / alpha
;
83 dest_data
[x
* 4 + 3] = alpha
;
86 src_data
+= src_stride
;
87 dest_data
+= dest_stride
;
92 convert_no_alpha (guchar
*dest_data
,
103 src_data
+= src_stride
* src_y
+ src_x
* 4;
105 for (y
= 0; y
< height
; y
++) {
106 guint32
*src
= (guint32
*) src_data
;
108 for (x
= 0; x
< width
; x
++) {
109 dest_data
[x
* 3 + 0] = src
[x
] >> 16;
110 dest_data
[x
* 3 + 1] = src
[x
] >> 8;
111 dest_data
[x
* 3 + 2] = src
[x
];
114 src_data
+= src_stride
;
115 dest_data
+= dest_stride
;
120 * gdk_pixbuf_get_from_surface:
121 * @surface: surface to copy from
122 * @src_x: Source X coordinate within @surface
123 * @src_y: Source Y coordinate within @surface
124 * @width: Width in pixels of region to get
125 * @height: Height in pixels of region to get
127 * Transfers image data from a `cairo_surface_t` and converts it
130 * This allows you to efficiently read individual pixels from cairo surfaces.
132 * This function will create an RGB pixbuf with 8 bits per channel.
133 * The pixbuf will contain an alpha channel if the @surface contains one.
135 * Returns: (nullable) (transfer full): A newly-created pixbuf with a
136 * reference count of 1
138 * Deprecated: 4.12: Use [class@Gdk.Texture] and subclasses instead
139 * cairo surfaces and pixbufs
142 gdk_pixbuf_get_from_surface (cairo_surface_t
*surface
,
148 cairo_content_t content
;
151 /* General sanity checks */
152 g_return_val_if_fail (surface
!= NULL
, NULL
);
153 g_return_val_if_fail (width
> 0 && height
> 0, NULL
);
155 content
= cairo_surface_get_content (surface
) | CAIRO_CONTENT_COLOR
;
156 dest
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
157 !!(content
& CAIRO_CONTENT_ALPHA
),
161 if (cairo_surface_get_type (surface
) == CAIRO_SURFACE_TYPE_IMAGE
&&
162 cairo_image_surface_get_format (surface
) == gdk_cairo_format_for_content (content
))
163 surface
= cairo_surface_reference (surface
);
166 surface
= gdk_cairo_surface_coerce_to_image (surface
, content
,
172 cairo_surface_flush (surface
);
173 if (cairo_surface_status (surface
) || dest
== NULL
)
175 cairo_surface_destroy (surface
);
176 g_clear_object (&dest
);
180 if (gdk_pixbuf_get_has_alpha (dest
))
181 convert_alpha (gdk_pixbuf_get_pixels (dest
),
182 gdk_pixbuf_get_rowstride (dest
),
183 cairo_image_surface_get_data (surface
),
184 cairo_image_surface_get_stride (surface
),
188 convert_no_alpha (gdk_pixbuf_get_pixels (dest
),
189 gdk_pixbuf_get_rowstride (dest
),
190 cairo_image_surface_get_data (surface
),
191 cairo_image_surface_get_stride (surface
),
195 cairo_surface_destroy (surface
);