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);
290 if (private->ref_count > 1)
291 private->ref_count -= 1;
294 XFreeGC (private->xdisplay, private->xgc);
295 memset (gc, 0, sizeof (GdkGCPrivate));
301 gdk_gc_get_values (GdkGC *gc,
304 GdkGCPrivate *private;
307 g_return_if_fail (gc != NULL);
308 g_return_if_fail (values != NULL);
310 private = (GdkGCPrivate*) gc;
312 if (XGetGCValues (private->xdisplay, private->xgc,
313 GCForeground | GCBackground | GCFont |
314 GCFunction | GCTile | GCStipple | /* GCClipMask | */
315 GCSubwindowMode | GCGraphicsExposures |
316 GCTileStipXOrigin | GCTileStipYOrigin |
317 GCClipXOrigin | GCClipYOrigin |
318 GCLineWidth | GCLineStyle | GCCapStyle |
319 GCFillStyle | GCJoinStyle, &xvalues))
321 values->foreground.pixel = xvalues.foreground;
322 values->background.pixel = xvalues.background;
323 values->font = gdk_font_lookup (xvalues.font);
325 switch (xvalues.function)
328 values->function = GDK_COPY;
331 values->function = GDK_INVERT;
334 values->function = GDK_XOR;
337 values->function = GDK_CLEAR;
340 values->function = GDK_AND;
343 values->function = GDK_AND_REVERSE;
346 values->function = GDK_AND_INVERT;
349 values->function = GDK_NOOP;
352 values->function = GDK_OR;
355 values->function = GDK_EQUIV;
358 values->function = GDK_OR_REVERSE;
361 values->function =GDK_COPY_INVERT;
364 values->function = GDK_OR_INVERT;
367 values->function = GDK_NAND;
370 values->function = GDK_SET;
374 switch (xvalues.fill_style)
377 values->fill = GDK_SOLID;
380 values->fill = GDK_TILED;
383 values->fill = GDK_STIPPLED;
385 case FillOpaqueStippled:
386 values->fill = GDK_OPAQUE_STIPPLED;
390 values->tile = gdk_pixmap_lookup (xvalues.tile);
391 values->stipple = gdk_pixmap_lookup (xvalues.stipple);
392 values->clip_mask = NULL;
393 values->subwindow_mode = xvalues.subwindow_mode;
394 values->ts_x_origin = xvalues.ts_x_origin;
395 values->ts_y_origin = xvalues.ts_y_origin;
396 values->clip_x_origin = xvalues.clip_x_origin;
397 values->clip_y_origin = xvalues.clip_y_origin;
398 values->graphics_exposures = xvalues.graphics_exposures;
399 values->line_width = xvalues.line_width;
401 switch (xvalues.line_style)
404 values->line_style = GDK_LINE_SOLID;
407 values->line_style = GDK_LINE_ON_OFF_DASH;
410 values->line_style = GDK_LINE_DOUBLE_DASH;
414 switch (xvalues.cap_style)
417 values->cap_style = GDK_CAP_NOT_LAST;
420 values->cap_style = GDK_CAP_BUTT;
423 values->cap_style = GDK_CAP_ROUND;
426 values->cap_style = GDK_CAP_PROJECTING;
430 switch (xvalues.join_style)
433 values->join_style = GDK_JOIN_MITER;
436 values->join_style = GDK_JOIN_ROUND;
439 values->join_style = GDK_JOIN_BEVEL;
445 memset (values, 0, sizeof (GdkGCValues));
450 gdk_gc_set_foreground (GdkGC *gc,
453 GdkGCPrivate *private;
455 g_return_if_fail (gc != NULL);
456 g_return_if_fail (color != NULL);
458 private = (GdkGCPrivate*) gc;
459 XSetForeground (private->xdisplay, private->xgc, color->pixel);
463 gdk_gc_set_background (GdkGC *gc,
466 GdkGCPrivate *private;
468 g_return_if_fail (gc != NULL);
469 g_return_if_fail (color != NULL);
471 private = (GdkGCPrivate*) gc;
472 XSetBackground (private->xdisplay, private->xgc, color->pixel);
476 gdk_gc_set_font (GdkGC *gc,
479 GdkGCPrivate *gc_private;
480 GdkFontPrivate *font_private;
482 g_return_if_fail (gc != NULL);
483 g_return_if_fail (font != NULL);
485 if (font->type == GDK_FONT_FONT)
487 gc_private = (GdkGCPrivate*) gc;
488 font_private = (GdkFontPrivate*) font;
490 XSetFont (gc_private->xdisplay, gc_private->xgc,
491 ((XFontStruct *) font_private->xfont)->fid);
496 gdk_gc_set_function (GdkGC *gc,
497 GdkFunction function)
499 GdkGCPrivate *private;
501 g_return_if_fail (gc != NULL);
503 private = (GdkGCPrivate*) gc;
508 XSetFunction (private->xdisplay, private->xgc, GXcopy);
511 XSetFunction (private->xdisplay, private->xgc, GXinvert);
514 XSetFunction (private->xdisplay, private->xgc, GXxor);
517 XSetFunction (private->xdisplay, private->xgc, GXclear);
520 XSetFunction (private->xdisplay, private->xgc, GXand);
522 case GDK_AND_REVERSE:
523 XSetFunction (private->xdisplay, private->xgc, GXandReverse);
526 XSetFunction (private->xdisplay, private->xgc, GXandInverted);
529 XSetFunction (private->xdisplay, private->xgc, GXnoop);
532 XSetFunction (private->xdisplay, private->xgc, GXor);
535 XSetFunction (private->xdisplay, private->xgc, GXequiv);
538 XSetFunction (private->xdisplay, private->xgc, GXorReverse);
540 case GDK_COPY_INVERT:
541 XSetFunction (private->xdisplay, private->xgc, GXcopyInverted);
544 XSetFunction (private->xdisplay, private->xgc, GXorInverted);
547 XSetFunction (private->xdisplay, private->xgc, GXnand);
550 XSetFunction (private->xdisplay, private->xgc, GXset);
556 gdk_gc_set_fill (GdkGC *gc,
559 GdkGCPrivate *private;
561 g_return_if_fail (gc != NULL);
563 private = (GdkGCPrivate*) gc;
568 XSetFillStyle (private->xdisplay, private->xgc, FillSolid);
571 XSetFillStyle (private->xdisplay, private->xgc, FillTiled);
574 XSetFillStyle (private->xdisplay, private->xgc, FillStippled);
576 case GDK_OPAQUE_STIPPLED:
577 XSetFillStyle (private->xdisplay, private->xgc, FillOpaqueStippled);
583 gdk_gc_set_tile (GdkGC *gc,
586 GdkGCPrivate *private;
587 GdkPixmapPrivate *pixmap_private;
590 g_return_if_fail (gc != NULL);
592 private = (GdkGCPrivate*) gc;
597 pixmap_private = (GdkPixmapPrivate*) tile;
598 pixmap = pixmap_private->xwindow;
601 XSetTile (private->xdisplay, private->xgc, pixmap);
605 gdk_gc_set_stipple (GdkGC *gc,
608 GdkGCPrivate *private;
609 GdkPixmapPrivate *pixmap_private;
612 g_return_if_fail (gc != NULL);
614 private = (GdkGCPrivate*) gc;
619 pixmap_private = (GdkPixmapPrivate*) stipple;
620 pixmap = pixmap_private->xwindow;
623 XSetStipple (private->xdisplay, private->xgc, pixmap);
627 gdk_gc_set_ts_origin (GdkGC *gc,
631 GdkGCPrivate *private;
633 g_return_if_fail (gc != NULL);
635 private = (GdkGCPrivate*) gc;
637 XSetTSOrigin (private->xdisplay, private->xgc, x, y);
641 gdk_gc_set_clip_origin (GdkGC *gc,
645 GdkGCPrivate *private;
647 g_return_if_fail (gc != NULL);
649 private = (GdkGCPrivate*) gc;
651 XSetClipOrigin (private->xdisplay, private->xgc, x, y);
655 gdk_gc_set_clip_mask (GdkGC *gc,
658 GdkGCPrivate *private;
661 g_return_if_fail (gc != NULL);
665 GdkWindowPrivate *mask_private;
667 mask_private = (GdkWindowPrivate*) mask;
668 if (mask_private->destroyed)
670 xmask = mask_private->xwindow;
675 private = (GdkGCPrivate*) gc;
677 XSetClipMask (private->xdisplay, private->xgc, xmask);
682 gdk_gc_set_clip_rectangle (GdkGC *gc,
683 GdkRectangle *rectangle)
685 GdkGCPrivate *private;
686 XRectangle xrectangle;
688 g_return_if_fail (gc != NULL);
690 private = (GdkGCPrivate*) gc;
694 xrectangle.x = rectangle->x;
695 xrectangle.y = rectangle->y;
696 xrectangle.width = rectangle->width;
697 xrectangle.height = rectangle->height;
699 XSetClipRectangles (private->xdisplay, private->xgc, 0, 0,
700 &xrectangle, 1, Unsorted);
703 XSetClipMask (private->xdisplay, private->xgc, None);
707 gdk_gc_set_clip_region (GdkGC *gc,
710 GdkGCPrivate *private;
712 g_return_if_fail (gc != NULL);
714 private = (GdkGCPrivate*) gc;
718 GdkRegionPrivate *region_private;
720 region_private = (GdkRegionPrivate*) region;
721 XSetRegion (private->xdisplay, private->xgc, region_private->xregion);
724 XSetClipMask (private->xdisplay, private->xgc, None);
728 gdk_gc_set_subwindow (GdkGC *gc,
729 GdkSubwindowMode mode)
731 GdkGCPrivate *private;
733 g_return_if_fail (gc != NULL);
735 private = (GdkGCPrivate*) gc;
737 XSetSubwindowMode (private->xdisplay, private->xgc, mode);
741 gdk_gc_set_exposures (GdkGC *gc,
744 GdkGCPrivate *private;
746 g_return_if_fail (gc != NULL);
748 private = (GdkGCPrivate*) gc;
750 XSetGraphicsExposures (private->xdisplay, private->xgc, exposures);
754 gdk_gc_set_line_attributes (GdkGC *gc,
756 GdkLineStyle line_style,
757 GdkCapStyle cap_style,
758 GdkJoinStyle join_style)
760 GdkGCPrivate *private;
765 g_return_if_fail (gc != NULL);
767 private = (GdkGCPrivate*) gc;
772 xline_style = LineSolid;
774 case GDK_LINE_ON_OFF_DASH:
775 xline_style = LineOnOffDash;
777 case GDK_LINE_DOUBLE_DASH:
778 xline_style = LineDoubleDash;
786 case GDK_CAP_NOT_LAST:
787 xcap_style = CapNotLast;
790 xcap_style = CapButt;
793 xcap_style = CapRound;
795 case GDK_CAP_PROJECTING:
796 xcap_style = CapProjecting;
805 xjoin_style = JoinMiter;
808 xjoin_style = JoinRound;
811 xjoin_style = JoinBevel;
817 XSetLineAttributes (private->xdisplay, private->xgc, line_width,
818 xline_style, xcap_style, xjoin_style);
822 gdk_gc_set_dashes (GdkGC *gc,
827 GdkGCPrivate *private;
829 g_return_if_fail (gc != NULL);
830 g_return_if_fail (dash_list != NULL);
832 private = (GdkGCPrivate*) gc;
834 XSetDashes (private->xdisplay, private->xgc, dash_offset, dash_list, n);
838 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
840 GdkGCPrivate *dst_private, *src_private;
842 src_private = (GdkGCPrivate *) src_gc;
843 dst_private = (GdkGCPrivate *) dst_gc;
845 XCopyGC (src_private->xdisplay, src_private->xgc, ~((~1) << GCLastBit),