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