]> Pileus Git - ~andy/gtk/blob - gdk/gdkgc.c
API: remove gdk_draw_rectangle()
[~andy/gtk] / gdk / gdkgc.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 /*
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/. 
25  */
26
27 #include "config.h"
28 #include <string.h>
29
30 #include "gdkcairo.h"
31 #include "gdkgc.h"
32 #include "gdkinternals.h"
33 #include "gdkpixmap.h"
34 #include "gdkprivate.h"
35
36
37 static void gdk_gc_finalize   (GObject      *object);
38
39 typedef struct _GdkGCPrivate GdkGCPrivate;
40
41 struct _GdkGCPrivate
42 {
43   cairo_region_t *clip_region;
44
45   guint32 region_tag_applied;
46   int region_tag_offset_x;
47   int region_tag_offset_y;
48
49   cairo_region_t *old_clip_region;
50   GdkPixmap *old_clip_mask;
51
52   GdkBitmap *stipple;
53   GdkPixmap *tile;
54
55   GdkPixmap *clip_mask;
56
57   guint32 fg_pixel;
58   guint32 bg_pixel;
59
60   guint subwindow_mode : 1;
61   guint fill : 2;
62   guint exposures : 2;
63 };
64
65 #define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate))
66
67 G_DEFINE_TYPE (GdkGC, gdk_gc, G_TYPE_OBJECT)
68
69 static void
70 gdk_gc_class_init (GdkGCClass *class)
71 {
72   GObjectClass *object_class = G_OBJECT_CLASS (class);
73   
74   object_class->finalize = gdk_gc_finalize;
75
76   g_type_class_add_private (object_class, sizeof (GdkGCPrivate));
77 }
78
79 static void
80 gdk_gc_init (GdkGC *gc)
81 {
82   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
83
84   priv->fill = GDK_SOLID;
85
86   /* These are the default X11 value, which we match. They are clearly
87    * wrong for TrueColor displays, so apps have to change them.
88    */
89   priv->fg_pixel = 0;
90   priv->bg_pixel = 1;
91 }
92
93 /**
94  * gdk_gc_new:
95  * @drawable: a #GdkDrawable. The created GC must always be used
96  *   with drawables of the same depth as this one.
97  *
98  * Create a new graphics context with default values. 
99  *
100  * Returns: the new graphics context.
101  **/
102 GdkGC*
103 gdk_gc_new (GdkDrawable *drawable)
104 {
105   g_return_val_if_fail (drawable != NULL, NULL);
106
107   return gdk_gc_new_with_values (drawable, NULL, 0);
108 }
109
110 /**
111  * gdk_gc_new_with_values:
112  * @drawable: a #GdkDrawable. The created GC must always be used
113  *   with drawables of the same depth as this one.
114  * @values: a structure containing initial values for the GC.
115  * @values_mask: a bit mask indicating which fields in @values
116  *   are set.
117  * 
118  * Create a new GC with the given initial values.
119  * 
120  * Return value: the new graphics context.
121  **/
122 GdkGC*
123 gdk_gc_new_with_values (GdkDrawable     *drawable,
124                         GdkGCValues     *values,
125                         GdkGCValuesMask  values_mask)
126 {
127   g_return_val_if_fail (drawable != NULL, NULL);
128
129   return GDK_DRAWABLE_GET_CLASS (drawable)->create_gc (drawable,
130                                                        values,
131                                                        values_mask);
132 }
133
134 /**
135  * _gdk_gc_init:
136  * @gc: a #GdkGC
137  * @drawable: a #GdkDrawable.
138  * @values: a structure containing initial values for the GC.
139  * @values_mask: a bit mask indicating which fields in @values
140  *   are set.
141  * 
142  * Does initialization of the generic portions of a #GdkGC
143  * created with the specified values and values_mask. This
144  * should be called out of the implementation of
145  * GdkDrawable.create_gc() immediately after creating the
146  * #GdkGC object.
147  **/
148 void
149 _gdk_gc_init (GdkGC           *gc,
150               GdkDrawable     *drawable,
151               GdkGCValues     *values,
152               GdkGCValuesMask  values_mask)
153 {
154   GdkGCPrivate *priv;
155
156   g_return_if_fail (GDK_IS_GC (gc));
157
158   priv = GDK_GC_GET_PRIVATE (gc);
159
160   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
161     gc->clip_x_origin = values->clip_x_origin;
162   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
163     gc->clip_y_origin = values->clip_y_origin;
164   if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
165     priv->clip_mask = g_object_ref (values->clip_mask);
166   if (values_mask & GDK_GC_TS_X_ORIGIN)
167     gc->ts_x_origin = values->ts_x_origin;
168   if (values_mask & GDK_GC_TS_Y_ORIGIN)
169     gc->ts_y_origin = values->ts_y_origin;
170   if (values_mask & GDK_GC_FILL)
171     priv->fill = values->fill;
172   if (values_mask & GDK_GC_STIPPLE)
173     {
174       priv->stipple = values->stipple;
175       if (priv->stipple)
176         g_object_ref (priv->stipple);
177     }
178   if (values_mask & GDK_GC_TILE)
179     {
180       priv->tile = values->tile;
181       if (priv->tile)
182         g_object_ref (priv->tile);
183     }
184   if (values_mask & GDK_GC_FOREGROUND)
185     priv->fg_pixel = values->foreground.pixel;
186   if (values_mask & GDK_GC_BACKGROUND)
187     priv->bg_pixel = values->background.pixel;
188   if (values_mask & GDK_GC_SUBWINDOW)
189     priv->subwindow_mode = values->subwindow_mode;
190   if (values_mask & GDK_GC_EXPOSURES)
191     priv->exposures = values->graphics_exposures;
192   else
193     priv->exposures = TRUE;
194
195   gc->colormap = gdk_drawable_get_colormap (drawable);
196   if (gc->colormap)
197     g_object_ref (gc->colormap);
198 }
199
200 static void
201 gdk_gc_finalize (GObject *object)
202 {
203   GdkGC *gc = GDK_GC (object);
204   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
205
206   if (priv->clip_region)
207     cairo_region_destroy (priv->clip_region);
208   if (priv->old_clip_region)
209     cairo_region_destroy (priv->old_clip_region);
210   if (priv->clip_mask)
211     g_object_unref (priv->clip_mask);
212   if (priv->old_clip_mask)
213     g_object_unref (priv->old_clip_mask);
214   if (gc->colormap)
215     g_object_unref (gc->colormap);
216   if (priv->tile)
217     g_object_unref (priv->tile);
218   if (priv->stipple)
219     g_object_unref (priv->stipple);
220
221   G_OBJECT_CLASS (gdk_gc_parent_class)->finalize (object);
222 }
223
224 /**
225  * gdk_gc_get_values:
226  * @gc:  a #GdkGC.
227  * @values: the #GdkGCValues structure in which to store the results.
228  * 
229  * Retrieves the current values from a graphics context. Note that 
230  * only the pixel values of the @values->foreground and @values->background
231  * are filled, use gdk_colormap_query_color() to obtain the rgb values
232  * if you need them.
233  **/
234 void
235 gdk_gc_get_values (GdkGC       *gc,
236                    GdkGCValues *values)
237 {
238   g_return_if_fail (GDK_IS_GC (gc));
239   g_return_if_fail (values != NULL);
240
241   GDK_GC_GET_CLASS (gc)->get_values (gc, values);
242 }
243
244 /**
245  * gdk_gc_set_values:
246  * @gc: a #GdkGC
247  * @values: struct containing the new values
248  * @values_mask: mask indicating which struct fields are to be used
249  *
250  * Sets attributes of a graphics context in bulk. For each flag set in
251  * @values_mask, the corresponding field will be read from @values and
252  * set as the new value for @gc. If you're only setting a few values
253  * on @gc, calling individual "setter" functions is likely more
254  * convenient.
255  * 
256  **/
257 void
258 gdk_gc_set_values (GdkGC           *gc,
259                    GdkGCValues     *values,
260                    GdkGCValuesMask  values_mask)
261 {
262   GdkGCPrivate *priv;
263
264   g_return_if_fail (GDK_IS_GC (gc));
265   g_return_if_fail (values != NULL);
266
267   priv = GDK_GC_GET_PRIVATE (gc);
268
269   if ((values_mask & GDK_GC_CLIP_X_ORIGIN) ||
270       (values_mask & GDK_GC_CLIP_Y_ORIGIN) ||
271       (values_mask & GDK_GC_CLIP_MASK) ||
272       (values_mask & GDK_GC_SUBWINDOW))
273     _gdk_gc_remove_drawable_clip (gc);
274   
275   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
276     gc->clip_x_origin = values->clip_x_origin;
277   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
278     gc->clip_y_origin = values->clip_y_origin;
279   if (values_mask & GDK_GC_TS_X_ORIGIN)
280     gc->ts_x_origin = values->ts_x_origin;
281   if (values_mask & GDK_GC_TS_Y_ORIGIN)
282     gc->ts_y_origin = values->ts_y_origin;
283   if (values_mask & GDK_GC_CLIP_MASK)
284     {
285       if (priv->clip_mask)
286         {
287           g_object_unref (priv->clip_mask);
288           priv->clip_mask = NULL;
289         }
290       if (values->clip_mask)
291         priv->clip_mask = g_object_ref (values->clip_mask);
292       
293       if (priv->clip_region)
294         {
295           cairo_region_destroy (priv->clip_region);
296           priv->clip_region = NULL;
297         }
298     }
299   if (values_mask & GDK_GC_FILL)
300     priv->fill = values->fill;
301   if (values_mask & GDK_GC_STIPPLE)
302     {
303       if (priv->stipple != values->stipple)
304         {
305           if (priv->stipple)
306             g_object_unref (priv->stipple);
307           priv->stipple = values->stipple;
308           if (priv->stipple)
309             g_object_ref (priv->stipple);
310         }
311     }
312   if (values_mask & GDK_GC_TILE)
313     {
314       if (priv->tile != values->tile)
315         {
316           if (priv->tile)
317             g_object_unref (priv->tile);
318           priv->tile = values->tile;
319           if (priv->tile)
320             g_object_ref (priv->tile);
321         }
322     }
323   if (values_mask & GDK_GC_FOREGROUND)
324     priv->fg_pixel = values->foreground.pixel;
325   if (values_mask & GDK_GC_BACKGROUND)
326     priv->bg_pixel = values->background.pixel;
327   if (values_mask & GDK_GC_SUBWINDOW)
328     priv->subwindow_mode = values->subwindow_mode;
329   if (values_mask & GDK_GC_EXPOSURES)
330     priv->exposures = values->graphics_exposures;
331   
332   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
333 }
334
335 /**
336  * gdk_gc_set_foreground:
337  * @gc: a #GdkGC.
338  * @color: the new foreground color.
339  * 
340  * Sets the foreground color for a graphics context.
341  * Note that this function uses @color->pixel, use 
342  * gdk_gc_set_rgb_fg_color() to specify the foreground 
343  * color as red, green, blue components.
344  **/
345 void
346 gdk_gc_set_foreground (GdkGC          *gc,
347                        const GdkColor *color)
348 {
349   GdkGCValues values;
350
351   g_return_if_fail (GDK_IS_GC (gc));
352   g_return_if_fail (color != NULL);
353
354   values.foreground = *color;
355   gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND);
356 }
357
358 /**
359  * gdk_gc_set_background:
360  * @gc: a #GdkGC.
361  * @color: the new background color.
362  * 
363  * Sets the background color for a graphics context.
364  * Note that this function uses @color->pixel, use 
365  * gdk_gc_set_rgb_bg_color() to specify the background 
366  * color as red, green, blue components.
367  **/
368 void
369 gdk_gc_set_background (GdkGC          *gc,
370                        const GdkColor *color)
371 {
372   GdkGCValues values;
373
374   g_return_if_fail (GDK_IS_GC (gc));
375   g_return_if_fail (color != NULL);
376
377   values.background = *color;
378   gdk_gc_set_values (gc, &values, GDK_GC_BACKGROUND);
379 }
380
381 /**
382  * gdk_gc_set_function:
383  * @gc: a #GdkGC.
384  * @function: the #GdkFunction to use
385  * 
386  * Determines how the current pixel values and the
387  * pixel values being drawn are combined to produce
388  * the final pixel values.
389  **/
390 void
391 gdk_gc_set_function (GdkGC       *gc,
392                      GdkFunction  function)
393 {
394   GdkGCValues values;
395
396   g_return_if_fail (GDK_IS_GC (gc));
397
398   values.function = function;
399   gdk_gc_set_values (gc, &values, GDK_GC_FUNCTION);
400 }
401
402 /**
403  * gdk_gc_set_fill:
404  * @gc: a #GdkGC.
405  * @fill: the new fill mode.
406  * 
407  * Set the fill mode for a graphics context.
408  **/
409 void
410 gdk_gc_set_fill (GdkGC   *gc,
411                  GdkFill  fill)
412 {
413   GdkGCValues values;
414
415   g_return_if_fail (GDK_IS_GC (gc));
416
417   values.fill = fill;
418   gdk_gc_set_values (gc, &values, GDK_GC_FILL);
419 }
420
421 /**
422  * gdk_gc_set_tile:
423  * @gc:  a #GdkGC.
424  * @tile:  the new tile pixmap.
425  * 
426  * Set a tile pixmap for a graphics context.
427  * This will only be used if the fill mode
428  * is %GDK_TILED.
429  **/
430 void
431 gdk_gc_set_tile (GdkGC     *gc,
432                  GdkPixmap *tile)
433 {
434   GdkGCValues values;
435
436   g_return_if_fail (GDK_IS_GC (gc));
437
438   values.tile = tile;
439   gdk_gc_set_values (gc, &values, GDK_GC_TILE);
440 }
441
442 /**
443  * gdk_gc_set_stipple:
444  * @gc: a #GdkGC.
445  * @stipple: the new stipple bitmap.
446  * 
447  * Set the stipple bitmap for a graphics context. The
448  * stipple will only be used if the fill mode is
449  * %GDK_STIPPLED or %GDK_OPAQUE_STIPPLED.
450  **/
451 void
452 gdk_gc_set_stipple (GdkGC     *gc,
453                     GdkPixmap *stipple)
454 {
455   GdkGCValues values;
456
457   g_return_if_fail (GDK_IS_GC (gc));
458
459   values.stipple = stipple;
460   gdk_gc_set_values (gc, &values, GDK_GC_STIPPLE);
461 }
462
463 /**
464  * gdk_gc_set_ts_origin:
465  * @gc:  a #GdkGC.
466  * @x: the x-coordinate of the origin.
467  * @y: the y-coordinate of the origin.
468  * 
469  * Set the origin when using tiles or stipples with
470  * the GC. The tile or stipple will be aligned such
471  * that the upper left corner of the tile or stipple
472  * will coincide with this point.
473  **/
474 void
475 gdk_gc_set_ts_origin (GdkGC *gc,
476                       gint   x,
477                       gint   y)
478 {
479   GdkGCValues values;
480
481   g_return_if_fail (GDK_IS_GC (gc));
482
483   values.ts_x_origin = x;
484   values.ts_y_origin = y;
485   
486   gdk_gc_set_values (gc, &values,
487                      GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN);
488 }
489
490 /**
491  * gdk_gc_set_clip_origin:
492  * @gc: a #GdkGC.
493  * @x: the x-coordinate of the origin.
494  * @y: the y-coordinate of the origin.
495  * 
496  * Sets the origin of the clip mask. The coordinates are
497  * interpreted relative to the upper-left corner of
498  * the destination drawable of the current operation.
499  **/
500 void
501 gdk_gc_set_clip_origin (GdkGC *gc,
502                         gint   x,
503                         gint   y)
504 {
505   GdkGCValues values;
506
507   g_return_if_fail (GDK_IS_GC (gc));
508
509   values.clip_x_origin = x;
510   values.clip_y_origin = y;
511   
512   gdk_gc_set_values (gc, &values,
513                      GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
514 }
515
516 /**
517  * gdk_gc_set_clip_mask:
518  * @gc: the #GdkGC.
519  * @mask: a bitmap.
520  * 
521  * Sets the clip mask for a graphics context from a bitmap.
522  * The clip mask is interpreted relative to the clip
523  * origin. (See gdk_gc_set_clip_origin()).
524  **/
525 void
526 gdk_gc_set_clip_mask (GdkGC     *gc,
527                       GdkBitmap *mask)
528 {
529   GdkGCValues values;
530   
531   g_return_if_fail (GDK_IS_GC (gc));
532   
533   values.clip_mask = mask;
534   gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
535 }
536
537 /* Takes ownership of passed in region */
538 static void
539 _gdk_gc_set_clip_region_real (GdkGC     *gc,
540                               cairo_region_t *region,
541                               gboolean reset_origin)
542 {
543   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
544
545   if (priv->clip_mask)
546     {
547       g_object_unref (priv->clip_mask);
548       priv->clip_mask = NULL;
549     }
550   
551   if (priv->clip_region)
552     cairo_region_destroy (priv->clip_region);
553
554   priv->clip_region = region;
555
556   _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
557 }
558
559 /* Doesn't copy region, allows not to reset origin */
560 void
561 _gdk_gc_set_clip_region_internal (GdkGC     *gc,
562                                   cairo_region_t *region,
563                                   gboolean reset_origin)
564 {
565   _gdk_gc_remove_drawable_clip (gc);
566   _gdk_gc_set_clip_region_real (gc, region, reset_origin);
567 }
568
569
570 void
571 _gdk_gc_add_drawable_clip (GdkGC     *gc,
572                            guint32    region_tag,
573                            cairo_region_t *region,
574                            int        offset_x,
575                            int        offset_y)
576 {
577   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
578
579   if (priv->region_tag_applied == region_tag &&
580       offset_x == priv->region_tag_offset_x &&
581       offset_y == priv->region_tag_offset_y)
582     return; /* Already appied this drawable region */
583   
584   if (priv->region_tag_applied)
585     _gdk_gc_remove_drawable_clip (gc);
586
587   region = cairo_region_copy (region);
588   if (offset_x != 0 || offset_y != 0)
589     cairo_region_translate (region, offset_x, offset_y);
590
591   if (priv->clip_mask)
592     {
593       int w, h;
594       GdkPixmap *new_mask;
595       GdkGC *tmp_gc;
596       GdkColor black = {0, 0, 0, 0};
597       GdkRectangle r;
598       cairo_region_overlap_t overlap;
599
600       gdk_drawable_get_size (priv->clip_mask, &w, &h);
601
602       r.x = 0;
603       r.y = 0;
604       r.width = w;
605       r.height = h;
606
607       /* Its quite common to expose areas that are completely in or outside
608        * the region, so we try to avoid allocating bitmaps that are just fully
609        * set or completely unset.
610        */
611       overlap = cairo_region_contains_rectangle (region, &r);
612       if (overlap == CAIRO_REGION_OVERLAP_PART)
613         {
614           cairo_t *cr;
615
616            /* The region and the mask intersect, create a new clip mask that
617               includes both areas */
618           priv->old_clip_mask = g_object_ref (priv->clip_mask);
619           new_mask = gdk_pixmap_new (priv->old_clip_mask, w, h, -1);
620
621           cr = gdk_cairo_create (new_mask);
622
623           cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
624           cairo_paint (cr);
625
626           gdk_cairo_set_source_pixmap (cr, priv->old_clip_mask, 0, 0);
627           gdk_cairo_region (cr, region);
628           cairo_fill (cr);
629
630           cairo_destroy (cr);
631
632           cairo_region_destroy (region);
633
634           gdk_gc_set_clip_mask (gc, new_mask);
635
636           g_object_unref (new_mask);
637         }
638       else if (overlap == CAIRO_REGION_OVERLAP_OUT)
639         {
640           /* No intersection, set empty clip region */
641           cairo_region_t *empty = cairo_region_create ();
642
643           cairo_region_destroy (region);
644           priv->old_clip_mask = g_object_ref (priv->clip_mask);
645           priv->clip_region = empty;
646           _gdk_windowing_gc_set_clip_region (gc, empty, FALSE);
647         }
648       else
649         {
650           /* Completely inside region, don't set unnecessary clip */
651           cairo_region_destroy (region);
652           return;
653         }
654     }
655   else
656     {
657       priv->old_clip_region = priv->clip_region;
658       priv->clip_region = region;
659       if (priv->old_clip_region)
660         cairo_region_intersect (region, priv->old_clip_region);
661
662       _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
663     }
664
665   priv->region_tag_applied = region_tag;
666   priv->region_tag_offset_x = offset_x;
667   priv->region_tag_offset_y = offset_y;
668 }
669
670 void
671 _gdk_gc_remove_drawable_clip (GdkGC *gc)
672 {
673   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
674
675   if (priv->region_tag_applied)
676     {
677       priv->region_tag_applied = 0;
678       if (priv->old_clip_mask)
679         {
680           gdk_gc_set_clip_mask (gc, priv->old_clip_mask);
681           g_object_unref (priv->old_clip_mask);
682           priv->old_clip_mask = NULL;
683
684           if (priv->clip_region)
685             {
686               g_object_unref (priv->clip_region);
687               priv->clip_region = NULL;
688             }
689         }
690       else
691         {
692           _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE);
693           priv->old_clip_region = NULL;
694         }
695     }
696 }
697
698 /**
699  * gdk_gc_set_clip_rectangle:
700  * @gc: a #GdkGC.
701  * @rectangle: the rectangle to clip to.
702  * 
703  * Sets the clip mask for a graphics context from a
704  * rectangle. The clip mask is interpreted relative to the clip
705  * origin. (See gdk_gc_set_clip_origin()).
706  **/
707 void
708 gdk_gc_set_clip_rectangle (GdkGC              *gc,
709                            const GdkRectangle *rectangle)
710 {
711   cairo_region_t *region;
712   
713   g_return_if_fail (GDK_IS_GC (gc));
714
715   _gdk_gc_remove_drawable_clip (gc);
716   
717   if (rectangle)
718     region = cairo_region_create_rectangle (rectangle);
719   else
720     region = NULL;
721
722   _gdk_gc_set_clip_region_real (gc, region, TRUE);
723 }
724
725 /**
726  * gdk_gc_set_clip_region:
727  * @gc: a #GdkGC.
728  * @region: the #cairo_region_t. 
729  * 
730  * Sets the clip mask for a graphics context from a region structure.
731  * The clip mask is interpreted relative to the clip origin. (See
732  * gdk_gc_set_clip_origin()).
733  **/
734 void
735 gdk_gc_set_clip_region (GdkGC           *gc,
736                         const cairo_region_t *region)
737 {
738   cairo_region_t *copy;
739
740   g_return_if_fail (GDK_IS_GC (gc));
741
742   _gdk_gc_remove_drawable_clip (gc);
743   
744   if (region)
745     copy = cairo_region_copy (region);
746   else
747     copy = NULL;
748
749   _gdk_gc_set_clip_region_real (gc, copy, TRUE);
750 }
751
752 /**
753  * _gdk_gc_get_clip_region:
754  * @gc: a #GdkGC
755  * 
756  * Gets the current clip region for @gc, if any.
757  * 
758  * Return value: the clip region for the GC, or %NULL.
759  *   (if a clip mask is set, the return will be %NULL)
760  *   This value is owned by the GC and must not be freed.
761  **/
762 cairo_region_t *
763 _gdk_gc_get_clip_region (GdkGC *gc)
764 {
765   g_return_val_if_fail (GDK_IS_GC (gc), NULL);
766
767   return GDK_GC_GET_PRIVATE (gc)->clip_region;
768 }
769
770 /**
771  * _gdk_gc_get_clip_mask:
772  * @gc: a #GdkGC
773  *
774  * Gets the current clip mask for @gc, if any.
775  *
776  * Return value: the clip mask for the GC, or %NULL.
777  *   (if a clip region is set, the return will be %NULL)
778  *   This value is owned by the GC and must not be freed.
779  **/
780 GdkBitmap *
781 _gdk_gc_get_clip_mask (GdkGC *gc)
782 {
783   g_return_val_if_fail (GDK_IS_GC (gc), NULL);
784
785   return GDK_GC_GET_PRIVATE (gc)->clip_mask;
786 }
787
788 /**
789  * _gdk_gc_get_fill:
790  * @gc: a #GdkGC
791  * 
792  * Gets the current file style for the GC
793  * 
794  * Return value: the file style for the GC
795  **/
796 GdkFill
797 _gdk_gc_get_fill (GdkGC *gc)
798 {
799   g_return_val_if_fail (GDK_IS_GC (gc), GDK_SOLID);
800
801   return GDK_GC_GET_PRIVATE (gc)->fill;
802 }
803
804 gboolean
805 _gdk_gc_get_exposures (GdkGC *gc)
806 {
807   g_return_val_if_fail (GDK_IS_GC (gc), FALSE);
808
809   return GDK_GC_GET_PRIVATE (gc)->exposures;
810 }
811
812 /**
813  * _gdk_gc_get_tile:
814  * @gc: a #GdkGC
815  * 
816  * Gets the tile pixmap for @gc, if any
817  * 
818  * Return value: the tile set on the GC, or %NULL. The
819  *   value is owned by the GC and must not be freed.
820  **/
821 GdkPixmap *
822 _gdk_gc_get_tile (GdkGC *gc)
823 {
824   g_return_val_if_fail (GDK_IS_GC (gc), NULL);
825
826   return GDK_GC_GET_PRIVATE (gc)->tile;
827 }
828
829 /**
830  * _gdk_gc_get_stipple:
831  * @gc: a #GdkGC
832  * 
833  * Gets the stipple pixmap for @gc, if any
834  * 
835  * Return value: the stipple set on the GC, or %NULL. The
836  *   value is owned by the GC and must not be freed.
837  **/
838 GdkBitmap *
839 _gdk_gc_get_stipple (GdkGC *gc)
840 {
841   g_return_val_if_fail (GDK_IS_GC (gc), NULL);
842
843   return GDK_GC_GET_PRIVATE (gc)->stipple;
844 }
845
846 /**
847  * _gdk_gc_get_fg_pixel:
848  * @gc: a #GdkGC
849  * 
850  * Gets the foreground pixel value for @gc. If the
851  * foreground pixel has never been set, returns the
852  * default value 0.
853  * 
854  * Return value: the foreground pixel value of the GC
855  **/
856 guint32
857 _gdk_gc_get_fg_pixel (GdkGC *gc)
858 {
859   g_return_val_if_fail (GDK_IS_GC (gc), 0);
860   
861   return GDK_GC_GET_PRIVATE (gc)->fg_pixel;
862 }
863
864 /**
865  * _gdk_gc_get_bg_pixel:
866  * @gc: a #GdkGC
867  * 
868  * Gets the background pixel value for @gc.If the
869  * foreground pixel has never been set, returns the
870  * default value 1.
871  * 
872  * Return value: the foreground pixel value of the GC
873  **/
874 guint32
875 _gdk_gc_get_bg_pixel (GdkGC *gc)
876 {
877   g_return_val_if_fail (GDK_IS_GC (gc), 0);
878   
879   return GDK_GC_GET_PRIVATE (gc)->bg_pixel;
880 }
881
882 /**
883  * gdk_gc_set_subwindow:
884  * @gc: a #GdkGC.
885  * @mode: the subwindow mode.
886  * 
887  * Sets how drawing with this GC on a window will affect child
888  * windows of that window. 
889  **/
890 void
891 gdk_gc_set_subwindow (GdkGC            *gc,
892                       GdkSubwindowMode  mode)
893 {
894   GdkGCValues values;
895   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
896
897   g_return_if_fail (GDK_IS_GC (gc));
898
899   /* This could get called a lot to reset the subwindow mode in
900      the client side clipping, so bail out early */ 
901   if (priv->subwindow_mode == mode)
902     return;
903   
904   values.subwindow_mode = mode;
905   gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
906 }
907
908 GdkSubwindowMode
909 _gdk_gc_get_subwindow (GdkGC *gc)
910 {
911   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
912
913   return priv->subwindow_mode;
914 }
915
916 /**
917  * gdk_gc_set_exposures:
918  * @gc: a #GdkGC.
919  * @exposures: if %TRUE, exposure events will be generated.
920  * 
921  * Sets whether copying non-visible portions of a drawable
922  * using this graphics context generate exposure events
923  * for the corresponding regions of the destination
924  * drawable. (See gdk_draw_drawable()).
925  **/
926 void
927 gdk_gc_set_exposures (GdkGC     *gc,
928                       gboolean   exposures)
929 {
930   GdkGCValues values;
931
932   g_return_if_fail (GDK_IS_GC (gc));
933
934   values.graphics_exposures = exposures;
935   gdk_gc_set_values (gc, &values, GDK_GC_EXPOSURES);
936 }
937
938 /**
939  * gdk_gc_set_line_attributes:
940  * @gc: a #GdkGC.
941  * @line_width: the width of lines.
942  * @line_style: the dash-style for lines.
943  * @cap_style: the manner in which the ends of lines are drawn.
944  * @join_style: the in which lines are joined together.
945  * 
946  * Sets various attributes of how lines are drawn. See
947  * the corresponding members of #GdkGCValues for full
948  * explanations of the arguments.
949  **/
950 void
951 gdk_gc_set_line_attributes (GdkGC       *gc,
952                             gint         line_width,
953                             GdkLineStyle line_style,
954                             GdkCapStyle  cap_style,
955                             GdkJoinStyle join_style)
956 {
957   GdkGCValues values;
958
959   values.line_width = line_width;
960   values.line_style = line_style;
961   values.cap_style = cap_style;
962   values.join_style = join_style;
963
964   gdk_gc_set_values (gc, &values,
965                      GDK_GC_LINE_WIDTH |
966                      GDK_GC_LINE_STYLE |
967                      GDK_GC_CAP_STYLE |
968                      GDK_GC_JOIN_STYLE);
969 }
970
971 /**
972  * gdk_gc_set_dashes:
973  * @gc: a #GdkGC.
974  * @dash_offset: the phase of the dash pattern.
975  * @dash_list: an array of dash lengths.
976  * @n: the number of elements in @dash_list.
977  * 
978  * Sets the way dashed-lines are drawn. Lines will be
979  * drawn with alternating on and off segments of the
980  * lengths specified in @dash_list. The manner in
981  * which the on and off segments are drawn is determined
982  * by the @line_style value of the GC. (This can
983  * be changed with gdk_gc_set_line_attributes().)
984  *
985  * The @dash_offset defines the phase of the pattern, 
986  * specifying how many pixels into the dash-list the pattern 
987  * should actually begin.
988  **/
989 void
990 gdk_gc_set_dashes (GdkGC *gc,
991                    gint   dash_offset,
992                    gint8  dash_list[],
993                    gint   n)
994 {
995   g_return_if_fail (GDK_IS_GC (gc));
996   g_return_if_fail (dash_list != NULL);
997
998   GDK_GC_GET_CLASS (gc)->set_dashes (gc, dash_offset, dash_list, n);
999 }
1000
1001 /**
1002  * gdk_gc_offset:
1003  * @gc: a #GdkGC
1004  * @x_offset: amount by which to offset the GC in the X direction
1005  * @y_offset: amount by which to offset the GC in the Y direction
1006  * 
1007  * Offset attributes such as the clip and tile-stipple origins
1008  * of the GC so that drawing at x - x_offset, y - y_offset with
1009  * the offset GC  has the same effect as drawing at x, y with the original
1010  * GC.
1011  **/
1012 void
1013 gdk_gc_offset (GdkGC *gc,
1014                gint   x_offset,
1015                gint   y_offset)
1016 {
1017   if (x_offset != 0 || y_offset != 0)
1018     {
1019       GdkGCValues values;
1020
1021       values.clip_x_origin = gc->clip_x_origin - x_offset;
1022       values.clip_y_origin = gc->clip_y_origin - y_offset;
1023       values.ts_x_origin = gc->ts_x_origin - x_offset;
1024       values.ts_y_origin = gc->ts_y_origin - y_offset;
1025       
1026       gdk_gc_set_values (gc, &values,
1027                          GDK_GC_CLIP_X_ORIGIN |
1028                          GDK_GC_CLIP_Y_ORIGIN |
1029                          GDK_GC_TS_X_ORIGIN |
1030                          GDK_GC_TS_Y_ORIGIN);
1031     }
1032 }
1033
1034 /**
1035  * gdk_gc_copy:
1036  * @dst_gc: the destination graphics context.
1037  * @src_gc: the source graphics context.
1038  * 
1039  * Copy the set of values from one graphics context
1040  * onto another graphics context.
1041  **/
1042 void
1043 gdk_gc_copy (GdkGC *dst_gc,
1044              GdkGC *src_gc)
1045 {
1046   GdkGCPrivate *dst_priv, *src_priv;
1047   
1048   g_return_if_fail (GDK_IS_GC (dst_gc));
1049   g_return_if_fail (GDK_IS_GC (src_gc));
1050
1051   dst_priv = GDK_GC_GET_PRIVATE (dst_gc);
1052   src_priv = GDK_GC_GET_PRIVATE (src_gc);
1053
1054   _gdk_windowing_gc_copy (dst_gc, src_gc);
1055
1056   dst_gc->clip_x_origin = src_gc->clip_x_origin;
1057   dst_gc->clip_y_origin = src_gc->clip_y_origin;
1058   dst_gc->ts_x_origin = src_gc->ts_x_origin;
1059   dst_gc->ts_y_origin = src_gc->ts_y_origin;
1060
1061   if (src_gc->colormap)
1062     g_object_ref (src_gc->colormap);
1063
1064   if (dst_gc->colormap)
1065     g_object_unref (dst_gc->colormap);
1066
1067   dst_gc->colormap = src_gc->colormap;
1068
1069   if (dst_priv->clip_region)
1070     cairo_region_destroy (dst_priv->clip_region);
1071
1072   if (src_priv->clip_region)
1073     dst_priv->clip_region = cairo_region_copy (src_priv->clip_region);
1074   else
1075     dst_priv->clip_region = NULL;
1076
1077   dst_priv->region_tag_applied = src_priv->region_tag_applied;
1078   
1079   if (dst_priv->old_clip_region)
1080     cairo_region_destroy (dst_priv->old_clip_region);
1081
1082   if (src_priv->old_clip_region)
1083     dst_priv->old_clip_region = cairo_region_copy (src_priv->old_clip_region);
1084   else
1085     dst_priv->old_clip_region = NULL;
1086
1087   if (src_priv->clip_mask)
1088     dst_priv->clip_mask = g_object_ref (src_priv->clip_mask);
1089   else
1090     dst_priv->clip_mask = NULL;
1091   
1092   if (src_priv->old_clip_mask)
1093     dst_priv->old_clip_mask = g_object_ref (src_priv->old_clip_mask);
1094   else
1095     dst_priv->old_clip_mask = NULL;
1096   
1097   dst_priv->fill = src_priv->fill;
1098   
1099   if (dst_priv->stipple)
1100     g_object_unref (dst_priv->stipple);
1101   dst_priv->stipple = src_priv->stipple;
1102   if (dst_priv->stipple)
1103     g_object_ref (dst_priv->stipple);
1104   
1105   if (dst_priv->tile)
1106     g_object_unref (dst_priv->tile);
1107   dst_priv->tile = src_priv->tile;
1108   if (dst_priv->tile)
1109     g_object_ref (dst_priv->tile);
1110
1111   dst_priv->fg_pixel = src_priv->fg_pixel;
1112   dst_priv->bg_pixel = src_priv->bg_pixel;
1113   dst_priv->subwindow_mode = src_priv->subwindow_mode;
1114   dst_priv->exposures = src_priv->exposures;
1115 }
1116
1117 /**
1118  * gdk_gc_set_colormap:
1119  * @gc: a #GdkGC
1120  * @colormap: a #GdkColormap
1121  * 
1122  * Sets the colormap for the GC to the given colormap. The depth
1123  * of the colormap's visual must match the depth of the drawable
1124  * for which the GC was created.
1125  **/
1126 void
1127 gdk_gc_set_colormap (GdkGC       *gc,
1128                      GdkColormap *colormap)
1129 {
1130   g_return_if_fail (GDK_IS_GC (gc));
1131   g_return_if_fail (GDK_IS_COLORMAP (colormap));
1132
1133   if (gc->colormap != colormap)
1134     {
1135       if (gc->colormap)
1136         g_object_unref (gc->colormap);
1137
1138       gc->colormap = colormap;
1139       g_object_ref (gc->colormap);
1140     }
1141     
1142 }
1143
1144 /**
1145  * gdk_gc_get_colormap:
1146  * @gc: a #GdkGC
1147  * 
1148  * Retrieves the colormap for a given GC, if it exists.
1149  * A GC will have a colormap if the drawable for which it was created
1150  * has a colormap, or if a colormap was set explicitely with
1151  * gdk_gc_set_colormap.
1152  * 
1153  * Return value: the colormap of @gc, or %NULL if @gc doesn't have one.
1154  **/
1155 GdkColormap *
1156 gdk_gc_get_colormap (GdkGC *gc)
1157 {
1158   g_return_val_if_fail (GDK_IS_GC (gc), NULL);
1159
1160   return gc->colormap;
1161 }
1162
1163 static GdkColormap *
1164 gdk_gc_get_colormap_warn (GdkGC *gc)
1165 {
1166   GdkColormap *colormap = gdk_gc_get_colormap (gc);
1167   if (!colormap)
1168     {
1169       g_warning ("gdk_gc_set_rgb_fg_color() and gdk_gc_set_rgb_bg_color() can\n"
1170                  "only be used on GC's with a colormap. A GC will have a colormap\n"
1171                  "if it is created for a drawable with a colormap, or if a\n"
1172                  "colormap has been set explicitly with gdk_gc_set_colormap.\n");
1173       return NULL;
1174     }
1175
1176   return colormap;
1177 }
1178
1179 /**
1180  * gdk_gc_set_rgb_fg_color:
1181  * @gc: a #GdkGC
1182  * @color: an unallocated #GdkColor.
1183  * 
1184  * Set the foreground color of a GC using an unallocated color. The
1185  * pixel value for the color will be determined using GdkRGB. If the
1186  * colormap for the GC has not previously been initialized for GdkRGB,
1187  * then for pseudo-color colormaps (colormaps with a small modifiable
1188  * number of colors), a colorcube will be allocated in the colormap.
1189  * 
1190  * Calling this function for a GC without a colormap is an error.
1191  **/
1192 void
1193 gdk_gc_set_rgb_fg_color (GdkGC          *gc,
1194                          const GdkColor *color)
1195 {
1196   GdkColormap *cmap;
1197   GdkColor tmp_color;
1198
1199   g_return_if_fail (GDK_IS_GC (gc));
1200   g_return_if_fail (color != NULL);
1201
1202   cmap = gdk_gc_get_colormap_warn (gc);
1203   if (!cmap)
1204     return;
1205
1206   tmp_color = *color;
1207   if (!gdk_colormap_alloc_color (cmap, &tmp_color, FALSE, TRUE))
1208     return;
1209   gdk_gc_set_foreground (gc, &tmp_color);
1210 }
1211
1212 /**
1213  * gdk_gc_set_rgb_bg_color:
1214  * @gc: a #GdkGC
1215  * @color: an unallocated #GdkColor.
1216  * 
1217  * Set the background color of a GC using an unallocated color. The
1218  * pixel value for the color will be determined using GdkRGB. If the
1219  * colormap for the GC has not previously been initialized for GdkRGB,
1220  * then for pseudo-color colormaps (colormaps with a small modifiable
1221  * number of colors), a colorcube will be allocated in the colormap.
1222  * 
1223  * Calling this function for a GC without a colormap is an error.
1224  **/
1225 void
1226 gdk_gc_set_rgb_bg_color (GdkGC          *gc,
1227                          const GdkColor *color)
1228 {
1229   GdkColormap *cmap;
1230   GdkColor tmp_color;
1231
1232   g_return_if_fail (GDK_IS_GC (gc));
1233   g_return_if_fail (color != NULL);
1234
1235   cmap = gdk_gc_get_colormap_warn (gc);
1236   if (!cmap)
1237     return;
1238
1239   tmp_color = *color;
1240   if (!gdk_colormap_alloc_color (cmap, &tmp_color, FALSE, TRUE))
1241     return;
1242   gdk_gc_set_background (gc, &tmp_color);
1243 }
1244
1245 static cairo_surface_t *
1246 make_stipple_tile_surface (cairo_t   *cr,
1247                            GdkBitmap *stipple,
1248                            GdkColor  *foreground,
1249                            GdkColor  *background)
1250 {
1251   cairo_t *tmp_cr;
1252   cairo_surface_t *surface; 
1253   cairo_surface_t *alpha_surface;
1254   gint width, height;
1255
1256   gdk_drawable_get_size (stipple,
1257                          &width, &height);
1258   
1259   alpha_surface = _gdk_drawable_ref_cairo_surface (stipple);
1260   
1261   surface = cairo_surface_create_similar (cairo_get_target (cr),
1262                                           CAIRO_CONTENT_COLOR_ALPHA,
1263                                           width, height);
1264
1265   tmp_cr = cairo_create (surface);
1266   
1267   cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SOURCE);
1268  
1269   if (background)
1270       gdk_cairo_set_source_color (tmp_cr, background);
1271   else
1272       cairo_set_source_rgba (tmp_cr, 0, 0, 0 ,0);
1273
1274   cairo_paint (tmp_cr);
1275
1276   cairo_set_operator (tmp_cr, CAIRO_OPERATOR_OVER);
1277
1278   gdk_cairo_set_source_color (tmp_cr, foreground);
1279   cairo_mask_surface (tmp_cr, alpha_surface, 0, 0);
1280   
1281   cairo_destroy (tmp_cr);
1282   cairo_surface_destroy (alpha_surface);
1283
1284   return surface;
1285 }
1286
1287 static void
1288 gc_get_foreground (GdkGC    *gc,
1289                    GdkColor *color)
1290 {
1291   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
1292   
1293   color->pixel = priv->bg_pixel;
1294
1295   if (gc->colormap)
1296     gdk_colormap_query_color (gc->colormap, priv->fg_pixel, color);
1297   else
1298     g_warning ("No colormap in gc_get_foreground");
1299 }
1300
1301 static void
1302 gc_get_background (GdkGC    *gc,
1303                    GdkColor *color)
1304 {
1305   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
1306   
1307   color->pixel = priv->bg_pixel;
1308
1309   if (gc->colormap)
1310     gdk_colormap_query_color (gc->colormap, priv->bg_pixel, color);
1311   else
1312     g_warning ("No colormap in gc_get_background");
1313 }
1314
1315 /**
1316  * _gdk_gc_update_context:
1317  * @gc: a #GdkGC
1318  * @cr: a #cairo_t
1319  * @override_foreground: a foreground color to use to override the
1320  *   foreground color of the GC
1321  * @override_stipple: a stipple pattern to use to override the
1322  *   stipple from the GC. If this is present and the fill mode
1323  *   of the GC isn't %GDK_STIPPLED or %GDK_OPAQUE_STIPPLED
1324  *   the fill mode will be forced to %GDK_STIPPLED
1325  * @gc_changed: pass %FALSE if the @gc has not changed since the
1326  *     last call to this function
1327  * @target_drawable: The drawable you're drawing in. If passed in
1328  *     this is used for client side window clip emulation.
1329  * 
1330  * Set the attributes of a cairo context to match those of a #GdkGC
1331  * as far as possible. Some aspects of a #GdkGC, such as clip masks
1332  * and functions other than %GDK_COPY are not currently handled.
1333  **/
1334 void
1335 _gdk_gc_update_context (GdkGC          *gc,
1336                         cairo_t        *cr,
1337                         const GdkColor *override_foreground,
1338                         GdkBitmap      *override_stipple,
1339                         gboolean        gc_changed,
1340                         GdkDrawable    *target_drawable)
1341 {
1342   GdkGCPrivate *priv;
1343   GdkFill fill;
1344   GdkColor foreground;
1345   GdkColor background;
1346   cairo_surface_t *tile_surface = NULL;
1347   GdkBitmap *stipple = NULL;
1348
1349   g_return_if_fail (GDK_IS_GC (gc));
1350   g_return_if_fail (cr != NULL);
1351   g_return_if_fail (override_stipple == NULL || GDK_IS_PIXMAP (override_stipple));
1352
1353   priv = GDK_GC_GET_PRIVATE (gc);
1354
1355   _gdk_gc_remove_drawable_clip (gc);
1356
1357   fill = priv->fill;
1358   if (override_stipple && fill != GDK_OPAQUE_STIPPLED)
1359     fill = GDK_STIPPLED;
1360
1361   if (fill != GDK_TILED)
1362     {
1363       if (override_foreground)
1364         foreground = *override_foreground;
1365       else
1366         gc_get_foreground (gc, &foreground);
1367     }
1368
1369   if (fill == GDK_OPAQUE_STIPPLED)
1370     gc_get_background (gc, &background);
1371
1372
1373   switch (fill)
1374     {
1375     case GDK_SOLID:
1376       break;
1377     case GDK_TILED:
1378       if (!priv->tile)
1379         fill = GDK_SOLID;
1380       break;
1381     case GDK_STIPPLED:
1382     case GDK_OPAQUE_STIPPLED:
1383       if (override_stipple)
1384         stipple = override_stipple;
1385       else
1386         stipple = priv->stipple;
1387       
1388       if (!stipple)
1389         fill = GDK_SOLID;
1390       break;
1391     }
1392   
1393   switch (fill)
1394     {
1395     case GDK_SOLID:
1396       gdk_cairo_set_source_color (cr, &foreground);
1397       break;
1398     case GDK_TILED:
1399       tile_surface = _gdk_drawable_ref_cairo_surface (priv->tile);
1400       break;
1401     case GDK_STIPPLED:
1402       tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, NULL);
1403       break;
1404     case GDK_OPAQUE_STIPPLED:
1405       tile_surface = make_stipple_tile_surface (cr, stipple, &foreground, &background);
1406       break;
1407     }
1408
1409   /* Tiles, stipples, and clip regions are all specified in device space,
1410    * not user space. For the clip region, we can simply change the matrix,
1411    * clip, then clip back, but for the source pattern, we need to
1412    * compute the right matrix.
1413    *
1414    * What we want is:
1415    *
1416    *     CTM_inverse * Pattern_matrix = Translate(- ts_x, - ts_y)
1417    *
1418    * (So that ts_x, ts_y in device space is taken to 0,0 in pattern
1419    * space). So, pattern_matrix = CTM * Translate(- ts_x, - tx_y);
1420    */
1421
1422   if (tile_surface)
1423     {
1424       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (tile_surface);
1425       cairo_matrix_t user_to_device;
1426       cairo_matrix_t user_to_pattern;
1427       cairo_matrix_t device_to_pattern;
1428
1429       cairo_get_matrix (cr, &user_to_device);
1430       cairo_matrix_init_translate (&device_to_pattern,
1431                                    - gc->ts_x_origin, - gc->ts_y_origin);
1432       cairo_matrix_multiply (&user_to_pattern,
1433                              &user_to_device, &device_to_pattern);
1434       
1435       cairo_pattern_set_matrix (pattern, &user_to_pattern);
1436       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
1437       cairo_set_source (cr, pattern);
1438       
1439       cairo_surface_destroy (tile_surface);
1440       cairo_pattern_destroy (pattern);
1441     }
1442
1443   if (!gc_changed)
1444     return;
1445
1446   cairo_reset_clip (cr);
1447   /* The reset above resets the window clip rect, so we want to re-set that */
1448   if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
1449     GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
1450
1451   if (priv->clip_region)
1452     {
1453       cairo_save (cr);
1454
1455       cairo_identity_matrix (cr);
1456       cairo_translate (cr, gc->clip_x_origin, gc->clip_y_origin);
1457
1458       cairo_new_path (cr);
1459       gdk_cairo_region (cr, priv->clip_region);
1460
1461       cairo_restore (cr);
1462
1463       cairo_clip (cr);
1464     }
1465
1466 }