mirror of
https://github.com/brl/mutter.git
synced 2025-04-14 22:29:39 +00:00

Move all objects and functions namespaced with Mutter into the Meta namespace to get a single consistent namespace. Changes that aren't simply changing mutter to meta: MutterWindow => MetaWindowActor mutter_get_windows => meta_get_window_actors mutter_plugin_get_windows => meta_plugin_get_window_actors https://bugzilla.gnome.org/show_bug.cgi?id=628520
351 lines
8.7 KiB
C
351 lines
8.7 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
#define _GNU_SOURCE /* For M_PI */
|
|
|
|
#include <math.h>
|
|
|
|
#include "compositor-private.h"
|
|
#include "shadow.h"
|
|
#include "tidy/tidy-texture-frame.h"
|
|
|
|
#define SHADOW_RADIUS 8
|
|
#define SHADOW_OPACITY 0.9
|
|
#define SHADOW_OFFSET_X (SHADOW_RADIUS)
|
|
#define SHADOW_OFFSET_Y (SHADOW_RADIUS)
|
|
|
|
#define MAX_TILE_SZ 8 /* Must be <= shaddow radius */
|
|
#define TILE_WIDTH (3*MAX_TILE_SZ)
|
|
#define TILE_HEIGHT (3*MAX_TILE_SZ)
|
|
|
|
static unsigned char* shadow_gaussian_make_tile (void);
|
|
|
|
ClutterActor *
|
|
meta_create_shadow_frame (MetaCompositor *compositor)
|
|
{
|
|
ClutterActor *frame;
|
|
|
|
if (!compositor->shadow_src)
|
|
{
|
|
guchar *data;
|
|
|
|
data = shadow_gaussian_make_tile ();
|
|
|
|
compositor->shadow_src = clutter_texture_new ();
|
|
|
|
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
|
|
data,
|
|
TRUE,
|
|
TILE_WIDTH,
|
|
TILE_HEIGHT,
|
|
TILE_WIDTH*4,
|
|
4,
|
|
0,
|
|
NULL);
|
|
g_free (data);
|
|
}
|
|
|
|
frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
|
|
MAX_TILE_SZ,
|
|
MAX_TILE_SZ,
|
|
MAX_TILE_SZ,
|
|
MAX_TILE_SZ);
|
|
|
|
clutter_actor_set_position (frame,
|
|
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
|
|
|
|
return frame;
|
|
}
|
|
|
|
typedef struct GaussianMap
|
|
{
|
|
int size;
|
|
double * data;
|
|
} GaussianMap;
|
|
|
|
static double
|
|
gaussian (double r, double x, double y)
|
|
{
|
|
return ((1 / (sqrt (2 * M_PI * r))) *
|
|
exp ((- (x * x + y * y)) / (2 * r * r)));
|
|
}
|
|
|
|
|
|
static GaussianMap *
|
|
make_gaussian_map (double r)
|
|
{
|
|
GaussianMap *c;
|
|
int size = ((int) ceil ((r * 3)) + 1) & ~1;
|
|
int center = size / 2;
|
|
int x, y;
|
|
double t = 0.0;
|
|
double g;
|
|
|
|
c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
|
|
c->size = size;
|
|
|
|
c->data = (double *) (c + 1);
|
|
|
|
for (y = 0; y < size; y++)
|
|
for (x = 0; x < size; x++)
|
|
{
|
|
g = gaussian (r, (double) (x - center), (double) (y - center));
|
|
t += g;
|
|
c->data[y * size + x] = g;
|
|
}
|
|
|
|
for (y = 0; y < size; y++)
|
|
for (x = 0; x < size; x++)
|
|
c->data[y*size + x] /= t;
|
|
|
|
return c;
|
|
}
|
|
|
|
static unsigned char
|
|
sum_gaussian (GaussianMap * map, double opacity,
|
|
int x, int y, int width, int height)
|
|
{
|
|
int fx, fy;
|
|
double * g_data;
|
|
double * g_line = map->data;
|
|
int g_size = map->size;
|
|
int center = g_size / 2;
|
|
int fx_start, fx_end;
|
|
int fy_start, fy_end;
|
|
double v;
|
|
unsigned int r;
|
|
|
|
/*
|
|
* Compute set of filter values which are "in range",
|
|
* that's the set with:
|
|
* 0 <= x + (fx-center) && x + (fx-center) < width &&
|
|
* 0 <= y + (fy-center) && y + (fy-center) < height
|
|
*
|
|
* 0 <= x + (fx - center) x + fx - center < width
|
|
* center - x <= fx fx < width + center - x
|
|
*/
|
|
|
|
fx_start = center - x;
|
|
if (fx_start < 0)
|
|
fx_start = 0;
|
|
fx_end = width + center - x;
|
|
if (fx_end > g_size)
|
|
fx_end = g_size;
|
|
|
|
fy_start = center - y;
|
|
if (fy_start < 0)
|
|
fy_start = 0;
|
|
fy_end = height + center - y;
|
|
if (fy_end > g_size)
|
|
fy_end = g_size;
|
|
|
|
g_line = g_line + fy_start * g_size + fx_start;
|
|
|
|
v = 0;
|
|
for (fy = fy_start; fy < fy_end; fy++)
|
|
{
|
|
g_data = g_line;
|
|
g_line += g_size;
|
|
|
|
for (fx = fx_start; fx < fx_end; fx++)
|
|
v += *g_data++;
|
|
}
|
|
if (v > 1)
|
|
v = 1;
|
|
|
|
v *= (opacity * 255.0);
|
|
|
|
r = (unsigned int) v;
|
|
|
|
return (unsigned char) r;
|
|
}
|
|
|
|
static unsigned char *
|
|
shadow_gaussian_make_tile ()
|
|
{
|
|
unsigned char * data;
|
|
int size;
|
|
int center;
|
|
int x, y;
|
|
unsigned char d;
|
|
int pwidth, pheight;
|
|
double opacity = SHADOW_OPACITY;
|
|
static GaussianMap * gaussian_map = NULL;
|
|
|
|
struct _mypixel
|
|
{
|
|
unsigned char r;
|
|
unsigned char g;
|
|
unsigned char b;
|
|
unsigned char a;
|
|
} * _d;
|
|
|
|
|
|
if (!gaussian_map)
|
|
gaussian_map =
|
|
make_gaussian_map (SHADOW_RADIUS);
|
|
|
|
size = gaussian_map->size;
|
|
center = size / 2;
|
|
|
|
/* Top & bottom */
|
|
|
|
pwidth = MAX_TILE_SZ;
|
|
pheight = MAX_TILE_SZ;
|
|
|
|
data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
|
|
|
|
_d = (struct _mypixel*) data;
|
|
|
|
/* N */
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
center, y - center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
for (x = 0; x < pwidth; x++)
|
|
{
|
|
_d[y*3*pwidth + x + pwidth].r = 0;
|
|
_d[y*3*pwidth + x + pwidth].g = 0;
|
|
_d[y*3*pwidth + x + pwidth].b = 0;
|
|
_d[y*3*pwidth + x + pwidth].a = d;
|
|
}
|
|
|
|
}
|
|
|
|
/* S */
|
|
pwidth = MAX_TILE_SZ;
|
|
pheight = MAX_TILE_SZ;
|
|
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
center, y - center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
for (x = 0; x < pwidth; x++)
|
|
{
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].r = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].g = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].b = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].a = d;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/* w */
|
|
pwidth = MAX_TILE_SZ;
|
|
pheight = MAX_TILE_SZ;
|
|
|
|
for (x = 0; x < pwidth; x++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x - center, center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x].r = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x].g = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x].b = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x].a = d;
|
|
}
|
|
|
|
}
|
|
|
|
/* E */
|
|
for (x = 0; x < pwidth; x++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x - center, center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].r = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].g = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].b = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].a = d;
|
|
}
|
|
|
|
}
|
|
|
|
/* NW */
|
|
pwidth = MAX_TILE_SZ;
|
|
pheight = MAX_TILE_SZ;
|
|
|
|
for (x = 0; x < pwidth; x++)
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x-center, y-center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
_d[y*3*pwidth + x].r = 0;
|
|
_d[y*3*pwidth + x].g = 0;
|
|
_d[y*3*pwidth + x].b = 0;
|
|
_d[y*3*pwidth + x].a = d;
|
|
}
|
|
|
|
/* SW */
|
|
for (x = 0; x < pwidth; x++)
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x-center, y-center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].r = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].g = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].b = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].a = d;
|
|
}
|
|
|
|
/* SE */
|
|
for (x = 0; x < pwidth; x++)
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x-center, y-center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
|
2*pwidth].r = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
|
2*pwidth].g = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
|
2*pwidth].b = 0;
|
|
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
|
|
2*pwidth].a = d;
|
|
}
|
|
|
|
/* NE */
|
|
for (x = 0; x < pwidth; x++)
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
x-center, y-center,
|
|
TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].r = 0;
|
|
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].g = 0;
|
|
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].b = 0;
|
|
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].a = d;
|
|
}
|
|
|
|
/* center */
|
|
pwidth = MAX_TILE_SZ;
|
|
pheight = MAX_TILE_SZ;
|
|
|
|
d = sum_gaussian (gaussian_map, opacity,
|
|
center, center, TILE_WIDTH, TILE_HEIGHT);
|
|
|
|
for (x = 0; x < pwidth; x++)
|
|
for (y = 0; y < pheight; y++)
|
|
{
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].r = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].g = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].b = 0;
|
|
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].a = 0;
|
|
}
|
|
|
|
return data;
|
|
}
|