]> Pileus Git - ~andy/gtk/blob - gdk/gdkdraw.c
API: remove gdk_draw_{line,lines,segments}
[~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 "config.h"
28 #include <math.h>
29 #include <pango/pangocairo.h>
30 #include <gdk-pixbuf/gdk-pixbuf.h>
31 #include "gdkcairo.h"
32 #include "gdkdrawable.h"
33 #include "gdkinternals.h"
34 #include "gdkwindow.h"
35 #include "gdkscreen.h"
36 #include "gdkpixbuf.h"
37
38
39 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable  *drawable,
40                                                               gint          x,
41                                                               gint          y,
42                                                               gint          width,
43                                                               gint          height,
44                                                               gint         *composite_x_offset,
45                                                               gint         *composite_y_offset);
46 static cairo_region_t *  gdk_drawable_real_get_visible_region     (GdkDrawable  *drawable);
47 static void         gdk_drawable_real_draw_drawable          (GdkDrawable  *drawable,
48                                                               GdkGC        *gc,
49                                                               GdkDrawable  *src,
50                                                               gint          xsrc,
51                                                               gint          ysrc,
52                                                               gint          xdest,
53                                                               gint          ydest,
54                                                               gint          width,
55                                                               gint          height);
56      
57
58 G_DEFINE_ABSTRACT_TYPE (GdkDrawable, gdk_drawable, G_TYPE_OBJECT)
59
60 static void
61 gdk_drawable_class_init (GdkDrawableClass *klass)
62 {
63   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
64   /* Default implementation for clip and visible region is the same */
65   klass->get_clip_region = gdk_drawable_real_get_visible_region;
66   klass->get_visible_region = gdk_drawable_real_get_visible_region;
67   klass->draw_drawable = gdk_drawable_real_draw_drawable;
68 }
69
70 static void
71 gdk_drawable_init (GdkDrawable *drawable)
72 {
73 }
74
75 /* Manipulation of drawables
76  */
77
78 /**
79  * gdk_drawable_get_size:
80  * @drawable: a #GdkDrawable
81  * @width: (out) (allow-none): location to store drawable's width, or %NULL
82  * @height: (out) (allow-none): location to store drawable's height, or %NULL
83  *
84  * Fills *@width and *@height with the size of @drawable.
85  * @width or @height can be %NULL if you only want the other one.
86  *
87  * On the X11 platform, if @drawable is a #GdkWindow, the returned
88  * size is the size reported in the most-recently-processed configure
89  * event, rather than the current size on the X server.
90  * 
91  **/
92 void
93 gdk_drawable_get_size (GdkDrawable *drawable,
94                        gint        *width,
95                        gint        *height)
96 {
97   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
98
99   GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);  
100 }
101
102 /**
103  * gdk_drawable_get_visual:
104  * @drawable: a #GdkDrawable
105  * 
106  * Gets the #GdkVisual describing the pixel format of @drawable.
107  * 
108  * Return value: a #GdkVisual
109  **/
110 GdkVisual*
111 gdk_drawable_get_visual (GdkDrawable *drawable)
112 {
113   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
114   
115   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
116 }
117
118 /**
119  * gdk_drawable_get_depth:
120  * @drawable: a #GdkDrawable
121  * 
122  * Obtains the bit depth of the drawable, that is, the number of bits
123  * that make up a pixel in the drawable's visual. Examples are 8 bits
124  * per pixel, 24 bits per pixel, etc.
125  * 
126  * Return value: number of bits per pixel
127  **/
128 gint
129 gdk_drawable_get_depth (GdkDrawable *drawable)
130 {
131   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
132
133   return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
134 }
135 /**
136  * gdk_drawable_get_screen:
137  * @drawable: a #GdkDrawable
138  * 
139  * Gets the #GdkScreen associated with a #GdkDrawable.
140  * 
141  * Return value: the #GdkScreen associated with @drawable
142  *
143  * Since: 2.2
144  **/
145 GdkScreen*
146 gdk_drawable_get_screen(GdkDrawable *drawable)
147 {
148   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
149
150   return GDK_DRAWABLE_GET_CLASS (drawable)->get_screen (drawable);
151 }
152
153 /**
154  * gdk_drawable_get_display:
155  * @drawable: a #GdkDrawable
156  * 
157  * Gets the #GdkDisplay associated with a #GdkDrawable.
158  * 
159  * Return value: the #GdkDisplay associated with @drawable
160  *
161  * Since: 2.2
162  **/
163 GdkDisplay*
164 gdk_drawable_get_display (GdkDrawable *drawable)
165 {
166   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
167   
168   return gdk_screen_get_display (gdk_drawable_get_screen (drawable));
169 }
170         
171 /**
172  * gdk_drawable_set_colormap:
173  * @drawable: a #GdkDrawable
174  * @colormap: a #GdkColormap
175  *
176  * Sets the colormap associated with @drawable. Normally this will
177  * happen automatically when the drawable is created; you only need to
178  * use this function if the drawable-creating function did not have a
179  * way to determine the colormap, and you then use drawable operations
180  * that require a colormap. The colormap for all drawables and
181  * graphics contexts you intend to use together should match. i.e.
182  * when using a #GdkGC to draw to a drawable, or copying one drawable
183  * to another, the colormaps should match.
184  * 
185  **/
186 void
187 gdk_drawable_set_colormap (GdkDrawable *drawable,
188                            GdkColormap *cmap)
189 {
190   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
191   g_return_if_fail (cmap == NULL || gdk_drawable_get_depth (drawable)
192                     == cmap->visual->depth);
193
194   GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
195 }
196
197 /**
198  * gdk_drawable_get_colormap:
199  * @drawable: a #GdkDrawable
200  * 
201  * Gets the colormap for @drawable, if one is set; returns
202  * %NULL otherwise.
203  * 
204  * Return value: the colormap, or %NULL
205  **/
206 GdkColormap*
207 gdk_drawable_get_colormap (GdkDrawable *drawable)
208 {
209   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
210
211   return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
212 }
213
214 /* Drawing
215  */
216
217 /**
218  * gdk_draw_point:
219  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
220  * @gc: a #GdkGC.
221  * @x: the x coordinate of the point.
222  * @y: the y coordinate of the point.
223  * 
224  * Draws a point, using the foreground color and other attributes of 
225  * the #GdkGC.
226  **/
227 void
228 gdk_draw_point (GdkDrawable *drawable,
229                 GdkGC       *gc,
230                 gint         x,
231                 gint         y)
232 {
233   GdkPoint point;
234
235   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
236   g_return_if_fail (GDK_IS_GC (gc));
237
238   point.x = x;
239   point.y = y;
240   
241   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1);
242 }
243
244 /**
245  * gdk_draw_rectangle:
246  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
247  * @gc: a #GdkGC.
248  * @filled: %TRUE if the rectangle should be filled.
249  * @x: the x coordinate of the left edge of the rectangle.
250  * @y: the y coordinate of the top edge of the rectangle.
251  * @width: the width of the rectangle.
252  * @height: the height of the rectangle.
253  * 
254  * Draws a rectangular outline or filled rectangle, using the foreground color
255  * and other attributes of the #GdkGC.
256  *
257  * A rectangle drawn filled is 1 pixel smaller in both dimensions than a 
258  * rectangle outlined. Calling 
259  * <literal>gdk_draw_rectangle (window, gc, TRUE, 0, 0, 20, 20)</literal> 
260  * results in a filled rectangle 20 pixels wide and 20 pixels high. Calling
261  * <literal>gdk_draw_rectangle (window, gc, FALSE, 0, 0, 20, 20)</literal> 
262  * results in an outlined rectangle with corners at (0, 0), (0, 20), (20, 20),
263  * and (20, 0), which makes it 21 pixels wide and 21 pixels high.
264  **/
265 void
266 gdk_draw_rectangle (GdkDrawable *drawable,
267                     GdkGC       *gc,
268                     gboolean     filled,
269                     gint         x,
270                     gint         y,
271                     gint         width,
272                     gint         height)
273 {  
274   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
275   g_return_if_fail (GDK_IS_GC (gc));
276
277   if (width < 0 || height < 0)
278     {
279       gint real_width;
280       gint real_height;
281       
282       gdk_drawable_get_size (drawable, &real_width, &real_height);
283
284       if (width < 0)
285         width = real_width;
286       if (height < 0)
287         height = real_height;
288     }
289
290   GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y,
291                                                      width, height);
292 }
293
294 /**
295  * gdk_draw_drawable:
296  * @drawable: a #GdkDrawable
297  * @gc: a #GdkGC sharing the drawable's visual and colormap
298  * @src: the source #GdkDrawable, which may be the same as @drawable
299  * @xsrc: X position in @src of rectangle to draw
300  * @ysrc: Y position in @src of rectangle to draw
301  * @xdest: X position in @drawable where the rectangle should be drawn
302  * @ydest: Y position in @drawable where the rectangle should be drawn
303  * @width: width of rectangle to draw, or -1 for entire @src width
304  * @height: height of rectangle to draw, or -1 for entire @src height
305  *
306  * Copies the @width x @height region of @src at coordinates (@xsrc,
307  * @ysrc) to coordinates (@xdest, @ydest) in @drawable.
308  * @width and/or @height may be given as -1, in which case the entire
309  * @src drawable will be copied.
310  *
311  * Most fields in @gc are not used for this operation, but notably the
312  * clip mask or clip region will be honored.
313  *
314  * The source and destination drawables must have the same visual and
315  * colormap, or errors will result. (On X11, failure to match
316  * visual/colormap results in a BadMatch error from the X server.)
317  * A common cause of this problem is an attempt to draw a bitmap to
318  * a color drawable. The way to draw a bitmap is to set the bitmap as 
319  * the stipple on the #GdkGC, set the fill mode to %GDK_STIPPLED, and 
320  * then draw the rectangle.
321  **/
322 void
323 gdk_draw_drawable (GdkDrawable *drawable,
324                    GdkGC       *gc,
325                    GdkDrawable *src,
326                    gint         xsrc,
327                    gint         ysrc,
328                    gint         xdest,
329                    gint         ydest,
330                    gint         width,
331                    gint         height)
332 {
333   GdkDrawable *composite;
334   gint composite_x_offset = 0;
335   gint composite_y_offset = 0;
336
337   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
338   g_return_if_fail (GDK_IS_DRAWABLE (src));
339   g_return_if_fail (GDK_IS_GC (gc));
340
341   if (width < 0 || height < 0)
342     {
343       gint real_width;
344       gint real_height;
345       
346       gdk_drawable_get_size (src, &real_width, &real_height);
347
348       if (width < 0)
349         width = real_width;
350       if (height < 0)
351         height = real_height;
352     }
353
354
355   composite =
356     GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
357                                                           xsrc, ysrc,
358                                                           width, height,
359                                                           &composite_x_offset,
360                                                           &composite_y_offset);
361
362   /* TODO: For non-native windows this may copy stuff from other overlapping
363      windows. We should clip that and (for windows with bg != None) clear that
364      area in the destination instead. */
365
366   if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src)
367     GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable, gc,
368                                                                composite,
369                                                                xsrc - composite_x_offset,
370                                                                ysrc - composite_y_offset,
371                                                                xdest, ydest,
372                                                                width, height,
373                                                                src);
374   else /* backwards compat for old out-of-tree implementations of GdkDrawable (are there any?) */
375     GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
376                                                       composite,
377                                                       xsrc - composite_x_offset,
378                                                       ysrc - composite_y_offset,
379                                                       xdest, ydest,
380                                                       width, height);
381
382   g_object_unref (composite);
383 }
384
385 /**
386  * gdk_draw_points:
387  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
388  * @gc: a #GdkGC.
389  * @points: an array of #GdkPoint structures.
390  * @n_points: the number of points to be drawn.
391  * 
392  * Draws a number of points, using the foreground color and other 
393  * attributes of the #GdkGC.
394  **/
395 void
396 gdk_draw_points (GdkDrawable    *drawable,
397                  GdkGC          *gc,
398                  const GdkPoint *points,
399                  gint            n_points)
400 {
401   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
402   g_return_if_fail ((points != NULL) && (n_points > 0));
403   g_return_if_fail (GDK_IS_GC (gc));
404   g_return_if_fail (n_points >= 0);
405
406   if (n_points == 0)
407     return;
408
409   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc,
410                                                   (GdkPoint *) points, n_points);
411 }
412
413 static GdkDrawable *
414 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
415                                           gint         x,
416                                           gint         y,
417                                           gint         width,
418                                           gint         height,
419                                           gint        *composite_x_offset,
420                                           gint        *composite_y_offset)
421 {
422   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
423
424   *composite_x_offset = 0;
425   *composite_y_offset = 0;
426   
427   return g_object_ref (drawable);
428 }
429
430 /**
431  * gdk_drawable_get_clip_region:
432  * @drawable: a #GdkDrawable
433  * 
434  * Computes the region of a drawable that potentially can be written
435  * to by drawing primitives. This region will not take into account
436  * the clip region for the GC, and may also not take into account
437  * other factors such as if the window is obscured by other windows,
438  * but no area outside of this region will be affected by drawing
439  * primitives.
440  * 
441  * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
442  *          when you are done.
443  **/
444 cairo_region_t *
445 gdk_drawable_get_clip_region (GdkDrawable *drawable)
446 {
447   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
448
449   return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
450 }
451
452 /**
453  * gdk_drawable_get_visible_region:
454  * @drawable: a #GdkDrawable
455  * 
456  * Computes the region of a drawable that is potentially visible.
457  * This does not necessarily take into account if the window is
458  * obscured by other windows, but no area outside of this region
459  * is visible.
460  * 
461  * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
462  *          when you are done.
463  **/
464 cairo_region_t *
465 gdk_drawable_get_visible_region (GdkDrawable *drawable)
466 {
467   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
468
469   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
470 }
471
472 static cairo_region_t *
473 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
474 {
475   GdkRectangle rect;
476
477   rect.x = 0;
478   rect.y = 0;
479
480   gdk_drawable_get_size (drawable, &rect.width, &rect.height);
481
482   return cairo_region_create_rectangle (&rect);
483 }
484
485 /**
486  * _gdk_drawable_ref_cairo_surface:
487  * @drawable: a #GdkDrawable
488  * 
489  * Obtains a #cairo_surface_t for the given drawable. If a
490  * #cairo_surface_t for the drawable already exists, it will be
491  * referenced, otherwise a new surface will be created.
492  * 
493  * Return value: a newly referenced #cairo_surface_t that points
494  *  to @drawable. Unref with cairo_surface_destroy()
495  **/
496 cairo_surface_t *
497 _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
498 {
499   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
500
501   return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
502 }
503
504 /* Implementation of the old vfunc in terms of the new one
505    in case someone calls it directly (which they shouldn't!) */
506 static void
507 gdk_drawable_real_draw_drawable (GdkDrawable  *drawable,
508                                  GdkGC         *gc,
509                                  GdkDrawable  *src,
510                                  gint           xsrc,
511                                  gint           ysrc,
512                                  gint           xdest,
513                                  gint           ydest,
514                                  gint           width,
515                                  gint           height)
516 {
517   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable,
518                                                              gc,
519                                                              src,
520                                                              xsrc,
521                                                              ysrc,
522                                                              xdest,
523                                                              ydest,
524                                                              width,
525                                                              height,
526                                                              src);
527 }
528
529 /************************************************************************/
530
531 /**
532  * _gdk_drawable_get_scratch_gc:
533  * @drawable: A #GdkDrawable
534  * @graphics_exposures: Whether the returned #GdkGC should generate graphics exposures 
535  * 
536  * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
537  * the standard values for @drawable, except for the graphics_exposures
538  * field which is determined by the @graphics_exposures parameter.
539  *
540  * The foreground color of the returned #GdkGC is undefined. The #GdkGC
541  * must not be altered in any way, except to change its foreground color.
542  * 
543  * Return value: A #GdkGC suitable for drawing on @drawable
544  * 
545  * Since: 2.4
546  **/
547 GdkGC *
548 _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
549                               gboolean     graphics_exposures)
550 {
551   GdkScreen *screen;
552   gint depth;
553
554   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
555
556   screen = gdk_drawable_get_screen (drawable);
557
558   g_return_val_if_fail (!screen->closed, NULL);
559
560   depth = gdk_drawable_get_depth (drawable) - 1;
561
562   if (graphics_exposures)
563     {
564       if (!screen->exposure_gcs[depth])
565         {
566           GdkGCValues values;
567           GdkGCValuesMask mask;
568
569           values.graphics_exposures = TRUE;
570           mask = GDK_GC_EXPOSURES;  
571
572           screen->exposure_gcs[depth] =
573             gdk_gc_new_with_values (drawable, &values, mask);
574         }
575
576       return screen->exposure_gcs[depth];
577     }
578   else
579     {
580       if (!screen->normal_gcs[depth])
581         {
582           screen->normal_gcs[depth] =
583             gdk_gc_new (drawable);
584         }
585
586       return screen->normal_gcs[depth];
587     }
588 }
589
590 /**
591  * _gdk_drawable_get_subwindow_scratch_gc:
592  * @drawable: A #GdkDrawable
593  * 
594  * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
595  * the standard values for @drawable, except for the graphics_exposures
596  * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
597  *
598  * The foreground color of the returned #GdkGC is undefined. The #GdkGC
599  * must not be altered in any way, except to change its foreground color.
600  * 
601  * Return value: A #GdkGC suitable for drawing on @drawable
602  * 
603  * Since: 2.18
604  **/
605 GdkGC *
606 _gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
607 {
608   GdkScreen *screen;
609   gint depth;
610
611   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
612
613   screen = gdk_drawable_get_screen (drawable);
614
615   g_return_val_if_fail (!screen->closed, NULL);
616
617   depth = gdk_drawable_get_depth (drawable) - 1;
618
619   if (!screen->subwindow_gcs[depth])
620     {
621       GdkGCValues values;
622       GdkGCValuesMask mask;
623       
624       values.graphics_exposures = TRUE;
625       values.subwindow_mode = GDK_INCLUDE_INFERIORS;
626       mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;  
627       
628       screen->subwindow_gcs[depth] =
629         gdk_gc_new_with_values (drawable, &values, mask);
630     }
631   
632   return screen->subwindow_gcs[depth];
633 }
634
635
636 /*
637  * _gdk_drawable_get_source_drawable:
638  * @drawable: a #GdkDrawable
639  *
640  * Returns a drawable for the passed @drawable that is guaranteed to be
641  * usable to create a pixmap (e.g.: not an offscreen window).
642  *
643  * Since: 2.16
644  */
645 GdkDrawable *
646 _gdk_drawable_get_source_drawable (GdkDrawable *drawable)
647 {
648   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
649
650   if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
651     return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
652
653   return drawable;
654 }
655
656 cairo_surface_t *
657 _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
658                                     int width,
659                                     int height)
660 {
661   return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,
662                                                                   width, height);
663 }