1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include <pango/pangocairo.h>
30 #include <gdk-pixbuf/gdk-pixbuf.h>
32 #include "gdkdrawable.h"
33 #include "gdkinternals.h"
34 #include "gdkwindow.h"
35 #include "gdkscreen.h"
36 #include "gdkpixbuf.h"
39 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
44 gint *composite_x_offset,
45 gint *composite_y_offset);
46 static cairo_region_t * gdk_drawable_real_get_visible_region (GdkDrawable *drawable);
47 static void gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
58 G_DEFINE_ABSTRACT_TYPE (GdkDrawable, gdk_drawable, G_TYPE_OBJECT)
61 gdk_drawable_class_init (GdkDrawableClass *klass)
63 klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
64 /* Default implementation for clip and visible region is the same */
65 klass->get_clip_region = gdk_drawable_real_get_visible_region;
66 klass->get_visible_region = gdk_drawable_real_get_visible_region;
67 klass->draw_drawable = gdk_drawable_real_draw_drawable;
71 gdk_drawable_init (GdkDrawable *drawable)
75 /* Manipulation of drawables
79 * gdk_drawable_get_size:
80 * @drawable: a #GdkDrawable
81 * @width: (out) (allow-none): location to store drawable's width, or %NULL
82 * @height: (out) (allow-none): location to store drawable's height, or %NULL
84 * Fills *@width and *@height with the size of @drawable.
85 * @width or @height can be %NULL if you only want the other one.
87 * On the X11 platform, if @drawable is a #GdkWindow, the returned
88 * size is the size reported in the most-recently-processed configure
89 * event, rather than the current size on the X server.
93 gdk_drawable_get_size (GdkDrawable *drawable,
97 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
99 GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);
103 * gdk_drawable_get_visual:
104 * @drawable: a #GdkDrawable
106 * Gets the #GdkVisual describing the pixel format of @drawable.
108 * Return value: a #GdkVisual
111 gdk_drawable_get_visual (GdkDrawable *drawable)
113 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
115 return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
119 * gdk_drawable_get_depth:
120 * @drawable: a #GdkDrawable
122 * Obtains the bit depth of the drawable, that is, the number of bits
123 * that make up a pixel in the drawable's visual. Examples are 8 bits
124 * per pixel, 24 bits per pixel, etc.
126 * Return value: number of bits per pixel
129 gdk_drawable_get_depth (GdkDrawable *drawable)
131 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
133 return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
136 * gdk_drawable_get_screen:
137 * @drawable: a #GdkDrawable
139 * Gets the #GdkScreen associated with a #GdkDrawable.
141 * Return value: the #GdkScreen associated with @drawable
146 gdk_drawable_get_screen(GdkDrawable *drawable)
148 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
150 return GDK_DRAWABLE_GET_CLASS (drawable)->get_screen (drawable);
154 * gdk_drawable_get_display:
155 * @drawable: a #GdkDrawable
157 * Gets the #GdkDisplay associated with a #GdkDrawable.
159 * Return value: the #GdkDisplay associated with @drawable
164 gdk_drawable_get_display (GdkDrawable *drawable)
166 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
168 return gdk_screen_get_display (gdk_drawable_get_screen (drawable));
172 * gdk_drawable_set_colormap:
173 * @drawable: a #GdkDrawable
174 * @colormap: a #GdkColormap
176 * Sets the colormap associated with @drawable. Normally this will
177 * happen automatically when the drawable is created; you only need to
178 * use this function if the drawable-creating function did not have a
179 * way to determine the colormap, and you then use drawable operations
180 * that require a colormap. The colormap for all drawables and
181 * graphics contexts you intend to use together should match. i.e.
182 * when using a #GdkGC to draw to a drawable, or copying one drawable
183 * to another, the colormaps should match.
187 gdk_drawable_set_colormap (GdkDrawable *drawable,
190 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
191 g_return_if_fail (cmap == NULL || gdk_drawable_get_depth (drawable)
192 == cmap->visual->depth);
194 GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
198 * gdk_drawable_get_colormap:
199 * @drawable: a #GdkDrawable
201 * Gets the colormap for @drawable, if one is set; returns
204 * Return value: the colormap, or %NULL
207 gdk_drawable_get_colormap (GdkDrawable *drawable)
209 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
211 return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
219 * @drawable: a #GdkDrawable
220 * @gc: a #GdkGC sharing the drawable's visual and colormap
221 * @src: the source #GdkDrawable, which may be the same as @drawable
222 * @xsrc: X position in @src of rectangle to draw
223 * @ysrc: Y position in @src of rectangle to draw
224 * @xdest: X position in @drawable where the rectangle should be drawn
225 * @ydest: Y position in @drawable where the rectangle should be drawn
226 * @width: width of rectangle to draw, or -1 for entire @src width
227 * @height: height of rectangle to draw, or -1 for entire @src height
229 * Copies the @width x @height region of @src at coordinates (@xsrc,
230 * @ysrc) to coordinates (@xdest, @ydest) in @drawable.
231 * @width and/or @height may be given as -1, in which case the entire
232 * @src drawable will be copied.
234 * Most fields in @gc are not used for this operation, but notably the
235 * clip mask or clip region will be honored.
237 * The source and destination drawables must have the same visual and
238 * colormap, or errors will result. (On X11, failure to match
239 * visual/colormap results in a BadMatch error from the X server.)
240 * A common cause of this problem is an attempt to draw a bitmap to
241 * a color drawable. The way to draw a bitmap is to set the bitmap as
242 * the stipple on the #GdkGC, set the fill mode to %GDK_STIPPLED, and
243 * then draw the rectangle.
246 gdk_draw_drawable (GdkDrawable *drawable,
256 GdkDrawable *composite;
257 gint composite_x_offset = 0;
258 gint composite_y_offset = 0;
260 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
261 g_return_if_fail (GDK_IS_DRAWABLE (src));
262 g_return_if_fail (GDK_IS_GC (gc));
264 if (width < 0 || height < 0)
269 gdk_drawable_get_size (src, &real_width, &real_height);
274 height = real_height;
279 GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
283 &composite_y_offset);
285 /* TODO: For non-native windows this may copy stuff from other overlapping
286 windows. We should clip that and (for windows with bg != None) clear that
287 area in the destination instead. */
289 if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src)
290 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable, gc,
292 xsrc - composite_x_offset,
293 ysrc - composite_y_offset,
297 else /* backwards compat for old out-of-tree implementations of GdkDrawable (are there any?) */
298 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
300 xsrc - composite_x_offset,
301 ysrc - composite_y_offset,
305 g_object_unref (composite);
309 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
314 gint *composite_x_offset,
315 gint *composite_y_offset)
317 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
319 *composite_x_offset = 0;
320 *composite_y_offset = 0;
322 return g_object_ref (drawable);
326 * gdk_drawable_get_clip_region:
327 * @drawable: a #GdkDrawable
329 * Computes the region of a drawable that potentially can be written
330 * to by drawing primitives. This region will not take into account
331 * the clip region for the GC, and may also not take into account
332 * other factors such as if the window is obscured by other windows,
333 * but no area outside of this region will be affected by drawing
336 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
340 gdk_drawable_get_clip_region (GdkDrawable *drawable)
342 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
344 return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
348 * gdk_drawable_get_visible_region:
349 * @drawable: a #GdkDrawable
351 * Computes the region of a drawable that is potentially visible.
352 * This does not necessarily take into account if the window is
353 * obscured by other windows, but no area outside of this region
356 * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
360 gdk_drawable_get_visible_region (GdkDrawable *drawable)
362 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
364 return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
367 static cairo_region_t *
368 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
375 gdk_drawable_get_size (drawable, &rect.width, &rect.height);
377 return cairo_region_create_rectangle (&rect);
381 * _gdk_drawable_ref_cairo_surface:
382 * @drawable: a #GdkDrawable
384 * Obtains a #cairo_surface_t for the given drawable. If a
385 * #cairo_surface_t for the drawable already exists, it will be
386 * referenced, otherwise a new surface will be created.
388 * Return value: a newly referenced #cairo_surface_t that points
389 * to @drawable. Unref with cairo_surface_destroy()
392 _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
394 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
396 return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
399 /* Implementation of the old vfunc in terms of the new one
400 in case someone calls it directly (which they shouldn't!) */
402 gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
412 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable,
424 /************************************************************************/
427 * _gdk_drawable_get_scratch_gc:
428 * @drawable: A #GdkDrawable
429 * @graphics_exposures: Whether the returned #GdkGC should generate graphics exposures
431 * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
432 * the standard values for @drawable, except for the graphics_exposures
433 * field which is determined by the @graphics_exposures parameter.
435 * The foreground color of the returned #GdkGC is undefined. The #GdkGC
436 * must not be altered in any way, except to change its foreground color.
438 * Return value: A #GdkGC suitable for drawing on @drawable
443 _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
444 gboolean graphics_exposures)
449 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
451 screen = gdk_drawable_get_screen (drawable);
453 g_return_val_if_fail (!screen->closed, NULL);
455 depth = gdk_drawable_get_depth (drawable) - 1;
457 if (graphics_exposures)
459 if (!screen->exposure_gcs[depth])
462 GdkGCValuesMask mask;
464 values.graphics_exposures = TRUE;
465 mask = GDK_GC_EXPOSURES;
467 screen->exposure_gcs[depth] =
468 gdk_gc_new_with_values (drawable, &values, mask);
471 return screen->exposure_gcs[depth];
475 if (!screen->normal_gcs[depth])
477 screen->normal_gcs[depth] =
478 gdk_gc_new (drawable);
481 return screen->normal_gcs[depth];
486 * _gdk_drawable_get_subwindow_scratch_gc:
487 * @drawable: A #GdkDrawable
489 * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
490 * the standard values for @drawable, except for the graphics_exposures
491 * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
493 * The foreground color of the returned #GdkGC is undefined. The #GdkGC
494 * must not be altered in any way, except to change its foreground color.
496 * Return value: A #GdkGC suitable for drawing on @drawable
501 _gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
506 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
508 screen = gdk_drawable_get_screen (drawable);
510 g_return_val_if_fail (!screen->closed, NULL);
512 depth = gdk_drawable_get_depth (drawable) - 1;
514 if (!screen->subwindow_gcs[depth])
517 GdkGCValuesMask mask;
519 values.graphics_exposures = TRUE;
520 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
521 mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;
523 screen->subwindow_gcs[depth] =
524 gdk_gc_new_with_values (drawable, &values, mask);
527 return screen->subwindow_gcs[depth];
532 * _gdk_drawable_get_source_drawable:
533 * @drawable: a #GdkDrawable
535 * Returns a drawable for the passed @drawable that is guaranteed to be
536 * usable to create a pixmap (e.g.: not an offscreen window).
541 _gdk_drawable_get_source_drawable (GdkDrawable *drawable)
543 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
545 if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
546 return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
552 _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
556 return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,