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