/* Pig * Copyright (C) 2011 Benjamin Otte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __PIG_PIXBUF_SHARED_PRIVATE_H__ #define __PIG_PIXBUF_SHARED_PRIVATE_H__ #include #include /* This header contains code as inline functions that is used by both * libpig-pixbuf and libpig (in particular: The pixbuf loader). */ G_BEGIN_DECLS static inline guint8 _pig_multiply_alpha (guint8 color, guint8 alpha) { guint temp = (alpha * color) + 0x80; return (temp + (temp >> 8)) >> 8; } static inline void _pig_pixbuf_copy_to_surface (cairo_surface_t *surface, const GdkPixbuf *pixbuf, int x, int y, int width, int height) { guchar *gdk_pixels, *cairo_pixels; int gdk_stride, n_channels, cairo_stride; int i, j; /* spell out the invariants that must hold for this code to work */ g_assert (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32 || cairo_image_surface_get_format (surface) == CAIRO_FORMAT_RGB24); g_assert (cairo_image_surface_get_width (surface) == gdk_pixbuf_get_width (pixbuf)); g_assert (cairo_image_surface_get_height (surface) == gdk_pixbuf_get_height (pixbuf)); g_assert (x >= 0 && y >= 0); g_assert (x + width <= cairo_image_surface_get_width (surface)); g_assert (y + height <= cairo_image_surface_get_height (surface)); gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); gdk_stride = gdk_pixbuf_get_rowstride (pixbuf); n_channels = gdk_pixbuf_get_n_channels (pixbuf); gdk_pixels += x * n_channels + y * gdk_stride; cairo_pixels = cairo_image_surface_get_data (surface); cairo_stride = cairo_image_surface_get_stride (surface); cairo_pixels += x * 4 + y * cairo_stride; for (j = 0; j < height; j++) { guchar *p = gdk_pixels; guint32 *q = (guint32 *) cairo_pixels; if (n_channels == 3) { for (i = 0; i < width; i++) { q[i] = (0xFF << 24) | (p[0] << 16) | (p[1] << 8 ) | p[2]; p += 3; } } else { for (i = 0; i < width; i++) { q[i] = (p[3] << 24) | (_pig_multiply_alpha (p[0], p[3]) << 16) | (_pig_multiply_alpha (p[1], p[3]) << 8) | _pig_multiply_alpha (p[2], p[3]); p += 4; } } gdk_pixels += gdk_stride; cairo_pixels += cairo_stride; } } G_END_DECLS #endif /* __PIG_PIXBUF_SHARED_PRIVATE_H__ */