]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
Fixes #136082 and #135265, patch by Morten Welinder.
[~andy/gtk] / gdk / x11 / gdkdrawable-x11.c
1 /* 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
29 #include "gdkx.h"
30 #include "gdkregion-generic.h"
31
32 #include <pango/pangoxft.h>
33
34 #include <stdlib.h>
35 #include <string.h>             /* for memcpy() */
36
37 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
38 #define USE_SHM
39 #endif
40
41 #ifdef USE_SHM
42 #include <X11/extensions/XShm.h>
43 #endif /* USE_SHM */
44
45 #include "gdkprivate-x11.h"
46 #include "gdkdrawable-x11.h"
47 #include "gdkpixmap-x11.h"
48 #include "gdkscreen-x11.h"
49 #include "gdkdisplay-x11.h"
50
51 static void gdk_x11_draw_rectangle (GdkDrawable    *drawable,
52                                     GdkGC          *gc,
53                                     gboolean        filled,
54                                     gint            x,
55                                     gint            y,
56                                     gint            width,
57                                     gint            height);
58 static void gdk_x11_draw_arc       (GdkDrawable    *drawable,
59                                     GdkGC          *gc,
60                                     gboolean        filled,
61                                     gint            x,
62                                     gint            y,
63                                     gint            width,
64                                     gint            height,
65                                     gint            angle1,
66                                     gint            angle2);
67 static void gdk_x11_draw_polygon   (GdkDrawable    *drawable,
68                                     GdkGC          *gc,
69                                     gboolean        filled,
70                                     GdkPoint       *points,
71                                     gint            npoints);
72 static void gdk_x11_draw_text      (GdkDrawable    *drawable,
73                                     GdkFont        *font,
74                                     GdkGC          *gc,
75                                     gint            x,
76                                     gint            y,
77                                     const gchar    *text,
78                                     gint            text_length);
79 static void gdk_x11_draw_text_wc   (GdkDrawable    *drawable,
80                                     GdkFont        *font,
81                                     GdkGC          *gc,
82                                     gint            x,
83                                     gint            y,
84                                     const GdkWChar *text,
85                                     gint            text_length);
86 static void gdk_x11_draw_drawable  (GdkDrawable    *drawable,
87                                     GdkGC          *gc,
88                                     GdkPixmap      *src,
89                                     gint            xsrc,
90                                     gint            ysrc,
91                                     gint            xdest,
92                                     gint            ydest,
93                                     gint            width,
94                                     gint            height);
95 static void gdk_x11_draw_points    (GdkDrawable    *drawable,
96                                     GdkGC          *gc,
97                                     GdkPoint       *points,
98                                     gint            npoints);
99 static void gdk_x11_draw_segments  (GdkDrawable    *drawable,
100                                     GdkGC          *gc,
101                                     GdkSegment     *segs,
102                                     gint            nsegs);
103 static void gdk_x11_draw_lines     (GdkDrawable    *drawable,
104                                     GdkGC          *gc,
105                                     GdkPoint       *points,
106                                     gint            npoints);
107 static void gdk_x11_draw_glyphs    (GdkDrawable      *drawable,
108                                     GdkGC            *gc,
109                                     PangoFont        *font,
110                                     gint              x,
111                                     gint              y,
112                                     PangoGlyphString *glyphs);
113 static void gdk_x11_draw_image     (GdkDrawable     *drawable,
114                                     GdkGC           *gc,
115                                     GdkImage        *image,
116                                     gint             xsrc,
117                                     gint             ysrc,
118                                     gint             xdest,
119                                     gint             ydest,
120                                     gint             width,
121                                     gint             height);
122 static void gdk_x11_draw_pixbuf    (GdkDrawable     *drawable,
123                                     GdkGC           *gc,
124                                     GdkPixbuf       *pixbuf,
125                                     gint             src_x,
126                                     gint             src_y,
127                                     gint             dest_x,
128                                     gint             dest_y,
129                                     gint             width,
130                                     gint             height,
131                                     GdkRgbDither     dither,
132                                     gint             x_dither,
133                                     gint             y_dither);
134
135 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
136                                     GdkColormap    *colormap);
137
138 static GdkColormap* gdk_x11_get_colormap   (GdkDrawable    *drawable);
139 static gint         gdk_x11_get_depth      (GdkDrawable    *drawable);
140 static GdkScreen *  gdk_x11_get_screen     (GdkDrawable    *drawable);
141 static GdkVisual*   gdk_x11_get_visual     (GdkDrawable    *drawable);
142
143 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
144
145 static void gdk_drawable_impl_x11_finalize   (GObject *object);
146
147 static gpointer parent_class = NULL;
148
149 GType
150 _gdk_drawable_impl_x11_get_type (void)
151 {
152   static GType object_type = 0;
153
154   if (!object_type)
155     {
156       static const GTypeInfo object_info =
157       {
158         sizeof (GdkDrawableImplX11Class),
159         (GBaseInitFunc) NULL,
160         (GBaseFinalizeFunc) NULL,
161         (GClassInitFunc) gdk_drawable_impl_x11_class_init,
162         NULL,           /* class_finalize */
163         NULL,           /* class_data */
164         sizeof (GdkDrawableImplX11),
165         0,              /* n_preallocs */
166         (GInstanceInitFunc) NULL,
167       };
168       
169       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
170                                             "GdkDrawableImplX11",
171                                             &object_info, 0);
172     }
173   
174   return object_type;
175 }
176
177 static void
178 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
179 {
180   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
181   GObjectClass *object_class = G_OBJECT_CLASS (klass);
182   
183   parent_class = g_type_class_peek_parent (klass);
184
185   object_class->finalize = gdk_drawable_impl_x11_finalize;
186   
187   drawable_class->create_gc = _gdk_x11_gc_new;
188   drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
189   drawable_class->draw_arc = gdk_x11_draw_arc;
190   drawable_class->draw_polygon = gdk_x11_draw_polygon;
191   drawable_class->draw_text = gdk_x11_draw_text;
192   drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
193   drawable_class->draw_drawable = gdk_x11_draw_drawable;
194   drawable_class->draw_points = gdk_x11_draw_points;
195   drawable_class->draw_segments = gdk_x11_draw_segments;
196   drawable_class->draw_lines = gdk_x11_draw_lines;
197   drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
198   drawable_class->draw_image = gdk_x11_draw_image;
199   drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
200   
201   drawable_class->set_colormap = gdk_x11_set_colormap;
202   drawable_class->get_colormap = gdk_x11_get_colormap;
203
204   drawable_class->get_depth = gdk_x11_get_depth;
205   drawable_class->get_screen = gdk_x11_get_screen;
206   drawable_class->get_visual = gdk_x11_get_visual;
207   
208   drawable_class->_copy_to_image = _gdk_x11_copy_to_image;
209 }
210
211 static void
212 gdk_drawable_impl_x11_finalize (GObject *object)
213 {
214   gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
215
216   G_OBJECT_CLASS (parent_class)->finalize (object);
217 }
218
219 static void
220 try_pixmap (Display *xdisplay,
221             int      screen,
222             int      depth)
223 {
224   Pixmap pixmap = XCreatePixmap (xdisplay,
225                                  RootWindow (xdisplay, screen),
226                                  1, 1, depth);
227   XFreePixmap (xdisplay, pixmap);
228 }
229
230 gboolean
231 _gdk_x11_have_render (GdkDisplay *display)
232 {
233   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
234   GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display);
235
236   if (x11display->have_render == GDK_UNKNOWN)
237     {
238       int event_base, error_base;
239       x11display->have_render =
240         XRenderQueryExtension (xdisplay, &event_base, &error_base)
241         ? GDK_YES : GDK_NO;
242
243       if (x11display->have_render == GDK_YES)
244         {
245           /*
246            * Sun advertises RENDER, but fails to support 32-bit pixmaps.
247            * That is just no good.  Therefore, we check all screens
248            * for proper support.
249            */
250
251           int screen;
252           for (screen = 0; screen < ScreenCount (xdisplay); screen++)
253             {
254               int count;
255               int *depths = XListDepths (xdisplay, screen, &count);
256               gboolean has_8 = FALSE, has_32 = FALSE;
257
258               if (depths)
259                 {
260                   int i;
261
262                   for (i = 0; i < count; i++)
263                     {
264                       if (depths[i] == 8)
265                         has_8 = TRUE;
266                       else if (depths[i] == 32)
267                         has_32 = TRUE;
268                     }
269                   XFree (depths);
270                 }
271
272               /* At this point, we might have a false positive;
273                * buggy versions of Xinerama only report depths for
274                * which there is an associated visual; so we actually
275                * go ahead and try create pixmaps.
276                */
277               if (!(has_8 && has_32))
278                 {
279                   gdk_error_trap_push ();
280                   if (!has_8)
281                     try_pixmap (xdisplay, screen, 8);
282                   if (!has_32)
283                     try_pixmap (xdisplay, screen, 32);
284                   XSync (xdisplay, False);
285                   if (gdk_error_trap_pop () == 0)
286                     {
287                       has_8 = TRUE;
288                       has_32 = TRUE;
289                     }
290                 }
291               
292               if (!(has_8 && has_32))
293                 {
294                   g_warning ("The X server advertises that RENDER support is present,\n"
295                              "but fails to supply the necessary pixmap support.  In\n"
296                              "other words, it is buggy.");
297                   x11display->have_render = GDK_NO;
298                   break;
299                 }
300             }
301         }
302     }
303
304   return x11display->have_render == GDK_YES;
305 }
306
307 static XftDraw *
308 gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
309 {
310   GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
311
312    if (impl->xft_draw == NULL)
313     {
314       GdkColormap *colormap = gdk_drawable_get_colormap (drawable);
315       
316       if (colormap)
317         {
318           GdkVisual *visual;
319
320           visual = gdk_colormap_get_visual (colormap);
321       
322           impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
323                                           GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
324         }
325       else if (gdk_drawable_get_depth (drawable) == 1)
326         {
327           impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid);
328         }
329       else
330         {
331           g_warning ("Using Xft rendering requires the drawable argument to\n"
332                      "have a specified colormap. All windows have a colormap,\n"
333                      "however, pixmaps only have colormap by default if they\n"
334                      "were created with a non-NULL window argument. Otherwise\n"
335                      "a colormap must be set on them with gdk_drawable_set_colormap");
336           return NULL;
337         }
338     }
339
340    return impl->xft_draw;
341 }
342
343 static Picture
344 gdk_x11_drawable_get_picture (GdkDrawable *drawable)
345 {
346   XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable);
347
348   return draw ? XftDrawPicture (draw) : None;
349 }
350
351 static void
352 gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable,
353                                   GdkGC       *gc)
354 {
355   GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
356   XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
357
358   if (gc && gc_private->clip_region)
359     {
360       GdkRegionBox *boxes = gc_private->clip_region->rects;
361       gint n_boxes = gc_private->clip_region->numRects;
362 #if 0                           /* Until XftDrawSetClipRectangles is there */
363       XRectangle *rects = g_new (XRectangle, n_boxes);
364       int i;
365
366       for (i=0; i < n_boxes; i++)
367         {
368           rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
369           rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
370           rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
371           rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
372         }
373       XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes);
374
375       g_free (rects);
376 #else
377       Region xregion = XCreateRegion ();
378       int i;
379  
380       for (i=0; i < n_boxes; i++)
381         {
382           XRectangle rect;
383           
384           rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
385           rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
386           rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x;
387           rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y;
388           
389           XUnionRectWithRegion (&rect, xregion, xregion);
390         }
391       
392       XftDrawSetClip (xft_draw, xregion);
393       XDestroyRegion (xregion);
394 #endif      
395     }
396   else
397     {
398       XftDrawSetClip (xft_draw, NULL);
399     }
400 }
401
402 /*****************************************************
403  * X11 specific implementations of generic functions *
404  *****************************************************/
405
406 static GdkColormap*
407 gdk_x11_get_colormap (GdkDrawable *drawable)
408 {
409   GdkDrawableImplX11 *impl;
410
411   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
412
413   return impl->colormap;
414 }
415
416 static void
417 gdk_x11_set_colormap (GdkDrawable *drawable,
418                       GdkColormap *colormap)
419 {
420   GdkDrawableImplX11 *impl;
421
422   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
423
424   if (impl->colormap == colormap)
425     return;
426   
427   if (impl->colormap)
428     g_object_unref (impl->colormap);
429   impl->colormap = colormap;
430   if (impl->colormap)
431     g_object_ref (impl->colormap);
432 }
433
434 /* Drawing
435  */
436
437 static void
438 gdk_x11_draw_rectangle (GdkDrawable *drawable,
439                         GdkGC       *gc,
440                         gboolean     filled,
441                         gint         x,
442                         gint         y,
443                         gint         width,
444                         gint         height)
445 {
446   GdkDrawableImplX11 *impl;
447
448   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
449   
450   if (filled)
451     XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
452                     GDK_GC_GET_XGC (gc), x, y, width, height);
453   else
454     XDrawRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
455                     GDK_GC_GET_XGC (gc), x, y, width, height);
456 }
457
458 static void
459 gdk_x11_draw_arc (GdkDrawable *drawable,
460                   GdkGC       *gc,
461                   gboolean     filled,
462                   gint         x,
463                   gint         y,
464                   gint         width,
465                   gint         height,
466                   gint         angle1,
467                   gint         angle2)
468 {
469   GdkDrawableImplX11 *impl;
470
471   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
472
473   
474   if (filled)
475     XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
476               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
477   else
478     XDrawArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
479               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
480 }
481
482 static void
483 gdk_x11_draw_polygon (GdkDrawable *drawable,
484                       GdkGC       *gc,
485                       gboolean     filled,
486                       GdkPoint    *points,
487                       gint         npoints)
488 {
489   XPoint *tmp_points;
490   gint tmp_npoints, i;
491   GdkDrawableImplX11 *impl;
492
493   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
494
495   
496   if (!filled &&
497       (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
498     {
499       tmp_npoints = npoints + 1;
500       tmp_points = g_new (XPoint, tmp_npoints);
501       tmp_points[npoints].x = points[0].x;
502       tmp_points[npoints].y = points[0].y;
503     }
504   else
505     {
506       tmp_npoints = npoints;
507       tmp_points = g_new (XPoint, tmp_npoints);
508     }
509
510   for (i=0; i<npoints; i++)
511     {
512       tmp_points[i].x = points[i].x;
513       tmp_points[i].y = points[i].y;
514     }
515   
516   if (filled)
517     XFillPolygon (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
518                   GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
519   else
520     XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
521                 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
522
523   g_free (tmp_points);
524 }
525
526 /* gdk_x11_draw_text
527  *
528  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
529  *
530  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
531  */
532 static void
533 gdk_x11_draw_text (GdkDrawable *drawable,
534                    GdkFont     *font,
535                    GdkGC       *gc,
536                    gint         x,
537                    gint         y,
538                    const gchar *text,
539                    gint         text_length)
540 {
541   GdkDrawableImplX11 *impl;
542   Display *xdisplay;
543
544   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
545   xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
546   
547   if (font->type == GDK_FONT_FONT)
548     {
549       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
550       XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
551       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
552         {
553           XDrawString (xdisplay, impl->xid,
554                        GDK_GC_GET_XGC (gc), x, y, text, text_length);
555         }
556       else
557         {
558           XDrawString16 (xdisplay, impl->xid,
559                          GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
560         }
561     }
562   else if (font->type == GDK_FONT_FONTSET)
563     {
564       XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
565       XmbDrawString (xdisplay, impl->xid,
566                      fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
567     }
568   else
569     g_error("undefined font type\n");
570 }
571
572 static void
573 gdk_x11_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   GdkDrawableImplX11 *impl;
582   Display *xdisplay;
583
584   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
585   xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
586   
587   if (font->type == GDK_FONT_FONT)
588     {
589       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
590       gchar *text_8bit;
591       gint i;
592       XSetFont(xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
593       text_8bit = g_new (gchar, text_length);
594       for (i=0; i<text_length; i++) text_8bit[i] = text[i];
595       XDrawString (xdisplay, impl->xid,
596                    GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
597       g_free (text_8bit);
598     }
599   else if (font->type == GDK_FONT_FONTSET)
600     {
601       if (sizeof(GdkWChar) == sizeof(wchar_t))
602         {
603           XwcDrawString (xdisplay, impl->xid,
604                          (XFontSet) GDK_FONT_XFONT (font),
605                          GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
606         }
607       else
608         {
609           wchar_t *text_wchar;
610           gint i;
611           text_wchar = g_new (wchar_t, text_length);
612           for (i=0; i<text_length; i++) text_wchar[i] = text[i];
613           XwcDrawString (xdisplay, impl->xid,
614                          (XFontSet) GDK_FONT_XFONT (font),
615                          GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
616           g_free (text_wchar);
617         }
618     }
619   else
620     g_error("undefined font type\n");
621 }
622
623 static void
624 gdk_x11_draw_drawable (GdkDrawable *drawable,
625                        GdkGC       *gc,
626                        GdkPixmap   *src,
627                        gint         xsrc,
628                        gint         ysrc,
629                        gint         xdest,
630                        gint         ydest,
631                        gint         width,
632                        gint         height)
633 {
634   int src_depth = gdk_drawable_get_depth (src);
635   int dest_depth = gdk_drawable_get_depth (drawable);
636   GdkDrawableImplX11 *impl;
637   GdkDrawableImplX11 *src_impl;
638   
639   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
640
641   if (GDK_IS_DRAWABLE_IMPL_X11 (src))
642     src_impl = GDK_DRAWABLE_IMPL_X11 (src);
643   else
644     src_impl = NULL;
645   
646   if (src_depth == 1)
647     {
648       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
649                  src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
650                  impl->xid,
651                  GDK_GC_GET_XGC (gc),
652                  xsrc, ysrc,
653                  width, height,
654                  xdest, ydest);
655     }
656   else if (dest_depth != 0 && src_depth == dest_depth)
657     {
658       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
659                  src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
660                  impl->xid,
661                  GDK_GC_GET_XGC (gc),
662                  xsrc, ysrc,
663                  width, height,
664                  xdest, ydest);
665     }
666   else
667     g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
668                src_depth, dest_depth);
669 }
670
671 static void
672 gdk_x11_draw_points (GdkDrawable *drawable,
673                      GdkGC       *gc,
674                      GdkPoint    *points,
675                      gint         npoints)
676 {
677   GdkDrawableImplX11 *impl;
678
679   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
680
681   
682   /* We special-case npoints == 1, because X will merge multiple
683    * consecutive XDrawPoint requests into a PolyPoint request
684    */
685   if (npoints == 1)
686     {
687       XDrawPoint (GDK_SCREEN_XDISPLAY (impl->screen),
688                   impl->xid,
689                   GDK_GC_GET_XGC (gc),
690                   points[0].x, points[0].y);
691     }
692   else
693     {
694       gint i;
695       XPoint *tmp_points = g_new (XPoint, npoints);
696
697       for (i=0; i<npoints; i++)
698         {
699           tmp_points[i].x = points[i].x;
700           tmp_points[i].y = points[i].y;
701         }
702       
703       XDrawPoints (GDK_SCREEN_XDISPLAY (impl->screen),
704                    impl->xid,
705                    GDK_GC_GET_XGC (gc),
706                    tmp_points,
707                    npoints,
708                    CoordModeOrigin);
709
710       g_free (tmp_points);
711     }
712 }
713
714 static void
715 gdk_x11_draw_segments (GdkDrawable *drawable,
716                        GdkGC       *gc,
717                        GdkSegment  *segs,
718                        gint         nsegs)
719 {
720   GdkDrawableImplX11 *impl;
721
722   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
723
724   
725   /* We special-case nsegs == 1, because X will merge multiple
726    * consecutive XDrawLine requests into a PolySegment request
727    */
728   if (nsegs == 1)
729     {
730       XDrawLine (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
731                  GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
732                  segs[0].x2, segs[0].y2);
733     }
734   else
735     {
736       gint i;
737       XSegment *tmp_segs = g_new (XSegment, nsegs);
738
739       for (i=0; i<nsegs; i++)
740         {
741           tmp_segs[i].x1 = segs[i].x1;
742           tmp_segs[i].x2 = segs[i].x2;
743           tmp_segs[i].y1 = segs[i].y1;
744           tmp_segs[i].y2 = segs[i].y2;
745         }
746       
747       XDrawSegments (GDK_SCREEN_XDISPLAY (impl->screen),
748                      impl->xid,
749                      GDK_GC_GET_XGC (gc),
750                      tmp_segs, nsegs);
751
752       g_free (tmp_segs);
753     }
754 }
755
756 static void
757 gdk_x11_draw_lines (GdkDrawable *drawable,
758                     GdkGC       *gc,
759                     GdkPoint    *points,
760                     gint         npoints)
761 {
762   gint i;
763   XPoint *tmp_points = g_new (XPoint, npoints);
764   GdkDrawableImplX11 *impl;
765
766   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
767
768   
769   for (i=0; i<npoints; i++)
770     {
771       tmp_points[i].x = points[i].x;
772       tmp_points[i].y = points[i].y;
773     }
774       
775   XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
776               impl->xid,
777               GDK_GC_GET_XGC (gc),
778               tmp_points, npoints,
779               CoordModeOrigin);
780
781   g_free (tmp_points);
782 }
783
784 static void
785 gdk_x11_draw_glyphs (GdkDrawable      *drawable,
786                      GdkGC            *gc,
787                      PangoFont        *font,
788                      gint              x,
789                      gint              y,
790                      PangoGlyphString *glyphs)
791 {
792   GdkDrawableImplX11 *impl;
793   XftColor color;
794   XftDraw *draw;
795
796   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
797
798   g_return_if_fail (PANGO_XFT_IS_FONT (font));
799  
800   _gdk_gc_x11_get_fg_xft_color (gc, &color);
801       
802   gdk_x11_drawable_update_xft_clip (drawable, gc);
803   draw = gdk_x11_drawable_get_xft_draw (drawable);
804       
805   pango_xft_render (draw, &color, font, glyphs, x, y);
806 }
807
808 static void
809 gdk_x11_draw_image     (GdkDrawable     *drawable,
810                         GdkGC           *gc,
811                         GdkImage        *image,
812                         gint             xsrc,
813                         gint             ysrc,
814                         gint             xdest,
815                         gint             ydest,
816                         gint             width,
817                         gint             height)
818 {
819   GdkDrawableImplX11 *impl;
820   
821   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
822
823 #ifdef USE_SHM  
824   if (image->type == GDK_IMAGE_SHARED)
825     XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
826                   GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
827                   xsrc, ysrc, xdest, ydest, width, height, False);
828   else
829 #endif
830     XPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
831                GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
832                xsrc, ysrc, xdest, ydest, width, height);
833 }
834
835 static gint
836 gdk_x11_get_depth (GdkDrawable *drawable)
837 {
838   /* This is a bit bogus but I'm not sure the other way is better */
839
840   return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
841 }
842
843
844 static GdkDrawable * get_impl_drawable (GdkDrawable *drawable)
845 {
846   GdkDrawable *impl;
847   
848   if (GDK_IS_WINDOW (drawable))
849     impl = ((GdkPixmapObject *)drawable)->impl;
850   else if (GDK_IS_PIXMAP (drawable))
851     impl = ((GdkPixmapObject *)drawable)->impl;
852   else
853     {
854       g_warning (G_STRLOC " drawable is not a pixmap or window");
855       return None;
856     }
857   return impl;
858 }
859
860
861 static GdkScreen*
862 gdk_x11_get_screen (GdkDrawable *drawable)
863 {
864   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
865     return GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
866   else
867     return GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen;
868 }
869
870 static GdkVisual*
871 gdk_x11_get_visual (GdkDrawable    *drawable)
872 {
873   return gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
874 }
875
876 /**
877  * gdk_x11_drawable_get_xdisplay:
878  * @drawable: a #GdkDrawable.
879  * 
880  * Returns the display of a #GdkDrawable.
881  * 
882  * Return value: an Xlib <type>Display*</type>.
883  **/
884 Display *
885 gdk_x11_drawable_get_xdisplay (GdkDrawable *drawable)
886 {
887   if (GDK_IS_DRAWABLE_IMPL_X11 (drawable))
888     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
889   else
890     return GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (get_impl_drawable (drawable))->screen);
891 }
892
893 /**
894  * gdk_x11_drawable_get_xid:
895  * @drawable: a #GdkDrawable.
896  * 
897  * Returns the X resource (window or pixmap) belonging to a #GdkDrawable.
898  * 
899  * Return value: the ID of @drawable's X resource.
900  **/
901 XID
902 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
903 {
904   GdkDrawable *impl;
905   
906   if (GDK_IS_WINDOW (drawable))
907     impl = ((GdkPixmapObject *)drawable)->impl;
908   else if (GDK_IS_PIXMAP (drawable))
909     impl = ((GdkPixmapObject *)drawable)->impl;
910   else
911     {
912       g_warning (G_STRLOC " drawable is not a pixmap or window");
913       return None;
914     }
915
916   return ((GdkDrawableImplX11 *)impl)->xid;
917 }
918
919 /* Code for accelerated alpha compositing using the RENDER extension.
920  * It's a bit long because there are lots of possibilities for
921  * what's the fastest depending on the available picture formats,
922  * whether we can used shared pixmaps, etc.
923  */
924 typedef enum {
925   FORMAT_NONE,
926   FORMAT_EXACT_MASK,
927   FORMAT_ARGB_MASK,
928   FORMAT_ARGB
929 } FormatType;
930
931 static FormatType
932 select_format (GdkDisplay         *display,
933                XRenderPictFormat **format,
934                XRenderPictFormat **mask)
935 {
936   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
937   XRenderPictFormat pf;
938
939   if (!_gdk_x11_have_render (display))
940     return FORMAT_NONE;
941   
942   /* Look for a 32-bit xRGB and Axxx formats that exactly match the
943    * in memory data format. We can use them as pixmap and mask
944    * to deal with non-premultiplied data.
945    */
946
947   pf.type = PictTypeDirect;
948   pf.depth = 32;
949   pf.direct.redMask = 0xff;
950   pf.direct.greenMask = 0xff;
951   pf.direct.blueMask = 0xff;
952   
953   pf.direct.alphaMask = 0;
954   if (ImageByteOrder (xdisplay) == LSBFirst)
955     {
956       /* ABGR */
957       pf.direct.red = 0;
958       pf.direct.green = 8;
959       pf.direct.blue = 16;
960     }
961   else
962     {
963       /* RGBA */
964       pf.direct.red = 24;
965       pf.direct.green = 16;
966       pf.direct.blue = 8;
967     }
968   
969   *format = XRenderFindFormat (xdisplay,
970                                (PictFormatType | PictFormatDepth |
971                                 PictFormatRedMask | PictFormatRed |
972                                 PictFormatGreenMask | PictFormatGreen |
973                                 PictFormatBlueMask | PictFormatBlue |
974                                 PictFormatAlphaMask),
975                                &pf,
976                                0);
977
978   pf.direct.alphaMask = 0xff;
979   if (ImageByteOrder (xdisplay) == LSBFirst)
980     {
981       /* ABGR */
982       pf.direct.alpha = 24;
983     }
984   else
985     {
986       pf.direct.alpha = 0;
987     }
988   
989   *mask = XRenderFindFormat (xdisplay,
990                              (PictFormatType | PictFormatDepth |
991                               PictFormatAlphaMask | PictFormatAlpha),
992                              &pf,
993                              0);
994
995   if (*format && *mask)
996     return FORMAT_EXACT_MASK;
997
998   /* OK, that failed, now look for xRGB and Axxx formats in
999    * RENDER's preferred order
1000    */
1001   pf.direct.alphaMask = 0;
1002   /* ARGB */
1003   pf.direct.red = 16;
1004   pf.direct.green = 8;
1005   pf.direct.blue = 0;
1006   
1007   *format = XRenderFindFormat (xdisplay,
1008                                (PictFormatType | PictFormatDepth |
1009                                 PictFormatRedMask | PictFormatRed |
1010                                 PictFormatGreenMask | PictFormatGreen |
1011                                 PictFormatBlueMask | PictFormatBlue |
1012                                 PictFormatAlphaMask),
1013                                &pf,
1014                                0);
1015
1016   pf.direct.alphaMask = 0xff;
1017   pf.direct.alpha = 24;
1018   
1019   *mask = XRenderFindFormat (xdisplay,
1020                              (PictFormatType | PictFormatDepth |
1021                               PictFormatAlphaMask | PictFormatAlpha),
1022                              &pf,
1023                              0);
1024
1025   if (*format && *mask)
1026     return FORMAT_ARGB_MASK;
1027
1028   /* Finally, if neither of the above worked, fall back to
1029    * looking for combined ARGB -- we'll premultiply ourselves.
1030    */
1031
1032   pf.type = PictTypeDirect;
1033   pf.depth = 32;
1034   pf.direct.red = 16;
1035   pf.direct.green = 8;
1036   pf.direct.blue = 0;
1037   pf.direct.alphaMask = 0xff;
1038   pf.direct.alpha = 24;
1039
1040   *format = XRenderFindFormat (xdisplay,
1041                                (PictFormatType | PictFormatDepth |
1042                                 PictFormatRedMask | PictFormatRed |
1043                                 PictFormatGreenMask | PictFormatGreen |
1044                                 PictFormatBlueMask | PictFormatBlue |
1045                                 PictFormatAlphaMask | PictFormatAlpha),
1046                                &pf,
1047                                0);
1048   *mask = NULL;
1049
1050   if (*format)
1051     return FORMAT_ARGB;
1052
1053   return FORMAT_NONE;
1054 }
1055
1056 #if 0
1057 static void
1058 list_formats (XRenderPictFormat *pf)
1059 {
1060   gint i;
1061   
1062   for (i=0 ;; i++)
1063     {
1064       XRenderPictFormat *pf = XRenderFindFormat (impl->xdisplay, 0, NULL, i);
1065       if (pf)
1066         {
1067           g_print ("%2d R-%#06x/%#06x G-%#06x/%#06x B-%#06x/%#06x A-%#06x/%#06x\n",
1068                    pf->depth,
1069                    pf->direct.red,
1070                    pf->direct.redMask,
1071                    pf->direct.green,
1072                    pf->direct.greenMask,
1073                    pf->direct.blue,
1074                    pf->direct.blueMask,
1075                    pf->direct.alpha,
1076                    pf->direct.alphaMask);
1077         }
1078       else
1079         break;
1080     }
1081 }
1082 #endif  
1083
1084 static void
1085 convert_to_format (guchar        *src_buf,
1086                    gint           src_rowstride,
1087                    guchar        *dest_buf,
1088                    gint           dest_rowstride,
1089                    FormatType     dest_format,
1090                    GdkByteOrder   dest_byteorder,
1091                    gint           width,
1092                    gint           height)
1093 {
1094   gint i;
1095
1096   for (i=0; i < height; i++)
1097     {
1098       switch (dest_format)
1099         {
1100         case FORMAT_EXACT_MASK:
1101           {
1102             memcpy (dest_buf + i * dest_rowstride,
1103                     src_buf + i * src_rowstride,
1104                     width * 4);
1105             break;
1106           }
1107         case FORMAT_ARGB_MASK:
1108           {
1109             guchar *row = src_buf + i * src_rowstride;
1110             if (((gsize)row & 3) != 0)
1111               {
1112                 guchar *p = row;
1113                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1114                 guchar *end = p + 4 * width;
1115
1116                 while (p < end)
1117                   {
1118                     *q = (p[3] << 24) | (p[0] << 16) | (p[1] << 8) | p[2];
1119                     p += 4;
1120                     q++;
1121                   }
1122               }
1123             else
1124               {
1125                 guint32 *p = (guint32 *)row;
1126                 guint32 *q = (guint32 *)(dest_buf + i * dest_rowstride);
1127                 guint32 *end = p + width;
1128
1129 #if G_BYTE_ORDER == G_LITTLE_ENDIAN         
1130                 if (dest_byteorder == GDK_LSB_FIRST)
1131                   {
1132                     /* ABGR => ARGB */
1133                 
1134                     while (p < end)
1135                       {
1136                         *q = ( (*p & 0xff00ff00) |
1137                                ((*p & 0x000000ff) << 16) |
1138                                ((*p & 0x00ff0000) >> 16));
1139                         q++;
1140                         p++;
1141                       }
1142                   }
1143                 else
1144                   {
1145                     /* ABGR => BGRA */
1146                 
1147                     while (p < end)
1148                       {
1149                         *q = (((*p & 0xff000000) >> 24) |
1150                               ((*p & 0x00ffffff) << 8));
1151                         q++;
1152                         p++;
1153                       }
1154                   }
1155 #else /* G_BYTE_ORDER == G_BIG_ENDIAN */
1156                 if (dest_byteorder == GDK_LSB_FIRST)
1157                   {
1158                     /* RGBA => BGRA */
1159                 
1160                     while (p < end)
1161                       {
1162                         *q = ( (*p & 0x00ff00ff) |
1163                                ((*p & 0x0000ff00) << 16) |
1164                                ((*p & 0xff000000) >> 16));
1165                         q++;
1166                         p++;
1167                       }
1168                   }
1169                 else
1170                   {
1171                     /* RGBA => ARGB */
1172                 
1173                     while (p < end)
1174                       {
1175                         *q = (((*p & 0xffffff00) >> 8) |
1176                               ((*p & 0x000000ff) << 24));
1177                         q++;
1178                         p++;
1179                       }
1180                   }
1181 #endif /* G_BYTE_ORDER*/            
1182               }
1183             break;
1184           }
1185         case FORMAT_ARGB:
1186           {
1187             guchar *p = (src_buf + i * src_rowstride);
1188             guchar *q = (dest_buf + i * dest_rowstride);
1189             guchar *end = p + 4 * width;
1190             guint t1,t2,t3;
1191             
1192 #define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
1193             
1194             if (dest_byteorder == GDK_LSB_FIRST)
1195               {
1196                 while (p < end)
1197                   {
1198                     MULT(q[0], p[2], p[3], t1);
1199                     MULT(q[1], p[1], p[3], t2);
1200                     MULT(q[2], p[0], p[3], t3);
1201                     q[3] = p[3];
1202                     p += 4;
1203                     q += 4;
1204                   }
1205               }
1206             else
1207               {
1208                 while (p < end)
1209                   {
1210                     q[0] = p[3];
1211                     MULT(q[1], p[0], p[3], t1);
1212                     MULT(q[2], p[1], p[3], t2);
1213                     MULT(q[3], p[2], p[3], t3);
1214                     p += 4;
1215                     q += 4;
1216                   }
1217               }
1218 #undef MULT
1219             break;
1220           }
1221         case FORMAT_NONE:
1222           g_assert_not_reached ();
1223           break;
1224         }
1225     }
1226 }
1227
1228 static void
1229 draw_with_images (GdkDrawable       *drawable,
1230                   GdkGC             *gc,
1231                   FormatType         format_type,
1232                   XRenderPictFormat *format,
1233                   XRenderPictFormat *mask_format,
1234                   guchar            *src_rgb,
1235                   gint               src_rowstride,
1236                   gint               dest_x,
1237                   gint               dest_y,
1238                   gint               width,
1239                   gint               height)
1240 {
1241   GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
1242   Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
1243   GdkImage *image;
1244   GdkPixmap *pix;
1245   GdkGC *pix_gc;
1246   Picture pict;
1247   Picture dest_pict;
1248   Picture mask = None;
1249   gint x0, y0;
1250
1251   pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
1252                                                   
1253   pict = XRenderCreatePicture (xdisplay, 
1254                                GDK_PIXMAP_XID (pix),
1255                                format, 0, NULL);
1256   if (mask_format)
1257     mask = XRenderCreatePicture (xdisplay, 
1258                                  GDK_PIXMAP_XID (pix),
1259                                  mask_format, 0, NULL);
1260
1261   dest_pict = gdk_x11_drawable_get_picture (drawable);  
1262   
1263   pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
1264
1265   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1266     {
1267       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1268       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1269         {
1270           gint xs0, ys0;
1271           
1272           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1273           
1274           image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
1275           
1276           convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1277                              (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1278                              format_type, image->byte_order, 
1279                              width1, height1);
1280
1281           gdk_draw_image (pix, pix_gc,
1282                           image, xs0, ys0, x0, y0, width1, height1);
1283         }
1284     }
1285   
1286   XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1287                     0, 0, 0, 0, dest_x, dest_y, width, height);
1288
1289   XRenderFreePicture (xdisplay, pict);
1290   if (mask)
1291     XRenderFreePicture (xdisplay, mask);
1292   
1293   g_object_unref (pix);
1294 }
1295
1296 typedef struct _ShmPixmapInfo ShmPixmapInfo;
1297
1298 struct _ShmPixmapInfo
1299 {
1300   GdkImage *image;
1301   Pixmap    pix;
1302   Picture   pict;
1303   Picture   mask;
1304 };
1305
1306 /* Returns FALSE if we can't get a shm pixmap */
1307 static gboolean
1308 get_shm_pixmap_for_image (Display           *xdisplay,
1309                           GdkImage          *image,
1310                           XRenderPictFormat *format,
1311                           XRenderPictFormat *mask_format,
1312                           Pixmap            *pix,
1313                           Picture           *pict,
1314                           Picture           *mask)
1315 {
1316   ShmPixmapInfo *info;
1317   
1318   if (image->type != GDK_IMAGE_SHARED)
1319     return FALSE;
1320   
1321   info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
1322   if (!info)
1323     {
1324       *pix = _gdk_x11_image_get_shm_pixmap (image);
1325       
1326       if (!*pix)
1327         return FALSE;
1328       
1329       info = g_new (ShmPixmapInfo, 1);
1330       info->pix = *pix;
1331       
1332       info->pict = XRenderCreatePicture (xdisplay, info->pix,
1333                                          format, 0, NULL);
1334       if (mask_format)
1335         info->mask = XRenderCreatePicture (xdisplay, info->pix,
1336                                            mask_format, 0, NULL);
1337       else
1338         info->mask = None;
1339
1340       g_object_set_data (G_OBJECT (image), "gdk-x11-shm-pixmap", info);
1341     }
1342
1343   *pix = info->pix;
1344   *pict = info->pict;
1345   *mask = info->mask;
1346
1347   return TRUE;
1348 }
1349
1350 #ifdef USE_SHM
1351 /* Returns FALSE if drawing with ShmPixmaps is not possible */
1352 static gboolean
1353 draw_with_pixmaps (GdkDrawable       *drawable,
1354                    GdkGC             *gc,
1355                    FormatType         format_type,
1356                    XRenderPictFormat *format,
1357                    XRenderPictFormat *mask_format,
1358                    guchar            *src_rgb,
1359                    gint               src_rowstride,
1360                    gint               dest_x,
1361                    gint               dest_y,
1362                    gint               width,
1363                    gint               height)
1364 {
1365   Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
1366   GdkImage *image;
1367   Pixmap pix;
1368   Picture pict;
1369   Picture dest_pict;
1370   Picture mask = None;
1371   gint x0, y0;
1372
1373   dest_pict = gdk_x11_drawable_get_picture (drawable);
1374   
1375   for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1376     {
1377       gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1378       for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1379         {
1380           gint xs0, ys0;
1381           
1382           gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1383           
1384           image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
1385                                           width1, height1, 32, &xs0, &ys0);
1386           if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
1387             return FALSE;
1388
1389           convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
1390                              (guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
1391                              format_type, image->byte_order, 
1392                              width1, height1);
1393
1394           XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict, 
1395                             xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
1396                             width1, height1);
1397         }
1398     }
1399
1400   return TRUE;
1401 }
1402 #endif
1403
1404 static void
1405 gdk_x11_draw_pixbuf (GdkDrawable     *drawable,
1406                      GdkGC           *gc,
1407                      GdkPixbuf       *pixbuf,
1408                      gint             src_x,
1409                      gint             src_y,
1410                      gint             dest_x,
1411                      gint             dest_y,
1412                      gint             width,
1413                      gint             height,
1414                      GdkRgbDither     dither,
1415                      gint             x_dither,
1416                      gint             y_dither)
1417 {
1418   FormatType format_type;
1419   XRenderPictFormat *format, *mask_format;
1420   gint rowstride;
1421 #ifdef USE_SHM  
1422   gboolean use_pixmaps = TRUE;
1423 #endif /* USE_SHM */
1424     
1425   format_type = select_format (gdk_drawable_get_display (drawable),
1426                                &format, &mask_format);
1427
1428   if (format_type == FORMAT_NONE ||
1429       !gdk_pixbuf_get_has_alpha (pixbuf) ||
1430       gdk_drawable_get_depth (drawable) == 1 ||
1431       (dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
1432       gdk_x11_drawable_get_picture (drawable) == None)
1433     {
1434       GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
1435       GDK_DRAWABLE_CLASS (parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
1436                                                       src_x, src_y, dest_x, dest_y,
1437                                                       width, height,
1438                                                       dither, x_dither, y_dither);
1439       return;
1440     }
1441
1442   gdk_x11_drawable_update_xft_clip (drawable, gc);
1443
1444   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1445
1446 #ifdef USE_SHM
1447   if (use_pixmaps)
1448     {
1449       if (!draw_with_pixmaps (drawable, gc,
1450                               format_type, format, mask_format,
1451                               gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1452                               rowstride,
1453                               dest_x, dest_y, width, height))
1454         use_pixmaps = FALSE;
1455     }
1456
1457   if (!use_pixmaps)
1458 #endif /* USE_SHM */
1459     draw_with_images (drawable, gc,
1460                       format_type, format, mask_format,
1461                       gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
1462                       rowstride,
1463                       dest_x, dest_y, width, height);
1464 }