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