1 ////////////////////////////////////////////////////////////////////////////////
2 //3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
3 //      10        20        30        40        50        60        70        80
4 //
5 // notify-osd
6 //
7 // raico-blur.c - implements public API for blurring cairo image-surfaces
8 //
9 // Copyright 2009 Canonical Ltd.
10 //
11 // Authors:
12 //    Mirco "MacSlow" Mueller <mirco.mueller@canonical.com>
13 //
14 // This program is free software: you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License version 3, as published
16 // by the Free Software Foundation.
17 //
18 // This program is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranties of
20 // MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
21 // PURPOSE.  See the GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with this program.  If not, see <http://www.gnu.org/licenses/>.
25 //
26 ////////////////////////////////////////////////////////////////////////////////
27 
28 #include "raico-blur.h"
29 #include "exponential-blur.h"
30 #include "stack-blur.h"
31 #include "gaussian-blur.h"
32 
33 struct _raico_blur_private_t
34 {
35 	raico_blur_quality_t quality; // low, medium, high
36 	guint                radius;  // blur-radius
37 };
38 
39 raico_blur_t*
raico_blur_create(raico_blur_quality_t quality)40 raico_blur_create (raico_blur_quality_t quality)
41 {
42 	raico_blur_t*         blur = NULL;
43 	raico_blur_private_t* priv = NULL;
44 
45 	blur = g_new0 (raico_blur_t, 1);
46 	if (!blur)
47 	{
48 		g_debug ("raico_blur_create(): could not allocate blur struct");
49 		return NULL;
50 	}
51 
52 	priv = g_new0 (raico_blur_private_t, 1);
53 	if (!priv)
54 	{
55 		g_debug ("raico_blur_create(): could not allocate priv struct");
56 		g_free ((gpointer) blur);
57 		return NULL;
58 	}
59 
60 	priv->quality = quality;
61 	priv->radius  = 0;
62 
63 	blur->priv = priv;
64 
65 	return blur;
66 }
67 
68 raico_blur_quality_t
raico_blur_get_quality(raico_blur_t * blur)69 raico_blur_get_quality (raico_blur_t* blur)
70 {
71 	g_assert (blur != NULL);
72 
73 	return blur->priv->quality;
74 }
75 
76 void
raico_blur_set_quality(raico_blur_t * blur,raico_blur_quality_t quality)77 raico_blur_set_quality (raico_blur_t*        blur,
78 			raico_blur_quality_t quality)
79 {
80 	if (!blur)
81 	{
82 		g_debug ("raico_blur_set_quality(): NULL blur-pointer passed");
83 		return;
84 	}
85 
86 	blur->priv->quality = quality;
87 }
88 
89 guint
raico_blur_get_radius(raico_blur_t * blur)90 raico_blur_get_radius (raico_blur_t* blur)
91 {
92 	g_assert (blur != NULL);
93 
94 	return blur->priv->radius;
95 }
96 
97 void
raico_blur_set_radius(raico_blur_t * blur,guint radius)98 raico_blur_set_radius (raico_blur_t* blur,
99 		       guint         radius)
100 {
101 	if (!blur)
102 	{
103 		g_debug ("raico_blur_set_radius(): NULL blur-pointer passed");
104 		return;
105 	}
106 
107 	blur->priv->radius = radius;
108 }
109 
110 void
raico_blur_apply(raico_blur_t * blur,cairo_surface_t * surface)111 raico_blur_apply (raico_blur_t*    blur,
112 		  cairo_surface_t* surface)
113 {
114 	cairo_format_t format;
115 
116 	// sanity checks
117 	if (!blur)
118 	{
119 		g_debug ("raico_blur_apply(): NULL blur-pointer passed");
120 		return;
121 	}
122 
123 	if (!surface)
124 	{
125 		g_debug ("raico_blur_apply(): NULL surface-pointer passed");
126 		return;
127 	}
128 
129 	if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
130 	{
131 		g_debug ("raico_blur_apply(): invalid surface status");
132 		return;
133 	}
134 
135 	if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE)
136 	{
137 		g_debug ("raico_blur_apply(): non-image surface passed");
138 		return;
139 	}
140 
141 	format = cairo_image_surface_get_format (surface);
142 	if (format != CAIRO_FORMAT_A8 &&
143 	    format != CAIRO_FORMAT_RGB24 &&
144 	    format != CAIRO_FORMAT_ARGB32)
145 	{
146 		g_debug ("raico_blur_apply(): unsupported image-format");
147 		return;
148 	}
149 
150 	// stupid, but you never know
151 	if (blur->priv->radius == 0)
152 		return;
153 
154 	// now do the real work
155 	switch (blur->priv->quality)
156 	{
157 		case RAICO_BLUR_QUALITY_LOW:
158 			surface_exponential_blur (surface, blur->priv->radius);
159 		break;
160 
161 		case RAICO_BLUR_QUALITY_MEDIUM:
162 			//surface_stack_blur (surface, blur->priv->radius);
163 			surface_gaussian_blur (surface, blur->priv->radius);
164 		break;
165 
166 		case RAICO_BLUR_QUALITY_HIGH:
167 			surface_gaussian_blur (surface, blur->priv->radius);
168 		break;
169 	}
170 }
171 
172 void
raico_blur_destroy(raico_blur_t * blur)173 raico_blur_destroy (raico_blur_t* blur)
174 {
175 	if (!blur)
176 	{
177 		g_debug ("raico_blur_destroy(): invalid blur-pointer passed");
178 		return;
179 	}
180 
181 	g_free ((gpointer) blur->priv);
182 	g_free ((gpointer) blur);
183 }
184 
185