]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdrawable-x11.c
Merge no-flicker branch into HEAD
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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
29 static void    gdk_x11_drawable_destroy   (GdkDrawable     *drawable);
30
31 static void gdk_x11_draw_rectangle (GdkDrawable    *drawable,
32                                     GdkGC          *gc,
33                                     gint            filled,
34                                     gint            x,
35                                     gint            y,
36                                     gint            width,
37                                     gint            height);
38 static void gdk_x11_draw_arc       (GdkDrawable    *drawable,
39                                     GdkGC          *gc,
40                                     gint            filled,
41                                     gint            x,
42                                     gint            y,
43                                     gint            width,
44                                     gint            height,
45                                     gint            angle1,
46                                     gint            angle2);
47 static void gdk_x11_draw_polygon   (GdkDrawable    *drawable,
48                                     GdkGC          *gc,
49                                     gint            filled,
50                                     GdkPoint       *points,
51                                     gint            npoints);
52 static void gdk_x11_draw_text      (GdkDrawable    *drawable,
53                                     GdkFont        *font,
54                                     GdkGC          *gc,
55                                     gint            x,
56                                     gint            y,
57                                     const gchar    *text,
58                                     gint            text_length);
59 static void gdk_x11_draw_text_wc   (GdkDrawable    *drawable,
60                                     GdkFont        *font,
61                                     GdkGC          *gc,
62                                     gint            x,
63                                     gint            y,
64                                     const GdkWChar *text,
65                                     gint            text_length);
66 static void gdk_x11_draw_drawable  (GdkDrawable    *drawable,
67                                     GdkGC          *gc,
68                                     GdkPixmap      *src,
69                                     gint            xsrc,
70                                     gint            ysrc,
71                                     gint            xdest,
72                                     gint            ydest,
73                                     gint            width,
74                                     gint            height);
75 static void gdk_x11_draw_points    (GdkDrawable    *drawable,
76                                     GdkGC          *gc,
77                                     GdkPoint       *points,
78                                     gint            npoints);
79 static void gdk_x11_draw_segments  (GdkDrawable    *drawable,
80                                     GdkGC          *gc,
81                                     GdkSegment     *segs,
82                                     gint            nsegs);
83 static void gdk_x11_draw_lines     (GdkDrawable    *drawable,
84                                     GdkGC          *gc,
85                                     GdkPoint       *points,
86                                     gint            npoints);
87
88
89 GdkDrawableClass _gdk_x11_drawable_class = {
90   gdk_x11_drawable_destroy,
91   _gdk_x11_gc_new,
92   gdk_x11_draw_rectangle,
93   gdk_x11_draw_arc,
94   gdk_x11_draw_polygon,
95   gdk_x11_draw_text,
96   gdk_x11_draw_text_wc,
97   gdk_x11_draw_drawable,
98   gdk_x11_draw_points,
99   gdk_x11_draw_segments,
100   gdk_x11_draw_lines
101 };
102
103 /*****************************************************
104  * X11 specific implementations of generic functions *
105  *****************************************************/
106
107 GdkColormap*
108 gdk_drawable_get_colormap (GdkDrawable *drawable)
109 {
110   GdkDrawablePrivate *drawable_private;
111   XWindowAttributes window_attributes;
112   
113   g_return_val_if_fail (drawable != NULL, NULL);
114   drawable_private = (GdkDrawablePrivate*) drawable;
115   
116   if (!GDK_DRAWABLE_DESTROYED (drawable))
117     {
118       if (drawable_private->colormap == NULL &&
119           GDK_IS_WINDOW (drawable))
120         {
121           XGetWindowAttributes (GDK_DRAWABLE_XDISPLAY (drawable),
122                                 GDK_DRAWABLE_XID (drawable),
123                                 &window_attributes);
124           drawable_private->colormap =  gdk_colormap_lookup (window_attributes.colormap);
125         }
126
127       return drawable_private->colormap;
128     }
129   
130   return NULL;
131 }
132
133 void
134 gdk_drawable_set_colormap (GdkDrawable *drawable,
135                            GdkColormap *colormap)
136 {
137   GdkDrawablePrivate *drawable_private;
138   GdkColormapPrivateX *colormap_private;
139   
140   g_return_if_fail (drawable != NULL);
141   g_return_if_fail (colormap != NULL);
142   
143   drawable_private = (GdkDrawablePrivate *)drawable;
144   colormap_private = (GdkColormapPrivateX *)colormap;
145   
146   if (!GDK_DRAWABLE_DESTROYED (drawable))
147     {
148       if (GDK_IS_WINDOW (drawable))
149         {
150           g_return_if_fail (colormap_private->base.visual !=
151                             ((GdkColormapPrivate *)(drawable_private->colormap))->visual);
152
153           XSetWindowColormap (GDK_DRAWABLE_XDISPLAY (drawable),
154                               GDK_DRAWABLE_XID (drawable),
155                               colormap_private->xcolormap);
156         }
157
158       if (drawable_private->colormap)
159         gdk_colormap_unref (drawable_private->colormap);
160       drawable_private->colormap = colormap;
161       gdk_colormap_ref (drawable_private->colormap);
162
163       if (GDK_IS_WINDOW (drawable) &&
164           drawable_private->window_type != GDK_WINDOW_TOPLEVEL)
165         gdk_window_add_colormap_windows (drawable);
166     }
167 }
168
169 /* Drawing
170  */
171 static void 
172 gdk_x11_drawable_destroy (GdkDrawable *drawable)
173 {
174   
175 }
176
177 static void
178 gdk_x11_draw_rectangle (GdkDrawable *drawable,
179                         GdkGC       *gc,
180                         gint         filled,
181                         gint         x,
182                         gint         y,
183                         gint         width,
184                         gint         height)
185 {
186   if (filled)
187     XFillRectangle (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
188                     GDK_GC_GET_XGC (gc), x, y, width, height);
189   else
190     XDrawRectangle (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
191                     GDK_GC_GET_XGC (gc), x, y, width, height);
192 }
193
194 static void
195 gdk_x11_draw_arc (GdkDrawable *drawable,
196                   GdkGC       *gc,
197                   gint         filled,
198                   gint         x,
199                   gint         y,
200                   gint         width,
201                   gint         height,
202                   gint         angle1,
203                   gint         angle2)
204 {
205   if (filled)
206     XFillArc (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
207               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
208   else
209     XDrawArc (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
210               GDK_GC_GET_XGC (gc), x, y, width, height, angle1, angle2);
211 }
212
213 static void
214 gdk_x11_draw_polygon (GdkDrawable *drawable,
215                       GdkGC       *gc,
216                       gint         filled,
217                       GdkPoint    *points,
218                       gint         npoints)
219 {
220   XPoint *tmp_points;
221   gint tmp_npoints, i;
222
223   if (!filled &&
224       (points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
225     {
226       tmp_npoints = npoints + 1;
227       tmp_points = g_new (XPoint, tmp_npoints);
228       tmp_points[npoints].x = points[0].x;
229       tmp_points[npoints].y = points[0].y;
230     }
231   else
232     {
233       tmp_npoints = npoints;
234       tmp_points = g_new (XPoint, tmp_npoints);
235     }
236
237   for (i=0; i<npoints; i++)
238     {
239       tmp_points[i].x = points[i].x;
240       tmp_points[i].y = points[i].y;
241     }
242   
243   if (filled)
244     XFillPolygon (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
245                   GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, Complex, CoordModeOrigin);
246   else
247     XDrawLines (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
248                 GDK_GC_GET_XGC (gc), tmp_points, tmp_npoints, CoordModeOrigin);
249
250   g_free (tmp_points);
251 }
252
253 /* gdk_x11_draw_text
254  *
255  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
256  *
257  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
258  */
259 static void
260 gdk_x11_draw_text (GdkDrawable *drawable,
261                    GdkFont     *font,
262                    GdkGC       *gc,
263                    gint         x,
264                    gint         y,
265                    const gchar *text,
266                    gint         text_length)
267 {
268   if (font->type == GDK_FONT_FONT)
269     {
270       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
271       XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_GET_XGC (gc), xfont->fid);
272       if ((xfont->min_byte1 == 0) && (xfont->max_byte1 == 0))
273         {
274           XDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
275                        GDK_GC_GET_XGC (gc), x, y, text, text_length);
276         }
277       else
278         {
279           XDrawString16 (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
280                          GDK_GC_GET_XGC (gc), x, y, (XChar2b *) text, text_length / 2);
281         }
282     }
283   else if (font->type == GDK_FONT_FONTSET)
284     {
285       XFontSet fontset = (XFontSet) GDK_FONT_XFONT (font);
286       XmbDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
287                      fontset, GDK_GC_GET_XGC (gc), x, y, text, text_length);
288     }
289   else
290     g_error("undefined font type\n");
291 }
292
293 static void
294 gdk_x11_draw_text_wc (GdkDrawable    *drawable,
295                       GdkFont        *font,
296                       GdkGC          *gc,
297                       gint            x,
298                       gint            y,
299                       const GdkWChar *text,
300                       gint            text_length)
301 {
302   if (font->type == GDK_FONT_FONT)
303     {
304       XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
305       gchar *text_8bit;
306       gint i;
307       XSetFont(GDK_DRAWABLE_XDISPLAY (drawable), GDK_GC_GET_XGC (gc), xfont->fid);
308       text_8bit = g_new (gchar, text_length);
309       for (i=0; i<text_length; i++) text_8bit[i] = text[i];
310       XDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
311                    GDK_GC_GET_XGC (gc), x, y, text_8bit, text_length);
312       g_free (text_8bit);
313     }
314   else if (font->type == GDK_FONT_FONTSET)
315     {
316       if (sizeof(GdkWChar) == sizeof(wchar_t))
317         {
318           XwcDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
319                          (XFontSet) GDK_FONT_XFONT (font),
320                          GDK_GC_GET_XGC (gc), x, y, (wchar_t *)text, text_length);
321         }
322       else
323         {
324           wchar_t *text_wchar;
325           gint i;
326           text_wchar = g_new (wchar_t, text_length);
327           for (i=0; i<text_length; i++) text_wchar[i] = text[i];
328           XwcDrawString (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
329                          (XFontSet) GDK_FONT_XFONT (font),
330                          GDK_GC_GET_XGC (gc), x, y, text_wchar, text_length);
331           g_free (text_wchar);
332         }
333     }
334   else
335     g_error("undefined font type\n");
336 }
337
338 static void
339 gdk_x11_draw_drawable (GdkDrawable *drawable,
340                        GdkGC       *gc,
341                        GdkPixmap   *src,
342                        gint         xsrc,
343                        gint         ysrc,
344                        gint         xdest,
345                        gint         ydest,
346                        gint         width,
347                        gint         height)
348 {
349   int src_depth = gdk_drawable_get_depth (src);
350   int dest_depth = gdk_drawable_get_depth (drawable);
351
352   if (src_depth == 1)
353     {
354       XCopyArea (GDK_DRAWABLE_XDISPLAY (drawable),
355                  GDK_DRAWABLE_XID (src),
356                  GDK_DRAWABLE_XID (drawable),
357                  GDK_GC_GET_XGC (gc),
358                  xsrc, ysrc,
359                  width, height,
360                  xdest, ydest);
361     }
362   else if (dest_depth != 0 && src_depth == dest_depth)
363     {
364       XCopyArea (GDK_DRAWABLE_XDISPLAY (drawable),
365                  GDK_DRAWABLE_XID (src),
366                  GDK_DRAWABLE_XID (drawable),
367                  GDK_GC_GET_XGC (gc),
368                  xsrc, ysrc,
369                  width, height,
370                  xdest, ydest);
371     }
372   else
373     g_warning ("Attempt to copy between drawables of mismatched depths!\n");
374 }
375
376 static void
377 gdk_x11_draw_points (GdkDrawable *drawable,
378                      GdkGC       *gc,
379                      GdkPoint    *points,
380                      gint         npoints)
381 {
382   /* We special-case npoints == 1, because X will merge multiple
383    * consecutive XDrawPoint requests into a PolyPoint request
384    */
385   if (npoints == 1)
386     {
387       XDrawPoint (GDK_DRAWABLE_XDISPLAY (drawable),
388                   GDK_DRAWABLE_XID (drawable),
389                   GDK_GC_GET_XGC (gc),
390                   points[0].x, points[0].y);
391     }
392   else
393     {
394       gint i;
395       XPoint *tmp_points = g_new (XPoint, npoints);
396
397       for (i=0; i<npoints; i++)
398         {
399           tmp_points[i].x = points[i].x;
400           tmp_points[i].y = points[i].y;
401         }
402       
403       XDrawPoints (GDK_DRAWABLE_XDISPLAY (drawable),
404                    GDK_DRAWABLE_XID (drawable),
405                    GDK_GC_GET_XGC (gc),
406                    tmp_points,
407                    npoints,
408                    CoordModeOrigin);
409
410       g_free (tmp_points);
411     }
412 }
413
414 static void
415 gdk_x11_draw_segments (GdkDrawable *drawable,
416                        GdkGC       *gc,
417                        GdkSegment  *segs,
418                        gint         nsegs)
419 {
420   /* We special-case nsegs == 1, because X will merge multiple
421    * consecutive XDrawLine requests into a PolySegment request
422    */
423   if (nsegs == 1)
424     {
425       XDrawLine (GDK_DRAWABLE_XDISPLAY (drawable), GDK_DRAWABLE_XID (drawable),
426                  GDK_GC_GET_XGC (gc), segs[0].x1, segs[0].y1,
427                  segs[0].x2, segs[0].y2);
428     }
429   else
430     {
431       gint i;
432       XSegment *tmp_segs = g_new (XSegment, nsegs);
433
434       for (i=0; i<nsegs; i++)
435         {
436           tmp_segs[i].x1 = segs[i].x1;
437           tmp_segs[i].x2 = segs[i].x2;
438           tmp_segs[i].y1 = segs[i].y1;
439           tmp_segs[i].y2 = segs[i].y2;
440         }
441       
442       XDrawSegments (GDK_DRAWABLE_XDISPLAY (drawable),
443                      GDK_DRAWABLE_XID (drawable),
444                      GDK_GC_GET_XGC (gc),
445                      tmp_segs, nsegs);
446
447       g_free (tmp_segs);
448     }
449 }
450
451 static void
452 gdk_x11_draw_lines (GdkDrawable *drawable,
453                     GdkGC       *gc,
454                     GdkPoint    *points,
455                     gint         npoints)
456 {
457   gint i;
458   XPoint *tmp_points = g_new (XPoint, npoints);
459
460   for (i=0; i<npoints; i++)
461     {
462       tmp_points[i].x = points[i].x;
463       tmp_points[i].y = points[i].y;
464     }
465       
466   XDrawLines (GDK_DRAWABLE_XDISPLAY (drawable),
467               GDK_DRAWABLE_XID (drawable),
468               GDK_GC_GET_XGC (gc),
469               tmp_points, npoints,
470               CoordModeOrigin);
471
472   g_free (tmp_points);
473 }