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