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.
8 gdk_cairo_format_for_content (cairo_content_t content
)
12 case CAIRO_CONTENT_COLOR
:
13 return CAIRO_FORMAT_RGB24
;
14 case CAIRO_CONTENT_ALPHA
:
15 return CAIRO_FORMAT_A8
;
16 case CAIRO_CONTENT_COLOR_ALPHA
:
18 return CAIRO_FORMAT_ARGB32
;
23 static cairo_surface_t
*
24 gdk_cairo_surface_coerce_to_image (cairo_surface_t
*surface
,
25 cairo_content_t content
,
31 cairo_surface_t
*copy
;
34 copy
= cairo_image_surface_create (gdk_cairo_format_for_content (content
),
38 cr
= cairo_create (copy
);
39 cairo_set_operator (cr
, CAIRO_OPERATOR_SOURCE
);
40 cairo_set_source_surface (cr
, surface
, -src_x
, -src_y
);
49 convert_alpha (guchar
*dest_data
,
60 src_data
+= src_stride
* src_y
+ src_x
* 4;
62 for (y
= 0; y
< height
; y
++) {
63 guint32
*src
= (guint32
*) src_data
;
65 for (x
= 0; x
< width
; x
++) {
66 guint alpha
= src
[x
] >> 24;
70 dest_data
[x
* 4 + 0] = 0;
71 dest_data
[x
* 4 + 1] = 0;
72 dest_data
[x
* 4 + 2] = 0;
76 dest_data
[x
* 4 + 0] = (((src
[x
] & 0xff0000) >> 16) * 255 + alpha
/ 2) / alpha
;
77 dest_data
[x
* 4 + 1] = (((src
[x
] & 0x00ff00) >> 8) * 255 + alpha
/ 2) / alpha
;
78 dest_data
[x
* 4 + 2] = (((src
[x
] & 0x0000ff) >> 0) * 255 + alpha
/ 2) / alpha
;
80 dest_data
[x
* 4 + 3] = alpha
;
83 src_data
+= src_stride
;
84 dest_data
+= dest_stride
;
89 convert_no_alpha (guchar
*dest_data
,
100 src_data
+= src_stride
* src_y
+ src_x
* 4;
102 for (y
= 0; y
< height
; y
++) {
103 guint32
*src
= (guint32
*) src_data
;
105 for (x
= 0; x
< width
; x
++) {
106 dest_data
[x
* 3 + 0] = src
[x
] >> 16;
107 dest_data
[x
* 3 + 1] = src
[x
] >> 8;
108 dest_data
[x
* 3 + 2] = src
[x
];
111 src_data
+= src_stride
;
112 dest_data
+= dest_stride
;
117 * gdk_pixbuf_get_from_surface:
118 * @surface: surface to copy from
119 * @src_x: Source X coordinate within @surface
120 * @src_y: Source Y coordinate within @surface
121 * @width: Width in pixels of region to get
122 * @height: Height in pixels of region to get
124 * Transfers image data from a `cairo_surface_t` and converts it
127 * This allows you to efficiently read individual pixels from cairo surfaces.
129 * This function will create an RGB pixbuf with 8 bits per channel.
130 * The pixbuf will contain an alpha channel if the @surface contains one.
132 * Returns: (nullable) (transfer full): A newly-created pixbuf with a
133 * reference count of 1
135 * Deprecated: 4.12: Use [class@Gdk.Texture] and subclasses instead
136 * cairo surfaces and pixbufs
139 gdk_pixbuf_get_from_surface (cairo_surface_t
*surface
,
145 cairo_content_t content
;
148 /* General sanity checks */
149 g_return_val_if_fail (surface
!= NULL
, NULL
);
150 g_return_val_if_fail (width
> 0 && height
> 0, NULL
);
152 content
= cairo_surface_get_content (surface
) | CAIRO_CONTENT_COLOR
;
153 dest
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
154 !!(content
& CAIRO_CONTENT_ALPHA
),
158 if (cairo_surface_get_type (surface
) == CAIRO_SURFACE_TYPE_IMAGE
&&
159 cairo_image_surface_get_format (surface
) == gdk_cairo_format_for_content (content
))
160 surface
= cairo_surface_reference (surface
);
163 surface
= gdk_cairo_surface_coerce_to_image (surface
, content
,
169 cairo_surface_flush (surface
);
170 if (cairo_surface_status (surface
) || dest
== NULL
)
172 cairo_surface_destroy (surface
);
173 g_clear_object (&dest
);
177 if (gdk_pixbuf_get_has_alpha (dest
))
178 convert_alpha (gdk_pixbuf_get_pixels (dest
),
179 gdk_pixbuf_get_rowstride (dest
),
180 cairo_image_surface_get_data (surface
),
181 cairo_image_surface_get_stride (surface
),
185 convert_no_alpha (gdk_pixbuf_get_pixels (dest
),
186 gdk_pixbuf_get_rowstride (dest
),
187 cairo_image_surface_get_data (surface
),
188 cairo_image_surface_get_stride (surface
),
192 cairo_surface_destroy (surface
);