bugfix for previous patch - xcompmgr.c
Michael Knorr
damage-list@freenet.de
Thu, 04 Dec 2003 22:00:15 +0100
This is a multi-part message in MIME format.
--------------070703000608070607040201
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
There were some problems with very small windows in make_shadow
with my last patch. Thanks go to Daniel Krippner for reporting
this.
Incremental diff against the last version and full diff against
cvs head are attached to this message.
Greetings
Michael Knorr
--------------070703000608070607040201
Content-Type: text/plain;
name="xcompfull.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="xcompfull.diff"
--- ../xcompmgr/xcompmgr.c 2003-12-02 10:51:12.000000000 +0100
+++ xcompmgr.c 2003-12-04 20:29:35.000000000 +0100
@@ -67,6 +67,7 @@
typedef struct _conv {
int size;
double *data;
+ double *precalc_sums;
} conv;
win *list;
@@ -114,6 +115,70 @@
}
+/* precalculate some gaussian sums
+ gdata:
+ x0y0 x1y0 x2y0 ...
+ x0y1 x1y1 x2y1 ...
+ x0y2 x1y2 x2y2 ...
+ ...
+
+ gsums:
+ a1=x0y0 a2=x1y0+a1 a3=x2y0+a2 ...
+ a4=x0y1+a1 a5=x1y1+a2+a4-a1 a6=x2y1+a3+a5-a2 ...
+ a7=x0y2+a4 a8=x1y2+a5+a7-a4 a9=x2y2+a6+a8-a5 ...
+ ...
+ */
+static double *
+make_gaussian_sums(conv *map)
+{
+ int gsize = map->size;
+ double * gdata = map->data;
+ double * gsums = map->precalc_sums;
+ int x, y;
+ double v;
+ for (y = 0; y < gsize; y++)
+ {
+ for (x = 0; x < gsize; x++)
+ {
+ if (x > 0 && y > 0)
+ {
+ v = gdata[y * gsize + x]
+ + gsums[(y - 1) * gsize + x]
+ + gsums[y * gsize + x - 1]
+ - gsums[(y - 1) * gsize + x - 1];
+ }
+ else if (y > 0) /* we are on the top of the grid ( x == 0 ) */
+ {
+ v = gdata[y * gsize]
+ + gsums[(y - 1) * gsize];
+ }
+ else if (x > 0) /* we are on the left of the grid ( y == 0 ) */
+ {
+ v = gdata[x]
+ + gsums[x - 1];
+ }
+ else /* top left position ( x == 0 && y == 0 ) */
+ {
+ v = gdata[0];
+ }
+
+ if (v > 1.0)
+ {
+ v = 1.0;
+ }
+ else if (v < 0.0)
+ {
+ v = 0.0;
+ }
+
+ gsums[y * gsize + x] = v;
+
+ // printf("x: %d, y: %d, v: %f\n", x, y, v);
+ }
+ }
+}
+
+
static conv *
make_gaussian_map (Display *dpy, double r)
{
@@ -123,10 +188,12 @@
int x, y;
double t;
double g;
+ int data_size = size * size;
- c = malloc (sizeof (conv) + size * size * sizeof (double));
+ c = malloc (sizeof(conv) + sizeof(double) * data_size * 2);
c->size = size;
c->data = (double *) (c + 1);
+ c->precalc_sums = c->data + data_size;
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
{
@@ -140,6 +207,9 @@
{
c->data[y*size + x] /= t;
}
+
+ make_gaussian_sums(c);
+
return c;
}
@@ -164,6 +234,101 @@
sum_gaussian (conv *map, double opacity, int x, int y, int width, int height)
{
int fx, fy;
+ double *gsums = map->precalc_sums;
+ int gsize = map->size;
+ int center = gsize / 2;
+ int fx_start, fx_end;
+ int fy_start, fy_end;
+ double v;
+
+ /*
+ * 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;
+ else if (fx_start > gsize - 1)
+ fx_start = gsize - 1;
+ fx_end = width + center - x - 1;
+ if (fx_end > gsize - 1)
+ fx_end = gsize - 1;
+ if(fx_end < fx_start)
+ fx_end = fx_start;
+
+ fy_start = center - y;
+ if (fy_start < 0)
+ fy_start = 0;
+ else if (fy_start > gsize - 1)
+ fy_start = gsize - 1;
+ fy_end = height + center - y - 1;
+ if (fy_end > gsize - 1)
+ fy_end = gsize - 1;
+ if(fy_end < fy_start)
+ fy_end = fy_start;
+
+ if (fx_start > 0 && fy_start > 0)
+ {
+ /* fx_start fx_end
+ +-------+---+---+---+---+---+---+---+
+ |(--)+ D|(-)|(-)|(-)|(-)|- B| | |
+ +-------+---+---+---+---+---+---+---+
+ fy_start |(-)|(+)|(+)|(+)|(+)|(+)| | |
+ +---+---+---+---+---+---+---+---+
+ |(-)|(+)|(+)|(+)|(+)|(+)| | |
+ +---+---+---+---+---+---+---+---+
+ |(-)|(+)|(+)|(+)|(+)|(+)| | |
+ +---+---+---+---+---+---+---+---+
+ fy_end |- C|(+)|(+)|(+)|(+)|+ A| | |
+ +---+---+---+---+---+---+---+---+
+ | | | | | | | | |
+ +---+---+---+---+---+---+---+---+
+ */
+ v = gsums[fy_end * gsize + fx_end] /* A */
+ - gsums[(fy_start - 1) * gsize + fx_end] /* B */
+ - gsums[fy_end * gsize + fx_start - 1] /* C */
+ + gsums[(fy_start - 1) * gsize + fx_start - 1]; /* D */
+ }
+ else if (fy_start > 0) /* fx_start == 0 */
+ {
+ v = gsums[fy_end * gsize + fx_end]
+ - gsums[(fy_start - 1) * gsize + fx_end]; /* B */
+ }
+ else if (fx_start > 0) /* fy_start == 0 */
+ {
+ v = gsums[fy_end * gsize + fx_end]
+ - gsums[fy_end * gsize + fx_start - 1];
+ }
+ else /* fx_start == 0 && fy_start == 0 */
+ {
+ v = gsums[fy_end * gsize + fx_end];
+ // printf("fx_start: %d, fx_end: %d, fy_start: %d, fy_end: %d, v: %f\n", fx_start, fx_end, fy_start, fy_end, v);
+ }
+
+ if (v > 1.0)
+ {
+ v = 1.0;
+ }
+ else if (v < 0.0)
+ {
+ v = 0.0;
+ }
+
+ return ((unsigned char) (v * opacity * 255.0));
+}
+
+
+#if 0
+static unsigned char
+sum_gaussian (conv *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;
@@ -212,6 +377,7 @@
return ((unsigned char) (v * opacity * 255.0));
}
+#endif
static XImage *
make_shadow (Display *dpy, double opacity, int width, int height)
@@ -225,7 +391,7 @@
int center = gsize / 2;
int x, y;
unsigned char d;
- int x_diff;
+ int y_diff, x_diff;
data = malloc (swidth * sheight * sizeof (unsigned char));
ximage = XCreateImage (dpy,
@@ -239,22 +405,29 @@
* Build the gaussian in sections
*/
+ ylimit = gsize;
+ if (ylimit > sheight / 2)
+ ylimit = sheight / 2;
+ xlimit = gsize;
+ if (xlimit > swidth / 2)
+ xlimit = swidth / 2;
+
+ y_diff = sheight - 2 * ylimit;
+ x_diff = swidth - 2 * xlimit;
+
/*
- * center (fill the complete data array)
+ * center (fill the complete data array without top and bottom)
*/
- d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
- memset(data, d, sheight * swidth);
+ if(y_diff > 0)
+ {
+ d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
+ memset(&data[ylimit * swidth], d, y_diff * swidth);
+ }
/*
* corners
*/
- ylimit = gsize;
- if (ylimit > sheight / 2)
- ylimit = (sheight + 1) / 2;
- xlimit = gsize;
- if (xlimit > swidth / 2)
- xlimit = (swidth + 1) / 2;
for (y = 0; y < ylimit; y++)
for (x = 0; x < xlimit; x++)
@@ -269,14 +442,13 @@
/*
* top/bottom
*/
- x_diff = swidth - (gsize * 2);
- if (x_diff > 0 && ylimit > 0)
+ if (x_diff > 0)
{
for (y = 0; y < ylimit; y++)
{
d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height);
- memset (&data[y * swidth + gsize], d, x_diff);
- memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
+ memset (&data[y * swidth + xlimit], d, x_diff);
+ memset (&data[(sheight - y - 1) * swidth + xlimit], d, x_diff);
#if 0
for (x = gsize; x < swidth - gsize; x++)
{
@@ -290,26 +462,19 @@
/*
* sides
*/
-
- for (x = 0; x < xlimit; x++)
+ if(y_diff > 0)
{
- d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
- for (y = gsize; y < sheight - gsize; y++)
+ for (x = 0; x < xlimit; x++)
{
- data[y * swidth + x] = d;
- data[y * swidth + (swidth - x - 1)] = d;
+ d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
+ for (y = ylimit; y < sheight - ylimit; y++)
+ {
+ data[y * swidth + x] = d;
+ data[y * swidth + (swidth - x - 1)] = d;
+ }
}
}
- /*
- * center
- */
-
- d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
- for (y = ylimit; y < sheight - ylimit; y++)
- for (x = xlimit; x < swidth - xlimit; x++)
- data[y * swidth + x] = d;
-
return ximage;
}
--------------070703000608070607040201
Content-Type: text/plain;
name="xcompincr.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="xcompincr.diff"
--- xcompmgr1.c 2003-12-03 01:05:49.000000000 +0100
+++ xcompmgr.c 2003-12-04 20:29:35.000000000 +0100
@@ -391,7 +391,7 @@
int center = gsize / 2;
int x, y;
unsigned char d;
- int x_diff;
+ int y_diff, x_diff;
data = malloc (swidth * sheight * sizeof (unsigned char));
ximage = XCreateImage (dpy,
@@ -407,17 +407,23 @@
ylimit = gsize;
if (ylimit > sheight / 2)
- ylimit = (sheight + 1) / 2;
+ ylimit = sheight / 2;
xlimit = gsize;
if (xlimit > swidth / 2)
- xlimit = (swidth + 1) / 2;
-
+ xlimit = swidth / 2;
+
+ y_diff = sheight - 2 * ylimit;
+ x_diff = swidth - 2 * xlimit;
+
/*
* center (fill the complete data array without top and bottom)
*/
- d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
- memset(&data[ylimit * swidth], d, (sheight - 2 * ylimit) * swidth);
+ if(y_diff > 0)
+ {
+ d = sum_gaussian (gaussianMap, opacity, center, center, width, height);
+ memset(&data[ylimit * swidth], d, y_diff * swidth);
+ }
/*
* corners
@@ -436,14 +442,13 @@
/*
* top/bottom
*/
- x_diff = swidth - (gsize * 2);
- if (x_diff > 0 && ylimit > 0)
+ if (x_diff > 0)
{
for (y = 0; y < ylimit; y++)
{
d = sum_gaussian (gaussianMap, opacity, center, y - center, width, height);
- memset (&data[y * swidth + gsize], d, x_diff);
- memset (&data[(sheight - y - 1) * swidth + gsize], d, x_diff);
+ memset (&data[y * swidth + xlimit], d, x_diff);
+ memset (&data[(sheight - y - 1) * swidth + xlimit], d, x_diff);
#if 0
for (x = gsize; x < swidth - gsize; x++)
{
@@ -457,14 +462,16 @@
/*
* sides
*/
-
- for (x = 0; x < xlimit; x++)
+ if(y_diff > 0)
{
- d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
- for (y = gsize; y < sheight - gsize; y++)
+ for (x = 0; x < xlimit; x++)
{
- data[y * swidth + x] = d;
- data[y * swidth + (swidth - x - 1)] = d;
+ d = sum_gaussian (gaussianMap, opacity, x - center, center, width, height);
+ for (y = ylimit; y < sheight - ylimit; y++)
+ {
+ data[y * swidth + x] = d;
+ data[y * swidth + (swidth - x - 1)] = d;
+ }
}
}
--------------070703000608070607040201--