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