]> www.fi.muni.cz Git - evince.git/blob - shell/ev-utils.c
38281f6d0f33e4b0ef8adb875e4489641df44d55
[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
26 #include <string.h>
27 #include <math.h>
28
29 #define PRINT_CONFIG_FILENAME   "ev-print-config.xml"
30
31 typedef struct
32 {
33   int size;
34   double *data;
35 } ConvFilter;
36
37 static double
38 gaussian (double x, double y, double r)
39 {
40     return ((1 / (2 * M_PI * r)) *
41             exp ((- (x * x + y * y)) / (2 * r * r)));
42 }
43
44 static ConvFilter *
45 create_blur_filter (int radius)
46 {
47   ConvFilter *filter;
48   int x, y;
49   double sum;
50   
51   filter = g_new0 (ConvFilter, 1);
52   filter->size = radius * 2 + 1;
53   filter->data = g_new (double, filter->size * filter->size);
54
55   sum = 0.0;
56   
57   for (y = 0 ; y < filter->size; y++)
58     {
59       for (x = 0 ; x < filter->size; x++)
60         {
61           sum += filter->data[y * filter->size + x] = gaussian (x - (filter->size >> 1),
62                                                                 y - (filter->size >> 1),
63                                                                 radius);
64         }
65     }
66
67   for (y = 0; y < filter->size; y++)
68     {
69       for (x = 0; x < filter->size; x++)
70         {
71           filter->data[y * filter->size + x] /= sum;
72         }
73     }
74
75   return filter;
76   
77 }
78
79 static GdkPixbuf *
80 create_shadow (GdkPixbuf *src, int blur_radius,
81                int x_offset, int y_offset, double opacity)
82 {
83   int x, y, i, j;
84   int width, height;
85   GdkPixbuf *dest;
86   static ConvFilter *filter = NULL;
87   int src_rowstride, dest_rowstride;
88   int src_bpp, dest_bpp;
89   
90   guchar *src_pixels, *dest_pixels;
91
92   if (!filter)
93     filter = create_blur_filter (blur_radius);
94
95   if (x_offset < 0)
96           x_offset = (blur_radius * 4) / 5;
97   
98   if (y_offset < 0)
99           y_offset = (blur_radius * 4) / 5;
100
101   
102   width = gdk_pixbuf_get_width (src) + blur_radius * 2 + x_offset;
103   height = gdk_pixbuf_get_height (src) + blur_radius * 2 + y_offset;
104
105   dest = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src), TRUE,
106                          gdk_pixbuf_get_bits_per_sample (src),
107                          width, height);
108   gdk_pixbuf_fill (dest, 0);  
109   src_pixels = gdk_pixbuf_get_pixels (src);
110   src_rowstride = gdk_pixbuf_get_rowstride (src);
111   src_bpp = gdk_pixbuf_get_has_alpha (src) ? 4 : 3;
112   
113   dest_pixels = gdk_pixbuf_get_pixels (dest);
114   dest_rowstride = gdk_pixbuf_get_rowstride (dest);
115   dest_bpp = gdk_pixbuf_get_has_alpha (dest) ? 4 : 3;
116   
117   for (y = 0; y < height; y++)
118     {
119       for (x = 0; x < width; x++)
120         {
121           int sumr = 0, sumg = 0, sumb = 0, suma = 0;
122
123           for (i = 0; i < filter->size; i++)
124             {
125               for (j = 0; j < filter->size; j++)
126                 {
127                   int src_x, src_y;
128
129                   src_y = -(blur_radius + x_offset) + y - (filter->size >> 1) + i;
130                   src_x = -(blur_radius + y_offset) + x - (filter->size >> 1) + j;
131
132                   if (src_y < 0 || src_y > gdk_pixbuf_get_height (src) ||
133                       src_x < 0 || src_x > gdk_pixbuf_get_width (src))
134                     continue;
135
136                   sumr += src_pixels [src_y * src_rowstride +
137                                       src_x * src_bpp + 0] *
138                     filter->data [i * filter->size + j];
139                   sumg += src_pixels [src_y * src_rowstride +
140                                       src_x * src_bpp + 1] * 
141                     filter->data [i * filter->size + j];
142
143                   sumb += src_pixels [src_y * src_rowstride +
144                                       src_x * src_bpp + 2] * 
145                     filter->data [i * filter->size + j];
146                   
147                   if (src_bpp == 4)
148                     suma += src_pixels [src_y * src_rowstride +
149                                         src_x * src_bpp + 3] *
150                     filter->data [i * filter->size + j];
151                   else
152                           suma += 0xff;
153                     
154                 }
155             }
156
157           if (dest_bpp == 4)
158             dest_pixels [y * dest_rowstride +
159                          x * dest_bpp + 3] = (suma * opacity) / (filter->size * filter->size);
160
161         }
162     }
163   
164   return dest;
165 }
166
167 GdkPixbuf *
168 ev_pixbuf_add_shadow (GdkPixbuf *src, int size,
169                       int x_offset, int y_offset, double opacity)
170 {
171   GdkPixbuf *dest;
172   
173   dest = create_shadow (src, size, x_offset, y_offset, opacity);
174
175   gdk_pixbuf_composite (src, dest,
176                         size, size,
177                         gdk_pixbuf_get_width (src),
178                         gdk_pixbuf_get_height (src),
179                         size, size,
180                         1.0, 1.0,
181                         GDK_INTERP_NEAREST, 255);
182
183   return dest;
184 }
185
186
187 /* Simple function to output the contents of a region.  Used solely for testing
188  * the region code.
189  */
190 void
191 ev_print_region_contents (GdkRegion *region)
192 {
193         GdkRectangle *rectangles = NULL;
194         gint n_rectangles, i;
195
196         if (region == NULL) {
197                 g_print ("<empty region>\n");
198                 return;
199         }
200
201         g_print ("<region %p>\n", region);
202         gdk_region_get_rectangles (region, &rectangles, &n_rectangles);
203         for (i = 0; i < n_rectangles; i++) {
204                 g_print ("\t(%d %d, %d %d) [%dx%d]\n",
205                          rectangles[i].x,
206                          rectangles[i].y,
207                          rectangles[i].x + rectangles[i].width,
208                          rectangles[i].y + rectangles[i].height,
209                          rectangles[i].width,
210                          rectangles[i].height);
211         }
212         g_free (rectangles);
213 }
214
215 #ifdef WITH_GNOME_PRINT
216 gboolean
217 using_pdf_printer (GnomePrintConfig *config)
218 {
219         const guchar *driver;
220
221         driver = gnome_print_config_get (
222                 config, (const guchar *)"Settings.Engine.Backend.Driver");
223
224         if (driver) {
225                 if (!strcmp ((const gchar *)driver, "gnome-print-pdf"))
226                         return TRUE;
227                 else
228                         return FALSE;
229         }
230
231         return FALSE;
232 }
233
234 gboolean
235 using_postscript_printer (GnomePrintConfig *config)
236 {
237         const guchar *driver;
238         const guchar *transport;
239
240         driver = gnome_print_config_get (
241                 config, (const guchar *)"Settings.Engine.Backend.Driver");
242
243         transport = gnome_print_config_get (
244                 config, (const guchar *)"Settings.Transport.Backend");
245
246         if (driver) {
247                 if (!strcmp ((const gchar *)driver, "gnome-print-ps"))
248                         return TRUE;
249                 else
250                         return FALSE;
251         } else  if (transport) { /* these transports default to PostScript */
252                 if (!strcmp ((const gchar *)transport, "CUPS"))
253                         return TRUE;
254                 else if (!strcmp ((const gchar *)transport, "LPD"))
255                         return TRUE;
256                 else if (!strcmp ((const gchar *)transport, "PAPI"))
257                         return TRUE;
258         }
259
260         return FALSE;
261 }
262
263 GnomePrintConfig *
264 load_print_config_from_file (void)
265 {
266         GnomePrintConfig *print_config = NULL;
267         char *file_name, *contents = NULL;
268
269         file_name = g_build_filename (ev_dot_dir (), PRINT_CONFIG_FILENAME,
270                                       NULL);
271
272         if (g_file_get_contents (file_name, &contents, NULL, NULL)) {
273                 print_config = gnome_print_config_from_string (contents, 0);
274                 g_free (contents);
275         }
276
277         if (print_config == NULL) {
278                 print_config = gnome_print_config_default ();
279         }
280
281         g_free (file_name);
282
283         return print_config;
284 }
285
286 void
287 save_print_config_to_file (GnomePrintConfig *config)
288 {
289         char *file_name, *str;
290
291         g_return_if_fail (config != NULL);
292
293         str = gnome_print_config_to_string (config, 0);
294         if (str == NULL) return;
295
296         file_name = g_build_filename (ev_dot_dir (),
297                                       PRINT_CONFIG_FILENAME,
298                                       NULL);
299
300         g_file_set_contents (file_name, str, -1, NULL);
301
302         g_free (file_name);
303         g_free (str);
304 }
305 #endif /* WITH_GNOME_PRINT */
306