1
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3
#define _GNU_SOURCE /* For M_PI */
7
#include "compositor-private.h"
9
#include "tidy/tidy-texture-frame.h"
11
#define SHADOW_RADIUS 8
12
#define SHADOW_OPACITY 0.9
13
#define SHADOW_OFFSET_X (SHADOW_RADIUS)
14
#define SHADOW_OFFSET_Y (SHADOW_RADIUS)
16
#define MAX_TILE_SZ 8 /* Must be <= shaddow radius */
17
#define TILE_WIDTH (3*MAX_TILE_SZ)
18
#define TILE_HEIGHT (3*MAX_TILE_SZ)
20
static unsigned char* shadow_gaussian_make_tile (void);
23
meta_create_shadow_frame (MetaCompositor *compositor)
27
if (!compositor->shadow_src)
31
data = shadow_gaussian_make_tile ();
33
compositor->shadow_src = clutter_texture_new ();
35
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
47
frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
53
clutter_actor_set_position (frame,
54
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
59
typedef struct GaussianMap
66
gaussian (double r, double x, double y)
68
return ((1 / (sqrt (2 * M_PI * r))) *
69
exp ((- (x * x + y * y)) / (2 * r * r)));
74
make_gaussian_map (double r)
77
int size = ((int) ceil ((r * 3)) + 1) & ~1;
78
int center = size / 2;
83
c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
86
c->data = (double *) (c + 1);
88
for (y = 0; y < size; y++)
89
for (x = 0; x < size; x++)
91
g = gaussian (r, (double) (x - center), (double) (y - center));
93
c->data[y * size + x] = g;
96
for (y = 0; y < size; y++)
97
for (x = 0; x < size; x++)
98
c->data[y*size + x] /= t;
104
sum_gaussian (GaussianMap * map, double opacity,
105
int x, int y, int width, int height)
109
double * g_line = map->data;
110
int g_size = map->size;
111
int center = g_size / 2;
112
int fx_start, fx_end;
113
int fy_start, fy_end;
118
* Compute set of filter values which are "in range",
119
* that's the set with:
120
* 0 <= x + (fx-center) && x + (fx-center) < width &&
121
* 0 <= y + (fy-center) && y + (fy-center) < height
123
* 0 <= x + (fx - center) x + fx - center < width
124
* center - x <= fx fx < width + center - x
127
fx_start = center - x;
130
fx_end = width + center - x;
134
fy_start = center - y;
137
fy_end = height + center - y;
141
g_line = g_line + fy_start * g_size + fx_start;
144
for (fy = fy_start; fy < fy_end; fy++)
149
for (fx = fx_start; fx < fx_end; fx++)
155
v *= (opacity * 255.0);
157
r = (unsigned int) v;
159
return (unsigned char) r;
162
static unsigned char *
163
shadow_gaussian_make_tile ()
165
unsigned char * data;
171
double opacity = SHADOW_OPACITY;
172
static GaussianMap * gaussian_map = NULL;
185
make_gaussian_map (SHADOW_RADIUS);
187
size = gaussian_map->size;
192
pwidth = MAX_TILE_SZ;
193
pheight = MAX_TILE_SZ;
195
data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
197
_d = (struct _mypixel*) data;
200
for (y = 0; y < pheight; y++)
202
d = sum_gaussian (gaussian_map, opacity,
204
TILE_WIDTH, TILE_HEIGHT);
205
for (x = 0; x < pwidth; x++)
207
_d[y*3*pwidth + x + pwidth].r = 0;
208
_d[y*3*pwidth + x + pwidth].g = 0;
209
_d[y*3*pwidth + x + pwidth].b = 0;
210
_d[y*3*pwidth + x + pwidth].a = d;
216
pwidth = MAX_TILE_SZ;
217
pheight = MAX_TILE_SZ;
219
for (y = 0; y < pheight; y++)
221
d = sum_gaussian (gaussian_map, opacity,
223
TILE_WIDTH, TILE_HEIGHT);
224
for (x = 0; x < pwidth; x++)
226
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].r = 0;
227
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].g = 0;
228
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].b = 0;
229
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].a = d;
236
pwidth = MAX_TILE_SZ;
237
pheight = MAX_TILE_SZ;
239
for (x = 0; x < pwidth; x++)
241
d = sum_gaussian (gaussian_map, opacity,
243
TILE_WIDTH, TILE_HEIGHT);
244
for (y = 0; y < pheight; y++)
246
_d[y*3*pwidth + 3*pwidth*pheight + x].r = 0;
247
_d[y*3*pwidth + 3*pwidth*pheight + x].g = 0;
248
_d[y*3*pwidth + 3*pwidth*pheight + x].b = 0;
249
_d[y*3*pwidth + 3*pwidth*pheight + x].a = d;
255
for (x = 0; x < pwidth; x++)
257
d = sum_gaussian (gaussian_map, opacity,
259
TILE_WIDTH, TILE_HEIGHT);
260
for (y = 0; y < pheight; y++)
262
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].r = 0;
263
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].g = 0;
264
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].b = 0;
265
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].a = d;
271
pwidth = MAX_TILE_SZ;
272
pheight = MAX_TILE_SZ;
274
for (x = 0; x < pwidth; x++)
275
for (y = 0; y < pheight; y++)
277
d = sum_gaussian (gaussian_map, opacity,
279
TILE_WIDTH, TILE_HEIGHT);
281
_d[y*3*pwidth + x].r = 0;
282
_d[y*3*pwidth + x].g = 0;
283
_d[y*3*pwidth + x].b = 0;
284
_d[y*3*pwidth + x].a = d;
288
for (x = 0; x < pwidth; x++)
289
for (y = 0; y < pheight; y++)
291
d = sum_gaussian (gaussian_map, opacity,
293
TILE_WIDTH, TILE_HEIGHT);
295
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].r = 0;
296
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].g = 0;
297
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].b = 0;
298
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].a = d;
302
for (x = 0; x < pwidth; x++)
303
for (y = 0; y < pheight; y++)
305
d = sum_gaussian (gaussian_map, opacity,
307
TILE_WIDTH, TILE_HEIGHT);
309
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
311
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
313
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
315
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
320
for (x = 0; x < pwidth; x++)
321
for (y = 0; y < pheight; y++)
323
d = sum_gaussian (gaussian_map, opacity,
325
TILE_WIDTH, TILE_HEIGHT);
327
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].r = 0;
328
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].g = 0;
329
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].b = 0;
330
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].a = d;
334
pwidth = MAX_TILE_SZ;
335
pheight = MAX_TILE_SZ;
337
d = sum_gaussian (gaussian_map, opacity,
338
center, center, TILE_WIDTH, TILE_HEIGHT);
340
for (x = 0; x < pwidth; x++)
341
for (y = 0; y < pheight; y++)
343
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].r = 0;
344
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].g = 0;
345
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].b = 0;
346
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].a = 0;