1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
30 #include "gdkprivate.h"
34 gdk_gc_new (GdkWindow *window)
36 return gdk_gc_new_with_values (window, NULL, 0);
40 gdk_gc_new_with_values (GdkWindow *window,
42 GdkGCValuesMask values_mask)
44 GdkWindowPrivate *window_private;
46 GdkGCPrivate *private;
49 unsigned long xvalues_mask;
51 g_return_val_if_fail (window != NULL, NULL);
53 window_private = (GdkWindowPrivate*) window;
54 if (window_private->destroyed)
57 private = g_new (GdkGCPrivate, 1);
58 gc = (GdkGC*) private;
60 xwindow = window_private->xwindow;
61 private->xdisplay = window_private->xdisplay;
62 private->ref_count = 1;
64 xvalues.function = GXcopy;
65 xvalues.fill_style = FillSolid;
66 xvalues.arc_mode = ArcPieSlice;
67 xvalues.subwindow_mode = ClipByChildren;
68 xvalues.graphics_exposures = True;
69 xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
71 if (values_mask & GDK_GC_FOREGROUND)
73 xvalues.foreground = values->foreground.pixel;
74 xvalues_mask |= GCForeground;
76 if (values_mask & GDK_GC_BACKGROUND)
78 xvalues.background = values->background.pixel;
79 xvalues_mask |= GCBackground;
81 if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
83 xvalues.font = ((XFontStruct *) ((GdkFontPrivate*) values->font)->xfont)->fid;
84 xvalues_mask |= GCFont;
86 if (values_mask & GDK_GC_FUNCTION)
88 switch (values->function)
91 xvalues.function = GXcopy;
94 xvalues.function = GXinvert;
97 xvalues.function = GXxor;
100 xvalues.function = GXclear;
103 xvalues.function = GXand;
105 case GDK_AND_REVERSE:
106 xvalues.function = GXandReverse;
109 xvalues.function = GXandInverted;
112 xvalues.function = GXnoop;
115 xvalues.function = GXor;
118 xvalues.function = GXequiv;
121 xvalues.function = GXorReverse;
123 case GDK_COPY_INVERT:
124 xvalues.function = GXcopyInverted;
127 xvalues.function = GXorInverted;
130 xvalues.function = GXnand;
133 xvalues.function = GXset;
136 xvalues_mask |= GCFunction;
138 if (values_mask & GDK_GC_FILL)
140 switch (values->fill)
143 xvalues.fill_style = FillSolid;
146 xvalues.fill_style = FillTiled;
149 xvalues.fill_style = FillStippled;
151 case GDK_OPAQUE_STIPPLED:
152 xvalues.fill_style = FillOpaqueStippled;
155 xvalues_mask |= GCFillStyle;
157 if (values_mask & GDK_GC_TILE)
159 xvalues.tile = ((GdkPixmapPrivate*) values->tile)->xwindow;
160 xvalues_mask |= GCTile;
162 if (values_mask & GDK_GC_STIPPLE)
164 xvalues.stipple = ((GdkPixmapPrivate*) values->stipple)->xwindow;
165 xvalues_mask |= GCStipple;
167 if (values_mask & GDK_GC_CLIP_MASK)
169 xvalues.clip_mask = ((GdkPixmapPrivate*) values->clip_mask)->xwindow;
170 xvalues_mask |= GCClipMask;
172 if (values_mask & GDK_GC_SUBWINDOW)
174 xvalues.subwindow_mode = values->subwindow_mode;
175 xvalues_mask |= GCSubwindowMode;
177 if (values_mask & GDK_GC_TS_X_ORIGIN)
179 xvalues.ts_x_origin = values->ts_x_origin;
180 xvalues_mask |= GCTileStipXOrigin;
182 if (values_mask & GDK_GC_TS_Y_ORIGIN)
184 xvalues.ts_y_origin = values->ts_y_origin;
185 xvalues_mask |= GCTileStipYOrigin;
187 if (values_mask & GDK_GC_CLIP_X_ORIGIN)
189 xvalues.clip_x_origin = values->clip_x_origin;
190 xvalues_mask |= GCClipXOrigin;
192 if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
194 xvalues.clip_y_origin = values->clip_y_origin;
195 xvalues_mask |= GCClipYOrigin;
198 if (values_mask & GDK_GC_EXPOSURES)
199 xvalues.graphics_exposures = values->graphics_exposures;
201 xvalues.graphics_exposures = False;
202 xvalues_mask |= GCGraphicsExposures;
204 if (values_mask & GDK_GC_LINE_WIDTH)
206 xvalues.line_width = values->line_width;
207 xvalues_mask |= GCLineWidth;
209 if (values_mask & GDK_GC_LINE_STYLE)
211 switch (values->line_style)
214 xvalues.line_style = LineSolid;
216 case GDK_LINE_ON_OFF_DASH:
217 xvalues.line_style = LineOnOffDash;
219 case GDK_LINE_DOUBLE_DASH:
220 xvalues.line_style = LineDoubleDash;
223 xvalues_mask |= GCLineStyle;
225 if (values_mask & GDK_GC_CAP_STYLE)
227 switch (values->cap_style)
229 case GDK_CAP_NOT_LAST:
230 xvalues.cap_style = CapNotLast;
233 xvalues.cap_style = CapButt;
236 xvalues.cap_style = CapRound;
238 case GDK_CAP_PROJECTING:
239 xvalues.cap_style = CapProjecting;
242 xvalues_mask |= GCCapStyle;
244 if (values_mask & GDK_GC_JOIN_STYLE)
246 switch (values->join_style)
249 xvalues.join_style = JoinMiter;
252 xvalues.join_style = JoinRound;
255 xvalues.join_style = JoinBevel;
258 xvalues_mask |= GCJoinStyle;
261 private->xgc = XCreateGC (private->xdisplay, xwindow, xvalues_mask, &xvalues);
267 gdk_gc_destroy (GdkGC *gc)
273 gdk_gc_ref (GdkGC *gc)
275 GdkGCPrivate *private = (GdkGCPrivate*) gc;
277 g_return_val_if_fail (gc != NULL, NULL);
278 private->ref_count += 1;
284 gdk_gc_unref (GdkGC *gc)
286 GdkGCPrivate *private = (GdkGCPrivate*) gc;
288 g_return_if_fail (gc != NULL);
289 g_return_if_fail (private->ref_count > 0);
291 if (private->ref_count > 1)
292 private->ref_count -= 1;
295 XFreeGC (private->xdisplay, private->xgc);
296 memset (gc, 0, sizeof (GdkGCPrivate));
302 gdk_gc_get_values (GdkGC *gc,
305 GdkGCPrivate *private;
308 g_return_if_fail (gc != NULL);
309 g_return_if_fail (values != NULL);
311 private = (GdkGCPrivate*) gc;
313 if (XGetGCValues (private->xdisplay, private->xgc,
314 GCForeground | GCBackground | GCFont |
315 GCFunction | GCTile | GCStipple | /* GCClipMask | */
316 GCSubwindowMode | GCGraphicsExposures |
317 GCTileStipXOrigin | GCTileStipYOrigin |
318 GCClipXOrigin | GCClipYOrigin |
319 GCLineWidth | GCLineStyle | GCCapStyle |
320 GCFillStyle | GCJoinStyle, &xvalues))
322 values->foreground.pixel = xvalues.foreground;
323 values->background.pixel = xvalues.background;
324 values->font = gdk_font_lookup (xvalues.font);
326 switch (xvalues.function)
329 values->function = GDK_COPY;
332 values->function = GDK_INVERT;
335 values->function = GDK_XOR;
338 values->function = GDK_CLEAR;
341 values->function = GDK_AND;
344 values->function = GDK_AND_REVERSE;
347 values->function = GDK_AND_INVERT;
350 values->function = GDK_NOOP;
353 values->function = GDK_OR;
356 values->function = GDK_EQUIV;
359 values->function = GDK_OR_REVERSE;
362 values->function =GDK_COPY_INVERT;
365 values->function = GDK_OR_INVERT;
368 values->function = GDK_NAND;
371 values->function = GDK_SET;
375 switch (xvalues.fill_style)
378 values->fill = GDK_SOLID;
381 values->fill = GDK_TILED;
384 values->fill = GDK_STIPPLED;
386 case FillOpaqueStippled:
387 values->fill = GDK_OPAQUE_STIPPLED;
391 values->tile = gdk_pixmap_lookup (xvalues.tile);
392 values->stipple = gdk_pixmap_lookup (xvalues.stipple);
393 values->clip_mask = NULL;
394 values->subwindow_mode = xvalues.subwindow_mode;
395 values->ts_x_origin = xvalues.ts_x_origin;
396 values->ts_y_origin = xvalues.ts_y_origin;
397 values->clip_x_origin = xvalues.clip_x_origin;
398 values->clip_y_origin = xvalues.clip_y_origin;
399 values->graphics_exposures = xvalues.graphics_exposures;
400 values->line_width = xvalues.line_width;
402 switch (xvalues.line_style)
405 values->line_style = GDK_LINE_SOLID;
408 values->line_style = GDK_LINE_ON_OFF_DASH;
411 values->line_style = GDK_LINE_DOUBLE_DASH;
415 switch (xvalues.cap_style)
418 values->cap_style = GDK_CAP_NOT_LAST;
421 values->cap_style = GDK_CAP_BUTT;
424 values->cap_style = GDK_CAP_ROUND;
427 values->cap_style = GDK_CAP_PROJECTING;
431 switch (xvalues.join_style)
434 values->join_style = GDK_JOIN_MITER;
437 values->join_style = GDK_JOIN_ROUND;
440 values->join_style = GDK_JOIN_BEVEL;
446 memset (values, 0, sizeof (GdkGCValues));
451 gdk_gc_set_foreground (GdkGC *gc,
454 GdkGCPrivate *private;
456 g_return_if_fail (gc != NULL);
457 g_return_if_fail (color != NULL);
459 private = (GdkGCPrivate*) gc;
460 XSetForeground (private->xdisplay, private->xgc, color->pixel);
464 gdk_gc_set_background (GdkGC *gc,
467 GdkGCPrivate *private;
469 g_return_if_fail (gc != NULL);
470 g_return_if_fail (color != NULL);
472 private = (GdkGCPrivate*) gc;
473 XSetBackground (private->xdisplay, private->xgc, color->pixel);
477 gdk_gc_set_font (GdkGC *gc,
480 GdkGCPrivate *gc_private;
481 GdkFontPrivate *font_private;
483 g_return_if_fail (gc != NULL);
484 g_return_if_fail (font != NULL);
486 if (font->type == GDK_FONT_FONT)
488 gc_private = (GdkGCPrivate*) gc;
489 font_private = (GdkFontPrivate*) font;
491 XSetFont (gc_private->xdisplay, gc_private->xgc,
492 ((XFontStruct *) font_private->xfont)->fid);
497 gdk_gc_set_function (GdkGC *gc,
498 GdkFunction function)
500 GdkGCPrivate *private;
502 g_return_if_fail (gc != NULL);
504 private = (GdkGCPrivate*) gc;
509 XSetFunction (private->xdisplay, private->xgc, GXcopy);
512 XSetFunction (private->xdisplay, private->xgc, GXinvert);
515 XSetFunction (private->xdisplay, private->xgc, GXxor);
518 XSetFunction (private->xdisplay, private->xgc, GXclear);
521 XSetFunction (private->xdisplay, private->xgc, GXand);
523 case GDK_AND_REVERSE:
524 XSetFunction (private->xdisplay, private->xgc, GXandReverse);
527 XSetFunction (private->xdisplay, private->xgc, GXandInverted);
530 XSetFunction (private->xdisplay, private->xgc, GXnoop);
533 XSetFunction (private->xdisplay, private->xgc, GXor);
536 XSetFunction (private->xdisplay, private->xgc, GXequiv);
539 XSetFunction (private->xdisplay, private->xgc, GXorReverse);
541 case GDK_COPY_INVERT:
542 XSetFunction (private->xdisplay, private->xgc, GXcopyInverted);
545 XSetFunction (private->xdisplay, private->xgc, GXorInverted);
548 XSetFunction (private->xdisplay, private->xgc, GXnand);
551 XSetFunction (private->xdisplay, private->xgc, GXset);
557 gdk_gc_set_fill (GdkGC *gc,
560 GdkGCPrivate *private;
562 g_return_if_fail (gc != NULL);
564 private = (GdkGCPrivate*) gc;
569 XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
572 XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
575 XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
577 case GDK_OPAQUE_STIPPLED:
578 XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
584 gdk_gc_set_tile (GdkGC *gc,
587 GdkGCPrivate *private;
588 GdkPixmapPrivate *pixmap_private;
591 g_return_if_fail (gc != NULL);
593 private = (GdkGCPrivate*) gc;
598 pixmap_private = (GdkPixmapPrivate*) tile;
599 pixmap = pixmap_private->xwindow;
602 XSetTile (private->xdisplay, private->xgc, pixmap);
606 gdk_gc_set_stipple (GdkGC *gc,
609 GdkGCPrivate *private;
610 GdkPixmapPrivate *pixmap_private;
613 g_return_if_fail (gc != NULL);
615 private = (GdkGCPrivate*) gc;
620 pixmap_private = (GdkPixmapPrivate*) stipple;
621 pixmap = pixmap_private->xwindow;
624 XSetStipple (private->xdisplay, private->xgc, pixmap);
628 gdk_gc_set_ts_origin (GdkGC *gc,
632 GdkGCPrivate *private;
634 g_return_if_fail (gc != NULL);
636 private = (GdkGCPrivate*) gc;
638 XSetTSOrigin (private->xdisplay, private->xgc, x, y);
642 gdk_gc_set_clip_origin (GdkGC *gc,
646 GdkGCPrivate *private;
648 g_return_if_fail (gc != NULL);
650 private = (GdkGCPrivate*) gc;
652 XSetClipOrigin (private->xdisplay, private->xgc, x, y);
656 gdk_gc_set_clip_mask (GdkGC *gc,
659 GdkGCPrivate *private;
662 g_return_if_fail (gc != NULL);
666 GdkWindowPrivate *mask_private;
668 mask_private = (GdkWindowPrivate*) mask;
669 if (mask_private->destroyed)
671 xmask = mask_private->xwindow;
676 private = (GdkGCPrivate*) gc;
678 XSetClipMask (private->xdisplay, private->xgc, xmask);
683 gdk_gc_set_clip_rectangle (GdkGC *gc,
684 GdkRectangle *rectangle)
686 GdkGCPrivate *private;
687 XRectangle xrectangle;
689 g_return_if_fail (gc != NULL);
691 private = (GdkGCPrivate*) gc;
695 xrectangle.x = rectangle->x;
696 xrectangle.y = rectangle->y;
697 xrectangle.width = rectangle->width;
698 xrectangle.height = rectangle->height;
700 XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
701 &xrectangle, 1, Unsorted);
704 XSetClipMask (private->xdisplay, private->xgc, None);
708 gdk_gc_set_clip_region (GdkGC *gc,
711 GdkGCPrivate *private;
713 g_return_if_fail (gc != NULL);
715 private = (GdkGCPrivate*) gc;
719 GdkRegionPrivate *region_private;
721 region_private = (GdkRegionPrivate*) region;
722 XSetRegion (private->xdisplay, private->xgc, region_private->xregion);
725 XSetClipMask (private->xdisplay, private->xgc, None);
729 gdk_gc_set_subwindow (GdkGC *gc,
730 GdkSubwindowMode mode)
732 GdkGCPrivate *private;
734 g_return_if_fail (gc != NULL);
736 private = (GdkGCPrivate*) gc;
738 XSetSubwindowMode (private->xdisplay, private->xgc, mode);
742 gdk_gc_set_exposures (GdkGC *gc,
745 GdkGCPrivate *private;
747 g_return_if_fail (gc != NULL);
749 private = (GdkGCPrivate*) gc;
751 XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
755 gdk_gc_set_line_attributes (GdkGC *gc,
757 GdkLineStyle line_style,
758 GdkCapStyle cap_style,
759 GdkJoinStyle join_style)
761 GdkGCPrivate *private;
766 g_return_if_fail (gc != NULL);
768 private = (GdkGCPrivate*) gc;
773 xline_style = LineSolid;
775 case GDK_LINE_ON_OFF_DASH:
776 xline_style = LineOnOffDash;
778 case GDK_LINE_DOUBLE_DASH:
779 xline_style = LineDoubleDash;
787 case GDK_CAP_NOT_LAST:
788 xcap_style = CapNotLast;
791 xcap_style = CapButt;
794 xcap_style = CapRound;
796 case GDK_CAP_PROJECTING:
797 xcap_style = CapProjecting;
806 xjoin_style = JoinMiter;
809 xjoin_style = JoinRound;
812 xjoin_style = JoinBevel;
818 XSetLineAttributes (private->xdisplay, private->xgc, line_width,
819 xline_style, xcap_style, xjoin_style);
823 gdk_gc_set_dashes (GdkGC *gc,
828 GdkGCPrivate *private;
830 g_return_if_fail (gc != NULL);
831 g_return_if_fail (dash_list != NULL);
833 private = (GdkGCPrivate*) gc;
835 XSetDashes (private->xdisplay, private->xgc, dash_offset, dash_list, n);
839 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
841 GdkGCPrivate *dst_private, *src_private;
843 src_private = (GdkGCPrivate *) src_gc;
844 dst_private = (GdkGCPrivate *) dst_gc;
846 XCopyGC (src_private->xdisplay, src_private->xgc, ~((~1) << GCLastBit),