]> www.fi.muni.cz Git - evince.git/blob - shell/ev-utils.c
Bump requirements to gtk 2.8 and drop all idfefs used.
[evince.git] / shell / ev-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8; c-indent-level: 8 -*- */
2 /*
3  *  Copyright (C) 2004 Anders Carlsson <andersca@gnome.org>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  */
20
21 #include <config.h>
22
23 #include "ev-utils.h"
24 #include "ev-file-helpers.h"
25 #include <math.h>
26
27 #define PRINT_CONFIG_FILENAME   "ev-print-config.xml"
28
29 typedef struct
30 {
31   int size;
32   double *data;
33 } ConvFilter;
34
35 static double
36 gaussian (double x, double y, double r)
37 {
38     return ((1 / (2 * M_PI * r)) *
39             exp ((- (x * x + y * y)) / (2 * r * r)));
40 }
41
42 static ConvFilter *
43 create_blur_filter (int radius)
44 {
45   ConvFilter *filter;
46   int x, y;
47   double sum;
48   
49   filter = g_new0 (ConvFilter, 1);
50   filter->size = radius * 2 + 1;
51   filter->data = g_new (double, filter->size * filter->size);
52
53   sum = 0.0;
54   
55   for (y = 0 ; y < filter->size; y++)
56     {
57       for (x = 0 ; x < filter->size; x++)
58         {
59           sum += filter->data[y * filter->size + x] = gaussian (x - (filter->size >> 1),
60                                                                 y - (filter->size >> 1),
61                                                                 radius);
62         }
63     }
64
65   for (y = 0; y < filter->size; y++)
66     {
67       for (x = 0; x < filter->size; x++)
68         {
69           filter->data[y * filter->size + x] /= sum;
70         }
71     }
72
73   return filter;
74   
75 }
76
77 static GdkPixbuf *
78 create_shadow (GdkPixbuf *src, int blur_radius,
79                int x_offset, int y_offset, double opacity)
80 {
81   int x, y, i, j;
82   int width, height;
83   GdkPixbuf *dest;
84   static ConvFilter *filter = NULL;
85   int src_rowstride, dest_rowstride;
86   int src_bpp, dest_bpp;
87   
88   guchar *src_pixels, *dest_pixels;
89
90   if (!filter)
91     filter = create_blur_filter (blur_radius);
92
93   if (x_offset < 0)
94           x_offset = (blur_radius * 4) / 5;
95   
96   if (y_offset < 0)
97           y_offset = (blur_radius * 4) / 5;
98
99   
100   width = gdk_pixbuf_get_width (src) + blur_radius * 2 + x_offset;
101   height = gdk_pixbuf_get_height (src) + blur_radius * 2 + y_offset;
102
103   dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src), TRUE,
104                          gdk_pixbuf_get_bits_per_sample (src),
105                          width, height);
106   gdk_pixbuf_fill (dest, 0);  
107   src_pixels = gdk_pixbuf_get_pixels (src);
108   src_rowstride = gdk_pixbuf_get_rowstride (src);
109   src_bpp = gdk_pixbuf_get_has_alpha (src) ? 4 : 3;
110   
111   dest_pixels = gdk_pixbuf_get_pixels (dest);
112   dest_rowstride = gdk_pixbuf_get_rowstride (dest);
113   dest_bpp = gdk_pixbuf_get_has_alpha (dest) ? 4 : 3;
114   
115   for (y = 0; y < height; y++)
116     {
117       for (x = 0; x < width; x++)
118         {
119           int sumr = 0, sumg = 0, sumb = 0, suma = 0;
120
121           for (i = 0; i < filter->size; i++)
122             {
123               for (j = 0; j < filter->size; j++)
124                 {
125                   int src_x, src_y;
126
127                   src_y = -(blur_radius + x_offset) + y - (filter->size >> 1) + i;
128                   src_x = -(blur_radius + y_offset) + x - (filter->size >> 1) + j;
129
130                   if (src_y < 0 || src_y > gdk_pixbuf_get_height (src) ||
131                       src_x < 0 || src_x > gdk_pixbuf_get_width (src))
132                     continue;
133
134                   sumr += src_pixels [src_y * src_rowstride +
135                                       src_x * src_bpp + 0] *
136                     filter->data [i * filter->size + j];
137                   sumg += src_pixels [src_y * src_rowstride +
138                                       src_x * src_bpp + 1] * 
139                     filter->data [i * filter->size + j];
140
141                   sumb += src_pixels [src_y * src_rowstride +
142                                       src_x * src_bpp + 2] * 
143                     filter->data [i * filter->size + j];
144                   
145                   if (src_bpp == 4)
146                     suma += src_pixels [src_y * src_rowstride +
147                                         src_x * src_bpp + 3] *
148                     filter->data [i * filter->size + j];
149                   else
150                           suma += 0xff;
151                     
152                 }
153             }
154
155           if (dest_bpp == 4)
156             dest_pixels [y * dest_rowstride +
157                          x * dest_bpp + 3] = (suma * opacity) / (filter->size * filter->size);
158
159         }
160     }
161   
162   return dest;
163 }
164
165 GdkPixbuf *
166 ev_pixbuf_add_shadow (GdkPixbuf *src, int size,
167                       int x_offset, int y_offset, double opacity)
168 {
169   GdkPixbuf *dest;
170   
171   dest = create_shadow (src, size, x_offset, y_offset, opacity);
172
173   gdk_pixbuf_composite (src, dest,
174                         size, size,
175                         gdk_pixbuf_get_width (src),
176                         gdk_pixbuf_get_height (src),
177                         size, size,
178                         1.0, 1.0,
179                         GDK_INTERP_NEAREST, 255);
180
181   return dest;
182 }
183
184
185 /* Simple function to output the contents of a region.  Used solely for testing
186  * the region code.
187  */
188 void
189 ev_print_region_contents (GdkRegion *region)
190 {
191         GdkRectangle *rectangles = NULL;
192         gint n_rectangles, i;
193
194         if (region == NULL) {
195                 g_print ("<empty region>\n");
196                 return;
197         }
198
199         g_print ("<region %p>\n", region);
200         gdk_region_get_rectangles (region, &rectangles, &n_rectangles);
201         for (i = 0; i < n_rectangles; i++) {
202                 g_print ("\t(%d %d, %d %d) [%dx%d]\n",
203                          rectangles[i].x,
204                          rectangles[i].y,
205                          rectangles[i].x + rectangles[i].width,
206                          rectangles[i].y + rectangles[i].height,
207                          rectangles[i].width,
208                          rectangles[i].height);
209         }
210         g_free (rectangles);
211 }
212
213 #ifdef WITH_GNOME_PRINT
214 gboolean
215 using_pdf_printer (GnomePrintConfig *config)
216 {
217         const guchar *driver;
218
219         driver = gnome_print_config_get (
220                 config, (const guchar *)"Settings.Engine.Backend.Driver");
221
222         if (driver) {
223                 if (!strcmp ((const gchar *)driver, "gnome-print-pdf"))
224                         return TRUE;
225                 else
226                         return FALSE;
227         }
228
229         return FALSE;
230 }
231
232 gboolean
233 using_postscript_printer (GnomePrintConfig *config)
234 {
235         const guchar *driver;
236         const guchar *transport;
237
238         driver = gnome_print_config_get (
239                 config, (const guchar *)"Settings.Engine.Backend.Driver");
240
241         transport = gnome_print_config_get (
242                 config, (const guchar *)"Settings.Transport.Backend");
243
244         if (driver) {
245                 if (!strcmp ((const gchar *)driver, "gnome-print-ps"))
246                         return TRUE;
247                 else
248                         return FALSE;
249         } else  if (transport) { /* these transports default to PostScript */
250                 if (!strcmp ((const gchar *)transport, "CUPS"))
251                         return TRUE;
252                 else if (!strcmp ((const gchar *)transport, "LPD"))
253                         return TRUE;
254         }
255
256         return FALSE;
257 }
258
259 GnomePrintConfig *
260 load_print_config_from_file (void)
261 {
262         GnomePrintConfig *print_config = NULL;
263         char *file_name, *contents = NULL;
264
265         file_name = g_build_filename (ev_dot_dir (), PRINT_CONFIG_FILENAME,
266                                       NULL);
267
268         if (g_file_get_contents (file_name, &contents, NULL, NULL)) {
269                 print_config = gnome_print_config_from_string (contents, 0);
270                 g_free (contents);
271         }
272
273         if (print_config == NULL) {
274                 print_config = gnome_print_config_default ();
275         }
276
277         g_free (file_name);
278
279         return print_config;
280 }
281
282 void
283 save_print_config_to_file (GnomePrintConfig *config)
284 {
285         char *file_name, *str;
286
287         g_return_if_fail (config != NULL);
288
289         str = gnome_print_config_to_string (config, 0);
290         if (str == NULL) return;
291
292         file_name = g_build_filename (ev_dot_dir (),
293                                       PRINT_CONFIG_FILENAME,
294                                       NULL);
295
296         g_file_set_contents (file_name, str, -1, NULL);
297
298         g_free (file_name);
299         g_free (str);
300 }
301 #endif /* WITH_GNOME_PRINT */
302