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 Display *xdisplay = GDK_GC_XDISPLAY (gc);
212 GdkGCX11 *private = GDK_GC_X11 (gc);
213 GC xgc = private->xgc;
215 if (private->dirty_mask & GDK_GC_DIRTY_CLIP)
217 if (!private->clip_region)
218 XSetClipOrigin (xdisplay, xgc,
219 gc->clip_x_origin, gc->clip_y_origin);
222 XRectangle *rectangles;
225 _gdk_region_get_xrectangles (private->clip_region,
231 XSetClipRectangles (xdisplay, xgc, 0, 0,
239 if (private->dirty_mask & GDK_GC_DIRTY_TS)
241 XSetTSOrigin (xdisplay, xgc,
242 gc->ts_x_origin, gc->ts_y_origin);
245 private->dirty_mask = 0;
250 gdk_x11_gc_get_values (GdkGC *gc,
255 if (XGetGCValues (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
256 GCForeground | GCBackground | GCFont |
257 GCFunction | GCTile | GCStipple | /* GCClipMask | */
258 GCSubwindowMode | GCGraphicsExposures |
259 GCTileStipXOrigin | GCTileStipYOrigin |
260 GCClipXOrigin | GCClipYOrigin |
261 GCLineWidth | GCLineStyle | GCCapStyle |
262 GCFillStyle | GCJoinStyle, &xvalues))
264 values->foreground.pixel = xvalues.foreground;
265 values->background.pixel = xvalues.background;
266 values->font = gdk_font_lookup_for_display (GDK_GC_DISPLAY (gc),
269 switch (xvalues.function)
272 values->function = GDK_COPY;
275 values->function = GDK_INVERT;
278 values->function = GDK_XOR;
281 values->function = GDK_CLEAR;
284 values->function = GDK_AND;
287 values->function = GDK_AND_REVERSE;
290 values->function = GDK_AND_INVERT;
293 values->function = GDK_NOOP;
296 values->function = GDK_OR;
299 values->function = GDK_EQUIV;
302 values->function = GDK_OR_REVERSE;
305 values->function =GDK_COPY_INVERT;
308 values->function = GDK_OR_INVERT;
311 values->function = GDK_NAND;
314 values->function = GDK_SET;
317 values->function = GDK_NOR;
321 switch (xvalues.fill_style)
324 values->fill = GDK_SOLID;
327 values->fill = GDK_TILED;
330 values->fill = GDK_STIPPLED;
332 case FillOpaqueStippled:
333 values->fill = GDK_OPAQUE_STIPPLED;
337 values->tile = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
339 values->stipple = gdk_pixmap_lookup_for_display (GDK_GC_DISPLAY (gc),
341 values->clip_mask = NULL;
342 values->subwindow_mode = xvalues.subwindow_mode;
343 values->ts_x_origin = xvalues.ts_x_origin;
344 values->ts_y_origin = xvalues.ts_y_origin;
345 values->clip_x_origin = xvalues.clip_x_origin;
346 values->clip_y_origin = xvalues.clip_y_origin;
347 values->graphics_exposures = xvalues.graphics_exposures;
348 values->line_width = xvalues.line_width;
350 switch (xvalues.line_style)
353 values->line_style = GDK_LINE_SOLID;
356 values->line_style = GDK_LINE_ON_OFF_DASH;
359 values->line_style = GDK_LINE_DOUBLE_DASH;
363 switch (xvalues.cap_style)
366 values->cap_style = GDK_CAP_NOT_LAST;
369 values->cap_style = GDK_CAP_BUTT;
372 values->cap_style = GDK_CAP_ROUND;
375 values->cap_style = GDK_CAP_PROJECTING;
379 switch (xvalues.join_style)
382 values->join_style = GDK_JOIN_MITER;
385 values->join_style = GDK_JOIN_ROUND;
388 values->join_style = GDK_JOIN_BEVEL;
394 memset (values, 0, sizeof (GdkGCValues));
399 clear_fg_picture (GdkGC *gc)
401 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
403 if (x11_gc->fg_picture != None)
405 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture);
406 x11_gc->fg_picture = None;
411 gdk_x11_gc_set_values (GdkGC *gc,
413 GdkGCValuesMask values_mask)
417 unsigned long xvalues_mask = 0;
419 x11_gc = GDK_GC_X11 (gc);
421 if (values_mask & (GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN))
423 values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
424 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
427 if (values_mask & (GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN))
429 values_mask &= ~(GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
430 x11_gc->dirty_mask |= GDK_GC_DIRTY_TS;
433 if (values_mask & GDK_GC_CLIP_MASK)
435 if (x11_gc->clip_region)
437 gdk_region_destroy (x11_gc->clip_region);
438 x11_gc->clip_region = NULL;
441 x11_gc->have_clip_mask = values->clip_mask != NULL;
444 if (values_mask & GDK_GC_FOREGROUND)
445 x11_gc->fg_pixel = values->foreground.pixel;
447 if (values_mask & GDK_GC_BACKGROUND)
449 if (x11_gc->bg_pixel != values->background.pixel)
451 x11_gc->bg_pixel = values->background.pixel;
452 if (x11_gc->fill == GDK_OPAQUE_STIPPLED)
453 clear_fg_picture (gc);
457 if (values_mask & GDK_GC_FILL)
459 if (x11_gc->fill != values->fill)
461 clear_fg_picture (gc);
462 x11_gc->fill = values->fill;
466 if (values_mask & GDK_GC_STIPPLE)
468 if (x11_gc->stipple != values->stipple)
470 if (x11_gc->fill == GDK_STIPPLED || x11_gc->fill == GDK_OPAQUE_STIPPLED)
471 clear_fg_picture (gc);
473 g_object_unref (x11_gc->stipple);
474 x11_gc->stipple = values->stipple;
476 g_object_ref (x11_gc->stipple);
480 if (values_mask & GDK_GC_TILE)
482 if (x11_gc->tile != values->tile)
484 if (x11_gc->fill == GDK_TILED)
485 clear_fg_picture (gc);
487 g_object_unref (x11_gc->tile);
488 x11_gc->tile = values->tile;
490 g_object_ref (x11_gc->tile);
494 gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
496 XChangeGC (GDK_GC_XDISPLAY (gc),
503 gdk_x11_gc_set_dashes (GdkGC *gc,
508 g_return_if_fail (GDK_IS_GC (gc));
509 g_return_if_fail (dash_list != NULL);
511 XSetDashes (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc),
512 dash_offset, dash_list, n);
516 gdk_x11_gc_values_to_xvalues (GdkGCValues *values,
517 GdkGCValuesMask mask,
519 unsigned long *xvalues_mask)
521 /* Optimization for the common case (gdk_gc_new()) */
522 if (values == NULL || mask == 0)
525 if (mask & GDK_GC_FOREGROUND)
527 xvalues->foreground = values->foreground.pixel;
528 *xvalues_mask |= GCForeground;
530 if (mask & GDK_GC_BACKGROUND)
532 xvalues->background = values->background.pixel;
533 *xvalues_mask |= GCBackground;
535 if ((mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
537 xvalues->font = ((XFontStruct *) (GDK_FONT_XFONT (values->font)))->fid;
538 *xvalues_mask |= GCFont;
540 if (mask & GDK_GC_FUNCTION)
542 switch (values->function)
545 xvalues->function = GXcopy;
548 xvalues->function = GXinvert;
551 xvalues->function = GXxor;
554 xvalues->function = GXclear;
557 xvalues->function = GXand;
559 case GDK_AND_REVERSE:
560 xvalues->function = GXandReverse;
563 xvalues->function = GXandInverted;
566 xvalues->function = GXnoop;
569 xvalues->function = GXor;
572 xvalues->function = GXequiv;
575 xvalues->function = GXorReverse;
577 case GDK_COPY_INVERT:
578 xvalues->function = GXcopyInverted;
581 xvalues->function = GXorInverted;
584 xvalues->function = GXnand;
587 xvalues->function = GXset;
590 xvalues->function = GXnor;
593 *xvalues_mask |= GCFunction;
595 if (mask & GDK_GC_FILL)
597 switch (values->fill)
600 xvalues->fill_style = FillSolid;
603 xvalues->fill_style = FillTiled;
606 xvalues->fill_style = FillStippled;
608 case GDK_OPAQUE_STIPPLED:
609 xvalues->fill_style = FillOpaqueStippled;
612 *xvalues_mask |= GCFillStyle;
614 if (mask & GDK_GC_TILE)
617 xvalues->tile = GDK_DRAWABLE_XID (values->tile);
619 xvalues->tile = None;
621 *xvalues_mask |= GCTile;
623 if (mask & GDK_GC_STIPPLE)
626 xvalues->stipple = GDK_DRAWABLE_XID (values->stipple);
628 xvalues->stipple = None;
630 *xvalues_mask |= GCStipple;
632 if (mask & GDK_GC_CLIP_MASK)
634 if (values->clip_mask)
635 xvalues->clip_mask = GDK_DRAWABLE_XID (values->clip_mask);
637 xvalues->clip_mask = None;
639 *xvalues_mask |= GCClipMask;
642 if (mask & GDK_GC_SUBWINDOW)
644 xvalues->subwindow_mode = values->subwindow_mode;
645 *xvalues_mask |= GCSubwindowMode;
647 if (mask & GDK_GC_TS_X_ORIGIN)
649 xvalues->ts_x_origin = values->ts_x_origin;
650 *xvalues_mask |= GCTileStipXOrigin;
652 if (mask & GDK_GC_TS_Y_ORIGIN)
654 xvalues->ts_y_origin = values->ts_y_origin;
655 *xvalues_mask |= GCTileStipYOrigin;
657 if (mask & GDK_GC_CLIP_X_ORIGIN)
659 xvalues->clip_x_origin = values->clip_x_origin;
660 *xvalues_mask |= GCClipXOrigin;
662 if (mask & GDK_GC_CLIP_Y_ORIGIN)
664 xvalues->clip_y_origin = values->clip_y_origin;
665 *xvalues_mask |= GCClipYOrigin;
668 if (mask & GDK_GC_EXPOSURES)
670 xvalues->graphics_exposures = values->graphics_exposures;
671 *xvalues_mask |= GCGraphicsExposures;
674 if (mask & GDK_GC_LINE_WIDTH)
676 xvalues->line_width = values->line_width;
677 *xvalues_mask |= GCLineWidth;
679 if (mask & GDK_GC_LINE_STYLE)
681 switch (values->line_style)
684 xvalues->line_style = LineSolid;
686 case GDK_LINE_ON_OFF_DASH:
687 xvalues->line_style = LineOnOffDash;
689 case GDK_LINE_DOUBLE_DASH:
690 xvalues->line_style = LineDoubleDash;
693 *xvalues_mask |= GCLineStyle;
695 if (mask & GDK_GC_CAP_STYLE)
697 switch (values->cap_style)
699 case GDK_CAP_NOT_LAST:
700 xvalues->cap_style = CapNotLast;
703 xvalues->cap_style = CapButt;
706 xvalues->cap_style = CapRound;
708 case GDK_CAP_PROJECTING:
709 xvalues->cap_style = CapProjecting;
712 *xvalues_mask |= GCCapStyle;
714 if (mask & GDK_GC_JOIN_STYLE)
716 switch (values->join_style)
719 xvalues->join_style = JoinMiter;
722 xvalues->join_style = JoinRound;
725 xvalues->join_style = JoinBevel;
728 *xvalues_mask |= GCJoinStyle;
734 * gdk_gc_set_clip_rectangle:
736 * @rectangle: the rectangle to clip to.
738 * Sets the clip mask for a graphics context from a
739 * rectangle. The clip mask is interpreted relative to the clip
740 * origin. (See gdk_gc_set_clip_origin()).
743 gdk_gc_set_clip_rectangle (GdkGC *gc,
744 GdkRectangle *rectangle)
747 gboolean had_region = FALSE;
749 g_return_if_fail (GDK_IS_GC (gc));
751 x11_gc = GDK_GC_X11 (gc);
753 if (x11_gc->clip_region)
756 gdk_region_destroy (x11_gc->clip_region);
760 x11_gc->clip_region = gdk_region_rectangle (rectangle);
762 x11_gc->clip_region = NULL;
764 /* Unset immediately, to make sure Xlib doesn't keep the
765 * XID of an old clip mask cached
767 if ((had_region && !rectangle) || x11_gc->have_clip_mask)
769 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
770 x11_gc->have_clip_mask = FALSE;
773 gc->clip_x_origin = 0;
774 gc->clip_y_origin = 0;
776 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
780 * gdk_gc_set_clip_region:
782 * @region: the #GdkRegion.
784 * Sets the clip mask for a graphics context from a region structure.
785 * The clip mask is interpreted relative to the clip origin. (See
786 * gdk_gc_set_clip_origin()).
789 gdk_gc_set_clip_region (GdkGC *gc,
793 gboolean had_region = FALSE;
795 g_return_if_fail (GDK_IS_GC (gc));
797 x11_gc = GDK_GC_X11 (gc);
799 if (x11_gc->clip_region)
802 gdk_region_destroy (x11_gc->clip_region);
806 x11_gc->clip_region = gdk_region_copy (region);
808 x11_gc->clip_region = NULL;
810 /* Unset immediately, to make sure Xlib doesn't keep the
811 * XID of an old clip mask cached
813 if ((had_region && !region) || x11_gc->have_clip_mask)
815 XSetClipMask (GDK_GC_XDISPLAY (gc), GDK_GC_XGC (gc), None);
816 x11_gc->have_clip_mask = FALSE;
819 gc->clip_x_origin = 0;
820 gc->clip_y_origin = 0;
822 x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
828 * @dst_gc: the destination graphics context.
829 * @src_gc: the source graphics context.
831 * Copy the set of values from one graphics context
832 * onto another graphics context.
835 gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc)
837 GdkGCX11 *x11_src_gc;
838 GdkGCX11 *x11_dst_gc;
840 g_return_if_fail (GDK_IS_GC_X11 (dst_gc));
841 g_return_if_fail (GDK_IS_GC_X11 (src_gc));
843 x11_dst_gc = GDK_GC_X11 (dst_gc);
844 x11_src_gc = GDK_GC_X11 (src_gc);
846 XCopyGC (GDK_GC_XDISPLAY (src_gc), GDK_GC_XGC (src_gc), ~((~1) << GCLastBit),
847 GDK_GC_XGC (dst_gc));
849 dst_gc->clip_x_origin = src_gc->clip_x_origin;
850 dst_gc->clip_y_origin = src_gc->clip_y_origin;
851 dst_gc->ts_x_origin = src_gc->ts_x_origin;
852 dst_gc->ts_y_origin = src_gc->ts_y_origin;
854 if (src_gc->colormap)
855 g_object_ref (src_gc->colormap);
857 if (dst_gc->colormap)
858 g_object_unref (dst_gc->colormap);
860 dst_gc->colormap = src_gc->colormap;
862 if (x11_dst_gc->clip_region)
863 gdk_region_destroy (x11_dst_gc->clip_region);
865 if (x11_src_gc->clip_region)
866 x11_dst_gc->clip_region = gdk_region_copy (x11_src_gc->clip_region);
868 x11_dst_gc->clip_region = NULL;
870 x11_dst_gc->dirty_mask = x11_src_gc->dirty_mask;
871 x11_dst_gc->fg_pixel = x11_src_gc->fg_pixel;
872 x11_dst_gc->fill = x11_src_gc->fill;
874 if (x11_dst_gc->stipple)
875 g_object_unref (x11_dst_gc->stipple);
876 x11_dst_gc->stipple = x11_src_gc->stipple;
877 if (x11_dst_gc->stipple)
878 g_object_ref (x11_dst_gc->stipple);
880 if (x11_dst_gc->tile)
881 g_object_unref (x11_dst_gc->tile);
882 x11_dst_gc->tile = x11_src_gc->tile;
883 if (x11_dst_gc->tile)
884 g_object_ref (x11_dst_gc->tile);
886 clear_fg_picture (dst_gc);
893 * Gets the #GdkScreen for which @gc was created
895 * Returns: the #GdkScreen for @gc.
900 gdk_gc_get_screen (GdkGC *gc)
902 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
904 return GDK_GC_X11 (gc)->screen;
908 * gdk_x11_gc_get_xdisplay:
911 * Returns the display of a #GdkGC.
913 * Return value: an Xlib <type>Display*</type>.
916 gdk_x11_gc_get_xdisplay (GdkGC *gc)
918 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
920 return GDK_SCREEN_XDISPLAY (gdk_gc_get_screen (gc));
924 * gdk_x11_gc_get_xgc:
927 * Returns the X GC of a #GdkGC.
929 * Return value: an Xlib <type>GC</type>.
932 gdk_x11_gc_get_xgc (GdkGC *gc)
936 g_return_val_if_fail (GDK_IS_GC_X11 (gc), NULL);
938 gc_x11 = GDK_GC_X11 (gc);
940 if (gc_x11->dirty_mask)
941 _gdk_x11_gc_flush (gc);
946 /* Various bits of the below are roughly cribbed from XFree86
947 * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard
950 static XRenderPictFormat *
951 foreground_format (GdkGC *gc)
953 XRenderPictFormat pf;
955 pf.type = PictTypeDirect;
957 pf.direct.redMask = 0xff;
958 pf.direct.greenMask = 0xff;
959 pf.direct.blueMask = 0xff;
960 pf.direct.alphaMask = 0xff;
962 return XRenderFindFormat (GDK_GC_XDISPLAY (gc),
966 PictFormatGreenMask |
968 PictFormatAlphaMask),
974 make_fg_tile_picture (GdkGC *gc)
976 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
977 GdkVisual *visual = gdk_drawable_get_visual (x11_gc->tile);
978 XRenderPictFormat *format = NULL;
982 format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc),
983 GDK_VISUAL_XVISUAL (visual));
985 else if (x11_gc->depth == 1)
987 format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
993 XRenderPictureAttributes pa;
996 return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
997 GDK_PIXMAP_XID (x11_gc->tile),
1006 make_stipple_picture (GdkGC *gc)
1008 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1009 XRenderPictFormat *format = NULL;
1010 XRenderPictureAttributes pa;
1012 format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc),
1016 return XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1017 GDK_PIXMAP_XID (x11_gc->stipple),
1023 make_color_picture (GdkGC *gc,
1024 XRenderColor *color)
1026 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1027 XRenderPictureAttributes pa;
1028 XRenderPictFormat *pix_format = foreground_format (gc);
1035 pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1036 GDK_SCREEN_XROOTWIN (x11_gc->screen),
1037 1, 1, pix_format->depth);
1039 picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1043 XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1045 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1053 get_bg_color (GdkGC *gc,
1054 XRenderColor *render_color)
1056 GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
1059 cmap = gdk_gc_get_colormap (gc);
1065 gdk_colormap_query_color (cmap, x11_gc->bg_pixel, &color);
1067 render_color->alpha = 0xffff;
1068 render_color->red = color.red;
1069 render_color->green = color.green;
1070 render_color->blue = color.blue;
1072 else /* Not worth warning, just use black */
1074 render_color->alpha = 0xffff;
1075 render_color->red = 0;
1076 render_color->green = 0;
1077 render_color->blue = 0;
1082 * _gdk_x11_gc_get_fg_picture:
1085 * Gets a Xrender Picture object suitable for being the source
1086 * drawable for drawing with the foreground the graphics context.
1088 * Return value: a Picture, owned by the GC; this cannot be
1089 * used over subsequent modification of the GC.
1092 _gdk_x11_gc_get_fg_picture (GdkGC *gc)
1095 gboolean new = FALSE;
1100 g_return_val_if_fail (GDK_IS_GC_X11 (gc), None);
1102 if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc)))
1105 x11_gc = GDK_GC_X11 (gc);
1111 switch (x11_gc->fill)
1118 if (!x11_gc->fg_picture)
1119 x11_gc->fg_picture = make_fg_tile_picture (gc);
1121 if (x11_gc->fg_picture != None)
1122 return x11_gc->fg_picture;
1126 case GDK_OPAQUE_STIPPLED:
1127 if (x11_gc->stipple)
1129 gdk_drawable_get_size (x11_gc->stipple, &width, &height);
1130 fill = x11_gc->fill;
1135 if (x11_gc->fg_picture == None)
1137 XRenderPictureAttributes pa;
1138 XRenderPictFormat *pix_format = foreground_format (gc);
1144 pix = XCreatePixmap (GDK_GC_XDISPLAY (gc),
1145 GDK_SCREEN_XROOTWIN (x11_gc->screen),
1146 width, height, pix_format->depth);
1148 x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc),
1152 XFreePixmap (GDK_GC_XDISPLAY (gc), pix);
1157 _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor);
1159 if (x11_gc->fg_picture_color.alpha != 0xffff ||
1160 x11_gc->fg_picture_color.red != xftcolor.color.red ||
1161 x11_gc->fg_picture_color.green != xftcolor.color.green ||
1162 x11_gc->fg_picture_color.blue != xftcolor.color.blue)
1164 x11_gc->fg_picture_color.alpha = 0xffff;
1165 x11_gc->fg_picture_color.red = xftcolor.color.red;
1166 x11_gc->fg_picture_color.green = xftcolor.color.green;
1167 x11_gc->fg_picture_color.blue = xftcolor.color.blue;
1175 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1176 x11_gc->fg_picture, &x11_gc->fg_picture_color,
1177 0, 0, width, height);
1181 Picture stipple_picture = make_stipple_picture (gc);
1183 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1184 x11_gc->fg_picture, &x11_gc->fg_picture_color,
1185 0, 0, width, height);
1186 XRenderComposite (GDK_GC_XDISPLAY (gc),
1188 stipple_picture, None, x11_gc->fg_picture,
1189 0, 0, 0, 0, 0, 0, width, height);
1191 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1194 case GDK_OPAQUE_STIPPLED:
1196 XRenderColor bg_color;
1198 Picture stipple_picture = make_stipple_picture (gc);
1199 Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color);
1201 get_bg_color (gc, &bg_color);
1203 XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc,
1204 x11_gc->fg_picture, &bg_color,
1205 0, 0, width, height);
1206 XRenderComposite (GDK_GC_XDISPLAY (gc),
1208 fg_picture, stipple_picture, x11_gc->fg_picture,
1209 0, 0, 0, 0, 0, 0, width, height);
1211 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture);
1212 XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture);
1216 g_assert_not_reached (); /* handled above */
1220 return x11_gc->fg_picture;
1224 * _gdk_gc_x11_get_fg_xft_color:
1226 * @xftcolor: location to store the color
1228 * Gets the foreground color of the GC as a XftColor.
1231 _gdk_gc_x11_get_fg_xft_color (GdkGC *gc,
1238 g_return_if_fail (GDK_IS_GC_X11 (gc));
1240 x11_gc = GDK_GC_X11 (gc);
1242 cmap = gdk_gc_get_colormap (gc);
1244 xftcolor->pixel = x11_gc->fg_pixel;
1248 gdk_colormap_query_color (cmap, xftcolor->pixel, &color);
1249 xftcolor->color.alpha = 0xffff;
1250 xftcolor->color.red = color.red;
1251 xftcolor->color.green = color.green;
1252 xftcolor->color.blue = color.blue;
1254 else if (x11_gc->depth == 1)
1256 /* Drawing with Xft on a bitmap is a bit bizzare; it
1257 * takes alpha >= 0x8000 to mean 'set to 1' and
1258 * alpha < 0x8000 to mean 'set to 0'.
1260 if (xftcolor->pixel)
1262 xftcolor->color.red = 0xffff;
1263 xftcolor->color.green = 0xffff;
1264 xftcolor->color.blue = 0xffff;
1265 xftcolor->color.alpha = 0xffff;
1269 xftcolor->color.red = 0;
1270 xftcolor->color.green = 0;
1271 xftcolor->color.blue = 0;
1272 xftcolor->color.alpha = 0;
1277 g_warning ("Using Xft rendering requires the GC argument to have a\n"
1278 "specified colormap. If the GC was created for a drawable\n"
1279 "with a colormap, the colormap will be set on the GC\n"
1280 "automatically. Otherwise, a colormap must be set on it with"
1281 "gdk_gc_set_colormap");
1286 _gdk_windowing_gc_get_foreground (GdkGC *gc,
1292 g_return_if_fail (GDK_IS_GC_X11 (gc));
1294 x11_gc = GDK_GC_X11 (gc);
1296 color->pixel = x11_gc->fg_pixel;
1298 cmap = gdk_gc_get_colormap (gc);
1301 gdk_colormap_query_color (cmap, x11_gc->fg_pixel, color);
1303 g_warning ("No colormap in _gdk_windowing_gc_get_foreground");