]> Pileus Git - ~andy/gtk/blob - gdk/gdkdraw.c
new function, turns off decorations for a window.
[~andy/gtk] / gdk / gdkdraw.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 "gdkdrawable.h"
28 #include "gdkinternals.h"
29 #include "gdkwindow.h"
30
31 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
32                                                               gint         x,
33                                                               gint         y,
34                                                               gint         width,
35                                                               gint         height,
36                                                               gint        *composite_x_offset,
37                                                               gint        *composite_y_offset);
38 static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable *drawable);
39
40 static void gdk_drawable_class_init (GdkDrawableClass *klass);
41
42 GType
43 gdk_drawable_get_type (void)
44 {
45   static GType object_type = 0;
46
47   if (!object_type)
48     {
49       static const GTypeInfo object_info =
50       {
51         sizeof (GdkDrawableClass),
52         (GBaseInitFunc) NULL,
53         (GBaseFinalizeFunc) NULL,
54         (GClassInitFunc) gdk_drawable_class_init,
55         NULL,           /* class_finalize */
56         NULL,           /* class_data */
57         sizeof (GdkDrawable),
58         0,              /* n_preallocs */
59         (GInstanceInitFunc) NULL,
60       };
61       
62       object_type = g_type_register_static (G_TYPE_OBJECT,
63                                             "GdkDrawable",
64                                             &object_info, 0);
65     }  
66
67   return object_type;
68 }
69
70 static void
71 gdk_drawable_class_init (GdkDrawableClass *klass)
72 {
73   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
74   /* Default implementation for clip and visible region is the same */
75   klass->get_clip_region = gdk_drawable_real_get_visible_region;
76   klass->get_visible_region = gdk_drawable_real_get_visible_region;
77 }
78
79 /* Manipulation of drawables
80  */
81
82 /**
83  * gdk_drawable_set_data:
84  * @drawable: a #GdkDrawable
85  * @key: name to store the data under
86  * @data: arbitrary data
87  * @destroy_func: function to free @data, or %NULL
88  *
89  * This function is equivalent to g_object_set_data(),
90  * the #GObject variant should be used instead.
91  * 
92  **/
93 void          
94 gdk_drawable_set_data (GdkDrawable   *drawable,
95                        const gchar   *key,
96                        gpointer       data,
97                        GDestroyNotify destroy_func)
98 {
99   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
100   
101   g_object_set_qdata_full (G_OBJECT (drawable),
102                            g_quark_from_string (key),
103                            data,
104                            destroy_func);
105 }
106
107 /**
108  * gdk_drawable_get_data:
109  * @drawable: a #GdkDrawable
110  * @key: name the data was stored under
111  * 
112  * Equivalent to g_object_get_data(); the #GObject variant should be
113  * used instead.
114  * 
115  * Return value: the data stored at @key
116  **/
117 gpointer
118 gdk_drawable_get_data (GdkDrawable   *drawable,
119                        const gchar   *key)
120 {
121   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
122   
123   return g_object_get_qdata (G_OBJECT (drawable),
124                              g_quark_try_string (key));
125 }
126
127 /**
128  * gdk_drawable_get_size:
129  * @drawable: a #GdkDrawable
130  * @width: location to store drawable's width, or %NULL
131  * @height: location to store drawable's height, or %NULL
132  *
133  * Fills *@width and *@height with the size of @drawable.
134  * @width or @height can be %NULL if you only want the other one.
135  * 
136  **/
137 void
138 gdk_drawable_get_size (GdkDrawable *drawable,
139                        gint        *width,
140                        gint        *height)
141 {
142   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
143
144   GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);  
145 }
146
147 /**
148  * gdk_drawable_get_visual:
149  * @drawable: a #GdkDrawable
150  * 
151  * Gets the #GdkVisual describing the pixel format of @drawable.
152  * 
153  * Return value: a #GdkVisual
154  **/
155 GdkVisual*
156 gdk_drawable_get_visual (GdkDrawable *drawable)
157 {
158   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
159   
160   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
161 }
162
163 /**
164  * gdk_drawable_get_depth:
165  * @drawable: a #GdkDrawable
166  * 
167  * Obtains the bit depth of the drawable, that is, the number of bits
168  * that make up a pixel in the drawable's visual. Examples are 8 bits
169  * per pixel, 24 bits per pixel, etc.
170  * 
171  * Return value: number of bits per pixel
172  **/
173 gint
174 gdk_drawable_get_depth (GdkDrawable *drawable)
175 {
176   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
177
178   return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
179 }
180
181 /**
182  * gdk_drawable_set_colormap:
183  * @drawable: a #GdkDrawable
184  * @colormap: a #GdkColormap
185  *
186  * Sets the colormap associated with @drawable. Normally this will
187  * happen automatically when the drawable is created; you only need to
188  * use this function if the drawable-creating function did not have a
189  * way to determine the colormap, and you then use drawable operations
190  * that require a colormap. The colormap for all drawables and
191  * graphics contexts you intend to use together should match. i.e.
192  * when using a #GdkGC to draw to a drawable, or copying one drawable
193  * to another, the colormaps should match.
194  * 
195  **/
196 void
197 gdk_drawable_set_colormap (GdkDrawable *drawable,
198                            GdkColormap *cmap)
199 {
200   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
201
202   GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
203 }
204
205 /**
206  * gdk_drawable_get_colormap:
207  * @drawable: a #GdkDrawable
208  * 
209  * Gets the colormap for @drawable, if one is set; returns
210  * %NULL otherwise.
211  * 
212  * Return value: the colormap, or %NULL
213  **/
214 GdkColormap*
215 gdk_drawable_get_colormap (GdkDrawable *drawable)
216 {
217   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
218
219   return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
220 }
221
222 /**
223  * gdk_drawable_ref:
224  * @drawable: a #GdkDrawable
225  * 
226  * Deprecated equivalent of calling g_object_ref() on @drawable.
227  * (Drawables were not objects in previous versions of GDK.)
228  * 
229  * Return value: the same @drawable passed in
230  **/
231 GdkDrawable*
232 gdk_drawable_ref (GdkDrawable *drawable)
233 {
234   return (GdkDrawable *) g_object_ref (G_OBJECT (drawable));
235 }
236
237 /**
238  * gdk_drawable_unref:
239  * @drawable: a #GdkDrawable
240  * 
241  * Deprecated equivalent of calling g_object_unref() on @drawable.
242  * 
243  **/
244 void
245 gdk_drawable_unref (GdkDrawable *drawable)
246 {
247   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
248
249   g_object_unref (G_OBJECT (drawable));
250 }
251
252 /* Drawing
253  */
254 void
255 gdk_draw_point (GdkDrawable *drawable,
256                 GdkGC       *gc,
257                 gint         x,
258                 gint         y)
259 {
260   GdkPoint point;
261
262   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
263   g_return_if_fail (GDK_IS_GC (gc));
264
265   point.x = x;
266   point.y = y;
267   
268   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1);
269 }
270
271 void
272 gdk_draw_line (GdkDrawable *drawable,
273                GdkGC       *gc,
274                gint         x1,
275                gint         y1,
276                gint         x2,
277                gint         y2)
278 {
279   GdkSegment segment;
280
281   g_return_if_fail (drawable != NULL);
282   g_return_if_fail (gc != NULL);
283   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
284   g_return_if_fail (GDK_IS_GC (gc));
285
286   segment.x1 = x1;
287   segment.y1 = y1;
288   segment.x2 = x2;
289   segment.y2 = y2;
290   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, &segment, 1);
291 }
292
293 void
294 gdk_draw_rectangle (GdkDrawable *drawable,
295                     GdkGC       *gc,
296                     gint         filled,
297                     gint         x,
298                     gint         y,
299                     gint         width,
300                     gint         height)
301 {  
302   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
303   g_return_if_fail (GDK_IS_GC (gc));
304
305   if (width < 0 || height < 0)
306     {
307       gint real_width;
308       gint real_height;
309       
310       gdk_drawable_get_size (drawable, &real_width, &real_height);
311
312       if (width < 0)
313         width = real_width;
314       if (height < 0)
315         height = real_height;
316     }
317
318   GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y,
319                                                      width, height);
320 }
321
322 void
323 gdk_draw_arc (GdkDrawable *drawable,
324               GdkGC       *gc,
325               gint         filled,
326               gint         x,
327               gint         y,
328               gint         width,
329               gint         height,
330               gint         angle1,
331               gint         angle2)
332 {  
333   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
334   g_return_if_fail (GDK_IS_GC (gc));
335
336   if (width < 0 || height < 0)
337     {
338       gint real_width;
339       gint real_height;
340       
341       gdk_drawable_get_size (drawable, &real_width, &real_height);
342
343       if (width < 0)
344         width = real_width;
345       if (height < 0)
346         height = real_height;
347     }
348
349   GDK_DRAWABLE_GET_CLASS (drawable)->draw_arc (drawable, gc, filled,
350                                                x, y, width, height, angle1, angle2);
351 }
352
353 void
354 gdk_draw_polygon (GdkDrawable *drawable,
355                   GdkGC       *gc,
356                   gint         filled,
357                   GdkPoint    *points,
358                   gint         npoints)
359 {
360   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
361   g_return_if_fail (GDK_IS_GC (gc));
362
363   GDK_DRAWABLE_GET_CLASS (drawable)->draw_polygon (drawable, gc, filled,
364                                                    points, npoints);
365 }
366
367 /* gdk_draw_string
368  *
369  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
370  *
371  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
372  */
373 void
374 gdk_draw_string (GdkDrawable *drawable,
375                  GdkFont     *font,
376                  GdkGC       *gc,
377                  gint         x,
378                  gint         y,
379                  const gchar *string)
380 {
381   gdk_draw_text (drawable, font, gc, x, y, string, _gdk_font_strlen (font, string));
382 }
383
384 /* gdk_draw_text
385  *
386  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
387  *
388  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
389  */
390 void
391 gdk_draw_text (GdkDrawable *drawable,
392                GdkFont     *font,
393                GdkGC       *gc,
394                gint         x,
395                gint         y,
396                const gchar *text,
397                gint         text_length)
398 {
399   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
400   g_return_if_fail (font != NULL);
401   g_return_if_fail (GDK_IS_GC (gc));
402   g_return_if_fail (text != NULL);
403
404   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text (drawable, font, gc, x, y, text, text_length);
405 }
406
407 void
408 gdk_draw_text_wc (GdkDrawable    *drawable,
409                   GdkFont        *font,
410                   GdkGC          *gc,
411                   gint            x,
412                   gint            y,
413                   const GdkWChar *text,
414                   gint            text_length)
415 {
416   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
417   g_return_if_fail (font != NULL);
418   g_return_if_fail (GDK_IS_GC (gc));
419   g_return_if_fail (text != NULL);
420
421   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text_wc (drawable, font, gc, x, y, text, text_length);
422 }
423
424 void
425 gdk_draw_drawable (GdkDrawable *drawable,
426                    GdkGC       *gc,
427                    GdkDrawable *src,
428                    gint         xsrc,
429                    gint         ysrc,
430                    gint         xdest,
431                    gint         ydest,
432                    gint         width,
433                    gint         height)
434 {
435   GdkDrawable *composite;
436   gint composite_x_offset = 0;
437   gint composite_y_offset = 0;
438
439   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
440   g_return_if_fail (src != NULL);
441   g_return_if_fail (GDK_IS_GC (gc));
442
443   if (width < 0 || height < 0)
444     {
445       gint real_width;
446       gint real_height;
447       
448       gdk_drawable_get_size (src, &real_width, &real_height);
449
450       if (width < 0)
451         width = real_width;
452       if (height < 0)
453         height = real_height;
454     }
455
456
457   composite =
458     GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
459                                                           xsrc, ysrc,
460                                                           width, height,
461                                                           &composite_x_offset,
462                                                           &composite_y_offset);
463
464   
465   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
466                                                     xsrc - composite_x_offset,
467                                                     ysrc - composite_y_offset,
468                                                     xdest, ydest,
469                                                     width, height);
470   
471   g_object_unref (G_OBJECT (composite));
472 }
473
474 void
475 gdk_draw_image (GdkDrawable *drawable,
476                 GdkGC       *gc,
477                 GdkImage    *image,
478                 gint         xsrc,
479                 gint         ysrc,
480                 gint         xdest,
481                 gint         ydest,
482                 gint         width,
483                 gint         height)
484 {
485   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
486   g_return_if_fail (image != NULL);
487   g_return_if_fail (GDK_IS_GC (gc));
488
489   if (width == -1)
490     width = image->width;
491   if (height == -1)
492     height = image->height;
493
494   GDK_DRAWABLE_GET_CLASS (drawable)->draw_image (drawable, gc, image, xsrc, ysrc,
495                                                  xdest, ydest, width, height);
496 }
497
498 void
499 gdk_draw_points (GdkDrawable *drawable,
500                  GdkGC       *gc,
501                  GdkPoint    *points,
502                  gint         npoints)
503 {
504   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
505   g_return_if_fail ((points != NULL) && (npoints > 0));
506   g_return_if_fail (GDK_IS_GC (gc));
507   g_return_if_fail (npoints >= 0);
508
509   if (npoints == 0)
510     return;
511
512   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, points, npoints);
513 }
514
515 void
516 gdk_draw_segments (GdkDrawable *drawable,
517                    GdkGC       *gc,
518                    GdkSegment  *segs,
519                    gint         nsegs)
520 {
521   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
522
523   if (nsegs == 0)
524     return;
525
526   g_return_if_fail (segs != NULL);
527   g_return_if_fail (GDK_IS_GC (gc));
528   g_return_if_fail (nsegs >= 0);
529
530   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, segs, nsegs);
531 }
532
533 void
534 gdk_draw_lines (GdkDrawable *drawable,
535                 GdkGC       *gc,
536                 GdkPoint    *points,
537                 gint         npoints)
538 {
539
540   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
541   g_return_if_fail (points != NULL);
542   g_return_if_fail (GDK_IS_GC (gc));
543   g_return_if_fail (npoints >= 0);
544
545   if (npoints == 0)
546     return;
547
548   GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc, points, npoints);
549 }
550
551 void
552 gdk_draw_glyphs (GdkDrawable      *drawable,
553                  GdkGC            *gc,
554                  PangoFont        *font,
555                  gint              x,
556                  gint              y,
557                  PangoGlyphString *glyphs)
558 {
559   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
560   g_return_if_fail (GDK_IS_GC (gc));
561
562
563   GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs);
564 }
565
566
567 /**
568  * gdk_drawable_get_image:
569  * @drawable: a #GdkDrawable
570  * @x: x coordinate on @drawable
571  * @y: y coordinate on @drawable
572  * @width: width of region to get
573  * @height: height or region to get
574  * 
575  * A #GdkImage stores client-side image data (pixels). In contrast,
576  * #GdkPixmap and #GdkWindow are server-side
577  * objects. gdk_drawable_get_image() obtains the pixels from a
578  * server-side drawable as a client-side #GdkImage.  The format of a
579  * #GdkImage depends on the #GdkVisual of the current display, which
580  * makes manipulating #GdkImage extremely difficult; therefore, in
581  * most cases you should use gdk_pixbuf_get_from_drawable() instead of
582  * this lower-level function. A #GdkPixbuf contains image data in a
583  * canonicalized RGB format, rather than a display-dependent format.
584  * Of course, there's a convenience vs. speed tradeoff here, so you'll
585  * want to think about what makes sense for your application.
586  *
587  * @x, @y, @width, and @height define the region of @drawable to
588  * obtain as an image.
589  *
590  * You would usually copy image data to the client side if you intend
591  * to examine the values of individual pixels, for example to darken
592  * an image or add a red tint. It would be prohibitively slow to
593  * make a round-trip request to the windowing system for each pixel,
594  * so instead you get all of them at once, modify them, then copy
595  * them all back at once.
596  *
597  * If the X server or other windowing system backend is on the local
598  * machine, this function may use shared memory to avoid copying
599  * the image data.
600  * 
601  * Return value: a #GdkImage containing the contents of @drawable
602  **/
603 GdkImage*
604 gdk_drawable_get_image (GdkDrawable *drawable,
605                         gint         x,
606                         gint         y,
607                         gint         width,
608                         gint         height)
609 {
610   GdkDrawable *composite;
611   gint composite_x_offset = 0;
612   gint composite_y_offset = 0;
613   GdkImage *retval;
614   
615   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
616   g_return_val_if_fail (x >= 0, NULL);
617   g_return_val_if_fail (y >= 0, NULL);
618
619   /* FIXME? Note race condition since we get the size then
620    * get the image, and the size may have changed.
621    */
622   
623   if (width < 0 || height < 0)
624     gdk_drawable_get_size (drawable,
625                            width < 0 ? &width : NULL,
626                            height < 0 ? &height : NULL);
627   
628   composite =
629     GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
630                                                                x, y,
631                                                                width, height,
632                                                                &composite_x_offset,
633                                                                &composite_y_offset); 
634   
635   retval = GDK_DRAWABLE_GET_CLASS (composite)->get_image (composite,
636                                                           x - composite_x_offset,
637                                                           y - composite_y_offset,
638                                                           width, height);
639
640   g_object_unref (G_OBJECT (composite));
641
642   return retval;
643 }
644
645 static GdkDrawable*
646 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
647                                           gint         x,
648                                           gint         y,
649                                           gint         width,
650                                           gint         height,
651                                           gint        *composite_x_offset,
652                                           gint        *composite_y_offset)
653 {
654   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
655
656   *composite_x_offset = 0;
657   *composite_y_offset = 0;
658   
659   return GDK_DRAWABLE (g_object_ref (G_OBJECT (drawable)));
660 }
661
662 /**
663  * gdk_drawable_get_clip_region:
664  * @drawable: a #GdkDrawable
665  * 
666  * Computes the region of a drawable that potentially can be written
667  * to by drawing primitives. This region will not take into account
668  * the clip region for the GC, and may also not take into account
669  * other factors such as if the window is obscured by other windows,
670  * but no area outside of this region will be affected by drawing
671  * primitives.
672  * 
673  * Return value: a #GdkRegion. This must be freed with gdk_region_destroy()
674  *               when you are done.
675  **/
676 GdkRegion *
677 gdk_drawable_get_clip_region (GdkDrawable *drawable)
678 {
679   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
680
681   return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
682 }
683
684 /**
685  * gdk_drawable_get_visible_region:
686  * @drawable: 
687  * 
688  * Computes the region of a drawable that is potentially visible.
689  * This does not necessarily take into account if the window is
690  * obscured by other windows, but no area outside of this region
691  * is visible.
692  * 
693  * Return value: a #GdkRegion. This must be freed with gdk_region_destroy()
694  *               when you are done.
695  **/
696 GdkRegion *
697 gdk_drawable_get_visible_region (GdkDrawable *drawable)
698 {
699   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
700
701   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
702 }
703
704 static GdkRegion *
705 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
706 {
707   GdkRectangle rect;
708
709   rect.x = 0;
710   rect.y = 0;
711
712   gdk_drawable_get_size (drawable, &rect.width, &rect.height);
713
714   return gdk_region_rectangle (&rect);
715 }