Пример #1
0
cairo_surface_t *
_cairo_image_surface_create_from_pixbuf (GdkPixbuf *pixbuf)
{
	cairo_surface_t          *surface;
	cairo_surface_metadata_t *metadata;
	int                      width;
	int                      height;
	int                      p_stride;
	int                      p_n_channels;
	guchar                  *p_pixels;
	int                      s_stride;
	unsigned char           *s_pixels;
	int                      h, w;
	guint32                  pixel;
	guchar                   r, g, b, a;

	if (pixbuf == NULL)
		return NULL;

	g_object_get (G_OBJECT (pixbuf),
		      "width", &width,
		      "height", &height,
		      "rowstride", &p_stride,
		      "n-channels", &p_n_channels,
		      "pixels", &p_pixels,
		      NULL );
	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
	s_stride = cairo_image_surface_get_stride (surface);
	s_pixels = _cairo_image_surface_flush_and_get_data (surface);

	metadata = _cairo_image_surface_get_metadata (surface);
	metadata->has_alpha = (p_n_channels == 4);

	if (p_n_channels == 4) {
		guchar *s_iter;
		guchar *p_iter;

		for (h = 0; h < height; h++) {
			s_iter = s_pixels;
			p_iter = p_pixels;

			for (w = 0; w < width; w++) {
				a = p_iter[3];
				if (a == 0xff) {
					pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff);
				}
				else if (a == 0) {
					pixel = 0;
				}
				else {
					r = _cairo_multiply_alpha (p_iter[0], a);
					g = _cairo_multiply_alpha (p_iter[1], a);
					b = _cairo_multiply_alpha (p_iter[2], a);
					pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
				}
				memcpy (s_iter, &pixel, sizeof (guint32));

				s_iter += 4;
				p_iter += p_n_channels;
			}

			s_pixels += s_stride;
			p_pixels += p_stride;
		}
	}
	else {
		guchar *s_iter;
		guchar *p_iter;

		for (h = 0; h < height; h++) {
			s_iter = s_pixels;
			p_iter = p_pixels;

			for (w = 0; w < width; w++) {
				pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff);
				memcpy (s_iter, &pixel, sizeof (guint32));

				s_iter += 4;
				p_iter += p_n_channels;
			}

			s_pixels += s_stride;
			p_pixels += p_stride;
		}
	}

	cairo_surface_mark_dirty (surface);

	return surface;
}