~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gdk/x11/gdkdrawable-x11.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

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