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/.
31 #include "gdkprivate-x11.h"
32 #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_class_init (GdkGCX11Class *klass);
58 static void gdk_gc_x11_finalize (GObject *object);
60 static gpointer parent_class = NULL;
63 _gdk_gc_x11_get_type (void)
65 static GType object_type = 0;
69 static const GTypeInfo object_info =
71 sizeof (GdkGCX11Class),
73 (GBaseFinalizeFunc) NULL,
74 (GClassInitFunc) gdk_gc_x11_class_init,
75 NULL, /* class_finalize */
76 NULL, /* class_data */
79 (GInstanceInitFunc) NULL,
82 object_type = g_type_register_static (GDK_TYPE_GC,
91 gdk_gc_x11_class_init (GdkGCX11Class *klass)
93 GObjectClass *object_class = G_OBJECT_CLASS (klass);
94 GdkGCClass *gc_class = GDK_GC_CLASS (klass);
96 parent_class = g_type_class_peek_parent (klass);
98 object_class->finalize = gdk_gc_x11_finalize;
100 gc_class->get_values = gdk_x11_gc_get_values;
101 gc_class->set_values = gdk_x11_gc_set_values;
102 gc_class->set_dashes = gdk_x11_gc_set_dashes;
106 gdk_gc_x11_finalize (GObject *object)
108 GdkGCX11 *x11_gc = GDK_GC_X11 (object);
110 if (x11_gc->clip_region)
111 gdk_region_destroy (x11_gc->clip_region);
113 if (x11_gc->fg_picture != None)
114 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
117 g_object_unref (x11_gc->stipple);
119 g_object_unref (x11_gc->tile);
121 XFreeGC (GDK_GC_XDISPLAY (x11_gc), GDK_GC_XGC (x11_gc));
123 G_OBJECT_CLASS (parent_class)->finalize (object);
128 _gdk_x11_gc_new (GdkDrawable *drawable,
130 GdkGCValuesMask values_mask)
136 unsigned long xvalues_mask;
138 /* NOTICE that the drawable here has to be the impl drawable,
139 * not the publically-visible drawables.
141 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_X11 (drawable), NULL);
143 gc = g_object_new (_gdk_gc_x11_get_type (), NULL);
144 private = GDK_GC_X11 (gc);
146 private->dirty_mask = 0;
147 private->have_clip_mask = FALSE;
148 private->clip_region = NULL;
150 private->screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
152 private->depth = gdk_drawable_get_depth (drawable);
154 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
156 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
157 private->dirty_mask |= GDK_GC_DIRTY_CLIP;
160 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
162 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
163 private->dirty_mask |= GDK_GC_DIRTY_TS;
166 if (values_mask & GDK_GC_FOREGROUND)
167 private->fg_pixel = values->foreground.pixel;
169 if (values_mask & GDK_GC_BACKGROUND)
170 private->bg_pixel = values->background.pixel;
172 if (values_mask & GDK_GC_FILL)
173 private->fill = values->fill;
175 if (values_mask & GDK_GC_STIPPLE)
177 private->stipple = values->stipple;
178 if (private->stipple)
179 g_object_ref (private->stipple);
182 if (values_mask & GDK_GC_TILE)
184 private->tile = values->tile;
186 g_object_ref (private->tile);
189 if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
190 private->have_clip_mask = TRUE;
192 xvalues.function = GXcopy;
193 xvalues.fill_style = FillSolid;
194 xvalues.arc_mode = ArcPieSlice;
195 xvalues.subwindow_mode = ClipByChildren;
196 xvalues.graphics_exposures = False;
197 xvalues_mask = GCFunction | GCFillStyle | GCArcMode | GCSubwindowMode | GCGraphicsExposures;
199 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
201 private->xgc = XCreateGC (GDK_GC_XDISPLAY (gc),
202 GDK_DRAWABLE_IMPL_X11 (drawable)->xid,
203 xvalues_mask, &xvalues);
209 _gdk_x11_gc_flush (GdkGC *gc)
211 GdkGCX11 *private = GDK_GC_X11 (gc);
213 if (private->dirty_mask & GDK_GC_DIRTY_CLIP)
215 if (!private->clip_region)
216 XSetClipOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
217 gc->clip_x_origin, gc->clip_y_origin);
220 XRectangle *rectangles;
223 _gdk_region_get_xrectangles (private->clip_region,
229 XSetClipRectangles (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), 0, 0,
237 if (private->dirty_mask & GDK_GC_DIRTY_TS)
239 XSetTSOrigin (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
240 gc->ts_x_origin, gc->ts_y_origin);
243 private->dirty_mask = 0;
244 return GDK_GC_XGC (gc);
248 gdk_x11_gc_get_values (GdkGC *gc,
253 if (XGetGCValues (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
254 GCForeground | GCBackground | GCFont |
255 GCFunction | GCTile | GCStipple | /* GCClipMask | */
256 GCSubwindowMode | GCGraphicsExposures |
257 GCTileStipXOrigin | GCTileStipYOrigin |
258 GCClipXOrigin | GCClipYOrigin |
259 GCLineWidth | GCLineStyle | GCCapStyle |
260 GCFillStyle | GCJoinStyle, &xvalues))
262 values->foreground.pixel = xvalues.foreground;
263 values->background.pixel = xvalues.background;
264 values->font = gdk_font_lookup_for_display (GDK_GC_DISPLAY (gc),
267 switch (xvalues.function)
270 values->function = GDK_COPY;
273 values->function = GDK_INVERT;
276 values->function = GDK_XOR;
279 values->function = GDK_CLEAR;
282 values->function = GDK_AND;
285 values->function = GDK_AND_REVERSE;
288 values->function = GDK_AND_INVERT;
291 values->function = GDK_NOOP;
294 values->function = GDK_OR;
297 values->function = GDK_EQUIV;
300 values->function = GDK_OR_REVERSE;
303 values->function =GDK_COPY_INVERT;
306 values->function = GDK_OR_INVERT;
309 values->function = GDK_NAND;
312 values->function = GDK_SET;
315 values->function = GDK_NOR;
319 switch (xvalues.fill_style)
322 values->fill = GDK_SOLID;
325 values->fill = GDK_TILED;
328 values->fill = GDK_STIPPLED;
330 case FillOpaqueStippled:
331 values->fill = GDK_OPAQUE_STIPPLED;
335 values->tile = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
337 values->stipple = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
339 values->clip_mask = NULL;
340 values->subwindow_mode = xvalues.subwindow_mode;
341 values->ts_x_origin = xvalues.ts_x_origin;
342 values->ts_y_origin = xvalues.ts_y_origin;
343 values->clip_x_origin = xvalues.clip_x_origin;
344 values->clip_y_origin = xvalues.clip_y_origin;
345 values->graphics_exposures = xvalues.graphics_exposures;
346 values->line_width = xvalues.line_width;
348 switch (xvalues.line_style)
351 values->line_style = GDK_LINE_SOLID;
354 values->line_style = GDK_LINE_ON_OFF_DASH;
357 values->line_style = GDK_LINE_DOUBLE_DASH;
361 switch (xvalues.cap_style)
364 values->cap_style = GDK_CAP_NOT_LAST;
367 values->cap_style = GDK_CAP_BUTT;
370 values->cap_style = GDK_CAP_ROUND;
373 values->cap_style = GDK_CAP_PROJECTING;
377 switch (xvalues.join_style)
380 values->join_style = GDK_JOIN_MITER;
383 values->join_style = GDK_JOIN_ROUND;
386 values->join_style = GDK_JOIN_BEVEL;
392 memset (values, 0, sizeof (GdkGCValues));
397 clear_fg_picture (GdkGC *gc)
399 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
401 if (x11_gc->fg_picture != None)
403 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
404 x11_gc->fg_picture = None;
409 gdk_x11_gc_set_values (GdkGC *gc,
411 GdkGCValuesMask values_mask)
415 unsigned long xvalues_mask = 0;
417 x11_gc = GDK_GC_X11 (gc);
419 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
421 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
422 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
425 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
427 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
428 x11_gc->dirty_mask |= GDK_GC_DIRTY_TS;
431 if (values_mask & GDK_GC_CLIP_MASK)
433 if (x11_gc->clip_region)
435 gdk_region_destroy (x11_gc->clip_region);
436 x11_gc->clip_region = NULL;
439 x11_gc->have_clip_mask = values->clip_mask != NULL;
442 if (values_mask & GDK_GC_FOREGROUND)
443 x11_gc->fg_pixel = values->foreground.pixel;
445 if (values_mask & GDK_GC_BACKGROUND)
447 if (x11_gc->bg_pixel != values->background.pixel)
449 x11_gc->bg_pixel = values->background.pixel;
450 if (x11_gc->fill == GDK_OPAQUE_STIPPLED)
451 clear_fg_picture (gc);
455 if (values_mask & GDK_GC_FILL)
457 if (x11_gc->fill != values->fill)
459 clear_fg_picture (gc);
460 x11_gc->fill = values->fill;
464 if (values_mask & GDK_GC_STIPPLE)
466 if (x11_gc->stipple != values->stipple)
468 if (x11_gc->fill == GDK_STIPPLED || x11_gc->fill == GDK_OPAQUE_STIPPLED)
469 clear_fg_picture (gc);
471 g_object_unref (x11_gc->stipple);
472 x11_gc->stipple = values->stipple;
474 g_object_ref (x11_gc->stipple);
478 if (values_mask & GDK_GC_TILE)
480 if (x11_gc->tile != values->tile)
482 if (x11_gc->fill == GDK_TILED)
483 clear_fg_picture (gc);
485 g_object_unref (x11_gc->tile);
486 x11_gc->tile = values->tile;
488 g_object_ref (x11_gc->tile);
492 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
494 XChangeGC (GDK_GC_XDISPLAY (gc),
501 gdk_x11_gc_set_dashes (GdkGC *gc,
506 g_return_if_fail (GDK_IS_GC (gc));
507 g_return_if_fail (dash_list != NULL);
509 XSetDashes (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
510 dash_offset, dash_list, n);
514 gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
515 GdkGCValuesMask mask,
517 unsigned long *xvalues_mask)
519 /* Optimization for the common case (gdk_gc_new()) */
520 if (values == NULL || mask == 0)
523 if (mask & GDK_GC_FOREGROUND)
525 xvalues->foreground = values->foreground.pixel;
526 *xvalues_mask |= GCForeground;
528 if (mask & GDK_GC_BACKGROUND)
530 xvalues->background = values->background.pixel;
531 *xvalues_mask |= GCBackground;
533 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
535 xvalues->font = ((XFontStruct *) (GDK_FONT_XFONT (values->font)))->fid;
536 *xvalues_mask |= GCFont;
538 if (mask & GDK_GC_FUNCTION)
540 switch (values->function)
543 xvalues->function = GXcopy;
546 xvalues->function = GXinvert;
549 xvalues->function = GXxor;
552 xvalues->function = GXclear;
555 xvalues->function = GXand;
557 case GDK_AND_REVERSE:
558 xvalues->function = GXandReverse;
561 xvalues->function = GXandInverted;
564 xvalues->function = GXnoop;
567 xvalues->function = GXor;
570 xvalues->function = GXequiv;
573 xvalues->function = GXorReverse;
575 case GDK_COPY_INVERT:
576 xvalues->function = GXcopyInverted;
579 xvalues->function = GXorInverted;
582 xvalues->function = GXnand;
585 xvalues->function = GXset;
588 xvalues->function = GXnor;
591 *xvalues_mask |= GCFunction;
593 if (mask & GDK_GC_FILL)
595 switch (values->fill)
598 xvalues->fill_style = FillSolid;
601 xvalues->fill_style = FillTiled;
604 xvalues->fill_style = FillStippled;
606 case GDK_OPAQUE_STIPPLED:
607 xvalues->fill_style = FillOpaqueStippled;
610 *xvalues_mask |= GCFillStyle;
612 if (mask & GDK_GC_TILE)
615 xvalues->tile = GDK_DRAWABLE_XID (values->tile);
617 xvalues->tile = None;
619 *xvalues_mask |= GCTile;
621 if (mask & GDK_GC_STIPPLE)
624 xvalues->stipple = GDK_DRAWABLE_XID (values->stipple);
626 xvalues->stipple = None;
628 *xvalues_mask |= GCStipple;
630 if (mask & GDK_GC_CLIP_MASK)
632 if (values->clip_mask)
633 xvalues->clip_mask = GDK_DRAWABLE_XID (values->clip_mask);
635 xvalues->clip_mask = None;
637 *xvalues_mask |= GCClipMask;
640 if (mask & GDK_GC_SUBWINDOW)
642 xvalues->subwindow_mode = values->subwindow_mode;
643 *xvalues_mask |= GCSubwindowMode;
645 if (mask & GDK_GC_TS_X_ORIGIN)
647 xvalues->ts_x_origin = values->ts_x_origin;
648 *xvalues_mask |= GCTileStipXOrigin;
650 if (mask & GDK_GC_TS_Y_ORIGIN)
652 xvalues->ts_y_origin = values->ts_y_origin;
653 *xvalues_mask |= GCTileStipYOrigin;
655 if (mask & GDK_GC_CLIP_X_ORIGIN)
657 xvalues->clip_x_origin = values->clip_x_origin;
658 *xvalues_mask |= GCClipXOrigin;
660 if (mask & GDK_GC_CLIP_Y_ORIGIN)
662 xvalues->clip_y_origin = values->clip_y_origin;
663 *xvalues_mask |= GCClipYOrigin;
666 if (mask & GDK_GC_EXPOSURES)
668 xvalues->graphics_exposures = values->graphics_exposures;
669 *xvalues_mask |= GCGraphicsExposures;
672 if (mask & GDK_GC_LINE_WIDTH)
674 xvalues->line_width = values->line_width;
675 *xvalues_mask |= GCLineWidth;
677 if (mask & GDK_GC_LINE_STYLE)
679 switch (values->line_style)
682 xvalues->line_style = LineSolid;
684 case GDK_LINE_ON_OFF_DASH:
685 xvalues->line_style = LineOnOffDash;
687 case GDK_LINE_DOUBLE_DASH:
688 xvalues->line_style = LineDoubleDash;
691 *xvalues_mask |= GCLineStyle;
693 if (mask & GDK_GC_CAP_STYLE)
695 switch (values->cap_style)
697 case GDK_CAP_NOT_LAST:
698 xvalues->cap_style = CapNotLast;
701 xvalues->cap_style = CapButt;
704 xvalues->cap_style = CapRound;
706 case GDK_CAP_PROJECTING:
707 xvalues->cap_style = CapProjecting;
710 *xvalues_mask |= GCCapStyle;
712 if (mask & GDK_GC_JOIN_STYLE)
714 switch (values->join_style)
717 xvalues->join_style = JoinMiter;
720 xvalues->join_style = JoinRound;
723 xvalues->join_style = JoinBevel;
726 *xvalues_mask |= GCJoinStyle;
732 * gdk_gc_set_clip_rectangle:
734 * @rectangle: the rectangle to clip to.
736 * Sets the clip mask for a graphics context from a
737 * rectangle. The clip mask is interpreted relative to the clip
738 * origin. (See gdk_gc_set_clip_origin()).
741 gdk_gc_set_clip_rectangle (GdkGC *gc,
742 GdkRectangle *rectangle)
745 gboolean had_region = FALSE;
747 g_return_if_fail (GDK_IS_GC (gc));
749 x11_gc = GDK_GC_X11 (gc);
751 if (x11_gc->clip_region)
754 gdk_region_destroy (x11_gc->clip_region);
758 x11_gc->clip_region = gdk_region_rectangle (rectangle);
760 x11_gc->clip_region = NULL;
762 /* Unset immediately, to make sure Xlib doesn't keep the
763 * XID of an old clip mask cached
765 if ((had_region && !rectangle) || x11_gc->have_clip_mask)
767 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
768 x11_gc->have_clip_mask = FALSE;
771 gc->clip_x_origin = 0;
772 gc->clip_y_origin = 0;
774 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
778 * gdk_gc_set_clip_region:
780 * @region: the #GdkRegion.
782 * Sets the clip mask for a graphics context from a region structure.
783 * The clip mask is interpreted relative to the clip origin. (See
784 * gdk_gc_set_clip_origin()).
787 gdk_gc_set_clip_region (GdkGC *gc,
791 gboolean had_region = FALSE;
793 g_return_if_fail (GDK_IS_GC (gc));
795 x11_gc = GDK_GC_X11 (gc);
797 if (x11_gc->clip_region)
800 gdk_region_destroy (x11_gc->clip_region);
804 x11_gc->clip_region = gdk_region_copy (region);
806 x11_gc->clip_region = NULL;
808 /* Unset immediately, to make sure Xlib doesn't keep the
809 * XID of an old clip mask cached
811 if ((had_region && !region) || x11_gc->have_clip_mask)
813 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
814 x11_gc->have_clip_mask = FALSE;
817 gc->clip_x_origin = 0;
818 gc->clip_y_origin = 0;
820 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
826 * @dst_gc: the destination graphics context.
827 * @src_gc: the source graphics context.
829 * Copy the set of values from one graphics context
830 * onto another graphics context.
833 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
835 GdkGCX11 *x11_src_gc;
836 GdkGCX11 *x11_dst_gc;
838 g_return_if_fail (GDK_IS_GC_X11 (dst_gc));
839 g_return_if_fail (GDK_IS_GC_X11 (src_gc));
841 x11_dst_gc = GDK_GC_X11 (dst_gc);
842 x11_src_gc = GDK_GC_X11 (src_gc);
844 XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit),
845 GDK_GC_XGC (dst_gc));
847 dst_gc->clip_x_origin = src_gc->clip_x_origin;
848 dst_gc->clip_y_origin = src_gc->clip_y_origin;
849 dst_gc->ts_x_origin = src_gc->ts_x_origin;
850 dst_gc->ts_y_origin = src_gc->ts_y_origin;
852 if (src_gc->colormap)
853 g_object_ref (src_gc->colormap);
855 if (dst_gc->colormap)
856 g_object_unref (dst_gc->colormap);
858 dst_gc->colormap = src_gc->colormap;
860 if (x11_dst_gc->clip_region)
861 gdk_region_destroy (x11_dst_gc->clip_region);
863 if (x11_src_gc->clip_region)
864 x11_dst_gc->clip_region = gdk_region_copy (x11_src_gc->clip_region);
866 x11_dst_gc->clip_region = NULL;
868 x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
869 x11_dst_gc->fg_pixel = x11_src_gc->fg_pixel;
870 x11_dst_gc->fill = x11_src_gc->fill;
872 if (x11_dst_gc->stipple)
873 g_object_unref (x11_dst_gc->stipple);
874 x11_dst_gc->stipple = x11_src_gc->stipple;
875 if (x11_dst_gc->stipple)
876 g_object_ref (x11_dst_gc->stipple);
878 if (x11_dst_gc->tile)
879 g_object_unref (x11_dst_gc->tile);
880 x11_dst_gc->tile = x11_src_gc->tile;
881 if (x11_dst_gc->tile)
882 g_object_ref (x11_dst_gc->tile);
884 clear_fg_picture (dst_gc);
891 * Gets the #GdkScreen for which @gc was created
893 * Returns: the #GdkScreen for @gc.
898 gdk_gc_get_screen (GdkGC *gc)
900 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
902 return GDK_GC_X11 (gc)->screen;
906 * gdk_x11_gc_get_xdisplay:
909 * Returns the display of a #GdkGC.
911 * Return value: an Xlib <type>Display*</type>.
914 gdk_x11_gc_get_xdisplay (GdkGC *gc)
916 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
918 return GDK_SCREEN_XDISPLAY (gdk_gc_get_screen (gc));
922 * gdk_x11_gc_get_xgc:
925 * Returns the X GC of a #GdkGC.
927 * Return value: an Xlib <type>GC</type>.
930 gdk_x11_gc_get_xgc (GdkGC *gc)
934 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
936 gc_x11 = GDK_GC_X11 (gc);
938 if (gc_x11->dirty_mask)
939 _gdk_x11_gc_flush (gc);
944 /* Various bits of the below are roughly cribbed from XFree86
945 * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard
948 static XRenderPictFormat *
949 foreground_format (GdkGC *gc)
951 XRenderPictFormat pf;
953 pf.type = PictTypeDirect;
955 pf.direct.redMask = 0xff;
956 pf.direct.greenMask = 0xff;
957 pf.direct.blueMask = 0xff;
958 pf.direct.alphaMask = 0xff;
960 return XRenderFindFormat (GDK_GC_XDISPLAY (gc),
964 PictFormatGreenMask |
966 PictFormatAlphaMask),
972 make_fg_tile_picture (GdkGC *gc)
974 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
975 GdkVisual *visual = gdk_drawable_get_visual (x11_gc->tile);
976 XRenderPictFormat *format = NULL;
980 format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc),
981 GDK_VISUAL_XVISUAL (visual));
983 else if (x11_gc->depth == 1)
985 format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
991 XRenderPictureAttributes pa;
994 return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
995 GDK_PIXMAP_XID (x11_gc->tile),
1002 make_stipple_picture (GdkGC *gc)
1004 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1005 XRenderPictFormat *format = NULL;
1006 XRenderPictureAttributes pa;
1008 format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
1012 return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1013 GDK_PIXMAP_XID (x11_gc->stipple),
1019 make_color_picture (GdkGC *gc,
1020 XRenderColor *color)
1022 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1023 XRenderPictureAttributes pa;
1024 XRenderPictFormat *pix_format = foreground_format (gc);
1031 pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1032 GDK_SCREEN_XROOTWIN (x11_gc->screen),
1033 1, 1, pix_format->depth);
1035 picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1039 XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1041 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1049 get_bg_color (GdkGC *gc,
1050 XRenderColor *render_color)
1052 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1055 cmap = gdk_gc_get_colormap (gc);
1061 gdk_colormap_query_color (cmap, x11_gc->bg_pixel, &color);
1063 render_color->alpha = 0xffff;
1064 render_color->red = color.red;
1065 render_color->green = color.green;
1066 render_color->blue = color.blue;
1068 else /* Not worth warning, just use black */
1070 render_color->alpha = 0xffff;
1071 render_color->red = 0;
1072 render_color->green = 0;
1073 render_color->blue = 0;
1078 * _gdk_x11_gc_get_fg_picture:
1081 * Gets a Xrender Picture object suitable for being the source
1082 * drawable for drawing with the foreground the graphics context.
1084 * Return value: a Picture, owned by the GC; this cannot be
1085 * used over subsequent modification of the GC.
1088 _gdk_x11_gc_get_fg_picture (GdkGC *gc)
1091 gboolean new = FALSE;
1096 g_return_val_if_fail (GDK_IS_GC_X11 (gc), None);
1098 if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc)))
1101 x11_gc = GDK_GC_X11 (gc);
1107 switch (x11_gc->fill)
1114 if (!x11_gc->fg_picture)
1115 x11_gc->fg_picture = make_fg_tile_picture (gc);
1117 if (x11_gc->fg_picture != None)
1118 return x11_gc->fg_picture;
1122 case GDK_OPAQUE_STIPPLED:
1123 if (x11_gc->stipple)
1125 gdk_drawable_get_size (x11_gc->stipple, &width, &height);
1126 fill = x11_gc->fill;
1131 if (x11_gc->fg_picture == None)
1133 XRenderPictureAttributes pa;
1134 XRenderPictFormat *pix_format = foreground_format (gc);
1140 pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1141 GDK_SCREEN_XROOTWIN (x11_gc->screen),
1142 width, height, pix_format->depth);
1144 x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1148 XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1153 _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor);
1155 if (x11_gc->fg_picture_color.alpha != 0xffff ||
1156 x11_gc->fg_picture_color.red != xftcolor.color.red ||
1157 x11_gc->fg_picture_color.green != xftcolor.color.green ||
1158 x11_gc->fg_picture_color.blue != xftcolor.color.blue)
1160 x11_gc->fg_picture_color.alpha = 0xffff;
1161 x11_gc->fg_picture_color.red = xftcolor.color.red;
1162 x11_gc->fg_picture_color.green = xftcolor.color.green;
1163 x11_gc->fg_picture_color.blue = xftcolor.color.blue;
1171 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1172 x11_gc->fg_picture, &x11_gc->fg_picture_color,
1173 0, 0, width, height);
1177 Picture stipple_picture = make_stipple_picture (gc);
1179 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1180 x11_gc->fg_picture, &x11_gc->fg_picture_color,
1181 0, 0, width, height);
1182 XRenderComposite (GDK_GC_XDISPLAY (gc),
1184 stipple_picture, None, x11_gc->fg_picture,
1185 0, 0, 0, 0, 0, 0, width, height);
1187 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1190 case GDK_OPAQUE_STIPPLED:
1192 XRenderColor bg_color;
1194 Picture stipple_picture = make_stipple_picture (gc);
1195 Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color);
1197 get_bg_color (gc, &bg_color);
1199 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1200 x11_gc->fg_picture, &bg_color,
1201 0, 0, width, height);
1202 XRenderComposite (GDK_GC_XDISPLAY (gc),
1204 fg_picture, stipple_picture, x11_gc->fg_picture,
1205 0, 0, 0, 0, 0, 0, width, height);
1207 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1208 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture);
1212 g_assert_not_reached (); /* handled above */
1216 return x11_gc->fg_picture;
1220 * _gdk_gc_x11_get_fg_xft_color:
1222 * @xftcolor: location to store the color
1224 * Gets the foreground color of the GC as a XftColor.
1227 _gdk_gc_x11_get_fg_xft_color (GdkGC *gc,
1234 g_return_if_fail (GDK_IS_GC_X11 (gc));
1236 x11_gc = GDK_GC_X11 (gc);
1238 cmap = gdk_gc_get_colormap (gc);
1240 xftcolor->pixel = x11_gc->fg_pixel;
1244 gdk_colormap_query_color (cmap, xftcolor->pixel, &color);
1245 xftcolor->color.alpha = 0xffff;
1246 xftcolor->color.red = color.red;
1247 xftcolor->color.green = color.green;
1248 xftcolor->color.blue = color.blue;
1250 else if (x11_gc->depth == 1)
1252 /* Drawing with Xft on a bitmap is a bit bizzare; it
1253 * takes alpha >= 0x8000 to mean 'set to 1' and
1254 * alpha < 0x8000 to mean 'set to 0'.
1256 if (xftcolor->pixel)
1258 xftcolor->color.red = 0xffff;
1259 xftcolor->color.green = 0xffff;
1260 xftcolor->color.blue = 0xffff;
1261 xftcolor->color.alpha = 0xffff;
1265 xftcolor->color.red = 0;
1266 xftcolor->color.green = 0;
1267 xftcolor->color.blue = 0;
1268 xftcolor->color.alpha = 0;
1273 g_warning ("Using Xft rendering requires the GC argument to have a\n"
1274 "specified colormap. If the GC was created for a drawable\n"
1275 "with a colormap, the colormap will be set on the GC\n"
1276 "automatically. Otherwise, a colormap must be set on it with"
1277 "gdk_gc_set_colormap");
1282 _gdk_windowing_gc_get_foreground (GdkGC *gc,
1288 g_return_if_fail (GDK_IS_GC_X11 (gc));
1290 x11_gc = GDK_GC_X11 (gc);
1292 color->pixel = x11_gc->fg_pixel;
1294 cmap = gdk_gc_get_colormap (gc);
1297 gdk_colormap_query_color (cmap, x11_gc->fg_pixel, color);
1299 g_warning ("No colormap in _gdk_windowing_gc_get_foreground");