Beispiel #1
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;
}
Beispiel #2
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);
}
Beispiel #3
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));
}
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);
}
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");
}