]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[~andy/gtk] / gdk / x11 / gdkdrawable-x11.c
1 /* GDK - The 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 "gdkprivate-x11.h"
28 #include <pango/pangox.h>
29 #include <config.h>
30
31 #include <stdlib.h>
32
33 #if defined (HAVE_IPC_H) && defined (HAVE_SHM_H) && defined (HAVE_XSHM_H)
34 #define USE_SHM
35 #endif
36
37 #ifdef USE_SHM
38 #include <X11/extensions/XShm.h>
39 #endif /* USE_SHM */
40
41 #include "gdkprivate-x11.h"
42 #include "gdkdrawable-x11.h"
43 #include "gdkpixmap-x11.h"
44
45 static void gdk_x11_draw_rectangle (GdkDrawable    *drawable,
46                                     GdkGC          *gc,
47                                     gint            filled,
48                                     gint            x,
49                                     gint            y,
50                                     gint            width,
51                                     gint            height);
52 static void gdk_x11_draw_arc       (GdkDrawable    *drawable,
53                                     GdkGC          *gc,
54                                     gint            filled,
55                                     gint            x,
56                                     gint            y,
57                                     gint            width,
58                                     gint            height,
59                                     gint            angle1,
60                                     gint            angle2);
61 static void gdk_x11_draw_polygon   (GdkDrawable    *drawable,
62                                     GdkGC          *gc,
63                                     gint            filled,
64                                     GdkPoint       *points,
65                                     gint            npoints);
66 static void gdk_x11_draw_text      (GdkDrawable    *drawable,
67                                     GdkFont        *font,
68                                     GdkGC          *gc,
69                                     gint            x,
70                                     gint            y,
71                                     const gchar    *text,
72                                     gint            text_length);
73 static void gdk_x11_draw_text_wc   (GdkDrawable    *drawable,
74                                     GdkFont        *font,
75                                     GdkGC          *gc,
76                                     gint            x,
77                                     gint            y,
78                                     const GdkWChar *text,
79                                     gint            text_length);
80 static void gdk_x11_draw_drawable  (GdkDrawable    *drawable,
81                                     GdkGC          *gc,
82                                     GdkPixmap      *src,
83                                     gint            xsrc,
84                                     gint            ysrc,
85                                     gint            xdest,
86                                     gint            ydest,
87                                     gint            width,
88                                     gint            height);
89 static void gdk_x11_draw_points    (GdkDrawable    *drawable,
90                                     GdkGC          *gc,
91                                     GdkPoint       *points,
92                                     gint            npoints);
93 static void gdk_x11_draw_segments  (GdkDrawable    *drawable,
94                                     GdkGC          *gc,
95                                     GdkSegment     *segs,
96                                     gint            nsegs);
97 static void gdk_x11_draw_lines     (GdkDrawable    *drawable,
98                                     GdkGC          *gc,
99                                     GdkPoint       *points,
100                                     gint            npoints);
101 static void gdk_x11_draw_glyphs    (GdkDrawable      *drawable,
102                                     GdkGC            *gc,
103                                     PangoFont        *font,
104                                     gint              x,
105                                     gint              y,
106                                     PangoGlyphString *glyphs);
107 static void gdk_x11_draw_image     (GdkDrawable     *drawable,
108                                     GdkGC           *gc,
109                                     GdkImage        *image,
110                                     gint             xsrc,
111                                     gint             ysrc,
112                                     gint             xdest,
113                                     gint             ydest,
114                                     gint             width,
115                                     gint             height);
116
117 static void gdk_x11_set_colormap   (GdkDrawable    *drawable,
118                                     GdkColormap    *colormap);
119
120 static GdkColormap* gdk_x11_get_colormap   (GdkDrawable    *drawable);
121
122 static gint         gdk_x11_get_depth      (GdkDrawable    *drawable);
123
124 static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass);
125
126 static gpointer parent_class = NULL;
127
128 GType
129 gdk_drawable_impl_x11_get_type (void)
130 {
131   static GType object_type = 0;
132
133   if (!object_type)
134     {
135       static const GTypeInfo object_info =
136       {
137         sizeof (GdkDrawableImplX11Class),
138         (GBaseInitFunc) NULL,
139         (GBaseFinalizeFunc) NULL,
140         (GClassInitFunc) gdk_drawable_impl_x11_class_init,
141         NULL,           /* class_finalize */
142         NULL,           /* class_data */
143         sizeof (GdkDrawableImplX11),
144         0,              /* n_preallocs */
145         (GInstanceInitFunc) NULL,
146       };
147       
148       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
149                                             "GdkDrawableImplX11",
150                                             &object_info);
151     }
152   
153   return object_type;
154 }
155
156 static void
157 gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
158 {
159   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
160
161   parent_class = g_type_class_peek_parent (klass);
162
163   drawable_class->create_gc = _gdk_x11_gc_new;
164   drawable_class->draw_rectangle = gdk_x11_draw_rectangle;
165   drawable_class->draw_arc = gdk_x11_draw_arc;
166   drawable_class->draw_polygon = gdk_x11_draw_polygon;
167   drawable_class->draw_text = gdk_x11_draw_text;
168   drawable_class->draw_text_wc = gdk_x11_draw_text_wc;
169   drawable_class->draw_drawable = gdk_x11_draw_drawable;
170   drawable_class->draw_points = gdk_x11_draw_points;
171   drawable_class->draw_segments = gdk_x11_draw_segments;
172   drawable_class->draw_lines = gdk_x11_draw_lines;
173   drawable_class->draw_glyphs = gdk_x11_draw_glyphs;
174   drawable_class->draw_image = gdk_x11_draw_image;
175   
176   drawable_class->set_colormap = gdk_x11_set_colormap;
177   drawable_class->get_colormap = gdk_x11_get_colormap;
178
179   drawable_class->get_depth = gdk_x11_get_depth;
180 }
181
182 /*****************************************************
183  * X11 specific implementations of generic functions *
184  *****************************************************/
185
186 static GdkColormap*
187 gdk_x11_get_colormap (GdkDrawable *drawable)
188 {
189   GdkDrawableImplX11 *impl;
190
191   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
192
193   return impl->colormap;
194 }
195
196 static void
197 gdk_x11_set_colormap (GdkDrawable *drawable,
198                       GdkColormap *colormap)
199 {
200   GdkDrawableImplX11 *impl;
201   
202   g_return_if_fail (colormap != NULL);  
203
204   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
205
206   if (impl->colormap == colormap)
207     return;
208   
209   if (impl->colormap)
210     gdk_colormap_unref (impl->colormap);
211   impl->colormap = colormap;
212   if (impl->colormap)
213     gdk_colormap_ref (impl->colormap);
214 }
215
216 /* Drawing
217  */
218
219 static void
220 gdk_x11_draw_rectangle (GdkDrawable *drawable,
221                         GdkGC       *gc,
222                         gint         filled,
223                         gint         x,
224                         gint         y,
225                         gint         width,
226                         gint         height)
227 {
228   GdkDrawableImplX11 *impl;
229
230   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
231   
232   if (filled)
233     XFillRectangle (impl->xdisplay, impl->xid,
234                     GDK_GC_GET_XGC (gc), x, y, width, height);
235   else
236     XDrawRectangle (impl->xdisplay, impl->xid,
237                     GDK_GC_GET_XGC (gc), x, y, width, height);
238 }
239
240 static void
241 gdk_x11_draw_arc (GdkDrawable *drawable,
242                   GdkGC       *gc,
243                   gint         filled,
244                   gint         x,
245                   gint         y,
246                   gint         width,
247                   gint         height,
248                   gint         angle1,
249                   gint         angle2)
250 {
251   GdkDrawableImplX11 *impl;
252
253   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
254
255   
256   if (filled)
257     XFillArc (impl->xdisplay, impl->xid,
258               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
259   else
260     XDrawArc (impl->xdisplay, impl->xid,
261               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
262 }
263
264 static void
265 gdk_x11_draw_polygon (GdkDrawable *drawable,
266                       GdkGC       *gc,
267                       gint         filled,
268                       GdkPoint    *points,
269                       gint         npoints)
270 {
271   XPoint *tmp_points;
272   gint tmp_npoints, i;
273   GdkDrawableImplX11 *impl;
274
275   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
276
277   
278   if (!filled &&
279       (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
280     {
281       tmp_npoints = npoints + 1;
282       tmp_points = g_new (XPoint, tmp_npoints);
283       tmp_points[npoints].x = points[0].x;
284       tmp_points[npoints].y = points[0].y;
285     }
286   else
287     {
288       tmp_npoints = npoints;
289       tmp_points = g_new (XPoint, tmp_npoints);
290     }
291
292   for (i=0; i<npoints; i++)
293     {
294       tmp_points[i].x = points[i].x;
295       tmp_points[i].y = points[i].y;
296     }
297   
298   if (filled)
299     XFillPolygon (impl->xdisplay, impl->xid,
300                   GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
301   else
302     XDrawLines (impl->xdisplay, impl->xid,
303                 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
304
305   g_free (tmp_points);
306 }
307
308 /* gdk_x11_draw_text
309  *
310  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
311  *
312  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
313  */
314 static void
315 gdk_x11_draw_text (GdkDrawable *drawable,
316                    GdkFont     *font,
317                    GdkGC       *gc,
318                    gint         x,
319                    gint         y,
320                    const gchar *text,
321                    gint         text_length)
322 {
323   GdkDrawableImplX11 *impl;
324
325   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
326   
327   if (font->type == GDK_FONT_FONT)
328     {
329       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
330       XSetFont(impl->xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
331       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
332         {
333           XDrawString (impl->xdisplay, impl->xid,
334                        GDK_GC_GET_XGC (gc), x, y, text, text_length);
335         }
336       else
337         {
338           XDrawString16 (impl->xdisplay, impl->xid,
339                          GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
340         }
341     }
342   else if (font->type == GDK_FONT_FONTSET)
343     {
344       XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
345       XmbDrawString (impl->xdisplay, impl->xid,
346                      fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
347     }
348   else
349     g_error("undefined font type\n");
350 }
351
352 static void
353 gdk_x11_draw_text_wc (GdkDrawable    *drawable,
354                       GdkFont        *font,
355                       GdkGC          *gc,
356                       gint            x,
357                       gint            y,
358                       const GdkWChar *text,
359                       gint            text_length)
360 {
361   GdkDrawableImplX11 *impl;
362
363   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
364   
365   if (font->type == GDK_FONT_FONT)
366     {
367       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
368       gchar *text_8bit;
369       gint i;
370       XSetFont(impl->xdisplay, GDK_GC_GET_XGC (gc), xfont->fid);
371       text_8bit = g_new (gchar, text_length);
372       for (i=0; i<text_length; i++) text_8bit[i] = text[i];
373       XDrawString (impl->xdisplay, impl->xid,
374                    GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
375       g_free (text_8bit);
376     }
377   else if (font->type == GDK_FONT_FONTSET)
378     {
379       if (sizeof(GdkWChar) == sizeof(wchar_t))
380         {
381           XwcDrawString (impl->xdisplay, impl->xid,
382                          (XFontSet) GDK_FONT_XFONT (font),
383                          GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
384         }
385       else
386         {
387           wchar_t *text_wchar;
388           gint i;
389           text_wchar = g_new (wchar_t, text_length);
390           for (i=0; i<text_length; i++) text_wchar[i] = text[i];
391           XwcDrawString (impl->xdisplay, impl->xid,
392                          (XFontSet) GDK_FONT_XFONT (font),
393                          GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
394           g_free (text_wchar);
395         }
396     }
397   else
398     g_error("undefined font type\n");
399 }
400
401 static void
402 gdk_x11_draw_drawable (GdkDrawable *drawable,
403                        GdkGC       *gc,
404                        GdkPixmap   *src,
405                        gint         xsrc,
406                        gint         ysrc,
407                        gint         xdest,
408                        gint         ydest,
409                        gint         width,
410                        gint         height)
411 {
412   int src_depth = gdk_drawable_get_depth (src);
413   int dest_depth = gdk_drawable_get_depth (drawable);
414   GdkDrawableImplX11 *impl;
415
416   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
417   
418   if (src_depth == 1)
419     {
420       XCopyArea (impl->xdisplay,
421                  GDK_DRAWABLE_XID (src),
422                  impl->xid,
423                  GDK_GC_GET_XGC (gc),
424                  xsrc, ysrc,
425                  width, height,
426                  xdest, ydest);
427     }
428   else if (dest_depth != 0 && src_depth == dest_depth)
429     {
430       XCopyArea (impl->xdisplay,
431                  GDK_DRAWABLE_XID (src),
432                  impl->xid,
433                  GDK_GC_GET_XGC (gc),
434                  xsrc, ysrc,
435                  width, height,
436                  xdest, ydest);
437     }
438   else
439     g_warning ("Attempt to copy between drawables of mismatched depths!\n");
440 }
441
442 static void
443 gdk_x11_draw_points (GdkDrawable *drawable,
444                      GdkGC       *gc,
445                      GdkPoint    *points,
446                      gint         npoints)
447 {
448   GdkDrawableImplX11 *impl;
449
450   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
451
452   
453   /* We special-case npoints == 1, because X will merge multiple
454    * consecutive XDrawPoint requests into a PolyPoint request
455    */
456   if (npoints == 1)
457     {
458       XDrawPoint (impl->xdisplay,
459                   impl->xid,
460                   GDK_GC_GET_XGC (gc),
461                   points[0].x, points[0].y);
462     }
463   else
464     {
465       gint i;
466       XPoint *tmp_points = g_new (XPoint, npoints);
467
468       for (i=0; i<npoints; i++)
469         {
470           tmp_points[i].x = points[i].x;
471           tmp_points[i].y = points[i].y;
472         }
473       
474       XDrawPoints (impl->xdisplay,
475                    impl->xid,
476                    GDK_GC_GET_XGC (gc),
477                    tmp_points,
478                    npoints,
479                    CoordModeOrigin);
480
481       g_free (tmp_points);
482     }
483 }
484
485 static void
486 gdk_x11_draw_segments (GdkDrawable *drawable,
487                        GdkGC       *gc,
488                        GdkSegment  *segs,
489                        gint         nsegs)
490 {
491   GdkDrawableImplX11 *impl;
492
493   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
494
495   
496   /* We special-case nsegs == 1, because X will merge multiple
497    * consecutive XDrawLine requests into a PolySegment request
498    */
499   if (nsegs == 1)
500     {
501       XDrawLine (impl->xdisplay, impl->xid,
502                  GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
503                  segs[0].x2, segs[0].y2);
504     }
505   else
506     {
507       gint i;
508       XSegment *tmp_segs = g_new (XSegment, nsegs);
509
510       for (i=0; i<nsegs; i++)
511         {
512           tmp_segs[i].x1 = segs[i].x1;
513           tmp_segs[i].x2 = segs[i].x2;
514           tmp_segs[i].y1 = segs[i].y1;
515           tmp_segs[i].y2 = segs[i].y2;
516         }
517       
518       XDrawSegments (impl->xdisplay,
519                      impl->xid,
520                      GDK_GC_GET_XGC (gc),
521                      tmp_segs, nsegs);
522
523       g_free (tmp_segs);
524     }
525 }
526
527 static void
528 gdk_x11_draw_lines (GdkDrawable *drawable,
529                     GdkGC       *gc,
530                     GdkPoint    *points,
531                     gint         npoints)
532 {
533   gint i;
534   XPoint *tmp_points = g_new (XPoint, npoints);
535   GdkDrawableImplX11 *impl;
536
537   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
538
539   
540   for (i=0; i<npoints; i++)
541     {
542       tmp_points[i].x = points[i].x;
543       tmp_points[i].y = points[i].y;
544     }
545       
546   XDrawLines (impl->xdisplay,
547               impl->xid,
548               GDK_GC_GET_XGC (gc),
549               tmp_points, npoints,
550               CoordModeOrigin);
551
552   g_free (tmp_points);
553 }
554
555 static void
556 gdk_x11_draw_glyphs (GdkDrawable      *drawable,
557                      GdkGC            *gc,
558                      PangoFont        *font,
559                      gint              x,
560                      gint              y,
561                      PangoGlyphString *glyphs)
562 {
563   GdkDrawableImplX11 *impl;
564
565   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
566
567   pango_x_render (impl->xdisplay,
568                   impl->xid,
569                   GDK_GC_GET_XGC (gc),
570                   font, glyphs, x, y);
571 }
572
573 static void
574 gdk_x11_draw_image     (GdkDrawable     *drawable,
575                         GdkGC           *gc,
576                         GdkImage        *image,
577                         gint             xsrc,
578                         gint             ysrc,
579                         gint             xdest,
580                         gint             ydest,
581                         gint             width,
582                         gint             height)
583 {
584   GdkDrawableImplX11 *impl;
585   
586   impl = GDK_DRAWABLE_IMPL_X11 (drawable);
587
588   if (image->type == GDK_IMAGE_SHARED)
589     XShmPutImage (impl->xdisplay, impl->xid,
590                   GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
591                   xsrc, ysrc, xdest, ydest, width, height, False);
592   else
593     XPutImage (impl->xdisplay, impl->xid,
594                GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
595                xsrc, ysrc, xdest, ydest, width, height);
596 }
597
598 static gint
599 gdk_x11_get_depth (GdkDrawable *drawable)
600 {
601   /* This is a bit bogus but I'm not sure the other way is better */
602
603   return gdk_drawable_get_depth (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
604 }
605