legacy-imlib2/rgbadraw.c

1414 lines
30 KiB
C

#include <X11/Xlib.h>
#include "common.h"
#include "colormod.h"
#include "scale.h"
#include "image.h"
#include "context.h"
#include "rgba.h"
#include "blend.h"
#include "updates.h"
#include "rgbadraw.h"
void
__imlib_FlipImageHoriz(ImlibImage *im)
{
DATA32 *p1, *p2, tmp;
int x, y;
for (y = 0; y < im->h; y++)
{
p1 = im->data + (y * im->w);
p2 = im->data + ((y + 1) * im->w) - 1;
for (x = 0; x < (im->w >> 1); x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2--;
}
}
}
void
__imlib_FlipImageVert(ImlibImage *im)
{
DATA32 *p1, *p2, tmp;
int x, y;
for (y = 0; y < (im->h >> 1); y++)
{
p1 = im->data + (y * im->w);
p2 = im->data + ((im->h - 1 - y) * im->w);
for (x = 0; x < im->w; x++)
{
tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2++;
}
}
}
void
__imlib_FlipImageDiagonal(ImlibImage *im)
{
DATA32 *p1, *p2, *data;
int x, y, tmp;
data = malloc(im->w * im->h * sizeof(DATA32));
p1 = im->data;
for (y = im->h - 1; y >= 0; y--)
{
p2 = data + y;
for (x = 0; x < im->w; x++)
{
*p2 = *p1;
p2 += im->h;
p1++;
}
}
free(im->data);
im->data = data;
tmp = im->w;
im->w = im->h;
im->h = tmp;
tmp = im->border.top;
im->border.top = im->border.left;
im->border.left = tmp;
tmp = im->border.bottom;
im->border.bottom = im->border.right;
im->border.right = tmp;
}
void
__imlib_BlurImage(ImlibImage *im, int rad)
{
DATA32 *p1, *p2, *data;
int x, y, mx, my, mw, mh, mt, xx, yy;
int a, r, g, b;
int *as, *rs, *gs, *bs;
if (rad < 1)
return;
data = malloc(im->w * im->h * sizeof(DATA32));
as = malloc(sizeof(int) * im->w);
rs = malloc(sizeof(int) * im->w);
gs = malloc(sizeof(int) * im->w);
bs = malloc(sizeof(int) * im->w);
for (y = 0; y < im->h; y++)
{
my = y - rad;
mh = (rad << 1) + 1;
if (my < 0)
{
mh += my;
my = 0;
}
if ((my + mh) > im->h)
mh = im->h - my;
p1 = data + (y * im->w);
memset(as, 0, im->w * sizeof(int));
memset(rs, 0, im->w * sizeof(int));
memset(gs, 0, im->w * sizeof(int));
memset(bs, 0, im->w * sizeof(int));
for (yy = 0; yy < mh; yy++)
{
p2 = im->data + ((yy + my) * im->w);
for (x = 0; x < im->w; x++)
{
as[x] += (*p2 >> 24) & 0xff;
rs[x] += (*p2 >> 16) & 0xff;
gs[x] += (*p2 >> 8) & 0xff;
bs[x] += *p2 & 0xff;
p2 ++;
}
}
if (im->w > ((rad << 1) + 1))
{
for (x = 0; x < im->w; x++)
{
a = 0; r = 0; g = 0; b = 0;
mx = x - rad;
mw = (rad << 1) + 1;
if (mx < 0)
{
mw += mx;
mx = 0;
}
if ((mx + mw) > im->w)
mw = im->w - mx;
mt = mw * mh;
for (xx = mx; xx < (mw + mx); xx++)
{
a += as[xx];
r += rs[xx];
g += gs[xx];
b += bs[xx];
}
a = a / mt; r = r / mt; g = g / mt; b = b / mt;
*p1 = (a << 24) | (r << 16) | (g << 8) | b;
p1++;
}
}
else
{
}
}
free(as);
free(rs);
free(gs);
free(bs);
free(im->data);
im->data = data;
}
void
__imlib_SharpenImage(ImlibImage *im, int rad)
{
DATA32 *data, *p1, *p2;
int a, r, g, b, x, y;
/* FIXME: impliment */
data = malloc(im->w * im->h * sizeof(DATA32));
if (rad == 0)
return;
else
{
int mul, mul2, tot;
mul = (rad * 4) + 1;
mul2 = rad;
tot = mul - (mul2 * 4);
for (y = 1; y < (im->h - 1); y++)
{
p1 = im->data + 1 + (y * im->w);
p2 = data + 1 + (y * im->w);
for (x = 1; x < (im->w - 1); x++)
{
b = (int)((p1[0] ) & 0xff) * 5;
g = (int)((p1[0] >> 8 ) & 0xff) * 5;
r = (int)((p1[0] >> 16) & 0xff) * 5;
a = (int)((p1[0] >> 24) & 0xff) * 5;
b -= (int)((p1[-1] ) & 0xff);
g -= (int)((p1[-1] >> 8 ) & 0xff);
r -= (int)((p1[-1] >> 16) & 0xff);
a -= (int)((p1[-1] >> 24) & 0xff);
b -= (int)((p1[1] ) & 0xff);
g -= (int)((p1[1] >> 8 ) & 0xff);
r -= (int)((p1[1] >> 16) & 0xff);
a -= (int)((p1[1] >> 24) & 0xff);
b -= (int)((p1[-im->w] ) & 0xff);
g -= (int)((p1[-im->w] >> 8 ) & 0xff);
r -= (int)((p1[-im->w] >> 16) & 0xff);
a -= (int)((p1[-im->w] >> 24) & 0xff);
b -= (int)((p1[im->w] ) & 0xff);
g -= (int)((p1[im->w] >> 8 ) & 0xff);
r -= (int)((p1[im->w] >> 16) & 0xff);
a -= (int)((p1[im->w] >> 24) & 0xff);
a = (a & ((~a) >> 16));
a = ((a | ((a & 256) - ((a & 256) >> 8))) );
r = (r & ((~r) >> 16));
r = ((r | ((r & 256) - ((r & 256) >> 8))) );
g = (g & ((~g) >> 16));
g = ((g | ((g & 256) - ((g & 256) >> 8))) );
b = (b & ((~b) >> 16));
b = ((b | ((b & 256) - ((b & 256) >> 8))) );
*p2 = (a << 24) | (r << 16) | (g << 8) | b;
p2++;
p1++;
}
}
}
free(im->data);
im->data = data;
}
void
__imlib_TileImageHoriz(ImlibImage *im)
{
DATA32 *p1, *p2, *p3, *p, *data;
int x, y, per, tmp, na, nr, ng, nb, mix, a, r, g, b, aa, rr, gg, bb;
data = malloc(im->w * im->h * sizeof(DATA32));
p1 = im->data;
p = data;
for (y = 0; y < im->h; y++)
{
p2 = p1 + (im->w >> 1);
p3 = p1;
per = (im->w >> 1);
for (x = 0; x < (im->w >> 1); x++)
{
mix = (x * 255) / per;
b = (*p1 ) & 0xff;
g = (*p1 >> 8 ) & 0xff;
r = (*p1 >> 16) & 0xff;
a = (*p1 >> 24) & 0xff;
bb = (*p2 ) & 0xff;
gg = (*p2 >> 8 ) & 0xff;
rr = (*p2 >> 16) & 0xff;
aa = (*p2 >> 24) & 0xff;
tmp = (r - rr) * mix;
nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (g - gg) * mix;
ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (b - bb) * mix;
nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (a - aa) * mix;
na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
*p = (na << 24) | (nr << 16) | (ng << 8) | nb;
p++;
p1++;
p2++;
}
p2 = p3;
per = (im->w - (im->w >> 1));
for (; x < im->w; x++)
{
mix = ((im->w - 1 - x) * 255) / per;
b = (*p1 ) & 0xff;
g = (*p1 >> 8 ) & 0xff;
r = (*p1 >> 16) & 0xff;
a = (*p1 >> 24) & 0xff;
bb = (*p2 ) & 0xff;
gg = (*p2 >> 8 ) & 0xff;
rr = (*p2 >> 16) & 0xff;
aa = (*p2 >> 24) & 0xff;
tmp = (r - rr) * mix;
nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (g - gg) * mix;
ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (b - bb) * mix;
nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (a - aa) * mix;
na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
*p = (na << 24) | (nr << 16) | (ng << 8) | nb;
p++;
p1++;
p2++;
}
}
free(im->data);
im->data = data;
}
void
__imlib_TileImageVert(ImlibImage *im)
{
DATA32 *p1, *p2, *p, *data;
int x, y, tmp, na, nr, ng, nb, mix, a, r, g, b, aa, rr, gg, bb;
data = malloc(im->w * im->h * sizeof(DATA32));
p = data;
for (y = 0; y < im->h; y++)
{
p1 = im->data + (y * im->w);
if (y < (im->h >> 1))
{
p2 = im->data + ((y + (im->h >> 1)) * im->w);
mix = (y * 255) / (im->h >> 1);
}
else
{
p2 = im->data + ((y - (im->h - (im->h >> 1))) * im->w);
mix = ((im->h - y) * 255) / (im->h - (im->h >> 1));
}
for (x = 0; x < im->w; x++)
{
b = (*p1 ) & 0xff;
g = (*p1 >> 8 ) & 0xff;
r = (*p1 >> 16) & 0xff;
a = (*p1 >> 24) & 0xff;
bb = (*p2 ) & 0xff;
gg = (*p2 >> 8 ) & 0xff;
rr = (*p2 >> 16) & 0xff;
aa = (*p2 >> 24) & 0xff;
tmp = (r - rr) * mix;
nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (g - gg) * mix;
ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (b - bb) * mix;
nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);
tmp = (a - aa) * mix;
na = aa + ((tmp + (tmp >> 8) + 0x80) >> 8);
*p = (na << 24) | (nr << 16) | (ng << 8) | nb;
p++;
p1++;
p2++;
}
}
free(im->data);
im->data = data;
}
#define BLEND(r1, g1, b1, a1, dest) \
bb = ((dest) ) & 0xff;\
gg = ((dest) >> 8 ) & 0xff;\
rr = ((dest) >> 16) & 0xff;\
aa = ((dest) >> 24) & 0xff;\
tmp = ((r1) - rr) * (a1);\
nr = rr + ((tmp + (tmp >> 8) + 0x80) >> 8);\
tmp = ((g1) - gg) * (a1);\
ng = gg + ((tmp + (tmp >> 8) + 0x80) >> 8);\
tmp = ((b1) - bb) * (a1);\
nb = bb + ((tmp + (tmp >> 8) + 0x80) >> 8);\
tmp = (a1) + aa;\
na = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
(dest) = (na << 24) | (nr << 16) | (ng << 8) | nb;
#define BLEND_ADD(r1, g1, b1, a1, dest) \
bb = ((dest) ) & 0xff;\
gg = ((dest) >> 8 ) & 0xff;\
rr = ((dest) >> 16) & 0xff;\
aa = ((dest) >> 24) & 0xff;\
tmp = rr + (((r1) * (a1)) >> 8);\
nr = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
tmp = gg + (((g1) * (a1)) >> 8);\
ng = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
tmp = bb + (((b1) * (a1)) >> 8);\
nb = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
tmp = (a1) + aa;\
na = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
(dest) = (na << 24) | (nr << 16) | (ng << 8) | nb;
#define BLEND_SUB(r1, g1, b1, a1, dest) \
bb = ((dest) ) & 0xff;\
gg = ((dest) >> 8 ) & 0xff;\
rr = ((dest) >> 16) & 0xff;\
aa = ((dest) >> 24) & 0xff;\
tmp = rr - (((r1) * (a1)) >> 8);\
nr = tmp & (~(tmp >> 8));\
tmp = gg - (((g1) * (a1)) >> 8);\
ng = tmp & (~(tmp >> 8));\
tmp = bb - (((b1) * (a1)) >> 8);\
nb = tmp & (~(tmp >> 8));\
tmp = (a1) + aa;\
na = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
(dest) = (na << 24) | (nr << 16) | (ng << 8) | nb;
#define BLEND_RE(r1, g1, b1, a1, dest) \
bb = ((dest) ) & 0xff;\
gg = ((dest) >> 8 ) & 0xff;\
rr = ((dest) >> 16) & 0xff;\
aa = ((dest) >> 24) & 0xff;\
tmp = rr + ((((r1) - 127) * (a1)) >> 7);\
nr = (tmp | ((tmp & 256) - ((tmp & 256) >> 8))) & (~(tmp >> 8));\
tmp = gg + ((((g1) - 127) * (a1)) >> 7);\
ng = (tmp | ((tmp & 256) - ((tmp & 256) >> 8))) & (~(tmp >> 8));\
tmp = bb + ((((b1) - 127) * (a1)) >> 7);\
nb = (tmp | ((tmp & 256) - ((tmp & 256) >> 8))) & (~(tmp >> 8));\
tmp = (a1) + aa;\
na = (tmp | ((tmp & 256) - ((tmp & 256) >> 8)));\
(dest) = (na << 24) | (nr << 16) | (ng << 8) | nb;
ImlibUpdate *
__imlib_draw_line(ImlibImage *im, int x1, int y1, int x2, int y2,
DATA8 r, DATA8 g, DATA8 b, DATA8 a,
ImlibOp op, char make_updates)
{
int x, y, dx, dy, yy, xx, am, tmp;
DATA32 *p;
DATA8 aaa, nr, ng, nb, rr, gg, bb, aa, na;
/* clip to top edge */
if ((y1 < 0) && (y2 < 0))
return NULL;
if (y1 < 0)
{
x1 += (y1 * (x1 - x2)) / (y2 - y1);
y1 = 0;
}
if (y2 < 0)
{
x2 += (y2 * (x1 - x2)) / (y2 - y1);
y2 = 0;
}
/* clip to bottom edge */
if ((y1 >= im->h) && (y2 >= im->h))
return NULL;
if (y1 >= im->h)
{
x1 -= ((im->h - y1) * (x1 - x2)) / (y2 - y1);
y1 = im->h - 1;
}
if (y2 >= im->h)
{
x2 -= ((im->h - y2) * (x1 - x2)) / (y2 - y1);
y2 = im->h - 1;
}
/* clip to top edge */
if ((x1 < 0) && (x2 < 0))
return NULL;
if (x1 < 0)
{
y1 += (x1 * (y1 - y2)) / (x2 - x1);
x1 = 0;
}
if (x2 < 0)
{
y2 += (x2 * (y1 - y2)) / (x2 - x1);
x2 = 0;
}
/* clip to bottom edge */
if ((x1 >= im->w) && (x2 >= im->w))
return NULL;
if (x1 >= im->w)
{
y1 -= ((im->w - x1) * (y1 - y2)) / (x2 - x1);
x1 = im->w - 1;
}
if (y2 >= im->w)
{
y2 -= ((im->w - x2) * (y1 - y2)) / (x2 - x1);
x2 = im->w - 1;
}
dx = x2 - x1;
dy = y2 - y1;
if (x1 > x2)
{
int tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
dx = x2 - x1;
dy = y2 - y1;
}
switch (op)
{
case OP_COPY:
/* vertical line */
if (dx == 0)
{
if (y1 < y2)
{
p = &(im->data[(im->w * y1) + x1]);
for (y = y1; y <= y2; y++)
{
BLEND(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y1, 1, (y2 - y1 + 1));
}
else
{
p = &(im->data[(im->w * y2) + x1]);
for (y = y2; y <= y1; y++)
{
BLEND(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y2, 1, (y1 - y2 + 1));
}
}
/* horizontal line */
if (dy == 0)
{
if (x1 < x2)
{
p = &(im->data[(im->w * y1) + x1]);
for (x = x1; x <= x2; x++)
{
BLEND(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x1, y1, (x2 - x1 + 1), 1);
}
else
{
p = &(im->data[(im->w * y1) + x2]);
for (x = x2; x <= x1; x++)
{
BLEND(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x2, y1, (x1 - x2 + 1), 1);
}
}
/* 1 */
/* \ */
/* \ */
/* 2 */
if (y2 > y1)
{
/* steep */
if (dy > dx)
{
dx = ((dx << 16) / dy);
x = x1 << 16;
for (y = y1; y <= y2; y++)
{
xx = x >> 16;
am = 256 - (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p ++;
BLEND(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
}
/* 2 */
/* / */
/* / */
/* 1 */
else
{
/* steep */
if (-dy > dx)
{
dx = ((dx << 16) / -dy);
x = (x1 + 1) << 16;
for (y = y1; y >= y2; y--)
{
xx = x >> 16;
am = (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p--;
BLEND(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
}
break;
case OP_ADD:
/* vertical line */
if (dx == 0)
{
if (y1 < y2)
{
p = &(im->data[(im->w * y1) + x1]);
for (y = y1; y <= y2; y++)
{
BLEND_ADD(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y1, 1, (y2 - y1 + 1));
}
else
{
p = &(im->data[(im->w * y2) + x1]);
for (y = y2; y <= y1; y++)
{
BLEND_ADD(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y2, 1, (y1 - y2 + 1));
}
}
/* horizontal line */
if (dy == 0)
{
if (x1 < x2)
{
p = &(im->data[(im->w * y1) + x1]);
for (x = x1; x <= x2; x++)
{
BLEND_ADD(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x1, y1, (x2 - x1 + 1), 1);
}
else
{
p = &(im->data[(im->w * y1) + x2]);
for (x = x2; x <= x1; x++)
{
BLEND_ADD(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x2, y1, (x1 - x2 + 1), 1);
}
}
/* 1 */
/* \ */
/* \ */
/* 2 */
if (y2 > y1)
{
/* steep */
if (dy > dx)
{
dx = ((dx << 16) / dy);
x = x1 << 16;
for (y = y1; y <= y2; y++)
{
xx = x >> 16;
am = 256 - (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_ADD(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p ++;
BLEND_ADD(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_ADD(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_ADD(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
}
/* 2 */
/* / */
/* / */
/* 1 */
else
{
/* steep */
if (-dy > dx)
{
dx = ((dx << 16) / -dy);
x = (x1 + 1) << 16;
for (y = y1; y >= y2; y--)
{
xx = x >> 16;
am = (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_ADD(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p--;
BLEND_ADD(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_ADD(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_ADD(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
}
break;
case OP_SUBTRACT:
/* vertical line */
if (dx == 0)
{
if (y1 < y2)
{
p = &(im->data[(im->w * y1) + x1]);
for (y = y1; y <= y2; y++)
{
BLEND_SUB(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y1, 1, (y2 - y1 + 1));
}
else
{
p = &(im->data[(im->w * y2) + x1]);
for (y = y2; y <= y1; y++)
{
BLEND_SUB(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y2, 1, (y1 - y2 + 1));
}
}
/* horizontal line */
if (dy == 0)
{
if (x1 < x2)
{
p = &(im->data[(im->w * y1) + x1]);
for (x = x1; x <= x2; x++)
{
BLEND_SUB(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x1, y1, (x2 - x1 + 1), 1);
}
else
{
p = &(im->data[(im->w * y1) + x2]);
for (x = x2; x <= x1; x++)
{
BLEND_SUB(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x2, y1, (x1 - x2 + 1), 1);
}
}
/* 1 */
/* \ */
/* \ */
/* 2 */
if (y2 > y1)
{
/* steep */
if (dy > dx)
{
dx = ((dx << 16) / dy);
x = x1 << 16;
for (y = y1; y <= y2; y++)
{
xx = x >> 16;
am = 256 - (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_SUB(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p ++;
BLEND_SUB(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_SUB(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_SUB(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
}
/* 2 */
/* / */
/* / */
/* 1 */
else
{
/* steep */
if (-dy > dx)
{
dx = ((dx << 16) / -dy);
x = (x1 + 1) << 16;
for (y = y1; y >= y2; y--)
{
xx = x >> 16;
am = (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_SUB(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p--;
BLEND_SUB(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_SUB(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_SUB(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
}
break;
case OP_RESHADE:
/* vertical line */
if (dx == 0)
{
if (y1 < y2)
{
p = &(im->data[(im->w * y1) + x1]);
for (y = y1; y <= y2; y++)
{
BLEND_RE(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y1, 1, (y2 - y1 + 1));
}
else
{
p = &(im->data[(im->w * y2) + x1]);
for (y = y2; y <= y1; y++)
{
BLEND_RE(r, g, b, a, *p);
p += im->w;
}
return __imlib_AddUpdate(NULL, x1, y2, 1, (y1 - y2 + 1));
}
}
/* horizontal line */
if (dy == 0)
{
if (x1 < x2)
{
p = &(im->data[(im->w * y1) + x1]);
for (x = x1; x <= x2; x++)
{
BLEND_RE(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x1, y1, (x2 - x1 + 1), 1);
}
else
{
p = &(im->data[(im->w * y1) + x2]);
for (x = x2; x <= x1; x++)
{
BLEND_RE(r, g, b, a, *p);
p++;
}
return __imlib_AddUpdate(NULL, x2, y1, (x1 - x2 + 1), 1);
}
}
/* 1 */
/* \ */
/* \ */
/* 2 */
if (y2 > y1)
{
/* steep */
if (dy > dx)
{
dx = ((dx << 16) / dy);
x = x1 << 16;
for (y = y1; y <= y2; y++)
{
xx = x >> 16;
am = 256 - (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_RE(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p ++;
BLEND_RE(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_RE(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_RE(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y1,
(x2 - x1 + 1), (y2 - y1 + 1));
}
}
/* 2 */
/* / */
/* / */
/* 1 */
else
{
/* steep */
if (-dy > dx)
{
dx = ((dx << 16) / -dy);
x = (x1 + 1) << 16;
for (y = y1; y >= y2; y--)
{
xx = x >> 16;
am = (((x - (xx << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * y) + xx]);
BLEND_RE(r, g, b, aaa, *p);
if (xx < (im->w - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p--;
BLEND_RE(r, g, b, aaa, *p);
}
x += dx;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
/* shallow */
else
{
dy = ((dy << 16) / dx);
y = y1 << 16;
for (x = x1; x <= x2; x++)
{
yy = y >> 16;
am = 256 - (((y - (yy << 16)) + 1) >> 8);
aaa = (a * am) >> 8;
p = &(im->data[(im->w * yy) + x]);
BLEND_RE(r, g, b, aaa, *p);
if (yy < (im->h - 1))
{
am = 256 - am;
aaa = (a * am) >> 8;
p += im->w;
BLEND_RE(r, g, b, aaa, *p);
}
y += dy;
}
return __imlib_AddUpdate(NULL, x1, y2,
(x2 - x1 + 1), (y1 - y2 + 1));
}
}
break;
default:
break;
}
return NULL;
}
void
__imlib_draw_box(ImlibImage *im, int x, int y, int w, int h,
DATA8 r, DATA8 g, DATA8 b, DATA8 a,
ImlibOp op)
{
__imlib_draw_line(im, x, y, x + w - 1, y, r, g, b, a, op, 0);
__imlib_draw_line(im, x, y, x, y + h - 1, r, g, b, a, op, 0);
__imlib_draw_line(im, x, y + h - 1, x + w - 1, y + h - 1, r, g, b, a, op, 0);
__imlib_draw_line(im, x + w - 1, y, x + w - 1, y + h - 1, r, g, b, a, op, 0);
}
void
__imlib_draw_filled_box(ImlibImage *im, int x, int y, int w, int h,
DATA8 r, DATA8 g, DATA8 b, DATA8 a,
ImlibOp op)
{
int yy, xx, tmp;
DATA32 *p;
DATA8 nr, ng, nb, rr, gg, bb, aa, na;
if (x < 0)
{
w += x;
x = 0;
}
if (w <= 0)
return;
if ((x + w) > im->w)
w = (im->w - x);
if (w <= 0)
return;
if (y < 0)
{
h += y;
y = 0;
}
if (h <= 0)
return;
if ((y + h) > im->h)
h = (im->h - y);
if (h <= 0)
return;
switch (op)
{
case OP_COPY:
for (yy = 0; yy < h; yy++)
{
p = im->data + (y * im->w) + x;
for (xx = 0; xx < w; xx++)
{
BLEND(r, g, b, a, *p);
p++;
}
}
break;
case OP_ADD:
for (yy = 0; yy < h; yy++)
{
p = im->data + (y * im->w) + x;
for (xx = 0; xx < w; xx++)
{
BLEND_ADD(r, g, b, a, *p);
p++;
}
}
break;
case OP_SUBTRACT:
for (yy = 0; yy < h; yy++)
{
p = im->data + (y * im->w) + x;
for (xx = 0; xx < w; xx++)
{
BLEND_SUB(r, g, b, a, *p);
p++;
}
}
break;
case OP_RESHADE:
for (yy = 0; yy < h; yy++)
{
p = im->data + (y * im->w) + x;
for (xx = 0; xx < w; xx++)
{
BLEND_RE(r, g, b, a, *p);
p++;
}
}
break;
default:
break;
}
}
void
__imlib_copy_image_data(ImlibImage *im, int x, int y, int w, int h, int nx,
int ny)
{
int xx, yy, jump;
DATA32 *p1, *p2;
/* clip horizontal co-ordinates so that both dest and src fit inside */
/* the image */
if (x < 0)
{
w += x;
nx -= x;
x = 0;
}
if (w <= 0)
return;
if (nx < 0)
{
w += nx;
x -= nx;
nx = 0;
}
if (w <= 0)
return;
if ((x + w) > im->w)
w = (im->w - x);
if (w <= 0)
return;
if ((nx + w) > im->w)
w = (im->w - nx);
if (w <= 0)
return;
/* clip vertical co-ordinates so that both dest and src fit inside */
/* the image */
if (y < 0)
{
h += y;
ny -= y;
y = 0;
}
if (h <= 0)
return;
if (ny < 0)
{
h += ny;
y -= ny;
ny = 0;
}
if (h <= 0)
return;
if ((y + h) > im->h)
h = (im->h - y);
if (h <= 0)
return;
if ((ny + h) > im->h)
h = (im->h - ny);
if (h <= 0)
return;
/* figure out what our source and destnation start pointers are */
p1 = im->data + (y * im->w) + x;
p2 = im->data + (ny * im->w) + nx;
/* the pointer jump between lines */
jump = (im->w - w);
/* dest < src address - we can copy forwards */
if (p2 < p1)
{
/* work our way thru the array */
for (yy = 0; yy < h; yy++)
{
for (xx = 0; xx < w; xx++)
{
*p2 = *p1;
p1++;
p2++;
}
p1 += jump;
p2 += jump;
}
}
/* dst > src - we must copy backwards */
else
{
/* new pointers to start working at (bottom-right of rect) */
p1 = im->data + ((y + h - 1) * im->w) + x + w - 1;
p2 = im->data + ((ny + h - 1) * im->w) + nx + w - 1;
/* work our way thru the array */
for (yy = 0; yy < h; yy++)
{
for (xx = 0; xx < w; xx++)
{
*p2 = *p1;
p1--;
p2--;
}
p1 -= jump;
p2 -= jump;
}
}
}
void
__imlib_copy_alpha_data(ImlibImage *src, ImlibImage *dst,
int x, int y, int w, int h, int nx, int ny)
{
int xx, yy, jump, jump2;
DATA32 *p1, *p2;
/* clip horizontal co-ordinates so that both dest and src fit inside */
/* the image */
if (x < 0)
{
w += x;
nx -= x;
x = 0;
}
if (w <= 0)
return;
if (nx < 0)
{
w += nx;
x -= nx;
nx = 0;
}
if (w <= 0)
return;
if ((x + w) > src->w)
w = (src->w - x);
if (w <= 0)
return;
if ((nx + w) > dst->w)
w = (dst->w - nx);
if (w <= 0)
return;
/* clip vertical co-ordinates so that both dest and src fit inside */
/* the image */
if (y < 0)
{
h += y;
ny -= y;
y = 0;
}
if (h <= 0)
return;
if (ny < 0)
{
h += ny;
y -= ny;
ny = 0;
}
if (h <= 0)
return;
if ((y + h) > src->h)
h = (src->h - y);
if (h <= 0)
return;
if ((ny + h) > dst->h)
h = (dst->h - ny);
if (h <= 0)
return;
/* figure out what our source and destnation start pointers are */
p1 = src->data + (y * src->h) + x;
p2 = dst->data + (ny * dst->h) + nx;
/* the pointer jump between lines */
jump = (src->w - w);
jump2 = (dst->w - w);
/* copy forwards */
if (p2 < p1)
{
/* work our way thru the array */
for (yy = 0; yy < h; yy++)
{
for (xx = 0; xx < w; xx++)
{
*p2 = (*p1 & 0xff000000) | (*p2 & 0x00ffffff);
p1++;
p2++;
}
p1 += jump;
p2 += jump2;
}
}
}