]> Pileus Git - ~andy/gtk/blob - gdk/gdkpixbuf-render.c
Remove deprecated code from GdkPixbuf
[~andy/gtk] / gdk / gdkpixbuf-render.c
1 /* GdkPixbuf library - Rendering functions
2  *
3  * Copyright (C) 1999 The Free Software Foundation
4  *
5  * Author: Federico Mena-Quintero <federico@gimp.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "config.h"
24 #include <gdk/gdk.h>
25 #include "gdk-pixbuf-private.h"
26 #include "gdkpixbuf.h"
27 #include "gdkscreen.h"
28 #include "gdkinternals.h"
29 #include "gdkalias.h"
30
31 \f
32
33 /**
34  * gdk_pixbuf_render_threshold_alpha:
35  * @pixbuf: A pixbuf.
36  * @bitmap: Bitmap where the bilevel mask will be painted to.
37  * @src_x: Source X coordinate.
38  * @src_y: source Y coordinate.
39  * @dest_x: Destination X coordinate.
40  * @dest_y: Destination Y coordinate.
41  * @width: Width of region to threshold, or -1 to use pixbuf width
42  * @height: Height of region to threshold, or -1 to use pixbuf height
43  * @alpha_threshold: Opacity values below this will be painted as zero; all
44  * other values will be painted as one.
45  *
46  * Takes the opacity values in a rectangular portion of a pixbuf and thresholds
47  * them to produce a bi-level alpha mask that can be used as a clipping mask for
48  * a drawable.
49  *
50  **/
51 void
52 gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf,
53                                    GdkBitmap *bitmap,
54                                    int src_x,  int src_y,
55                                    int dest_x, int dest_y,
56                                    int width,  int height,
57                                    int alpha_threshold)
58 {
59   GdkGC *gc;
60   GdkColor color;
61   int x, y;
62   guchar *p;
63   int start, start_status;
64   int status;
65
66   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
67   g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
68   g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
69   g_return_if_fail (pixbuf->bits_per_sample == 8);
70
71   if (width == -1) 
72     width = pixbuf->width;
73   if (height == -1)
74     height = pixbuf->height;
75
76   g_return_if_fail (bitmap != NULL);
77   g_return_if_fail (width >= 0 && height >= 0);
78   g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
79   g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
80
81   g_return_if_fail (alpha_threshold >= 0 && alpha_threshold <= 255);
82
83   if (width == 0 || height == 0)
84     return;
85
86   gc = _gdk_drawable_get_scratch_gc (bitmap, FALSE);
87
88   if (!pixbuf->has_alpha)
89     {
90       color.pixel = (alpha_threshold == 255) ? 0 : 1;
91       gdk_gc_set_foreground (gc, &color);
92       gdk_draw_rectangle (bitmap, gc, TRUE, dest_x, dest_y, width, height);
93       return;
94     }
95
96   color.pixel = 0;
97   gdk_gc_set_foreground (gc, &color);
98   gdk_draw_rectangle (bitmap, gc, TRUE, dest_x, dest_y, width, height);
99
100   color.pixel = 1;
101   gdk_gc_set_foreground (gc, &color);
102
103   for (y = 0; y < height; y++)
104     {
105       p = (pixbuf->pixels + (y + src_y) * pixbuf->rowstride + src_x * pixbuf->n_channels
106            + pixbuf->n_channels - 1);
107             
108       start = 0;
109       start_status = *p < alpha_threshold;
110             
111       for (x = 0; x < width; x++)
112         {
113           status = *p < alpha_threshold;
114           
115           if (status != start_status)
116             {
117               if (!start_status)
118                 gdk_draw_line (bitmap, gc,
119                                start + dest_x, y + dest_y,
120                                x - 1 + dest_x, y + dest_y);
121               
122               start = x;
123               start_status = status;
124             }
125           
126           p += pixbuf->n_channels;
127         }
128       
129       if (!start_status)
130         gdk_draw_line (bitmap, gc,
131                        start + dest_x, y + dest_y,
132                        x - 1 + dest_x, y + dest_y);
133     }
134 }
135
136 /**
137  * gdk_pixbuf_render_pixmap_and_mask:
138  * @pixbuf: A pixbuf.
139  * @pixmap_return: Location to store a pointer to the created pixmap,
140  *   or %NULL if the pixmap is not needed.
141  * @mask_return: Location to store a pointer to the created mask,
142  *   or %NULL if the mask is not needed.
143  * @alpha_threshold: Threshold value for opacity values.
144  *
145  * Creates a pixmap and a mask bitmap which are returned in the @pixmap_return
146  * and @mask_return arguments, respectively, and renders a pixbuf and its
147  * corresponding thresholded alpha mask to them.  This is merely a convenience
148  * function; applications that need to render pixbufs with dither offsets or to
149  * given drawables should use gdk_draw_pixbuf() and gdk_pixbuf_render_threshold_alpha().
150  *
151  * The pixmap that is created is created for the colormap returned
152  * by gdk_rgb_get_colormap(). You normally will want to instead use
153  * the actual colormap for a widget, and use
154  * gdk_pixbuf_render_pixmap_and_mask_for_colormap().
155  *
156  * If the pixbuf does not have an alpha channel, then *@mask_return will be set
157  * to %NULL.
158  **/
159 void
160 gdk_pixbuf_render_pixmap_and_mask (GdkPixbuf  *pixbuf,
161                                    GdkPixmap **pixmap_return,
162                                    GdkBitmap **mask_return,
163                                    int         alpha_threshold)
164 {
165   gdk_pixbuf_render_pixmap_and_mask_for_colormap (pixbuf,
166                                                   gdk_rgb_get_colormap (),
167                                                   pixmap_return, mask_return,
168                                                   alpha_threshold);
169 }
170
171 /**
172  * gdk_pixbuf_render_pixmap_and_mask_for_colormap:
173  * @pixbuf: A pixbuf.
174  * @colormap: A #GdkColormap
175  * @pixmap_return: Location to store a pointer to the created pixmap,
176  *   or %NULL if the pixmap is not needed.
177  * @mask_return: Location to store a pointer to the created mask,
178  *   or %NULL if the mask is not needed.
179  * @alpha_threshold: Threshold value for opacity values.
180  *
181  * Creates a pixmap and a mask bitmap which are returned in the @pixmap_return
182  * and @mask_return arguments, respectively, and renders a pixbuf and its
183  * corresponding tresholded alpha mask to them.  This is merely a convenience
184  * function; applications that need to render pixbufs with dither offsets or to
185  * given drawables should use gdk_draw_pixbuf(), and gdk_pixbuf_render_threshold_alpha().
186  *
187  * The pixmap that is created uses the #GdkColormap specified by @colormap.
188  * This colormap must match the colormap of the window where the pixmap
189  * will eventually be used or an error will result.
190  *
191  * If the pixbuf does not have an alpha channel, then *@mask_return will be set
192  * to %NULL.
193  **/
194 void
195 gdk_pixbuf_render_pixmap_and_mask_for_colormap (GdkPixbuf   *pixbuf,
196                                                 GdkColormap *colormap,
197                                                 GdkPixmap  **pixmap_return,
198                                                 GdkBitmap  **mask_return,
199                                                 int          alpha_threshold)
200 {
201   GdkScreen *screen;
202
203   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
204   g_return_if_fail (GDK_IS_COLORMAP (colormap));
205
206   screen = gdk_colormap_get_screen (colormap);
207   
208   if (pixmap_return)
209     {
210       GdkGC *gc;
211       *pixmap_return = gdk_pixmap_new (gdk_screen_get_root_window (screen),
212                                        gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
213                                        gdk_colormap_get_visual (colormap)->depth);
214
215       gdk_drawable_set_colormap (GDK_DRAWABLE (*pixmap_return), colormap);
216       gc = _gdk_drawable_get_scratch_gc (*pixmap_return, FALSE);
217
218       /* If the pixbuf has an alpha channel, using gdk_pixbuf_draw would give
219        * random pixel values in the area that are within the mask, but semi-
220        * transparent. So we treat the pixbuf like a pixbuf without alpha channel;
221        * see bug #487865.
222        */
223       if (gdk_pixbuf_get_has_alpha (pixbuf))
224         gdk_draw_rgb_32_image (*pixmap_return, gc,
225                                0, 0,
226                                gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
227                                GDK_RGB_DITHER_NORMAL,
228                                gdk_pixbuf_get_pixels (pixbuf), gdk_pixbuf_get_rowstride (pixbuf));
229       else
230         gdk_draw_pixbuf (*pixmap_return, gc, pixbuf, 
231                          0, 0, 0, 0,
232                          gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
233                          GDK_RGB_DITHER_NORMAL,
234                          0, 0);
235     }
236   
237   if (mask_return)
238     {
239       if (gdk_pixbuf_get_has_alpha (pixbuf))
240         {
241           *mask_return = gdk_pixmap_new (gdk_screen_get_root_window (screen),
242                                          gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf), 1);
243
244           gdk_pixbuf_render_threshold_alpha (pixbuf, *mask_return,
245                                              0, 0, 0, 0,
246                                              gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf),
247                                              alpha_threshold);
248         }
249       else
250         *mask_return = NULL;
251     }
252 }
253
254 #define __GDK_PIXBUF_RENDER_C__
255 #include "gdkaliasdef.c"
256