]> Pileus Git - ~andy/gtk/blob - gdk/quartz/gdkgc-quartz.c
API: remove gdk_draw_drawable()
[~andy/gtk] / gdk / quartz / gdkgc-quartz.c
1 /* gdkgc-quartz.c
2  *
3  * Copyright (C) 2005 Imendio AB
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include "gdkgc.h"
24 #include "gdkprivate-quartz.h"
25
26 static gpointer parent_class = NULL;
27
28 static void
29 gdk_quartz_gc_get_values (GdkGC       *gc,
30                           GdkGCValues *values)
31 {
32   GdkGCQuartz *private;
33
34   private = GDK_GC_QUARTZ (gc);
35
36   values->foreground.pixel = _gdk_gc_get_fg_pixel (gc);
37   values->background.pixel = _gdk_gc_get_bg_pixel (gc);
38
39   values->function = private->function;
40
41   values->fill = _gdk_gc_get_fill (gc);
42   values->tile = _gdk_gc_get_tile (gc);
43   values->stipple = _gdk_gc_get_stipple (gc);
44   
45   /* The X11 backend always returns a NULL clip_mask. */
46   values->clip_mask = NULL;
47
48   values->ts_x_origin = gc->ts_x_origin;
49   values->ts_y_origin = gc->ts_y_origin;
50   values->clip_x_origin = gc->clip_x_origin;
51   values->clip_y_origin = gc->clip_y_origin;
52
53   values->graphics_exposures = private->graphics_exposures;
54
55   values->line_width = private->line_width;
56   values->line_style = private->line_style;
57   values->cap_style = private->cap_style;
58   values->join_style = private->join_style;
59 }
60
61
62 static void
63 data_provider_release (void *info, const void *data, size_t size)
64 {
65   g_free (info);
66 }
67
68 static CGImageRef
69 create_clip_mask (GdkPixmap *source_pixmap)
70 {
71   int width, height, bytes_per_row, bits_per_pixel;
72   void *data;
73   CGImageRef source;
74   CGImageRef clip_mask;
75   CGContextRef cg_context;
76   CGDataProviderRef data_provider;
77
78   /* We need to flip the clip mask here, because this cannot be done during
79    * the drawing process when this mask will be used to do clipping.  We
80    * quickly create a new CGImage, set up a CGContext, draw the source
81    * image while flipping, and done.  If this appears too slow in the
82    * future, we would look into doing this by hand on the actual raw
83    * data.
84    */
85   source = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (source_pixmap)->impl)->image;
86
87   width = CGImageGetWidth (source);
88   height = CGImageGetHeight (source);
89   bytes_per_row = CGImageGetBytesPerRow (source);
90   bits_per_pixel = CGImageGetBitsPerPixel (source);
91
92   data = g_malloc (height * bytes_per_row);
93   data_provider = CGDataProviderCreateWithData (data, data,
94                                                 height * bytes_per_row,
95                                                 data_provider_release);
96
97   clip_mask = CGImageCreate (width, height, 8,
98                              bits_per_pixel,
99                              bytes_per_row,
100                              CGImageGetColorSpace (source),
101                              CGImageGetAlphaInfo (source),
102                              data_provider, NULL, FALSE,
103                              kCGRenderingIntentDefault);
104   CGDataProviderRelease (data_provider);
105
106   cg_context = CGBitmapContextCreate (data,
107                                       width, height,
108                                       CGImageGetBitsPerComponent (source),
109                                       bytes_per_row,
110                                       CGImageGetColorSpace (source),
111                                       CGImageGetBitmapInfo (source));
112
113   CGContextTranslateCTM (cg_context, 0, height);
114   CGContextScaleCTM (cg_context, 1.0, -1.0);
115
116   CGContextDrawImage (cg_context,
117                       CGRectMake (0, 0, width, height), source);
118
119   CGContextRelease (cg_context);
120
121   return clip_mask;
122 }
123
124 static void
125 gdk_quartz_gc_set_values (GdkGC           *gc,
126                           GdkGCValues     *values,
127                           GdkGCValuesMask  mask)
128 {
129   GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
130
131   if (mask & GDK_GC_FUNCTION)
132     private->function = values->function;
133
134   if (mask & GDK_GC_SUBWINDOW)
135     private->subwindow_mode = values->subwindow_mode;
136
137   if (mask & GDK_GC_EXPOSURES)
138     private->graphics_exposures = values->graphics_exposures;
139
140   if (mask & GDK_GC_CLIP_MASK)
141     {
142       private->have_clip_region = FALSE;
143       private->have_clip_mask = values->clip_mask != NULL;
144       if (private->clip_mask)
145         CGImageRelease (private->clip_mask);
146
147       if (values->clip_mask)
148         private->clip_mask = create_clip_mask (values->clip_mask);
149       else
150         private->clip_mask = NULL;
151     }
152
153   if (mask & GDK_GC_LINE_WIDTH)
154     private->line_width = values->line_width;
155
156   if (mask & GDK_GC_LINE_STYLE)
157     private->line_style = values->line_style;
158
159   if (mask & GDK_GC_CAP_STYLE)
160     private->cap_style = values->cap_style;
161
162   if (mask & GDK_GC_JOIN_STYLE)
163     private->join_style = values->join_style;
164 }
165
166 static void
167 gdk_quartz_gc_set_dashes (GdkGC *gc,
168                           gint   dash_offset,
169                           gint8  dash_list[],
170                           gint   n)
171 {
172   GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
173   gint i;
174
175   private->dash_count = n;
176   g_free (private->dash_lengths);
177   private->dash_lengths = g_new (CGFloat, n);
178   for (i = 0; i < n; i++)
179     private->dash_lengths[i] = (CGFloat) dash_list[i];
180   private->dash_phase = (CGFloat) dash_offset;
181 }
182
183 static void
184 gdk_gc_quartz_finalize (GObject *object)
185 {
186   GdkGCQuartz *private = GDK_GC_QUARTZ (object);
187
188   if (private->clip_mask)
189     CGImageRelease (private->clip_mask);
190
191   G_OBJECT_CLASS (parent_class)->finalize (object);
192 }
193
194 static void
195 gdk_gc_quartz_class_init (GdkGCQuartzClass *klass)
196 {
197   GObjectClass *object_class = G_OBJECT_CLASS (klass);
198   GdkGCClass *gc_class = GDK_GC_CLASS (klass);
199   
200   parent_class = g_type_class_peek_parent (klass);
201
202   object_class->finalize = gdk_gc_quartz_finalize;
203
204   gc_class->get_values = gdk_quartz_gc_get_values;
205   gc_class->set_values = gdk_quartz_gc_set_values;
206   gc_class->set_dashes = gdk_quartz_gc_set_dashes;
207 }
208
209 static void
210 gdk_gc_quartz_init (GdkGCQuartz *gc_quartz)
211 {
212   gc_quartz->function = GDK_COPY;
213   gc_quartz->subwindow_mode = GDK_CLIP_BY_CHILDREN;
214   gc_quartz->graphics_exposures = TRUE;
215   gc_quartz->line_width = 0;
216   gc_quartz->line_style = GDK_LINE_SOLID;
217   gc_quartz->cap_style = GDK_CAP_BUTT;
218   gc_quartz->join_style = GDK_JOIN_MITER;
219 }
220
221 GType
222 _gdk_gc_quartz_get_type (void)
223 {
224   static GType object_type = 0;
225
226   if (!object_type)
227     {
228       const GTypeInfo object_info =
229       {
230         sizeof (GdkGCQuartzClass),
231         (GBaseInitFunc) NULL,
232         (GBaseFinalizeFunc) NULL,
233         (GClassInitFunc) gdk_gc_quartz_class_init,
234         NULL,           /* class_finalize */
235         NULL,           /* class_data */
236         sizeof (GdkGCQuartz),
237         0,              /* n_preallocs */
238         (GInstanceInitFunc) gdk_gc_quartz_init,
239       };
240       
241       object_type = g_type_register_static (GDK_TYPE_GC,
242                                             "GdkGCQuartz",
243                                             &object_info, 0);
244     }
245   
246   return object_type;
247 }
248
249 GdkGC *
250 _gdk_quartz_gc_new (GdkDrawable      *drawable,
251                     GdkGCValues      *values,
252                     GdkGCValuesMask   values_mask)
253 {
254   GdkGC *gc;
255
256   gc = g_object_new (GDK_TYPE_GC_QUARTZ, NULL);
257
258   _gdk_gc_init (gc, drawable, values, values_mask);
259
260   gdk_quartz_gc_set_values (gc, values, values_mask);
261
262   return gc;
263 }
264
265 void
266 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
267                                    const cairo_region_t *region,
268                                    gboolean         reset_origin)
269 {
270   GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
271
272   if ((private->have_clip_region && ! region) || private->have_clip_mask)
273     {
274       if (private->clip_mask)
275         {
276           CGImageRelease (private->clip_mask);
277           private->clip_mask = NULL;
278         }
279       private->have_clip_mask = FALSE;
280     }
281
282   private->have_clip_region = region != NULL;
283
284   if (reset_origin)
285     {
286       gc->clip_x_origin = 0;
287       gc->clip_y_origin = 0;
288     }
289 }
290
291 void
292 _gdk_windowing_gc_copy (GdkGC *dst_gc,
293                         GdkGC *src_gc)
294 {
295   GdkGCQuartz *dst_quartz_gc = GDK_GC_QUARTZ (dst_gc);
296   GdkGCQuartz *src_quartz_gc = GDK_GC_QUARTZ (src_gc);
297
298   dst_quartz_gc->function = src_quartz_gc->function;
299   dst_quartz_gc->subwindow_mode = src_quartz_gc->subwindow_mode;
300   dst_quartz_gc->graphics_exposures = src_quartz_gc->graphics_exposures;
301
302   dst_quartz_gc->have_clip_region = src_quartz_gc->have_clip_region;
303   dst_quartz_gc->have_clip_mask = src_quartz_gc->have_clip_mask;
304
305   if (dst_quartz_gc->clip_mask)
306     {
307       CGImageRelease (dst_quartz_gc->clip_mask);
308       dst_quartz_gc->clip_mask = NULL;
309     }
310   
311   if (src_quartz_gc->clip_mask)
312     dst_quartz_gc->clip_mask =
313       CGImageCreateCopy (GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src_quartz_gc->clip_mask)->impl)->image);
314
315   dst_quartz_gc->line_width = src_quartz_gc->line_width;
316   dst_quartz_gc->line_style = src_quartz_gc->line_style;
317   dst_quartz_gc->cap_style = src_quartz_gc->cap_style;
318   dst_quartz_gc->join_style = src_quartz_gc->join_style;
319
320   g_free (dst_quartz_gc->dash_lengths);
321   dst_quartz_gc->dash_lengths = g_memdup (src_quartz_gc->dash_lengths,
322                                           sizeof (CGFloat) * src_quartz_gc->dash_count);
323   dst_quartz_gc->dash_count = src_quartz_gc->dash_count;
324   dst_quartz_gc->dash_phase = src_quartz_gc->dash_phase;
325 }
326
327 GdkScreen *  
328 gdk_gc_get_screen (GdkGC *gc)
329 {
330   return _gdk_screen;
331 }
332
333 struct PatternCallbackInfo
334 {
335   GdkGCQuartz *private_gc;
336   GdkDrawable *drawable;
337 };
338
339 static void
340 pattern_callback_info_release (void *info)
341 {
342   g_free (info);
343 }
344
345 static void
346 gdk_quartz_draw_tiled_pattern (void         *info,
347                                CGContextRef  context)
348 {
349   struct PatternCallbackInfo *pinfo = info;
350   GdkGC       *gc = GDK_GC (pinfo->private_gc);
351   CGImageRef   pattern_image;
352   size_t       width, height;
353
354   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
355
356   width = CGImageGetWidth (pattern_image);
357   height = CGImageGetHeight (pattern_image);
358
359   CGContextDrawImage (context, 
360                       CGRectMake (0, 0, width, height),
361                       pattern_image);
362 }
363
364 static void
365 gdk_quartz_draw_stippled_pattern (void         *info,
366                                   CGContextRef  context)
367 {
368   struct PatternCallbackInfo *pinfo = info;
369   GdkGC      *gc = GDK_GC (pinfo->private_gc);
370   CGImageRef  pattern_image;
371   CGRect      rect;
372   CGColorRef  color;
373
374   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
375   rect = CGRectMake (0, 0,
376                      CGImageGetWidth (pattern_image),
377                      CGImageGetHeight (pattern_image));
378
379   CGContextClipToMask (context, rect, pattern_image);
380   color = _gdk_quartz_colormap_get_cgcolor_from_pixel (pinfo->drawable,
381                                                        _gdk_gc_get_fg_pixel (gc));
382   CGContextSetFillColorWithColor (context, color);
383   CGColorRelease (color);
384
385   CGContextFillRect (context, rect);
386 }
387
388 static void
389 gdk_quartz_draw_opaque_stippled_pattern (void         *info,
390                                          CGContextRef  context)
391 {
392   struct PatternCallbackInfo *pinfo = info;
393   GdkGC      *gc = GDK_GC (pinfo->private_gc);
394   CGImageRef  pattern_image;
395   CGRect      rect;
396   CGColorRef  color;
397
398   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
399   rect = CGRectMake (0, 0,
400                      CGImageGetWidth (pattern_image),
401                      CGImageGetHeight (pattern_image));
402
403   color = _gdk_quartz_colormap_get_cgcolor_from_pixel (pinfo->drawable,
404                                                        _gdk_gc_get_bg_pixel (gc));
405   CGContextSetFillColorWithColor (context, color);
406   CGColorRelease (color);
407
408   CGContextFillRect (context, rect);
409
410   CGContextClipToMask (context, rect, pattern_image);
411   color = _gdk_quartz_colormap_get_cgcolor_from_pixel (info,
412                                                        _gdk_gc_get_fg_pixel (gc));
413   CGContextSetFillColorWithColor (context, color);
414   CGColorRelease (color);
415
416   CGContextFillRect (context, rect);
417 }
418
419 void
420 _gdk_quartz_gc_update_cg_context (GdkGC                      *gc,
421                                   GdkDrawable                *drawable,
422                                   CGContextRef                context,
423                                   GdkQuartzContextValuesMask  mask)
424 {
425   GdkGCQuartz *private;
426   guint32      fg_pixel;
427   guint32      bg_pixel;
428
429   g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
430
431   if (!gc)
432     return;
433
434   private = GDK_GC_QUARTZ (gc);
435
436   if (private->have_clip_region)
437     {
438       CGRect rect;
439       CGRect *cg_rects;
440       cairo_region_t *region;
441       gint n_rects, i;
442
443       region = _gdk_gc_get_clip_region (gc);
444       n_rects = cairo_region_num_rectangles (region);
445
446       if (n_rects == 1)
447         cg_rects = &rect;
448       else
449         cg_rects = g_new (CGRect, n_rects);
450
451       for (i = 0; i < n_rects; i++)
452         {
453           cairo_rectangle_int_t cairo_rect;
454           cairo_region_get_rectangle (region, i, &cairo_rect);
455           cg_rects[i].origin.x = cairo_rect.x + gc->clip_x_origin;
456           cg_rects[i].origin.y = cairo_rect.y + gc->clip_y_origin;
457           cg_rects[i].size.width = cairo_rect.width;
458           cg_rects[i].size.height = cairo_rect.height;
459         }
460
461       CGContextClipToRects (context, cg_rects, n_rects);
462
463       if (cg_rects != &rect)
464         g_free (cg_rects);
465     }
466   else if (private->have_clip_mask && private->clip_mask)
467     {
468       /* Note: This is 10.4 only. For lower versions, we need to transform the
469        * mask into a region.
470        */
471       CGContextClipToMask (context,
472                            CGRectMake (gc->clip_x_origin, gc->clip_y_origin,
473                                        CGImageGetWidth (private->clip_mask),
474                                        CGImageGetHeight (private->clip_mask)),
475                            private->clip_mask);
476     }
477
478   fg_pixel = _gdk_gc_get_fg_pixel (gc);
479   bg_pixel = _gdk_gc_get_bg_pixel (gc);
480
481   {
482     CGBlendMode blend_mode = kCGBlendModeNormal;
483
484     switch (private->function)
485       {
486       case GDK_COPY:
487         blend_mode = kCGBlendModeNormal;
488         break;
489
490       case GDK_INVERT:
491       case GDK_XOR:
492         blend_mode = kCGBlendModeExclusion;
493         fg_pixel = 0xffffffff;
494         bg_pixel = 0xffffffff;
495         break;
496
497       case GDK_CLEAR:
498       case GDK_AND:
499       case GDK_AND_REVERSE:
500       case GDK_AND_INVERT:
501       case GDK_NOOP:
502       case GDK_OR:
503       case GDK_EQUIV:
504       case GDK_OR_REVERSE:
505       case GDK_COPY_INVERT:
506       case GDK_OR_INVERT:
507       case GDK_NAND:
508       case GDK_NOR:
509       case GDK_SET:
510         blend_mode = kCGBlendModeNormal; /* FIXME */
511         break;
512       }
513
514     CGContextSetBlendMode (context, blend_mode);
515   }
516
517   /* FIXME: implement subwindow mode */
518
519   /* FIXME: implement graphics exposures */
520
521   if (mask & GDK_QUARTZ_CONTEXT_STROKE)
522     {
523       CGLineCap  line_cap  = kCGLineCapButt;
524       CGLineJoin line_join = kCGLineJoinMiter;
525       CGColorRef color;
526
527       color = _gdk_quartz_colormap_get_cgcolor_from_pixel (drawable,
528                                                            fg_pixel);
529       CGContextSetStrokeColorWithColor (context, color);
530       CGColorRelease (color);
531
532       CGContextSetLineWidth (context, MAX (G_MINFLOAT, private->line_width));
533
534       switch (private->line_style)
535         {
536         case GDK_LINE_SOLID:
537           CGContextSetLineDash (context, 0.0, NULL, 0);
538           break;
539
540         case GDK_LINE_DOUBLE_DASH:
541           /* FIXME: Implement; for now, fall back to GDK_LINE_ON_OFF_DASH */
542
543         case GDK_LINE_ON_OFF_DASH:
544           CGContextSetLineDash (context, private->dash_phase,
545                                 private->dash_lengths, private->dash_count);
546           break;
547         }
548
549       switch (private->cap_style)
550         {
551         case GDK_CAP_NOT_LAST:
552           /* FIXME: Implement; for now, fall back to GDK_CAP_BUTT */
553         case GDK_CAP_BUTT:
554           line_cap = kCGLineCapButt;
555           break;
556         case GDK_CAP_ROUND:
557           line_cap = kCGLineCapRound;
558           break;
559         case GDK_CAP_PROJECTING:
560           line_cap = kCGLineCapSquare;
561           break;
562         }
563
564       CGContextSetLineCap (context, line_cap);
565
566       switch (private->join_style)
567         {
568         case GDK_JOIN_MITER:
569           line_join = kCGLineJoinMiter;
570           break;
571         case GDK_JOIN_ROUND:
572           line_join = kCGLineJoinRound;
573           break;
574         case GDK_JOIN_BEVEL:
575           line_join = kCGLineJoinBevel;
576           break;
577         }
578
579       CGContextSetLineJoin (context, line_join);
580     }
581
582   if (mask & GDK_QUARTZ_CONTEXT_FILL)
583     {
584       GdkFill         fill = _gdk_gc_get_fill (gc);
585       CGColorSpaceRef baseSpace;
586       CGColorSpaceRef patternSpace;
587       CGFloat         alpha     = 1.0;
588
589       if (fill == GDK_SOLID)
590         {
591           CGColorRef color;
592
593           color = _gdk_quartz_colormap_get_cgcolor_from_pixel (drawable,
594                                                                fg_pixel);
595           CGContextSetFillColorWithColor (context, color);
596           CGColorRelease (color);
597         }
598       else
599         {
600           if (!private->ts_pattern)
601             {
602               CGImageRef pattern_image = NULL;
603               gfloat     width, height;
604               gboolean   is_colored = FALSE;
605               CGPatternCallbacks callbacks =  { 0, NULL, NULL };
606               struct PatternCallbackInfo *info;
607               CGPoint    phase;
608
609               info = g_new (struct PatternCallbackInfo, 1);
610               /* Won't ref to avoid circular dependencies */
611               info->drawable = drawable;
612               info->private_gc = private;
613
614               callbacks.releaseInfo = pattern_callback_info_release;
615
616               switch (fill)
617                 {
618                 case GDK_TILED:
619                   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_tile (gc))->impl)->image;
620                   is_colored = TRUE;
621                   callbacks.drawPattern = gdk_quartz_draw_tiled_pattern;
622                   break;
623                 case GDK_STIPPLED:
624                   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
625                   is_colored = FALSE;
626                   callbacks.drawPattern = gdk_quartz_draw_stippled_pattern;
627                   break;
628                 case GDK_OPAQUE_STIPPLED:
629                   pattern_image = GDK_PIXMAP_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (_gdk_gc_get_stipple (gc))->impl)->image;
630                   is_colored = TRUE;
631                   callbacks.drawPattern = gdk_quartz_draw_opaque_stippled_pattern;
632                   break;
633                 default:
634                   break;
635                 }
636
637               width  = CGImageGetWidth (pattern_image);
638               height = CGImageGetHeight (pattern_image);
639
640               phase = CGPointApplyAffineTransform (CGPointMake (gc->ts_x_origin, gc->ts_y_origin), CGContextGetCTM (context));
641               CGContextSetPatternPhase (context, CGSizeMake (phase.x, phase.y));
642
643               private->ts_pattern = CGPatternCreate (info,
644                                                      CGRectMake (0, 0, width, height),
645                                                      CGAffineTransformIdentity,
646                                                      width, height,
647                                                      kCGPatternTilingConstantSpacing,
648                                                      is_colored,
649                                                      &callbacks);
650             }
651
652           baseSpace = (fill == GDK_STIPPLED) ? CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB) : NULL;
653           patternSpace = CGColorSpaceCreatePattern (baseSpace);
654
655           CGContextSetFillColorSpace (context, patternSpace);
656           CGColorSpaceRelease (patternSpace);
657           CGColorSpaceRelease (baseSpace);
658
659           if (fill == GDK_STIPPLED)
660             {
661               CGColorRef color;
662               const CGFloat *components;
663
664               color = _gdk_quartz_colormap_get_cgcolor_from_pixel (drawable,
665                                                                    fg_pixel);
666               components = CGColorGetComponents (color);
667
668               CGContextSetFillPattern (context, private->ts_pattern,
669                                        components);
670               CGColorRelease (color);
671             }
672           else
673             CGContextSetFillPattern (context, private->ts_pattern, &alpha);
674        }
675     }
676
677   if (mask & GDK_QUARTZ_CONTEXT_TEXT)
678     {
679       /* FIXME: implement text */
680     }
681
682   if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
683       private->is_window = TRUE;
684   else
685       private->is_window = FALSE;
686 }