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