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 GdkImage* gdk_drawable_real_get_image (GdkDrawable *drawable,
44 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
49 gint *composite_x_offset,
50 gint *composite_y_offset);
51 static GdkRegion * gdk_drawable_real_get_visible_region (GdkDrawable *drawable);
52 static void gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable,
64 static void gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
75 G_DEFINE_ABSTRACT_TYPE (GdkDrawable, gdk_drawable, G_TYPE_OBJECT)
78 gdk_drawable_class_init (GdkDrawableClass *klass)
80 klass->get_image = gdk_drawable_real_get_image;
81 klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
82 /* Default implementation for clip and visible region is the same */
83 klass->get_clip_region = gdk_drawable_real_get_visible_region;
84 klass->get_visible_region = gdk_drawable_real_get_visible_region;
85 klass->draw_pixbuf = gdk_drawable_real_draw_pixbuf;
86 klass->draw_drawable = gdk_drawable_real_draw_drawable;
90 gdk_drawable_init (GdkDrawable *drawable)
94 /* Manipulation of drawables
98 * gdk_drawable_get_size:
99 * @drawable: a #GdkDrawable
100 * @width: (out) (allow-none): location to store drawable's width, or %NULL
101 * @height: (out) (allow-none): location to store drawable's height, or %NULL
103 * Fills *@width and *@height with the size of @drawable.
104 * @width or @height can be %NULL if you only want the other one.
106 * On the X11 platform, if @drawable is a #GdkWindow, the returned
107 * size is the size reported in the most-recently-processed configure
108 * event, rather than the current size on the X server.
112 gdk_drawable_get_size (GdkDrawable *drawable,
116 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
118 if (GDK_DRAWABLE_GET_CLASS (drawable)->get_size != NULL)
119 GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);
123 * gdk_drawable_get_visual:
124 * @drawable: a #GdkDrawable
126 * Gets the #GdkVisual describing the pixel format of @drawable.
128 * Return value: a #GdkVisual
131 gdk_drawable_get_visual (GdkDrawable *drawable)
133 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
135 return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
139 * gdk_drawable_get_depth:
140 * @drawable: a #GdkDrawable
142 * Obtains the bit depth of the drawable, that is, the number of bits
143 * that make up a pixel in the drawable's visual. Examples are 8 bits
144 * per pixel, 24 bits per pixel, etc.
146 * Return value: number of bits per pixel
149 gdk_drawable_get_depth (GdkDrawable *drawable)
151 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
153 return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
156 * gdk_drawable_get_screen:
157 * @drawable: a #GdkDrawable
159 * Gets the #GdkScreen associated with a #GdkDrawable.
161 * Return value: the #GdkScreen associated with @drawable
166 gdk_drawable_get_screen(GdkDrawable *drawable)
168 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
170 return GDK_DRAWABLE_GET_CLASS (drawable)->get_screen (drawable);
174 * gdk_drawable_get_display:
175 * @drawable: a #GdkDrawable
177 * Gets the #GdkDisplay associated with a #GdkDrawable.
179 * Return value: the #GdkDisplay associated with @drawable
184 gdk_drawable_get_display (GdkDrawable *drawable)
186 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
188 return gdk_screen_get_display (gdk_drawable_get_screen (drawable));
192 * gdk_drawable_set_colormap:
193 * @drawable: a #GdkDrawable
194 * @colormap: a #GdkColormap
196 * Sets the colormap associated with @drawable. Normally this will
197 * happen automatically when the drawable is created; you only need to
198 * use this function if the drawable-creating function did not have a
199 * way to determine the colormap, and you then use drawable operations
200 * that require a colormap. The colormap for all drawables and
201 * graphics contexts you intend to use together should match. i.e.
202 * when using a #GdkGC to draw to a drawable, or copying one drawable
203 * to another, the colormaps should match.
207 gdk_drawable_set_colormap (GdkDrawable *drawable,
210 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
211 g_return_if_fail (cmap == NULL || gdk_drawable_get_depth (drawable)
212 == cmap->visual->depth);
214 GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
218 * gdk_drawable_get_colormap:
219 * @drawable: a #GdkDrawable
221 * Gets the colormap for @drawable, if one is set; returns
224 * Return value: the colormap, or %NULL
227 gdk_drawable_get_colormap (GdkDrawable *drawable)
229 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
231 return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
239 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
241 * @x: the x coordinate of the point.
242 * @y: the y coordinate of the point.
244 * Draws a point, using the foreground color and other attributes of
248 gdk_draw_point (GdkDrawable *drawable,
255 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
256 g_return_if_fail (GDK_IS_GC (gc));
261 GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1);
266 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
268 * @x1_: the x coordinate of the start point.
269 * @y1_: the y coordinate of the start point.
270 * @x2_: the x coordinate of the end point.
271 * @y2_: the y coordinate of the end point.
273 * Draws a line, using the foreground color and other attributes of
277 gdk_draw_line (GdkDrawable *drawable,
286 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
287 g_return_if_fail (GDK_IS_GC (gc));
293 GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, &segment, 1);
297 * gdk_draw_rectangle:
298 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
300 * @filled: %TRUE if the rectangle should be filled.
301 * @x: the x coordinate of the left edge of the rectangle.
302 * @y: the y coordinate of the top edge of the rectangle.
303 * @width: the width of the rectangle.
304 * @height: the height of the rectangle.
306 * Draws a rectangular outline or filled rectangle, using the foreground color
307 * and other attributes of the #GdkGC.
309 * A rectangle drawn filled is 1 pixel smaller in both dimensions than a
310 * rectangle outlined. Calling
311 * <literal>gdk_draw_rectangle (window, gc, TRUE, 0, 0, 20, 20)</literal>
312 * results in a filled rectangle 20 pixels wide and 20 pixels high. Calling
313 * <literal>gdk_draw_rectangle (window, gc, FALSE, 0, 0, 20, 20)</literal>
314 * results in an outlined rectangle with corners at (0, 0), (0, 20), (20, 20),
315 * and (20, 0), which makes it 21 pixels wide and 21 pixels high.
318 gdk_draw_rectangle (GdkDrawable *drawable,
326 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
327 g_return_if_fail (GDK_IS_GC (gc));
329 if (width < 0 || height < 0)
334 gdk_drawable_get_size (drawable, &real_width, &real_height);
339 height = real_height;
342 GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y,
348 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
350 * @filled: %TRUE if the arc should be filled, producing a 'pie slice'.
351 * @x: the x coordinate of the left edge of the bounding rectangle.
352 * @y: the y coordinate of the top edge of the bounding rectangle.
353 * @width: the width of the bounding rectangle.
354 * @height: the height of the bounding rectangle.
355 * @angle1: the start angle of the arc, relative to the 3 o'clock position,
356 * counter-clockwise, in 1/64ths of a degree.
357 * @angle2: the end angle of the arc, relative to @angle1, in 1/64ths
360 * Draws an arc or a filled 'pie slice'. The arc is defined by the bounding
361 * rectangle of the entire ellipse, and the start and end angles of the part
362 * of the ellipse to be drawn.
365 gdk_draw_arc (GdkDrawable *drawable,
375 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
376 g_return_if_fail (GDK_IS_GC (gc));
378 if (width < 0 || height < 0)
383 gdk_drawable_get_size (drawable, &real_width, &real_height);
388 height = real_height;
391 GDK_DRAWABLE_GET_CLASS (drawable)->draw_arc (drawable, gc, filled,
392 x, y, width, height, angle1, angle2);
397 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
399 * @filled: %TRUE if the polygon should be filled. The polygon is closed
400 * automatically, connecting the last point to the first point if
402 * @points: an array of #GdkPoint structures specifying the points making
404 * @n_points: the number of points.
406 * Draws an outlined or filled polygon.
409 gdk_draw_polygon (GdkDrawable *drawable,
412 const GdkPoint *points,
415 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
416 g_return_if_fail (GDK_IS_GC (gc));
418 GDK_DRAWABLE_GET_CLASS (drawable)->draw_polygon (drawable, gc, filled,
425 * @drawable: a #GdkDrawable
426 * @gc: a #GdkGC sharing the drawable's visual and colormap
427 * @src: the source #GdkDrawable, which may be the same as @drawable
428 * @xsrc: X position in @src of rectangle to draw
429 * @ysrc: Y position in @src of rectangle to draw
430 * @xdest: X position in @drawable where the rectangle should be drawn
431 * @ydest: Y position in @drawable where the rectangle should be drawn
432 * @width: width of rectangle to draw, or -1 for entire @src width
433 * @height: height of rectangle to draw, or -1 for entire @src height
435 * Copies the @width x @height region of @src at coordinates (@xsrc,
436 * @ysrc) to coordinates (@xdest, @ydest) in @drawable.
437 * @width and/or @height may be given as -1, in which case the entire
438 * @src drawable will be copied.
440 * Most fields in @gc are not used for this operation, but notably the
441 * clip mask or clip region will be honored.
443 * The source and destination drawables must have the same visual and
444 * colormap, or errors will result. (On X11, failure to match
445 * visual/colormap results in a BadMatch error from the X server.)
446 * A common cause of this problem is an attempt to draw a bitmap to
447 * a color drawable. The way to draw a bitmap is to set the bitmap as
448 * the stipple on the #GdkGC, set the fill mode to %GDK_STIPPLED, and
449 * then draw the rectangle.
452 gdk_draw_drawable (GdkDrawable *drawable,
462 GdkDrawable *composite;
463 gint composite_x_offset = 0;
464 gint composite_y_offset = 0;
466 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
467 g_return_if_fail (GDK_IS_DRAWABLE (src));
468 g_return_if_fail (GDK_IS_GC (gc));
470 if (width < 0 || height < 0)
475 gdk_drawable_get_size (src, &real_width, &real_height);
480 height = real_height;
485 GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
489 &composite_y_offset);
491 /* TODO: For non-native windows this may copy stuff from other overlapping
492 windows. We should clip that and (for windows with bg != None) clear that
493 area in the destination instead. */
495 if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src)
496 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable, gc,
498 xsrc - composite_x_offset,
499 ysrc - composite_y_offset,
503 else /* backwards compat for old out-of-tree implementations of GdkDrawable (are there any?) */
504 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
506 xsrc - composite_x_offset,
507 ysrc - composite_y_offset,
511 g_object_unref (composite);
516 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
518 * @image: the #GdkImage to draw.
519 * @xsrc: the left edge of the source rectangle within @image.
520 * @ysrc: the top of the source rectangle within @image.
521 * @xdest: the x coordinate of the destination within @drawable.
522 * @ydest: the y coordinate of the destination within @drawable.
523 * @width: the width of the area to be copied, or -1 to make the area
524 * extend to the right edge of @image.
525 * @height: the height of the area to be copied, or -1 to make the area
526 * extend to the bottom edge of @image.
528 * Draws a #GdkImage onto a drawable.
529 * The depth of the #GdkImage must match the depth of the #GdkDrawable.
532 gdk_draw_image (GdkDrawable *drawable,
542 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
543 g_return_if_fail (GDK_IS_IMAGE (image));
544 g_return_if_fail (GDK_IS_GC (gc));
547 width = image->width;
549 height = image->height;
551 GDK_DRAWABLE_GET_CLASS (drawable)->draw_image (drawable, gc, image, xsrc, ysrc,
552 xdest, ydest, width, height);
557 * @drawable: Destination drawable.
558 * @gc: (allow-none): a #GdkGC, used for clipping, or %NULL
559 * @pixbuf: a #GdkPixbuf
560 * @src_x: Source X coordinate within pixbuf.
561 * @src_y: Source Y coordinates within pixbuf.
562 * @dest_x: Destination X coordinate within drawable.
563 * @dest_y: Destination Y coordinate within drawable.
564 * @width: Width of region to render, in pixels, or -1 to use pixbuf width.
565 * @height: Height of region to render, in pixels, or -1 to use pixbuf height.
566 * @dither: Dithering mode for #GdkRGB.
567 * @x_dither: X offset for dither.
568 * @y_dither: Y offset for dither.
570 * Renders a rectangular portion of a pixbuf to a drawable. The destination
571 * drawable must have a colormap. All windows have a colormap, however, pixmaps
572 * only have colormap by default if they were created with a non-%NULL window
573 * argument. Otherwise a colormap must be set on them with
574 * gdk_drawable_set_colormap().
576 * On older X servers, rendering pixbufs with an alpha channel involves round
577 * trips to the X server, and may be somewhat slow.
579 * If GDK is built with the Sun mediaLib library, the gdk_draw_pixbuf
580 * function is accelerated using mediaLib, which provides hardware
581 * acceleration on Intel, AMD, and Sparc chipsets. If desired, mediaLib
582 * support can be turned off by setting the GDK_DISABLE_MEDIALIB environment
588 gdk_draw_pixbuf (GdkDrawable *drawable,
590 const GdkPixbuf *pixbuf,
601 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
602 g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
603 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
605 if (width == 0 || height == 0)
609 width = gdk_pixbuf_get_width (pixbuf);
611 height = gdk_pixbuf_get_height (pixbuf);
613 GDK_DRAWABLE_GET_CLASS (drawable)->draw_pixbuf (drawable, gc,
614 (GdkPixbuf *) pixbuf,
615 src_x, src_y, dest_x, dest_y,
617 dither, x_dither, y_dither);
622 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
624 * @points: an array of #GdkPoint structures.
625 * @n_points: the number of points to be drawn.
627 * Draws a number of points, using the foreground color and other
628 * attributes of the #GdkGC.
631 gdk_draw_points (GdkDrawable *drawable,
633 const GdkPoint *points,
636 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
637 g_return_if_fail ((points != NULL) && (n_points > 0));
638 g_return_if_fail (GDK_IS_GC (gc));
639 g_return_if_fail (n_points >= 0);
644 GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc,
645 (GdkPoint *) points, n_points);
650 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
652 * @segs: an array of #GdkSegment structures specifying the start and
653 * end points of the lines to be drawn.
654 * @n_segs: the number of line segments to draw, i.e. the size of the
657 * Draws a number of unconnected lines.
660 gdk_draw_segments (GdkDrawable *drawable,
662 const GdkSegment *segs,
665 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
670 g_return_if_fail (segs != NULL);
671 g_return_if_fail (GDK_IS_GC (gc));
672 g_return_if_fail (n_segs >= 0);
674 GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc,
675 (GdkSegment *) segs, n_segs);
680 * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
682 * @points: an array of #GdkPoint structures specifying the endpoints of the
683 * @n_points: the size of the @points array.
685 * Draws a series of lines connecting the given points.
686 * The way in which joins between lines are draw is determined by the
687 * #GdkCapStyle value in the #GdkGC. This can be set with
688 * gdk_gc_set_line_attributes().
691 gdk_draw_lines (GdkDrawable *drawable,
693 const GdkPoint *points,
696 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
697 g_return_if_fail (points != NULL);
698 g_return_if_fail (GDK_IS_GC (gc));
699 g_return_if_fail (n_points >= 0);
704 GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc,
705 (GdkPoint *) points, n_points);
709 real_draw_glyphs (GdkDrawable *drawable,
711 const PangoMatrix *matrix,
715 PangoGlyphString *glyphs)
719 cr = gdk_cairo_create (drawable);
720 _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
724 cairo_matrix_t cairo_matrix;
726 cairo_matrix.xx = matrix->xx;
727 cairo_matrix.yx = matrix->yx;
728 cairo_matrix.xy = matrix->xy;
729 cairo_matrix.yy = matrix->yy;
730 cairo_matrix.x0 = matrix->x0;
731 cairo_matrix.y0 = matrix->y0;
733 cairo_set_matrix (cr, &cairo_matrix);
736 cairo_move_to (cr, x, y);
737 pango_cairo_show_glyph_string (cr, font, glyphs);
744 * @drawable: a #GdkDrawable
746 * @font: font to be used
747 * @x: X coordinate of baseline origin
748 * @y: Y coordinate of baseline origin
749 * @glyphs: the glyph string to draw
751 * This is a low-level function; 99% of text rendering should be done
752 * using gdk_draw_layout() instead.
754 * A glyph is a single image in a font. This function draws a sequence of
755 * glyphs. To obtain a sequence of glyphs you have to understand a
756 * lot about internationalized text handling, which you don't want to
757 * understand; thus, use gdk_draw_layout() instead of this function,
758 * gdk_draw_layout() handles the details.
762 gdk_draw_glyphs (GdkDrawable *drawable,
767 PangoGlyphString *glyphs)
769 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
770 g_return_if_fail (GDK_IS_GC (gc));
772 real_draw_glyphs (drawable, gc, NULL, font,
777 * gdk_draw_glyphs_transformed:
778 * @drawable: a #GdkDrawable
780 * @matrix: (allow-none): a #PangoMatrix, or %NULL to use an identity transformation
781 * @font: the font in which to draw the string
782 * @x: the x position of the start of the string (in Pango
783 * units in user space coordinates)
784 * @y: the y position of the baseline (in Pango units
785 * in user space coordinates)
786 * @glyphs: the glyph string to draw
788 * Renders a #PangoGlyphString onto a drawable, possibly
789 * transforming the layed-out coordinates through a transformation
790 * matrix. Note that the transformation matrix for @font is not
791 * changed, so to produce correct rendering results, the @font
792 * must have been loaded using a #PangoContext with an identical
793 * transformation matrix to that passed in to this function.
795 * See also gdk_draw_glyphs(), gdk_draw_layout().
800 gdk_draw_glyphs_transformed (GdkDrawable *drawable,
802 const PangoMatrix *matrix,
806 PangoGlyphString *glyphs)
808 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
809 g_return_if_fail (GDK_IS_GC (gc));
811 real_draw_glyphs (drawable, gc, matrix, font,
812 x / PANGO_SCALE, y / PANGO_SCALE, glyphs);
816 * gdk_draw_trapezoids:
817 * @drawable: a #GdkDrawable
819 * @trapezoids: an array of #GdkTrapezoid structures
820 * @n_trapezoids: the number of trapezoids to draw
822 * Draws a set of anti-aliased trapezoids. The trapezoids are
823 * combined using saturation addition, then drawn over the background
824 * as a set. This is low level functionality used internally to implement
825 * rotated underlines and backgrouds when rendering a PangoLayout and is
826 * likely not useful for applications.
831 gdk_draw_trapezoids (GdkDrawable *drawable,
833 const GdkTrapezoid *trapezoids,
839 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
840 g_return_if_fail (GDK_IS_GC (gc));
841 g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
843 cr = gdk_cairo_create (drawable);
844 _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
846 for (i = 0; i < n_trapezoids; i++)
848 cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1);
849 cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1);
850 cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2);
851 cairo_line_to (cr, trapezoids[i].x12, trapezoids[i].y2);
852 cairo_close_path (cr);
861 * gdk_drawable_copy_to_image:
862 * @drawable: a #GdkDrawable
863 * @image: (allow-none): a #GdkDrawable, or %NULL if a new @image should be created.
864 * @src_x: x coordinate on @drawable
865 * @src_y: y coordinate on @drawable
866 * @dest_x: x coordinate within @image. Must be 0 if @image is %NULL
867 * @dest_y: y coordinate within @image. Must be 0 if @image is %NULL
868 * @width: width of region to get
869 * @height: height or region to get
871 * Copies a portion of @drawable into the client side image structure
872 * @image. If @image is %NULL, creates a new image of size @width x @height
873 * and copies into that. See gdk_drawable_get_image() for further details.
875 * Return value: @image, or a new a #GdkImage containing the contents
881 gdk_drawable_copy_to_image (GdkDrawable *drawable,
890 GdkDrawable *composite;
891 gint composite_x_offset = 0;
892 gint composite_y_offset = 0;
896 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
897 g_return_val_if_fail (src_x >= 0, NULL);
898 g_return_val_if_fail (src_y >= 0, NULL);
900 /* FIXME? Note race condition since we get the size then
901 * get the image, and the size may have changed.
904 if (width < 0 || height < 0)
905 gdk_drawable_get_size (drawable,
906 width < 0 ? &width : NULL,
907 height < 0 ? &height : NULL);
910 GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
914 &composite_y_offset);
916 retval = GDK_DRAWABLE_GET_CLASS (composite)->_copy_to_image (composite,
918 src_x - composite_x_offset,
919 src_y - composite_y_offset,
923 g_object_unref (composite);
925 if (!image && retval)
927 cmap = gdk_drawable_get_colormap (drawable);
930 gdk_image_set_colormap (retval, cmap);
937 * gdk_drawable_get_image:
938 * @drawable: a #GdkDrawable
939 * @x: x coordinate on @drawable
940 * @y: y coordinate on @drawable
941 * @width: width of region to get
942 * @height: height or region to get
944 * A #GdkImage stores client-side image data (pixels). In contrast,
945 * #GdkPixmap and #GdkWindow are server-side
946 * objects. gdk_drawable_get_image() obtains the pixels from a
947 * server-side drawable as a client-side #GdkImage. The format of a
948 * #GdkImage depends on the #GdkVisual of the current display, which
949 * makes manipulating #GdkImage extremely difficult; therefore, in
950 * most cases you should use gdk_pixbuf_get_from_drawable() instead of
951 * this lower-level function. A #GdkPixbuf contains image data in a
952 * canonicalized RGB format, rather than a display-dependent format.
953 * Of course, there's a convenience vs. speed tradeoff here, so you'll
954 * want to think about what makes sense for your application.
956 * @x, @y, @width, and @height define the region of @drawable to
957 * obtain as an image.
959 * You would usually copy image data to the client side if you intend
960 * to examine the values of individual pixels, for example to darken
961 * an image or add a red tint. It would be prohibitively slow to
962 * make a round-trip request to the windowing system for each pixel,
963 * so instead you get all of them at once, modify them, then copy
964 * them all back at once.
966 * If the X server or other windowing system backend is on the local
967 * machine, this function may use shared memory to avoid copying
970 * If the source drawable is a #GdkWindow and partially offscreen
971 * or obscured, then the obscured portions of the returned image
972 * will contain undefined data.
974 * Return value: a #GdkImage containing the contents of @drawable
977 gdk_drawable_get_image (GdkDrawable *drawable,
983 GdkDrawable *composite;
984 gint composite_x_offset = 0;
985 gint composite_y_offset = 0;
989 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
990 g_return_val_if_fail (x >= 0, NULL);
991 g_return_val_if_fail (y >= 0, NULL);
993 /* FIXME? Note race condition since we get the size then
994 * get the image, and the size may have changed.
997 if (width < 0 || height < 0)
998 gdk_drawable_get_size (drawable,
999 width < 0 ? &width : NULL,
1000 height < 0 ? &height : NULL);
1003 GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
1006 &composite_x_offset,
1007 &composite_y_offset);
1009 retval = GDK_DRAWABLE_GET_CLASS (composite)->get_image (composite,
1010 x - composite_x_offset,
1011 y - composite_y_offset,
1014 g_object_unref (composite);
1016 cmap = gdk_drawable_get_colormap (drawable);
1019 gdk_image_set_colormap (retval, cmap);
1025 gdk_drawable_real_get_image (GdkDrawable *drawable,
1031 return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
1034 static GdkDrawable *
1035 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
1040 gint *composite_x_offset,
1041 gint *composite_y_offset)
1043 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1045 *composite_x_offset = 0;
1046 *composite_y_offset = 0;
1048 return g_object_ref (drawable);
1052 * gdk_drawable_get_clip_region:
1053 * @drawable: a #GdkDrawable
1055 * Computes the region of a drawable that potentially can be written
1056 * to by drawing primitives. This region will not take into account
1057 * the clip region for the GC, and may also not take into account
1058 * other factors such as if the window is obscured by other windows,
1059 * but no area outside of this region will be affected by drawing
1062 * Returns: a #GdkRegion. This must be freed with gdk_region_destroy()
1063 * when you are done.
1066 gdk_drawable_get_clip_region (GdkDrawable *drawable)
1068 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1070 return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
1074 * gdk_drawable_get_visible_region:
1075 * @drawable: a #GdkDrawable
1077 * Computes the region of a drawable that is potentially visible.
1078 * This does not necessarily take into account if the window is
1079 * obscured by other windows, but no area outside of this region
1082 * Returns: a #GdkRegion. This must be freed with gdk_region_destroy()
1083 * when you are done.
1086 gdk_drawable_get_visible_region (GdkDrawable *drawable)
1088 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1090 return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
1094 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
1101 gdk_drawable_get_size (drawable, &rect.width, &rect.height);
1103 return gdk_region_rectangle (&rect);
1107 * _gdk_drawable_ref_cairo_surface:
1108 * @drawable: a #GdkDrawable
1110 * Obtains a #cairo_surface_t for the given drawable. If a
1111 * #cairo_surface_t for the drawable already exists, it will be
1112 * referenced, otherwise a new surface will be created.
1114 * Return value: a newly referenced #cairo_surface_t that points
1115 * to @drawable. Unref with cairo_surface_destroy()
1118 _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
1120 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1122 return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
1126 composite (guchar *src_buf,
1129 gint dest_rowstride,
1133 guchar *src = src_buf;
1134 guchar *dest = dest_buf;
1138 gint twidth = width;
1147 t = a * p[0] + (255 - a) * q[0] + 0x80;
1148 q[0] = (t + (t >> 8)) >> 8;
1149 t = a * p[1] + (255 - a) * q[1] + 0x80;
1150 q[1] = (t + (t >> 8)) >> 8;
1151 t = a * p[2] + (255 - a) * q[2] + 0x80;
1152 q[2] = (t + (t >> 8)) >> 8;
1158 src += src_rowstride;
1159 dest += dest_rowstride;
1164 composite_0888 (guchar *src_buf,
1167 gint dest_rowstride,
1168 GdkByteOrder dest_byte_order,
1172 guchar *src = src_buf;
1173 guchar *dest = dest_buf;
1177 gint twidth = width;
1181 if (dest_byte_order == GDK_LSB_FIRST)
1187 t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
1188 q[0] = (t + (t >> 8)) >> 8;
1189 t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
1190 q[1] = (t + (t >> 8)) >> 8;
1191 t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
1192 q[2] = (t + (t >> 8)) >> 8;
1203 t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
1204 q[1] = (t + (t >> 8)) >> 8;
1205 t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
1206 q[2] = (t + (t >> 8)) >> 8;
1207 t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
1208 q[3] = (t + (t >> 8)) >> 8;
1214 src += src_rowstride;
1215 dest += dest_rowstride;
1221 composite_0888_medialib (guchar *src_buf,
1224 gint dest_rowstride,
1225 GdkByteOrder dest_byte_order,
1229 guchar *src = src_buf;
1230 guchar *dest = dest_buf;
1232 mlib_image img_src, img_dst;
1234 mlib_ImageSetStruct (&img_dst,
1242 mlib_ImageSetStruct (&img_src,
1250 if (dest_byte_order == GDK_LSB_FIRST)
1251 mlib_ImageBlendRGBA2BGRA (&img_dst, &img_src);
1253 mlib_ImageBlendRGBA2ARGB (&img_dst, &img_src);
1258 composite_565 (guchar *src_buf,
1261 gint dest_rowstride,
1262 GdkByteOrder dest_byte_order,
1266 guchar *src = src_buf;
1267 guchar *dest = dest_buf;
1271 gint twidth = width;
1273 gushort *q = (gushort *)dest;
1279 guint tr1, tg1, tb1;
1283 /* This is fast, and corresponds to what composite() above does
1284 * if we converted to 8-bit first.
1286 tr = (tmp & 0xf800);
1287 tr1 = a * p[0] + (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1288 tg = (tmp & 0x07e0);
1289 tg1 = a * p[1] + (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1290 tb = (tmp & 0x001f);
1291 tb1 = a * p[2] + (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1293 *q = (((tr1 + (tr1 >> 8)) & 0xf800) |
1294 (((tg1 + (tg1 >> 8)) & 0xfc00) >> 5) |
1295 ((tb1 + (tb1 >> 8)) >> 11));
1297 /* This version correspond to the result we get with XRENDER -
1298 * a bit of precision is lost since we convert to 8 bit after premultiplying
1299 * instead of at the end
1301 guint tr2, tg2, tb2;
1302 guint tr3, tg3, tb3;
1304 tr = (tmp & 0xf800);
1305 tr1 = (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1306 tr2 = a * p[0] + 0x80;
1307 tr3 = ((tr1 + (tr1 >> 8)) >> 8) + ((tr2 + (tr2 >> 8)) >> 8);
1309 tg = (tmp & 0x07e0);
1310 tg1 = (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1311 tg2 = a * p[0] + 0x80;
1312 tg3 = ((tg1 + (tg1 >> 8)) >> 8) + ((tg2 + (tg2 >> 8)) >> 8);
1314 tb = (tmp & 0x001f);
1315 tb1 = (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1316 tb2 = a * p[0] + 0x80;
1317 tb3 = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
1319 *q = (((tr3 & 0xf8) << 8) |
1320 ((tg3 & 0xfc) << 3) |
1328 src += src_rowstride;
1329 dest += dest_rowstride;
1333 /* Implementation of the old vfunc in terms of the new one
1334 in case someone calls it directly (which they shouldn't!) */
1336 gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
1346 GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable,
1359 gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable,
1368 GdkRgbDither dither,
1372 GdkPixbuf *composited = NULL;
1373 gint dwidth, dheight;
1376 GdkRectangle tmp_rect;
1377 GdkDrawable *real_drawable;
1379 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1380 g_return_if_fail (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
1381 g_return_if_fail (gdk_pixbuf_get_n_channels (pixbuf) == 3 ||
1382 gdk_pixbuf_get_n_channels (pixbuf) == 4);
1383 g_return_if_fail (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
1385 g_return_if_fail (drawable != NULL);
1388 width = gdk_pixbuf_get_width (pixbuf);
1390 height = gdk_pixbuf_get_height (pixbuf);
1392 g_return_if_fail (width >= 0 && height >= 0);
1393 g_return_if_fail (src_x >= 0 && src_x + width <= gdk_pixbuf_get_width (pixbuf));
1394 g_return_if_fail (src_y >= 0 && src_y + height <= gdk_pixbuf_get_height (pixbuf));
1396 /* Clip to the drawable; this is required for get_from_drawable() so
1397 * can't be done implicitly
1414 gdk_drawable_get_size (drawable, &dwidth, &dheight);
1416 if ((dest_x + width) > dwidth)
1417 width = dwidth - dest_x;
1419 if ((dest_y + height) > dheight)
1420 height = dheight - dest_y;
1422 if (width <= 0 || height <= 0)
1425 /* Clip to the clip region; this avoids getting more
1426 * image data from the server than we need to.
1429 tmp_rect.x = dest_x;
1430 tmp_rect.y = dest_y;
1431 tmp_rect.width = width;
1432 tmp_rect.height = height;
1434 drect = gdk_region_rectangle (&tmp_rect);
1435 clip = gdk_drawable_get_clip_region (drawable);
1437 gdk_region_intersect (drect, clip);
1439 gdk_region_get_clipbox (drect, &tmp_rect);
1441 gdk_region_destroy (drect);
1442 gdk_region_destroy (clip);
1444 if (tmp_rect.width == 0 ||
1445 tmp_rect.height == 0)
1450 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
1452 /* Drawable is a wrapper here, but at this time we
1453 have already retargeted the destination to any
1454 impl window and set the clip, so what we really
1455 want to do is draw directly on the impl, ignoring
1456 client side subwindows. We also use the impl
1457 in the pixmap target case to avoid resetting the
1458 already set clip on the GC. */
1459 if (GDK_IS_WINDOW (drawable))
1460 real_drawable = GDK_WINDOW_OBJECT (drawable)->impl;
1462 real_drawable = GDK_PIXMAP_OBJECT (drawable)->impl;
1464 if (gdk_pixbuf_get_has_alpha (pixbuf))
1466 GdkVisual *visual = gdk_drawable_get_visual (drawable);
1467 void (*composite_func) (guchar *src_buf,
1470 gint dest_rowstride,
1471 GdkByteOrder dest_byte_order,
1473 gint height) = NULL;
1475 /* First we see if we have a visual-specific composition function that can composite
1476 * the pixbuf data directly onto the image
1480 gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
1483 if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
1484 visual->depth == 16 &&
1485 visual->red_mask == 0xf800 &&
1486 visual->green_mask == 0x07e0 &&
1487 visual->blue_mask == 0x001f)
1488 composite_func = composite_565;
1489 else if (visual->depth == 24 && bits_per_pixel == 32 &&
1490 visual->red_mask == 0xff0000 &&
1491 visual->green_mask == 0x00ff00 &&
1492 visual->blue_mask == 0x0000ff)
1495 if (_gdk_use_medialib ())
1496 composite_func = composite_0888_medialib;
1498 composite_func = composite_0888;
1500 composite_func = composite_0888;
1505 /* We can't use our composite func if we are required to dither
1507 if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
1510 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1512 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1513 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1517 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1519 GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
1521 gdk_drawable_get_depth (drawable), &xs0, &ys0);
1523 gdk_drawable_copy_to_image (drawable, image,
1524 dest_x + x0, dest_y + y0,
1527 (*composite_func) (gdk_pixbuf_get_pixels (pixbuf) + (src_y + y0) * gdk_pixbuf_get_rowstride (pixbuf) + (src_x + x0) * 4,
1528 gdk_pixbuf_get_rowstride (pixbuf),
1529 (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
1533 gdk_draw_image (real_drawable, gc, image,
1535 dest_x + x0, dest_y + y0,
1544 /* No special composition func, convert dest to 24 bit RGB data, composite against
1545 * that, and convert back.
1547 composited = gdk_pixbuf_get_from_drawable (NULL,
1555 composite (gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4,
1556 gdk_pixbuf_get_rowstride (pixbuf),
1557 gdk_pixbuf_get_pixels (composited),
1558 gdk_pixbuf_get_rowstride (composited),
1567 pixbuf = composited;
1570 if (gdk_pixbuf_get_n_channels (pixbuf) == 4)
1572 guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4;
1574 gdk_draw_rgb_32_image_dithalign (real_drawable, gc,
1578 buf, gdk_pixbuf_get_rowstride (pixbuf),
1579 x_dither, y_dither);
1581 else /* n_channels == 3 */
1583 guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 3;
1585 gdk_draw_rgb_image_dithalign (real_drawable, gc,
1589 buf, gdk_pixbuf_get_rowstride (pixbuf),
1590 x_dither, y_dither);
1595 g_object_unref (composited);
1598 /************************************************************************/
1601 * _gdk_drawable_get_scratch_gc:
1602 * @drawable: A #GdkDrawable
1603 * @graphics_exposures: Whether the returned #GdkGC should generate graphics exposures
1605 * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
1606 * the standard values for @drawable, except for the graphics_exposures
1607 * field which is determined by the @graphics_exposures parameter.
1609 * The foreground color of the returned #GdkGC is undefined. The #GdkGC
1610 * must not be altered in any way, except to change its foreground color.
1612 * Return value: A #GdkGC suitable for drawing on @drawable
1617 _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
1618 gboolean graphics_exposures)
1623 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1625 screen = gdk_drawable_get_screen (drawable);
1627 g_return_val_if_fail (!screen->closed, NULL);
1629 depth = gdk_drawable_get_depth (drawable) - 1;
1631 if (graphics_exposures)
1633 if (!screen->exposure_gcs[depth])
1636 GdkGCValuesMask mask;
1638 values.graphics_exposures = TRUE;
1639 mask = GDK_GC_EXPOSURES;
1641 screen->exposure_gcs[depth] =
1642 gdk_gc_new_with_values (drawable, &values, mask);
1645 return screen->exposure_gcs[depth];
1649 if (!screen->normal_gcs[depth])
1651 screen->normal_gcs[depth] =
1652 gdk_gc_new (drawable);
1655 return screen->normal_gcs[depth];
1660 * _gdk_drawable_get_subwindow_scratch_gc:
1661 * @drawable: A #GdkDrawable
1663 * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
1664 * the standard values for @drawable, except for the graphics_exposures
1665 * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
1667 * The foreground color of the returned #GdkGC is undefined. The #GdkGC
1668 * must not be altered in any way, except to change its foreground color.
1670 * Return value: A #GdkGC suitable for drawing on @drawable
1675 _gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
1680 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1682 screen = gdk_drawable_get_screen (drawable);
1684 g_return_val_if_fail (!screen->closed, NULL);
1686 depth = gdk_drawable_get_depth (drawable) - 1;
1688 if (!screen->subwindow_gcs[depth])
1691 GdkGCValuesMask mask;
1693 values.graphics_exposures = TRUE;
1694 values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1695 mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;
1697 screen->subwindow_gcs[depth] =
1698 gdk_gc_new_with_values (drawable, &values, mask);
1701 return screen->subwindow_gcs[depth];
1706 * _gdk_drawable_get_source_drawable:
1707 * @drawable: a #GdkDrawable
1709 * Returns a drawable for the passed @drawable that is guaranteed to be
1710 * usable to create a pixmap (e.g.: not an offscreen window).
1715 _gdk_drawable_get_source_drawable (GdkDrawable *drawable)
1717 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1719 if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
1720 return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
1726 _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
1730 return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,
1735 #define __GDK_DRAW_C__
1736 #include "gdkaliasdef.c"