/** * 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); }
/** * eel_gtk_widget_get_bounds: * @gtk_widget: The source GtkWidget. * * Return value: An EelIRect representation of the given GtkWidget's geometry * relative to its parent. In the Gtk universe this is known as "allocation." * */ EelIRect eel_gtk_widget_get_bounds (GtkWidget *gtk_widget) { g_return_val_if_fail (GTK_IS_WIDGET (gtk_widget), eel_irect_empty); return eel_irect_assign (gtk_widget->allocation.x, gtk_widget->allocation.y, (int) gtk_widget->allocation.width, (int) gtk_widget->allocation.height); }
/** * 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"); }