~ubuntu-branches/ubuntu/oneiric/mutter/oneiric-201109070806

« back to all changes in this revision

Viewing changes to src/compositor/shadow.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Ancell
  • Date: 2010-11-30 10:56:20 UTC
  • Revision ID: james.westby@ubuntu.com-20101130105620-5pg8qjx4fn4nt00b
Tags: 2.91.3-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
 
 
3
 
#define _GNU_SOURCE /* For M_PI */
4
 
 
5
 
#include <math.h>
6
 
 
7
 
#include "compositor-private.h"
8
 
#include "shadow.h"
9
 
#include "tidy/tidy-texture-frame.h"
10
 
 
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)
15
 
 
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)
19
 
 
20
 
static unsigned char* shadow_gaussian_make_tile (void);
21
 
 
22
 
ClutterActor *
23
 
meta_create_shadow_frame (MetaCompositor *compositor)
24
 
{
25
 
  ClutterActor *frame;
26
 
 
27
 
  if (!compositor->shadow_src)
28
 
    {
29
 
      guchar *data;
30
 
 
31
 
      data = shadow_gaussian_make_tile ();
32
 
 
33
 
      compositor->shadow_src = clutter_texture_new ();
34
 
 
35
 
      clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
36
 
                                         data,
37
 
                                         TRUE,
38
 
                                         TILE_WIDTH,
39
 
                                         TILE_HEIGHT,
40
 
                                         TILE_WIDTH*4,
41
 
                                         4,
42
 
                                         0,
43
 
                                         NULL);
44
 
      g_free (data);
45
 
    }
46
 
 
47
 
  frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
48
 
                                  MAX_TILE_SZ,
49
 
                                  MAX_TILE_SZ,
50
 
                                  MAX_TILE_SZ,
51
 
                                  MAX_TILE_SZ);
52
 
 
53
 
  clutter_actor_set_position (frame,
54
 
                              SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
55
 
 
56
 
  return frame;
57
 
}
58
 
 
59
 
typedef struct GaussianMap
60
 
{
61
 
  int      size;
62
 
  double * data;
63
 
} GaussianMap;
64
 
 
65
 
static double
66
 
gaussian (double r, double x, double y)
67
 
{
68
 
  return ((1 / (sqrt (2 * M_PI * r))) *
69
 
          exp ((- (x * x + y * y)) / (2 * r * r)));
70
 
}
71
 
 
72
 
 
73
 
static GaussianMap *
74
 
make_gaussian_map (double r)
75
 
{
76
 
  GaussianMap  *c;
77
 
  int             size = ((int) ceil ((r * 3)) + 1) & ~1;
78
 
  int             center = size / 2;
79
 
  int             x, y;
80
 
  double          t = 0.0;
81
 
  double          g;
82
 
 
83
 
  c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
84
 
  c->size = size;
85
 
 
86
 
  c->data = (double *) (c + 1);
87
 
 
88
 
  for (y = 0; y < size; y++)
89
 
    for (x = 0; x < size; x++)
90
 
      {
91
 
        g = gaussian (r, (double) (x - center), (double) (y - center));
92
 
        t += g;
93
 
        c->data[y * size + x] = g;
94
 
      }
95
 
 
96
 
  for (y = 0; y < size; y++)
97
 
    for (x = 0; x < size; x++)
98
 
      c->data[y*size + x] /= t;
99
 
 
100
 
  return c;
101
 
}
102
 
 
103
 
static unsigned char
104
 
sum_gaussian (GaussianMap * map, double opacity,
105
 
              int x, int y, int width, int height)
106
 
{
107
 
  int              fx, fy;
108
 
  double         * g_data;
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;
114
 
  double           v;
115
 
  unsigned int     r;
116
 
 
117
 
  /*
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
122
 
   *
123
 
   *  0 <= x + (fx - center)    x + fx - center < width
124
 
   *  center - x <= fx  fx < width + center - x
125
 
   */
126
 
 
127
 
  fx_start = center - x;
128
 
  if (fx_start < 0)
129
 
    fx_start = 0;
130
 
  fx_end = width + center - x;
131
 
  if (fx_end > g_size)
132
 
    fx_end = g_size;
133
 
 
134
 
  fy_start = center - y;
135
 
  if (fy_start < 0)
136
 
    fy_start = 0;
137
 
  fy_end = height + center - y;
138
 
  if (fy_end > g_size)
139
 
    fy_end = g_size;
140
 
 
141
 
  g_line = g_line + fy_start * g_size + fx_start;
142
 
 
143
 
  v = 0;
144
 
  for (fy = fy_start; fy < fy_end; fy++)
145
 
    {
146
 
      g_data = g_line;
147
 
      g_line += g_size;
148
 
 
149
 
      for (fx = fx_start; fx < fx_end; fx++)
150
 
        v += *g_data++;
151
 
    }
152
 
  if (v > 1)
153
 
    v = 1;
154
 
 
155
 
  v *= (opacity * 255.0);
156
 
 
157
 
  r = (unsigned int) v;
158
 
 
159
 
  return (unsigned char) r;
160
 
}
161
 
 
162
 
static unsigned char *
163
 
shadow_gaussian_make_tile ()
164
 
{
165
 
  unsigned char              * data;
166
 
  int                          size;
167
 
  int                          center;
168
 
  int                          x, y;
169
 
  unsigned char                d;
170
 
  int                          pwidth, pheight;
171
 
  double                       opacity = SHADOW_OPACITY;
172
 
  static GaussianMap       * gaussian_map = NULL;
173
 
 
174
 
  struct _mypixel
175
 
  {
176
 
    unsigned char r;
177
 
    unsigned char g;
178
 
    unsigned char b;
179
 
    unsigned char a;
180
 
  } * _d;
181
 
 
182
 
 
183
 
  if (!gaussian_map)
184
 
    gaussian_map =
185
 
      make_gaussian_map (SHADOW_RADIUS);
186
 
 
187
 
  size   = gaussian_map->size;
188
 
  center = size / 2;
189
 
 
190
 
  /* Top & bottom */
191
 
 
192
 
  pwidth  = MAX_TILE_SZ;
193
 
  pheight = MAX_TILE_SZ;
194
 
 
195
 
  data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
196
 
 
197
 
  _d = (struct _mypixel*) data;
198
 
 
199
 
  /* N */
200
 
  for (y = 0; y < pheight; y++)
201
 
    {
202
 
      d = sum_gaussian (gaussian_map, opacity,
203
 
                        center, y - center,
204
 
                        TILE_WIDTH, TILE_HEIGHT);
205
 
      for (x = 0; x < pwidth; x++)
206
 
        {
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;
211
 
        }
212
 
 
213
 
    }
214
 
 
215
 
  /* S */
216
 
  pwidth = MAX_TILE_SZ;
217
 
  pheight = MAX_TILE_SZ;
218
 
 
219
 
  for (y = 0; y < pheight; y++)
220
 
    {
221
 
      d = sum_gaussian (gaussian_map, opacity,
222
 
                        center, y - center,
223
 
                        TILE_WIDTH, TILE_HEIGHT);
224
 
      for (x = 0; x < pwidth; x++)
225
 
        {
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;
230
 
        }
231
 
 
232
 
    }
233
 
 
234
 
 
235
 
  /* w */
236
 
  pwidth = MAX_TILE_SZ;
237
 
  pheight = MAX_TILE_SZ;
238
 
 
239
 
  for (x = 0; x < pwidth; x++)
240
 
    {
241
 
      d = sum_gaussian (gaussian_map, opacity,
242
 
                        x - center, center,
243
 
                        TILE_WIDTH, TILE_HEIGHT);
244
 
      for (y = 0; y < pheight; y++)
245
 
        {
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;
250
 
        }
251
 
 
252
 
    }
253
 
 
254
 
  /* E */
255
 
  for (x = 0; x < pwidth; x++)
256
 
    {
257
 
      d = sum_gaussian (gaussian_map, opacity,
258
 
                                               x - center, center,
259
 
                                               TILE_WIDTH, TILE_HEIGHT);
260
 
      for (y = 0; y < pheight; y++)
261
 
        {
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;
266
 
        }
267
 
 
268
 
    }
269
 
 
270
 
  /* NW */
271
 
  pwidth = MAX_TILE_SZ;
272
 
  pheight = MAX_TILE_SZ;
273
 
 
274
 
  for (x = 0; x < pwidth; x++)
275
 
    for (y = 0; y < pheight; y++)
276
 
      {
277
 
        d = sum_gaussian (gaussian_map, opacity,
278
 
                          x-center, y-center,
279
 
                          TILE_WIDTH, TILE_HEIGHT);
280
 
 
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;
285
 
      }
286
 
 
287
 
  /* SW */
288
 
  for (x = 0; x < pwidth; x++)
289
 
    for (y = 0; y < pheight; y++)
290
 
      {
291
 
        d = sum_gaussian (gaussian_map, opacity,
292
 
                          x-center, y-center,
293
 
                          TILE_WIDTH, TILE_HEIGHT);
294
 
 
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;
299
 
      }
300
 
 
301
 
  /* SE */
302
 
  for (x = 0; x < pwidth; x++)
303
 
    for (y = 0; y < pheight; y++)
304
 
      {
305
 
        d = sum_gaussian (gaussian_map, opacity,
306
 
                          x-center, y-center,
307
 
                          TILE_WIDTH, TILE_HEIGHT);
308
 
 
309
 
        _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
310
 
           2*pwidth].r = 0;
311
 
        _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
312
 
           2*pwidth].g = 0;
313
 
        _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
314
 
           2*pwidth].b = 0;
315
 
        _d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
316
 
           2*pwidth].a = d;
317
 
      }
318
 
 
319
 
  /* NE */
320
 
  for (x = 0; x < pwidth; x++)
321
 
    for (y = 0; y < pheight; y++)
322
 
      {
323
 
        d = sum_gaussian (gaussian_map, opacity,
324
 
                          x-center, y-center,
325
 
                          TILE_WIDTH, TILE_HEIGHT);
326
 
 
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;
331
 
      }
332
 
 
333
 
  /* center */
334
 
  pwidth = MAX_TILE_SZ;
335
 
  pheight = MAX_TILE_SZ;
336
 
 
337
 
  d = sum_gaussian (gaussian_map, opacity,
338
 
                    center, center, TILE_WIDTH, TILE_HEIGHT);
339
 
 
340
 
  for (x = 0; x < pwidth; x++)
341
 
    for (y = 0; y < pheight; y++)
342
 
      {
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;
347
 
      }
348
 
 
349
 
  return data;
350
 
}