mirror of
https://github.com/gnustep/libs-back.git
synced 2025-02-23 11:51:27 +00:00
Implement dissolving.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@14484 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
de72985141
commit
7ad3a88b9b
4 changed files with 506 additions and 5 deletions
|
@ -1,3 +1,8 @@
|
|||
2002-09-18 19:59 Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
* Source/art/blit.h, Source/art/blit.m, Source/art/composite.m:
|
||||
Implement -dissolveGState:fromRect:toPoint:delta:.
|
||||
|
||||
2002-09-18 00:36 Alexander Malmberg <alexander@malmberg.org>
|
||||
|
||||
* Source/art/image.m (-DPSimage:::::::::::): Treat input as
|
||||
|
|
|
@ -41,6 +41,7 @@ typedef struct
|
|||
{
|
||||
unsigned char *dst, *dsta;
|
||||
unsigned char *src, *srca;
|
||||
unsigned char fraction; /* for dissolving */
|
||||
} composite_run_t;
|
||||
|
||||
|
||||
|
@ -125,6 +126,11 @@ typedef struct draw_info_s
|
|||
void (*composite_plusd_oa)(composite_run_t *c, int num);
|
||||
void (*composite_plusd_ao)(composite_run_t *c, int num);
|
||||
void (*composite_plusd_oo)(composite_run_t *c, int num);
|
||||
|
||||
void (*dissolve_aa)(composite_run_t *c, int num);
|
||||
void (*dissolve_oa)(composite_run_t *c, int num);
|
||||
void (*dissolve_ao)(composite_run_t *c, int num);
|
||||
void (*dissolve_oo)(composite_run_t *c, int num);
|
||||
} draw_info_t;
|
||||
|
||||
#define RENDER_RUN_ALPHA (DI.render_run_alpha)
|
||||
|
|
|
@ -1122,6 +1122,128 @@ static void MPRE(plusd_ao_oo) (composite_run_t *c, int num)
|
|||
}
|
||||
|
||||
|
||||
static void MPRE(dissolve_aa) (composite_run_t *c, int num)
|
||||
{
|
||||
BLEND_TYPE *s = (BLEND_TYPE *)c->src, *d = (BLEND_TYPE *)c->dst;
|
||||
#ifndef INLINE_ALPHA
|
||||
unsigned char *src_alpha = c->srca,
|
||||
*dst_alpha = c->dsta;
|
||||
#endif
|
||||
int sr, sg, sb, sa, dr, dg, db, da;
|
||||
int fraction = c->fraction;
|
||||
|
||||
for (; num; num--)
|
||||
{
|
||||
BLEND_READ_ALPHA(s, src_alpha, sr, sg, sb, sa)
|
||||
BLEND_READ_ALPHA(d, dst_alpha, dr, dg, db, da)
|
||||
|
||||
sr = (sr * fraction + 0xff) >> 8;
|
||||
sg = (sg * fraction + 0xff) >> 8;
|
||||
sb = (sb * fraction + 0xff) >> 8;
|
||||
sa = (sa * fraction + 0xff) >> 8;
|
||||
|
||||
da = sa + ((da * (255 - sa) + 0xff) >> 8);
|
||||
sa = 255 - sa;
|
||||
dr = sr + ((dr * sa + 0xff) >> 8);
|
||||
dg = sg + ((dg * sa + 0xff) >> 8);
|
||||
db = sb + ((db * sa + 0xff) >> 8);
|
||||
|
||||
BLEND_WRITE_ALPHA(d, dst_alpha, dr, dg, db, da)
|
||||
|
||||
ALPHA_INC(s, src_alpha)
|
||||
ALPHA_INC(d, dst_alpha)
|
||||
}
|
||||
}
|
||||
static void MPRE(dissolve_ao) (composite_run_t *c, int num)
|
||||
{
|
||||
BLEND_TYPE *s = (BLEND_TYPE *)c->src, *d = (BLEND_TYPE *)c->dst;
|
||||
#ifndef INLINE_ALPHA
|
||||
unsigned char *src_alpha = c->srca;
|
||||
#endif
|
||||
int sr, sg, sb, sa, dr, dg, db;
|
||||
int fraction = c->fraction;
|
||||
|
||||
for (; num; num--)
|
||||
{
|
||||
BLEND_READ_ALPHA(s, src_alpha, sr, sg, sb, sa)
|
||||
BLEND_READ(d, dr, dg, db)
|
||||
|
||||
sr = (sr * fraction + 0xff) >> 8;
|
||||
sg = (sg * fraction + 0xff) >> 8;
|
||||
sb = (sb * fraction + 0xff) >> 8;
|
||||
sa = (sa * fraction + 0xff) >> 8;
|
||||
|
||||
sa = 255 - sa;
|
||||
dr = sr + ((dr * sa + 0xff) >> 8);
|
||||
dg = sg + ((dg * sa + 0xff) >> 8);
|
||||
db = sb + ((db * sa + 0xff) >> 8);
|
||||
|
||||
BLEND_WRITE(d, dr, dg, db)
|
||||
|
||||
ALPHA_INC(s, src_alpha)
|
||||
BLEND_INC(d)
|
||||
}
|
||||
}
|
||||
static void MPRE(dissolve_oa) (composite_run_t *c, int num)
|
||||
{
|
||||
BLEND_TYPE *s = (BLEND_TYPE *)c->src, *d = (BLEND_TYPE *)c->dst;
|
||||
#ifndef INLINE_ALPHA
|
||||
unsigned char *dst_alpha = c->dsta;
|
||||
#endif
|
||||
int sr, sg, sb, sa, dr, dg, db, da;
|
||||
int fraction = c->fraction;
|
||||
|
||||
for (; num; num--)
|
||||
{
|
||||
BLEND_READ(s, sr, sg, sb)
|
||||
BLEND_READ_ALPHA(d, dst_alpha, dr, dg, db, da)
|
||||
|
||||
sr = (sr * fraction + 0xff) >> 8;
|
||||
sg = (sg * fraction + 0xff) >> 8;
|
||||
sb = (sb * fraction + 0xff) >> 8;
|
||||
sa = fraction;
|
||||
|
||||
da = sa + ((da * (255 - sa) + 0xff) >> 8);
|
||||
sa = 255 - sa;
|
||||
dr = sr + ((dr * sa + 0xff) >> 8);
|
||||
dg = sg + ((dg * sa + 0xff) >> 8);
|
||||
db = sb + ((db * sa + 0xff) >> 8);
|
||||
|
||||
BLEND_WRITE_ALPHA(d, dst_alpha, dr, dg, db, da)
|
||||
|
||||
BLEND_INC(s)
|
||||
ALPHA_INC(d, dst_alpha)
|
||||
}
|
||||
}
|
||||
static void MPRE(dissolve_oo) (composite_run_t *c, int num)
|
||||
{
|
||||
BLEND_TYPE *s = (BLEND_TYPE *)c->src, *d = (BLEND_TYPE *)c->dst;
|
||||
int sr, sg, sb, sa, dr, dg, db;
|
||||
int fraction = c->fraction;
|
||||
|
||||
for (; num; num--)
|
||||
{
|
||||
BLEND_READ(s, sr, sg, sb)
|
||||
BLEND_READ(d, dr, dg, db)
|
||||
|
||||
sr = (sr * fraction + 0xff) >> 8;
|
||||
sg = (sg * fraction + 0xff) >> 8;
|
||||
sb = (sb * fraction + 0xff) >> 8;
|
||||
sa = fraction;
|
||||
|
||||
sa = 255 - sa;
|
||||
dr = sr + ((dr * sa + 0xff) >> 8);
|
||||
dg = sg + ((dg * sa + 0xff) >> 8);
|
||||
db = sb + ((db * sa + 0xff) >> 8);
|
||||
|
||||
BLEND_WRITE(d, dr, dg, db)
|
||||
|
||||
BLEND_INC(s)
|
||||
BLEND_INC(d)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#undef I_NAME
|
||||
#undef BLEND_TYPE
|
||||
#undef BLEND_READ
|
||||
|
@ -1450,6 +1572,10 @@ static draw_info_t draw_infos[DI_NUM] = {
|
|||
NPRE(plusd_oa,x), \
|
||||
NPRE(plusd_ao_oo,x), \
|
||||
NPRE(plusd_ao_oo,x), \
|
||||
NPRE(dissolve_aa,x), \
|
||||
NPRE(dissolve_oa,x), \
|
||||
NPRE(dissolve_ao,x), \
|
||||
NPRE(dissolve_oo,x),
|
||||
|
||||
/* TODO: try to implement fallback versions? possible? */
|
||||
{DI_FALLBACK ,0, 0,0,-1,/*C(fallback)*/},
|
||||
|
|
|
@ -825,12 +825,376 @@ static BOOL _rect_advance(rect_trace_t *t, int *x0, int *x1)
|
|||
- (void) dissolveGState: (GSGState *)source
|
||||
fromRect: (NSRect)aRect
|
||||
toPoint: (NSPoint)aPoint
|
||||
delta: (float)delta
|
||||
delta: (float)fraction
|
||||
{
|
||||
NSLog(@"ignoring dissolveGState: %08x fromRect: (%g %g)+(%g %g) toPoint: (%g %g) delta: %g",
|
||||
source,
|
||||
aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height,
|
||||
aPoint.x, aPoint.y, delta);
|
||||
/* much setup code shared with compositeGState:... */
|
||||
ARTGState *ags = (ARTGState *)source;
|
||||
unsigned char *dst, *dst_alpha, *src, *src_alpha;
|
||||
|
||||
void (*blit_func)(composite_run_t *c, int num) = NULL;
|
||||
|
||||
NSPoint sp, dp;
|
||||
|
||||
int cx0,cy0,cx1,cy1;
|
||||
int sx0,sy0;
|
||||
|
||||
int sbpl, dbpl;
|
||||
int asbpl, adbpl;
|
||||
|
||||
rect_trace_t state;
|
||||
|
||||
/* 0 = top->down, 1 = bottom->up */
|
||||
/*
|
||||
TODO: this does not handle the horizontal case
|
||||
either 0=top->down, left->right, 2=top->down, right->left
|
||||
or keep 0 and add 2=top->down, make temporary copy of source
|
||||
could allocate a temporary array on the stack large enough to hold
|
||||
one row and do the operations on it
|
||||
*/
|
||||
/* currently 2=top->down, be careful with overlapping rows */
|
||||
/* order=1 is handled generically by flipping sbpl and dbpl and
|
||||
adjusting the pointers. order=2 is handled specially */
|
||||
int order;
|
||||
|
||||
int delta;
|
||||
|
||||
|
||||
if (!wi || !wi->data || !ags->wi || !ags->wi->data) return;
|
||||
if (all_clipped) return;
|
||||
|
||||
|
||||
/* Set up all the pointers and clip things */
|
||||
|
||||
dbpl = wi->bytes_per_line;
|
||||
sbpl = ags->wi->bytes_per_line;
|
||||
|
||||
cx0 = clip_x0;
|
||||
cy0 = clip_y0;
|
||||
cx1 = clip_x1;
|
||||
cy1 = clip_y1;
|
||||
|
||||
sp = [ags->ctm pointInMatrixSpace: aRect.origin];
|
||||
sp.x = floor(sp.x);
|
||||
sp.y = floor(ags->wi->sy - sp.y);
|
||||
dp = [ctm pointInMatrixSpace: aPoint];
|
||||
dp.x = floor(dp.x);
|
||||
dp.y = floor(wi->sy - dp.y);
|
||||
|
||||
if (dp.x - cx0 > sp.x)
|
||||
cx0 = dp.x - sp.x;
|
||||
if (dp.y - cy0 > sp.y)
|
||||
cy0 = dp.y - sp.y;
|
||||
|
||||
if (cx1 - dp.x > ags->wi->sx - sp.x)
|
||||
cx1 = dp.x + ags->wi->sx - sp.x;
|
||||
if (cy1 - dp.y > ags->wi->sy - sp.y)
|
||||
cy1 = dp.y + ags->wi->sy - sp.y;
|
||||
|
||||
sx0 = sp.x - dp.x + cx0;
|
||||
sy0 = sp.y - dp.y + cy0;
|
||||
|
||||
dst = wi->data + cx0 * DI.bytes_per_pixel + cy0 * dbpl;
|
||||
src = ags->wi->data + sx0 * DI.bytes_per_pixel + sy0 * sbpl;
|
||||
|
||||
if (ags->wi->has_alpha)
|
||||
{
|
||||
if (DI.inline_alpha)
|
||||
src_alpha = src;
|
||||
else
|
||||
src_alpha = ags->wi->alpha + sx0 + sy0 * ags->wi->sx;
|
||||
asbpl = ags->wi->sx;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_alpha = NULL;
|
||||
asbpl = 0;
|
||||
}
|
||||
|
||||
if (wi->has_alpha)
|
||||
{
|
||||
if (DI.inline_alpha)
|
||||
dst_alpha = dst;
|
||||
else
|
||||
dst_alpha = wi->alpha + cx0 + cy0 * wi->sx;
|
||||
adbpl = wi->sx;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_alpha = NULL;
|
||||
adbpl = 0;
|
||||
}
|
||||
|
||||
cy1 -= cy0;
|
||||
cx1 -= cx0;
|
||||
|
||||
if (cx0<0 || cy0<0 || cx0+cx1>wi->sx || cy0+cy1>wi->sy ||
|
||||
sx0<0 || sy0<0 || sx0+cx1>ags->wi->sx || sy0+cy1>ags->wi->sy)
|
||||
{
|
||||
NSLog(@"Warning: invalid coordinates in dissolve: (%g %g)+(%g %g) -> (%g %g) got (%i %i) (%i %i) +(%i %i)",
|
||||
aRect.origin.x,aRect.origin.x,aRect.size.width,aRect.size.height,aPoint.x,aPoint.y,
|
||||
cx0,cy0,sx0,sy0,cx1,cy1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cx1<=0 || cy1<=0)
|
||||
return;
|
||||
|
||||
/* To handle overlapping areas properly, we sometimes need to do
|
||||
things bottom-up instead of top-down. If so, we flip the
|
||||
coordinates here. */
|
||||
order = 0;
|
||||
if (ags == self && sy0 <= cy0)
|
||||
{
|
||||
order = 1;
|
||||
dst += dbpl * (cy1 - 1);
|
||||
src += sbpl * (cy1 - 1);
|
||||
dst_alpha += adbpl * (cy1 - 1);
|
||||
src_alpha += asbpl * (cy1 - 1);
|
||||
dbpl = -dbpl;
|
||||
sbpl = -sbpl;
|
||||
adbpl = -adbpl;
|
||||
asbpl = -asbpl;
|
||||
if (sy0 == cy0)
|
||||
{
|
||||
if ((sx0 >= cx0 && sx0 <= cx0 + cx1) || (cx0 >= sx0 && cx0 <= sx0 + cx1))
|
||||
{
|
||||
order = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ags->wi->has_alpha && wi->has_alpha)
|
||||
blit_func = DI.dissolve_aa;
|
||||
else if (wi->has_alpha)
|
||||
blit_func = DI.dissolve_oa;
|
||||
else if (ags->wi->has_alpha)
|
||||
blit_func = DI.dissolve_ao;
|
||||
else
|
||||
blit_func = DI.dissolve_oo;
|
||||
|
||||
if (!blit_func)
|
||||
{
|
||||
NSLog(@"unimplemented: dissolveGState: %p fromRect: (%g %g)+(%g %g) toPoint: (%g %g) delta: %g",
|
||||
source,
|
||||
aRect.origin.x, aRect.origin.y,
|
||||
aRect.size.width, aRect.size.height,
|
||||
aPoint.x, aPoint.y,
|
||||
fraction);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
int ry;
|
||||
int x0, x1;
|
||||
_rect_setup(&state, aRect, sx0, sx0 + cx1, ags->ctm, order, &ry, ags->wi->sy);
|
||||
if (order)
|
||||
{
|
||||
if (ry < sy0)
|
||||
return;
|
||||
delta = sy0 + cy1 - ry;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ry >= sy0 + cy1)
|
||||
return;
|
||||
delta = ry - sy0;
|
||||
}
|
||||
|
||||
if (delta > 0)
|
||||
{
|
||||
src += sbpl * delta;
|
||||
src_alpha += asbpl * delta;
|
||||
dst += dbpl * delta;
|
||||
dst_alpha += adbpl * delta;
|
||||
}
|
||||
else if (delta < 0)
|
||||
{
|
||||
delta = -delta;
|
||||
while (delta)
|
||||
{
|
||||
if (!_rect_advance(&state,&x0,&x1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
delta--;
|
||||
}
|
||||
if (delta)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* this breaks the alpha pointer in some, but that's ok since in
|
||||
all those cases, the alpha pointer isn't used (inline alpha or
|
||||
no alpha) */
|
||||
if (order == 2)
|
||||
{
|
||||
unsigned char tmpbuf[cx1 * DI.bytes_per_pixel];
|
||||
unsigned char tmpbufa[cx1];
|
||||
int y;
|
||||
composite_run_t c;
|
||||
int x0, x1;
|
||||
|
||||
c.dst = dst;
|
||||
c.dsta = dst_alpha;
|
||||
c.src = tmpbuf;
|
||||
c.srca = tmpbufa;
|
||||
c.fraction = fraction * 255;
|
||||
for (y = cy1 - delta - 1; y >= 0; y--)
|
||||
{
|
||||
if (!_rect_advance(&state,&x0,&x1))
|
||||
break;
|
||||
x1 -= x0;
|
||||
|
||||
c.dst += x0 * DI.bytes_per_pixel;
|
||||
c.dsta += x0;
|
||||
|
||||
if (x1)
|
||||
{
|
||||
memcpy(tmpbuf, src + x0 * DI.bytes_per_pixel, x1 * DI.bytes_per_pixel);
|
||||
if (ags->wi->has_alpha && !DI.inline_alpha)
|
||||
memcpy(tmpbufa, src_alpha + x0, x1);
|
||||
|
||||
if (!clip_span)
|
||||
{
|
||||
blit_func(&c, x1);
|
||||
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
||||
c.dsta += adbpl - x0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int *span, *end;
|
||||
BOOL state = NO;
|
||||
|
||||
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
||||
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
||||
|
||||
x0 = x0 + cx0 - clip_x0;
|
||||
x1 += x0;
|
||||
while (span != end && *span < x0)
|
||||
{
|
||||
state = !state;
|
||||
span++;
|
||||
if (span == end)
|
||||
break;
|
||||
}
|
||||
if (span != end)
|
||||
{
|
||||
while (span != end && *span < x1)
|
||||
{
|
||||
if (state)
|
||||
blit_func(&c, *span - x0);
|
||||
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
||||
c.dsta += (*span - x0);
|
||||
c.src += (*span - x0) * DI.bytes_per_pixel;
|
||||
c.srca += (*span - x0);
|
||||
x0 = *span;
|
||||
|
||||
state = !state;
|
||||
span++;
|
||||
if (span == end)
|
||||
break;
|
||||
}
|
||||
if (state)
|
||||
blit_func(&c, x1 - x0);
|
||||
}
|
||||
x0 = x0 - cx0 + clip_x0;
|
||||
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
||||
c.dsta += adbpl - x0;
|
||||
c.src = tmpbuf;
|
||||
c.srca = tmpbufa;
|
||||
}
|
||||
}
|
||||
|
||||
src += sbpl;
|
||||
src_alpha += asbpl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int y;
|
||||
composite_run_t c;
|
||||
int x0, x1;
|
||||
|
||||
c.dst = dst;
|
||||
c.dsta = dst_alpha;
|
||||
c.src = src;
|
||||
c.srca = src_alpha;
|
||||
c.fraction = fraction * 255;
|
||||
if (order)
|
||||
y = cy1 - delta - 1;
|
||||
else
|
||||
y = delta;
|
||||
for (; y < cy1 && y >= 0; order? y-- : y++)
|
||||
{
|
||||
if (!_rect_advance(&state,&x0,&x1))
|
||||
break;
|
||||
x1 -= x0;
|
||||
if (x1 <= 0)
|
||||
{
|
||||
c.dst += dbpl;
|
||||
c.dsta += adbpl;
|
||||
c.src += sbpl;
|
||||
c.srca += asbpl;
|
||||
continue;
|
||||
}
|
||||
c.dst += x0 * DI.bytes_per_pixel;
|
||||
c.dsta += x0;
|
||||
c.src += x0 * DI.bytes_per_pixel;
|
||||
c.srca += x0;
|
||||
if (!clip_span)
|
||||
{
|
||||
blit_func(&c, x1);
|
||||
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
||||
c.dsta += adbpl - x0;
|
||||
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
||||
c.srca += asbpl - x0;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int *span, *end;
|
||||
BOOL state = NO;
|
||||
|
||||
span = &clip_span[clip_index[y + cy0 - clip_y0]];
|
||||
end = &clip_span[clip_index[y + cy0 - clip_y0 + 1]];
|
||||
|
||||
x0 = x0 + cx0 - clip_x0;
|
||||
x1 += x0;
|
||||
while (span != end && *span < x0)
|
||||
{
|
||||
state = !state;
|
||||
span++;
|
||||
if (span == end)
|
||||
break;
|
||||
}
|
||||
if (span != end)
|
||||
{
|
||||
while (span != end && *span < x1)
|
||||
{
|
||||
if (state)
|
||||
blit_func(&c, *span - x0);
|
||||
c.dst += (*span - x0) * DI.bytes_per_pixel;
|
||||
c.dsta += (*span - x0);
|
||||
c.src += (*span - x0) * DI.bytes_per_pixel;
|
||||
c.srca += (*span - x0);
|
||||
x0 = *span;
|
||||
|
||||
state = !state;
|
||||
span++;
|
||||
if (span == end)
|
||||
break;
|
||||
}
|
||||
if (state)
|
||||
blit_func(&c, x1 - x0);
|
||||
}
|
||||
x0 = x0 - cx0 + clip_x0;
|
||||
c.dst += dbpl - x0 * DI.bytes_per_pixel;
|
||||
c.dsta += adbpl - x0;
|
||||
c.src += sbpl - x0 * DI.bytes_per_pixel;
|
||||
c.srca += asbpl - x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
UPDATE_UNBUFFERED
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue