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/.
29 #include "gdkregion-generic.h"
34 GDK_GC_DIRTY_CLIP = 1 << 0,
35 GDK_GC_DIRTY_TS = 1 << 1
38 static void gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
41 unsigned long *xvalues_mask);
43 static void gdk_x11_gc_get_values (GdkGC *gc,
45 static void gdk_x11_gc_set_values (GdkGC *gc,
47 GdkGCValuesMask values_mask);
48 static void gdk_x11_gc_set_dashes (GdkGC *gc,
53 static void gdk_gc_x11_class_init (GdkGCX11Class *klass);
54 static void gdk_gc_x11_finalize (GObject *object);
56 static gpointer parent_class = NULL;
59 gdk_gc_x11_get_type (void)
61 static GType object_type = 0;
65 static const GTypeInfo object_info =
67 sizeof (GdkGCX11Class),
69 (GBaseFinalizeFunc) NULL,
70 (GClassInitFunc) gdk_gc_x11_class_init,
71 NULL, /* class_finalize */
72 NULL, /* class_data */
75 (GInstanceInitFunc) NULL,
78 object_type = g_type_register_static (GDK_TYPE_GC,
87 gdk_gc_x11_class_init (GdkGCX11Class *klass)
89 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90 GdkGCClass *gc_class = GDK_GC_CLASS (klass);
92 parent_class = g_type_class_peek_parent (klass);
94 object_class->finalize = gdk_gc_x11_finalize;
96 gc_class->get_values = gdk_x11_gc_get_values;
97 gc_class->set_values = gdk_x11_gc_set_values;
98 gc_class->set_dashes = gdk_x11_gc_set_dashes;
102 gdk_gc_x11_finalize (GObject *object)
104 GdkGCX11 *x11_gc = GDK_GC_X11 (object);
106 if (x11_gc->clip_region)
107 gdk_region_destroy (x11_gc->clip_region);
109 XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
111 G_OBJECT_CLASS (parent_class)->finalize (object);
116 _gdk_x11_gc_new (GdkDrawable *drawable,
118 GdkGCValuesMask values_mask)
124 unsigned long xvalues_mask;
126 /* NOTICE that the drawable here has to be the impl drawable,
127 * not the publically-visible drawables.
129 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_X11 (drawable), NULL);
131 gc = g_object_new (gdk_gc_x11_get_type (), NULL);
132 private = GDK_GC_X11 (gc);
134 private->dirty_mask = 0;
135 private->clip_region = NULL;
137 private->xdisplay = GDK_DRAWABLE_IMPL_X11 (drawable)->xdisplay;
139 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
141 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
142 private->dirty_mask |= GDK_GC_DIRTY_CLIP;
145 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
147 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
148 private->dirty_mask |= GDK_GC_DIRTY_TS;
151 xvalues.function = GXcopy;
152 xvalues.fill_style = FillSolid;
153 xvalues.arc_mode = ArcPieSlice;
154 xvalues.subwindow_mode = ClipByChildren;
155 xvalues.graphics_exposures = False;
156 xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
158 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
160 private->xgc = XCreateGC (GDK_GC_XDISPLAY (gc),
161 GDK_DRAWABLE_IMPL_X11 (drawable)->xid,
162 xvalues_mask, &xvalues);
168 _gdk_x11_gc_flush (GdkGC *gc)
170 GdkGCX11 *private = GDK_GC_X11 (gc);
172 if (private->dirty_mask & GDK_GC_DIRTY_CLIP)
174 if (!private->clip_region)
175 XSetClipOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
176 gc->clip_x_origin, gc->clip_y_origin);
179 XRectangle *rectangles = g_new (XRectangle, private->clip_region->numRects);
180 GdkRegionBox *boxes = private->clip_region->rects;
183 for (i=0; i<private->clip_region->numRects; i++)
185 rectangles[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
186 rectangles[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
187 rectangles[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].x;
188 rectangles[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rectangles[i].y;
191 XSetClipRectangles(GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0, rectangles,
192 private->clip_region->numRects, YXBanded);
198 if (private->dirty_mask & GDK_GC_DIRTY_TS)
200 XSetTSOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
201 gc->ts_x_origin, gc->ts_y_origin);
204 private->dirty_mask = 0;
205 return GDK_GC_XGC (gc);
209 gdk_x11_gc_get_values (GdkGC *gc,
214 if (XGetGCValues (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
215 GCForeground | GCBackground | GCFont |
216 GCFunction | GCTile | GCStipple | /* GCClipMask | */
217 GCSubwindowMode | GCGraphicsExposures |
218 GCTileStipXOrigin | GCTileStipYOrigin |
219 GCClipXOrigin | GCClipYOrigin |
220 GCLineWidth | GCLineStyle | GCCapStyle |
221 GCFillStyle | GCJoinStyle, &xvalues))
223 values->foreground.pixel = xvalues.foreground;
224 values->background.pixel = xvalues.background;
225 values->font = gdk_font_lookup (xvalues.font);
227 switch (xvalues.function)
230 values->function = GDK_COPY;
233 values->function = GDK_INVERT;
236 values->function = GDK_XOR;
239 values->function = GDK_CLEAR;
242 values->function = GDK_AND;
245 values->function = GDK_AND_REVERSE;
248 values->function = GDK_AND_INVERT;
251 values->function = GDK_NOOP;
254 values->function = GDK_OR;
257 values->function = GDK_EQUIV;
260 values->function = GDK_OR_REVERSE;
263 values->function =GDK_COPY_INVERT;
266 values->function = GDK_OR_INVERT;
269 values->function = GDK_NAND;
272 values->function = GDK_SET;
275 values->function = GDK_NOR;
279 switch (xvalues.fill_style)
282 values->fill = GDK_SOLID;
285 values->fill = GDK_TILED;
288 values->fill = GDK_STIPPLED;
290 case FillOpaqueStippled:
291 values->fill = GDK_OPAQUE_STIPPLED;
295 values->tile = gdk_pixmap_lookup (xvalues.tile);
296 values->stipple = gdk_pixmap_lookup (xvalues.stipple);
297 values->clip_mask = NULL;
298 values->subwindow_mode = xvalues.subwindow_mode;
299 values->ts_x_origin = xvalues.ts_x_origin;
300 values->ts_y_origin = xvalues.ts_y_origin;
301 values->clip_x_origin = xvalues.clip_x_origin;
302 values->clip_y_origin = xvalues.clip_y_origin;
303 values->graphics_exposures = xvalues.graphics_exposures;
304 values->line_width = xvalues.line_width;
306 switch (xvalues.line_style)
309 values->line_style = GDK_LINE_SOLID;
312 values->line_style = GDK_LINE_ON_OFF_DASH;
315 values->line_style = GDK_LINE_DOUBLE_DASH;
319 switch (xvalues.cap_style)
322 values->cap_style = GDK_CAP_NOT_LAST;
325 values->cap_style = GDK_CAP_BUTT;
328 values->cap_style = GDK_CAP_ROUND;
331 values->cap_style = GDK_CAP_PROJECTING;
335 switch (xvalues.join_style)
338 values->join_style = GDK_JOIN_MITER;
341 values->join_style = GDK_JOIN_ROUND;
344 values->join_style = GDK_JOIN_BEVEL;
350 memset (values, 0, sizeof (GdkGCValues));
356 gdk_x11_gc_set_values (GdkGC *gc,
358 GdkGCValuesMask values_mask)
362 unsigned long xvalues_mask = 0;
364 g_return_if_fail (GDK_IS_GC (gc));
366 x11_gc = GDK_GC_X11 (gc);
368 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
370 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
371 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
374 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
376 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
377 x11_gc->dirty_mask |= GDK_GC_DIRTY_TS;
380 if (values_mask & GDK_GC_CLIP_MASK)
382 if (x11_gc->clip_region)
384 gdk_region_destroy (x11_gc->clip_region);
385 x11_gc->clip_region = NULL;
389 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
391 XChangeGC (GDK_GC_XDISPLAY (gc),
398 gdk_x11_gc_set_dashes (GdkGC *gc,
403 g_return_if_fail (GDK_IS_GC (gc));
404 g_return_if_fail (dash_list != NULL);
406 XSetDashes (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
407 dash_offset, dash_list, n);
411 gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
412 GdkGCValuesMask mask,
414 unsigned long *xvalues_mask)
416 /* Optimization for the common case (gdk_gc_new()) */
417 if (values == NULL || mask == 0)
420 if (mask & GDK_GC_FOREGROUND)
422 xvalues->foreground = values->foreground.pixel;
423 *xvalues_mask |= GCForeground;
425 if (mask & GDK_GC_BACKGROUND)
427 xvalues->background = values->background.pixel;
428 *xvalues_mask |= GCBackground;
430 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
432 xvalues->font = ((XFontStruct *) (GDK_FONT_XFONT (values->font)))->fid;
433 *xvalues_mask |= GCFont;
435 if (mask & GDK_GC_FUNCTION)
437 switch (values->function)
440 xvalues->function = GXcopy;
443 xvalues->function = GXinvert;
446 xvalues->function = GXxor;
449 xvalues->function = GXclear;
452 xvalues->function = GXand;
454 case GDK_AND_REVERSE:
455 xvalues->function = GXandReverse;
458 xvalues->function = GXandInverted;
461 xvalues->function = GXnoop;
464 xvalues->function = GXor;
467 xvalues->function = GXequiv;
470 xvalues->function = GXorReverse;
472 case GDK_COPY_INVERT:
473 xvalues->function = GXcopyInverted;
476 xvalues->function = GXorInverted;
479 xvalues->function = GXnand;
482 xvalues->function = GXset;
485 xvalues->function = GXnor;
488 *xvalues_mask |= GCFunction;
490 if (mask & GDK_GC_FILL)
492 switch (values->fill)
495 xvalues->fill_style = FillSolid;
498 xvalues->fill_style = FillTiled;
501 xvalues->fill_style = FillStippled;
503 case GDK_OPAQUE_STIPPLED:
504 xvalues->fill_style = FillOpaqueStippled;
507 *xvalues_mask |= GCFillStyle;
509 if (mask & GDK_GC_TILE)
512 xvalues->tile = GDK_DRAWABLE_XID (values->tile);
514 xvalues->tile = None;
516 *xvalues_mask |= GCTile;
518 if (mask & GDK_GC_STIPPLE)
521 xvalues->stipple = GDK_DRAWABLE_XID (values->stipple);
523 xvalues->stipple = None;
525 *xvalues_mask |= GCStipple;
527 if (mask & GDK_GC_CLIP_MASK)
529 if (values->clip_mask)
530 xvalues->clip_mask = GDK_DRAWABLE_XID (values->clip_mask);
532 xvalues->clip_mask = None;
534 *xvalues_mask |= GCClipMask;
537 if (mask & GDK_GC_SUBWINDOW)
539 xvalues->subwindow_mode = values->subwindow_mode;
540 *xvalues_mask |= GCSubwindowMode;
542 if (mask & GDK_GC_TS_X_ORIGIN)
544 xvalues->ts_x_origin = values->ts_x_origin;
545 *xvalues_mask |= GCTileStipXOrigin;
547 if (mask & GDK_GC_TS_Y_ORIGIN)
549 xvalues->ts_y_origin = values->ts_y_origin;
550 *xvalues_mask |= GCTileStipYOrigin;
552 if (mask & GDK_GC_CLIP_X_ORIGIN)
554 xvalues->clip_x_origin = values->clip_x_origin;
555 *xvalues_mask |= GCClipXOrigin;
557 if (mask & GDK_GC_CLIP_Y_ORIGIN)
559 xvalues->clip_y_origin = values->clip_y_origin;
560 *xvalues_mask |= GCClipYOrigin;
563 if (mask & GDK_GC_EXPOSURES)
565 xvalues->graphics_exposures = values->graphics_exposures;
566 *xvalues_mask |= GCGraphicsExposures;
569 if (mask & GDK_GC_LINE_WIDTH)
571 xvalues->line_width = values->line_width;
572 *xvalues_mask |= GCLineWidth;
574 if (mask & GDK_GC_LINE_STYLE)
576 switch (values->line_style)
579 xvalues->line_style = LineSolid;
581 case GDK_LINE_ON_OFF_DASH:
582 xvalues->line_style = LineOnOffDash;
584 case GDK_LINE_DOUBLE_DASH:
585 xvalues->line_style = LineDoubleDash;
588 *xvalues_mask |= GCLineStyle;
590 if (mask & GDK_GC_CAP_STYLE)
592 switch (values->cap_style)
594 case GDK_CAP_NOT_LAST:
595 xvalues->cap_style = CapNotLast;
598 xvalues->cap_style = CapButt;
601 xvalues->cap_style = CapRound;
603 case GDK_CAP_PROJECTING:
604 xvalues->cap_style = CapProjecting;
607 *xvalues_mask |= GCCapStyle;
609 if (mask & GDK_GC_JOIN_STYLE)
611 switch (values->join_style)
614 xvalues->join_style = JoinMiter;
617 xvalues->join_style = JoinRound;
620 xvalues->join_style = JoinBevel;
623 *xvalues_mask |= GCJoinStyle;
629 gdk_gc_set_clip_rectangle (GdkGC *gc,
630 GdkRectangle *rectangle)
634 g_return_if_fail (GDK_IS_GC (gc));
636 x11_gc = GDK_GC_X11 (gc);
638 if (x11_gc->clip_region)
639 gdk_region_destroy (x11_gc->clip_region);
642 x11_gc->clip_region = gdk_region_rectangle (rectangle);
645 x11_gc->clip_region = NULL;
646 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
649 gc->clip_x_origin = 0;
650 gc->clip_y_origin = 0;
652 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
656 gdk_gc_set_clip_region (GdkGC *gc,
661 g_return_if_fail (GDK_IS_GC (gc));
663 x11_gc = GDK_GC_X11 (gc);
665 if (x11_gc->clip_region)
666 gdk_region_destroy (x11_gc->clip_region);
669 x11_gc->clip_region = gdk_region_copy (region);
672 x11_gc->clip_region = NULL;
673 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
676 gc->clip_x_origin = 0;
677 gc->clip_y_origin = 0;
679 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
684 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
686 g_return_if_fail (GDK_IS_GC_X11 (dst_gc));
687 g_return_if_fail (GDK_IS_GC_X11 (src_gc));
689 XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit),
690 GDK_GC_XGC (dst_gc));