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