Split shadow code into a separate file
Separate code related to creating the gaussian-blurred shadow texture into a separate file. Move the definition of MetaCompositor into a compositor-private.h so that the shadow code can cache the source in the compositor structure. http://bugzilla.gnome.org/show_bug.cgi?id=587251
This commit is contained in:
parent
9d36e8d853
commit
f0d22e18c4
@ -22,12 +22,15 @@ mutter_SOURCES= \
|
||||
core/boxes.c \
|
||||
include/boxes.h \
|
||||
compositor/compositor.c \
|
||||
compositor/compositor-private.h \
|
||||
compositor/mutter-module.c \
|
||||
compositor/mutter-module.h \
|
||||
compositor/mutter-plugin.c \
|
||||
compositor/mutter-plugin-manager.c \
|
||||
compositor/mutter-plugin-manager.h \
|
||||
compositor/mutter-shaped-texture.c \
|
||||
compositor/shadow.c \
|
||||
compositor/shadow.h \
|
||||
compositor/mutter-shaped-texture.h \
|
||||
compositor/tidy/tidy-texture-frame.c \
|
||||
compositor/tidy/tidy-texture-frame.h \
|
||||
|
25
src/compositor/compositor-private.h
Normal file
25
src/compositor/compositor-private.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_COMPOSITOR_PRIVATE_H
|
||||
#define META_COMPOSITOR_PRIVATE_H
|
||||
|
||||
#include "compositor.h"
|
||||
#include "display.h"
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
struct _MetaCompositor
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
Atom atom_x_root_pixmap;
|
||||
Atom atom_x_set_root;
|
||||
Atom atom_net_wm_window_opacity;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
gboolean show_redraw : 1;
|
||||
gboolean debug : 1;
|
||||
gboolean no_mipmaps : 1;
|
||||
};
|
||||
|
||||
#endif /* META_COMPOSITOR_PRIVATE_H */
|
@ -1,28 +1,23 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "../core/window-private.h"
|
||||
#include "display.h"
|
||||
#include "screen.h"
|
||||
#include "frame.h"
|
||||
#include "errors.h"
|
||||
#include "window.h"
|
||||
#include "compositor.h"
|
||||
#include "compositor-private.h"
|
||||
#include "compositor-mutter.h"
|
||||
#include "mutter-plugin-manager.h"
|
||||
#include "tidy/tidy-texture-frame.h"
|
||||
#include "xprops.h"
|
||||
#include "prefs.h"
|
||||
#include "shadow.h"
|
||||
#include "mutter-shaped-texture.h"
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlibint.h>
|
||||
@ -32,19 +27,8 @@
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/x11/clutter-x11.h>
|
||||
|
||||
#include <cogl/cogl.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)
|
||||
|
||||
#define CHECK_LIST_INTEGRITY_START(list) \
|
||||
{int len2__; int len__ = g_list_length(list);
|
||||
|
||||
@ -103,8 +87,6 @@ meta_xattrs_get_type (void)
|
||||
return our_type;
|
||||
}
|
||||
|
||||
static unsigned char* shadow_gaussian_make_tile (void);
|
||||
|
||||
static inline gboolean
|
||||
composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
{
|
||||
@ -117,21 +99,6 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
|
||||
return (major > maj || (major == maj && minor >= min));
|
||||
}
|
||||
|
||||
struct _MetaCompositor
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
Atom atom_x_root_pixmap;
|
||||
Atom atom_x_set_root;
|
||||
Atom atom_net_wm_window_opacity;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
||||
gboolean show_redraw : 1;
|
||||
gboolean debug : 1;
|
||||
gboolean no_mipmaps : 1;
|
||||
};
|
||||
|
||||
typedef struct _MetaCompScreen
|
||||
{
|
||||
MetaScreen *screen;
|
||||
@ -443,15 +410,8 @@ mutter_window_constructed (GObject *object)
|
||||
|
||||
if (mutter_window_has_shadow (self))
|
||||
{
|
||||
priv->shadow =
|
||||
tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ,
|
||||
MAX_TILE_SZ);
|
||||
priv->shadow = mutter_create_shadow_frame (compositor);
|
||||
|
||||
clutter_actor_set_position (priv->shadow,
|
||||
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
|
||||
}
|
||||
|
||||
@ -581,15 +541,7 @@ mutter_window_set_property (GObject *object,
|
||||
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (mw), &w, &h);
|
||||
|
||||
priv->shadow =
|
||||
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 (priv->shadow,
|
||||
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
|
||||
priv->shadow = mutter_create_shadow_frame (compositor);
|
||||
|
||||
clutter_actor_set_size (priv->shadow, w, h);
|
||||
|
||||
@ -2539,7 +2491,6 @@ meta_compositor_new (MetaDisplay *display)
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
MetaCompositor *compositor;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
guchar *data;
|
||||
|
||||
if (!composite_at_least_version (display, 0, 3))
|
||||
return NULL;
|
||||
@ -2559,23 +2510,6 @@ meta_compositor_new (MetaDisplay *display)
|
||||
compositor->atom_x_set_root = atoms[1];
|
||||
compositor->atom_net_wm_window_opacity = atoms[2];
|
||||
|
||||
/* Shadow setup */
|
||||
|
||||
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);
|
||||
free (data);
|
||||
|
||||
return compositor;
|
||||
}
|
||||
|
||||
@ -2586,300 +2520,3 @@ mutter_get_overlay_window (MetaScreen *screen)
|
||||
|
||||
return info->output;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------- */
|
||||
/* Shadow Generation */
|
||||
|
||||
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 = 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;
|
||||
}
|
||||
|
350
src/compositor/shadow.c
Normal file
350
src/compositor/shadow.c
Normal file
@ -0,0 +1,350 @@
|
||||
/* -*- 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 *
|
||||
mutter_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;
|
||||
}
|
9
src/compositor/shadow.h
Normal file
9
src/compositor/shadow.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef SHADOW_H
|
||||
#define SHADOW_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "compositor.h"
|
||||
|
||||
ClutterActor *mutter_create_shadow_frame (MetaCompositor *compositor);
|
||||
|
||||
#endif /* SHADOW_H */
|
Loading…
Reference in New Issue
Block a user