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