]> Pileus Git - ~andy/gtk/blob - gdk/gdkdraw.c
Fix for #119555, Peter Zelesny:
[~andy/gtk] / gdk / gdkdraw.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "gdkdrawable.h"
28 #include "gdkinternals.h"
29 #include "gdkwindow.h"
30 #include "gdkscreen.h"
31 #include "gdk-pixbuf-private.h"
32 #include "gdkpixbuf.h"
33
34 static GdkImage*    gdk_drawable_real_get_image (GdkDrawable     *drawable,
35                                                  gint             x,
36                                                  gint             y,
37                                                  gint             width,
38                                                  gint             height);
39 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable  *drawable,
40                                                               gint          x,
41                                                               gint          y,
42                                                               gint          width,
43                                                               gint          height,
44                                                               gint         *composite_x_offset,
45                                                               gint         *composite_y_offset);
46 static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable  *drawable);
47 static void         gdk_drawable_real_draw_pixbuf            (GdkDrawable  *drawable,
48                                                               GdkGC        *gc,
49                                                               GdkPixbuf    *pixbuf,
50                                                               gint          src_x,
51                                                               gint          src_y,
52                                                               gint          dest_x,
53                                                               gint          dest_y,
54                                                               gint          width,
55                                                               gint          height,
56                                                               GdkRgbDither  dither,
57                                                               gint          x_dither,
58                                                               gint          y_dither);
59
60 static void gdk_drawable_class_init (GdkDrawableClass *klass);
61
62 GType
63 gdk_drawable_get_type (void)
64 {
65   static GType object_type = 0;
66
67   if (!object_type)
68     {
69       static const GTypeInfo object_info =
70       {
71         sizeof (GdkDrawableClass),
72         (GBaseInitFunc) NULL,
73         (GBaseFinalizeFunc) NULL,
74         (GClassInitFunc) gdk_drawable_class_init,
75         NULL,           /* class_finalize */
76         NULL,           /* class_data */
77         sizeof (GdkDrawable),
78         0,              /* n_preallocs */
79         (GInstanceInitFunc) NULL,
80       };
81       
82       object_type = g_type_register_static (G_TYPE_OBJECT,
83                                             "GdkDrawable",
84                                             &object_info, 
85                                             G_TYPE_FLAG_ABSTRACT);
86     }  
87
88   return object_type;
89 }
90
91 static void
92 gdk_drawable_class_init (GdkDrawableClass *klass)
93 {
94   klass->get_image = gdk_drawable_real_get_image;
95   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
96   /* Default implementation for clip and visible region is the same */
97   klass->get_clip_region = gdk_drawable_real_get_visible_region;
98   klass->get_visible_region = gdk_drawable_real_get_visible_region;
99   klass->draw_pixbuf = gdk_drawable_real_draw_pixbuf;
100 }
101
102 /* Manipulation of drawables
103  */
104
105 /**
106  * gdk_drawable_set_data:
107  * @drawable: a #GdkDrawable
108  * @key: name to store the data under
109  * @data: arbitrary data
110  * @destroy_func: function to free @data, or %NULL
111  *
112  * This function is equivalent to g_object_set_data(),
113  * the #GObject variant should be used instead.
114  * 
115  **/
116 void          
117 gdk_drawable_set_data (GdkDrawable   *drawable,
118                        const gchar   *key,
119                        gpointer       data,
120                        GDestroyNotify destroy_func)
121 {
122   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
123   
124   g_object_set_qdata_full (G_OBJECT (drawable),
125                            g_quark_from_string (key),
126                            data,
127                            destroy_func);
128 }
129
130 /**
131  * gdk_drawable_get_data:
132  * @drawable: a #GdkDrawable
133  * @key: name the data was stored under
134  * 
135  * Equivalent to g_object_get_data(); the #GObject variant should be
136  * used instead.
137  * 
138  * Return value: the data stored at @key
139  **/
140 gpointer
141 gdk_drawable_get_data (GdkDrawable   *drawable,
142                        const gchar   *key)
143 {
144   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
145   
146   return g_object_get_qdata (G_OBJECT (drawable),
147                              g_quark_try_string (key));
148 }
149
150 /**
151  * gdk_drawable_get_size:
152  * @drawable: a #GdkDrawable
153  * @width: location to store drawable's width, or %NULL
154  * @height: location to store drawable's height, or %NULL
155  *
156  * Fills *@width and *@height with the size of @drawable.
157  * @width or @height can be %NULL if you only want the other one.
158  * 
159  * On the X11 platform, if @drawable is a #GdkWindow, the returned
160  * size is the size reported in the most-recently-processed configure
161  * event, rather than the current size on the X server.
162  * 
163  **/
164 void
165 gdk_drawable_get_size (GdkDrawable *drawable,
166                        gint        *width,
167                        gint        *height)
168 {
169   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
170
171   GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);  
172 }
173
174 /**
175  * gdk_drawable_get_visual:
176  * @drawable: a #GdkDrawable
177  * 
178  * Gets the #GdkVisual describing the pixel format of @drawable.
179  * 
180  * Return value: a #GdkVisual
181  **/
182 GdkVisual*
183 gdk_drawable_get_visual (GdkDrawable *drawable)
184 {
185   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
186   
187   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
188 }
189
190 /**
191  * gdk_drawable_get_depth:
192  * @drawable: a #GdkDrawable
193  * 
194  * Obtains the bit depth of the drawable, that is, the number of bits
195  * that make up a pixel in the drawable's visual. Examples are 8 bits
196  * per pixel, 24 bits per pixel, etc.
197  * 
198  * Return value: number of bits per pixel
199  **/
200 gint
201 gdk_drawable_get_depth (GdkDrawable *drawable)
202 {
203   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
204
205   return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
206 }
207 /**
208  * gdk_drawable_get_screen:
209  * @drawable: a #GdkDrawable
210  * 
211  * Gets the #GdkScreen associated with a #GdkDrawable.
212  * 
213  * Return value: the #GdkScreen associated with @drawable
214  *
215  * Since: 2.2
216  **/
217 GdkScreen*
218 gdk_drawable_get_screen(GdkDrawable *drawable)
219 {
220   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
221
222   return GDK_DRAWABLE_GET_CLASS (drawable)->get_screen (drawable);
223 }
224
225 /**
226  * gdk_drawable_get_display:
227  * @drawable: a #GdkDrawable
228  * 
229  * Gets the #GdkDisplay associated with a #GdkDrawable.
230  * 
231  * Return value: the #GdkDisplay associated with @drawable
232  *
233  * Since: 2.2
234  **/
235 GdkDisplay*
236 gdk_drawable_get_display (GdkDrawable *drawable)
237 {
238   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
239   
240   return gdk_screen_get_display (gdk_drawable_get_screen (drawable));
241 }
242         
243 /**
244  * gdk_drawable_set_colormap:
245  * @drawable: a #GdkDrawable
246  * @colormap: a #GdkColormap
247  *
248  * Sets the colormap associated with @drawable. Normally this will
249  * happen automatically when the drawable is created; you only need to
250  * use this function if the drawable-creating function did not have a
251  * way to determine the colormap, and you then use drawable operations
252  * that require a colormap. The colormap for all drawables and
253  * graphics contexts you intend to use together should match. i.e.
254  * when using a #GdkGC to draw to a drawable, or copying one drawable
255  * to another, the colormaps should match.
256  * 
257  **/
258 void
259 gdk_drawable_set_colormap (GdkDrawable *drawable,
260                            GdkColormap *cmap)
261 {
262   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
263   g_return_if_fail (cmap == NULL || gdk_drawable_get_depth (drawable)
264                     == cmap->visual->depth);
265
266   GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
267 }
268
269 /**
270  * gdk_drawable_get_colormap:
271  * @drawable: a #GdkDrawable
272  * 
273  * Gets the colormap for @drawable, if one is set; returns
274  * %NULL otherwise.
275  * 
276  * Return value: the colormap, or %NULL
277  **/
278 GdkColormap*
279 gdk_drawable_get_colormap (GdkDrawable *drawable)
280 {
281   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
282
283   return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
284 }
285
286 /**
287  * gdk_drawable_ref:
288  * @drawable: a #GdkDrawable
289  * 
290  * Deprecated equivalent of calling g_object_ref() on @drawable.
291  * (Drawables were not objects in previous versions of GDK.)
292  * 
293  * Return value: the same @drawable passed in
294  **/
295 GdkDrawable*
296 gdk_drawable_ref (GdkDrawable *drawable)
297 {
298   return (GdkDrawable *) g_object_ref (drawable);
299 }
300
301 /**
302  * gdk_drawable_unref:
303  * @drawable: a #GdkDrawable
304  * 
305  * Deprecated equivalent of calling g_object_unref() on @drawable.
306  * 
307  **/
308 void
309 gdk_drawable_unref (GdkDrawable *drawable)
310 {
311   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
312
313   g_object_unref (drawable);
314 }
315
316 /* Drawing
317  */
318
319 /**
320  * gdk_draw_point:
321  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
322  * @gc: a #GdkGC.
323  * @x: the x coordinate of the point.
324  * @y: the y coordinate of the point.
325  * 
326  * Draws a point, using the foreground color and other attributes of 
327  * the #GdkGC.
328  **/
329 void
330 gdk_draw_point (GdkDrawable *drawable,
331                 GdkGC       *gc,
332                 gint         x,
333                 gint         y)
334 {
335   GdkPoint point;
336
337   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
338   g_return_if_fail (GDK_IS_GC (gc));
339
340   point.x = x;
341   point.y = y;
342   
343   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1);
344 }
345
346 /**
347  * gdk_draw_line:
348  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap). 
349  * @gc: a #GdkGC.
350  * @x1_: the x coordinate of the start point.
351  * @y1_: the y coordinate of the start point.
352  * @x2_: the x coordinate of the end point.
353  * @y2_: the y coordinate of the end point.
354  * 
355  * Draws a line, using the foreground color and other attributes of 
356  * the #GdkGC.
357  **/
358 void
359 gdk_draw_line (GdkDrawable *drawable,
360                GdkGC       *gc,
361                gint         x1,
362                gint         y1,
363                gint         x2,
364                gint         y2)
365 {
366   GdkSegment segment;
367
368   g_return_if_fail (drawable != NULL);
369   g_return_if_fail (gc != NULL);
370   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
371   g_return_if_fail (GDK_IS_GC (gc));
372
373   segment.x1 = x1;
374   segment.y1 = y1;
375   segment.x2 = x2;
376   segment.y2 = y2;
377   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, &segment, 1);
378 }
379
380 /**
381  * gdk_draw_rectangle:
382  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
383  * @gc: a #GdkGC.
384  * @filled: %TRUE if the rectangle should be filled.
385  * @x: the x coordinate of the left edge of the rectangle.
386  * @y: the y coordinate of the top edge of the rectangle.
387  * @width: the width of the rectangle.
388  * @height: the height of the rectangle.
389  * 
390  * Draws a rectangular outline or filled rectangle, using the foreground color
391  * and other attributes of the #GdkGC.
392  *
393  * A rectangle drawn filled is 1 pixel smaller in both dimensions than a 
394  * rectangle outlined. Calling 
395  * <literal>gdk_draw_rectangle (window, gc, TRUE, 0, 0, 20, 20)</literal> 
396  * results in a filled rectangle 20 pixels wide and 20 pixels high. Calling
397  * <literal>gdk_draw_rectangle (window, gc, FALSE, 0, 0, 20, 20)</literal> 
398  * results in an outlined rectangle with corners at (0, 0), (0, 20), (20, 20),
399  * and (20, 0), which makes it 21 pixels wide and 21 pixels high.
400  **/
401 void
402 gdk_draw_rectangle (GdkDrawable *drawable,
403                     GdkGC       *gc,
404                     gboolean     filled,
405                     gint         x,
406                     gint         y,
407                     gint         width,
408                     gint         height)
409 {  
410   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
411   g_return_if_fail (GDK_IS_GC (gc));
412
413   if (width < 0 || height < 0)
414     {
415       gint real_width;
416       gint real_height;
417       
418       gdk_drawable_get_size (drawable, &real_width, &real_height);
419
420       if (width < 0)
421         width = real_width;
422       if (height < 0)
423         height = real_height;
424     }
425
426   GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y,
427                                                      width, height);
428 }
429
430 /**
431  * gdk_draw_arc:
432  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
433  * @gc: a #GdkGC.
434  * @filled: %TRUE if the arc should be filled, producing a 'pie slice'.
435  * @x: the x coordinate of the left edge of the bounding rectangle.
436  * @y: the y coordinate of the top edge of the bounding rectangle.
437  * @width: the width of the bounding rectangle.
438  * @height: the height of the bounding rectangle.
439  * @angle1: the start angle of the arc, relative to the 3 o'clock position,
440  *     counter-clockwise, in 1/64ths of a degree.
441  * @angle2: the end angle of the arc, relative to @angle1, in 1/64ths 
442  *     of a degree.
443  * 
444  * Draws an arc or a filled 'pie slice'. The arc is defined by the bounding
445  * rectangle of the entire ellipse, and the start and end angles of the part 
446  * of the ellipse to be drawn.
447  **/
448 void
449 gdk_draw_arc (GdkDrawable *drawable,
450               GdkGC       *gc,
451               gboolean     filled,
452               gint         x,
453               gint         y,
454               gint         width,
455               gint         height,
456               gint         angle1,
457               gint         angle2)
458 {  
459   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
460   g_return_if_fail (GDK_IS_GC (gc));
461
462   if (width < 0 || height < 0)
463     {
464       gint real_width;
465       gint real_height;
466       
467       gdk_drawable_get_size (drawable, &real_width, &real_height);
468
469       if (width < 0)
470         width = real_width;
471       if (height < 0)
472         height = real_height;
473     }
474
475   GDK_DRAWABLE_GET_CLASS (drawable)->draw_arc (drawable, gc, filled,
476                                                x, y, width, height, angle1, angle2);
477 }
478
479 /**
480  * gdk_draw_polygon:
481  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
482  * @gc: a #GdkGC.
483  * @filled: %TRUE if the polygon should be filled. The polygon is closed
484  *     automatically, connecting the last point to the first point if 
485  *     necessary.
486  * @points: an array of #GdkPoint structures specifying the points making 
487  *     up the polygon.
488  * @npoints: the number of points.
489  * 
490  * Draws an outlined or filled polygon.
491  **/
492 void
493 gdk_draw_polygon (GdkDrawable *drawable,
494                   GdkGC       *gc,
495                   gboolean     filled,
496                   GdkPoint    *points,
497                   gint         npoints)
498 {
499   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
500   g_return_if_fail (GDK_IS_GC (gc));
501
502   GDK_DRAWABLE_GET_CLASS (drawable)->draw_polygon (drawable, gc, filled,
503                                                    points, npoints);
504 }
505
506 /* gdk_draw_string
507  *
508  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
509  *
510  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
511  */
512 /**
513  * gdk_draw_string:
514  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
515  * @font: a #GdkFont.
516  * @gc: a #GdkGC.
517  * @x: the x coordinate of the left edge of the text.
518  * @y: the y coordinate of the baseline of the text.
519  * @string:  the string of characters to draw.
520  * 
521  * Draws a string of characters in the given font or fontset.
522  * 
523  * Deprecated: Use gdk_draw_layout() instead.
524  **/
525 void
526 gdk_draw_string (GdkDrawable *drawable,
527                  GdkFont     *font,
528                  GdkGC       *gc,
529                  gint         x,
530                  gint         y,
531                  const gchar *string)
532 {
533   gdk_draw_text (drawable, font, gc, x, y, string, _gdk_font_strlen (font, string));
534 }
535
536 /* gdk_draw_text
537  *
538  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
539  *
540  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
541  */
542 /**
543  * gdk_draw_text:
544  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
545  * @font: a #GdkFont.
546  * @gc: a #GdkGC.
547  * @x: the x coordinate of the left edge of the text.
548  * @y: the y coordinate of the baseline of the text.
549  * @text:  the characters to draw.
550  * @text_length: the number of characters of @text to draw.
551  * 
552  * Draws a number of characters in the given font or fontset.
553  *
554  * Deprecated: Use gdk_draw_layout() instead.
555  **/
556 void
557 gdk_draw_text (GdkDrawable *drawable,
558                GdkFont     *font,
559                GdkGC       *gc,
560                gint         x,
561                gint         y,
562                const gchar *text,
563                gint         text_length)
564 {
565   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
566   g_return_if_fail (font != NULL);
567   g_return_if_fail (GDK_IS_GC (gc));
568   g_return_if_fail (text != NULL);
569
570   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text (drawable, font, gc, x, y, text, text_length);
571 }
572
573 /**
574  * gdk_draw_text_wc:
575  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
576  * @font: a #GdkFont.
577  * @gc: a #GdkGC.
578  * @x: the x coordinate of the left edge of the text.
579  * @y: the y coordinate of the baseline of the text.
580  * @text: the wide characters to draw.
581  * @text_length: the number of characters to draw.
582  * 
583  * Draws a number of wide characters using the given font of fontset.
584  * If the font is a 1-byte font, the string is converted into 1-byte 
585  * characters (discarding the high bytes) before output.
586  * 
587  * Deprecated: Use gdk_draw_layout() instead.
588  **/
589 void
590 gdk_draw_text_wc (GdkDrawable    *drawable,
591                   GdkFont        *font,
592                   GdkGC          *gc,
593                   gint            x,
594                   gint            y,
595                   const GdkWChar *text,
596                   gint            text_length)
597 {
598   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
599   g_return_if_fail (font != NULL);
600   g_return_if_fail (GDK_IS_GC (gc));
601   g_return_if_fail (text != NULL);
602
603   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text_wc (drawable, font, gc, x, y, text, text_length);
604 }
605
606 /**
607  * gdk_draw_drawable:
608  * @drawable: a #GdkDrawable
609  * @gc: a #GdkGC sharing the drawable's visual and colormap
610  * @src: another #GdkDrawable
611  * @xsrc: X position in @src of rectangle to draw
612  * @ysrc: Y position in @src of rectangle to draw
613  * @xdest: X position in @drawable where the rectangle should be drawn
614  * @ydest: Y position in @drawable where the rectangle should be drawn
615  * @width: width of rectangle to draw, or -1 for entire @src width
616  * @height: height of rectangle to draw, or -1 for entire @src height
617  *
618  * Copies the @width x @height region of @src at coordinates (@xsrc,
619  * @ysrc) to coordinates (@xdest, @ydest) in @drawable.
620  * @width and/or @height may be given as -1, in which case the entire
621  * @src drawable will be copied.
622  *
623  * Most fields in @gc are not used for this operation, but notably the
624  * clip mask or clip region will be honored.
625  *
626  * The source and destination drawables must have the same visual and
627  * colormap, or errors will result. (On X11, failure to match
628  * visual/colormap results in a BadMatch error from the X server.)
629  * A common cause of this problem is an attempt to draw a bitmap to
630  * a color drawable. The way to draw a bitmap is to set the
631  * bitmap as a clip mask on your #GdkGC, then use gdk_draw_rectangle()
632  * to draw a rectangle clipped to the bitmap.
633  **/
634 void
635 gdk_draw_drawable (GdkDrawable *drawable,
636                    GdkGC       *gc,
637                    GdkDrawable *src,
638                    gint         xsrc,
639                    gint         ysrc,
640                    gint         xdest,
641                    gint         ydest,
642                    gint         width,
643                    gint         height)
644 {
645   GdkDrawable *composite;
646   gint composite_x_offset = 0;
647   gint composite_y_offset = 0;
648
649   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
650   g_return_if_fail (src != NULL);
651   g_return_if_fail (GDK_IS_GC (gc));
652
653   if (width < 0 || height < 0)
654     {
655       gint real_width;
656       gint real_height;
657       
658       gdk_drawable_get_size (src, &real_width, &real_height);
659
660       if (width < 0)
661         width = real_width;
662       if (height < 0)
663         height = real_height;
664     }
665
666
667   composite =
668     GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
669                                                           xsrc, ysrc,
670                                                           width, height,
671                                                           &composite_x_offset,
672                                                           &composite_y_offset);
673
674   
675   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
676                                                     xsrc - composite_x_offset,
677                                                     ysrc - composite_y_offset,
678                                                     xdest, ydest,
679                                                     width, height);
680   
681   g_object_unref (composite);
682 }
683
684 /**
685  * gdk_draw_image:
686  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
687  * @gc: a #GdkGC.
688  * @image: the #GdkImage to draw.
689  * @xsrc: the left edge of the source rectangle within @image.
690  * @ysrc: the top of the source rectangle within @image.
691  * @xdest: the x coordinate of the destination within @drawable.
692  * @ydest: the y coordinate of the destination within @drawable.
693  * @width: the width of the area to be copied, or -1 to make the area 
694  *     extend to the right edge of @image.
695  * @height: the height of the area to be copied, or -1 to make the area 
696  *     extend to the bottom edge of @image.
697  * 
698  * Draws a #GdkImage onto a drawable.
699  * The depth of the #GdkImage must match the depth of the #GdkDrawable.
700  **/
701 void
702 gdk_draw_image (GdkDrawable *drawable,
703                 GdkGC       *gc,
704                 GdkImage    *image,
705                 gint         xsrc,
706                 gint         ysrc,
707                 gint         xdest,
708                 gint         ydest,
709                 gint         width,
710                 gint         height)
711 {
712   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
713   g_return_if_fail (image != NULL);
714   g_return_if_fail (GDK_IS_GC (gc));
715
716   if (width == -1)
717     width = image->width;
718   if (height == -1)
719     height = image->height;
720
721   GDK_DRAWABLE_GET_CLASS (drawable)->draw_image (drawable, gc, image, xsrc, ysrc,
722                                                  xdest, ydest, width, height);
723 }
724
725 /**
726  * gdk_draw_pixbuf:
727  * @drawable: Destination drawable.
728  * @gc: a #GdkGC, used for clipping, or %NULL
729  * @pixbuf: a #GdkPixbuf
730  * @src_x: Source X coordinate within pixbuf.
731  * @src_y: Source Y coordinates within pixbuf.
732  * @dest_x: Destination X coordinate within drawable.
733  * @dest_y: Destination Y coordinate within drawable.
734  * @width: Width of region to render, in pixels, or -1 to use pixbuf width.
735  * @height: Height of region to render, in pixels, or -1 to use pixbuf height.
736  * @dither: Dithering mode for #GdkRGB.
737  * @x_dither: X offset for dither.
738  * @y_dither: Y offset for dither.
739  * 
740  * Renders a rectangular portion of a pixbuf to a drawable.  The destination
741  * drawable must have a colormap. All windows have a colormap, however, pixmaps
742  * only have colormap by default if they were created with a non-%NULL window 
743  * argument. Otherwise a colormap must be set on them with 
744  * gdk_drawable_set_colormap().
745  *
746  * On older X servers, rendering pixbufs with an alpha channel involves round 
747  * trips to the X server, and may be somewhat slow.
748  *
749  * Since: 2.2
750  **/
751 void
752 gdk_draw_pixbuf (GdkDrawable     *drawable,
753                   GdkGC           *gc,
754                   GdkPixbuf       *pixbuf,
755                   gint             src_x,
756                   gint             src_y,
757                   gint             dest_x,
758                   gint             dest_y,
759                   gint             width,
760                   gint             height,
761                   GdkRgbDither     dither,
762                   gint             x_dither,
763                   gint             y_dither)
764 {
765   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
766   g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
767   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
768
769   if (width == -1)
770     width = gdk_pixbuf_get_width (pixbuf);
771   if (height == -1)
772     height = gdk_pixbuf_get_height (pixbuf);
773
774   GDK_DRAWABLE_GET_CLASS (drawable)->draw_pixbuf (drawable, gc, pixbuf,
775                                                   src_x, src_y, dest_x, dest_y, width, height,
776                                                   dither, x_dither, y_dither);
777 }
778
779 /**
780  * gdk_draw_points:
781  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
782  * @gc: a #GdkGC.
783  * @points: an array of #GdkPoint structures.
784  * @npoints: the number of points to be drawn.
785  * 
786  * Draws a number of points, using the foreground color and other 
787  * attributes of the #GdkGC.
788  **/
789 void
790 gdk_draw_points (GdkDrawable *drawable,
791                  GdkGC       *gc,
792                  GdkPoint    *points,
793                  gint         npoints)
794 {
795   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
796   g_return_if_fail ((points != NULL) && (npoints > 0));
797   g_return_if_fail (GDK_IS_GC (gc));
798   g_return_if_fail (npoints >= 0);
799
800   if (npoints == 0)
801     return;
802
803   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, points, npoints);
804 }
805
806 /**
807  * gdk_draw_segments:
808  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
809  * @gc: a #GdkGC.
810  * @segs: an array of #GdkSegment structures specifying the start and 
811  *   end points of the lines to be drawn.
812  * @nsegs: the number of line segments to draw, i.e. the size of the 
813  *   @segs array.
814  * 
815  * Draws a number of unconnected lines.
816  **/
817 void
818 gdk_draw_segments (GdkDrawable *drawable,
819                    GdkGC       *gc,
820                    GdkSegment  *segs,
821                    gint         nsegs)
822 {
823   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
824
825   if (nsegs == 0)
826     return;
827
828   g_return_if_fail (segs != NULL);
829   g_return_if_fail (GDK_IS_GC (gc));
830   g_return_if_fail (nsegs >= 0);
831
832   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, segs, nsegs);
833 }
834
835 /**
836  * gdk_draw_lines:
837  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
838  * @gc: a #GdkGC.
839  * @points: an array of #GdkPoint structures specifying the endpoints of the
840  * @npoints: the size of the @points array.
841  * 
842  * Draws a series of lines connecting the given points.
843  * The way in which joins between lines are draw is determined by the
844  * #GdkCapStyle value in the #GdkGC. This can be set with
845  * gdk_gc_set_line_attributes().
846  **/
847 void
848 gdk_draw_lines (GdkDrawable *drawable,
849                 GdkGC       *gc,
850                 GdkPoint    *points,
851                 gint         npoints)
852 {
853   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
854   g_return_if_fail (points != NULL);
855   g_return_if_fail (GDK_IS_GC (gc));
856   g_return_if_fail (npoints >= 0);
857
858   if (npoints == 0)
859     return;
860
861   GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc, points, npoints);
862 }
863
864 /**
865  * gdk_draw_glyphs:
866  * @drawable: a #GdkDrawable
867  * @gc: a #GdkGC
868  * @font: font to be used
869  * @x: X coordinate of baseline origin
870  * @y: Y coordinate of baseline origin
871  * @glyphs: glyphs to render
872  *
873  * This is a low-level function; 99% of text rendering should be done
874  * using gdk_draw_layout() instead.
875  *
876  * A glyph is a character in a font. This function draws a sequence of
877  * glyphs.  To obtain a sequence of glyphs you have to understand a
878  * lot about internationalized text handling, which you don't want to
879  * understand; thus, use gdk_draw_layout() instead of this function,
880  * gdk_draw_layout() handles the details.
881  * 
882  **/
883 void
884 gdk_draw_glyphs (GdkDrawable      *drawable,
885                  GdkGC            *gc,
886                  PangoFont        *font,
887                  gint              x,
888                  gint              y,
889                  PangoGlyphString *glyphs)
890 {
891   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
892   g_return_if_fail (GDK_IS_GC (gc));
893
894
895   GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs);
896 }
897
898
899 /**
900  * gdk_drawable_copy_to_image:
901  * @drawable: a #GdkDrawable
902  * @image: a #GdkDrawable, or %NULL if a new @image should be created.
903  * @src_x: x coordinate on @drawable
904  * @src_y: y coordinate on @drawable
905  * @dest_x: x coordinate within @image. Must be 0 if @image is %NULL
906  * @dest_y: y coordinate within @image. Must be 0 if @image is %NULL
907  * @width: width of region to get
908  * @height: height or region to get
909  *
910  * Copies a portion of @drawable into the client side image structure
911  * @image. If @image is %NULL, creates a new image of size @width x @height
912  * and copies into that. See gdk_drawable_get_image() for further details.
913  * 
914  * Return value: @image, or a new a #GdkImage containing the contents
915  *               of @drawable
916  * 
917  * Since: 2.4
918  **/
919 GdkImage*
920 gdk_drawable_copy_to_image (GdkDrawable *drawable,
921                             GdkImage    *image,
922                             gint         src_x,
923                             gint         src_y,
924                             gint         dest_x,
925                             gint         dest_y,
926                             gint         width,
927                             gint         height)
928 {
929   GdkDrawable *composite;
930   gint composite_x_offset = 0;
931   gint composite_y_offset = 0;
932   GdkImage *retval;
933   GdkColormap *cmap;
934   
935   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
936   g_return_val_if_fail (src_x >= 0, NULL);
937   g_return_val_if_fail (src_y >= 0, NULL);
938
939   /* FIXME? Note race condition since we get the size then
940    * get the image, and the size may have changed.
941    */
942   
943   if (width < 0 || height < 0)
944     gdk_drawable_get_size (drawable,
945                            width < 0 ? &width : NULL,
946                            height < 0 ? &height : NULL);
947   
948   composite =
949     GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
950                                                                src_x, src_y,
951                                                                width, height,
952                                                                &composite_x_offset,
953                                                                &composite_y_offset); 
954   
955   retval = GDK_DRAWABLE_GET_CLASS (composite)->_copy_to_image (composite,
956                                                                image,
957                                                                src_x - composite_x_offset,
958                                                                src_y - composite_y_offset,
959                                                                dest_x, dest_y,
960                                                                width, height);
961
962   g_object_unref (composite);
963
964   if (!image && retval)
965     {
966       cmap = gdk_drawable_get_colormap (drawable);
967       
968       if (cmap)
969         gdk_image_set_colormap (retval, cmap);
970     }
971   
972   return retval;
973 }
974
975 /**
976  * gdk_drawable_get_image:
977  * @drawable: a #GdkDrawable
978  * @x: x coordinate on @drawable
979  * @y: y coordinate on @drawable
980  * @width: width of region to get
981  * @height: height or region to get
982  * 
983  * A #GdkImage stores client-side image data (pixels). In contrast,
984  * #GdkPixmap and #GdkWindow are server-side
985  * objects. gdk_drawable_get_image() obtains the pixels from a
986  * server-side drawable as a client-side #GdkImage.  The format of a
987  * #GdkImage depends on the #GdkVisual of the current display, which
988  * makes manipulating #GdkImage extremely difficult; therefore, in
989  * most cases you should use gdk_pixbuf_get_from_drawable() instead of
990  * this lower-level function. A #GdkPixbuf contains image data in a
991  * canonicalized RGB format, rather than a display-dependent format.
992  * Of course, there's a convenience vs. speed tradeoff here, so you'll
993  * want to think about what makes sense for your application.
994  *
995  * @x, @y, @width, and @height define the region of @drawable to
996  * obtain as an image.
997  *
998  * You would usually copy image data to the client side if you intend
999  * to examine the values of individual pixels, for example to darken
1000  * an image or add a red tint. It would be prohibitively slow to
1001  * make a round-trip request to the windowing system for each pixel,
1002  * so instead you get all of them at once, modify them, then copy
1003  * them all back at once.
1004  *
1005  * If the X server or other windowing system backend is on the local
1006  * machine, this function may use shared memory to avoid copying
1007  * the image data.
1008  *
1009  * If the source drawable is a #GdkWindow and partially offscreen
1010  * or obscured, then the obscured portions of the returned image
1011  * will contain undefined data.
1012  * 
1013  * Return value: a #GdkImage containing the contents of @drawable
1014  **/
1015 GdkImage*
1016 gdk_drawable_get_image (GdkDrawable *drawable,
1017                         gint         x,
1018                         gint         y,
1019                         gint         width,
1020                         gint         height)
1021 {
1022   GdkDrawable *composite;
1023   gint composite_x_offset = 0;
1024   gint composite_y_offset = 0;
1025   GdkImage *retval;
1026   GdkColormap *cmap;
1027   
1028   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1029   g_return_val_if_fail (x >= 0, NULL);
1030   g_return_val_if_fail (y >= 0, NULL);
1031
1032   /* FIXME? Note race condition since we get the size then
1033    * get the image, and the size may have changed.
1034    */
1035   
1036   if (width < 0 || height < 0)
1037     gdk_drawable_get_size (drawable,
1038                            width < 0 ? &width : NULL,
1039                            height < 0 ? &height : NULL);
1040   
1041   composite =
1042     GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
1043                                                                x, y,
1044                                                                width, height,
1045                                                                &composite_x_offset,
1046                                                                &composite_y_offset); 
1047   
1048   retval = GDK_DRAWABLE_GET_CLASS (composite)->get_image (composite,
1049                                                           x - composite_x_offset,
1050                                                           y - composite_y_offset,
1051                                                           width, height);
1052
1053   g_object_unref (composite);
1054
1055   cmap = gdk_drawable_get_colormap (drawable);
1056   
1057   if (retval && cmap)
1058     gdk_image_set_colormap (retval, cmap);
1059   
1060   return retval;
1061 }
1062
1063 static GdkImage*
1064 gdk_drawable_real_get_image (GdkDrawable     *drawable,
1065                              gint             x,
1066                              gint             y,
1067                              gint             width,
1068                              gint             height)
1069 {
1070   return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
1071 }
1072
1073 static GdkDrawable*
1074 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
1075                                           gint         x,
1076                                           gint         y,
1077                                           gint         width,
1078                                           gint         height,
1079                                           gint        *composite_x_offset,
1080                                           gint        *composite_y_offset)
1081 {
1082   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1083
1084   *composite_x_offset = 0;
1085   *composite_y_offset = 0;
1086   
1087   return g_object_ref (drawable);
1088 }
1089
1090 /**
1091  * gdk_drawable_get_clip_region:
1092  * @drawable: a #GdkDrawable
1093  * 
1094  * Computes the region of a drawable that potentially can be written
1095  * to by drawing primitives. This region will not take into account
1096  * the clip region for the GC, and may also not take into account
1097  * other factors such as if the window is obscured by other windows,
1098  * but no area outside of this region will be affected by drawing
1099  * primitives.
1100  * 
1101  * Return value: a #GdkRegion. This must be freed with gdk_region_destroy()
1102  *               when you are done.
1103  **/
1104 GdkRegion *
1105 gdk_drawable_get_clip_region (GdkDrawable *drawable)
1106 {
1107   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1108
1109   return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
1110 }
1111
1112 /**
1113  * gdk_drawable_get_visible_region:
1114  * @drawable: 
1115  * 
1116  * Computes the region of a drawable that is potentially visible.
1117  * This does not necessarily take into account if the window is
1118  * obscured by other windows, but no area outside of this region
1119  * is visible.
1120  * 
1121  * Return value: a #GdkRegion. This must be freed with gdk_region_destroy()
1122  *               when you are done.
1123  **/
1124 GdkRegion *
1125 gdk_drawable_get_visible_region (GdkDrawable *drawable)
1126 {
1127   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1128
1129   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
1130 }
1131
1132 static GdkRegion *
1133 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
1134 {
1135   GdkRectangle rect;
1136
1137   rect.x = 0;
1138   rect.y = 0;
1139
1140   gdk_drawable_get_size (drawable, &rect.width, &rect.height);
1141
1142   return gdk_region_rectangle (&rect);
1143 }
1144
1145 static void
1146 composite (guchar *src_buf,
1147            gint    src_rowstride,
1148            guchar *dest_buf,
1149            gint    dest_rowstride,
1150            gint    width,
1151            gint    height)
1152 {
1153   guchar *src = src_buf;
1154   guchar *dest = dest_buf;
1155
1156   while (height--)
1157     {
1158       gint twidth = width;
1159       guchar *p = src;
1160       guchar *q = dest;
1161
1162       while (twidth--)
1163         {
1164           guchar a = p[3];
1165           guint t;
1166
1167           t = a * p[0] + (255 - a) * q[0] + 0x80;
1168           q[0] = (t + (t >> 8)) >> 8;
1169           t = a * p[1] + (255 - a) * q[1] + 0x80;
1170           q[1] = (t + (t >> 8)) >> 8;
1171           t = a * p[2] + (255 - a) * q[2] + 0x80;
1172           q[2] = (t + (t >> 8)) >> 8;
1173
1174           p += 4;
1175           q += 3;
1176         }
1177       
1178       src += src_rowstride;
1179       dest += dest_rowstride;
1180     }
1181 }
1182
1183 static void
1184 composite_0888 (guchar      *src_buf,
1185                 gint         src_rowstride,
1186                 guchar      *dest_buf,
1187                 gint         dest_rowstride,
1188                 GdkByteOrder dest_byte_order,
1189                 gint         width,
1190                 gint         height)
1191 {
1192   guchar *src = src_buf;
1193   guchar *dest = dest_buf;
1194
1195   while (height--)
1196     {
1197       gint twidth = width;
1198       guchar *p = src;
1199       guchar *q = dest;
1200
1201       if (dest_byte_order == GDK_LSB_FIRST)
1202         {
1203           while (twidth--)
1204             {
1205               guint t;
1206               
1207               t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
1208               q[0] = (t + (t >> 8)) >> 8;
1209               t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
1210               q[1] = (t + (t >> 8)) >> 8;
1211               t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
1212               q[2] = (t + (t >> 8)) >> 8;
1213               p += 4;
1214               q += 4;
1215             }
1216         }
1217       else
1218         {
1219           while (twidth--)
1220             {
1221               guint t;
1222               
1223               t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
1224               q[1] = (t + (t >> 8)) >> 8;
1225               t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
1226               q[2] = (t + (t >> 8)) >> 8;
1227               t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
1228               q[3] = (t + (t >> 8)) >> 8;
1229               p += 4;
1230               q += 4;
1231             }
1232         }
1233       
1234       src += src_rowstride;
1235       dest += dest_rowstride;
1236     }
1237 }
1238
1239 static void
1240 composite_565 (guchar      *src_buf,
1241                gint         src_rowstride,
1242                guchar      *dest_buf,
1243                gint         dest_rowstride,
1244                GdkByteOrder dest_byte_order,
1245                gint         width,
1246                gint         height)
1247 {
1248   guchar *src = src_buf;
1249   guchar *dest = dest_buf;
1250
1251   while (height--)
1252     {
1253       gint twidth = width;
1254       guchar *p = src;
1255       gushort *q = (gushort *)dest;
1256
1257       while (twidth--)
1258         {
1259           guchar a = p[3];
1260           guint tr, tg, tb;
1261           guint tr1, tg1, tb1;
1262           guint tmp = *q;
1263
1264 #if 1
1265           /* This is fast, and corresponds to what composite() above does
1266            * if we converted to 8-bit first.
1267            */
1268           tr = (tmp & 0xf800);
1269           tr1 = a * p[0] + (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1270           tg = (tmp & 0x07e0);
1271           tg1 = a * p[1] + (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1272           tb = (tmp & 0x001f);
1273           tb1 = a * p[2] + (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1274
1275           *q = (((tr1 + (tr1 >> 8)) & 0xf800) |
1276                 (((tg1 + (tg1 >> 8)) & 0xfc00) >> 5)  |
1277                 ((tb1 + (tb1 >> 8)) >> 11));
1278 #else
1279           /* This version correspond to the result we get with XRENDER -
1280            * a bit of precision is lost since we convert to 8 bit after premultiplying
1281            * instead of at the end
1282            */
1283           guint tr2, tg2, tb2;
1284           guint tr3, tg3, tb3;
1285           
1286           tr = (tmp & 0xf800);
1287           tr1 = (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1288           tr2 = a * p[0] + 0x80;
1289           tr3 = ((tr1 + (tr1 >> 8)) >> 8) + ((tr2 + (tr2 >> 8)) >> 8);
1290
1291           tg = (tmp & 0x07e0);
1292           tg1 = (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1293           tg2 = a * p[0] + 0x80;
1294           tg3 = ((tg1 + (tg1 >> 8)) >> 8) + ((tg2 + (tg2 >> 8)) >> 8);
1295
1296           tb = (tmp & 0x001f);
1297           tb1 = (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1298           tb2 = a * p[0] + 0x80;
1299           tb3 = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
1300
1301           *q = (((tr3 & 0xf8) << 8) |
1302                 ((tg3 & 0xfc) << 3) |
1303                 ((tb3 >> 3)));
1304 #endif
1305           
1306           p += 4;
1307           q++;
1308         }
1309       
1310       src += src_rowstride;
1311       dest += dest_rowstride;
1312     }
1313 }
1314
1315 static void
1316 gdk_drawable_real_draw_pixbuf (GdkDrawable  *drawable,
1317                                GdkGC        *gc,
1318                                GdkPixbuf    *pixbuf,
1319                                gint          src_x,
1320                                gint          src_y,
1321                                gint          dest_x,
1322                                gint          dest_y,
1323                                gint          width,
1324                                gint          height,
1325                                GdkRgbDither  dither,
1326                                gint          x_dither,
1327                                gint          y_dither)
1328 {
1329   gboolean free_gc = FALSE;
1330   GdkPixbuf *composited = NULL;
1331   gint dwidth, dheight;
1332   GdkRegion *clip;
1333   GdkRegion *drect;
1334   GdkRectangle tmp_rect;
1335                                        
1336   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1337   g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
1338   g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
1339   g_return_if_fail (pixbuf->bits_per_sample == 8);
1340
1341   g_return_if_fail (drawable != NULL);
1342
1343   if (width == -1) 
1344     width = pixbuf->width;
1345   if (height == -1)
1346     height = pixbuf->height;
1347
1348   g_return_if_fail (width >= 0 && height >= 0);
1349   g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
1350   g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
1351
1352   /* Clip to the drawable; this is required for get_from_drawable() so
1353    * can't be done implicitly
1354    */
1355   
1356   if (dest_x < 0)
1357     {
1358       src_x -= dest_x;
1359       width += dest_x;
1360       dest_x = 0;
1361     }
1362
1363   if (dest_y < 0)
1364     {
1365       src_y -= dest_y;
1366       height += dest_y;
1367       dest_y = 0;
1368     }
1369
1370   gdk_drawable_get_size (drawable, &dwidth, &dheight);
1371
1372   if ((dest_x + width) > dwidth)
1373     width = dwidth - dest_x;
1374
1375   if ((dest_y + height) > dheight)
1376     height = dheight - dest_y;
1377
1378   if (width <= 0 || height <= 0)
1379     return;
1380
1381   /* Clip to the clip region; this avoids getting more
1382    * image data from the server than we need to.
1383    */
1384   
1385   tmp_rect.x = dest_x;
1386   tmp_rect.y = dest_y;
1387   tmp_rect.width = width;
1388   tmp_rect.height = height;
1389
1390   drect = gdk_region_rectangle (&tmp_rect);
1391   clip = gdk_drawable_get_clip_region (drawable);
1392
1393   gdk_region_intersect (drect, clip);
1394
1395   gdk_region_get_clipbox (drect, &tmp_rect);
1396   
1397   gdk_region_destroy (drect);
1398   gdk_region_destroy (clip);
1399
1400   if (tmp_rect.width == 0 ||
1401       tmp_rect.height == 0)
1402     return;
1403   
1404   /* Actually draw */
1405
1406   if (!gc)
1407     {
1408       gc = gdk_gc_new (drawable);
1409       free_gc = TRUE;
1410     }
1411   
1412   if (pixbuf->has_alpha)
1413     {
1414       GdkVisual *visual = gdk_drawable_get_visual (drawable);
1415       void (*composite_func) (guchar       *src_buf,
1416                               gint          src_rowstride,
1417                               guchar       *dest_buf,
1418                               gint          dest_rowstride,
1419                               GdkByteOrder  dest_byte_order,
1420                               gint          width,
1421                               gint          height) = NULL;
1422
1423       /* First we see if we have a visual-specific composition function that can composite
1424        * the pixbuf data directly onto the image
1425        */
1426       if (visual)
1427         {
1428           gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
1429                                                                    visual->depth);
1430           
1431           if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
1432               visual->depth == 16 &&
1433               visual->red_mask   == 0xf800 &&
1434               visual->green_mask == 0x07e0 &&
1435               visual->blue_mask  == 0x001f)
1436             composite_func = composite_565;
1437           else if (visual->depth == 24 && bits_per_pixel == 32 &&
1438                    visual->red_mask   == 0xff0000 &&
1439                    visual->green_mask == 0x00ff00 &&
1440                    visual->blue_mask  == 0x0000ff)
1441             composite_func = composite_0888;
1442         }
1443
1444       /* We can't use our composite func if we are required to dither
1445        */
1446       if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
1447         {
1448           gint x0, y0;
1449           for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1450             {
1451               gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1452               for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1453                 {
1454                   gint xs0, ys0;
1455                   
1456                   gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1457                   
1458                   GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
1459                                                             width1, height1,
1460                                                             gdk_drawable_get_depth (drawable), &xs0, &ys0);
1461                   
1462                   gdk_drawable_copy_to_image (drawable, image,
1463                                               dest_x + x0, dest_y + y0,
1464                                               xs0, ys0,
1465                                               width1, height1);
1466                   (*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4,
1467                                      pixbuf->rowstride,
1468                                      (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
1469                                      image->bpl,
1470                                      visual->byte_order,
1471                                      width1, height1);
1472                   gdk_draw_image (drawable, gc, image,
1473                                   xs0, ys0,
1474                                   dest_x + x0, dest_y + y0,
1475                                   width1, height1);
1476                 }
1477             }
1478           
1479           goto out;
1480         }
1481       else
1482         {
1483           /* No special composition func, convert dest to 24 bit RGB data, composite against
1484            * that, and convert back.
1485            */
1486           composited = gdk_pixbuf_get_from_drawable (NULL,
1487                                                      drawable,
1488                                                      NULL,
1489                                                      dest_x, dest_y,
1490                                                      0, 0,
1491                                                      width, height);
1492           
1493           if (composited)
1494             composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
1495                        pixbuf->rowstride,
1496                        composited->pixels,
1497                        composited->rowstride,
1498                        width, height);
1499         }
1500     }
1501
1502   if (composited)
1503     {
1504       src_x = 0;
1505       src_y = 0;
1506       pixbuf = composited;
1507     }
1508   
1509   if (pixbuf->n_channels == 4)
1510     {
1511       guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4;
1512
1513       gdk_draw_rgb_32_image_dithalign (drawable, gc,
1514                                        dest_x, dest_y,
1515                                        width, height,
1516                                        dither,
1517                                        buf, pixbuf->rowstride,
1518                                        x_dither, y_dither);
1519     }
1520   else                          /* n_channels == 3 */
1521     {
1522       guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3;
1523
1524       gdk_draw_rgb_image_dithalign (drawable, gc,
1525                                     dest_x, dest_y,
1526                                     width, height,
1527                                     dither,
1528                                     buf, pixbuf->rowstride,
1529                                     x_dither, y_dither);
1530     }
1531
1532  out:
1533   if (composited)
1534     g_object_unref (composited);
1535
1536   if (free_gc)
1537     g_object_unref (gc);
1538 }