]> Pileus Git - ~andy/gtk/blob - gdk/gdkgc.c
gdk/gdkgc.c: If gdk_gc_set_clip_rectangle is called with
[~andy/gtk] / gdk / gdkgc.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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <string.h>
19 #include <X11/Xlib.h>
20 #include "gdk.h"
21 #include "gdkprivate.h"
22
23
24 GdkGC*
25 gdk_gc_new (GdkWindow *window)
26 {
27   return gdk_gc_new_with_values (window, NULL, 0);
28 }
29
30 GdkGC*
31 gdk_gc_new_with_values (GdkWindow       *window,
32                         GdkGCValues     *values,
33                         GdkGCValuesMask  values_mask)
34 {
35   GdkGC *gc;
36   GdkGCPrivate *private;
37   Window xwindow;
38   XGCValues xvalues;
39   unsigned long xvalues_mask;
40
41   private = g_new (GdkGCPrivate, 1);
42   gc = (GdkGC*) private;
43
44   xwindow = ((GdkWindowPrivate*) window)->xwindow;
45   private->xdisplay = ((GdkWindowPrivate*) window)->xdisplay;
46
47   xvalues.function = GXcopy;
48   xvalues.fill_style = FillSolid;
49   xvalues.arc_mode = ArcPieSlice;
50   xvalues.subwindow_mode = ClipByChildren;
51   xvalues.graphics_exposures = True;
52   xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
53
54   if (values_mask & GDK_GC_FOREGROUND)
55     {
56       xvalues.foreground = values->foreground.pixel;
57       xvalues_mask |= GCForeground;
58     }
59   if (values_mask & GDK_GC_BACKGROUND)
60     {
61       xvalues.background = values->background.pixel;
62       xvalues_mask |= GCBackground;
63     }
64   if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
65     {
66       xvalues.font = ((XFontStruct *) ((GdkFontPrivate*) values->font)->xfont)->fid;
67       xvalues_mask |= GCFont;
68     }
69   if (values_mask & GDK_GC_FUNCTION)
70     {
71       switch (values->function)
72         {
73         case GDK_COPY:
74           xvalues.function = GXcopy;
75           break;
76         case GDK_INVERT:
77           xvalues.function = GXinvert;
78           break;
79         case GDK_XOR:
80           xvalues.function = GXxor;
81           break;
82         }
83       xvalues_mask |= GCFunction;
84     }
85   if (values_mask & GDK_GC_FILL)
86     {
87       switch (values->fill)
88         {
89         case GDK_SOLID:
90           xvalues.fill_style = FillSolid;
91           break;
92         case GDK_TILED:
93           xvalues.fill_style = FillTiled;
94           break;
95         case GDK_STIPPLED:
96           xvalues.fill_style = FillStippled;
97           break;
98         case GDK_OPAQUE_STIPPLED:
99           xvalues.fill_style = FillOpaqueStippled;
100           break;
101         }
102       xvalues_mask |= GCFillStyle;
103     }
104   if (values_mask & GDK_GC_TILE)
105     {
106       xvalues.tile = ((GdkPixmapPrivate*) values->tile)->xwindow;
107       xvalues_mask |= GCTile;
108     }
109   if (values_mask & GDK_GC_STIPPLE)
110     {
111       xvalues.stipple = ((GdkPixmapPrivate*) values->stipple)->xwindow;
112       xvalues_mask |= GCStipple;
113     }
114   if (values_mask & GDK_GC_CLIP_MASK)
115     {
116       xvalues.clip_mask = ((GdkPixmapPrivate*) values->clip_mask)->xwindow;
117       xvalues_mask |= GCClipMask;
118     }
119   if (values_mask & GDK_GC_SUBWINDOW)
120     {
121       xvalues.subwindow_mode = values->subwindow_mode;
122       xvalues_mask |= GCSubwindowMode;
123     }
124   if (values_mask & GDK_GC_TS_X_ORIGIN)
125     {
126       xvalues.ts_x_origin = values->ts_x_origin;
127       xvalues_mask |= GCTileStipXOrigin;
128     }
129   if (values_mask & GDK_GC_TS_Y_ORIGIN)
130     {
131       xvalues.ts_y_origin = values->ts_y_origin;
132       xvalues_mask |= GCTileStipYOrigin;
133     }
134   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
135     {
136       xvalues.clip_x_origin = values->clip_x_origin;
137       xvalues_mask |= GCClipXOrigin;
138     }
139   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
140     {
141       xvalues.clip_y_origin = values->clip_y_origin;
142       xvalues_mask |= GCClipYOrigin;
143     }
144   if (values_mask & GDK_GC_EXPOSURES)
145     {
146       xvalues.graphics_exposures = values->graphics_exposures;
147       xvalues_mask |= GCGraphicsExposures;
148     }
149   if (values_mask & GDK_GC_LINE_WIDTH)
150     {
151       xvalues.line_width = values->line_width;
152       xvalues_mask |= GCLineWidth;
153     }
154   if (values_mask & GDK_GC_LINE_STYLE)
155     {
156       switch (values->line_style)
157         {
158         case GDK_LINE_SOLID:
159           xvalues.line_style = LineSolid;
160           break;
161         case GDK_LINE_ON_OFF_DASH:
162           xvalues.line_style = LineOnOffDash;
163           break;
164         case GDK_LINE_DOUBLE_DASH:
165           xvalues.line_style = LineDoubleDash;
166           break;
167         }
168       xvalues_mask |= GCLineStyle;
169     }
170   if (values_mask & GDK_GC_CAP_STYLE)
171     {
172       switch (values->cap_style)
173         {
174         case GDK_CAP_NOT_LAST:
175           xvalues.cap_style = CapNotLast;
176           break;
177         case GDK_CAP_BUTT:
178           xvalues.cap_style = CapButt;
179           break;
180         case GDK_CAP_ROUND:
181           xvalues.cap_style = CapRound;
182           break;
183         case GDK_CAP_PROJECTING:
184           xvalues.cap_style = CapProjecting;
185           break;
186         }
187       xvalues_mask |= GCCapStyle;
188     }
189   if (values_mask & GDK_GC_JOIN_STYLE)
190     {
191       switch (values->join_style)
192         {
193         case GDK_JOIN_MITER:
194           xvalues.join_style = JoinMiter;
195           break;
196         case GDK_JOIN_ROUND:
197           xvalues.join_style = JoinRound;
198           break;
199         case GDK_JOIN_BEVEL:
200           xvalues.join_style = JoinBevel;
201           break;
202         }
203       xvalues_mask |= GCJoinStyle;
204     }
205
206   private->xgc = XCreateGC (private->xdisplay, xwindow, xvalues_mask, &xvalues);
207
208   return gc;
209 }
210
211 void
212 gdk_gc_destroy (GdkGC *gc)
213 {
214   GdkGCPrivate *private;
215
216   g_return_if_fail (gc != NULL);
217
218   private = (GdkGCPrivate*) gc;
219   XFreeGC (private->xdisplay, private->xgc);
220
221   memset (gc, 0, sizeof (GdkGCPrivate));
222   g_free (gc);
223 }
224
225 void
226 gdk_gc_get_values (GdkGC       *gc,
227                    GdkGCValues *values)
228 {
229   GdkGCPrivate *private;
230   XGCValues xvalues;
231
232   g_return_if_fail (gc != NULL);
233   g_return_if_fail (values != NULL);
234
235   private = (GdkGCPrivate*) gc;
236
237   if (XGetGCValues (private->xdisplay, private->xgc,
238                     GCForeground | GCBackground | GCFont |
239                     GCFunction | GCTile | GCStipple | /* GCClipMask | */
240                     GCSubwindowMode | GCGraphicsExposures |
241                     GCTileStipXOrigin | GCTileStipYOrigin |
242                     GCClipXOrigin | GCClipYOrigin |
243                     GCLineWidth | GCLineStyle | GCCapStyle |
244                     GCFillStyle | GCJoinStyle, &xvalues))
245     {
246       values->foreground.pixel = xvalues.foreground;
247       values->background.pixel = xvalues.background;
248       values->font = gdk_font_lookup (xvalues.font);
249
250       switch (xvalues.function)
251         {
252         case GXcopy:
253           values->function = GDK_COPY;
254           break;
255         case GXinvert:
256           values->function = GDK_INVERT;
257           break;
258         case GXxor:
259           values->function = GDK_XOR;
260           break;
261         }
262
263       switch (xvalues.fill_style)
264         {
265         case FillSolid:
266           values->fill = GDK_SOLID;
267           break;
268         case FillTiled:
269           values->fill = GDK_TILED;
270           break;
271         case FillStippled:
272           values->fill = GDK_STIPPLED;
273           break;
274         case FillOpaqueStippled:
275           values->fill = GDK_OPAQUE_STIPPLED;
276           break;
277         }
278
279       values->tile = gdk_pixmap_lookup (xvalues.tile);
280       values->stipple = gdk_pixmap_lookup (xvalues.stipple);
281       values->clip_mask = NULL;
282       values->subwindow_mode = xvalues.subwindow_mode;
283       values->ts_x_origin = xvalues.ts_x_origin;
284       values->ts_y_origin = xvalues.ts_y_origin;
285       values->clip_x_origin = xvalues.clip_x_origin;
286       values->clip_y_origin = xvalues.clip_y_origin;
287       values->graphics_exposures = xvalues.graphics_exposures;
288       values->line_width = xvalues.line_width;
289
290       switch (xvalues.line_style)
291         {
292         case LineSolid:
293           values->line_style = GDK_LINE_SOLID;
294           break;
295         case LineOnOffDash:
296           values->line_style = GDK_LINE_ON_OFF_DASH;
297           break;
298         case LineDoubleDash:
299           values->line_style = GDK_LINE_DOUBLE_DASH;
300           break;
301         }
302
303       switch (xvalues.cap_style)
304         {
305         case CapNotLast:
306           values->cap_style = GDK_CAP_NOT_LAST;
307           break;
308         case CapButt:
309           values->cap_style = GDK_CAP_BUTT;
310           break;
311         case CapRound:
312           values->cap_style = GDK_CAP_ROUND;
313           break;
314         case CapProjecting:
315           values->cap_style = GDK_CAP_PROJECTING;
316           break;
317         }
318
319       switch (xvalues.join_style)
320         {
321         case JoinMiter:
322           values->join_style = GDK_JOIN_MITER;
323           break;
324         case JoinRound:
325           values->join_style = GDK_JOIN_ROUND;
326           break;
327         case JoinBevel:
328           values->join_style = GDK_JOIN_BEVEL;
329           break;
330         }
331     }
332   else
333     {
334       memset (values, 0, sizeof (GdkGCValues));
335     }
336 }
337
338 void
339 gdk_gc_set_foreground (GdkGC    *gc,
340                        GdkColor *color)
341 {
342   GdkGCPrivate *private;
343
344   g_return_if_fail (gc != NULL);
345   g_return_if_fail (color != NULL);
346
347   private = (GdkGCPrivate*) gc;
348   XSetForeground (private->xdisplay, private->xgc, color->pixel);
349 }
350
351 void
352 gdk_gc_set_background (GdkGC    *gc,
353                        GdkColor *color)
354 {
355   GdkGCPrivate *private;
356
357   g_return_if_fail (gc != NULL);
358   g_return_if_fail (color != NULL);
359
360   private = (GdkGCPrivate*) gc;
361   XSetBackground (private->xdisplay, private->xgc, color->pixel);
362 }
363
364 void
365 gdk_gc_set_font (GdkGC   *gc,
366                  GdkFont *font)
367 {
368   GdkGCPrivate *gc_private;
369   GdkFontPrivate *font_private;
370
371   g_return_if_fail (gc != NULL);
372   g_return_if_fail (font != NULL);
373
374   if (font->type == GDK_FONT_FONT)
375     {
376       gc_private = (GdkGCPrivate*) gc;
377       font_private = (GdkFontPrivate*) font;
378       
379       XSetFont (gc_private->xdisplay, gc_private->xgc,
380                 ((XFontStruct *) font_private->xfont)->fid);
381     }
382 }
383
384 void
385 gdk_gc_set_function (GdkGC       *gc,
386                      GdkFunction  function)
387 {
388   GdkGCPrivate *private;
389
390   g_return_if_fail (gc != NULL);
391
392   private = (GdkGCPrivate*) gc;
393
394   switch (function)
395     {
396     case GDK_COPY:
397       XSetFunction (private->xdisplay, private->xgc, GXcopy);
398       break;
399     case GDK_INVERT:
400       XSetFunction (private->xdisplay, private->xgc, GXinvert);
401       break;
402     case GDK_XOR:
403       XSetFunction (private->xdisplay, private->xgc, GXor);
404       break;
405     }
406 }
407
408 void
409 gdk_gc_set_fill (GdkGC   *gc,
410                  GdkFill  fill)
411 {
412   GdkGCPrivate *private;
413
414   g_return_if_fail (gc != NULL);
415
416   private = (GdkGCPrivate*) gc;
417
418   switch (fill)
419     {
420     case GDK_SOLID:
421       XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
422       break;
423     case GDK_TILED:
424       XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
425       break;
426     case GDK_STIPPLED:
427       XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
428       break;
429     case GDK_OPAQUE_STIPPLED:
430       XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
431       break;
432     }
433 }
434
435 void
436 gdk_gc_set_tile (GdkGC     *gc,
437                  GdkPixmap *tile)
438 {
439   GdkGCPrivate *private;
440   GdkPixmapPrivate *pixmap_private;
441   Pixmap pixmap;
442
443   g_return_if_fail (gc != NULL);
444
445   private = (GdkGCPrivate*) gc;
446
447   pixmap = None;
448   if (tile)
449     {
450       pixmap_private = (GdkPixmapPrivate*) tile;
451       pixmap = pixmap_private->xwindow;
452     }
453
454   XSetTile (private->xdisplay, private->xgc, pixmap);
455 }
456
457 void
458 gdk_gc_set_stipple (GdkGC     *gc,
459                     GdkPixmap *stipple)
460 {
461   GdkGCPrivate *private;
462   GdkPixmapPrivate *pixmap_private;
463   Pixmap pixmap;
464
465   g_return_if_fail (gc != NULL);
466
467   private = (GdkGCPrivate*) gc;
468
469   pixmap = None;
470   if (stipple)
471     {
472       pixmap_private = (GdkPixmapPrivate*) stipple;
473       pixmap = pixmap_private->xwindow;
474     }
475
476   XSetStipple (private->xdisplay, private->xgc, pixmap);
477 }
478
479 void
480 gdk_gc_set_ts_origin (GdkGC *gc,
481                       gint   x,
482                       gint   y)
483 {
484   GdkGCPrivate *private;
485
486   g_return_if_fail (gc != NULL);
487
488   private = (GdkGCPrivate*) gc;
489
490   XSetTSOrigin (private->xdisplay, private->xgc, x, y);
491 }
492
493 void
494 gdk_gc_set_clip_origin (GdkGC *gc,
495                         gint   x,
496                         gint   y)
497 {
498   GdkGCPrivate *private;
499
500   g_return_if_fail (gc != NULL);
501
502   private = (GdkGCPrivate*) gc;
503
504   XSetClipOrigin (private->xdisplay, private->xgc, x, y);
505 }
506
507 void
508 gdk_gc_set_clip_mask (GdkGC     *gc,
509                       GdkBitmap *mask)
510 {
511   GdkGCPrivate *private;
512   Pixmap xmask;
513
514   g_return_if_fail (gc != NULL);
515
516   private = (GdkGCPrivate*) gc;
517
518   if (mask)
519     xmask = ((GdkWindowPrivate*) mask)->xwindow;
520   else
521     xmask = None;
522
523   XSetClipMask (private->xdisplay, private->xgc, xmask);
524 }
525
526
527 void
528 gdk_gc_set_clip_rectangle (GdkGC        *gc,
529                            GdkRectangle *rectangle)
530 {
531   GdkGCPrivate *private;
532   XRectangle xrectangle;
533
534   g_return_if_fail (gc != NULL);
535
536   private = (GdkGCPrivate*) gc;
537
538   if (rectangle)
539     {
540       xrectangle.x = rectangle->x; 
541       xrectangle.y = rectangle->y;
542       xrectangle.width = rectangle->width;
543       xrectangle.height = rectangle->height;
544       
545       XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
546                           &xrectangle, 1, Unsorted);
547     }
548   else
549     XSetClipMask (private->xdisplay, private->xgc, None);
550
551
552 void
553 gdk_gc_set_subwindow (GdkGC            *gc,
554                       GdkSubwindowMode  mode)
555 {
556   GdkGCPrivate *private;
557
558   g_return_if_fail (gc != NULL);
559
560   private = (GdkGCPrivate*) gc;
561
562   XSetSubwindowMode (private->xdisplay, private->xgc, mode);
563 }
564
565 void
566 gdk_gc_set_exposures (GdkGC *gc,
567                       gint   exposures)
568 {
569   GdkGCPrivate *private;
570
571   g_return_if_fail (gc != NULL);
572
573   private = (GdkGCPrivate*) gc;
574
575   XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
576 }
577
578 void
579 gdk_gc_set_line_attributes (GdkGC       *gc,
580                             gint         line_width,
581                             GdkLineStyle line_style,
582                             GdkCapStyle  cap_style,
583                             GdkJoinStyle join_style)
584 {
585   GdkGCPrivate *private;
586   int xline_style;
587   int xcap_style;
588   int xjoin_style;
589
590   g_return_if_fail (gc != NULL);
591
592   private = (GdkGCPrivate*) gc;
593
594   switch (line_style)
595     {
596     case GDK_LINE_SOLID:
597       xline_style = LineSolid;
598       break;
599     case GDK_LINE_ON_OFF_DASH:
600       xline_style = LineOnOffDash;
601       break;
602     case GDK_LINE_DOUBLE_DASH:
603       xline_style = LineDoubleDash;
604       break;
605     default:
606       xline_style = None;
607     }
608
609   switch (cap_style)
610     {
611     case GDK_CAP_NOT_LAST:
612       xcap_style = CapNotLast;
613       break;
614     case GDK_CAP_BUTT:
615       xcap_style = CapButt;
616       break;
617     case GDK_CAP_ROUND:
618       xcap_style = CapRound;
619       break;
620     case GDK_CAP_PROJECTING:
621       xcap_style = CapProjecting;
622       break;
623     default:
624       xcap_style = None;
625     }
626
627   switch (join_style)
628     {
629     case GDK_JOIN_MITER:
630       xjoin_style = JoinMiter;
631       break;
632     case GDK_JOIN_ROUND:
633       xjoin_style = JoinRound;
634       break;
635     case GDK_JOIN_BEVEL:
636       xjoin_style = JoinBevel;
637       break;
638     default:
639       xjoin_style = None;
640     }
641
642   XSetLineAttributes (private->xdisplay, private->xgc, line_width,
643                       xline_style, xcap_style, xjoin_style);
644 }