コード例 #1
0
/**
 * eel_gdk_pixbuf_draw_to_pixbuf:
 * @pixbuf: The source pixbuf to draw.
 * @destination_pixbuf: The destination pixbuf.
 * @source_x: The source pixbuf x coordiate to composite from.
 * @source_y: The source pixbuf y coordiate to composite from.
 * @destination_area: The destination area within the destination pixbuf.
 *                    This area will be clipped if invalid in any way.
 *
 * Copy one pixbuf onto another another..  This function has some advantages
 * over plain gdk_pixbuf_copy_area():
 *
 *   Composition paramters (source coordinate, destination area) are
 *   given in a way that is consistent with the rest of the extensions
 *   in this file.  That is, it matches the declaration of
 *   eel_gdk_pixbuf_draw_to_pixbuf_alpha() and
 *   eel_gdk_pixbuf_draw_to_drawable() very closely.
 *
 *   All values are clipped to make sure they are valid.
 *
 */
void
eel_gdk_pixbuf_draw_to_pixbuf (const GdkPixbuf *pixbuf,
                               GdkPixbuf *destination_pixbuf,
                               int source_x,
                               int source_y,
                               EelIRect destination_area)
{
    EelDimensions dimensions;
    EelIRect target;
    EelIRect source;
    int target_width;
    int target_height;
    int source_width;
    int source_height;

    g_return_if_fail (eel_gdk_pixbuf_is_valid (pixbuf));
    g_return_if_fail (eel_gdk_pixbuf_is_valid (destination_pixbuf));
    g_return_if_fail (!eel_irect_is_empty (&destination_area));

    dimensions = eel_gdk_pixbuf_get_dimensions (pixbuf);

    g_return_if_fail (source_x >= 0);
    g_return_if_fail (source_y >= 0);
    g_return_if_fail (source_x < dimensions.width);
    g_return_if_fail (source_y < dimensions.height);

    /* Clip the destination area to the pixbuf dimensions; bail if no work */
    target = eel_gdk_pixbuf_intersect (destination_pixbuf, 0, 0, destination_area);
    if (eel_irect_is_empty (&target))
    {
        return;
    }

    /* Assign the source area */
    source = eel_irect_assign (source_x,
                               source_y,
                               dimensions.width - source_x,
                               dimensions.height - source_y);

    /* Adjust the target width if the source area is smaller than the
     * source pixbuf dimensions */
    target_width = target.x1 - target.x0;
    target_height = target.y1 - target.y0;
    source_width = source.x1 - source.x0;
    source_height = source.y1 - source.y0;

    target.x1 = target.x0 + MIN (target_width, source_width);
    target.y1 = target.y0 + MIN (target_height, source_height);

    gdk_pixbuf_copy_area (pixbuf,
                          source.x0,
                          source.y0,
                          target.x1 - target.x0,
                          target.y1 - target.y0,
                          destination_pixbuf,
                          target.x0,
                          target.y0);
}
コード例 #2
0
/**
 * eel_gdk_pixbuf_intersect:
 * @pixbuf: A GdkPixbuf.
 * @pixbuf_x: X coordinate of pixbuf.
 * @pixbuf_y: Y coordinate of pixbuf.
 * @rectangle: An EelIRect.
 *
 * Return value: The intersection of the pixbuf and the given rectangle.
 *
 */
EelIRect
eel_gdk_pixbuf_intersect (const GdkPixbuf *pixbuf,
                          int pixbuf_x,
                          int pixbuf_y,
                          EelIRect rectangle)
{
    EelIRect intersection;
    EelIRect bounds;
    EelDimensions dimensions;

    g_return_val_if_fail (eel_gdk_pixbuf_is_valid (pixbuf), eel_irect_empty);

    dimensions = eel_gdk_pixbuf_get_dimensions (pixbuf);
    bounds = eel_irect_assign_dimensions (pixbuf_x, pixbuf_y, dimensions);

    eel_irect_intersect (&intersection, &rectangle, &bounds);

    /* In theory, this is not needed because a rectangle is empty
     * regardless of how MUCH negative the dimensions are.
     * However, to make debugging and self checks simpler, we
     * consistenly return a standard empty rectangle.
     */
    if (eel_irect_is_empty (&intersection))
    {
        return eel_irect_empty;
    }

    return intersection;
}
コード例 #3
0
/**
 * eel_gdk_pixbuf_fill_rectangle_with_color:
 * @pixbuf: Target pixbuf to fill into.
 * @area: Rectangle to fill.
 * @color: The color to use.
 *
 * Fill the rectangle with the the given color.
 */
void
eel_gdk_pixbuf_fill_rectangle_with_color (GdkPixbuf *pixbuf,
        EelIRect area,
        guint32 color)
{
    EelIRect target;
    guchar red;
    guchar green;
    guchar blue;
    guchar alpha;
    guchar *pixels;
    gboolean has_alpha;
    guint pixel_offset;
    guint rowstride;
    guchar *row_offset;
    int x;
    int y;

    g_return_if_fail (eel_gdk_pixbuf_is_valid (pixbuf));

    target = eel_gdk_pixbuf_intersect (pixbuf, 0, 0, area);
    if (eel_irect_is_empty (&target))
    {
        return;
    }

    pixels = gdk_pixbuf_get_pixels (pixbuf);
    rowstride = gdk_pixbuf_get_rowstride (pixbuf);
    has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
    pixel_offset = has_alpha ? 4 : 3;
    red = EEL_RGBA_COLOR_GET_R (color);
    green = EEL_RGBA_COLOR_GET_G (color);
    blue = EEL_RGBA_COLOR_GET_B (color);
    alpha = EEL_RGBA_COLOR_GET_A (color);

    row_offset = pixels + target.y0 * rowstride;

    for (y = target.y0; y < target.y1; y++)
    {
        guchar *offset = row_offset + (target.x0 * pixel_offset);

        for (x = target.x0; x < target.x1; x++)
        {
            *(offset++) = red;
            *(offset++) = green;
            *(offset++) = blue;

            if (has_alpha)
            {
                *(offset++) = alpha;
            }

        }

        row_offset += rowstride;
    }
}
コード例 #4
0
/**
 * eel_gdk_pixbuf_get_dimensions:
 * @pixbuf: A GdkPixbuf
 *
 * Return value: The dimensions of the pixbuf as a EelDimensions.
 *
 * This function is useful in code that uses libart rect
 * intersection routines.
 */
EelDimensions
eel_gdk_pixbuf_get_dimensions (const GdkPixbuf *pixbuf)
{
    EelDimensions dimensions;

    g_return_val_if_fail (eel_gdk_pixbuf_is_valid (pixbuf), eel_dimensions_empty);

    dimensions.width = gdk_pixbuf_get_width (pixbuf);
    dimensions.height = gdk_pixbuf_get_height (pixbuf);

    return dimensions;
}
コード例 #5
0
/**
 * eel_gdk_pixbuf_new_from_pixbuf_sub_area:
 * @pixbuf: The source pixbuf.
 * @area: The area within the source pixbuf to use for the sub pixbuf.
 *        This area needs to be contained within the bounds of the
 *        source pixbuf, otherwise it will be clipped to that.
 *
 * Return value: A newly allocated pixbuf that shares the pixel data
 *               of the source pixbuf in order to represent a sub area.
 *
 * Create a pixbuf from a sub area of another pixbuf.  The resulting pixbuf
 * will share the pixel data of the source pixbuf.  Memory bookeeping is
 * all taken care for the caller.  All you need to do is g_object_unref()
 * the resulting pixbuf to properly free resources.
 */
GdkPixbuf *
eel_gdk_pixbuf_new_from_pixbuf_sub_area (GdkPixbuf *pixbuf,
        EelIRect area)
{
    GdkPixbuf *sub_pixbuf;
    EelIRect target;
    guchar *pixels;

    g_return_val_if_fail (eel_gdk_pixbuf_is_valid (pixbuf), NULL);
    g_return_val_if_fail (!eel_irect_is_empty (&area), NULL);

    /* Clip the pixbuf by the given area; bail if no work */
    target = eel_gdk_pixbuf_intersect (pixbuf, 0, 0, area);
    if (eel_irect_is_empty (&target))
    {
        return NULL;
    }

    /* Since we are going to be sharing the given pixbuf's data, we need
     * to ref it.  It will be unreffed in the destroy function above */
    g_object_ref (pixbuf);

    /* Compute the offset into the pixel data */
    pixels =
        gdk_pixbuf_get_pixels (pixbuf)
        + (target.y0 * gdk_pixbuf_get_rowstride (pixbuf))
        + (target.x0 * (gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3));

    /* Make a pixbuf pretending its real estate is the sub area */
    sub_pixbuf = gdk_pixbuf_new_from_data (pixels,
                                           GDK_COLORSPACE_RGB,
                                           gdk_pixbuf_get_has_alpha (pixbuf),
                                           8,
                                           eel_irect_get_width (target),
                                           eel_irect_get_height (target),
                                           gdk_pixbuf_get_rowstride (pixbuf),
                                           pixbuf_destroy_callback,
                                           pixbuf);

    return sub_pixbuf;
}
コード例 #6
0
/**
 * eel_gdk_pixbuf_draw_to_pixbuf_alpha:
 * @pixbuf: The source pixbuf to draw.
 * @destination_pixbuf: The destination pixbuf.
 * @source_x: The source pixbuf x coordiate to composite from.
 * @source_y: The source pixbuf y coordiate to composite from.
 * @destination_area: The destination area within the destination pixbuf.
 *                    This area will be clipped if invalid in any way.
 * @opacity: The opacity of the drawn tiles where 0 <= opacity <= 255.
 * @interpolation_mode: The interpolation mode.  See <gdk-pixbuf.h>
 *
 * Composite one pixbuf over another.  This function has some advantages
 * over plain gdk_pixbuf_composite():
 *
 *   Composition paramters (source coordinate, destination area) are
 *   given in a way that is consistent with the rest of the extensions
 *   in this file.  That is, it matches the declaration of
 *   eel_gdk_pixbuf_draw_to_pixbuf() and
 *   eel_gdk_pixbuf_draw_to_drawable() very closely.
 *
 *   All values are clipped to make sure they are valid.
 *
 *   Workaround a limitation in gdk_pixbuf_composite() that does not allow
 *   the source (x,y) to be greater than (0,0)
 *
 */
void
eel_gdk_pixbuf_draw_to_pixbuf_alpha (const GdkPixbuf *pixbuf,
                                     GdkPixbuf *destination_pixbuf,
                                     int source_x,
                                     int source_y,
                                     EelIRect destination_area,
                                     int opacity,
                                     GdkInterpType interpolation_mode)
{
    EelDimensions dimensions;
    EelIRect target;
    EelIRect source;
    int target_width;
    int target_height;
    int source_width;
    int source_height;

    g_return_if_fail (eel_gdk_pixbuf_is_valid (pixbuf));
    g_return_if_fail (eel_gdk_pixbuf_is_valid (destination_pixbuf));
    g_return_if_fail (!eel_irect_is_empty (&destination_area));
    g_return_if_fail (opacity >= EEL_OPACITY_FULLY_TRANSPARENT);
    g_return_if_fail (opacity <= EEL_OPACITY_FULLY_OPAQUE);
    g_return_if_fail (interpolation_mode >= GDK_INTERP_NEAREST);
    g_return_if_fail (interpolation_mode <= GDK_INTERP_HYPER);

    dimensions = eel_gdk_pixbuf_get_dimensions (pixbuf);

    g_return_if_fail (source_x >= 0);
    g_return_if_fail (source_y >= 0);
    g_return_if_fail (source_x < dimensions.width);
    g_return_if_fail (source_y < dimensions.height);

    /* Clip the destination area to the pixbuf dimensions; bail if no work */
    target = eel_gdk_pixbuf_intersect (destination_pixbuf, 0, 0, destination_area);
    if (eel_irect_is_empty (&target))
    {
        return;
    }

    /* Assign the source area */
    source = eel_irect_assign (source_x,
                               source_y,
                               dimensions.width - source_x,
                               dimensions.height - source_y);

    /* Adjust the target width if the source area is smaller than the
     * source pixbuf dimensions */
    target_width = target.x1 - target.x0;
    target_height = target.y1 - target.y0;
    source_width = source.x1 - source.x0;
    source_height = source.y1 - source.y0;

    target.x1 = target.x0 + MIN (target_width, source_width);
    target.y1 = target.y0 + MIN (target_height, source_height);

    /* If the source point is not (0,0), then we need to create a sub pixbuf
     * with only the source area.  This is needed to work around a limitation
     * in gdk_pixbuf_composite() that requires the source area to be (0,0). */
    if (source.x0 != 0 || source.y0 != 0)
    {
        EelIRect area;
        int width;
        int height;

        width = dimensions.width - source.x0;
        height = dimensions.height - source.y0;

        area.x0 = source.x0;
        area.y0 = source.y0;
        area.x1 = area.x0 + width;
        area.y1 = area.y0 + height;

        pixbuf = eel_gdk_pixbuf_new_from_pixbuf_sub_area ((GdkPixbuf *) pixbuf, area);
    }
    else
    {
        g_object_ref (G_OBJECT (pixbuf));
    }

    gdk_pixbuf_composite (pixbuf,
                          destination_pixbuf,
                          target.x0,
                          target.y0,
                          target.x1 - target.x0,
                          target.y1 - target.y0,
                          target.x0,
                          target.y0,
                          1.0,
                          1.0,
                          interpolation_mode,
                          opacity);

    g_object_unref (G_OBJECT (pixbuf));
}
コード例 #7
0
void
eel_gdk_pixbuf_draw_to_drawable (const GdkPixbuf *pixbuf,
				 GdkDrawable *drawable,
				 GdkGC *gc,
				 int source_x,
				 int source_y,
				 EelIRect destination_area,
				 GdkRgbDither dither,
				 GdkPixbufAlphaMode alpha_compositing_mode,
				 int alpha_threshold)
{
	EelDimensions dimensions;
	EelIRect target;
	EelIRect source;
	int target_width;
	int target_height;
	int source_width;
	int source_height;

	g_return_if_fail (eel_gdk_pixbuf_is_valid (pixbuf));
	g_return_if_fail (drawable != NULL);
	g_return_if_fail (gc != NULL);
	g_return_if_fail (!eel_irect_is_empty (&destination_area));
 	g_return_if_fail (alpha_threshold > EEL_OPACITY_FULLY_TRANSPARENT);
 	g_return_if_fail (alpha_threshold <= EEL_OPACITY_FULLY_OPAQUE);
 	g_return_if_fail (alpha_compositing_mode >= GDK_PIXBUF_ALPHA_BILEVEL);
 	g_return_if_fail (alpha_compositing_mode <= GDK_PIXBUF_ALPHA_FULL);

	dimensions = eel_gdk_pixbuf_get_dimensions (pixbuf);
	
	g_return_if_fail (source_x >= 0);
	g_return_if_fail (source_y >= 0);
	g_return_if_fail (source_x < dimensions.width);
	g_return_if_fail (source_y < dimensions.height);

	/* Clip the destination area to the pixbuf dimensions; bail if no work */
	target = eel_gdk_pixbuf_intersect (pixbuf,
					   destination_area.x0,
					   destination_area.y0,
					   destination_area);
	if (eel_irect_is_empty (&target)) {
		return;
	}

	/* Assign the source area */
	source = eel_irect_assign (source_x,
				       source_y,
				       dimensions.width - source_x,
				       dimensions.height - source_y);

	/* Adjust the target width if the source area is smaller than the
	 * source pixbuf dimensions */
	target_width = target.x1 - target.x0;
	target_height = target.y1 - target.y0;
	source_width = source.x1 - source.x0;
	source_height = source.y1 - source.y0;

	target.x1 = target.x0 + MIN (target_width, source_width);
	target.y1 = target.y0 + MIN (target_height, source_height);

	gdk_draw_pixbuf (drawable, gc, (GdkPixbuf *) pixbuf,
			 source.x0,
			 source.y0,
			 target.x0,
			 target.y0,
			 target.x1 - target.x0,
			 target.y1 - target.y0,
			 dither,
			 0,
			 0);
}
コード例 #8
0
void
eel_self_check_gdk_pixbuf_extensions (void)
{
	GdkPixbuf *pixbuf;
	EelIRect clip_area;

	pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 100, 100);

	EEL_CHECK_BOOLEAN_RESULT (eel_gdk_pixbuf_is_valid (pixbuf), TRUE);
	EEL_CHECK_BOOLEAN_RESULT (eel_gdk_pixbuf_is_valid (NULL), FALSE);

	EEL_CHECK_DIMENSIONS_RESULT (eel_gdk_pixbuf_get_dimensions (pixbuf), 100, 100);

	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, eel_gdk_pixbuf_whole_pixbuf), 0, 0, 100, 100);

	clip_area = eel_irect_assign (0, 0, 0, 0);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 0, 0);

	clip_area = eel_irect_assign (0, 0, 0, 0);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 0, 0);

	clip_area = eel_irect_assign (0, 0, 100, 100);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 100, 100);

	clip_area = eel_irect_assign (-10, -10, 100, 100);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 90, 90);

	clip_area = eel_irect_assign (-10, -10, 110, 110);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 100, 100);

	clip_area = eel_irect_assign (0, 0, 99, 99);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 99, 99);

	clip_area = eel_irect_assign (0, 0, 1, 1);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 1, 1);

	clip_area = eel_irect_assign (-1, -1, 1, 1);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 0, 0);

	clip_area = eel_irect_assign (-1, -1, 2, 2);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 1, 1);

	clip_area = eel_irect_assign (100, 100, 1, 1);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 0, 0);

	clip_area = eel_irect_assign (101, 101, 1, 1);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 0, 0, 0, 0);

	clip_area = eel_irect_assign (80, 0, 100, 100);
	EEL_CHECK_RECTANGLE_RESULT (eel_gdk_pixbuf_intersect (pixbuf, 0, 0, clip_area), 80, 0, 100, 100);

	g_object_unref (pixbuf);

	/* No checks for empty pixbufs because GdkPixbuf doesn't seem to allow them. */
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "00,00,00"), "00,00,00,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "00,00,00,00"), "00,00,00,00");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "00,00,00,FF"), "00,00,00,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "01,01,01"), "01,01,01,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "FE,FE,FE"), "FE,FE,FE,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "FF,FF,FF"), "FF,FF,FF,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "FF,FF,FF,00"), "00,00,00,00");
	EEL_CHECK_STRING_RESULT (check_average_value (1, 1, "11,22,33"), "11,22,33,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "00,00,00"), "00,00,00,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "00,00,00,00"), "00,00,00,00");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "00,00,00,FF"), "00,00,00,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "01,01,01"), "01,01,01,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "FE,FE,FE"), "FE,FE,FE,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "FF,FF,FF"), "FF,FF,FF,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "FF,FF,FF,00"), "00,00,00,00");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "11,22,33"), "11,22,33,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "gray -1"), "7F,7F,7F,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "gray 0"), "80,80,80,FF");
	EEL_CHECK_STRING_RESULT (check_average_value (1000, 1000, "gray 1"), "80,80,80,FF");
}