summaryrefslogtreecommitdiff
path: root/libnautilus-private/nautilus-smooth-widget.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnautilus-private/nautilus-smooth-widget.c')
-rw-r--r--libnautilus-private/nautilus-smooth-widget.c983
1 files changed, 0 insertions, 983 deletions
diff --git a/libnautilus-private/nautilus-smooth-widget.c b/libnautilus-private/nautilus-smooth-widget.c
deleted file mode 100644
index 75ba2c20b..000000000
--- a/libnautilus-private/nautilus-smooth-widget.c
+++ /dev/null
@@ -1,983 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
-
-/* nautilus-smooth-widget.c - Functions and types shared by smooth widgets.
-
- Copyright (C) 2000 Eazel, Inc.
-
- The Gnome Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The Gnome 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
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the Gnome Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Authors: Ramiro Estrugo <ramiro@eazel.com>
-*/
-
-#include <config.h>
-
-#include "nautilus-smooth-widget.h"
-#include "nautilus-gdk-extensions.h"
-#include "nautilus-art-gtk-extensions.h"
-
-#include <gtk/gtksignal.h>
-
-static NautilusArtIPoint smooth_widget_get_tile_origin_point (const GtkWidget *widget,
- NautilusSmoothTileMode tile_mode_vertical,
- NautilusSmoothTileMode tile_mode_horizontal);
-static void smooth_widget_paint_tile_opaque (GtkWidget *widget,
- GdkGC *gc,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *dirty_area);
-static void smooth_widget_paint_tile_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- int tile_opacity,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *dirty_area);
-static void smooth_widget_paint_content_opaque (GtkWidget *widget,
- GdkGC *gc,
- const ArtIRect *content_bounds,
- const ArtIRect *dirty_area,
- NautilusSmoothPaintOpaqueCallback paint_callback,
- gpointer callback_data);
-static void smooth_widget_paint_content_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const ArtIRect *content_bounds,
- int content_opacity,
- const ArtIRect *dirty_area,
- NautilusSmoothCompositeCallback composite_callback,
- gpointer callback_data);
-static void smooth_widget_paint_tile_and_content_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- int tile_opacity,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *content_bounds,
- int content_opacity,
- const ArtIRect *dirty_area,
- NautilusSmoothCompositeCallback composite_callback,
- gpointer callback_data);
-
-/* We maintain a global list of smooth widgets. The smoothness of all these
- * widgets can then be changed with nautilus_smooth_widget_global_set_is_smooth().
- *
- * We do this so that labels and images will repect the "smooth_graphics"
- * automatically without any intervention from the users of these two widgets.
- */
-static GList *smooth_widget_list = NULL;
-
-/* We maintain a global list of types that can be smooth widgets.
- * We do this mostly for type safety - to make sure smooth operations only
- * happen on smooth widgets.
- */
-static GList *smooth_widget_type_list = NULL;
-
-static void
-smooth_widget_type_list_free (void)
-{
- g_list_free (smooth_widget_type_list);
- smooth_widget_type_list = NULL;
-}
-
-static void
-smooth_widget_list_free (void)
-{
- g_list_free (smooth_widget_list);
- smooth_widget_list = NULL;
-}
-
-static gboolean
-widget_is_smooth (const GtkWidget *widget)
-{
- GList *node;
-
- for (node = smooth_widget_type_list; node ; node = node->next) {
- GtkType type;
-
- type = GPOINTER_TO_INT (node->data);
-
- if (GTK_CHECK_TYPE ((widget), type)) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static void
-smooth_widget_set_is_smooth (GtkWidget *widget, gboolean is_smooth)
-{
- g_return_if_fail (widget_is_smooth (widget));
-
- gtk_signal_emit_by_name (GTK_OBJECT (widget), "set_is_smooth", is_smooth);
-}
-
-static void
-smooth_widget_destroy (GtkWidget *widget, gpointer callback_data)
-{
- g_return_if_fail (widget_is_smooth (widget));
-
- smooth_widget_list = g_list_remove (smooth_widget_list, widget);
-}
-
-static gboolean global_is_smooth = TRUE;
-
-void
-nautilus_smooth_widget_global_set_is_smooth (gboolean is_smooth)
-{
- GList *node;
-
- global_is_smooth = is_smooth;
-
- for (node = smooth_widget_list; node != NULL; node = node->next) {
- smooth_widget_set_is_smooth (GTK_WIDGET (node->data), global_is_smooth);
- }
-}
-
-/**
- * nautilus_smooth_widget_register:
- * @widget: A smooth widget.
- *
- * Register a smooth widget. For the life time of the widget, its
- * 'is_smooth' attribute will be toggled when
- * nautilus_smooth_widget_global_set_is_smooth() is called.
- */
-void
-nautilus_smooth_widget_register (GtkWidget *widget)
-{
- g_return_if_fail (widget_is_smooth (widget));
-
- smooth_widget_set_is_smooth (widget, global_is_smooth);
-
- if (smooth_widget_list == NULL) {
- g_atexit (smooth_widget_list_free);
- }
-
- smooth_widget_list = g_list_prepend (smooth_widget_list, widget);
-
- /* Keep track of the widget's destruction so we can purge it */
- gtk_signal_connect (GTK_OBJECT (widget),
- "destroy",
- GTK_SIGNAL_FUNC (smooth_widget_destroy),
- NULL);
-}
-
-/* Return the origin point for the widget given vertical
- * and horizontal tile modes.
- */
-static NautilusArtIPoint
-smooth_widget_get_tile_origin_point (const GtkWidget *widget,
- NautilusSmoothTileMode tile_mode_vertical,
- NautilusSmoothTileMode tile_mode_horizontal)
-
-{
- NautilusArtIPoint origin_point;
-
- g_return_val_if_fail (widget_is_smooth (widget), NAUTILUS_ART_IPOINT_ZERO);
- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NAUTILUS_ART_IPOINT_ZERO);
- g_return_val_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF, NAUTILUS_ART_IPOINT_ZERO);
- g_return_val_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR, NAUTILUS_ART_IPOINT_ZERO);
- g_return_val_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF, NAUTILUS_ART_IPOINT_ZERO);
- g_return_val_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR, NAUTILUS_ART_IPOINT_ZERO);
-
- origin_point = NAUTILUS_ART_IPOINT_ZERO;
-
- /* Using '0' for the ancestor origin works because our buddy GTK+
- * already makes our allocation.{x,y} the collected offsets of all
- * our ancestors.
- *
- * It might be more correct to make this the allocation.{x,y} of the
- * ancestor windowed widget - maybe.
- */
- switch (tile_mode_vertical) {
- case NAUTILUS_SMOOTH_TILE_SELF:
- origin_point.y = widget->allocation.y;
- break;
-
- case NAUTILUS_SMOOTH_TILE_ANCESTOR:
- origin_point.y = 0;
- break;
- }
-
- switch (tile_mode_horizontal) {
- case NAUTILUS_SMOOTH_TILE_SELF:
- origin_point.x = widget->allocation.x;
- break;
-
- case NAUTILUS_SMOOTH_TILE_ANCESTOR:
- origin_point.x = 0;
- break;
- }
-
- return origin_point;
-}
-
-/* Return an area of the smooth widget's Gtk background as a pixbuf.
- * The resulting pixbuf needs to be unrefed when done using it.
- */
-static GdkPixbuf *
-smooth_widget_get_gtk_background (GtkWidget *widget,
- const ArtIRect *area)
-{
- GdkPixbuf *background;
- int width;
- int height;
-
- g_return_val_if_fail (widget_is_smooth (widget), NULL);
- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
- g_return_val_if_fail (area != NULL && !art_irect_empty (area), NULL);
-
- width = nautilus_art_irect_get_width (area);
- height = nautilus_art_irect_get_height (area);
-
- background = nautilus_gdk_pixbuf_get_from_window_safe (widget->window,
- area->x0,
- area->y0,
- width,
- height);
- if (background == NULL) {
- ArtIRect fill_area;
-
- background = nautilus_gdk_pixbuf_get_global_buffer (width, height);
- nautilus_art_irect_assign (&fill_area, 0, 0, width, height);
- nautilus_gdk_pixbuf_fill_rectangle_with_color (background,
- &fill_area,
- NAUTILUS_RGB_COLOR_WHITE);
- gdk_pixbuf_ref (background);
- } else {
- g_assert (gdk_pixbuf_get_width (background) == width);
- g_assert (gdk_pixbuf_get_height (background) == height);
- }
-
- return background;
-}
-
-/* Return an area of the smooth widget's background as a pixbuf.
- * The resulting pixbuf needs to be unrefed when done using it.
- */
-static GdkPixbuf *
-smooth_widget_get_background (GtkWidget *widget,
- const ArtIRect *area,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color)
-{
- GdkPixbuf *buffer;
-
- g_return_val_if_fail (widget_is_smooth (widget), NULL);
- g_return_val_if_fail (GTK_WIDGET_REALIZED (widget), NULL);
- g_return_val_if_fail (area != NULL && !art_irect_empty (area), NULL);
- g_return_val_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK, NULL);
- g_return_val_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR, NULL);
-
- if (background_mode == NAUTILUS_SMOOTH_BACKGROUND_GTK) {
- buffer = smooth_widget_get_gtk_background (widget, area);
- } else {
- buffer = nautilus_gdk_pixbuf_get_global_buffer (nautilus_art_irect_get_width (area),
- nautilus_art_irect_get_height (area));
-
- if (background_mode == NAUTILUS_SMOOTH_BACKGROUND_CALLBACK) {
- gtk_signal_emit_by_name (GTK_OBJECT (widget),
- "draw_background",
- buffer,
- area);
- } else {
- nautilus_gdk_pixbuf_fill_rectangle_with_color (buffer,
- NULL,
- solid_background_color);
- }
-
- gdk_pixbuf_ref (buffer);
- }
- g_return_val_if_fail (nautilus_gdk_pixbuf_is_valid (buffer), NULL);
-
- return buffer;
-}
-
-/* Paint the smooth widget's tile in opaque mode */
-static void
-smooth_widget_paint_tile_opaque (GtkWidget *widget,
- GdkGC *gc,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *dirty_area)
-{
- ArtIRect tile_dirty_area;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (widget->window != NULL);
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (tile_pixbuf));
- g_return_if_fail (tile_bounds != NULL && !art_irect_empty (tile_bounds));
- g_return_if_fail (tile_origin != NULL);
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
-
- /* Clip the tile to the dirty area */
- art_irect_intersect (&tile_dirty_area, tile_bounds, dirty_area);
-
- /* Nothing to do */
- if (art_irect_empty (&tile_dirty_area)) {
- return;
- }
-
- /* Tile the drawable. */
- nautilus_gdk_pixbuf_draw_to_drawable_tiled (tile_pixbuf,
- widget->window,
- gc,
- &tile_dirty_area,
- gdk_pixbuf_get_width (tile_pixbuf),
- gdk_pixbuf_get_height (tile_pixbuf),
- tile_origin->x,
- tile_origin->y,
- GDK_RGB_DITHER_NONE,
- GDK_PIXBUF_ALPHA_BILEVEL,
- NAUTILUS_STANDARD_ALPHA_THRESHHOLD);
-}
-
-/* Paint the smooth widget's tile in transparent alpha composited mode */
-static void
-smooth_widget_paint_tile_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- int tile_opacity,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *dirty_area)
-{
- NautilusDimensions buffer_dimensions;
- ArtIRect tile_dirty_area;
- ArtIRect tile_area;
- GdkPixbuf *buffer;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (gc != NULL);
- g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK);
- g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR);
- g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (tile_pixbuf));
- g_return_if_fail (tile_bounds != NULL && !art_irect_empty (tile_bounds));
- g_return_if_fail (tile_origin != NULL);
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
-
- art_irect_intersect (&tile_dirty_area, tile_bounds, dirty_area);
-
- /* Nothing to do */
- if (art_irect_empty (&tile_dirty_area)) {
- return;
- }
-
- buffer = smooth_widget_get_background (widget,
- &tile_dirty_area,
- background_mode,
- solid_background_color);
-
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (buffer));
-
- buffer_dimensions = nautilus_gdk_pixbuf_get_dimensions (buffer);
-
- nautilus_art_irect_assign (&tile_area, 0, 0, buffer_dimensions.width, buffer_dimensions.height);
-
- /* Composite the tile into the buffer */
- nautilus_gdk_pixbuf_draw_to_pixbuf_tiled (tile_pixbuf,
- buffer,
- &tile_area,
- gdk_pixbuf_get_width (tile_pixbuf),
- gdk_pixbuf_get_height (tile_pixbuf),
- tile_origin->x - tile_dirty_area.x0,
- tile_origin->y - tile_dirty_area.y0,
- tile_opacity,
- GDK_INTERP_NEAREST);
-
- nautilus_gdk_pixbuf_draw_to_drawable (buffer,
- widget->window,
- gc,
- 0,
- 0,
- &tile_dirty_area,
- GDK_RGB_DITHER_NONE,
- GDK_PIXBUF_ALPHA_BILEVEL,
- NAUTILUS_STANDARD_ALPHA_THRESHHOLD);
-
- gdk_pixbuf_unref (buffer);
-}
-
-/* Paint the smooth widget's content in opaque mode */
-static void
-smooth_widget_paint_content_opaque (GtkWidget *widget,
- GdkGC *gc,
- const ArtIRect *content_bounds,
- const ArtIRect *dirty_area,
- NautilusSmoothPaintOpaqueCallback paint_callback,
- gpointer callback_data)
-{
- ArtIRect content_dirty_area;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (gc != NULL);
- g_return_if_fail (content_bounds != NULL && !art_irect_empty (content_bounds));
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
- g_return_if_fail (paint_callback != NULL);
-
- /* Clip the content to the dirty area */
- art_irect_intersect (&content_dirty_area, content_bounds, dirty_area);
-
- /* No work to do */
- if (art_irect_empty (&content_dirty_area)) {
- return;
- }
-
- /* Draw content to screen */
- (* paint_callback) (widget,
- widget->window,
- gc,
- content_dirty_area.x0 - content_bounds->x0,
- content_dirty_area.y0 - content_bounds->y0,
- &content_dirty_area,
- callback_data);
-}
-
-/* Paint the smooth widget's content in transparent alpha composited mode */
-static void
-smooth_widget_paint_content_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const ArtIRect *content_bounds,
- int content_opacity,
- const ArtIRect *dirty_area,
- NautilusSmoothCompositeCallback composite_callback,
- gpointer callback_data)
-{
- ArtIRect content_dirty_area;
- ArtIRect composite_area;
- GdkPixbuf *buffer;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (gc != NULL);
- g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK);
- g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR);
- g_return_if_fail (content_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (content_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (content_bounds != NULL && !art_irect_empty (content_bounds));
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
- g_return_if_fail (composite_callback != NULL);
-
- art_irect_intersect (&content_dirty_area, content_bounds, dirty_area);
-
- if (art_irect_empty (&content_dirty_area)) {
- return;
- }
-
- buffer = smooth_widget_get_background (widget,
- &content_dirty_area,
- background_mode,
- solid_background_color);
-
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (buffer));
-
- nautilus_art_irect_assign (&composite_area,
- 0,
- 0,
- nautilus_art_irect_get_width (&content_dirty_area),
- nautilus_art_irect_get_height (&content_dirty_area));
-
- /* Composite the content into the buffer */
- (* composite_callback) (widget,
- buffer,
- content_dirty_area.x0 - content_bounds->x0,
- content_dirty_area.y0 - content_bounds->y0,
- &composite_area,
- content_opacity,
- callback_data);
-
- /* Draw the composited buffer to the screen */
- nautilus_gdk_pixbuf_draw_to_drawable (buffer,
- widget->window,
- gc,
- 0,
- 0,
- &content_dirty_area,
- GDK_RGB_DITHER_NONE,
- GDK_PIXBUF_ALPHA_BILEVEL,
- NAUTILUS_STANDARD_ALPHA_THRESHHOLD);
-
- gdk_pixbuf_unref (buffer);
-}
-
-/* Paint both the smooth widget's tile and content in transparent alpha
- * composited mode. */
-static void
-smooth_widget_paint_tile_and_content_transparent (GtkWidget *widget,
- GdkGC *gc,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- int tile_opacity,
- const NautilusArtIPoint *tile_origin,
- const ArtIRect *content_bounds,
- int content_opacity,
- const ArtIRect *dirty_area,
- NautilusSmoothCompositeCallback composite_callback,
- gpointer callback_data)
-{
- ArtIRect tile_dirty_area;
- ArtIRect content_dirty_area;
- ArtIRect tile_and_content_intersection;
- ArtIRect tile_and_content_union;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (gc != NULL);
- g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK);
- g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR);
- g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (tile_pixbuf));
- g_return_if_fail (tile_bounds != NULL && !art_irect_empty (tile_bounds));
- g_return_if_fail (tile_origin != NULL);
- g_return_if_fail (content_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (content_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (content_bounds != NULL && !art_irect_empty (content_bounds));
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
- g_return_if_fail (composite_callback != NULL);
-
- art_irect_intersect (&tile_dirty_area, tile_bounds, dirty_area);
- art_irect_intersect (&content_dirty_area, content_bounds, dirty_area);
-
- /* Both empty, do nothing */
- if (art_irect_empty (&tile_dirty_area) && art_irect_empty (&content_dirty_area)) {
- return;
- }
-
- /* Only the pixbuf is dirty */
- if (art_irect_empty (&tile_dirty_area) && !art_irect_empty (&content_dirty_area)) {
- smooth_widget_paint_content_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- content_bounds,
- content_opacity,
- &content_dirty_area,
- composite_callback,
- NULL);
- return;
- }
-
- /* Only the tile is dirty */
- if (!art_irect_empty (&tile_dirty_area) && art_irect_empty (&content_dirty_area)) {
- smooth_widget_paint_tile_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- tile_pixbuf,
- tile_bounds,
- tile_opacity,
- tile_origin,
- &tile_dirty_area);
- return;
- }
-
- art_irect_intersect (&tile_and_content_intersection, &tile_dirty_area, &content_dirty_area);
-
- /* Both dirty without overlaping each other */
- if (art_irect_empty (&tile_and_content_intersection)) {
- smooth_widget_paint_tile_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- tile_pixbuf,
- tile_bounds,
- tile_opacity,
- tile_origin,
- &tile_dirty_area);
-
- smooth_widget_paint_content_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- content_bounds,
- content_opacity,
- &content_dirty_area,
- composite_callback,
- NULL);
- return;
- }
-
- /* Both dirty overlaping each other. We use the union of the
- * two rectangles even though its not the most efficient way.
- */
- art_irect_union (&tile_and_content_union, &tile_dirty_area, &content_dirty_area);
-
- if (!art_irect_empty (&tile_and_content_union)) {
- GdkPixbuf *buffer;
- ArtIRect tile_area;
- ArtIRect composite_area;
-
- buffer = smooth_widget_get_background (widget,
- &tile_and_content_union,
- background_mode,
- solid_background_color);
- g_return_if_fail (nautilus_gdk_pixbuf_is_valid (buffer));
-
- nautilus_art_irect_assign (&tile_area,
- tile_dirty_area.x0 - tile_and_content_union.x0,
- tile_dirty_area.y0 - tile_and_content_union.y0,
- nautilus_art_irect_get_width (&tile_dirty_area),
- nautilus_art_irect_get_height (&tile_dirty_area));
-
- /* Composite the tile into the buffer */
- nautilus_gdk_pixbuf_draw_to_pixbuf_tiled (tile_pixbuf,
- buffer,
- &tile_area,
- gdk_pixbuf_get_width (tile_pixbuf),
- gdk_pixbuf_get_height (tile_pixbuf),
- tile_origin->x - tile_and_content_union.x0,
- tile_origin->y - tile_and_content_union.y0,
- tile_opacity,
- GDK_INTERP_NEAREST);
-
- nautilus_art_irect_assign (&composite_area,
- content_dirty_area.x0 - tile_dirty_area.x0,
- content_dirty_area.y0 - tile_dirty_area.y0,
- nautilus_art_irect_get_width (&content_dirty_area),
- nautilus_art_irect_get_height (&content_dirty_area));
-
- /* Composite the content into the buffer */
- (* composite_callback) (widget,
- buffer,
- content_dirty_area.x0 - content_bounds->x0,
- content_dirty_area.y0 - content_bounds->y0,
- &composite_area,
- content_opacity,
- callback_data);
-
- /* Draw the composited buffer to the screen */
- nautilus_gdk_pixbuf_draw_to_drawable (buffer,
- widget->window,
- gc,
- 0,
- 0,
- &tile_and_content_union,
- GDK_RGB_DITHER_NONE,
- GDK_PIXBUF_ALPHA_BILEVEL,
- NAUTILUS_STANDARD_ALPHA_THRESHHOLD);
-
- gdk_pixbuf_unref (buffer);
- }
-}
-
-/**
- * nautilus_smooth_widget_paint:
- * @widget: A smooth widget.
- * @gc: GdkGC to use for copy area.
- * @is_smooth: Is the widget smooth ?
- * @background_mode: Background mode.
- * @solid_background_color: Background color for the case when
- * background_mode is NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR.
- * @tile_pixbuf: Pixbuf to use for tiling or NULL.
- * @tile_bounds: The bounds of the tile or NAUTILUS_ART_IRECT_EMPTY.
- * @tile_opacity: The opacity for the tile when is_smooth is TRUE.
- * @tile_mode_vertical: The vertical tiliing mode.
- * @tile_mode_horizontal: The horizontal tiliing mode.
- * @content_bounds: The bounds of the content or NAUTILUS_ART_IRECT_EMPTY.
- * @content_opacity: The opacity for the content when is_smooth is TRUE.
- * @dirty_area: The dirty area, usually from expose_event().
- * @paint_callback: Content painting callback for when is_smooth is FALSE.
- * @composite_callback: Content compositing callback for when is_smooth is TRUE.
- * @callback_data: Data passed to the callbacks.
- *
- * Paint a smooth widget. If the 'is_smooth' flag is TRUE, then all painting
- * will be done using alpha compositions. In this mode the tile_opacity
- * and pixbuf_opacity are honored. This mode is significantly slower.
- *
- * If the 'is_smooth' flag is FALSE, then all painting will be done
- * using simple copy_area operations. This is mode is very fast
- * but doesnt look as good. In this mode, the tile_opacity and
- * pixbuf_opacity are ignored.
- *
- * Also, when 'is_smooth' is TRUE, the 'background_mode' has a huge effect
- * on the performance of this function. Here we list the 3 background modes
- * in order of SLOWEST to FASTEST:
- *
- * NAUTILUS_SMOOTH_BACKGROUND_GTK:
- * Use the background as painted by Gtk. This includes arbitrarily complex
- * gradients, images and solid colors. Using this mode will ensure that
- * the content you are painting is smoothly displayed on top of anything
- * that is rendered by Gtk. Unfortunately, for this mode to work a lot
- * of information needs to be transfered back and forth to the X server.
- * That means it is very slow. If you "know" what the contents of the
- * surface you are painting on, use on of the other two modes.
- *
- * NAUTILUS_SMOOTH_BACKGROUND_CALLBACK:
- * Use a callback to draw the background. This makes is possible to use
- * already existing background rendering code. For example, Nautilus
- * uses a NautilusBackground object that can be used as a callback client
- * for this mode. The callback is implemented as a widget signal. The
- * signature of the callback is 'NautilusSmoothWidgetDrawBackground'.
- *
- * NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR:
- * Use a solid color for the background. This is the fastest mode. It also
- * has the benefit that since the background is always known, the content
- * you are rendering can be cached.
- *
- * If a tile_pixbuf is given, then it is rendered according to the value of
- * 'tile_mode_vertical' and 'tile_mode_horizontal' Here we list the 2
- * valid tiling modes:
- *
- * The 'paint_callback' is invoked when not it smooth mode.
- * The 'composite_callback' is invoked when in smooth mode.
- */
-void
-nautilus_smooth_widget_paint (GtkWidget *widget,
- GdkGC *gc,
- gboolean is_smooth,
- NautilusSmoothBackgroundMode background_mode,
- guint32 solid_background_color,
- const GdkPixbuf *tile_pixbuf,
- const ArtIRect *tile_bounds,
- int tile_opacity,
- NautilusSmoothTileMode tile_mode_vertical,
- NautilusSmoothTileMode tile_mode_horizontal,
- const ArtIRect *content_bounds,
- int content_opacity,
- const ArtIRect *dirty_area,
- NautilusSmoothPaintOpaqueCallback paint_callback,
- NautilusSmoothCompositeCallback composite_callback,
- gpointer callback_data)
-{
- gboolean tile_empty;
- gboolean content_empty;
- NautilusArtIPoint tile_origin;
-
- g_return_if_fail (widget_is_smooth (widget));
- g_return_if_fail (GTK_WIDGET_REALIZED (widget));
- g_return_if_fail (gc != NULL);
- g_return_if_fail (background_mode >= NAUTILUS_SMOOTH_BACKGROUND_GTK);
- g_return_if_fail (background_mode <= NAUTILUS_SMOOTH_BACKGROUND_SOLID_COLOR);
- g_return_if_fail (tile_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (tile_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (tile_bounds != NULL);
- g_return_if_fail (tile_mode_vertical >= NAUTILUS_SMOOTH_TILE_SELF);
- g_return_if_fail (tile_mode_vertical <= NAUTILUS_SMOOTH_TILE_ANCESTOR);
- g_return_if_fail (tile_mode_horizontal >= NAUTILUS_SMOOTH_TILE_SELF);
- g_return_if_fail (tile_mode_horizontal <= NAUTILUS_SMOOTH_TILE_ANCESTOR);
- g_return_if_fail (content_opacity >= NAUTILUS_OPACITY_FULLY_TRANSPARENT);
- g_return_if_fail (content_opacity <= NAUTILUS_OPACITY_FULLY_OPAQUE);
- g_return_if_fail (content_bounds != NULL);
- g_return_if_fail (dirty_area != NULL && !art_irect_empty (dirty_area));
- g_return_if_fail (paint_callback != NULL);
- g_return_if_fail (composite_callback != NULL);
-
- tile_empty = art_irect_empty (tile_bounds);
- content_empty = art_irect_empty (content_bounds);
-
- tile_origin = smooth_widget_get_tile_origin_point (widget,
- tile_mode_vertical,
- tile_mode_horizontal);
-
- /* Smooth */
- if (is_smooth) {
- if (!content_empty && !tile_empty) {
- smooth_widget_paint_tile_and_content_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- tile_pixbuf,
- tile_bounds,
- tile_opacity,
- &tile_origin,
- content_bounds,
- content_opacity,
- dirty_area,
- composite_callback,
- callback_data);
-
- } else if (!content_empty) {
- smooth_widget_paint_content_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- content_bounds,
- content_opacity,
- dirty_area,
- composite_callback,
- callback_data);
- } else {
- smooth_widget_paint_tile_transparent (widget,
- gc,
- background_mode,
- solid_background_color,
- tile_pixbuf,
- tile_bounds,
- tile_opacity,
- &tile_origin,
- dirty_area);
- }
- /* Not smooth */
- } else {
- /* Draw the tile if needed */
- if (!tile_empty) {
- smooth_widget_paint_tile_opaque (widget,
- gc,
- tile_pixbuf,
- tile_bounds,
- &tile_origin,
- dirty_area);
- }
-
- /* Drae the content if needed */
- if (!content_empty) {
- smooth_widget_paint_content_opaque (widget,
- gc,
- content_bounds,
- dirty_area,
- paint_callback,
- callback_data);
- }
- }
-}
-
-/**
- * nautilus_smooth_widget_get_tile_bounds:
- * @widget: A smooth widget.
- * @tile_pixbuf: The tile pixbuf.
- * @tile_width: The tile width.
- * @tile_height: The tile height.
- *
- * Return the bounds for the smooth widget's tile.
- *
- * tile_width controls the horizontal extent of the tile.
- *
- * tile_height controls the vertical extent of the tile.
- *
- * tile_width/tile_height can be integer values greater than
- * zero. We also allow two special values:
- *
- * NAUTILUS_SMOOTH_TILE_EXTENT_FULL:
- * Tile occupies the full extent available either horizontall (tile_width)
- * or vertically (tile_height). This basically mean that the tile occupies
- * the full 'GtkWidget allocation'
- *
- * NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP:
- * Tile occupies a single tile step. A tile step is equal to the width and
- * height of the tile pixbuf for the horizontal and veritcal cases
- * respectively.
- *
- */
-ArtIRect
-nautilus_smooth_widget_get_tile_bounds (const GtkWidget *widget,
- const GdkPixbuf *tile_pixbuf,
- int tile_width,
- int tile_height)
-{
- ArtIRect bounds;
- ArtIRect tile_bounds;
- ArtIRect clipped_tile_bounds;
-
- g_return_val_if_fail (widget_is_smooth (widget), NAUTILUS_ART_IRECT_EMPTY);
- g_return_val_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP, NAUTILUS_ART_IRECT_EMPTY);
- g_return_val_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP, NAUTILUS_ART_IRECT_EMPTY);
-
- if (tile_pixbuf == NULL) {
- return NAUTILUS_ART_IRECT_EMPTY;
- }
-
- tile_bounds.x0 = widget->allocation.x;
- tile_bounds.y0 = widget->allocation.y;
-
- if (tile_width == NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP) {
- tile_bounds.x1 = tile_bounds.x0 + gdk_pixbuf_get_width (tile_pixbuf);
- } else if (tile_width == NAUTILUS_SMOOTH_TILE_EXTENT_FULL) {
- tile_bounds.x1 = tile_bounds.x0 + widget->allocation.width;
- } else {
- tile_bounds.x1 = tile_bounds.x0 + tile_width;
- }
-
- if (tile_height == NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP) {
- tile_bounds.y1 = tile_bounds.y0 + gdk_pixbuf_get_height (tile_pixbuf);
- } else if (tile_height == NAUTILUS_SMOOTH_TILE_EXTENT_FULL) {
- tile_bounds.y1 = tile_bounds.y0 + widget->allocation.height;
- } else {
- tile_bounds.y1 = tile_bounds.y0 + tile_height;
- }
-
- /* Clip the tile bounds to the widget bounds */
- bounds = nautilus_gtk_widget_get_bounds (widget);
- art_irect_intersect (&clipped_tile_bounds, &tile_bounds, &bounds);
-
- return tile_bounds;
-}
-
-NautilusDimensions
-nautilus_smooth_widget_get_preferred_dimensions (const GtkWidget *widget,
- const NautilusDimensions *content_dimensions,
- const NautilusDimensions *tile_dimensions,
- int tile_width,
- int tile_height)
-{
- NautilusDimensions preferred_dimensions;
-
- g_return_val_if_fail (widget_is_smooth (widget), NAUTILUS_DIMENSIONS_EMPTY);
- g_return_val_if_fail (content_dimensions != NULL, NAUTILUS_DIMENSIONS_EMPTY);
- g_return_val_if_fail (tile_dimensions != NULL, NAUTILUS_DIMENSIONS_EMPTY);
- g_return_val_if_fail (tile_width >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP, NAUTILUS_DIMENSIONS_EMPTY);
- g_return_val_if_fail (tile_height >= NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP, NAUTILUS_DIMENSIONS_EMPTY);
-
- if (tile_width == NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP) {
- tile_width = tile_dimensions->width;
- } else {
- tile_width = 0;
- }
-
- if (tile_height == NAUTILUS_SMOOTH_TILE_EXTENT_ONE_STEP) {
- tile_height = tile_dimensions->height;
- } else {
- tile_height = 0;
- }
-
- preferred_dimensions.width = MAX (content_dimensions->width, tile_width) + (2 * GTK_MISC (widget)->xpad);
- preferred_dimensions.height = MAX (content_dimensions->height, tile_height) + (2 * GTK_MISC (widget)->ypad);
-
- /* Make sure the dimensions is not zero. Gtk goes berserk with zero size widget */
- preferred_dimensions.width = MAX (preferred_dimensions.width, 2);
- preferred_dimensions.height = MAX (preferred_dimensions.height, 2);
-
- return preferred_dimensions;
-}
-
-void
-nautilus_smooth_widget_register_type (GtkType type)
-{
- if (smooth_widget_type_list == NULL) {
- g_atexit (smooth_widget_type_list_free);
- }
-
- smooth_widget_type_list = g_list_append (smooth_widget_type_list, GINT_TO_POINTER (type));
-}
-