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 #include "gdkalias.h"
38 
39 static GdkImage*    gdk_drawable_real_get_image (GdkDrawable     *drawable,
40 						 gint             x,
41 						 gint             y,
42 						 gint             width,
43 						 gint             height);
44 static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable  *drawable,
45 							      gint          x,
46 							      gint          y,
47 							      gint          width,
48 							      gint          height,
49 							      gint         *composite_x_offset,
50 							      gint         *composite_y_offset);
51 static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable  *drawable);
52 static void         gdk_drawable_real_draw_pixbuf            (GdkDrawable  *drawable,
53 							      GdkGC        *gc,
54 							      GdkPixbuf    *pixbuf,
55 							      gint          src_x,
56 							      gint          src_y,
57 							      gint          dest_x,
58 							      gint          dest_y,
59 							      gint          width,
60 							      gint          height,
61 							      GdkRgbDither  dither,
62 							      gint          x_dither,
63 							      gint          y_dither);
64 static void         gdk_drawable_real_draw_drawable          (GdkDrawable  *drawable,
65 							      GdkGC	   *gc,
66 							      GdkDrawable  *src,
67 							      gint          xsrc,
68 							      gint	    ysrc,
69 							      gint	    xdest,
70 							      gint	    ydest,
71 							      gint	    width,
72 							      gint	    height);
73 
74 
G_DEFINE_ABSTRACT_TYPE(GdkDrawable,gdk_drawable,G_TYPE_OBJECT)75 G_DEFINE_ABSTRACT_TYPE (GdkDrawable, gdk_drawable, G_TYPE_OBJECT)
76 
77 static void
78 gdk_drawable_class_init (GdkDrawableClass *klass)
79 {
80   klass->get_image = gdk_drawable_real_get_image;
81   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
82   /* Default implementation for clip and visible region is the same */
83   klass->get_clip_region = gdk_drawable_real_get_visible_region;
84   klass->get_visible_region = gdk_drawable_real_get_visible_region;
85   klass->draw_pixbuf = gdk_drawable_real_draw_pixbuf;
86   klass->draw_drawable = gdk_drawable_real_draw_drawable;
87 }
88 
89 static void
gdk_drawable_init(GdkDrawable * drawable)90 gdk_drawable_init (GdkDrawable *drawable)
91 {
92 }
93 
94 /* Manipulation of drawables
95  */
96 
97 /**
98  * gdk_drawable_set_data:
99  * @drawable: a #GdkDrawable
100  * @key: name to store the data under
101  * @data: arbitrary data
102  * @destroy_func: (allow-none): function to free @data, or %NULL
103  *
104  * This function is equivalent to g_object_set_data(),
105  * the #GObject variant should be used instead.
106  *
107  **/
108 void
gdk_drawable_set_data(GdkDrawable * drawable,const gchar * key,gpointer data,GDestroyNotify destroy_func)109 gdk_drawable_set_data (GdkDrawable   *drawable,
110 		       const gchar   *key,
111 		       gpointer	      data,
112 		       GDestroyNotify destroy_func)
113 {
114   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
115 
116   g_object_set_qdata_full (G_OBJECT (drawable),
117                            g_quark_from_string (key),
118                            data,
119                            destroy_func);
120 }
121 
122 /**
123  * gdk_drawable_get_data:
124  * @drawable: a #GdkDrawable
125  * @key: name the data was stored under
126  *
127  * Equivalent to g_object_get_data(); the #GObject variant should be
128  * used instead.
129  *
130  * Return value: the data stored at @key
131  **/
132 gpointer
gdk_drawable_get_data(GdkDrawable * drawable,const gchar * key)133 gdk_drawable_get_data (GdkDrawable   *drawable,
134 		       const gchar   *key)
135 {
136   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
137 
138   return g_object_get_qdata (G_OBJECT (drawable),
139                              g_quark_try_string (key));
140 }
141 
142 /**
143  * gdk_drawable_get_size:
144  * @drawable: a #GdkDrawable
145  * @width: (out) (allow-none): location to store drawable's width, or %NULL
146  * @height: (out) (allow-none): location to store drawable's height, or %NULL
147  *
148  * Fills *@width and *@height with the size of @drawable.
149  * @width or @height can be %NULL if you only want the other one.
150  *
151  * On the X11 platform, if @drawable is a #GdkWindow, the returned
152  * size is the size reported in the most-recently-processed configure
153  * event, rather than the current size on the X server.
154  *
155  * Deprecated: 2.24: Use gdk_window_get_width() and gdk_window_get_height() for
156  *             #GdkWindows. Use gdk_pixmap_get_size() for #GdkPixmaps.
157  */
158 void
gdk_drawable_get_size(GdkDrawable * drawable,gint * width,gint * height)159 gdk_drawable_get_size (GdkDrawable *drawable,
160 		       gint        *width,
161 		       gint        *height)
162 {
163   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
164 
165   GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);
166 }
167 
168 /**
169  * gdk_drawable_get_visual:
170  * @drawable: a #GdkDrawable
171  *
172  * Gets the #GdkVisual describing the pixel format of @drawable.
173  *
174  * Return value: a #GdkVisual
175  *
176  * Deprecated: 2.24: Use gdk_window_get_visual()
177  */
178 GdkVisual*
gdk_drawable_get_visual(GdkDrawable * drawable)179 gdk_drawable_get_visual (GdkDrawable *drawable)
180 {
181   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
182 
183   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visual (drawable);
184 }
185 
186 /**
187  * gdk_drawable_get_depth:
188  * @drawable: a #GdkDrawable
189  *
190  * Obtains the bit depth of the drawable, that is, the number of bits
191  * that make up a pixel in the drawable's visual. Examples are 8 bits
192  * per pixel, 24 bits per pixel, etc.
193  *
194  * Return value: number of bits per pixel
195  **/
196 gint
gdk_drawable_get_depth(GdkDrawable * drawable)197 gdk_drawable_get_depth (GdkDrawable *drawable)
198 {
199   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), 0);
200 
201   return GDK_DRAWABLE_GET_CLASS (drawable)->get_depth (drawable);
202 }
203 /**
204  * gdk_drawable_get_screen:
205  * @drawable: a #GdkDrawable
206  *
207  * Gets the #GdkScreen associated with a #GdkDrawable.
208  *
209  * Return value: the #GdkScreen associated with @drawable
210  *
211  * Since: 2.2
212  *
213  * Deprecated: 2.24: Use gdk_window_get_screen() instead
214  **/
215 GdkScreen*
gdk_drawable_get_screen(GdkDrawable * drawable)216 gdk_drawable_get_screen (GdkDrawable *drawable)
217 {
218   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
219 
220   return GDK_DRAWABLE_GET_CLASS (drawable)->get_screen (drawable);
221 }
222 
223 /**
224  * gdk_drawable_get_display:
225  * @drawable: a #GdkDrawable
226  *
227  * Gets the #GdkDisplay associated with a #GdkDrawable.
228  *
229  * Return value: the #GdkDisplay associated with @drawable
230  *
231  * Since: 2.2
232  *
233  * Deprecated: 2.24: Use gdk_window_get_display() instead
234  **/
235 GdkDisplay*
gdk_drawable_get_display(GdkDrawable * drawable)236 gdk_drawable_get_display (GdkDrawable *drawable)
237 {
238   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
239 
240   return gdk_screen_get_display (gdk_drawable_get_screen (drawable));
241 }
242 
243 /**
244  * gdk_drawable_set_colormap:
245  * @drawable: a #GdkDrawable
246  * @colormap: a #GdkColormap
247  *
248  * Sets the colormap associated with @drawable. Normally this will
249  * happen automatically when the drawable is created; you only need to
250  * use this function if the drawable-creating function did not have a
251  * way to determine the colormap, and you then use drawable operations
252  * that require a colormap. The colormap for all drawables and
253  * graphics contexts you intend to use together should match. i.e.
254  * when using a #GdkGC to draw to a drawable, or copying one drawable
255  * to another, the colormaps should match.
256  *
257  **/
258 void
gdk_drawable_set_colormap(GdkDrawable * drawable,GdkColormap * cmap)259 gdk_drawable_set_colormap (GdkDrawable *drawable,
260                            GdkColormap *cmap)
261 {
262   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
263   g_return_if_fail (cmap == NULL || gdk_drawable_get_depth (drawable)
264                     == cmap->visual->depth);
265 
266   GDK_DRAWABLE_GET_CLASS (drawable)->set_colormap (drawable, cmap);
267 }
268 
269 /**
270  * gdk_drawable_get_colormap:
271  * @drawable: a #GdkDrawable
272  *
273  * Gets the colormap for @drawable, if one is set; returns
274  * %NULL otherwise.
275  *
276  * Return value: the colormap, or %NULL
277  **/
278 GdkColormap*
gdk_drawable_get_colormap(GdkDrawable * drawable)279 gdk_drawable_get_colormap (GdkDrawable *drawable)
280 {
281   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
282 
283   return GDK_DRAWABLE_GET_CLASS (drawable)->get_colormap (drawable);
284 }
285 
286 /**
287  * gdk_drawable_ref:
288  * @drawable: a #GdkDrawable
289  *
290  * Deprecated equivalent of calling g_object_ref() on @drawable.
291  * (Drawables were not objects in previous versions of GDK.)
292  *
293  * Return value: the same @drawable passed in
294  *
295  * Deprecated: 2.0: Use g_object_ref() instead.
296  **/
297 GdkDrawable*
gdk_drawable_ref(GdkDrawable * drawable)298 gdk_drawable_ref (GdkDrawable *drawable)
299 {
300   return (GdkDrawable *) g_object_ref (drawable);
301 }
302 
303 /**
304  * gdk_drawable_unref:
305  * @drawable: a #GdkDrawable
306  *
307  * Deprecated equivalent of calling g_object_unref() on @drawable.
308  *
309  * Deprecated: 2.0: Use g_object_unref() instead.
310  **/
311 void
gdk_drawable_unref(GdkDrawable * drawable)312 gdk_drawable_unref (GdkDrawable *drawable)
313 {
314   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
315 
316   g_object_unref (drawable);
317 }
318 
319 /* Drawing
320  */
321 
322 /**
323  * gdk_draw_point:
324  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
325  * @gc: a #GdkGC.
326  * @x: the x coordinate of the point.
327  * @y: the y coordinate of the point.
328  *
329  * Draws a point, using the foreground color and other attributes of
330  * the #GdkGC.
331  *
332  * Deprecated: 2.22: Use cairo_rectangle() and cairo_fill() or
333  * cairo_move_to() and cairo_stroke() instead.
334  **/
335 void
gdk_draw_point(GdkDrawable * drawable,GdkGC * gc,gint x,gint y)336 gdk_draw_point (GdkDrawable *drawable,
337                 GdkGC       *gc,
338                 gint         x,
339                 gint         y)
340 {
341   GdkPoint point;
342 
343   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
344   g_return_if_fail (GDK_IS_GC (gc));
345 
346   point.x = x;
347   point.y = y;
348 
349   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc, &point, 1);
350 }
351 
352 /**
353  * gdk_draw_line:
354  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
355  * @gc: a #GdkGC.
356  * @x1_: the x coordinate of the start point.
357  * @y1_: the y coordinate of the start point.
358  * @x2_: the x coordinate of the end point.
359  * @y2_: the y coordinate of the end point.
360  *
361  * Draws a line, using the foreground color and other attributes of
362  * the #GdkGC.
363  *
364  * Deprecated: 2.22: Use cairo_line_to() and cairo_stroke() instead.
365  * Be aware that the default line width in Cairo is 2 pixels and that your
366  * coordinates need to describe the center of the line. To draw a single
367  * pixel wide pixel-aligned line, you would use:
368  * |[cairo_set_line_width (cr, 1.0);
369  * cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
370  * cairo_move_to (cr, 0.5, 0.5);
371  * cairo_line_to (cr, 9.5, 0.5);
372  * cairo_stroke (cr);]|
373  * See also <ulink url="http://cairographics.org/FAQ/#sharp_lines">the Cairo
374  * FAQ</ulink> on this topic.
375  **/
376 void
gdk_draw_line(GdkDrawable * drawable,GdkGC * gc,gint x1,gint y1,gint x2,gint y2)377 gdk_draw_line (GdkDrawable *drawable,
378 	       GdkGC       *gc,
379 	       gint         x1,
380 	       gint         y1,
381 	       gint         x2,
382 	       gint         y2)
383 {
384   GdkSegment segment;
385 
386   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
387   g_return_if_fail (GDK_IS_GC (gc));
388 
389   segment.x1 = x1;
390   segment.y1 = y1;
391   segment.x2 = x2;
392   segment.y2 = y2;
393   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc, &segment, 1);
394 }
395 
396 /**
397  * gdk_draw_rectangle:
398  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
399  * @gc: a #GdkGC.
400  * @filled: %TRUE if the rectangle should be filled.
401  * @x: the x coordinate of the left edge of the rectangle.
402  * @y: the y coordinate of the top edge of the rectangle.
403  * @width: the width of the rectangle.
404  * @height: the height of the rectangle.
405  *
406  * Draws a rectangular outline or filled rectangle, using the foreground color
407  * and other attributes of the #GdkGC.
408  *
409  * A rectangle drawn filled is 1 pixel smaller in both dimensions than a
410  * rectangle outlined. Calling
411  * <literal>gdk_draw_rectangle (window, gc, TRUE, 0, 0, 20, 20)</literal>
412  * results in a filled rectangle 20 pixels wide and 20 pixels high. Calling
413  * <literal>gdk_draw_rectangle (window, gc, FALSE, 0, 0, 20, 20)</literal>
414  * results in an outlined rectangle with corners at (0, 0), (0, 20), (20, 20),
415  * and (20, 0), which makes it 21 pixels wide and 21 pixels high.
416  *
417  * Deprecated: 2.22: Use cairo_rectangle() and cairo_fill() or cairo_stroke()
418  * instead. For stroking, the same caveats for converting code apply as for
419  * gdk_draw_line().
420  **/
421 void
gdk_draw_rectangle(GdkDrawable * drawable,GdkGC * gc,gboolean filled,gint x,gint y,gint width,gint height)422 gdk_draw_rectangle (GdkDrawable *drawable,
423 		    GdkGC       *gc,
424 		    gboolean     filled,
425 		    gint         x,
426 		    gint         y,
427 		    gint         width,
428 		    gint         height)
429 {
430   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
431   g_return_if_fail (GDK_IS_GC (gc));
432 
433   if (width < 0 || height < 0)
434     {
435       gint real_width;
436       gint real_height;
437 
438       gdk_drawable_get_size (drawable, &real_width, &real_height);
439 
440       if (width < 0)
441         width = real_width;
442       if (height < 0)
443         height = real_height;
444     }
445 
446   GDK_DRAWABLE_GET_CLASS (drawable)->draw_rectangle (drawable, gc, filled, x, y,
447                                                      width, height);
448 }
449 
450 /**
451  * gdk_draw_arc:
452  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
453  * @gc: a #GdkGC.
454  * @filled: %TRUE if the arc should be filled, producing a 'pie slice'.
455  * @x: the x coordinate of the left edge of the bounding rectangle.
456  * @y: the y coordinate of the top edge of the bounding rectangle.
457  * @width: the width of the bounding rectangle.
458  * @height: the height of the bounding rectangle.
459  * @angle1: the start angle of the arc, relative to the 3 o'clock position,
460  *     counter-clockwise, in 1/64ths of a degree.
461  * @angle2: the end angle of the arc, relative to @angle1, in 1/64ths
462  *     of a degree.
463  *
464  * Draws an arc or a filled 'pie slice'. The arc is defined by the bounding
465  * rectangle of the entire ellipse, and the start and end angles of the part
466  * of the ellipse to be drawn.
467  *
468  * Deprecated: 2.22: Use cairo_arc() and cairo_fill() or cairo_stroke()
469  * instead. Note that arcs just like any drawing operation in Cairo are
470  * antialiased unless you call cairo_set_antialias().
471  **/
472 void
gdk_draw_arc(GdkDrawable * drawable,GdkGC * gc,gboolean filled,gint x,gint y,gint width,gint height,gint angle1,gint angle2)473 gdk_draw_arc (GdkDrawable *drawable,
474 	      GdkGC       *gc,
475 	      gboolean     filled,
476 	      gint         x,
477 	      gint         y,
478 	      gint         width,
479 	      gint         height,
480 	      gint         angle1,
481 	      gint         angle2)
482 {
483   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
484   g_return_if_fail (GDK_IS_GC (gc));
485 
486   if (width < 0 || height < 0)
487     {
488       gint real_width;
489       gint real_height;
490 
491       gdk_drawable_get_size (drawable, &real_width, &real_height);
492 
493       if (width < 0)
494         width = real_width;
495       if (height < 0)
496         height = real_height;
497     }
498 
499   GDK_DRAWABLE_GET_CLASS (drawable)->draw_arc (drawable, gc, filled,
500                                                x, y, width, height, angle1, angle2);
501 }
502 
503 /**
504  * gdk_draw_polygon:
505  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
506  * @gc: a #GdkGC.
507  * @filled: %TRUE if the polygon should be filled. The polygon is closed
508  *     automatically, connecting the last point to the first point if
509  *     necessary.
510  * @points: an array of #GdkPoint structures specifying the points making
511  *     up the polygon.
512  * @n_points: the number of points.
513  *
514  * Draws an outlined or filled polygon.
515  *
516  * Deprecated: 2.22: Use cairo_line_to() or cairo_append_path() and
517  * cairo_fill() or cairo_stroke() instead.
518  **/
519 void
gdk_draw_polygon(GdkDrawable * drawable,GdkGC * gc,gboolean filled,const GdkPoint * points,gint n_points)520 gdk_draw_polygon (GdkDrawable    *drawable,
521 		  GdkGC          *gc,
522 		  gboolean        filled,
523 		  const GdkPoint *points,
524 		  gint            n_points)
525 {
526   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
527   g_return_if_fail (GDK_IS_GC (gc));
528 
529   GDK_DRAWABLE_GET_CLASS (drawable)->draw_polygon (drawable, gc, filled,
530                                                    (GdkPoint *) points,
531                                                    n_points);
532 }
533 
534 /* gdk_draw_string
535  *
536  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
537  *
538  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
539  */
540 /**
541  * gdk_draw_string:
542  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
543  * @font: a #GdkFont.
544  * @gc: a #GdkGC.
545  * @x: the x coordinate of the left edge of the text.
546  * @y: the y coordinate of the baseline of the text.
547  * @string:  the string of characters to draw.
548  *
549  * Draws a string of characters in the given font or fontset.
550  *
551  * Deprecated: 2.4: Use gdk_draw_layout() instead.
552  **/
553 void
gdk_draw_string(GdkDrawable * drawable,GdkFont * font,GdkGC * gc,gint x,gint y,const gchar * string)554 gdk_draw_string (GdkDrawable *drawable,
555 		 GdkFont     *font,
556 		 GdkGC       *gc,
557 		 gint         x,
558 		 gint         y,
559 		 const gchar *string)
560 {
561   gdk_draw_text (drawable, font, gc, x, y, string, _gdk_font_strlen (font, string));
562 }
563 
564 /* gdk_draw_text
565  *
566  * Modified by Li-Da Lho to draw 16 bits and Multibyte strings
567  *
568  * Interface changed: add "GdkFont *font" to specify font or fontset explicitely
569  */
570 /**
571  * gdk_draw_text:
572  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
573  * @font: a #GdkFont.
574  * @gc: a #GdkGC.
575  * @x: the x coordinate of the left edge of the text.
576  * @y: the y coordinate of the baseline of the text.
577  * @text:  the characters to draw.
578  * @text_length: the number of characters of @text to draw.
579  *
580  * Draws a number of characters in the given font or fontset.
581  *
582  * Deprecated: 2.4: Use gdk_draw_layout() instead.
583  **/
584 void
gdk_draw_text(GdkDrawable * drawable,GdkFont * font,GdkGC * gc,gint x,gint y,const gchar * text,gint text_length)585 gdk_draw_text (GdkDrawable *drawable,
586 	       GdkFont     *font,
587 	       GdkGC       *gc,
588 	       gint         x,
589 	       gint         y,
590 	       const gchar *text,
591 	       gint         text_length)
592 {
593   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
594   g_return_if_fail (font != NULL);
595   g_return_if_fail (GDK_IS_GC (gc));
596   g_return_if_fail (text != NULL);
597 
598   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text (drawable, font, gc, x, y, text, text_length);
599 }
600 
601 /**
602  * gdk_draw_text_wc:
603  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
604  * @font: a #GdkFont.
605  * @gc: a #GdkGC.
606  * @x: the x coordinate of the left edge of the text.
607  * @y: the y coordinate of the baseline of the text.
608  * @text: the wide characters to draw.
609  * @text_length: the number of characters to draw.
610  *
611  * Draws a number of wide characters using the given font of fontset.
612  * If the font is a 1-byte font, the string is converted into 1-byte
613  * characters (discarding the high bytes) before output.
614  *
615  * Deprecated: 2.4: Use gdk_draw_layout() instead.
616  **/
617 void
gdk_draw_text_wc(GdkDrawable * drawable,GdkFont * font,GdkGC * gc,gint x,gint y,const GdkWChar * text,gint text_length)618 gdk_draw_text_wc (GdkDrawable	 *drawable,
619 		  GdkFont	 *font,
620 		  GdkGC		 *gc,
621 		  gint		  x,
622 		  gint		  y,
623 		  const GdkWChar *text,
624 		  gint		  text_length)
625 {
626   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
627   g_return_if_fail (font != NULL);
628   g_return_if_fail (GDK_IS_GC (gc));
629   g_return_if_fail (text != NULL);
630 
631   GDK_DRAWABLE_GET_CLASS (drawable)->draw_text_wc (drawable, font, gc, x, y, text, text_length);
632 }
633 
634 /**
635  * gdk_draw_drawable:
636  * @drawable: a #GdkDrawable
637  * @gc: a #GdkGC sharing the drawable's visual and colormap
638  * @src: the source #GdkDrawable, which may be the same as @drawable
639  * @xsrc: X position in @src of rectangle to draw
640  * @ysrc: Y position in @src of rectangle to draw
641  * @xdest: X position in @drawable where the rectangle should be drawn
642  * @ydest: Y position in @drawable where the rectangle should be drawn
643  * @width: width of rectangle to draw, or -1 for entire @src width
644  * @height: height of rectangle to draw, or -1 for entire @src height
645  *
646  * Copies the @width x @height region of @src at coordinates (@xsrc,
647  * @ysrc) to coordinates (@xdest, @ydest) in @drawable.
648  * @width and/or @height may be given as -1, in which case the entire
649  * @src drawable will be copied.
650  *
651  * Most fields in @gc are not used for this operation, but notably the
652  * clip mask or clip region will be honored.
653  *
654  * The source and destination drawables must have the same visual and
655  * colormap, or errors will result. (On X11, failure to match
656  * visual/colormap results in a BadMatch error from the X server.)
657  * A common cause of this problem is an attempt to draw a bitmap to
658  * a color drawable. The way to draw a bitmap is to set the bitmap as
659  * the stipple on the #GdkGC, set the fill mode to %GDK_STIPPLED, and
660  * then draw the rectangle.
661  *
662  * Deprecated: 2.22: Use gdk_cairo_set_source_pixmap(), cairo_rectangle()
663  * and cairo_fill() to draw pixmap on top of other drawables. Also keep
664  * in mind that the limitations on allowed sources do not apply to Cairo.
665  **/
666 void
gdk_draw_drawable(GdkDrawable * drawable,GdkGC * gc,GdkDrawable * src,gint xsrc,gint ysrc,gint xdest,gint ydest,gint width,gint height)667 gdk_draw_drawable (GdkDrawable *drawable,
668 		   GdkGC       *gc,
669 		   GdkDrawable *src,
670 		   gint         xsrc,
671 		   gint         ysrc,
672 		   gint         xdest,
673 		   gint         ydest,
674 		   gint         width,
675 		   gint         height)
676 {
677   GdkDrawable *composite;
678   gint composite_x_offset = 0;
679   gint composite_y_offset = 0;
680 
681   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
682   g_return_if_fail (GDK_IS_DRAWABLE (src));
683   g_return_if_fail (GDK_IS_GC (gc));
684 
685   if (width < 0 || height < 0)
686     {
687       gint real_width;
688       gint real_height;
689 
690       gdk_drawable_get_size (src, &real_width, &real_height);
691 
692       if (width < 0)
693         width = real_width;
694       if (height < 0)
695         height = real_height;
696     }
697 
698 
699   composite =
700     GDK_DRAWABLE_GET_CLASS (src)->get_composite_drawable (src,
701                                                           xsrc, ysrc,
702                                                           width, height,
703                                                           &composite_x_offset,
704                                                           &composite_y_offset);
705 
706   /* TODO: For non-native windows this may copy stuff from other overlapping
707      windows. We should clip that and (for windows with bg != None) clear that
708      area in the destination instead. */
709 
710   if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src)
711     GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable, gc,
712 							       composite,
713 							       xsrc - composite_x_offset,
714 							       ysrc - composite_y_offset,
715 							       xdest, ydest,
716 							       width, height,
717 							       src);
718   else /* backwards compat for old out-of-tree implementations of GdkDrawable (are there any?) */
719     GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
720 						      composite,
721 						      xsrc - composite_x_offset,
722 						      ysrc - composite_y_offset,
723 						      xdest, ydest,
724 						      width, height);
725 
726   g_object_unref (composite);
727 }
728 
729 /**
730  * gdk_draw_image:
731  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
732  * @gc: a #GdkGC.
733  * @image: the #GdkImage to draw.
734  * @xsrc: the left edge of the source rectangle within @image.
735  * @ysrc: the top of the source rectangle within @image.
736  * @xdest: the x coordinate of the destination within @drawable.
737  * @ydest: the y coordinate of the destination within @drawable.
738  * @width: the width of the area to be copied, or -1 to make the area
739  *     extend to the right edge of @image.
740  * @height: the height of the area to be copied, or -1 to make the area
741  *     extend to the bottom edge of @image.
742  *
743  * Draws a #GdkImage onto a drawable.
744  * The depth of the #GdkImage must match the depth of the #GdkDrawable.
745  *
746  * Deprecated: 2.22: Do not use #GdkImage anymore, instead use Cairo image
747  * surfaces.
748  **/
749 void
gdk_draw_image(GdkDrawable * drawable,GdkGC * gc,GdkImage * image,gint xsrc,gint ysrc,gint xdest,gint ydest,gint width,gint height)750 gdk_draw_image (GdkDrawable *drawable,
751 		GdkGC       *gc,
752 		GdkImage    *image,
753 		gint         xsrc,
754 		gint         ysrc,
755 		gint         xdest,
756 		gint         ydest,
757 		gint         width,
758 		gint         height)
759 {
760   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
761   g_return_if_fail (GDK_IS_IMAGE (image));
762   g_return_if_fail (GDK_IS_GC (gc));
763 
764   if (width == -1)
765     width = image->width;
766   if (height == -1)
767     height = image->height;
768 
769   GDK_DRAWABLE_GET_CLASS (drawable)->draw_image (drawable, gc, image, xsrc, ysrc,
770                                                  xdest, ydest, width, height);
771 }
772 
773 /**
774  * gdk_draw_pixbuf:
775  * @drawable: Destination drawable.
776  * @gc: (allow-none): a #GdkGC, used for clipping, or %NULL
777  * @pixbuf: a #GdkPixbuf
778  * @src_x: Source X coordinate within pixbuf.
779  * @src_y: Source Y coordinates within pixbuf.
780  * @dest_x: Destination X coordinate within drawable.
781  * @dest_y: Destination Y coordinate within drawable.
782  * @width: Width of region to render, in pixels, or -1 to use pixbuf width.
783  * @height: Height of region to render, in pixels, or -1 to use pixbuf height.
784  * @dither: Dithering mode for #GdkRGB.
785  * @x_dither: X offset for dither.
786  * @y_dither: Y offset for dither.
787  *
788  * Renders a rectangular portion of a pixbuf to a drawable.  The destination
789  * drawable must have a colormap. All windows have a colormap, however, pixmaps
790  * only have colormap by default if they were created with a non-%NULL window
791  * argument. Otherwise a colormap must be set on them with
792  * gdk_drawable_set_colormap().
793  *
794  * On older X servers, rendering pixbufs with an alpha channel involves round
795  * trips to the X server, and may be somewhat slow.
796  *
797  * If GDK is built with the Sun mediaLib library, the gdk_draw_pixbuf
798  * function is accelerated using mediaLib, which provides hardware
799  * acceleration on Intel, AMD, and Sparc chipsets.  If desired, mediaLib
800  * support can be turned off by setting the GDK_DISABLE_MEDIALIB environment
801  * variable.
802  *
803  * Since: 2.2
804  *
805  * Deprecated: 2.22: Use gdk_cairo_set_source_pixbuf() and cairo_paint() or
806  * cairo_rectangle() and cairo_fill() instead.
807  **/
808 void
gdk_draw_pixbuf(GdkDrawable * drawable,GdkGC * gc,const GdkPixbuf * pixbuf,gint src_x,gint src_y,gint dest_x,gint dest_y,gint width,gint height,GdkRgbDither dither,gint x_dither,gint y_dither)809 gdk_draw_pixbuf (GdkDrawable     *drawable,
810                  GdkGC           *gc,
811                  const GdkPixbuf *pixbuf,
812                  gint             src_x,
813                  gint             src_y,
814                  gint             dest_x,
815                  gint             dest_y,
816                  gint             width,
817                  gint             height,
818                  GdkRgbDither     dither,
819                  gint             x_dither,
820                  gint             y_dither)
821 {
822   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
823   g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
824   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
825 
826   if (width == 0 || height == 0)
827     return;
828 
829   if (width == -1)
830     width = gdk_pixbuf_get_width (pixbuf);
831   if (height == -1)
832     height = gdk_pixbuf_get_height (pixbuf);
833 
834   GDK_DRAWABLE_GET_CLASS (drawable)->draw_pixbuf (drawable, gc,
835                                                   (GdkPixbuf *) pixbuf,
836 						  src_x, src_y, dest_x, dest_y,
837                                                   width, height,
838 						  dither, x_dither, y_dither);
839 }
840 
841 /**
842  * gdk_draw_points:
843  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
844  * @gc: a #GdkGC.
845  * @points: an array of #GdkPoint structures.
846  * @n_points: the number of points to be drawn.
847  *
848  * Draws a number of points, using the foreground color and other
849  * attributes of the #GdkGC.
850  *
851  * Deprecated: 2.22: Use @n_points calls to cairo_rectangle() and
852  * cairo_fill() instead.
853  **/
854 void
gdk_draw_points(GdkDrawable * drawable,GdkGC * gc,const GdkPoint * points,gint n_points)855 gdk_draw_points (GdkDrawable    *drawable,
856 		 GdkGC          *gc,
857 		 const GdkPoint *points,
858 		 gint            n_points)
859 {
860   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
861   g_return_if_fail ((points != NULL) && (n_points > 0));
862   g_return_if_fail (GDK_IS_GC (gc));
863   g_return_if_fail (n_points >= 0);
864 
865   if (n_points == 0)
866     return;
867 
868   GDK_DRAWABLE_GET_CLASS (drawable)->draw_points (drawable, gc,
869                                                   (GdkPoint *) points, n_points);
870 }
871 
872 /**
873  * gdk_draw_segments:
874  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
875  * @gc: a #GdkGC.
876  * @segs: an array of #GdkSegment structures specifying the start and
877  *   end points of the lines to be drawn.
878  * @n_segs: the number of line segments to draw, i.e. the size of the
879  *   @segs array.
880  *
881  * Draws a number of unconnected lines.
882  *
883  * Deprecated: 2.22: Use cairo_move_to(), cairo_line_to() and cairo_stroke()
884  * instead. See the documentation of gdk_draw_line() for notes on line drawing
885  * with Cairo.
886  **/
887 void
gdk_draw_segments(GdkDrawable * drawable,GdkGC * gc,const GdkSegment * segs,gint n_segs)888 gdk_draw_segments (GdkDrawable      *drawable,
889 		   GdkGC            *gc,
890 		   const GdkSegment *segs,
891 		   gint              n_segs)
892 {
893   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
894 
895   if (n_segs == 0)
896     return;
897 
898   g_return_if_fail (segs != NULL);
899   g_return_if_fail (GDK_IS_GC (gc));
900   g_return_if_fail (n_segs >= 0);
901 
902   GDK_DRAWABLE_GET_CLASS (drawable)->draw_segments (drawable, gc,
903                                                     (GdkSegment *) segs, n_segs);
904 }
905 
906 /**
907  * gdk_draw_lines:
908  * @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
909  * @gc: a #GdkGC.
910  * @points: an array of #GdkPoint structures specifying the endpoints of the
911  * @n_points: the size of the @points array.
912  *
913  * Draws a series of lines connecting the given points.
914  * The way in which joins between lines are draw is determined by the
915  * #GdkCapStyle value in the #GdkGC. This can be set with
916  * gdk_gc_set_line_attributes().
917  *
918  * Deprecated: 2.22: Use cairo_line_to() and cairo_stroke() instead. See the
919  * documentation of gdk_draw_line() for notes on line drawing with Cairo.
920  **/
921 void
gdk_draw_lines(GdkDrawable * drawable,GdkGC * gc,const GdkPoint * points,gint n_points)922 gdk_draw_lines (GdkDrawable    *drawable,
923 		GdkGC          *gc,
924 		const GdkPoint *points,
925 		gint            n_points)
926 {
927   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
928   g_return_if_fail (points != NULL);
929   g_return_if_fail (GDK_IS_GC (gc));
930   g_return_if_fail (n_points >= 0);
931 
932   if (n_points == 0)
933     return;
934 
935   GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc,
936                                                  (GdkPoint *) points, n_points);
937 }
938 
939 static void
real_draw_glyphs(GdkDrawable * drawable,GdkGC * gc,const PangoMatrix * matrix,PangoFont * font,gdouble x,gdouble y,PangoGlyphString * glyphs)940 real_draw_glyphs (GdkDrawable       *drawable,
941 		  GdkGC	            *gc,
942 		  const PangoMatrix *matrix,
943 		  PangoFont         *font,
944 		  gdouble            x,
945 		  gdouble            y,
946 		  PangoGlyphString  *glyphs)
947 {
948   cairo_t *cr;
949 
950   cr = gdk_cairo_create (drawable);
951   _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
952 
953   if (matrix)
954     {
955       cairo_matrix_t cairo_matrix;
956 
957       cairo_matrix.xx = matrix->xx;
958       cairo_matrix.yx = matrix->yx;
959       cairo_matrix.xy = matrix->xy;
960       cairo_matrix.yy = matrix->yy;
961       cairo_matrix.x0 = matrix->x0;
962       cairo_matrix.y0 = matrix->y0;
963 
964       cairo_set_matrix (cr, &cairo_matrix);
965     }
966 
967   cairo_move_to (cr, x, y);
968   pango_cairo_show_glyph_string (cr, font, glyphs);
969 
970   cairo_destroy (cr);
971 }
972 
973 /**
974  * gdk_draw_glyphs:
975  * @drawable: a #GdkDrawable
976  * @gc: a #GdkGC
977  * @font: font to be used
978  * @x: X coordinate of baseline origin
979  * @y: Y coordinate of baseline origin
980  * @glyphs: the glyph string to draw
981  *
982  * This is a low-level function; 99% of text rendering should be done
983  * using gdk_draw_layout() instead.
984  *
985  * A glyph is a single image in a font. This function draws a sequence of
986  * glyphs.  To obtain a sequence of glyphs you have to understand a
987  * lot about internationalized text handling, which you don't want to
988  * understand; thus, use gdk_draw_layout() instead of this function,
989  * gdk_draw_layout() handles the details.
990  *
991  * Deprecated: 2.22: Use pango_cairo_show_glyphs() instead.
992  **/
993 void
gdk_draw_glyphs(GdkDrawable * drawable,GdkGC * gc,PangoFont * font,gint x,gint y,PangoGlyphString * glyphs)994 gdk_draw_glyphs (GdkDrawable      *drawable,
995 		 GdkGC            *gc,
996 		 PangoFont        *font,
997 		 gint              x,
998 		 gint              y,
999 		 PangoGlyphString *glyphs)
1000 {
1001   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
1002   g_return_if_fail (GDK_IS_GC (gc));
1003 
1004   real_draw_glyphs (drawable, gc, NULL, font,
1005 		    x, y, glyphs);
1006 }
1007 
1008 /**
1009  * gdk_draw_glyphs_transformed:
1010  * @drawable: a #GdkDrawable
1011  * @gc: a #GdkGC
1012  * @matrix: (allow-none): a #PangoMatrix, or %NULL to use an identity transformation
1013  * @font: the font in which to draw the string
1014  * @x:       the x position of the start of the string (in Pango
1015  *           units in user space coordinates)
1016  * @y:       the y position of the baseline (in Pango units
1017  *           in user space coordinates)
1018  * @glyphs:  the glyph string to draw
1019  *
1020  * Renders a #PangoGlyphString onto a drawable, possibly
1021  * transforming the layed-out coordinates through a transformation
1022  * matrix. Note that the transformation matrix for @font is not
1023  * changed, so to produce correct rendering results, the @font
1024  * must have been loaded using a #PangoContext with an identical
1025  * transformation matrix to that passed in to this function.
1026  *
1027  * See also gdk_draw_glyphs(), gdk_draw_layout().
1028  *
1029  * Since: 2.6
1030  *
1031  * Deprecated: 2.22: Use pango_cairo_show_glyphs() instead.
1032  **/
1033 void
gdk_draw_glyphs_transformed(GdkDrawable * drawable,GdkGC * gc,const PangoMatrix * matrix,PangoFont * font,gint x,gint y,PangoGlyphString * glyphs)1034 gdk_draw_glyphs_transformed (GdkDrawable       *drawable,
1035 			     GdkGC	       *gc,
1036 			     const PangoMatrix *matrix,
1037 			     PangoFont         *font,
1038 			     gint               x,
1039 			     gint               y,
1040 			     PangoGlyphString  *glyphs)
1041 {
1042   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
1043   g_return_if_fail (GDK_IS_GC (gc));
1044 
1045   real_draw_glyphs (drawable, gc, matrix, font,
1046 		    x / PANGO_SCALE, y / PANGO_SCALE, glyphs);
1047 }
1048 
1049 /**
1050  * gdk_draw_trapezoids:
1051  * @drawable: a #GdkDrawable
1052  * @gc: a #GdkGC
1053  * @trapezoids: an array of #GdkTrapezoid structures
1054  * @n_trapezoids: the number of trapezoids to draw
1055  *
1056  * Draws a set of anti-aliased trapezoids. The trapezoids are
1057  * combined using saturation addition, then drawn over the background
1058  * as a set. This is low level functionality used internally to implement
1059  * rotated underlines and backgrouds when rendering a PangoLayout and is
1060  * likely not useful for applications.
1061  *
1062  * Since: 2.6
1063  *
1064  * Deprecated: 2.22: Use Cairo path contruction functions and cairo_fill()
1065  * instead.
1066  **/
1067 void
gdk_draw_trapezoids(GdkDrawable * drawable,GdkGC * gc,const GdkTrapezoid * trapezoids,gint n_trapezoids)1068 gdk_draw_trapezoids (GdkDrawable        *drawable,
1069 		     GdkGC	        *gc,
1070 		     const GdkTrapezoid *trapezoids,
1071 		     gint                n_trapezoids)
1072 {
1073   cairo_t *cr;
1074   int i;
1075 
1076   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
1077   g_return_if_fail (GDK_IS_GC (gc));
1078   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
1079 
1080   cr = gdk_cairo_create (drawable);
1081   _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
1082 
1083   for (i = 0; i < n_trapezoids; i++)
1084     {
1085       cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1);
1086       cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1);
1087       cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2);
1088       cairo_line_to (cr, trapezoids[i].x12, trapezoids[i].y2);
1089       cairo_close_path (cr);
1090     }
1091 
1092   cairo_fill (cr);
1093 
1094   cairo_destroy (cr);
1095 }
1096 
1097 /**
1098  * gdk_drawable_copy_to_image:
1099  * @drawable: a #GdkDrawable
1100  * @image: (allow-none): a #GdkDrawable, or %NULL if a new @image should be created.
1101  * @src_x: x coordinate on @drawable
1102  * @src_y: y coordinate on @drawable
1103  * @dest_x: x coordinate within @image. Must be 0 if @image is %NULL
1104  * @dest_y: y coordinate within @image. Must be 0 if @image is %NULL
1105  * @width: width of region to get
1106  * @height: height or region to get
1107  *
1108  * Copies a portion of @drawable into the client side image structure
1109  * @image. If @image is %NULL, creates a new image of size @width x @height
1110  * and copies into that. See gdk_drawable_get_image() for further details.
1111  *
1112  * Return value: @image, or a new a #GdkImage containing the contents
1113  *               of @drawable
1114  *
1115  * Since: 2.4
1116  *
1117  * Deprecated: 2.22: Use @drawable as the source and draw to a Cairo image
1118  * surface if you want to download contents to the client.
1119  **/
1120 GdkImage*
gdk_drawable_copy_to_image(GdkDrawable * drawable,GdkImage * image,gint src_x,gint src_y,gint dest_x,gint dest_y,gint width,gint height)1121 gdk_drawable_copy_to_image (GdkDrawable *drawable,
1122 			    GdkImage    *image,
1123 			    gint         src_x,
1124 			    gint         src_y,
1125 			    gint         dest_x,
1126 			    gint         dest_y,
1127 			    gint         width,
1128 			    gint         height)
1129 {
1130   GdkDrawable *composite;
1131   gint composite_x_offset = 0;
1132   gint composite_y_offset = 0;
1133   GdkImage *retval;
1134   GdkColormap *cmap;
1135 
1136   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1137   g_return_val_if_fail (src_x >= 0, NULL);
1138   g_return_val_if_fail (src_y >= 0, NULL);
1139 
1140   /* FIXME? Note race condition since we get the size then
1141    * get the image, and the size may have changed.
1142    */
1143 
1144   if (width < 0 || height < 0)
1145     gdk_drawable_get_size (drawable,
1146                            width < 0 ? &width : NULL,
1147                            height < 0 ? &height : NULL);
1148 
1149   composite =
1150     GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
1151                                                                src_x, src_y,
1152                                                                width, height,
1153                                                                &composite_x_offset,
1154                                                                &composite_y_offset);
1155 
1156   retval = GDK_DRAWABLE_GET_CLASS (composite)->_copy_to_image (composite,
1157 							       image,
1158 							       src_x - composite_x_offset,
1159 							       src_y - composite_y_offset,
1160 							       dest_x, dest_y,
1161 							       width, height);
1162 
1163   g_object_unref (composite);
1164 
1165   if (!image && retval)
1166     {
1167       cmap = gdk_drawable_get_colormap (drawable);
1168 
1169       if (cmap)
1170 	gdk_image_set_colormap (retval, cmap);
1171     }
1172 
1173   return retval;
1174 }
1175 
1176 /**
1177  * gdk_drawable_get_image:
1178  * @drawable: a #GdkDrawable
1179  * @x: x coordinate on @drawable
1180  * @y: y coordinate on @drawable
1181  * @width: width of region to get
1182  * @height: height or region to get
1183  *
1184  * A #GdkImage stores client-side image data (pixels). In contrast,
1185  * #GdkPixmap and #GdkWindow are server-side
1186  * objects. gdk_drawable_get_image() obtains the pixels from a
1187  * server-side drawable as a client-side #GdkImage.  The format of a
1188  * #GdkImage depends on the #GdkVisual of the current display, which
1189  * makes manipulating #GdkImage extremely difficult; therefore, in
1190  * most cases you should use gdk_pixbuf_get_from_drawable() instead of
1191  * this lower-level function. A #GdkPixbuf contains image data in a
1192  * canonicalized RGB format, rather than a display-dependent format.
1193  * Of course, there's a convenience vs. speed tradeoff here, so you'll
1194  * want to think about what makes sense for your application.
1195  *
1196  * @x, @y, @width, and @height define the region of @drawable to
1197  * obtain as an image.
1198  *
1199  * You would usually copy image data to the client side if you intend
1200  * to examine the values of individual pixels, for example to darken
1201  * an image or add a red tint. It would be prohibitively slow to
1202  * make a round-trip request to the windowing system for each pixel,
1203  * so instead you get all of them at once, modify them, then copy
1204  * them all back at once.
1205  *
1206  * If the X server or other windowing system backend is on the local
1207  * machine, this function may use shared memory to avoid copying
1208  * the image data.
1209  *
1210  * If the source drawable is a #GdkWindow and partially offscreen
1211  * or obscured, then the obscured portions of the returned image
1212  * will contain undefined data.
1213  *
1214  * Return value: a #GdkImage containing the contents of @drawable
1215  *
1216  * Deprecated: 2.22: Use @drawable as the source and draw to a Cairo image
1217  * surface if you want to download contents to the client.
1218  **/
1219 GdkImage*
gdk_drawable_get_image(GdkDrawable * drawable,gint x,gint y,gint width,gint height)1220 gdk_drawable_get_image (GdkDrawable *drawable,
1221                         gint         x,
1222                         gint         y,
1223                         gint         width,
1224                         gint         height)
1225 {
1226   GdkDrawable *composite;
1227   gint composite_x_offset = 0;
1228   gint composite_y_offset = 0;
1229   GdkImage *retval;
1230   GdkColormap *cmap;
1231 
1232   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1233   g_return_val_if_fail (x >= 0, NULL);
1234   g_return_val_if_fail (y >= 0, NULL);
1235 
1236   /* FIXME? Note race condition since we get the size then
1237    * get the image, and the size may have changed.
1238    */
1239 
1240   if (width < 0 || height < 0)
1241     gdk_drawable_get_size (drawable,
1242                            width < 0 ? &width : NULL,
1243                            height < 0 ? &height : NULL);
1244 
1245   composite =
1246     GDK_DRAWABLE_GET_CLASS (drawable)->get_composite_drawable (drawable,
1247                                                                x, y,
1248                                                                width, height,
1249                                                                &composite_x_offset,
1250                                                                &composite_y_offset);
1251 
1252   retval = GDK_DRAWABLE_GET_CLASS (composite)->get_image (composite,
1253                                                           x - composite_x_offset,
1254                                                           y - composite_y_offset,
1255                                                           width, height);
1256 
1257   g_object_unref (composite);
1258 
1259   cmap = gdk_drawable_get_colormap (drawable);
1260 
1261   if (retval && cmap)
1262     gdk_image_set_colormap (retval, cmap);
1263 
1264   return retval;
1265 }
1266 
1267 static GdkImage*
gdk_drawable_real_get_image(GdkDrawable * drawable,gint x,gint y,gint width,gint height)1268 gdk_drawable_real_get_image (GdkDrawable     *drawable,
1269 			     gint             x,
1270 			     gint             y,
1271 			     gint             width,
1272 			     gint             height)
1273 {
1274   return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
1275 }
1276 
1277 static GdkDrawable *
gdk_drawable_real_get_composite_drawable(GdkDrawable * drawable,gint x,gint y,gint width,gint height,gint * composite_x_offset,gint * composite_y_offset)1278 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
1279                                           gint         x,
1280                                           gint         y,
1281                                           gint         width,
1282                                           gint         height,
1283                                           gint        *composite_x_offset,
1284                                           gint        *composite_y_offset)
1285 {
1286   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1287 
1288   *composite_x_offset = 0;
1289   *composite_y_offset = 0;
1290 
1291   return g_object_ref (drawable);
1292 }
1293 
1294 /**
1295  * gdk_drawable_get_clip_region:
1296  * @drawable: a #GdkDrawable
1297  *
1298  * Computes the region of a drawable that potentially can be written
1299  * to by drawing primitives. This region will not take into account
1300  * the clip region for the GC, and may also not take into account
1301  * other factors such as if the window is obscured by other windows,
1302  * but no area outside of this region will be affected by drawing
1303  * primitives.
1304  *
1305  * Returns: a #GdkRegion. This must be freed with gdk_region_destroy()
1306  *          when you are done.
1307  **/
1308 GdkRegion *
gdk_drawable_get_clip_region(GdkDrawable * drawable)1309 gdk_drawable_get_clip_region (GdkDrawable *drawable)
1310 {
1311   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1312 
1313   return GDK_DRAWABLE_GET_CLASS (drawable)->get_clip_region (drawable);
1314 }
1315 
1316 /**
1317  * gdk_drawable_get_visible_region:
1318  * @drawable: a #GdkDrawable
1319  *
1320  * Computes the region of a drawable that is potentially visible.
1321  * This does not necessarily take into account if the window is
1322  * obscured by other windows, but no area outside of this region
1323  * is visible.
1324  *
1325  * Returns: a #GdkRegion. This must be freed with gdk_region_destroy()
1326  *          when you are done.
1327  **/
1328 GdkRegion *
gdk_drawable_get_visible_region(GdkDrawable * drawable)1329 gdk_drawable_get_visible_region (GdkDrawable *drawable)
1330 {
1331   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1332 
1333   return GDK_DRAWABLE_GET_CLASS (drawable)->get_visible_region (drawable);
1334 }
1335 
1336 static GdkRegion *
gdk_drawable_real_get_visible_region(GdkDrawable * drawable)1337 gdk_drawable_real_get_visible_region (GdkDrawable *drawable)
1338 {
1339   GdkRectangle rect;
1340 
1341   rect.x = 0;
1342   rect.y = 0;
1343 
1344   gdk_drawable_get_size (drawable, &rect.width, &rect.height);
1345 
1346   return gdk_region_rectangle (&rect);
1347 }
1348 
1349 /**
1350  * _gdk_drawable_ref_cairo_surface:
1351  * @drawable: a #GdkDrawable
1352  *
1353  * Obtains a #cairo_surface_t for the given drawable. If a
1354  * #cairo_surface_t for the drawable already exists, it will be
1355  * referenced, otherwise a new surface will be created.
1356  *
1357  * Return value: a newly referenced #cairo_surface_t that points
1358  *  to @drawable. Unref with cairo_surface_destroy()
1359  **/
1360 cairo_surface_t *
_gdk_drawable_ref_cairo_surface(GdkDrawable * drawable)1361 _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
1362 {
1363   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1364 
1365   return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
1366 }
1367 
1368 static void
composite(guchar * src_buf,gint src_rowstride,guchar * dest_buf,gint dest_rowstride,gint width,gint height)1369 composite (guchar *src_buf,
1370 	   gint    src_rowstride,
1371 	   guchar *dest_buf,
1372 	   gint    dest_rowstride,
1373 	   gint    width,
1374 	   gint    height)
1375 {
1376   guchar *src = src_buf;
1377   guchar *dest = dest_buf;
1378 
1379   while (height--)
1380     {
1381       gint twidth = width;
1382       guchar *p = src;
1383       guchar *q = dest;
1384 
1385       while (twidth--)
1386 	{
1387 	  guchar a = p[3];
1388 	  guint t;
1389 
1390 	  t = a * p[0] + (255 - a) * q[0] + 0x80;
1391 	  q[0] = (t + (t >> 8)) >> 8;
1392 	  t = a * p[1] + (255 - a) * q[1] + 0x80;
1393 	  q[1] = (t + (t >> 8)) >> 8;
1394 	  t = a * p[2] + (255 - a) * q[2] + 0x80;
1395 	  q[2] = (t + (t >> 8)) >> 8;
1396 
1397 	  p += 4;
1398 	  q += 3;
1399 	}
1400 
1401       src += src_rowstride;
1402       dest += dest_rowstride;
1403     }
1404 }
1405 
1406 static void
composite_0888(guchar * src_buf,gint src_rowstride,guchar * dest_buf,gint dest_rowstride,GdkByteOrder dest_byte_order,gint width,gint height)1407 composite_0888 (guchar      *src_buf,
1408 		gint         src_rowstride,
1409 		guchar      *dest_buf,
1410 		gint         dest_rowstride,
1411 		GdkByteOrder dest_byte_order,
1412 		gint         width,
1413 		gint         height)
1414 {
1415   guchar *src = src_buf;
1416   guchar *dest = dest_buf;
1417 
1418   while (height--)
1419     {
1420       gint twidth = width;
1421       guchar *p = src;
1422       guchar *q = dest;
1423 
1424       if (dest_byte_order == GDK_LSB_FIRST)
1425 	{
1426 	  while (twidth--)
1427 	    {
1428 	      guint t;
1429 
1430 	      t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
1431 	      q[0] = (t + (t >> 8)) >> 8;
1432 	      t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
1433 	      q[1] = (t + (t >> 8)) >> 8;
1434 	      t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
1435 	      q[2] = (t + (t >> 8)) >> 8;
1436 	      p += 4;
1437 	      q += 4;
1438 	    }
1439 	}
1440       else
1441 	{
1442 	  while (twidth--)
1443 	    {
1444 	      guint t;
1445 
1446 	      t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
1447 	      q[1] = (t + (t >> 8)) >> 8;
1448 	      t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
1449 	      q[2] = (t + (t >> 8)) >> 8;
1450 	      t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
1451 	      q[3] = (t + (t >> 8)) >> 8;
1452 	      p += 4;
1453 	      q += 4;
1454 	    }
1455 	}
1456 
1457       src += src_rowstride;
1458       dest += dest_rowstride;
1459     }
1460 }
1461 
1462 #ifdef USE_MEDIALIB
1463 static void
composite_0888_medialib(guchar * src_buf,gint src_rowstride,guchar * dest_buf,gint dest_rowstride,GdkByteOrder dest_byte_order,gint width,gint height)1464 composite_0888_medialib (guchar      *src_buf,
1465 			 gint         src_rowstride,
1466 			 guchar      *dest_buf,
1467 			 gint         dest_rowstride,
1468 			 GdkByteOrder dest_byte_order,
1469 			 gint         width,
1470 			 gint         height)
1471 {
1472   guchar *src  = src_buf;
1473   guchar *dest = dest_buf;
1474 
1475   mlib_image img_src, img_dst;
1476 
1477   mlib_ImageSetStruct (&img_dst,
1478                        MLIB_BYTE,
1479                        4,
1480                        width,
1481                        height,
1482                        dest_rowstride,
1483                        dest_buf);
1484 
1485   mlib_ImageSetStruct (&img_src,
1486                        MLIB_BYTE,
1487                        4,
1488                        width,
1489                        height,
1490                        src_rowstride,
1491                        src_buf);
1492 
1493   if (dest_byte_order == GDK_LSB_FIRST)
1494       mlib_ImageBlendRGBA2BGRA (&img_dst, &img_src);
1495   else
1496       mlib_ImageBlendRGBA2ARGB (&img_dst, &img_src);
1497 }
1498 #endif
1499 
1500 static void
composite_565(guchar * src_buf,gint src_rowstride,guchar * dest_buf,gint dest_rowstride,GdkByteOrder dest_byte_order,gint width,gint height)1501 composite_565 (guchar      *src_buf,
1502 	       gint         src_rowstride,
1503 	       guchar      *dest_buf,
1504 	       gint         dest_rowstride,
1505 	       GdkByteOrder dest_byte_order,
1506 	       gint         width,
1507 	       gint         height)
1508 {
1509   guchar *src = src_buf;
1510   guchar *dest = dest_buf;
1511 
1512   while (height--)
1513     {
1514       gint twidth = width;
1515       guchar *p = src;
1516       gushort *q = (gushort *)dest;
1517 
1518       while (twidth--)
1519 	{
1520 	  guchar a = p[3];
1521 	  guint tr, tg, tb;
1522 	  guint tr1, tg1, tb1;
1523 	  guint tmp = *q;
1524 
1525 #if 1
1526 	  /* This is fast, and corresponds to what composite() above does
1527 	   * if we converted to 8-bit first.
1528 	   */
1529 	  tr = (tmp & 0xf800);
1530 	  tr1 = a * p[0] + (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1531 	  tg = (tmp & 0x07e0);
1532 	  tg1 = a * p[1] + (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1533 	  tb = (tmp & 0x001f);
1534 	  tb1 = a * p[2] + (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1535 
1536 	  *q = (((tr1 + (tr1 >> 8)) & 0xf800) |
1537 		(((tg1 + (tg1 >> 8)) & 0xfc00) >> 5)  |
1538 		((tb1 + (tb1 >> 8)) >> 11));
1539 #else
1540 	  /* This version correspond to the result we get with XRENDER -
1541 	   * a bit of precision is lost since we convert to 8 bit after premultiplying
1542 	   * instead of at the end
1543 	   */
1544 	  guint tr2, tg2, tb2;
1545 	  guint tr3, tg3, tb3;
1546 
1547 	  tr = (tmp & 0xf800);
1548 	  tr1 = (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
1549 	  tr2 = a * p[0] + 0x80;
1550 	  tr3 = ((tr1 + (tr1 >> 8)) >> 8) + ((tr2 + (tr2 >> 8)) >> 8);
1551 
1552 	  tg = (tmp & 0x07e0);
1553 	  tg1 = (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
1554 	  tg2 = a * p[0] + 0x80;
1555 	  tg3 = ((tg1 + (tg1 >> 8)) >> 8) + ((tg2 + (tg2 >> 8)) >> 8);
1556 
1557 	  tb = (tmp & 0x001f);
1558 	  tb1 = (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
1559 	  tb2 = a * p[0] + 0x80;
1560 	  tb3 = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
1561 
1562 	  *q = (((tr3 & 0xf8) << 8) |
1563 		((tg3 & 0xfc) << 3) |
1564 		((tb3 >> 3)));
1565 #endif
1566 
1567 	  p += 4;
1568 	  q++;
1569 	}
1570 
1571       src += src_rowstride;
1572       dest += dest_rowstride;
1573     }
1574 }
1575 
1576 /* Implementation of the old vfunc in terms of the new one
1577    in case someone calls it directly (which they shouldn't!) */
1578 static void
gdk_drawable_real_draw_drawable(GdkDrawable * drawable,GdkGC * gc,GdkDrawable * src,gint xsrc,gint ysrc,gint xdest,gint ydest,gint width,gint height)1579 gdk_drawable_real_draw_drawable (GdkDrawable  *drawable,
1580 				 GdkGC	       *gc,
1581 				 GdkDrawable  *src,
1582 				 gint		xsrc,
1583 				 gint		ysrc,
1584 				 gint		xdest,
1585 				 gint		ydest,
1586 				 gint		width,
1587 				 gint		height)
1588 {
1589   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable_with_src (drawable,
1590 							     gc,
1591 							     src,
1592 							     xsrc,
1593 							     ysrc,
1594 							     xdest,
1595 							     ydest,
1596 							     width,
1597 							     height,
1598 							     src);
1599 }
1600 
1601 static void
gdk_drawable_real_draw_pixbuf(GdkDrawable * drawable,GdkGC * gc,GdkPixbuf * pixbuf,gint src_x,gint src_y,gint dest_x,gint dest_y,gint width,gint height,GdkRgbDither dither,gint x_dither,gint y_dither)1602 gdk_drawable_real_draw_pixbuf (GdkDrawable  *drawable,
1603 			       GdkGC        *gc,
1604 			       GdkPixbuf    *pixbuf,
1605 			       gint          src_x,
1606 			       gint          src_y,
1607 			       gint          dest_x,
1608 			       gint          dest_y,
1609 			       gint          width,
1610 			       gint          height,
1611 			       GdkRgbDither  dither,
1612 			       gint          x_dither,
1613 			       gint          y_dither)
1614 {
1615   GdkPixbuf *composited = NULL;
1616   gint dwidth, dheight;
1617   GdkRegion *clip;
1618   GdkRegion *drect;
1619   GdkRectangle tmp_rect;
1620   GdkDrawable  *real_drawable;
1621 
1622   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1623   g_return_if_fail (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
1624   g_return_if_fail (gdk_pixbuf_get_n_channels (pixbuf) == 3 ||
1625                     gdk_pixbuf_get_n_channels (pixbuf) == 4);
1626   g_return_if_fail (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
1627 
1628   g_return_if_fail (drawable != NULL);
1629 
1630   if (width == -1)
1631     width = gdk_pixbuf_get_width (pixbuf);
1632   if (height == -1)
1633     height = gdk_pixbuf_get_height (pixbuf);
1634 
1635   g_return_if_fail (width >= 0 && height >= 0);
1636   g_return_if_fail (src_x >= 0 && src_x + width <= gdk_pixbuf_get_width (pixbuf));
1637   g_return_if_fail (src_y >= 0 && src_y + height <= gdk_pixbuf_get_height (pixbuf));
1638 
1639   /* Clip to the drawable; this is required for get_from_drawable() so
1640    * can't be done implicitly
1641    */
1642 
1643   if (dest_x < 0)
1644     {
1645       src_x -= dest_x;
1646       width += dest_x;
1647       dest_x = 0;
1648     }
1649 
1650   if (dest_y < 0)
1651     {
1652       src_y -= dest_y;
1653       height += dest_y;
1654       dest_y = 0;
1655     }
1656 
1657   gdk_drawable_get_size (drawable, &dwidth, &dheight);
1658 
1659   if ((dest_x + width) > dwidth)
1660     width = dwidth - dest_x;
1661 
1662   if ((dest_y + height) > dheight)
1663     height = dheight - dest_y;
1664 
1665   if (width <= 0 || height <= 0)
1666     return;
1667 
1668   /* Clip to the clip region; this avoids getting more
1669    * image data from the server than we need to.
1670    */
1671 
1672   tmp_rect.x = dest_x;
1673   tmp_rect.y = dest_y;
1674   tmp_rect.width = width;
1675   tmp_rect.height = height;
1676 
1677   drect = gdk_region_rectangle (&tmp_rect);
1678   clip = gdk_drawable_get_clip_region (drawable);
1679 
1680   gdk_region_intersect (drect, clip);
1681 
1682   gdk_region_get_clipbox (drect, &tmp_rect);
1683 
1684   gdk_region_destroy (drect);
1685   gdk_region_destroy (clip);
1686 
1687   if (tmp_rect.width == 0 ||
1688       tmp_rect.height == 0)
1689     return;
1690 
1691   /* Actually draw */
1692   if (!gc)
1693     gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
1694 
1695   /* Drawable is a wrapper here, but at this time we
1696      have already retargeted the destination to any
1697      impl window and set the clip, so what we really
1698      want to do is draw directly on the impl, ignoring
1699      client side subwindows. We also use the impl
1700      in the pixmap target case to avoid resetting the
1701      already set clip on the GC. */
1702   if (GDK_IS_WINDOW (drawable))
1703     real_drawable = GDK_WINDOW_OBJECT (drawable)->impl;
1704   else
1705     real_drawable = GDK_PIXMAP_OBJECT (drawable)->impl;
1706 
1707   if (gdk_pixbuf_get_has_alpha (pixbuf))
1708     {
1709       GdkVisual *visual = gdk_drawable_get_visual (drawable);
1710       void (*composite_func) (guchar       *src_buf,
1711 			      gint          src_rowstride,
1712 			      guchar       *dest_buf,
1713 			      gint          dest_rowstride,
1714 			      GdkByteOrder  dest_byte_order,
1715 			      gint          width,
1716 			      gint          height) = NULL;
1717 
1718       /* First we see if we have a visual-specific composition function that can composite
1719        * the pixbuf data directly onto the image
1720        */
1721       if (visual)
1722 	{
1723 	  gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
1724 								   visual->depth);
1725 
1726 	  if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
1727 	      visual->depth == 16 &&
1728 	      visual->red_mask   == 0xf800 &&
1729 	      visual->green_mask == 0x07e0 &&
1730 	      visual->blue_mask  == 0x001f)
1731 	    composite_func = composite_565;
1732 	  else if (visual->depth == 24 && bits_per_pixel == 32 &&
1733 		   visual->red_mask   == 0xff0000 &&
1734 		   visual->green_mask == 0x00ff00 &&
1735 		   visual->blue_mask  == 0x0000ff)
1736 	    {
1737 #ifdef USE_MEDIALIB
1738 	      if (_gdk_use_medialib ())
1739 	        composite_func = composite_0888_medialib;
1740 	      else
1741 	        composite_func = composite_0888;
1742 #else
1743 	      composite_func = composite_0888;
1744 #endif
1745 	    }
1746 	}
1747 
1748       /* We can't use our composite func if we are required to dither
1749        */
1750       if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
1751 	{
1752 	  gint x0, y0;
1753 	  for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1754 	    {
1755 	      gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1756 	      for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1757 		{
1758 		  gint xs0, ys0;
1759 
1760 		  gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1761 
1762 		  GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
1763 							    width1, height1,
1764 							    gdk_drawable_get_depth (drawable), &xs0, &ys0);
1765 
1766 		  gdk_drawable_copy_to_image (drawable, image,
1767 					      dest_x + x0, dest_y + y0,
1768 					      xs0, ys0,
1769 					      width1, height1);
1770 		  (*composite_func) (gdk_pixbuf_get_pixels (pixbuf) + (src_y + y0) * gdk_pixbuf_get_rowstride (pixbuf) + (src_x + x0) * 4,
1771 				     gdk_pixbuf_get_rowstride (pixbuf),
1772 				     (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
1773 				     image->bpl,
1774 				     visual->byte_order,
1775 				     width1, height1);
1776 		  gdk_draw_image (real_drawable, gc, image,
1777 				  xs0, ys0,
1778 				  dest_x + x0, dest_y + y0,
1779 				  width1, height1);
1780 		}
1781 	    }
1782 
1783 	  goto out;
1784 	}
1785       else
1786 	{
1787 	  /* No special composition func, convert dest to 24 bit RGB data, composite against
1788 	   * that, and convert back.
1789 	   */
1790 	  composited = gdk_pixbuf_get_from_drawable (NULL,
1791 						     drawable,
1792 						     NULL,
1793 						     dest_x, dest_y,
1794 						     0, 0,
1795 						     width, height);
1796 
1797 	  if (composited)
1798 	    composite (gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4,
1799 		       gdk_pixbuf_get_rowstride (pixbuf),
1800 		       gdk_pixbuf_get_pixels (composited),
1801 		       gdk_pixbuf_get_rowstride (composited),
1802 		       width, height);
1803 	}
1804     }
1805 
1806   if (composited)
1807     {
1808       src_x = 0;
1809       src_y = 0;
1810       pixbuf = composited;
1811     }
1812 
1813   if (gdk_pixbuf_get_n_channels (pixbuf) == 4)
1814     {
1815       guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4;
1816 
1817       gdk_draw_rgb_32_image_dithalign (real_drawable, gc,
1818 				       dest_x, dest_y,
1819 				       width, height,
1820 				       dither,
1821 				       buf, gdk_pixbuf_get_rowstride (pixbuf),
1822 				       x_dither, y_dither);
1823     }
1824   else				/* n_channels == 3 */
1825     {
1826       guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 3;
1827 
1828       gdk_draw_rgb_image_dithalign (real_drawable, gc,
1829 				    dest_x, dest_y,
1830 				    width, height,
1831 				    dither,
1832 				    buf, gdk_pixbuf_get_rowstride (pixbuf),
1833 				    x_dither, y_dither);
1834     }
1835 
1836  out:
1837   if (composited)
1838     g_object_unref (composited);
1839 }
1840 
1841 /************************************************************************/
1842 
1843 /**
1844  * _gdk_drawable_get_scratch_gc:
1845  * @drawable: A #GdkDrawable
1846  * @graphics_exposures: Whether the returned #GdkGC should generate graphics exposures
1847  *
1848  * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
1849  * the standard values for @drawable, except for the graphics_exposures
1850  * field which is determined by the @graphics_exposures parameter.
1851  *
1852  * The foreground color of the returned #GdkGC is undefined. The #GdkGC
1853  * must not be altered in any way, except to change its foreground color.
1854  *
1855  * Return value: A #GdkGC suitable for drawing on @drawable
1856  *
1857  * Since: 2.4
1858  **/
1859 GdkGC *
_gdk_drawable_get_scratch_gc(GdkDrawable * drawable,gboolean graphics_exposures)1860 _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
1861 			      gboolean     graphics_exposures)
1862 {
1863   GdkScreen *screen;
1864   gint depth;
1865 
1866   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1867 
1868   screen = gdk_drawable_get_screen (drawable);
1869 
1870   g_return_val_if_fail (!screen->closed, NULL);
1871 
1872   depth = gdk_drawable_get_depth (drawable) - 1;
1873 
1874   if (graphics_exposures)
1875     {
1876       if (!screen->exposure_gcs[depth])
1877 	{
1878 	  GdkGCValues values;
1879 	  GdkGCValuesMask mask;
1880 
1881 	  values.graphics_exposures = TRUE;
1882 	  mask = GDK_GC_EXPOSURES;
1883 
1884 	  screen->exposure_gcs[depth] =
1885 	    gdk_gc_new_with_values (drawable, &values, mask);
1886 	}
1887 
1888       return screen->exposure_gcs[depth];
1889     }
1890   else
1891     {
1892       if (!screen->normal_gcs[depth])
1893 	{
1894 	  screen->normal_gcs[depth] =
1895 	    gdk_gc_new (drawable);
1896 	}
1897 
1898       return screen->normal_gcs[depth];
1899     }
1900 }
1901 
1902 /**
1903  * _gdk_drawable_get_subwindow_scratch_gc:
1904  * @drawable: A #GdkDrawable
1905  *
1906  * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
1907  * the standard values for @drawable, except for the graphics_exposures
1908  * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
1909  *
1910  * The foreground color of the returned #GdkGC is undefined. The #GdkGC
1911  * must not be altered in any way, except to change its foreground color.
1912  *
1913  * Return value: A #GdkGC suitable for drawing on @drawable
1914  *
1915  * Since: 2.18
1916  **/
1917 GdkGC *
_gdk_drawable_get_subwindow_scratch_gc(GdkDrawable * drawable)1918 _gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
1919 {
1920   GdkScreen *screen;
1921   gint depth;
1922 
1923   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1924 
1925   screen = gdk_drawable_get_screen (drawable);
1926 
1927   g_return_val_if_fail (!screen->closed, NULL);
1928 
1929   depth = gdk_drawable_get_depth (drawable) - 1;
1930 
1931   if (!screen->subwindow_gcs[depth])
1932     {
1933       GdkGCValues values;
1934       GdkGCValuesMask mask;
1935 
1936       values.graphics_exposures = TRUE;
1937       values.subwindow_mode = GDK_INCLUDE_INFERIORS;
1938       mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;
1939 
1940       screen->subwindow_gcs[depth] =
1941 	gdk_gc_new_with_values (drawable, &values, mask);
1942     }
1943 
1944   return screen->subwindow_gcs[depth];
1945 }
1946 
1947 
1948 /*
1949  * _gdk_drawable_get_source_drawable:
1950  * @drawable: a #GdkDrawable
1951  *
1952  * Returns a drawable for the passed @drawable that is guaranteed to be
1953  * usable to create a pixmap (e.g.: not an offscreen window).
1954  *
1955  * Since: 2.16
1956  */
1957 GdkDrawable *
_gdk_drawable_get_source_drawable(GdkDrawable * drawable)1958 _gdk_drawable_get_source_drawable (GdkDrawable *drawable)
1959 {
1960   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1961 
1962   if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
1963     return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
1964 
1965   return drawable;
1966 }
1967 
1968 cairo_surface_t *
_gdk_drawable_create_cairo_surface(GdkDrawable * drawable,int width,int height)1969 _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
1970 				    int width,
1971 				    int height)
1972 {
1973   return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,
1974 								  width, height);
1975 }
1976 
1977 
1978 #define __GDK_DRAW_C__
1979 #include "gdkaliasdef.c"
1980