diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-12-09 03:35:01 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2013-12-09 03:35:01 +0100 |
commit | 71dbddef166f855e28dfae1989ddbd663d38176a (patch) | |
tree | ad74b330dc2aed585e5eab98298bd766d559835e /sys/src/libmemdraw/draw.c | |
parent | 193e55b88cec346a4c3f301057aef692a859b642 (diff) |
draw: fix drawing of replicated source image on memlayer with a clip rectangle
when a replicated source image with a clipr with clipr.min > Pt(0, 0),
drawclip() would properly translate the src->clipr on the dstr
but then clamp the source rectangle back on src->r.
while traversing down multiple layers, this would cause the translation to
be applied multiple times to the dst rectangle giving the wrong image result.
this change adds a new drawclipnorepl() function that avoids the clamping
of source and mask rectangles to src->r and mask->r. this is then used in
libmemlayer.
the final memimagedraw() call will call drawclip() which will do the final
claming.
a testcase is provided:
#include <u.h>
#include <libc.h>
#include <draw.h>
Image *blue;
Image *red;
void
main(int, char *argv[])
{
Image *i;
if(initdraw(nil, nil, argv[0]) < 0)
sysfatal("initdraw: %r");
i = allocimage(display, screen->r, screen->chan, 1, DWhite);
red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
blue = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPaleblue);
replclipr(red, 1, Rect(10, 10, 110, 110));
replclipr(blue, 1, Rect(11, 11, 111, 111));
/* draw on non-layer, works correctly */
draw(i, i->r, red, nil, ZP);
draw(i, i->r, blue, nil, ZP);
draw(screen, screen->r, i, nil, i->r.min);
flushimage(display, 1);
/* draw on (screen) layer is too far to the right */
draw(screen, screen->r, red, nil, ZP);
draw(screen, screen->r, blue, nil, ZP);
flushimage(display, 1);
for(;;){
sleep(1000);
}
}
Diffstat (limited to 'sys/src/libmemdraw/draw.c')
-rw-r--r-- | sys/src/libmemdraw/draw.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/sys/src/libmemdraw/draw.c b/sys/src/libmemdraw/draw.c index 96cb01e44..3bd5ff0e7 100644 --- a/sys/src/libmemdraw/draw.c +++ b/sys/src/libmemdraw/draw.c @@ -213,17 +213,16 @@ DBG print("alphadraw handled\n"); } #undef DBG + /* * Clip the destination rectangle further based on the properties of the * source and mask rectangles. Once the destination rectangle is properly * clipped, adjust the source and mask rectangles to be the same size. - * Then if source or mask is replicated, move its clipped rectangle - * so that its minimum point falls within the repl rectangle. * * Return zero if the final rectangle is null. */ int -drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr) +drawclipnorepl(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr) { Point rmin, delta; int splitcoords; @@ -270,15 +269,13 @@ drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, sr->min.y += mr->min.y-omr.min.y; sr->max.x += mr->max.x-omr.max.x; sr->max.y += mr->max.y-omr.max.y; - *p1 = mr->min; }else{ if(!(mask->flags&Frepl) && !rectclip(sr, mask->r)) return 0; if(!rectclip(sr, mask->clipr)) return 0; - *p1 = sr->min; + *mr = *sr; } - /* move source clipping back to destination */ delta.x = r->min.x - p0->x; delta.y = r->min.y - p0->y; @@ -286,6 +283,30 @@ drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, r->min.y = sr->min.y + delta.y; r->max.x = sr->max.x + delta.x; r->max.y = sr->max.y + delta.y; + *p0 = sr->min; + *p1 = mr->min; + + assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r)); + assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r)); + assert(ptinrect(r->min, dst->r)); + + return 1; +} + +/* + * like drawclipnorepl() above, but if source or mask is replicated, + * move its clipped rectangle so that its minimum point falls within + * the repl rectangle. + * + * Return zero if the final rectangle is null. + */ +int +drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, Point *p1, Rectangle *sr, Rectangle *mr) +{ + Point delta; + + if(!drawclipnorepl(dst, r, src, p0, mask, p1, sr, mr)) + return 0; /* move source rectangle so sr->min is in src->r */ if(src->flags&Frepl) { @@ -295,8 +316,8 @@ drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, sr->min.y += delta.y; sr->max.x += delta.x; sr->max.y += delta.y; + *p0 = sr->min; } - *p0 = sr->min; /* move mask point so it is in mask->r */ *p1 = drawrepl(mask->r, *p1); @@ -304,11 +325,8 @@ drawclip(Memimage *dst, Rectangle *r, Memimage *src, Point *p0, Memimage *mask, mr->max.x = p1->x+Dx(*sr); mr->max.y = p1->y+Dy(*sr); - assert(Dx(*sr) == Dx(*mr) && Dx(*mr) == Dx(*r)); - assert(Dy(*sr) == Dy(*mr) && Dy(*mr) == Dy(*r)); assert(ptinrect(*p0, src->r)); assert(ptinrect(*p1, mask->r)); - assert(ptinrect(r->min, dst->r)); return 1; } |