📄 draw.c
字号:
dy = Dy(r); z = allocdbuf(); if(z == nil) return 0; src = par->src; mask = par->mask; dst = par->dst; sr = par->sr; mr = par->mr; op = par->op; isgrey = dst->flags&Fgrey; /* * Buffering when src and dst are the same bitmap is sufficient but not * necessary. There are stronger conditions we could use. We could * check to see if the rectangles intersect, and if simply moving in the * correct y direction can avoid the need to buffer. */ needbuf = (src->data == dst->data); ndrawbuf = 0; getparam(&z->spar, src, sr, isgrey, needbuf, &ndrawbuf); getparam(&z->dpar, dst, r, isgrey, needbuf, &ndrawbuf); getparam(&z->mpar, mask, mr, 0, needbuf, &ndrawbuf); dir = (needbuf && byteaddr(dst, r.min) > byteaddr(src, sr.min)) ? -1 : 1; z->spar.dir = z->mpar.dir = z->dpar.dir = dir; /* * If the mask is purely boolean, we can convert from src to dst format * when we read src, and then just copy it to dst where the mask tells us to. * This requires a boolean (1-bit grey) mask and lack of a source alpha channel. * * The computation is accomplished by assigning the function pointers as follows: * rdsrc - read and convert source into dst format in a buffer * rdmask - convert mask to bytes, set pointer to it * rddst - fill with pointer to real dst data, but do no reads * calc - copy src onto dst when mask says to. * wrdst - do nothing * This is slightly sleazy, since things aren't doing exactly what their names say, * but it avoids a fair amount of code duplication to make this a case here * rather than have a separate booldraw. *///if(drawdebug) iprint("flag %lud mchan %lux=?%x dd %d\n", src->flags&Falpha, mask->chan, GREY1, dst->depth); if(!(src->flags&Falpha) && mask->chan == GREY1 && dst->depth >= 8 && op == SoverD){//if(drawdebug) iprint("boolcopy..."); rdsrc = convfn(dst, &z->dpar, src, &z->spar, &ndrawbuf); rddst = readptr; rdmask = readfn(mask); calc = boolcopyfn(dst, mask); wrdst = nullwrite; }else{ /* usual alphadraw parameter fetching */ rdsrc = readfn(src); rddst = readfn(dst); wrdst = writefn(dst); calc = alphacalc[op]; /* * If there is no alpha channel, we'll ask for a grey channel * and pretend it is the alpha. */ if(mask->flags&Falpha){ rdmask = readalphafn(mask); z->mpar.alphaonly = 1; }else{ z->mpar.greymaskcall = readfn(mask); z->mpar.convgrey = 1; rdmask = greymaskread; /* * Should really be above, but then boolcopyfns would have * to deal with bit alignment, and I haven't written that. * * This is a common case for things like ellipse drawing. * When there's no alpha involved and the mask is boolean, * we can avoid all the division and multiplication. */ if(mask->chan == GREY1 && !(src->flags&Falpha)) calc = boolcalc[op]; else if(op == SoverD && !(src->flags&Falpha)) calc = alphacalcS; } } /* * If the image has a small enough repl rectangle, * we can just read each line once and cache them. */ if(z->spar.replcache){ z->spar.replcall = rdsrc; rdsrc = replread; } if(z->mpar.replcache){ z->mpar.replcall = rdmask; rdmask = replread; } if(z->n < ndrawbuf){ free(z->p); if((z->p = mallocz(ndrawbuf, 0)) == nil){ z->inuse = 0; return 0; } z->n = ndrawbuf; } drawbuf = z->p; /* * Before we were saving only offsets from drawbuf in the parameter * structures; now that drawbuf has been grown to accomodate us, * we can fill in the pointers. */ z->spar.bufbase = drawbuf+z->spar.bufoff; z->mpar.bufbase = drawbuf+z->mpar.bufoff; z->dpar.bufbase = drawbuf+z->dpar.bufoff; z->spar.convbuf = drawbuf+z->spar.convbufoff; if(dir == 1){ starty = 0; endy = dy; }else{ starty = dy-1; endy = -1; } /* * srcy, masky, and dsty are offsets from the top of their * respective Rectangles. they need to be contained within * the rectangles, so clipy can keep them there without division. */ srcy = (starty + sr.min.y - src->r.min.y)%Dy(src->r); masky = (starty + mr.min.y - mask->r.min.y)%Dy(mask->r); dsty = starty + r.min.y - dst->r.min.y; assert(0 <= srcy && srcy < Dy(src->r)); assert(0 <= masky && masky < Dy(mask->r)); assert(0 <= dsty && dsty < Dy(dst->r)); for(y=starty; y!=endy; y+=dir, srcy+=dir, masky+=dir, dsty+=dir){ clipy(src, &srcy); clipy(dst, &dsty); clipy(mask, &masky); bsrc = rdsrc(&z->spar, z->spar.bufbase, srcy);DBG print("["); bmask = rdmask(&z->mpar, z->mpar.bufbase, masky);DBG print("]\n"); bdst = rddst(&z->dpar, z->dpar.bufbase, dsty);DBG dumpbuf("src", bsrc, dx);DBG dumpbuf("mask", bmask, dx);DBG dumpbuf("dst", bdst, dx); bdst = calc(bdst, bsrc, bmask, dx, isgrey, op); wrdst(&z->dpar, z->dpar.bytermin+dsty*z->dpar.bwidth, bdst); } z->inuse = 0; return 1;}#undef DBGstatic Bufferalphacalc0(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op){ USED(grey); USED(op); USED(b1); USED(b2); memset(bdst.rgba, 0, dx*bdst.delta); return bdst;}static Bufferalphacalc14(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fd, sadelta; int i, sa, ma, q; ulong s, t; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; q = bsrc.delta == 4 && bdst.delta == 4; for(i=0; i<dx; i++){ sa = *bsrc.alpha; ma = *bmask.alpha; fd = MUL(sa, ma, t); if(op == DoutS) fd = 255-fd; if(grey){ *bdst.grey = MUL(fd, *bdst.grey, t); bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(q){ *bdst.rgba = MUL0123(fd, *bdst.rgba, s, t); bsrc.rgba++; bdst.rgba++; bsrc.alpha += sadelta; bmask.alpha += bmask.delta; continue; } *bdst.red = MUL(fd, *bdst.red, t); *bdst.grn = MUL(fd, *bdst.grn, t); *bdst.blu = MUL(fd, *bdst.blu, t); bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = MUL(fd, *bdst.alpha, t); bdst.alpha += bdst.delta; } bmask.alpha += bmask.delta; bsrc.alpha += sadelta; } return obdst;}static Bufferalphacalc2810(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fs, sadelta; int i, ma, da, q; ulong s, t; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; q = bsrc.delta == 4 && bdst.delta == 4; for(i=0; i<dx; i++){ ma = *bmask.alpha; da = *bdst.alpha; if(op == SoutD) da = 255-da; fs = ma; if(op != S) fs = MUL(fs, da, t); if(grey){ *bdst.grey = MUL(fs, *bsrc.grey, t); bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(q){ *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t); bsrc.rgba++; bdst.rgba++; bmask.alpha += bmask.delta; bdst.alpha += bdst.delta; continue; } *bdst.red = MUL(fs, *bsrc.red, t); *bdst.grn = MUL(fs, *bsrc.grn, t); *bdst.blu = MUL(fs, *bsrc.blu, t); bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = MUL(fs, *bsrc.alpha, t); bdst.alpha += bdst.delta; } bmask.alpha += bmask.delta; bsrc.alpha += sadelta; } return obdst;}static Bufferalphacalc3679(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fs, fd, sadelta; int i, sa, ma, da, q; ulong s, t, u, v; obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; q = bsrc.delta == 4 && bdst.delta == 4; for(i=0; i<dx; i++){ sa = *bsrc.alpha; ma = *bmask.alpha; da = *bdst.alpha; if(op == SatopD) fs = MUL(ma, da, t); else fs = MUL(ma, 255-da, t); if(op == DoverS) fd = 255; else{ fd = MUL(sa, ma, t); if(op != DatopS) fd = 255-fd; } if(grey){ *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(q){ *bdst.rgba = MUL0123(fs, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v); bsrc.rgba++; bdst.rgba++; bsrc.alpha += sadelta; bmask.alpha += bmask.delta; bdst.alpha += bdst.delta; continue; } *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t); *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = MUL(fs, sa, s)+MUL(fd, da, t); bdst.alpha += bdst.delta; } bmask.alpha += bmask.delta; bsrc.alpha += sadelta; } return obdst;}static Bufferalphacalc5(Buffer bdst, Buffer b1, Buffer b2, int dx, int grey, int op){ USED(dx); USED(grey); USED(op); USED(b1); USED(b2); return bdst;}static Bufferalphacalc11(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fd, sadelta; int i, sa, ma, q; ulong s, t, u, v; USED(op); obdst = bdst; sadelta = bsrc.alpha == &ones ? 0 : bsrc.delta; q = bsrc.delta == 4 && bdst.delta == 4; for(i=0; i<dx; i++){ sa = *bsrc.alpha; ma = *bmask.alpha; fd = 255-MUL(sa, ma, t); if(grey){ *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(q){ *bdst.rgba = MUL0123(ma, *bsrc.rgba, s, t)+MUL0123(fd, *bdst.rgba, u, v); bsrc.rgba++; bdst.rgba++; bsrc.alpha += sadelta; bmask.alpha += bmask.delta; continue; } *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t); *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = MUL(ma, sa, s)+MUL(fd, *bdst.alpha, t); bdst.alpha += bdst.delta; } bmask.alpha += bmask.delta; bsrc.alpha += sadelta; } return obdst;}/*not used yetsource and mask alpha 1static BufferalphacalcS0(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int i; USED(op); obdst = bdst; if(bsrc.delta == bdst.delta){ memmove(bdst.rgba, bsrc.rgba, dx*bdst.delta); return obdst; } for(i=0; i<dx; i++){ if(grey){ *bdst.grey = *bsrc.grey; bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ *bdst.red = *bsrc.red; *bdst.grn = *bsrc.grn; *bdst.blu = *bsrc.blu; bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = 255; bdst.alpha += bdst.delta; } } return obdst;}*//* source alpha 1 */static BufferalphacalcS(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fd; int i, ma; ulong s, t; USED(op); obdst = bdst; for(i=0; i<dx; i++){ ma = *bmask.alpha; fd = 255-ma; if(grey){ *bdst.grey = MUL(ma, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ *bdst.red = MUL(ma, *bsrc.red, s)+MUL(fd, *bdst.red, t); *bdst.grn = MUL(ma, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); *bdst.blu = MUL(ma, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } if(bdst.alpha != &ones){ *bdst.alpha = ma+MUL(fd, *bdst.alpha, t); bdst.alpha += bdst.delta; } bmask.alpha += bmask.delta; } return obdst;}static Bufferboolcalc14(Buffer bdst, Buffer b1, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int i, ma, zero; USED(b1); obdst = bdst; for(i=0; i<dx; i++){ ma = *bmask.alpha; zero = ma ? op == DoutS : op == DinS; if(grey){ if(zero) *bdst.grey = 0; bdst.grey += bdst.delta; }else{ if(zero) *bdst.red = *bdst.grn = *bdst.blu = 0; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } bmask.alpha += bmask.delta; if(bdst.alpha != &ones){ if(zero) *bdst.alpha = 0; bdst.alpha += bdst.delta; } } return obdst;}static Bufferboolcalc236789(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int fs, fd; int i, ma, da, zero; ulong s, t; obdst = bdst; zero = !(op&1); for(i=0; i<dx; i++){ ma = *bmask.alpha; da = *bdst.alpha; fs = da; if(op&2) fs = 255-da; fd = 0; if(op&4) fd = 255; if(grey){ if(ma) *bdst.grey = MUL(fs, *bsrc.grey, s)+MUL(fd, *bdst.grey, t); else if(zero) *bdst.grey = 0; bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(ma){ *bdst.red = MUL(fs, *bsrc.red, s)+MUL(fd, *bdst.red, t); *bdst.grn = MUL(fs, *bsrc.grn, s)+MUL(fd, *bdst.grn, t); *bdst.blu = MUL(fs, *bsrc.blu, s)+MUL(fd, *bdst.blu, t); } else if(zero) *bdst.red = *bdst.grn = *bdst.blu = 0; bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } bmask.alpha += bmask.delta; if(bdst.alpha != &ones){ if(ma) *bdst.alpha = fs+MUL(fd, da, t); else if(zero) *bdst.alpha = 0; bdst.alpha += bdst.delta; } } return obdst;}static Bufferboolcalc1011(Buffer bdst, Buffer bsrc, Buffer bmask, int dx, int grey, int op){ Buffer obdst; int i, ma, zero; obdst = bdst; zero = !(op&1); for(i=0; i<dx; i++){ ma = *bmask.alpha; if(grey){ if(ma) *bdst.grey = *bsrc.grey; else if(zero) *bdst.grey = 0; bsrc.grey += bsrc.delta; bdst.grey += bdst.delta; }else{ if(ma){ *bdst.red = *bsrc.red; *bdst.grn = *bsrc.grn; *bdst.blu = *bsrc.blu; } else if(zero) *bdst.red = *bdst.grn = *bdst.blu = 0; bsrc.red += bsrc.delta; bsrc.blu += bsrc.delta; bsrc.grn += bsrc.delta; bdst.red += bdst.delta; bdst.blu += bdst.delta; bdst.grn += bdst.delta; } bmask.alpha += bmask.delta; if(bdst.alpha != &ones){ if(ma) *bdst.alpha = 255; else if(zero) *bdst.alpha = 0; bdst.alpha += bdst.delta; } } return obdst;}/* * Replicated cached scan line read. Call the function listed in the Param, * but cache the result so that for replicated images we only do the work once. */static Bufferreplread(Param *p, uchar *s, int y){ Buffer *b; USED(s);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -