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