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 Lesser 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser 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-2000. 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-x11.h"
31 #include "gdkregion-generic.h"
38 GDK_GC_DIRTY_CLIP = 1 << 0,
39 GDK_GC_DIRTY_TS = 1 << 1
42 static void gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
45 unsigned long *xvalues_mask);
47 static void gdk_x11_gc_get_values (GdkGC *gc,
49 static void gdk_x11_gc_set_values (GdkGC *gc,
51 GdkGCValuesMask values_mask);
52 static void gdk_x11_gc_set_dashes (GdkGC *gc,
57 static void gdk_gc_x11_finalize (GObject *object);
59 G_DEFINE_TYPE (GdkGCX11, _gdk_gc_x11, GDK_TYPE_GC)
62 _gdk_gc_x11_class_init (GdkGCX11Class *klass)
64 GObjectClass *object_class = G_OBJECT_CLASS (klass);
65 GdkGCClass *gc_class = GDK_GC_CLASS (klass);
67 object_class->finalize = gdk_gc_x11_finalize;
69 gc_class->get_values = gdk_x11_gc_get_values;
70 gc_class->set_values = gdk_x11_gc_set_values;
71 gc_class->set_dashes = gdk_x11_gc_set_dashes;
75 _gdk_gc_x11_init (GdkGCX11 *gc)
80 gdk_gc_x11_finalize (GObject *object)
82 GdkGCX11 *x11_gc = GDK_GC_X11 (object);
84 XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
86 G_OBJECT_CLASS (_gdk_gc_x11_parent_class)->finalize (object);
91 _gdk_x11_gc_new (GdkDrawable *drawable,
93 GdkGCValuesMask values_mask)
99 unsigned long xvalues_mask;
101 /* NOTICE that the drawable here has to be the impl drawable,
102 * not the publically-visible drawables.
104 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_X11 (drawable), NULL);
106 gc = g_object_new (_gdk_gc_x11_get_type (), NULL);
107 private = GDK_GC_X11 (gc);
109 _gdk_gc_init (gc, drawable, values, values_mask);
111 private->dirty_mask = 0;
112 private->have_clip_mask = FALSE;
114 private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
116 private->depth = gdk_drawable_get_depth (drawable);
118 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
120 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
121 private->dirty_mask |= GDK_GC_DIRTY_CLIP;
124 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
126 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
127 private->dirty_mask |= GDK_GC_DIRTY_TS;
130 if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
131 private->have_clip_mask = TRUE;
133 xvalues.function = GXcopy;
134 xvalues.fill_style = FillSolid;
135 xvalues.arc_mode = ArcPieSlice;
136 xvalues.subwindow_mode = ClipByChildren;
137 xvalues.graphics_exposures = False;
138 xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
140 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
142 private->xgc = XCreateGC (GDK_GC_XDISPLAY (gc),
143 GDK_DRAWABLE_IMPL_X11 (drawable)->xid,
144 xvalues_mask, &xvalues);
150 _gdk_x11_gc_flush (GdkGC *gc)
152 Display *xdisplay = GDK_GC_XDISPLAY (gc);
153 GdkGCX11 *private = GDK_GC_X11 (gc);
154 GC xgc = private->xgc;
156 if (private->dirty_mask & GDK_GC_DIRTY_CLIP)
158 GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
161 XSetClipOrigin (xdisplay, xgc,
162 gc->clip_x_origin, gc->clip_y_origin);
165 XRectangle *rectangles;
168 _gdk_region_get_xrectangles (clip_region,
174 XSetClipRectangles (xdisplay, xgc, 0, 0,
182 if (private->dirty_mask & GDK_GC_DIRTY_TS)
184 XSetTSOrigin (xdisplay, xgc,
185 gc->ts_x_origin, gc->ts_y_origin);
188 private->dirty_mask = 0;
193 gdk_x11_gc_get_values (GdkGC *gc,
198 if (XGetGCValues (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
199 GCForeground | GCBackground | GCFont |
200 GCFunction | GCTile | GCStipple | /* GCClipMask | */
201 GCSubwindowMode | GCGraphicsExposures |
202 GCTileStipXOrigin | GCTileStipYOrigin |
203 GCClipXOrigin | GCClipYOrigin |
204 GCLineWidth | GCLineStyle | GCCapStyle |
205 GCFillStyle | GCJoinStyle, &xvalues))
207 values->foreground.pixel = xvalues.foreground;
208 values->background.pixel = xvalues.background;
209 values->font = gdk_font_lookup_for_display (GDK_GC_DISPLAY (gc),
212 switch (xvalues.function)
215 values->function = GDK_COPY;
218 values->function = GDK_INVERT;
221 values->function = GDK_XOR;
224 values->function = GDK_CLEAR;
227 values->function = GDK_AND;
230 values->function = GDK_AND_REVERSE;
233 values->function = GDK_AND_INVERT;
236 values->function = GDK_NOOP;
239 values->function = GDK_OR;
242 values->function = GDK_EQUIV;
245 values->function = GDK_OR_REVERSE;
248 values->function =GDK_COPY_INVERT;
251 values->function = GDK_OR_INVERT;
254 values->function = GDK_NAND;
257 values->function = GDK_SET;
260 values->function = GDK_NOR;
264 switch (xvalues.fill_style)
267 values->fill = GDK_SOLID;
270 values->fill = GDK_TILED;
273 values->fill = GDK_STIPPLED;
275 case FillOpaqueStippled:
276 values->fill = GDK_OPAQUE_STIPPLED;
280 values->tile = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
282 values->stipple = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
284 values->clip_mask = NULL;
285 values->subwindow_mode = xvalues.subwindow_mode;
286 values->ts_x_origin = xvalues.ts_x_origin;
287 values->ts_y_origin = xvalues.ts_y_origin;
288 values->clip_x_origin = xvalues.clip_x_origin;
289 values->clip_y_origin = xvalues.clip_y_origin;
290 values->graphics_exposures = xvalues.graphics_exposures;
291 values->line_width = xvalues.line_width;
293 switch (xvalues.line_style)
296 values->line_style = GDK_LINE_SOLID;
299 values->line_style = GDK_LINE_ON_OFF_DASH;
302 values->line_style = GDK_LINE_DOUBLE_DASH;
306 switch (xvalues.cap_style)
309 values->cap_style = GDK_CAP_NOT_LAST;
312 values->cap_style = GDK_CAP_BUTT;
315 values->cap_style = GDK_CAP_ROUND;
318 values->cap_style = GDK_CAP_PROJECTING;
322 switch (xvalues.join_style)
325 values->join_style = GDK_JOIN_MITER;
328 values->join_style = GDK_JOIN_ROUND;
331 values->join_style = GDK_JOIN_BEVEL;
337 memset (values, 0, sizeof (GdkGCValues));
342 gdk_x11_gc_set_values (GdkGC *gc,
344 GdkGCValuesMask values_mask)
348 unsigned long xvalues_mask = 0;
350 x11_gc = GDK_GC_X11 (gc);
352 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
354 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
355 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
358 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
360 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
361 x11_gc->dirty_mask |= GDK_GC_DIRTY_TS;
364 if (values_mask & GDK_GC_CLIP_MASK)
366 x11_gc->have_clip_region = FALSE;
367 x11_gc->have_clip_mask = values->clip_mask != NULL;
370 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
372 XChangeGC (GDK_GC_XDISPLAY (gc),
379 gdk_x11_gc_set_dashes (GdkGC *gc,
384 g_return_if_fail (GDK_IS_GC (gc));
385 g_return_if_fail (dash_list != NULL);
387 XSetDashes (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
388 dash_offset, (char *)dash_list, n);
392 gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
393 GdkGCValuesMask mask,
395 unsigned long *xvalues_mask)
397 /* Optimization for the common case (gdk_gc_new()) */
398 if (values == NULL || mask == 0)
401 if (mask & GDK_GC_FOREGROUND)
403 xvalues->foreground = values->foreground.pixel;
404 *xvalues_mask |= GCForeground;
406 if (mask & GDK_GC_BACKGROUND)
408 xvalues->background = values->background.pixel;
409 *xvalues_mask |= GCBackground;
411 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
413 xvalues->font = ((XFontStruct *) (GDK_FONT_XFONT (values->font)))->fid;
414 *xvalues_mask |= GCFont;
416 if (mask & GDK_GC_FUNCTION)
418 switch (values->function)
421 xvalues->function = GXcopy;
424 xvalues->function = GXinvert;
427 xvalues->function = GXxor;
430 xvalues->function = GXclear;
433 xvalues->function = GXand;
435 case GDK_AND_REVERSE:
436 xvalues->function = GXandReverse;
439 xvalues->function = GXandInverted;
442 xvalues->function = GXnoop;
445 xvalues->function = GXor;
448 xvalues->function = GXequiv;
451 xvalues->function = GXorReverse;
453 case GDK_COPY_INVERT:
454 xvalues->function = GXcopyInverted;
457 xvalues->function = GXorInverted;
460 xvalues->function = GXnand;
463 xvalues->function = GXset;
466 xvalues->function = GXnor;
469 *xvalues_mask |= GCFunction;
471 if (mask & GDK_GC_FILL)
473 switch (values->fill)
476 xvalues->fill_style = FillSolid;
479 xvalues->fill_style = FillTiled;
482 xvalues->fill_style = FillStippled;
484 case GDK_OPAQUE_STIPPLED:
485 xvalues->fill_style = FillOpaqueStippled;
488 *xvalues_mask |= GCFillStyle;
490 if (mask & GDK_GC_TILE)
493 xvalues->tile = GDK_DRAWABLE_XID (values->tile);
495 xvalues->tile = None;
497 *xvalues_mask |= GCTile;
499 if (mask & GDK_GC_STIPPLE)
502 xvalues->stipple = GDK_DRAWABLE_XID (values->stipple);
504 xvalues->stipple = None;
506 *xvalues_mask |= GCStipple;
508 if (mask & GDK_GC_CLIP_MASK)
510 if (values->clip_mask)
511 xvalues->clip_mask = GDK_DRAWABLE_XID (values->clip_mask);
513 xvalues->clip_mask = None;
515 *xvalues_mask |= GCClipMask;
518 if (mask & GDK_GC_SUBWINDOW)
520 xvalues->subwindow_mode = values->subwindow_mode;
521 *xvalues_mask |= GCSubwindowMode;
523 if (mask & GDK_GC_TS_X_ORIGIN)
525 xvalues->ts_x_origin = values->ts_x_origin;
526 *xvalues_mask |= GCTileStipXOrigin;
528 if (mask & GDK_GC_TS_Y_ORIGIN)
530 xvalues->ts_y_origin = values->ts_y_origin;
531 *xvalues_mask |= GCTileStipYOrigin;
533 if (mask & GDK_GC_CLIP_X_ORIGIN)
535 xvalues->clip_x_origin = values->clip_x_origin;
536 *xvalues_mask |= GCClipXOrigin;
538 if (mask & GDK_GC_CLIP_Y_ORIGIN)
540 xvalues->clip_y_origin = values->clip_y_origin;
541 *xvalues_mask |= GCClipYOrigin;
544 if (mask & GDK_GC_EXPOSURES)
546 xvalues->graphics_exposures = values->graphics_exposures;
547 *xvalues_mask |= GCGraphicsExposures;
550 if (mask & GDK_GC_LINE_WIDTH)
552 xvalues->line_width = values->line_width;
553 *xvalues_mask |= GCLineWidth;
555 if (mask & GDK_GC_LINE_STYLE)
557 switch (values->line_style)
560 xvalues->line_style = LineSolid;
562 case GDK_LINE_ON_OFF_DASH:
563 xvalues->line_style = LineOnOffDash;
565 case GDK_LINE_DOUBLE_DASH:
566 xvalues->line_style = LineDoubleDash;
569 *xvalues_mask |= GCLineStyle;
571 if (mask & GDK_GC_CAP_STYLE)
573 switch (values->cap_style)
575 case GDK_CAP_NOT_LAST:
576 xvalues->cap_style = CapNotLast;
579 xvalues->cap_style = CapButt;
582 xvalues->cap_style = CapRound;
584 case GDK_CAP_PROJECTING:
585 xvalues->cap_style = CapProjecting;
588 *xvalues_mask |= GCCapStyle;
590 if (mask & GDK_GC_JOIN_STYLE)
592 switch (values->join_style)
595 xvalues->join_style = JoinMiter;
598 xvalues->join_style = JoinRound;
601 xvalues->join_style = JoinBevel;
604 *xvalues_mask |= GCJoinStyle;
610 _gdk_windowing_gc_set_clip_region (GdkGC *gc,
611 const GdkRegion *region,
612 gboolean reset_origin)
614 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
616 /* Unset immediately, to make sure Xlib doesn't keep the
617 * XID of an old clip mask cached
619 if ((x11_gc->have_clip_region && !region) || x11_gc->have_clip_mask)
621 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
622 x11_gc->have_clip_mask = FALSE;
625 x11_gc->have_clip_region = region != NULL;
629 gc->clip_x_origin = 0;
630 gc->clip_y_origin = 0;
633 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
637 _gdk_windowing_gc_copy (GdkGC *dst_gc,
640 GdkGCX11 *x11_src_gc = GDK_GC_X11 (src_gc);
641 GdkGCX11 *x11_dst_gc = GDK_GC_X11 (dst_gc);
643 XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit),
644 GDK_GC_XGC (dst_gc));
646 x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
647 x11_dst_gc->have_clip_region = x11_src_gc->have_clip_region;
648 x11_dst_gc->have_clip_mask = x11_src_gc->have_clip_mask;
655 * Gets the #GdkScreen for which @gc was created
657 * Returns: the #GdkScreen for @gc.
662 gdk_gc_get_screen (GdkGC *gc)
664 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
666 return GDK_GC_X11 (gc)->screen;
670 * gdk_x11_gc_get_xdisplay:
673 * Returns the display of a #GdkGC.
675 * Return value: an Xlib <type>Display*</type>.
678 gdk_x11_gc_get_xdisplay (GdkGC *gc)
680 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
682 return GDK_SCREEN_XDISPLAY (gdk_gc_get_screen (gc));
686 * gdk_x11_gc_get_xgc:
689 * Returns the X GC of a #GdkGC.
691 * Return value: an Xlib <type>GC</type>.
694 gdk_x11_gc_get_xgc (GdkGC *gc)
698 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
700 gc_x11 = GDK_GC_X11 (gc);
702 if (gc_x11->dirty_mask)
703 _gdk_x11_gc_flush (gc);
708 #define __GDK_GC_X11_C__
709 #include "gdkaliasdef.c"