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