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